aboutsummaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authornkozlovskiy <nmk@ydb.tech>2023-12-04 19:26:35 +0300
committernkozlovskiy <nmk@ydb.tech>2023-12-05 05:25:43 +0300
commite62474f851635573f9f6631039e113a02fd50179 (patch)
tree597d4bc8aad74ef42c55fd062398e93eceebfee3 /contrib
parente7eddec34be4f360877b46ffa2b70fde8a3a5b8f (diff)
downloadydb-e62474f851635573f9f6631039e113a02fd50179.tar.gz
ydb-oss sync: add clang16-rt/ to additionalPathsToCopy
Diffstat (limited to 'contrib')
-rw-r--r--contrib/libs/clang16-rt/.yandex_meta/devtools.copyrights.report115
-rw-r--r--contrib/libs/clang16-rt/.yandex_meta/devtools.licenses.report2562
-rw-r--r--contrib/libs/clang16-rt/CODE_OWNERS.TXT61
-rw-r--r--contrib/libs/clang16-rt/CREDITS.TXT36
-rw-r--r--contrib/libs/clang16-rt/LICENSE.TXT311
-rw-r--r--contrib/libs/clang16-rt/README.txt11
-rw-r--r--contrib/libs/clang16-rt/include/profile/InstrProfData.inc907
-rw-r--r--contrib/libs/clang16-rt/include/profile/MIBEntryDef.inc53
-rw-r--r--contrib/libs/clang16-rt/include/profile/MemProfData.inc202
-rw-r--r--contrib/libs/clang16-rt/include/sanitizer/allocator_interface.h88
-rw-r--r--contrib/libs/clang16-rt/include/sanitizer/coverage_interface.h35
-rw-r--r--contrib/libs/clang16-rt/include/sanitizer/dfsan_interface.h207
-rw-r--r--contrib/libs/clang16-rt/include/sanitizer/linux_syscall_hooks.h3100
-rw-r--r--contrib/libs/clang16-rt/include/sanitizer/memprof_interface.h65
-rw-r--r--contrib/libs/clang16-rt/include/sanitizer/netbsd_syscall_hooks.h5005
-rw-r--r--contrib/libs/clang16-rt/include/sanitizer/scudo_interface.h38
-rw-r--r--contrib/libs/clang16-rt/include/sanitizer/tsan_interface_atomic.h221
-rw-r--r--contrib/libs/clang16-rt/include/sanitizer/ubsan_interface.h32
-rw-r--r--contrib/libs/clang16-rt/lib/asan-preinit/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/asan-preinit/ya.make45
-rw-r--r--contrib/libs/clang16-rt/lib/asan/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/asan/README.txt26
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_activation.cpp143
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_activation.h22
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_activation_flags.inc36
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_allocator.cpp1194
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_allocator.h227
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_debugging.cpp147
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_descriptions.cpp507
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_descriptions.h269
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_errors.cpp620
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_errors.h479
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_fake_stack.cpp310
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_fake_stack.h175
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_flags.cpp206
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_flags.h48
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_flags.inc167
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_fuchsia.cpp274
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_globals.cpp460
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_globals_win.cpp61
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_init_version.h44
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_interceptors.cpp747
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_interceptors.h163
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_interceptors_memintrinsics.cpp43
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_interceptors_memintrinsics.h150
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_interceptors_vfork.S14
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_interface_internal.h274
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_internal.h162
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_linux.cpp253
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_lock.h0
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_mac.cpp295
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_malloc_linux.cpp226
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_malloc_mac.cpp102
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_malloc_win.cpp551
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_mapping.h412
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_mapping_sparc64.h121
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_memory_profile.cpp129
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_new_delete.cpp196
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_poisoning.cpp685
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_poisoning.h98
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_posix.cpp158
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_preinit.cpp24
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_premap_shadow.cpp64
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_premap_shadow.h29
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_report.cpp585
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_report.h103
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_rtl.cpp621
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_rtl_static.cpp36
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_rtl_x86_64.S146
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_scariness_score.h73
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_shadow_setup.cpp125
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_stack.cpp89
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_stack.h71
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_stats.cpp173
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_stats.h71
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_suppressions.cpp104
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_suppressions.h29
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_thread.cpp610
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_thread.h188
-rw-r--r--contrib/libs/clang16-rt/lib/asan/asan_win.cpp400
-rw-r--r--contrib/libs/clang16-rt/lib/asan/ya.make159
-rw-r--r--contrib/libs/clang16-rt/lib/asan_cxx/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/asan_cxx/ya.make51
-rw-r--r--contrib/libs/clang16-rt/lib/asan_static/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/asan_static/ya.make51
-rw-r--r--contrib/libs/clang16-rt/lib/builtins/README.txt353
-rw-r--r--contrib/libs/clang16-rt/lib/builtins/assembly.h292
-rw-r--r--contrib/libs/clang16-rt/lib/cfi/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/cfi/cfi.cpp476
-rw-r--r--contrib/libs/clang16-rt/lib/cfi/ya.make96
-rw-r--r--contrib/libs/clang16-rt/lib/cfi_diag/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/cfi_diag/ya.make126
-rw-r--r--contrib/libs/clang16-rt/lib/dd/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/dd/ya.make97
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan.cpp1262
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan.h112
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan_allocator.cpp297
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan_allocator.h30
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan_chained_origin_depot.cpp22
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan_chained_origin_depot.h26
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan_custom.cpp2488
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan_flags.h32
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan_flags.inc43
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan_interceptors.cpp220
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan_new_delete.cpp124
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan_origin.h127
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan_platform.h115
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan_thread.cpp134
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/dfsan_thread.h82
-rw-r--r--contrib/libs/clang16-rt/lib/dfsan/ya.make122
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/common.cpp112
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/common.h193
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/crash_handler.cpp162
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/crash_handler.h131
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/definitions.h20
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/guarded_pool_allocator.cpp469
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/guarded_pool_allocator.h250
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/mutex.h42
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/optional/backtrace.h53
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp67
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/optional/options_parser.cpp258
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/optional/options_parser.h31
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/optional/printf.h33
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/optional/segv_handler.h34
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/optional/segv_handler_posix.cpp259
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/options.h57
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/options.inc79
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/common_posix.cpp26
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.h22
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp115
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.h18
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_tls.h55
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/mutex_fuchsia.h23
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/mutex_posix.cpp30
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/mutex_posix.h23
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/utilities_posix.cpp30
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/stack_trace_compressor.cpp111
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/stack_trace_compressor.h38
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/utilities.h28
-rw-r--r--contrib/libs/clang16-rt/lib/gwp_asan/ya.make51
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan.cpp644
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan.h221
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_allocation_functions.cpp175
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_allocator.cpp628
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_allocator.h135
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_checks.h144
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_dynamic_shadow.cpp143
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_dynamic_shadow.h27
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_exceptions.cpp69
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_flags.h31
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_flags.inc83
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_fuchsia.cpp241
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_globals.cpp91
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_globals.h49
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_interceptors.cpp254
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_interceptors_vfork.S14
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_interface_internal.h190
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_linux.cpp557
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_malloc_bisect.h50
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_mapping.h75
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_memintrinsics.cpp44
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_new_delete.cpp138
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_poisoning.cpp36
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_poisoning.h24
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_preinit.cpp23
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_report.cpp804
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_report.h35
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_setjmp_aarch64.S101
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_setjmp_riscv64.S97
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_setjmp_x86_64.S82
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S158
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_tag_mismatch_riscv64.S132
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_thread.cpp204
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_thread.h120
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_thread_list.cpp15
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_thread_list.h226
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/hwasan_type_test.cpp25
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan/ya.make152
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan_aliases/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan_aliases/ya.make153
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan_aliases_cxx/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan_aliases_cxx/ya.make53
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan_cxx/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/hwasan_cxx/ya.make53
-rw-r--r--contrib/libs/clang16-rt/lib/interception/interception.h295
-rw-r--r--contrib/libs/clang16-rt/lib/interception/interception_linux.cpp83
-rw-r--r--contrib/libs/clang16-rt/lib/interception/interception_linux.h53
-rw-r--r--contrib/libs/clang16-rt/lib/interception/interception_mac.cpp18
-rw-r--r--contrib/libs/clang16-rt/lib/interception/interception_mac.h27
-rw-r--r--contrib/libs/clang16-rt/lib/interception/interception_type_test.cpp39
-rw-r--r--contrib/libs/clang16-rt/lib/interception/interception_win.cpp1071
-rw-r--r--contrib/libs/clang16-rt/lib/interception/interception_win.h83
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan.cpp115
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan.h56
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_allocator.cpp367
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_allocator.h117
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_common.cpp1089
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_common.h350
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_common_fuchsia.cpp167
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_common_linux.cpp147
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_common_mac.cpp238
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_flags.inc46
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_fuchsia.cpp129
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_fuchsia.h35
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_interceptors.cpp542
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_linux.cpp32
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_mac.cpp191
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_malloc_mac.cpp59
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_posix.cpp102
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_posix.h49
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_preinit.cpp21
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_thread.cpp102
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/lsan_thread.h60
-rw-r--r--contrib/libs/clang16-rt/lib/lsan/ya.make131
-rw-r--r--contrib/libs/clang16-rt/lib/memprof-preinit/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/memprof-preinit/ya.make45
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/README.txt17
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_allocator.cpp710
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_allocator.h103
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_descriptions.cpp70
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_descriptions.h45
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_flags.cpp93
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_flags.h45
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_flags.inc41
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_init_version.h26
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_interceptors.cpp364
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_interceptors.h60
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_interceptors_memintrinsics.cpp29
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_interceptors_memintrinsics.h79
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_interface_internal.h64
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_internal.h87
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_linux.cpp74
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_malloc_linux.cpp151
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_mapping.h113
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_mibmap.cpp37
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_mibmap.h27
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_new_delete.cpp145
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_posix.cpp55
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_preinit.cpp23
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_rawprofile.cpp246
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_rawprofile.h14
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_rtl.cpp307
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_shadow_setup.cpp62
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_stack.cpp59
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_stack.h66
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_stats.cpp157
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_stats.h61
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_thread.cpp219
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/memprof_thread.h135
-rw-r--r--contrib/libs/clang16-rt/lib/memprof/ya.make134
-rw-r--r--contrib/libs/clang16-rt/lib/memprof_cxx/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/memprof_cxx/ya.make45
-rw-r--r--contrib/libs/clang16-rt/lib/msan/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan.cpp745
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan.h318
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_allocator.cpp376
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_allocator.h31
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_chained_origin_depot.cpp42
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_chained_origin_depot.h38
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_flags.h29
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_flags.inc34
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_interceptors.cpp1797
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_interface_internal.h207
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_linux.cpp261
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_new_delete.cpp108
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_origin.h168
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_poisoning.cpp253
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_poisoning.h58
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_report.cpp279
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_report.h33
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_thread.cpp122
-rw-r--r--contrib/libs/clang16-rt/lib/msan/msan_thread.h81
-rw-r--r--contrib/libs/clang16-rt/lib/msan/ya.make134
-rw-r--r--contrib/libs/clang16-rt/lib/msan_cxx/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/msan_cxx/ya.make53
-rw-r--r--contrib/libs/clang16-rt/lib/profile/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/profile/GCDAProfiling.c637
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfiling.c76
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfiling.h329
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingBuffer.c167
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingFile.c1194
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingInternal.c26
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingInternal.h201
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingMerge.c185
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingMergeFile.c45
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingNameVar.c17
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformDarwin.c75
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformFuchsia.c190
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformLinux.c270
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformOther.c109
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformWindows.c73
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingPort.h152
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingRuntime.cpp24
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingUtil.c375
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingUtil.h87
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingValue.c358
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingVersionVar.c18
-rw-r--r--contrib/libs/clang16-rt/lib/profile/InstrProfilingWriter.c338
-rw-r--r--contrib/libs/clang16-rt/lib/profile/WindowsMMap.h76
-rw-r--r--contrib/libs/clang16-rt/lib/profile/ya.make58
-rw-r--r--contrib/libs/clang16-rt/lib/safestack/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/safestack/safestack.cpp310
-rw-r--r--contrib/libs/clang16-rt/lib/safestack/safestack_platform.h124
-rw-r--r--contrib/libs/clang16-rt/lib/safestack/safestack_util.h49
-rw-r--r--contrib/libs/clang16-rt/lib/safestack/ya.make49
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sancov_flags.cpp58
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sancov_flags.h39
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sancov_flags.inc20
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_addrhashmap.h393
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator.cpp209
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator.h78
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_checks.cpp22
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_checks.h76
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_combined.h199
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h79
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_interface.h47
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_internal.h57
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h271
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h381
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h898
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp144
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_report.h40
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_secondary.h322
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_size_class_map.h241
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_stats.h106
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_asm.h75
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic.h86
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang.h104
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang_mips.h117
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang_other.h85
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang_x86.h113
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h256
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_bitvector.h350
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_bvgraph.h164
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_chained_origin_depot.cpp148
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_chained_origin_depot.h46
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common.cpp401
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common.h1100
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc10695
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc568
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc612
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc128
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S48
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S49
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S64
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_loongarch64.inc.S57
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_riscv64.inc.S56
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S42
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interface.inc46
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interface_posix.inc15
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp226
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc3180
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_fuchsia.cpp254
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc43
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp288
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_win_sections.cpp67
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_dbghelp.h41
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h410
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cpp194
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector2.cpp421
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h98
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_dense_map.h705
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_dense_map_info.h282
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_errno.cpp34
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_errno.h38
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_errno_codes.h35
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_file.cpp251
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_file.h109
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flag_parser.cpp191
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flag_parser.h204
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flags.cpp139
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flags.h71
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flags.inc271
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flat_map.h173
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_freebsd.h137
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp501
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_fuchsia.h38
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_getauxval.h60
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_glibc_version.h26
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_hash.h67
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc1535
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_interface_internal.h153
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_internal_defs.h480
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_leb128.h87
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_lfstack.h72
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libc.cpp292
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libc.h89
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libignore.cpp129
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libignore.h115
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux.cpp2428
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux.h179
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp1079
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux_s390.cpp228
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_list.h166
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_local_address_space_view.h76
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_lzw.h159
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mac.cpp1457
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mac.h79
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mac_libcdep.cpp29
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc414
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mutex.cpp225
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mutex.h446
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_netbsd.cpp351
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_placement_new.h24
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform.h448
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h617
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp561
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h735
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp103
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp2740
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h2421
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_openbsd.h0
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp1345
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h1509
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.cpp368
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.h496
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_posix.cpp410
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_posix.h128
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp503
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_printf.cpp361
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps.h110
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp128
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_common.cpp192
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_fuchsia.cpp80
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cpp81
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cpp445
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp92
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_ptrauth.h41
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_quarantine.h318
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_report_decorator.h48
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_ring_buffer.h166
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_signal_interceptors.inc97
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_solaris.cpp230
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_solaris.h56
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stack_store.cpp379
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stack_store.h121
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp247
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stackdepot.h51
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h194
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp169
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace.h220
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp226
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp310
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h73
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_sparc.cpp85
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld.h65
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp43
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.h20
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp631
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_mac.cpp183
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp362
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp175
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_suppressions.cpp181
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_suppressions.h56
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer.cpp141
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer.h224
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_fuchsia.h42
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h165
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp209
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h49
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp568
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp205
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.h47
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_markup.cpp150
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp510
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp298
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp324
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc39
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_aarch64.inc137
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_arm.inc137
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_hexagon.inc131
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_loongarch64.inc171
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_riscv64.inc174
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc90
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscalls_netbsd.inc3944
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_termination.cpp99
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_thread_registry.cpp384
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_thread_registry.h168
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_thread_safety.h49
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp178
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h79
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_type_traits.cpp20
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_type_traits.h141
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp180
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_unwind_win.cpp93
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_vector.h124
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win.cpp1191
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win.h25
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win_defs.h174
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.h181
-rw-r--r--contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win_weak_interception.h32
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/allocator_config.h220
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/atomic_helpers.h145
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/bytemap.h43
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/checksum.cpp83
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/checksum.h59
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/chunk.h156
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/combined.h1531
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/common.cpp42
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/common.h214
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/crc32_hw.cpp20
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/flags.cpp73
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/flags.h38
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/flags.inc59
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/flags_parser.cpp164
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/flags_parser.h55
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/fuchsia.cpp220
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/fuchsia.h32
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/include/scudo/interface.h160
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/internal_defs.h166
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/linux.cpp252
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/linux.h25
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/list.h240
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/local_cache.h234
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/memtag.h335
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/mutex.h72
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/options.h74
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/platform.h80
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/primary32.h764
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/primary64.h784
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/quarantine.h297
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/release.cpp16
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/release.h430
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/report.cpp204
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/report.h59
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/rss_limit_checker.cpp37
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/rss_limit_checker.h63
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/secondary.h628
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/size_class_map.h377
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/stack_depot.h144
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/stats.h101
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/string_utils.cpp255
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/string_utils.h43
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/trusty.h24
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/tsd.h66
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/tsd_exclusive.h152
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/tsd_shared.h216
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/vector.h118
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c.cpp37
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c.h62
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c.inc288
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c_checks.h72
-rw-r--r--contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_cpp.cpp108
-rw-r--r--contrib/libs/clang16-rt/lib/scudo_standalone/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/scudo_standalone/ya.make70
-rw-r--r--contrib/libs/clang16-rt/lib/scudo_standalone_cxx/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/scudo_standalone_cxx/ya.make43
-rw-r--r--contrib/libs/clang16-rt/lib/stats/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/stats/stats.cpp136
-rw-r--r--contrib/libs/clang16-rt/lib/stats/stats.h42
-rw-r--r--contrib/libs/clang16-rt/lib/stats/stats_client.cpp83
-rw-r--r--contrib/libs/clang16-rt/lib/stats/ya.make110
-rw-r--r--contrib/libs/clang16-rt/lib/stats_client/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/stats_client/ya.make44
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/.yandex_meta/licenses.list.txt383
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/dd/dd_interceptors.cpp330
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/dd/dd_rtl.cpp158
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/dd/dd_rtl.h66
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_debugging.cpp262
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_defs.h217
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_dense_alloc.h196
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_external.cpp126
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_fd.cpp375
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_fd.h65
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_flags.cpp120
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_flags.h34
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_flags.inc82
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_ignoreset.cpp38
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_ignoreset.h36
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_ilist.h189
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors.h106
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_libdispatch.cpp814
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp521
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_mach_vm.cpp53
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp3180
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface.cpp92
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface.h431
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface.inc190
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_ann.cpp438
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_ann.h32
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_atomic.cpp925
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_java.cpp258
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_java.h99
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_malloc_mac.cpp71
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_md5.cpp250
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mman.cpp442
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mman.h80
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mutexset.cpp80
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mutexset.h91
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_new_delete.cpp199
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform.h938
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_linux.cpp553
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_mac.cpp304
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_posix.cpp143
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_windows.cpp33
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_preinit.cpp26
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_report.cpp477
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_report.h128
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl.cpp1123
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl.h813
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_aarch64.S245
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_access.cpp744
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_amd64.S210
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_loongarch64.S196
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_mips64.S214
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp578
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_ppc64.S288
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_proc.cpp59
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_report.cpp862
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_s390x.S49
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_thread.cpp368
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_shadow.h193
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_stack_trace.cpp57
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_stack_trace.h42
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_suppressions.cpp161
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_suppressions.h37
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_symbolize.cpp123
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_symbolize.h30
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_sync.cpp289
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_sync.h148
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_trace.h215
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_vector_clock.cpp126
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/rtl/tsan_vector_clock.h51
-rw-r--r--contrib/libs/clang16-rt/lib/tsan/ya.make173
-rw-r--r--contrib/libs/clang16-rt/lib/tsan_cxx/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/tsan_cxx/ya.make52
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_checks.inc71
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_diag.cpp445
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_diag.h266
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_diag_standalone.cpp38
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_flags.cpp80
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_flags.h46
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_flags.inc28
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers.cpp918
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers.h236
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers_cxx.cpp205
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers_cxx.h54
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_init.cpp76
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_init.h33
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_init_standalone.cpp33
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_init_standalone_preinit.cpp35
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_monitor.cpp75
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_monitor.h48
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_platform.h25
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_signals_standalone.cpp71
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_signals_standalone.h24
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash.cpp33
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash.h73
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash_itanium.cpp281
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash_win.cpp84
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_value.cpp158
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan/ubsan_value.h199
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan_minimal/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp143
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan_minimal/ya.make43
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan_standalone/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan_standalone/ya.make128
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan_standalone_cxx/.yandex_meta/licenses.list.txt377
-rw-r--r--contrib/libs/clang16-rt/lib/ubsan_standalone_cxx/ya.make49
-rw-r--r--contrib/libs/clang16-rt/ya.make45
665 files changed, 177845 insertions, 0 deletions
diff --git a/contrib/libs/clang16-rt/.yandex_meta/devtools.copyrights.report b/contrib/libs/clang16-rt/.yandex_meta/devtools.copyrights.report
new file mode 100644
index 00000000000..25b1033428d
--- /dev/null
+++ b/contrib/libs/clang16-rt/.yandex_meta/devtools.copyrights.report
@@ -0,0 +1,115 @@
+# File format ($ symbol means the beginning of a line):
+#
+# $ # this message
+# $ # =======================
+# $ # comments (all commentaries should starts with some number of spaces and # symbol)
+# ${action} {license id} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make
+# ${all_file_action} filename
+# $ # user commentaries (many lines)
+# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify)
+# ${action} {license spdx} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/3/ya.make
+# ${all_file_action} filename
+# $ # user commentaries
+# $ generated description
+# $ ...
+#
+# You can modify action, all_file_action and add commentaries
+# Available actions:
+# keep - keep license in contrib and use in credits
+# skip - skip license
+# remove - remove all files with this license
+# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file
+#
+# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory)
+# We suppose that that files can contain some license info
+# Available all file actions:
+# FILE_IGNORE - ignore file (do nothing)
+# FILE_INCLUDE - include all file data into licenses text file
+# =======================
+
+KEEP COPYRIGHT_SERVICE_LABEL 369853aeec235d11ed2b97b4f5174785
+BELONGS lib/tsan/ya.make
+ License text:
+ return AllocSuperBlock(c);
+ Block *ptr = MapBlock(idx);
+ xchg = ptr->next | (cmp & kCounterMask);
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ lib/tsan/rtl/tsan_dense_alloc.h [138:140]
+
+KEEP COPYRIGHT_SERVICE_LABEL 4ef7946d23591afdcc1fd9c9984ea3a4
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ License text:
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ lib/scudo/standalone/local_cache.h [210:212]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP COPYRIGHT_SERVICE_LABEL b8b2f9fffd684c9e8f615aa7e5b2d107
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ License text:
+ // Calling getenv should be fine (c)(tm) at any time.
+ const char *getEnv(const char *Name) { return getenv(Name); }
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ lib/scudo/standalone/linux.cpp [98:99]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP COPYRIGHT_SERVICE_LABEL d5cab39d5c14d8220d0131818428faff
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ License text:
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ lib/sanitizer_common/sanitizer_allocator_local_cache.h [243:245]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP COPYRIGHT_SERVICE_LABEL debfce3edcb19585edc08c5b1d986c0b
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+FILE_INCLUDE CREDITS.TXT found in files: LICENSE.TXT at line 293
+ License text:
+ Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ LICENSE.TXT [293:293]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP COPYRIGHT_SERVICE_LABEL ebc015cad7377d32e7b2fc0ae5293aa1
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+FILE_INCLUDE CREDITS.TXT found in files: LICENSE.TXT at line 252
+ License text:
+ Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ LICENSE.TXT [252:252]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
diff --git a/contrib/libs/clang16-rt/.yandex_meta/devtools.licenses.report b/contrib/libs/clang16-rt/.yandex_meta/devtools.licenses.report
new file mode 100644
index 00000000000..f5723b6fdad
--- /dev/null
+++ b/contrib/libs/clang16-rt/.yandex_meta/devtools.licenses.report
@@ -0,0 +1,2562 @@
+# File format ($ symbol means the beginning of a line):
+#
+# $ # this message
+# $ # =======================
+# $ # comments (all commentaries should starts with some number of spaces and # symbol)
+# ${action} {license spdx} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make
+# ${all_file_action} filename
+# $ # user commentaries (many lines)
+# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify)
+# ${action} {license spdx} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/3/ya.make
+# ${all_file_action} filename
+# $ # user commentaries
+# $ generated description
+# $ ...
+#
+# You can modify action, all_file_action and add commentaries
+# Available actions:
+# keep - keep license in contrib and use in credits
+# skip - skip license
+# remove - remove all files with this license
+# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file
+#
+# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory)
+# We suppose that that files can contain some license info
+# Available all file actions:
+# FILE_IGNORE - ignore file (do nothing)
+# FILE_INCLUDE - include all file data into licenses text file
+# =======================
+
+KEEP Apache-2.0 WITH LLVM-exception 13ccb04dbdb720576c825193b2c4014c
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ License text:
+ |* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ |* See https://llvm.org/LICENSE.txt for license information.
+ Scancode info:
+ Original SPDX id: Apache-2.0
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0
+ Files with this license:
+ include/profile/InstrProfData.inc [3:4]
+ include/profile/MIBEntryDef.inc [3:4]
+ include/profile/MemProfData.inc [5:6]
+ lib/profile/GCDAProfiling.c [3:4]
+ lib/profile/InstrProfiling.c [3:4]
+ lib/profile/InstrProfiling.h [3:4]
+ lib/profile/InstrProfilingBuffer.c [3:4]
+ lib/profile/InstrProfilingFile.c [3:4]
+ lib/profile/InstrProfilingInternal.c [3:4]
+ lib/profile/InstrProfilingInternal.h [3:4]
+ lib/profile/InstrProfilingMerge.c [3:4]
+ lib/profile/InstrProfilingMergeFile.c [3:4]
+ lib/profile/InstrProfilingNameVar.c [3:4]
+ lib/profile/InstrProfilingPlatformDarwin.c [3:4]
+ lib/profile/InstrProfilingPlatformFuchsia.c [3:4]
+ lib/profile/InstrProfilingPlatformLinux.c [3:4]
+ lib/profile/InstrProfilingPlatformOther.c [3:4]
+ lib/profile/InstrProfilingPlatformWindows.c [3:4]
+ lib/profile/InstrProfilingPort.h [3:4]
+ lib/profile/InstrProfilingUtil.c [3:4]
+ lib/profile/InstrProfilingUtil.h [3:4]
+ lib/profile/InstrProfilingValue.c [3:4]
+ lib/profile/InstrProfilingVersionVar.c [3:4]
+ lib/profile/InstrProfilingWriter.c [3:4]
+ lib/profile/WindowsMMap.h [3:4]
+ Scancode info:
+ Original SPDX id: LLVM-exception
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://llvm.org/foundation/relicensing/LICENSE.txt, https://spdx.org/licenses/LLVM-exception
+ Files with this license:
+ include/profile/InstrProfData.inc [3:4]
+ include/profile/MIBEntryDef.inc [3:4]
+ include/profile/MemProfData.inc [5:6]
+ lib/profile/GCDAProfiling.c [3:4]
+ lib/profile/InstrProfiling.c [3:4]
+ lib/profile/InstrProfiling.h [3:4]
+ lib/profile/InstrProfilingBuffer.c [3:4]
+ lib/profile/InstrProfilingFile.c [3:4]
+ lib/profile/InstrProfilingInternal.c [3:4]
+ lib/profile/InstrProfilingInternal.h [3:4]
+ lib/profile/InstrProfilingMerge.c [3:4]
+ lib/profile/InstrProfilingMergeFile.c [3:4]
+ lib/profile/InstrProfilingNameVar.c [3:4]
+ lib/profile/InstrProfilingPlatformDarwin.c [3:4]
+ lib/profile/InstrProfilingPlatformFuchsia.c [3:4]
+ lib/profile/InstrProfilingPlatformLinux.c [3:4]
+ lib/profile/InstrProfilingPlatformOther.c [3:4]
+ lib/profile/InstrProfilingPlatformWindows.c [3:4]
+ lib/profile/InstrProfilingPort.h [3:4]
+ lib/profile/InstrProfilingUtil.c [3:4]
+ lib/profile/InstrProfilingUtil.h [3:4]
+ lib/profile/InstrProfilingValue.c [3:4]
+ lib/profile/InstrProfilingVersionVar.c [3:4]
+ lib/profile/InstrProfilingWriter.c [3:4]
+ lib/profile/WindowsMMap.h [3:4]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP NCSA 281d1ec07e86b61c925d7c514deecb25
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ License text:
+ Compiler-RT is open source software. You may freely distribute it under the
+ terms of the license agreement found in LICENSE.txt.
+ Scancode info:
+ Original SPDX id: NCSA
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.otm.illinois.edu/faculty/forms/opensource.asp, https://spdx.org/licenses/NCSA
+ Files with this license:
+ README.txt [7:8]
+ lib/builtins/README.txt [7:8]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+SKIP LicenseRef-scancode-warranty-disclaimer 384445f689b03d412e739da3f7c142a6
+BELONGS lib/memprof/ya.make
+ License text:
+ "(WARNING: USE AT YOUR OWN RISK!)")
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-warranty-disclaimer
+ Score : 100.00
+ Match type : TEXT
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/warranty-disclaimer.LICENSE
+ Files with this license:
+ lib/memprof/memprof_flags.inc [33:33]
+
+KEEP NCSA 5a35b4c0d3b3923cac31a5a371332ca2
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ License text:
+ Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+ Scancode info:
+ Original SPDX id: NCSA
+ Score : 100.00
+ Match type : REFERENCE
+ Links : http://www.otm.illinois.edu/faculty/forms/opensource.asp, https://spdx.org/licenses/NCSA
+ Files with this license:
+ LICENSE.TXT [237:237]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP MIT 5debb370f50e1dfd24ff5144233a2ef6
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: MIT
+ Score : 100.00
+ Match type : TEXT
+ Links : http://opensource.org/licenses/mit-license.php, https://spdx.org/licenses/MIT
+ Files with this license:
+ LICENSE.TXT [295:311]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP Apache-2.0 WITH LLVM-exception 755ab7da3ff8c5d6ae90bdbebd177e49
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ License text:
+ // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ // See https://llvm.org/LICENSE.txt for license information.
+ Scancode info:
+ Original SPDX id: Apache-2.0
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0
+ Files with this license:
+ include/sanitizer/allocator_interface.h [3:4]
+ include/sanitizer/asan_interface.h [3:4]
+ include/sanitizer/common_interface_defs.h [3:4]
+ include/sanitizer/coverage_interface.h [3:4]
+ include/sanitizer/dfsan_interface.h [3:4]
+ include/sanitizer/hwasan_interface.h [3:4]
+ include/sanitizer/linux_syscall_hooks.h [3:4]
+ include/sanitizer/lsan_interface.h [3:4]
+ include/sanitizer/memprof_interface.h [3:4]
+ include/sanitizer/msan_interface.h [3:4]
+ include/sanitizer/netbsd_syscall_hooks.h [3:4]
+ include/sanitizer/scudo_interface.h [3:4]
+ include/sanitizer/tsan_interface.h [3:4]
+ include/sanitizer/tsan_interface_atomic.h [3:4]
+ include/sanitizer/ubsan_interface.h [3:4]
+ lib/asan/asan_activation.cpp [3:4]
+ lib/asan/asan_activation.h [3:4]
+ lib/asan/asan_activation_flags.inc [3:4]
+ lib/asan/asan_allocator.cpp [3:4]
+ lib/asan/asan_allocator.h [3:4]
+ lib/asan/asan_debugging.cpp [3:4]
+ lib/asan/asan_descriptions.cpp [3:4]
+ lib/asan/asan_descriptions.h [3:4]
+ lib/asan/asan_errors.cpp [3:4]
+ lib/asan/asan_errors.h [3:4]
+ lib/asan/asan_fake_stack.cpp [3:4]
+ lib/asan/asan_fake_stack.h [3:4]
+ lib/asan/asan_flags.cpp [3:4]
+ lib/asan/asan_flags.h [3:4]
+ lib/asan/asan_flags.inc [3:4]
+ lib/asan/asan_fuchsia.cpp [3:4]
+ lib/asan/asan_globals.cpp [3:4]
+ lib/asan/asan_globals_win.cpp [3:4]
+ lib/asan/asan_init_version.h [3:4]
+ lib/asan/asan_interceptors.cpp [3:4]
+ lib/asan/asan_interceptors.h [3:4]
+ lib/asan/asan_interceptors_memintrinsics.cpp [3:4]
+ lib/asan/asan_interceptors_memintrinsics.h [3:4]
+ lib/asan/asan_interface_internal.h [3:4]
+ lib/asan/asan_internal.h [3:4]
+ lib/asan/asan_linux.cpp [3:4]
+ lib/asan/asan_mac.cpp [3:4]
+ lib/asan/asan_malloc_linux.cpp [3:4]
+ lib/asan/asan_malloc_mac.cpp [3:4]
+ lib/asan/asan_malloc_win.cpp [3:4]
+ lib/asan/asan_mapping.h [3:4]
+ lib/asan/asan_mapping_sparc64.h [3:4]
+ lib/asan/asan_memory_profile.cpp [3:4]
+ lib/asan/asan_new_delete.cpp [3:4]
+ lib/asan/asan_poisoning.cpp [3:4]
+ lib/asan/asan_poisoning.h [3:4]
+ lib/asan/asan_posix.cpp [3:4]
+ lib/asan/asan_preinit.cpp [3:4]
+ lib/asan/asan_premap_shadow.cpp [3:4]
+ lib/asan/asan_premap_shadow.h [3:4]
+ lib/asan/asan_report.cpp [3:4]
+ lib/asan/asan_report.h [3:4]
+ lib/asan/asan_rtl.cpp [3:4]
+ lib/asan/asan_rtl_static.cpp [3:4]
+ lib/asan/asan_scariness_score.h [3:4]
+ lib/asan/asan_shadow_setup.cpp [3:4]
+ lib/asan/asan_stack.cpp [3:4]
+ lib/asan/asan_stack.h [3:4]
+ lib/asan/asan_stats.cpp [3:4]
+ lib/asan/asan_stats.h [3:4]
+ lib/asan/asan_suppressions.cpp [3:4]
+ lib/asan/asan_suppressions.h [3:4]
+ lib/asan/asan_thread.cpp [3:4]
+ lib/asan/asan_thread.h [3:4]
+ lib/asan/asan_win.cpp [4:5]
+ lib/builtins/assembly.h [3:4]
+ lib/cfi/cfi.cpp [3:4]
+ lib/dfsan/dfsan.cpp [3:4]
+ lib/dfsan/dfsan.h [3:4]
+ lib/dfsan/dfsan_allocator.cpp [3:4]
+ lib/dfsan/dfsan_allocator.h [3:4]
+ lib/dfsan/dfsan_chained_origin_depot.cpp [3:4]
+ lib/dfsan/dfsan_chained_origin_depot.h [3:4]
+ lib/dfsan/dfsan_custom.cpp [3:4]
+ lib/dfsan/dfsan_flags.h [3:4]
+ lib/dfsan/dfsan_flags.inc [3:4]
+ lib/dfsan/dfsan_interceptors.cpp [3:4]
+ lib/dfsan/dfsan_new_delete.cpp [3:4]
+ lib/dfsan/dfsan_origin.h [3:4]
+ lib/dfsan/dfsan_platform.h [3:4]
+ lib/dfsan/dfsan_thread.h [3:4]
+ lib/gwp_asan/common.cpp [3:4]
+ lib/gwp_asan/common.h [3:4]
+ lib/gwp_asan/crash_handler.cpp [3:4]
+ lib/gwp_asan/crash_handler.h [3:4]
+ lib/gwp_asan/definitions.h [3:4]
+ lib/gwp_asan/guarded_pool_allocator.cpp [3:4]
+ lib/gwp_asan/guarded_pool_allocator.h [3:4]
+ lib/gwp_asan/mutex.h [3:4]
+ lib/gwp_asan/optional/backtrace.h [3:4]
+ lib/gwp_asan/optional/backtrace_linux_libc.cpp [3:4]
+ lib/gwp_asan/optional/options_parser.cpp [3:4]
+ lib/gwp_asan/optional/options_parser.h [3:4]
+ lib/gwp_asan/optional/printf.h [3:4]
+ lib/gwp_asan/optional/segv_handler.h [3:4]
+ lib/gwp_asan/optional/segv_handler_posix.cpp [3:4]
+ lib/gwp_asan/options.h [3:4]
+ lib/gwp_asan/options.inc [3:4]
+ lib/gwp_asan/platform_specific/common_posix.cpp [3:4]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.h [3:4]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp [3:4]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.h [3:4]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_tls.h [3:4]
+ lib/gwp_asan/platform_specific/mutex_fuchsia.h [3:4]
+ lib/gwp_asan/platform_specific/mutex_posix.cpp [3:4]
+ lib/gwp_asan/platform_specific/mutex_posix.h [3:4]
+ lib/gwp_asan/platform_specific/utilities_posix.cpp [3:4]
+ lib/gwp_asan/stack_trace_compressor.cpp [3:4]
+ lib/gwp_asan/stack_trace_compressor.h [3:4]
+ lib/gwp_asan/utilities.h [3:4]
+ lib/hwasan/hwasan.cpp [3:4]
+ lib/hwasan/hwasan.h [3:4]
+ lib/hwasan/hwasan_allocation_functions.cpp [3:4]
+ lib/hwasan/hwasan_allocator.cpp [3:4]
+ lib/hwasan/hwasan_allocator.h [3:4]
+ lib/hwasan/hwasan_checks.h [3:4]
+ lib/hwasan/hwasan_dynamic_shadow.cpp [3:4]
+ lib/hwasan/hwasan_dynamic_shadow.h [3:4]
+ lib/hwasan/hwasan_exceptions.cpp [3:4]
+ lib/hwasan/hwasan_flags.h [3:4]
+ lib/hwasan/hwasan_flags.inc [3:4]
+ lib/hwasan/hwasan_fuchsia.cpp [3:4]
+ lib/hwasan/hwasan_globals.cpp [3:4]
+ lib/hwasan/hwasan_globals.h [3:4]
+ lib/hwasan/hwasan_interceptors.cpp [3:4]
+ lib/hwasan/hwasan_interface_internal.h [3:4]
+ lib/hwasan/hwasan_linux.cpp [3:4]
+ lib/hwasan/hwasan_malloc_bisect.h [3:4]
+ lib/hwasan/hwasan_mapping.h [3:4]
+ lib/hwasan/hwasan_memintrinsics.cpp [3:4]
+ lib/hwasan/hwasan_new_delete.cpp [3:4]
+ lib/hwasan/hwasan_poisoning.cpp [3:4]
+ lib/hwasan/hwasan_poisoning.h [3:4]
+ lib/hwasan/hwasan_preinit.cpp [3:4]
+ lib/hwasan/hwasan_report.cpp [3:4]
+ lib/hwasan/hwasan_report.h [3:4]
+ lib/hwasan/hwasan_setjmp_aarch64.S [3:4]
+ lib/hwasan/hwasan_setjmp_riscv64.S [3:4]
+ lib/hwasan/hwasan_setjmp_x86_64.S [3:4]
+ lib/hwasan/hwasan_thread.h [3:4]
+ lib/hwasan/hwasan_thread_list.h [3:4]
+ lib/hwasan/hwasan_type_test.cpp [3:4]
+ lib/interception/interception.h [3:4]
+ lib/interception/interception_linux.cpp [3:4]
+ lib/interception/interception_linux.h [3:4]
+ lib/interception/interception_mac.cpp [3:4]
+ lib/interception/interception_mac.h [3:4]
+ lib/interception/interception_type_test.cpp [3:4]
+ lib/interception/interception_win.cpp [3:4]
+ lib/interception/interception_win.h [3:4]
+ lib/lsan/lsan.cpp [3:4]
+ lib/lsan/lsan.h [3:4]
+ lib/lsan/lsan_allocator.cpp [3:4]
+ lib/lsan/lsan_allocator.h [3:4]
+ lib/lsan/lsan_common.cpp [3:4]
+ lib/lsan/lsan_common.h [3:4]
+ lib/lsan/lsan_common_fuchsia.cpp [3:4]
+ lib/lsan/lsan_common_linux.cpp [3:4]
+ lib/lsan/lsan_common_mac.cpp [3:4]
+ lib/lsan/lsan_flags.inc [3:4]
+ lib/lsan/lsan_fuchsia.cpp [3:4]
+ lib/lsan/lsan_fuchsia.h [3:4]
+ lib/lsan/lsan_interceptors.cpp [3:4]
+ lib/lsan/lsan_linux.cpp [3:4]
+ lib/lsan/lsan_mac.cpp [3:4]
+ lib/lsan/lsan_malloc_mac.cpp [3:4]
+ lib/lsan/lsan_posix.cpp [3:4]
+ lib/lsan/lsan_posix.h [3:4]
+ lib/lsan/lsan_preinit.cpp [3:4]
+ lib/lsan/lsan_thread.cpp [3:4]
+ lib/lsan/lsan_thread.h [3:4]
+ lib/memprof/memprof_allocator.cpp [3:4]
+ lib/memprof/memprof_allocator.h [3:4]
+ lib/memprof/memprof_descriptions.cpp [3:4]
+ lib/memprof/memprof_descriptions.h [3:4]
+ lib/memprof/memprof_flags.cpp [3:4]
+ lib/memprof/memprof_flags.h [3:4]
+ lib/memprof/memprof_flags.inc [3:4]
+ lib/memprof/memprof_init_version.h [3:4]
+ lib/memprof/memprof_interceptors.cpp [3:4]
+ lib/memprof/memprof_interceptors.h [3:4]
+ lib/memprof/memprof_interceptors_memintrinsics.cpp [3:4]
+ lib/memprof/memprof_interceptors_memintrinsics.h [3:4]
+ lib/memprof/memprof_interface_internal.h [3:4]
+ lib/memprof/memprof_internal.h [3:4]
+ lib/memprof/memprof_linux.cpp [3:4]
+ lib/memprof/memprof_malloc_linux.cpp [3:4]
+ lib/memprof/memprof_mapping.h [3:4]
+ lib/memprof/memprof_mibmap.cpp [3:4]
+ lib/memprof/memprof_new_delete.cpp [3:4]
+ lib/memprof/memprof_posix.cpp [3:4]
+ lib/memprof/memprof_preinit.cpp [3:4]
+ lib/memprof/memprof_rtl.cpp [3:4]
+ lib/memprof/memprof_shadow_setup.cpp [3:4]
+ lib/memprof/memprof_stack.cpp [3:4]
+ lib/memprof/memprof_stack.h [3:4]
+ lib/memprof/memprof_stats.cpp [3:4]
+ lib/memprof/memprof_stats.h [3:4]
+ lib/memprof/memprof_thread.cpp [3:4]
+ lib/memprof/memprof_thread.h [3:4]
+ lib/msan/msan.cpp [3:4]
+ lib/msan/msan.h [3:4]
+ lib/msan/msan_allocator.cpp [3:4]
+ lib/msan/msan_allocator.h [3:4]
+ lib/msan/msan_chained_origin_depot.cpp [3:4]
+ lib/msan/msan_chained_origin_depot.h [3:4]
+ lib/msan/msan_flags.h [3:4]
+ lib/msan/msan_flags.inc [3:4]
+ lib/msan/msan_interceptors.cpp [3:4]
+ lib/msan/msan_interface_internal.h [3:4]
+ lib/msan/msan_linux.cpp [3:4]
+ lib/msan/msan_new_delete.cpp [3:4]
+ lib/msan/msan_origin.h [3:4]
+ lib/msan/msan_poisoning.cpp [3:4]
+ lib/msan/msan_poisoning.h [3:4]
+ lib/msan/msan_report.cpp [3:4]
+ lib/msan/msan_report.h [3:4]
+ lib/msan/msan_thread.h [3:4]
+ lib/profile/InstrProfilingRuntime.cpp [3:4]
+ lib/safestack/safestack.cpp [3:4]
+ lib/safestack/safestack_platform.h [3:4]
+ lib/safestack/safestack_util.h [3:4]
+ lib/sanitizer_common/sancov_flags.cpp [3:4]
+ lib/sanitizer_common/sancov_flags.h [3:4]
+ lib/sanitizer_common/sancov_flags.inc [3:4]
+ lib/sanitizer_common/sanitizer_addrhashmap.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator.cpp [3:4]
+ lib/sanitizer_common/sanitizer_allocator.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_checks.cpp [3:4]
+ lib/sanitizer_common/sanitizer_allocator_checks.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_combined.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_dlsym.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_interface.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_internal.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_local_cache.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_primary32.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_primary64.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_report.cpp [3:4]
+ lib/sanitizer_common/sanitizer_allocator_report.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_secondary.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_size_class_map.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_stats.h [3:4]
+ lib/sanitizer_common/sanitizer_asm.h [3:4]
+ lib/sanitizer_common/sanitizer_atomic.h [3:4]
+ lib/sanitizer_common/sanitizer_atomic_clang.h [3:4]
+ lib/sanitizer_common/sanitizer_atomic_clang_mips.h [3:4]
+ lib/sanitizer_common/sanitizer_atomic_clang_other.h [3:4]
+ lib/sanitizer_common/sanitizer_atomic_clang_x86.h [3:4]
+ lib/sanitizer_common/sanitizer_atomic_msvc.h [3:4]
+ lib/sanitizer_common/sanitizer_bitvector.h [3:4]
+ lib/sanitizer_common/sanitizer_bvgraph.h [3:4]
+ lib/sanitizer_common/sanitizer_chained_origin_depot.cpp [3:4]
+ lib/sanitizer_common/sanitizer_chained_origin_depot.h [3:4]
+ lib/sanitizer_common/sanitizer_common.cpp [3:4]
+ lib/sanitizer_common/sanitizer_common.h [3:4]
+ lib/sanitizer_common/sanitizer_common_interceptors.inc [3:4]
+ lib/sanitizer_common/sanitizer_common_interceptors_format.inc [3:4]
+ lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc [3:4]
+ lib/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc [3:4]
+ lib/sanitizer_common/sanitizer_common_interface.inc [3:4]
+ lib/sanitizer_common/sanitizer_common_interface_posix.inc [3:4]
+ lib/sanitizer_common/sanitizer_common_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_common_syscalls.inc [3:4]
+ lib/sanitizer_common/sanitizer_coverage_fuchsia.cpp [3:4]
+ lib/sanitizer_common/sanitizer_coverage_interface.inc [3:4]
+ lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp [3:4]
+ lib/sanitizer_common/sanitizer_coverage_win_sections.cpp [3:4]
+ lib/sanitizer_common/sanitizer_dbghelp.h [3:4]
+ lib/sanitizer_common/sanitizer_deadlock_detector.h [3:4]
+ lib/sanitizer_common/sanitizer_deadlock_detector1.cpp [3:4]
+ lib/sanitizer_common/sanitizer_deadlock_detector2.cpp [3:4]
+ lib/sanitizer_common/sanitizer_deadlock_detector_interface.h [3:4]
+ lib/sanitizer_common/sanitizer_dense_map.h [3:4]
+ lib/sanitizer_common/sanitizer_dense_map_info.h [3:4]
+ lib/sanitizer_common/sanitizer_errno.cpp [3:4]
+ lib/sanitizer_common/sanitizer_errno.h [3:4]
+ lib/sanitizer_common/sanitizer_errno_codes.h [3:4]
+ lib/sanitizer_common/sanitizer_file.cpp [3:4]
+ lib/sanitizer_common/sanitizer_file.h [3:4]
+ lib/sanitizer_common/sanitizer_flag_parser.cpp [3:4]
+ lib/sanitizer_common/sanitizer_flag_parser.h [3:4]
+ lib/sanitizer_common/sanitizer_flags.cpp [3:4]
+ lib/sanitizer_common/sanitizer_flags.h [3:4]
+ lib/sanitizer_common/sanitizer_flags.inc [3:4]
+ lib/sanitizer_common/sanitizer_flat_map.h [3:4]
+ lib/sanitizer_common/sanitizer_freebsd.h [3:4]
+ lib/sanitizer_common/sanitizer_fuchsia.cpp [3:4]
+ lib/sanitizer_common/sanitizer_fuchsia.h [3:4]
+ lib/sanitizer_common/sanitizer_getauxval.h [3:4]
+ lib/sanitizer_common/sanitizer_glibc_version.h [3:4]
+ lib/sanitizer_common/sanitizer_hash.h [3:4]
+ lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc [3:4]
+ lib/sanitizer_common/sanitizer_interface_internal.h [3:4]
+ lib/sanitizer_common/sanitizer_internal_defs.h [3:4]
+ lib/sanitizer_common/sanitizer_leb128.h [3:4]
+ lib/sanitizer_common/sanitizer_lfstack.h [3:4]
+ lib/sanitizer_common/sanitizer_libc.cpp [3:4]
+ lib/sanitizer_common/sanitizer_libc.h [3:4]
+ lib/sanitizer_common/sanitizer_libignore.cpp [3:4]
+ lib/sanitizer_common/sanitizer_libignore.h [3:4]
+ lib/sanitizer_common/sanitizer_linux.cpp [3:4]
+ lib/sanitizer_common/sanitizer_linux.h [3:4]
+ lib/sanitizer_common/sanitizer_linux_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_linux_s390.cpp [3:4]
+ lib/sanitizer_common/sanitizer_list.h [3:4]
+ lib/sanitizer_common/sanitizer_local_address_space_view.h [3:4]
+ lib/sanitizer_common/sanitizer_lzw.h [3:4]
+ lib/sanitizer_common/sanitizer_mac.cpp [3:4]
+ lib/sanitizer_common/sanitizer_mac.h [3:4]
+ lib/sanitizer_common/sanitizer_mac_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_malloc_mac.inc [3:4]
+ lib/sanitizer_common/sanitizer_mutex.cpp [3:4]
+ lib/sanitizer_common/sanitizer_mutex.h [3:4]
+ lib/sanitizer_common/sanitizer_netbsd.cpp [3:4]
+ lib/sanitizer_common/sanitizer_placement_new.h [3:4]
+ lib/sanitizer_common/sanitizer_platform.h [3:4]
+ lib/sanitizer_common/sanitizer_platform_interceptors.h [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_freebsd.h [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_linux.cpp [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_netbsd.h [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_posix.cpp [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_posix.h [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_solaris.cpp [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_solaris.h [3:4]
+ lib/sanitizer_common/sanitizer_posix.cpp [3:4]
+ lib/sanitizer_common/sanitizer_posix.h [3:4]
+ lib/sanitizer_common/sanitizer_posix_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_printf.cpp [3:4]
+ lib/sanitizer_common/sanitizer_procmaps.h [3:4]
+ lib/sanitizer_common/sanitizer_procmaps_bsd.cpp [3:4]
+ lib/sanitizer_common/sanitizer_procmaps_common.cpp [3:4]
+ lib/sanitizer_common/sanitizer_procmaps_fuchsia.cpp [4:5]
+ lib/sanitizer_common/sanitizer_procmaps_linux.cpp [3:4]
+ lib/sanitizer_common/sanitizer_procmaps_mac.cpp [3:4]
+ lib/sanitizer_common/sanitizer_procmaps_solaris.cpp [3:4]
+ lib/sanitizer_common/sanitizer_ptrauth.h [3:4]
+ lib/sanitizer_common/sanitizer_quarantine.h [3:4]
+ lib/sanitizer_common/sanitizer_report_decorator.h [3:4]
+ lib/sanitizer_common/sanitizer_ring_buffer.h [3:4]
+ lib/sanitizer_common/sanitizer_signal_interceptors.inc [3:4]
+ lib/sanitizer_common/sanitizer_solaris.cpp [3:4]
+ lib/sanitizer_common/sanitizer_solaris.h [3:4]
+ lib/sanitizer_common/sanitizer_stack_store.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stack_store.h [3:4]
+ lib/sanitizer_common/sanitizer_stackdepot.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stackdepot.h [3:4]
+ lib/sanitizer_common/sanitizer_stackdepotbase.h [3:4]
+ lib/sanitizer_common/sanitizer_stacktrace.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stacktrace.h [3:4]
+ lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stacktrace_printer.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stacktrace_printer.h [3:4]
+ lib/sanitizer_common/sanitizer_stacktrace_sparc.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld.h [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.h [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld_mac.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld_win.cpp [3:4]
+ lib/sanitizer_common/sanitizer_suppressions.cpp [3:4]
+ lib/sanitizer_common/sanitizer_suppressions.h [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer.h [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_fuchsia.h [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_internal.h [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_mac.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_mac.h [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_markup.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_report.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_win.cpp [3:4]
+ lib/sanitizer_common/sanitizer_syscall_generic.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscall_linux_aarch64.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscall_linux_arm.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscall_linux_hexagon.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscall_linux_loongarch64.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscall_linux_riscv64.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscalls_netbsd.inc [3:4]
+ lib/sanitizer_common/sanitizer_termination.cpp [3:4]
+ lib/sanitizer_common/sanitizer_thread_registry.cpp [3:4]
+ lib/sanitizer_common/sanitizer_thread_registry.h [3:4]
+ lib/sanitizer_common/sanitizer_thread_safety.h [3:4]
+ lib/sanitizer_common/sanitizer_tls_get_addr.cpp [3:4]
+ lib/sanitizer_common/sanitizer_tls_get_addr.h [3:4]
+ lib/sanitizer_common/sanitizer_type_traits.cpp [3:4]
+ lib/sanitizer_common/sanitizer_type_traits.h [3:4]
+ lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_unwind_win.cpp [3:4]
+ lib/sanitizer_common/sanitizer_vector.h [3:4]
+ lib/sanitizer_common/sanitizer_win.cpp [3:4]
+ lib/sanitizer_common/sanitizer_win.h [3:4]
+ lib/sanitizer_common/sanitizer_win_defs.h [3:4]
+ lib/sanitizer_common/sanitizer_win_dll_thunk.h [3:4]
+ lib/sanitizer_common/sanitizer_win_weak_interception.h [3:4]
+ lib/scudo/standalone/allocator_config.h [3:4]
+ lib/scudo/standalone/atomic_helpers.h [3:4]
+ lib/scudo/standalone/bytemap.h [3:4]
+ lib/scudo/standalone/checksum.cpp [3:4]
+ lib/scudo/standalone/checksum.h [3:4]
+ lib/scudo/standalone/chunk.h [3:4]
+ lib/scudo/standalone/combined.h [3:4]
+ lib/scudo/standalone/common.cpp [3:4]
+ lib/scudo/standalone/common.h [3:4]
+ lib/scudo/standalone/crc32_hw.cpp [3:4]
+ lib/scudo/standalone/flags.cpp [3:4]
+ lib/scudo/standalone/flags.h [3:4]
+ lib/scudo/standalone/flags.inc [3:4]
+ lib/scudo/standalone/flags_parser.cpp [3:4]
+ lib/scudo/standalone/flags_parser.h [3:4]
+ lib/scudo/standalone/fuchsia.cpp [3:4]
+ lib/scudo/standalone/fuchsia.h [3:4]
+ lib/scudo/standalone/include/scudo/interface.h [3:4]
+ lib/scudo/standalone/internal_defs.h [3:4]
+ lib/scudo/standalone/linux.cpp [3:4]
+ lib/scudo/standalone/linux.h [3:4]
+ lib/scudo/standalone/list.h [3:4]
+ lib/scudo/standalone/local_cache.h [3:4]
+ lib/scudo/standalone/memtag.h [3:4]
+ lib/scudo/standalone/mutex.h [3:4]
+ lib/scudo/standalone/options.h [3:4]
+ lib/scudo/standalone/platform.h [3:4]
+ lib/scudo/standalone/primary32.h [3:4]
+ lib/scudo/standalone/primary64.h [3:4]
+ lib/scudo/standalone/quarantine.h [3:4]
+ lib/scudo/standalone/release.cpp [3:4]
+ lib/scudo/standalone/release.h [3:4]
+ lib/scudo/standalone/report.cpp [3:4]
+ lib/scudo/standalone/report.h [3:4]
+ lib/scudo/standalone/rss_limit_checker.cpp [3:4]
+ lib/scudo/standalone/rss_limit_checker.h [3:4]
+ lib/scudo/standalone/secondary.h [3:4]
+ lib/scudo/standalone/size_class_map.h [3:4]
+ lib/scudo/standalone/stack_depot.h [3:4]
+ lib/scudo/standalone/stats.h [3:4]
+ lib/scudo/standalone/string_utils.cpp [3:4]
+ lib/scudo/standalone/string_utils.h [3:4]
+ lib/scudo/standalone/trusty.h [3:4]
+ lib/scudo/standalone/tsd.h [3:4]
+ lib/scudo/standalone/tsd_exclusive.h [3:4]
+ lib/scudo/standalone/tsd_shared.h [3:4]
+ lib/scudo/standalone/vector.h [3:4]
+ lib/scudo/standalone/wrappers_c.cpp [3:4]
+ lib/scudo/standalone/wrappers_c.h [3:4]
+ lib/scudo/standalone/wrappers_c.inc [3:4]
+ lib/scudo/standalone/wrappers_c_checks.h [3:4]
+ lib/scudo/standalone/wrappers_cpp.cpp [3:4]
+ lib/stats/stats.cpp [3:4]
+ lib/stats/stats.h [3:4]
+ lib/stats/stats_client.cpp [3:4]
+ lib/tsan/dd/dd_interceptors.cpp [3:4]
+ lib/tsan/dd/dd_rtl.cpp [3:4]
+ lib/tsan/dd/dd_rtl.h [3:4]
+ lib/tsan/rtl/tsan_debugging.cpp [3:4]
+ lib/tsan/rtl/tsan_defs.h [3:4]
+ lib/tsan/rtl/tsan_dense_alloc.h [3:4]
+ lib/tsan/rtl/tsan_external.cpp [3:4]
+ lib/tsan/rtl/tsan_fd.cpp [3:4]
+ lib/tsan/rtl/tsan_fd.h [3:4]
+ lib/tsan/rtl/tsan_flags.cpp [3:4]
+ lib/tsan/rtl/tsan_flags.h [3:4]
+ lib/tsan/rtl/tsan_flags.inc [3:4]
+ lib/tsan/rtl/tsan_ignoreset.cpp [3:4]
+ lib/tsan/rtl/tsan_ignoreset.h [3:4]
+ lib/tsan/rtl/tsan_ilist.h [3:4]
+ lib/tsan/rtl/tsan_interceptors_libdispatch.cpp [3:4]
+ lib/tsan/rtl/tsan_interceptors_mac.cpp [3:4]
+ lib/tsan/rtl/tsan_interceptors_mach_vm.cpp [3:4]
+ lib/tsan/rtl/tsan_interceptors_posix.cpp [3:4]
+ lib/tsan/rtl/tsan_interface.cpp [3:4]
+ lib/tsan/rtl/tsan_interface.h [3:4]
+ lib/tsan/rtl/tsan_interface.inc [3:4]
+ lib/tsan/rtl/tsan_interface_ann.cpp [3:4]
+ lib/tsan/rtl/tsan_interface_ann.h [3:4]
+ lib/tsan/rtl/tsan_interface_atomic.cpp [3:4]
+ lib/tsan/rtl/tsan_interface_java.cpp [3:4]
+ lib/tsan/rtl/tsan_interface_java.h [3:4]
+ lib/tsan/rtl/tsan_malloc_mac.cpp [3:4]
+ lib/tsan/rtl/tsan_md5.cpp [3:4]
+ lib/tsan/rtl/tsan_mman.cpp [3:4]
+ lib/tsan/rtl/tsan_mman.h [3:4]
+ lib/tsan/rtl/tsan_mutexset.cpp [3:4]
+ lib/tsan/rtl/tsan_mutexset.h [3:4]
+ lib/tsan/rtl/tsan_new_delete.cpp [3:4]
+ lib/tsan/rtl/tsan_platform.h [3:4]
+ lib/tsan/rtl/tsan_platform_linux.cpp [3:4]
+ lib/tsan/rtl/tsan_platform_mac.cpp [3:4]
+ lib/tsan/rtl/tsan_platform_posix.cpp [3:4]
+ lib/tsan/rtl/tsan_platform_windows.cpp [3:4]
+ lib/tsan/rtl/tsan_preinit.cpp [3:4]
+ lib/tsan/rtl/tsan_report.cpp [3:4]
+ lib/tsan/rtl/tsan_report.h [3:4]
+ lib/tsan/rtl/tsan_rtl.cpp [3:4]
+ lib/tsan/rtl/tsan_rtl.h [3:4]
+ lib/tsan/rtl/tsan_rtl_access.cpp [3:4]
+ lib/tsan/rtl/tsan_rtl_mutex.cpp [3:4]
+ lib/tsan/rtl/tsan_rtl_proc.cpp [3:4]
+ lib/tsan/rtl/tsan_rtl_report.cpp [3:4]
+ lib/tsan/rtl/tsan_rtl_thread.cpp [3:4]
+ lib/tsan/rtl/tsan_shadow.h [3:4]
+ lib/tsan/rtl/tsan_stack_trace.cpp [3:4]
+ lib/tsan/rtl/tsan_stack_trace.h [3:4]
+ lib/tsan/rtl/tsan_suppressions.cpp [3:4]
+ lib/tsan/rtl/tsan_suppressions.h [3:4]
+ lib/tsan/rtl/tsan_symbolize.cpp [3:4]
+ lib/tsan/rtl/tsan_symbolize.h [3:4]
+ lib/tsan/rtl/tsan_sync.cpp [3:4]
+ lib/tsan/rtl/tsan_sync.h [3:4]
+ lib/tsan/rtl/tsan_trace.h [3:4]
+ lib/tsan/rtl/tsan_vector_clock.cpp [3:4]
+ lib/tsan/rtl/tsan_vector_clock.h [3:4]
+ lib/ubsan/ubsan_checks.inc [3:4]
+ lib/ubsan/ubsan_diag.cpp [3:4]
+ lib/ubsan/ubsan_diag.h [3:4]
+ lib/ubsan/ubsan_diag_standalone.cpp [3:4]
+ lib/ubsan/ubsan_flags.cpp [3:4]
+ lib/ubsan/ubsan_flags.h [3:4]
+ lib/ubsan/ubsan_flags.inc [3:4]
+ lib/ubsan/ubsan_handlers.cpp [3:4]
+ lib/ubsan/ubsan_handlers.h [3:4]
+ lib/ubsan/ubsan_handlers_cxx.cpp [3:4]
+ lib/ubsan/ubsan_handlers_cxx.h [3:4]
+ lib/ubsan/ubsan_init.cpp [3:4]
+ lib/ubsan/ubsan_init.h [3:4]
+ lib/ubsan/ubsan_init_standalone.cpp [3:4]
+ lib/ubsan/ubsan_init_standalone_preinit.cpp [3:4]
+ lib/ubsan/ubsan_monitor.cpp [3:4]
+ lib/ubsan/ubsan_monitor.h [3:4]
+ lib/ubsan/ubsan_platform.h [3:4]
+ lib/ubsan/ubsan_signals_standalone.cpp [3:4]
+ lib/ubsan/ubsan_signals_standalone.h [4:5]
+ lib/ubsan/ubsan_type_hash.cpp [3:4]
+ lib/ubsan/ubsan_type_hash.h [3:4]
+ lib/ubsan/ubsan_type_hash_itanium.cpp [3:4]
+ lib/ubsan/ubsan_type_hash_win.cpp [3:4]
+ lib/ubsan/ubsan_value.cpp [3:4]
+ lib/ubsan/ubsan_value.h [3:4]
+ Scancode info:
+ Original SPDX id: LLVM-exception
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://llvm.org/foundation/relicensing/LICENSE.txt, https://spdx.org/licenses/LLVM-exception
+ Files with this license:
+ include/sanitizer/allocator_interface.h [3:4]
+ include/sanitizer/asan_interface.h [3:4]
+ include/sanitizer/common_interface_defs.h [3:4]
+ include/sanitizer/coverage_interface.h [3:4]
+ include/sanitizer/dfsan_interface.h [3:4]
+ include/sanitizer/hwasan_interface.h [3:4]
+ include/sanitizer/linux_syscall_hooks.h [3:4]
+ include/sanitizer/lsan_interface.h [3:4]
+ include/sanitizer/memprof_interface.h [3:4]
+ include/sanitizer/msan_interface.h [3:4]
+ include/sanitizer/netbsd_syscall_hooks.h [3:4]
+ include/sanitizer/scudo_interface.h [3:4]
+ include/sanitizer/tsan_interface.h [3:4]
+ include/sanitizer/tsan_interface_atomic.h [3:4]
+ include/sanitizer/ubsan_interface.h [3:4]
+ lib/asan/asan_activation.cpp [3:4]
+ lib/asan/asan_activation.h [3:4]
+ lib/asan/asan_activation_flags.inc [3:4]
+ lib/asan/asan_allocator.cpp [3:4]
+ lib/asan/asan_allocator.h [3:4]
+ lib/asan/asan_debugging.cpp [3:4]
+ lib/asan/asan_descriptions.cpp [3:4]
+ lib/asan/asan_descriptions.h [3:4]
+ lib/asan/asan_errors.cpp [3:4]
+ lib/asan/asan_errors.h [3:4]
+ lib/asan/asan_fake_stack.cpp [3:4]
+ lib/asan/asan_fake_stack.h [3:4]
+ lib/asan/asan_flags.cpp [3:4]
+ lib/asan/asan_flags.h [3:4]
+ lib/asan/asan_flags.inc [3:4]
+ lib/asan/asan_fuchsia.cpp [3:4]
+ lib/asan/asan_globals.cpp [3:4]
+ lib/asan/asan_globals_win.cpp [3:4]
+ lib/asan/asan_init_version.h [3:4]
+ lib/asan/asan_interceptors.cpp [3:4]
+ lib/asan/asan_interceptors.h [3:4]
+ lib/asan/asan_interceptors_memintrinsics.cpp [3:4]
+ lib/asan/asan_interceptors_memintrinsics.h [3:4]
+ lib/asan/asan_interface_internal.h [3:4]
+ lib/asan/asan_internal.h [3:4]
+ lib/asan/asan_linux.cpp [3:4]
+ lib/asan/asan_mac.cpp [3:4]
+ lib/asan/asan_malloc_linux.cpp [3:4]
+ lib/asan/asan_malloc_mac.cpp [3:4]
+ lib/asan/asan_malloc_win.cpp [3:4]
+ lib/asan/asan_mapping.h [3:4]
+ lib/asan/asan_mapping_sparc64.h [3:4]
+ lib/asan/asan_memory_profile.cpp [3:4]
+ lib/asan/asan_new_delete.cpp [3:4]
+ lib/asan/asan_poisoning.cpp [3:4]
+ lib/asan/asan_poisoning.h [3:4]
+ lib/asan/asan_posix.cpp [3:4]
+ lib/asan/asan_preinit.cpp [3:4]
+ lib/asan/asan_premap_shadow.cpp [3:4]
+ lib/asan/asan_premap_shadow.h [3:4]
+ lib/asan/asan_report.cpp [3:4]
+ lib/asan/asan_report.h [3:4]
+ lib/asan/asan_rtl.cpp [3:4]
+ lib/asan/asan_rtl_static.cpp [3:4]
+ lib/asan/asan_scariness_score.h [3:4]
+ lib/asan/asan_shadow_setup.cpp [3:4]
+ lib/asan/asan_stack.cpp [3:4]
+ lib/asan/asan_stack.h [3:4]
+ lib/asan/asan_stats.cpp [3:4]
+ lib/asan/asan_stats.h [3:4]
+ lib/asan/asan_suppressions.cpp [3:4]
+ lib/asan/asan_suppressions.h [3:4]
+ lib/asan/asan_thread.cpp [3:4]
+ lib/asan/asan_thread.h [3:4]
+ lib/asan/asan_win.cpp [4:5]
+ lib/builtins/assembly.h [3:4]
+ lib/cfi/cfi.cpp [3:4]
+ lib/dfsan/dfsan.cpp [3:4]
+ lib/dfsan/dfsan.h [3:4]
+ lib/dfsan/dfsan_allocator.cpp [3:4]
+ lib/dfsan/dfsan_allocator.h [3:4]
+ lib/dfsan/dfsan_chained_origin_depot.cpp [3:4]
+ lib/dfsan/dfsan_chained_origin_depot.h [3:4]
+ lib/dfsan/dfsan_custom.cpp [3:4]
+ lib/dfsan/dfsan_flags.h [3:4]
+ lib/dfsan/dfsan_flags.inc [3:4]
+ lib/dfsan/dfsan_interceptors.cpp [3:4]
+ lib/dfsan/dfsan_new_delete.cpp [3:4]
+ lib/dfsan/dfsan_origin.h [3:4]
+ lib/dfsan/dfsan_platform.h [3:4]
+ lib/dfsan/dfsan_thread.h [3:4]
+ lib/gwp_asan/common.cpp [3:4]
+ lib/gwp_asan/common.h [3:4]
+ lib/gwp_asan/crash_handler.cpp [3:4]
+ lib/gwp_asan/crash_handler.h [3:4]
+ lib/gwp_asan/definitions.h [3:4]
+ lib/gwp_asan/guarded_pool_allocator.cpp [3:4]
+ lib/gwp_asan/guarded_pool_allocator.h [3:4]
+ lib/gwp_asan/mutex.h [3:4]
+ lib/gwp_asan/optional/backtrace.h [3:4]
+ lib/gwp_asan/optional/backtrace_linux_libc.cpp [3:4]
+ lib/gwp_asan/optional/options_parser.cpp [3:4]
+ lib/gwp_asan/optional/options_parser.h [3:4]
+ lib/gwp_asan/optional/printf.h [3:4]
+ lib/gwp_asan/optional/segv_handler.h [3:4]
+ lib/gwp_asan/optional/segv_handler_posix.cpp [3:4]
+ lib/gwp_asan/options.h [3:4]
+ lib/gwp_asan/options.inc [3:4]
+ lib/gwp_asan/platform_specific/common_posix.cpp [3:4]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.h [3:4]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp [3:4]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.h [3:4]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_tls.h [3:4]
+ lib/gwp_asan/platform_specific/mutex_fuchsia.h [3:4]
+ lib/gwp_asan/platform_specific/mutex_posix.cpp [3:4]
+ lib/gwp_asan/platform_specific/mutex_posix.h [3:4]
+ lib/gwp_asan/platform_specific/utilities_posix.cpp [3:4]
+ lib/gwp_asan/stack_trace_compressor.cpp [3:4]
+ lib/gwp_asan/stack_trace_compressor.h [3:4]
+ lib/gwp_asan/utilities.h [3:4]
+ lib/hwasan/hwasan.cpp [3:4]
+ lib/hwasan/hwasan.h [3:4]
+ lib/hwasan/hwasan_allocation_functions.cpp [3:4]
+ lib/hwasan/hwasan_allocator.cpp [3:4]
+ lib/hwasan/hwasan_allocator.h [3:4]
+ lib/hwasan/hwasan_checks.h [3:4]
+ lib/hwasan/hwasan_dynamic_shadow.cpp [3:4]
+ lib/hwasan/hwasan_dynamic_shadow.h [3:4]
+ lib/hwasan/hwasan_exceptions.cpp [3:4]
+ lib/hwasan/hwasan_flags.h [3:4]
+ lib/hwasan/hwasan_flags.inc [3:4]
+ lib/hwasan/hwasan_fuchsia.cpp [3:4]
+ lib/hwasan/hwasan_globals.cpp [3:4]
+ lib/hwasan/hwasan_globals.h [3:4]
+ lib/hwasan/hwasan_interceptors.cpp [3:4]
+ lib/hwasan/hwasan_interface_internal.h [3:4]
+ lib/hwasan/hwasan_linux.cpp [3:4]
+ lib/hwasan/hwasan_malloc_bisect.h [3:4]
+ lib/hwasan/hwasan_mapping.h [3:4]
+ lib/hwasan/hwasan_memintrinsics.cpp [3:4]
+ lib/hwasan/hwasan_new_delete.cpp [3:4]
+ lib/hwasan/hwasan_poisoning.cpp [3:4]
+ lib/hwasan/hwasan_poisoning.h [3:4]
+ lib/hwasan/hwasan_preinit.cpp [3:4]
+ lib/hwasan/hwasan_report.cpp [3:4]
+ lib/hwasan/hwasan_report.h [3:4]
+ lib/hwasan/hwasan_setjmp_aarch64.S [3:4]
+ lib/hwasan/hwasan_setjmp_riscv64.S [3:4]
+ lib/hwasan/hwasan_setjmp_x86_64.S [3:4]
+ lib/hwasan/hwasan_thread.h [3:4]
+ lib/hwasan/hwasan_thread_list.h [3:4]
+ lib/hwasan/hwasan_type_test.cpp [3:4]
+ lib/interception/interception.h [3:4]
+ lib/interception/interception_linux.cpp [3:4]
+ lib/interception/interception_linux.h [3:4]
+ lib/interception/interception_mac.cpp [3:4]
+ lib/interception/interception_mac.h [3:4]
+ lib/interception/interception_type_test.cpp [3:4]
+ lib/interception/interception_win.cpp [3:4]
+ lib/interception/interception_win.h [3:4]
+ lib/lsan/lsan.cpp [3:4]
+ lib/lsan/lsan.h [3:4]
+ lib/lsan/lsan_allocator.cpp [3:4]
+ lib/lsan/lsan_allocator.h [3:4]
+ lib/lsan/lsan_common.cpp [3:4]
+ lib/lsan/lsan_common.h [3:4]
+ lib/lsan/lsan_common_fuchsia.cpp [3:4]
+ lib/lsan/lsan_common_linux.cpp [3:4]
+ lib/lsan/lsan_common_mac.cpp [3:4]
+ lib/lsan/lsan_flags.inc [3:4]
+ lib/lsan/lsan_fuchsia.cpp [3:4]
+ lib/lsan/lsan_fuchsia.h [3:4]
+ lib/lsan/lsan_interceptors.cpp [3:4]
+ lib/lsan/lsan_linux.cpp [3:4]
+ lib/lsan/lsan_mac.cpp [3:4]
+ lib/lsan/lsan_malloc_mac.cpp [3:4]
+ lib/lsan/lsan_posix.cpp [3:4]
+ lib/lsan/lsan_posix.h [3:4]
+ lib/lsan/lsan_preinit.cpp [3:4]
+ lib/lsan/lsan_thread.cpp [3:4]
+ lib/lsan/lsan_thread.h [3:4]
+ lib/memprof/memprof_allocator.cpp [3:4]
+ lib/memprof/memprof_allocator.h [3:4]
+ lib/memprof/memprof_descriptions.cpp [3:4]
+ lib/memprof/memprof_descriptions.h [3:4]
+ lib/memprof/memprof_flags.cpp [3:4]
+ lib/memprof/memprof_flags.h [3:4]
+ lib/memprof/memprof_flags.inc [3:4]
+ lib/memprof/memprof_init_version.h [3:4]
+ lib/memprof/memprof_interceptors.cpp [3:4]
+ lib/memprof/memprof_interceptors.h [3:4]
+ lib/memprof/memprof_interceptors_memintrinsics.cpp [3:4]
+ lib/memprof/memprof_interceptors_memintrinsics.h [3:4]
+ lib/memprof/memprof_interface_internal.h [3:4]
+ lib/memprof/memprof_internal.h [3:4]
+ lib/memprof/memprof_linux.cpp [3:4]
+ lib/memprof/memprof_malloc_linux.cpp [3:4]
+ lib/memprof/memprof_mapping.h [3:4]
+ lib/memprof/memprof_mibmap.cpp [3:4]
+ lib/memprof/memprof_new_delete.cpp [3:4]
+ lib/memprof/memprof_posix.cpp [3:4]
+ lib/memprof/memprof_preinit.cpp [3:4]
+ lib/memprof/memprof_rtl.cpp [3:4]
+ lib/memprof/memprof_shadow_setup.cpp [3:4]
+ lib/memprof/memprof_stack.cpp [3:4]
+ lib/memprof/memprof_stack.h [3:4]
+ lib/memprof/memprof_stats.cpp [3:4]
+ lib/memprof/memprof_stats.h [3:4]
+ lib/memprof/memprof_thread.cpp [3:4]
+ lib/memprof/memprof_thread.h [3:4]
+ lib/msan/msan.cpp [3:4]
+ lib/msan/msan.h [3:4]
+ lib/msan/msan_allocator.cpp [3:4]
+ lib/msan/msan_allocator.h [3:4]
+ lib/msan/msan_chained_origin_depot.cpp [3:4]
+ lib/msan/msan_chained_origin_depot.h [3:4]
+ lib/msan/msan_flags.h [3:4]
+ lib/msan/msan_flags.inc [3:4]
+ lib/msan/msan_interceptors.cpp [3:4]
+ lib/msan/msan_interface_internal.h [3:4]
+ lib/msan/msan_linux.cpp [3:4]
+ lib/msan/msan_new_delete.cpp [3:4]
+ lib/msan/msan_origin.h [3:4]
+ lib/msan/msan_poisoning.cpp [3:4]
+ lib/msan/msan_poisoning.h [3:4]
+ lib/msan/msan_report.cpp [3:4]
+ lib/msan/msan_report.h [3:4]
+ lib/msan/msan_thread.h [3:4]
+ lib/profile/InstrProfilingRuntime.cpp [3:4]
+ lib/safestack/safestack.cpp [3:4]
+ lib/safestack/safestack_platform.h [3:4]
+ lib/safestack/safestack_util.h [3:4]
+ lib/sanitizer_common/sancov_flags.cpp [3:4]
+ lib/sanitizer_common/sancov_flags.h [3:4]
+ lib/sanitizer_common/sancov_flags.inc [3:4]
+ lib/sanitizer_common/sanitizer_addrhashmap.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator.cpp [3:4]
+ lib/sanitizer_common/sanitizer_allocator.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_checks.cpp [3:4]
+ lib/sanitizer_common/sanitizer_allocator_checks.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_combined.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_dlsym.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_interface.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_internal.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_local_cache.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_primary32.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_primary64.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_report.cpp [3:4]
+ lib/sanitizer_common/sanitizer_allocator_report.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_secondary.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_size_class_map.h [3:4]
+ lib/sanitizer_common/sanitizer_allocator_stats.h [3:4]
+ lib/sanitizer_common/sanitizer_asm.h [3:4]
+ lib/sanitizer_common/sanitizer_atomic.h [3:4]
+ lib/sanitizer_common/sanitizer_atomic_clang.h [3:4]
+ lib/sanitizer_common/sanitizer_atomic_clang_mips.h [3:4]
+ lib/sanitizer_common/sanitizer_atomic_clang_other.h [3:4]
+ lib/sanitizer_common/sanitizer_atomic_clang_x86.h [3:4]
+ lib/sanitizer_common/sanitizer_atomic_msvc.h [3:4]
+ lib/sanitizer_common/sanitizer_bitvector.h [3:4]
+ lib/sanitizer_common/sanitizer_bvgraph.h [3:4]
+ lib/sanitizer_common/sanitizer_chained_origin_depot.cpp [3:4]
+ lib/sanitizer_common/sanitizer_chained_origin_depot.h [3:4]
+ lib/sanitizer_common/sanitizer_common.cpp [3:4]
+ lib/sanitizer_common/sanitizer_common.h [3:4]
+ lib/sanitizer_common/sanitizer_common_interceptors.inc [3:4]
+ lib/sanitizer_common/sanitizer_common_interceptors_format.inc [3:4]
+ lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc [3:4]
+ lib/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc [3:4]
+ lib/sanitizer_common/sanitizer_common_interface.inc [3:4]
+ lib/sanitizer_common/sanitizer_common_interface_posix.inc [3:4]
+ lib/sanitizer_common/sanitizer_common_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_common_syscalls.inc [3:4]
+ lib/sanitizer_common/sanitizer_coverage_fuchsia.cpp [3:4]
+ lib/sanitizer_common/sanitizer_coverage_interface.inc [3:4]
+ lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp [3:4]
+ lib/sanitizer_common/sanitizer_coverage_win_sections.cpp [3:4]
+ lib/sanitizer_common/sanitizer_dbghelp.h [3:4]
+ lib/sanitizer_common/sanitizer_deadlock_detector.h [3:4]
+ lib/sanitizer_common/sanitizer_deadlock_detector1.cpp [3:4]
+ lib/sanitizer_common/sanitizer_deadlock_detector2.cpp [3:4]
+ lib/sanitizer_common/sanitizer_deadlock_detector_interface.h [3:4]
+ lib/sanitizer_common/sanitizer_dense_map.h [3:4]
+ lib/sanitizer_common/sanitizer_dense_map_info.h [3:4]
+ lib/sanitizer_common/sanitizer_errno.cpp [3:4]
+ lib/sanitizer_common/sanitizer_errno.h [3:4]
+ lib/sanitizer_common/sanitizer_errno_codes.h [3:4]
+ lib/sanitizer_common/sanitizer_file.cpp [3:4]
+ lib/sanitizer_common/sanitizer_file.h [3:4]
+ lib/sanitizer_common/sanitizer_flag_parser.cpp [3:4]
+ lib/sanitizer_common/sanitizer_flag_parser.h [3:4]
+ lib/sanitizer_common/sanitizer_flags.cpp [3:4]
+ lib/sanitizer_common/sanitizer_flags.h [3:4]
+ lib/sanitizer_common/sanitizer_flags.inc [3:4]
+ lib/sanitizer_common/sanitizer_flat_map.h [3:4]
+ lib/sanitizer_common/sanitizer_freebsd.h [3:4]
+ lib/sanitizer_common/sanitizer_fuchsia.cpp [3:4]
+ lib/sanitizer_common/sanitizer_fuchsia.h [3:4]
+ lib/sanitizer_common/sanitizer_getauxval.h [3:4]
+ lib/sanitizer_common/sanitizer_glibc_version.h [3:4]
+ lib/sanitizer_common/sanitizer_hash.h [3:4]
+ lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc [3:4]
+ lib/sanitizer_common/sanitizer_interface_internal.h [3:4]
+ lib/sanitizer_common/sanitizer_internal_defs.h [3:4]
+ lib/sanitizer_common/sanitizer_leb128.h [3:4]
+ lib/sanitizer_common/sanitizer_lfstack.h [3:4]
+ lib/sanitizer_common/sanitizer_libc.cpp [3:4]
+ lib/sanitizer_common/sanitizer_libc.h [3:4]
+ lib/sanitizer_common/sanitizer_libignore.cpp [3:4]
+ lib/sanitizer_common/sanitizer_libignore.h [3:4]
+ lib/sanitizer_common/sanitizer_linux.cpp [3:4]
+ lib/sanitizer_common/sanitizer_linux.h [3:4]
+ lib/sanitizer_common/sanitizer_linux_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_linux_s390.cpp [3:4]
+ lib/sanitizer_common/sanitizer_list.h [3:4]
+ lib/sanitizer_common/sanitizer_local_address_space_view.h [3:4]
+ lib/sanitizer_common/sanitizer_lzw.h [3:4]
+ lib/sanitizer_common/sanitizer_mac.cpp [3:4]
+ lib/sanitizer_common/sanitizer_mac.h [3:4]
+ lib/sanitizer_common/sanitizer_mac_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_malloc_mac.inc [3:4]
+ lib/sanitizer_common/sanitizer_mutex.cpp [3:4]
+ lib/sanitizer_common/sanitizer_mutex.h [3:4]
+ lib/sanitizer_common/sanitizer_netbsd.cpp [3:4]
+ lib/sanitizer_common/sanitizer_placement_new.h [3:4]
+ lib/sanitizer_common/sanitizer_platform.h [3:4]
+ lib/sanitizer_common/sanitizer_platform_interceptors.h [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_freebsd.h [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_linux.cpp [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_netbsd.h [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_posix.cpp [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_posix.h [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_solaris.cpp [3:4]
+ lib/sanitizer_common/sanitizer_platform_limits_solaris.h [3:4]
+ lib/sanitizer_common/sanitizer_posix.cpp [3:4]
+ lib/sanitizer_common/sanitizer_posix.h [3:4]
+ lib/sanitizer_common/sanitizer_posix_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_printf.cpp [3:4]
+ lib/sanitizer_common/sanitizer_procmaps.h [3:4]
+ lib/sanitizer_common/sanitizer_procmaps_bsd.cpp [3:4]
+ lib/sanitizer_common/sanitizer_procmaps_common.cpp [3:4]
+ lib/sanitizer_common/sanitizer_procmaps_fuchsia.cpp [4:5]
+ lib/sanitizer_common/sanitizer_procmaps_linux.cpp [3:4]
+ lib/sanitizer_common/sanitizer_procmaps_mac.cpp [3:4]
+ lib/sanitizer_common/sanitizer_procmaps_solaris.cpp [3:4]
+ lib/sanitizer_common/sanitizer_ptrauth.h [3:4]
+ lib/sanitizer_common/sanitizer_quarantine.h [3:4]
+ lib/sanitizer_common/sanitizer_report_decorator.h [3:4]
+ lib/sanitizer_common/sanitizer_ring_buffer.h [3:4]
+ lib/sanitizer_common/sanitizer_signal_interceptors.inc [3:4]
+ lib/sanitizer_common/sanitizer_solaris.cpp [3:4]
+ lib/sanitizer_common/sanitizer_solaris.h [3:4]
+ lib/sanitizer_common/sanitizer_stack_store.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stack_store.h [3:4]
+ lib/sanitizer_common/sanitizer_stackdepot.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stackdepot.h [3:4]
+ lib/sanitizer_common/sanitizer_stackdepotbase.h [3:4]
+ lib/sanitizer_common/sanitizer_stacktrace.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stacktrace.h [3:4]
+ lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stacktrace_printer.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stacktrace_printer.h [3:4]
+ lib/sanitizer_common/sanitizer_stacktrace_sparc.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld.h [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.h [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld_mac.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_stoptheworld_win.cpp [3:4]
+ lib/sanitizer_common/sanitizer_suppressions.cpp [3:4]
+ lib/sanitizer_common/sanitizer_suppressions.h [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer.h [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_fuchsia.h [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_internal.h [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_mac.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_mac.h [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_markup.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_report.cpp [3:4]
+ lib/sanitizer_common/sanitizer_symbolizer_win.cpp [3:4]
+ lib/sanitizer_common/sanitizer_syscall_generic.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscall_linux_aarch64.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscall_linux_arm.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscall_linux_hexagon.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscall_linux_loongarch64.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscall_linux_riscv64.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc [3:4]
+ lib/sanitizer_common/sanitizer_syscalls_netbsd.inc [3:4]
+ lib/sanitizer_common/sanitizer_termination.cpp [3:4]
+ lib/sanitizer_common/sanitizer_thread_registry.cpp [3:4]
+ lib/sanitizer_common/sanitizer_thread_registry.h [3:4]
+ lib/sanitizer_common/sanitizer_thread_safety.h [3:4]
+ lib/sanitizer_common/sanitizer_tls_get_addr.cpp [3:4]
+ lib/sanitizer_common/sanitizer_tls_get_addr.h [3:4]
+ lib/sanitizer_common/sanitizer_type_traits.cpp [3:4]
+ lib/sanitizer_common/sanitizer_type_traits.h [3:4]
+ lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp [3:4]
+ lib/sanitizer_common/sanitizer_unwind_win.cpp [3:4]
+ lib/sanitizer_common/sanitizer_vector.h [3:4]
+ lib/sanitizer_common/sanitizer_win.cpp [3:4]
+ lib/sanitizer_common/sanitizer_win.h [3:4]
+ lib/sanitizer_common/sanitizer_win_defs.h [3:4]
+ lib/sanitizer_common/sanitizer_win_dll_thunk.h [3:4]
+ lib/sanitizer_common/sanitizer_win_weak_interception.h [3:4]
+ lib/scudo/standalone/allocator_config.h [3:4]
+ lib/scudo/standalone/atomic_helpers.h [3:4]
+ lib/scudo/standalone/bytemap.h [3:4]
+ lib/scudo/standalone/checksum.cpp [3:4]
+ lib/scudo/standalone/checksum.h [3:4]
+ lib/scudo/standalone/chunk.h [3:4]
+ lib/scudo/standalone/combined.h [3:4]
+ lib/scudo/standalone/common.cpp [3:4]
+ lib/scudo/standalone/common.h [3:4]
+ lib/scudo/standalone/crc32_hw.cpp [3:4]
+ lib/scudo/standalone/flags.cpp [3:4]
+ lib/scudo/standalone/flags.h [3:4]
+ lib/scudo/standalone/flags.inc [3:4]
+ lib/scudo/standalone/flags_parser.cpp [3:4]
+ lib/scudo/standalone/flags_parser.h [3:4]
+ lib/scudo/standalone/fuchsia.cpp [3:4]
+ lib/scudo/standalone/fuchsia.h [3:4]
+ lib/scudo/standalone/include/scudo/interface.h [3:4]
+ lib/scudo/standalone/internal_defs.h [3:4]
+ lib/scudo/standalone/linux.cpp [3:4]
+ lib/scudo/standalone/linux.h [3:4]
+ lib/scudo/standalone/list.h [3:4]
+ lib/scudo/standalone/local_cache.h [3:4]
+ lib/scudo/standalone/memtag.h [3:4]
+ lib/scudo/standalone/mutex.h [3:4]
+ lib/scudo/standalone/options.h [3:4]
+ lib/scudo/standalone/platform.h [3:4]
+ lib/scudo/standalone/primary32.h [3:4]
+ lib/scudo/standalone/primary64.h [3:4]
+ lib/scudo/standalone/quarantine.h [3:4]
+ lib/scudo/standalone/release.cpp [3:4]
+ lib/scudo/standalone/release.h [3:4]
+ lib/scudo/standalone/report.cpp [3:4]
+ lib/scudo/standalone/report.h [3:4]
+ lib/scudo/standalone/rss_limit_checker.cpp [3:4]
+ lib/scudo/standalone/rss_limit_checker.h [3:4]
+ lib/scudo/standalone/secondary.h [3:4]
+ lib/scudo/standalone/size_class_map.h [3:4]
+ lib/scudo/standalone/stack_depot.h [3:4]
+ lib/scudo/standalone/stats.h [3:4]
+ lib/scudo/standalone/string_utils.cpp [3:4]
+ lib/scudo/standalone/string_utils.h [3:4]
+ lib/scudo/standalone/trusty.h [3:4]
+ lib/scudo/standalone/tsd.h [3:4]
+ lib/scudo/standalone/tsd_exclusive.h [3:4]
+ lib/scudo/standalone/tsd_shared.h [3:4]
+ lib/scudo/standalone/vector.h [3:4]
+ lib/scudo/standalone/wrappers_c.cpp [3:4]
+ lib/scudo/standalone/wrappers_c.h [3:4]
+ lib/scudo/standalone/wrappers_c.inc [3:4]
+ lib/scudo/standalone/wrappers_c_checks.h [3:4]
+ lib/scudo/standalone/wrappers_cpp.cpp [3:4]
+ lib/stats/stats.cpp [3:4]
+ lib/stats/stats.h [3:4]
+ lib/stats/stats_client.cpp [3:4]
+ lib/tsan/dd/dd_interceptors.cpp [3:4]
+ lib/tsan/dd/dd_rtl.cpp [3:4]
+ lib/tsan/dd/dd_rtl.h [3:4]
+ lib/tsan/rtl/tsan_debugging.cpp [3:4]
+ lib/tsan/rtl/tsan_defs.h [3:4]
+ lib/tsan/rtl/tsan_dense_alloc.h [3:4]
+ lib/tsan/rtl/tsan_external.cpp [3:4]
+ lib/tsan/rtl/tsan_fd.cpp [3:4]
+ lib/tsan/rtl/tsan_fd.h [3:4]
+ lib/tsan/rtl/tsan_flags.cpp [3:4]
+ lib/tsan/rtl/tsan_flags.h [3:4]
+ lib/tsan/rtl/tsan_flags.inc [3:4]
+ lib/tsan/rtl/tsan_ignoreset.cpp [3:4]
+ lib/tsan/rtl/tsan_ignoreset.h [3:4]
+ lib/tsan/rtl/tsan_ilist.h [3:4]
+ lib/tsan/rtl/tsan_interceptors_libdispatch.cpp [3:4]
+ lib/tsan/rtl/tsan_interceptors_mac.cpp [3:4]
+ lib/tsan/rtl/tsan_interceptors_mach_vm.cpp [3:4]
+ lib/tsan/rtl/tsan_interceptors_posix.cpp [3:4]
+ lib/tsan/rtl/tsan_interface.cpp [3:4]
+ lib/tsan/rtl/tsan_interface.h [3:4]
+ lib/tsan/rtl/tsan_interface.inc [3:4]
+ lib/tsan/rtl/tsan_interface_ann.cpp [3:4]
+ lib/tsan/rtl/tsan_interface_ann.h [3:4]
+ lib/tsan/rtl/tsan_interface_atomic.cpp [3:4]
+ lib/tsan/rtl/tsan_interface_java.cpp [3:4]
+ lib/tsan/rtl/tsan_interface_java.h [3:4]
+ lib/tsan/rtl/tsan_malloc_mac.cpp [3:4]
+ lib/tsan/rtl/tsan_md5.cpp [3:4]
+ lib/tsan/rtl/tsan_mman.cpp [3:4]
+ lib/tsan/rtl/tsan_mman.h [3:4]
+ lib/tsan/rtl/tsan_mutexset.cpp [3:4]
+ lib/tsan/rtl/tsan_mutexset.h [3:4]
+ lib/tsan/rtl/tsan_new_delete.cpp [3:4]
+ lib/tsan/rtl/tsan_platform.h [3:4]
+ lib/tsan/rtl/tsan_platform_linux.cpp [3:4]
+ lib/tsan/rtl/tsan_platform_mac.cpp [3:4]
+ lib/tsan/rtl/tsan_platform_posix.cpp [3:4]
+ lib/tsan/rtl/tsan_platform_windows.cpp [3:4]
+ lib/tsan/rtl/tsan_preinit.cpp [3:4]
+ lib/tsan/rtl/tsan_report.cpp [3:4]
+ lib/tsan/rtl/tsan_report.h [3:4]
+ lib/tsan/rtl/tsan_rtl.cpp [3:4]
+ lib/tsan/rtl/tsan_rtl.h [3:4]
+ lib/tsan/rtl/tsan_rtl_access.cpp [3:4]
+ lib/tsan/rtl/tsan_rtl_mutex.cpp [3:4]
+ lib/tsan/rtl/tsan_rtl_proc.cpp [3:4]
+ lib/tsan/rtl/tsan_rtl_report.cpp [3:4]
+ lib/tsan/rtl/tsan_rtl_thread.cpp [3:4]
+ lib/tsan/rtl/tsan_shadow.h [3:4]
+ lib/tsan/rtl/tsan_stack_trace.cpp [3:4]
+ lib/tsan/rtl/tsan_stack_trace.h [3:4]
+ lib/tsan/rtl/tsan_suppressions.cpp [3:4]
+ lib/tsan/rtl/tsan_suppressions.h [3:4]
+ lib/tsan/rtl/tsan_symbolize.cpp [3:4]
+ lib/tsan/rtl/tsan_symbolize.h [3:4]
+ lib/tsan/rtl/tsan_sync.cpp [3:4]
+ lib/tsan/rtl/tsan_sync.h [3:4]
+ lib/tsan/rtl/tsan_trace.h [3:4]
+ lib/tsan/rtl/tsan_vector_clock.cpp [3:4]
+ lib/tsan/rtl/tsan_vector_clock.h [3:4]
+ lib/ubsan/ubsan_checks.inc [3:4]
+ lib/ubsan/ubsan_diag.cpp [3:4]
+ lib/ubsan/ubsan_diag.h [3:4]
+ lib/ubsan/ubsan_diag_standalone.cpp [3:4]
+ lib/ubsan/ubsan_flags.cpp [3:4]
+ lib/ubsan/ubsan_flags.h [3:4]
+ lib/ubsan/ubsan_flags.inc [3:4]
+ lib/ubsan/ubsan_handlers.cpp [3:4]
+ lib/ubsan/ubsan_handlers.h [3:4]
+ lib/ubsan/ubsan_handlers_cxx.cpp [3:4]
+ lib/ubsan/ubsan_handlers_cxx.h [3:4]
+ lib/ubsan/ubsan_init.cpp [3:4]
+ lib/ubsan/ubsan_init.h [3:4]
+ lib/ubsan/ubsan_init_standalone.cpp [3:4]
+ lib/ubsan/ubsan_init_standalone_preinit.cpp [3:4]
+ lib/ubsan/ubsan_monitor.cpp [3:4]
+ lib/ubsan/ubsan_monitor.h [3:4]
+ lib/ubsan/ubsan_platform.h [3:4]
+ lib/ubsan/ubsan_signals_standalone.cpp [3:4]
+ lib/ubsan/ubsan_signals_standalone.h [4:5]
+ lib/ubsan/ubsan_type_hash.cpp [3:4]
+ lib/ubsan/ubsan_type_hash.h [3:4]
+ lib/ubsan/ubsan_type_hash_itanium.cpp [3:4]
+ lib/ubsan/ubsan_type_hash_win.cpp [3:4]
+ lib/ubsan/ubsan_value.cpp [3:4]
+ lib/ubsan/ubsan_value.h [3:4]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/memprof-preinit/ya.make lib/memprof_cxx/ya.make lib/msan_cxx/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats_client/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP Apache-2.0 WITH LLVM-exception 8494a9caed330d9a4f40e19cce7dc770
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: LLVM-exception
+ Score : 100.00
+ Match type : TEXT
+ Links : http://llvm.org/foundation/relicensing/LICENSE.txt, https://spdx.org/licenses/LLVM-exception
+ Files with this license:
+ LICENSE.TXT [208:222]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP Apache-2.0 WITH LLVM-exception 8a58f39345a246b9ca05473930feef83
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ License text:
+ |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ Scancode info:
+ Original SPDX id: Apache-2.0
+ Score : 100.00
+ Match type : TAG
+ Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0
+ Files with this license:
+ include/profile/InstrProfData.inc [5:5]
+ include/profile/MIBEntryDef.inc [5:5]
+ include/profile/MemProfData.inc [7:7]
+ lib/profile/GCDAProfiling.c [5:5]
+ lib/profile/InstrProfiling.c [5:5]
+ lib/profile/InstrProfiling.h [5:5]
+ lib/profile/InstrProfilingBuffer.c [5:5]
+ lib/profile/InstrProfilingFile.c [5:5]
+ lib/profile/InstrProfilingInternal.c [5:5]
+ lib/profile/InstrProfilingInternal.h [5:5]
+ lib/profile/InstrProfilingMerge.c [5:5]
+ lib/profile/InstrProfilingMergeFile.c [5:5]
+ lib/profile/InstrProfilingNameVar.c [5:5]
+ lib/profile/InstrProfilingPlatformDarwin.c [5:5]
+ lib/profile/InstrProfilingPlatformFuchsia.c [5:5]
+ lib/profile/InstrProfilingPlatformLinux.c [5:5]
+ lib/profile/InstrProfilingPlatformOther.c [5:5]
+ lib/profile/InstrProfilingPlatformWindows.c [5:5]
+ lib/profile/InstrProfilingPort.h [5:5]
+ lib/profile/InstrProfilingUtil.c [5:5]
+ lib/profile/InstrProfilingUtil.h [5:5]
+ lib/profile/InstrProfilingValue.c [5:5]
+ lib/profile/InstrProfilingVersionVar.c [5:5]
+ lib/profile/InstrProfilingWriter.c [5:5]
+ lib/profile/WindowsMMap.h [5:5]
+ Scancode info:
+ Original SPDX id: LLVM-exception
+ Score : 100.00
+ Match type : TAG
+ Links : http://llvm.org/foundation/relicensing/LICENSE.txt, https://spdx.org/licenses/LLVM-exception
+ Files with this license:
+ include/profile/InstrProfData.inc [5:5]
+ include/profile/MIBEntryDef.inc [5:5]
+ include/profile/MemProfData.inc [7:7]
+ lib/profile/GCDAProfiling.c [5:5]
+ lib/profile/InstrProfiling.c [5:5]
+ lib/profile/InstrProfiling.h [5:5]
+ lib/profile/InstrProfilingBuffer.c [5:5]
+ lib/profile/InstrProfilingFile.c [5:5]
+ lib/profile/InstrProfilingInternal.c [5:5]
+ lib/profile/InstrProfilingInternal.h [5:5]
+ lib/profile/InstrProfilingMerge.c [5:5]
+ lib/profile/InstrProfilingMergeFile.c [5:5]
+ lib/profile/InstrProfilingNameVar.c [5:5]
+ lib/profile/InstrProfilingPlatformDarwin.c [5:5]
+ lib/profile/InstrProfilingPlatformFuchsia.c [5:5]
+ lib/profile/InstrProfilingPlatformLinux.c [5:5]
+ lib/profile/InstrProfilingPlatformOther.c [5:5]
+ lib/profile/InstrProfilingPlatformWindows.c [5:5]
+ lib/profile/InstrProfilingPort.h [5:5]
+ lib/profile/InstrProfilingUtil.c [5:5]
+ lib/profile/InstrProfilingUtil.h [5:5]
+ lib/profile/InstrProfilingValue.c [5:5]
+ lib/profile/InstrProfilingVersionVar.c [5:5]
+ lib/profile/InstrProfilingWriter.c [5:5]
+ lib/profile/WindowsMMap.h [5:5]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+SKIP LicenseRef-scancode-warranty-disclaimer 9859678dbf968262a249b27e6bf5dfec
+BELONGS lib/asan/ya.make
+ License text:
+ "(WARNING: USE AT YOUR OWN RISK!)")
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-warranty-disclaimer
+ Score : 100.00
+ Match type : TEXT
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/warranty-disclaimer.LICENSE
+ Files with this license:
+ lib/asan/asan_flags.inc [157:157]
+
+KEEP Apache-2.0 9ac77f65a898755c7eed97099caded94
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: Apache-2.0
+ Score : 100.00
+ Match type : TEXT
+ Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0
+ Files with this license:
+ LICENSE.TXT [5:205]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP NCSA AND MIT acaf5a1ddffd6829f7ebecb9e50c6c5f
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: NCSA
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.otm.illinois.edu/faculty/forms/opensource.asp, https://spdx.org/licenses/NCSA
+ Files with this license:
+ LICENSE.TXT [240:245]
+ Scancode info:
+ Original SPDX id: MIT
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://opensource.org/licenses/mit-license.php, https://spdx.org/licenses/MIT
+ Files with this license:
+ LICENSE.TXT [240:245]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP NCSA b160d8bd561da097b0edd40b062e1c84
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: NCSA
+ Score : 100.00
+ Match type : TEXT
+ Links : http://www.otm.illinois.edu/faculty/forms/opensource.asp, https://spdx.org/licenses/NCSA
+ Files with this license:
+ LICENSE.TXT [264:289]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP Apache-2.0 WITH LLVM-exception b7566a1930e050e1090162bf1d543650
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ License text:
+ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ Scancode info:
+ Original SPDX id: Apache-2.0
+ Score : 100.00
+ Match type : TAG
+ Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0
+ Files with this license:
+ include/sanitizer/allocator_interface.h [5:5]
+ include/sanitizer/asan_interface.h [5:5]
+ include/sanitizer/common_interface_defs.h [5:5]
+ include/sanitizer/coverage_interface.h [5:5]
+ include/sanitizer/dfsan_interface.h [5:5]
+ include/sanitizer/hwasan_interface.h [5:5]
+ include/sanitizer/linux_syscall_hooks.h [5:5]
+ include/sanitizer/lsan_interface.h [5:5]
+ include/sanitizer/memprof_interface.h [5:5]
+ include/sanitizer/msan_interface.h [5:5]
+ include/sanitizer/netbsd_syscall_hooks.h [5:5]
+ include/sanitizer/scudo_interface.h [5:5]
+ include/sanitizer/tsan_interface.h [5:5]
+ include/sanitizer/tsan_interface_atomic.h [5:5]
+ include/sanitizer/ubsan_interface.h [5:5]
+ lib/asan/asan_activation.cpp [5:5]
+ lib/asan/asan_activation.h [5:5]
+ lib/asan/asan_activation_flags.inc [5:5]
+ lib/asan/asan_allocator.cpp [5:5]
+ lib/asan/asan_allocator.h [5:5]
+ lib/asan/asan_debugging.cpp [5:5]
+ lib/asan/asan_descriptions.cpp [5:5]
+ lib/asan/asan_descriptions.h [5:5]
+ lib/asan/asan_errors.cpp [5:5]
+ lib/asan/asan_errors.h [5:5]
+ lib/asan/asan_fake_stack.cpp [5:5]
+ lib/asan/asan_fake_stack.h [5:5]
+ lib/asan/asan_flags.cpp [5:5]
+ lib/asan/asan_flags.h [5:5]
+ lib/asan/asan_flags.inc [5:5]
+ lib/asan/asan_fuchsia.cpp [5:5]
+ lib/asan/asan_globals.cpp [5:5]
+ lib/asan/asan_globals_win.cpp [5:5]
+ lib/asan/asan_init_version.h [5:5]
+ lib/asan/asan_interceptors.cpp [5:5]
+ lib/asan/asan_interceptors.h [5:5]
+ lib/asan/asan_interceptors_memintrinsics.cpp [5:5]
+ lib/asan/asan_interceptors_memintrinsics.h [5:5]
+ lib/asan/asan_interface_internal.h [5:5]
+ lib/asan/asan_internal.h [5:5]
+ lib/asan/asan_linux.cpp [5:5]
+ lib/asan/asan_mac.cpp [5:5]
+ lib/asan/asan_malloc_linux.cpp [5:5]
+ lib/asan/asan_malloc_mac.cpp [5:5]
+ lib/asan/asan_malloc_win.cpp [5:5]
+ lib/asan/asan_mapping.h [5:5]
+ lib/asan/asan_mapping_sparc64.h [5:5]
+ lib/asan/asan_memory_profile.cpp [5:5]
+ lib/asan/asan_new_delete.cpp [5:5]
+ lib/asan/asan_poisoning.cpp [5:5]
+ lib/asan/asan_poisoning.h [5:5]
+ lib/asan/asan_posix.cpp [5:5]
+ lib/asan/asan_preinit.cpp [5:5]
+ lib/asan/asan_premap_shadow.cpp [5:5]
+ lib/asan/asan_premap_shadow.h [5:5]
+ lib/asan/asan_report.cpp [5:5]
+ lib/asan/asan_report.h [5:5]
+ lib/asan/asan_rtl.cpp [5:5]
+ lib/asan/asan_rtl_static.cpp [5:5]
+ lib/asan/asan_scariness_score.h [5:5]
+ lib/asan/asan_shadow_setup.cpp [5:5]
+ lib/asan/asan_stack.cpp [5:5]
+ lib/asan/asan_stack.h [5:5]
+ lib/asan/asan_stats.cpp [5:5]
+ lib/asan/asan_stats.h [5:5]
+ lib/asan/asan_suppressions.cpp [5:5]
+ lib/asan/asan_suppressions.h [5:5]
+ lib/asan/asan_thread.cpp [5:5]
+ lib/asan/asan_thread.h [5:5]
+ lib/asan/asan_win.cpp [6:6]
+ lib/builtins/assembly.h [5:5]
+ lib/cfi/cfi.cpp [5:5]
+ lib/dfsan/dfsan.cpp [5:5]
+ lib/dfsan/dfsan.h [5:5]
+ lib/dfsan/dfsan_allocator.cpp [5:5]
+ lib/dfsan/dfsan_allocator.h [5:5]
+ lib/dfsan/dfsan_chained_origin_depot.cpp [5:5]
+ lib/dfsan/dfsan_chained_origin_depot.h [5:5]
+ lib/dfsan/dfsan_custom.cpp [5:5]
+ lib/dfsan/dfsan_flags.h [5:5]
+ lib/dfsan/dfsan_flags.inc [5:5]
+ lib/dfsan/dfsan_interceptors.cpp [5:5]
+ lib/dfsan/dfsan_new_delete.cpp [5:5]
+ lib/dfsan/dfsan_origin.h [5:5]
+ lib/dfsan/dfsan_platform.h [5:5]
+ lib/dfsan/dfsan_thread.h [5:5]
+ lib/gwp_asan/common.cpp [5:5]
+ lib/gwp_asan/common.h [5:5]
+ lib/gwp_asan/crash_handler.cpp [5:5]
+ lib/gwp_asan/crash_handler.h [5:5]
+ lib/gwp_asan/definitions.h [5:5]
+ lib/gwp_asan/guarded_pool_allocator.cpp [5:5]
+ lib/gwp_asan/guarded_pool_allocator.h [5:5]
+ lib/gwp_asan/mutex.h [5:5]
+ lib/gwp_asan/optional/backtrace.h [5:5]
+ lib/gwp_asan/optional/backtrace_linux_libc.cpp [5:5]
+ lib/gwp_asan/optional/options_parser.cpp [5:5]
+ lib/gwp_asan/optional/options_parser.h [5:5]
+ lib/gwp_asan/optional/printf.h [5:5]
+ lib/gwp_asan/optional/segv_handler.h [5:5]
+ lib/gwp_asan/optional/segv_handler_posix.cpp [5:5]
+ lib/gwp_asan/options.h [5:5]
+ lib/gwp_asan/options.inc [5:5]
+ lib/gwp_asan/platform_specific/common_posix.cpp [5:5]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.h [5:5]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp [5:5]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.h [5:5]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_tls.h [5:5]
+ lib/gwp_asan/platform_specific/mutex_fuchsia.h [5:5]
+ lib/gwp_asan/platform_specific/mutex_posix.cpp [5:5]
+ lib/gwp_asan/platform_specific/mutex_posix.h [5:5]
+ lib/gwp_asan/platform_specific/utilities_posix.cpp [5:5]
+ lib/gwp_asan/stack_trace_compressor.cpp [5:5]
+ lib/gwp_asan/stack_trace_compressor.h [5:5]
+ lib/gwp_asan/utilities.h [5:5]
+ lib/hwasan/hwasan.cpp [5:5]
+ lib/hwasan/hwasan.h [5:5]
+ lib/hwasan/hwasan_allocation_functions.cpp [5:5]
+ lib/hwasan/hwasan_allocator.cpp [5:5]
+ lib/hwasan/hwasan_allocator.h [5:5]
+ lib/hwasan/hwasan_checks.h [5:5]
+ lib/hwasan/hwasan_dynamic_shadow.cpp [5:5]
+ lib/hwasan/hwasan_dynamic_shadow.h [5:5]
+ lib/hwasan/hwasan_exceptions.cpp [5:5]
+ lib/hwasan/hwasan_flags.h [5:5]
+ lib/hwasan/hwasan_flags.inc [5:5]
+ lib/hwasan/hwasan_fuchsia.cpp [5:5]
+ lib/hwasan/hwasan_globals.cpp [5:5]
+ lib/hwasan/hwasan_globals.h [5:5]
+ lib/hwasan/hwasan_interceptors.cpp [5:5]
+ lib/hwasan/hwasan_interface_internal.h [5:5]
+ lib/hwasan/hwasan_linux.cpp [5:5]
+ lib/hwasan/hwasan_malloc_bisect.h [5:5]
+ lib/hwasan/hwasan_mapping.h [5:5]
+ lib/hwasan/hwasan_memintrinsics.cpp [5:5]
+ lib/hwasan/hwasan_new_delete.cpp [5:5]
+ lib/hwasan/hwasan_poisoning.cpp [5:5]
+ lib/hwasan/hwasan_poisoning.h [5:5]
+ lib/hwasan/hwasan_preinit.cpp [5:5]
+ lib/hwasan/hwasan_report.cpp [5:5]
+ lib/hwasan/hwasan_report.h [5:5]
+ lib/hwasan/hwasan_setjmp_aarch64.S [5:5]
+ lib/hwasan/hwasan_setjmp_riscv64.S [5:5]
+ lib/hwasan/hwasan_setjmp_x86_64.S [5:5]
+ lib/hwasan/hwasan_thread.h [5:5]
+ lib/hwasan/hwasan_thread_list.h [5:5]
+ lib/hwasan/hwasan_type_test.cpp [5:5]
+ lib/interception/interception.h [5:5]
+ lib/interception/interception_linux.cpp [5:5]
+ lib/interception/interception_linux.h [5:5]
+ lib/interception/interception_mac.cpp [5:5]
+ lib/interception/interception_mac.h [5:5]
+ lib/interception/interception_type_test.cpp [5:5]
+ lib/interception/interception_win.cpp [5:5]
+ lib/interception/interception_win.h [5:5]
+ lib/lsan/lsan.cpp [5:5]
+ lib/lsan/lsan.h [5:5]
+ lib/lsan/lsan_allocator.cpp [5:5]
+ lib/lsan/lsan_allocator.h [5:5]
+ lib/lsan/lsan_common.cpp [5:5]
+ lib/lsan/lsan_common.h [5:5]
+ lib/lsan/lsan_common_fuchsia.cpp [5:5]
+ lib/lsan/lsan_common_linux.cpp [5:5]
+ lib/lsan/lsan_common_mac.cpp [5:5]
+ lib/lsan/lsan_flags.inc [5:5]
+ lib/lsan/lsan_fuchsia.cpp [5:5]
+ lib/lsan/lsan_fuchsia.h [5:5]
+ lib/lsan/lsan_interceptors.cpp [5:5]
+ lib/lsan/lsan_linux.cpp [5:5]
+ lib/lsan/lsan_mac.cpp [5:5]
+ lib/lsan/lsan_malloc_mac.cpp [5:5]
+ lib/lsan/lsan_posix.cpp [5:5]
+ lib/lsan/lsan_posix.h [5:5]
+ lib/lsan/lsan_preinit.cpp [5:5]
+ lib/lsan/lsan_thread.cpp [5:5]
+ lib/lsan/lsan_thread.h [5:5]
+ lib/memprof/memprof_allocator.cpp [5:5]
+ lib/memprof/memprof_allocator.h [5:5]
+ lib/memprof/memprof_descriptions.cpp [5:5]
+ lib/memprof/memprof_descriptions.h [5:5]
+ lib/memprof/memprof_flags.cpp [5:5]
+ lib/memprof/memprof_flags.h [5:5]
+ lib/memprof/memprof_flags.inc [5:5]
+ lib/memprof/memprof_init_version.h [5:5]
+ lib/memprof/memprof_interceptors.cpp [5:5]
+ lib/memprof/memprof_interceptors.h [5:5]
+ lib/memprof/memprof_interceptors_memintrinsics.cpp [5:5]
+ lib/memprof/memprof_interceptors_memintrinsics.h [5:5]
+ lib/memprof/memprof_interface_internal.h [5:5]
+ lib/memprof/memprof_internal.h [5:5]
+ lib/memprof/memprof_linux.cpp [5:5]
+ lib/memprof/memprof_malloc_linux.cpp [5:5]
+ lib/memprof/memprof_mapping.h [5:5]
+ lib/memprof/memprof_mibmap.cpp [5:5]
+ lib/memprof/memprof_new_delete.cpp [5:5]
+ lib/memprof/memprof_posix.cpp [5:5]
+ lib/memprof/memprof_preinit.cpp [5:5]
+ lib/memprof/memprof_rtl.cpp [5:5]
+ lib/memprof/memprof_shadow_setup.cpp [5:5]
+ lib/memprof/memprof_stack.cpp [5:5]
+ lib/memprof/memprof_stack.h [5:5]
+ lib/memprof/memprof_stats.cpp [5:5]
+ lib/memprof/memprof_stats.h [5:5]
+ lib/memprof/memprof_thread.cpp [5:5]
+ lib/memprof/memprof_thread.h [5:5]
+ lib/msan/msan.cpp [5:5]
+ lib/msan/msan.h [5:5]
+ lib/msan/msan_allocator.cpp [5:5]
+ lib/msan/msan_allocator.h [5:5]
+ lib/msan/msan_chained_origin_depot.cpp [5:5]
+ lib/msan/msan_chained_origin_depot.h [5:5]
+ lib/msan/msan_flags.h [5:5]
+ lib/msan/msan_flags.inc [5:5]
+ lib/msan/msan_interceptors.cpp [5:5]
+ lib/msan/msan_interface_internal.h [5:5]
+ lib/msan/msan_linux.cpp [5:5]
+ lib/msan/msan_new_delete.cpp [5:5]
+ lib/msan/msan_origin.h [5:5]
+ lib/msan/msan_poisoning.cpp [5:5]
+ lib/msan/msan_poisoning.h [5:5]
+ lib/msan/msan_report.cpp [5:5]
+ lib/msan/msan_report.h [5:5]
+ lib/msan/msan_thread.h [5:5]
+ lib/profile/InstrProfilingRuntime.cpp [5:5]
+ lib/safestack/safestack.cpp [5:5]
+ lib/safestack/safestack_platform.h [5:5]
+ lib/safestack/safestack_util.h [5:5]
+ lib/sanitizer_common/sancov_flags.cpp [5:5]
+ lib/sanitizer_common/sancov_flags.h [5:5]
+ lib/sanitizer_common/sancov_flags.inc [5:5]
+ lib/sanitizer_common/sanitizer_addrhashmap.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator.cpp [5:5]
+ lib/sanitizer_common/sanitizer_allocator.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_checks.cpp [5:5]
+ lib/sanitizer_common/sanitizer_allocator_checks.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_combined.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_dlsym.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_interface.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_internal.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_local_cache.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_primary32.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_primary64.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_report.cpp [5:5]
+ lib/sanitizer_common/sanitizer_allocator_report.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_secondary.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_size_class_map.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_stats.h [5:5]
+ lib/sanitizer_common/sanitizer_asm.h [5:5]
+ lib/sanitizer_common/sanitizer_atomic.h [5:5]
+ lib/sanitizer_common/sanitizer_atomic_clang.h [5:5]
+ lib/sanitizer_common/sanitizer_atomic_clang_mips.h [5:5]
+ lib/sanitizer_common/sanitizer_atomic_clang_other.h [5:5]
+ lib/sanitizer_common/sanitizer_atomic_clang_x86.h [5:5]
+ lib/sanitizer_common/sanitizer_atomic_msvc.h [5:5]
+ lib/sanitizer_common/sanitizer_bitvector.h [5:5]
+ lib/sanitizer_common/sanitizer_bvgraph.h [5:5]
+ lib/sanitizer_common/sanitizer_chained_origin_depot.cpp [5:5]
+ lib/sanitizer_common/sanitizer_chained_origin_depot.h [5:5]
+ lib/sanitizer_common/sanitizer_common.cpp [5:5]
+ lib/sanitizer_common/sanitizer_common.h [5:5]
+ lib/sanitizer_common/sanitizer_common_interceptors.inc [5:5]
+ lib/sanitizer_common/sanitizer_common_interceptors_format.inc [5:5]
+ lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc [5:5]
+ lib/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc [5:5]
+ lib/sanitizer_common/sanitizer_common_interface.inc [5:5]
+ lib/sanitizer_common/sanitizer_common_interface_posix.inc [5:5]
+ lib/sanitizer_common/sanitizer_common_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_common_syscalls.inc [5:5]
+ lib/sanitizer_common/sanitizer_coverage_fuchsia.cpp [5:5]
+ lib/sanitizer_common/sanitizer_coverage_interface.inc [5:5]
+ lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp [5:5]
+ lib/sanitizer_common/sanitizer_coverage_win_sections.cpp [5:5]
+ lib/sanitizer_common/sanitizer_dbghelp.h [5:5]
+ lib/sanitizer_common/sanitizer_deadlock_detector.h [5:5]
+ lib/sanitizer_common/sanitizer_deadlock_detector1.cpp [5:5]
+ lib/sanitizer_common/sanitizer_deadlock_detector2.cpp [5:5]
+ lib/sanitizer_common/sanitizer_deadlock_detector_interface.h [5:5]
+ lib/sanitizer_common/sanitizer_dense_map.h [5:5]
+ lib/sanitizer_common/sanitizer_dense_map_info.h [5:5]
+ lib/sanitizer_common/sanitizer_errno.cpp [5:5]
+ lib/sanitizer_common/sanitizer_errno.h [5:5]
+ lib/sanitizer_common/sanitizer_errno_codes.h [5:5]
+ lib/sanitizer_common/sanitizer_file.cpp [5:5]
+ lib/sanitizer_common/sanitizer_file.h [5:5]
+ lib/sanitizer_common/sanitizer_flag_parser.cpp [5:5]
+ lib/sanitizer_common/sanitizer_flag_parser.h [5:5]
+ lib/sanitizer_common/sanitizer_flags.cpp [5:5]
+ lib/sanitizer_common/sanitizer_flags.h [5:5]
+ lib/sanitizer_common/sanitizer_flags.inc [5:5]
+ lib/sanitizer_common/sanitizer_flat_map.h [5:5]
+ lib/sanitizer_common/sanitizer_freebsd.h [5:5]
+ lib/sanitizer_common/sanitizer_fuchsia.cpp [5:5]
+ lib/sanitizer_common/sanitizer_fuchsia.h [5:5]
+ lib/sanitizer_common/sanitizer_getauxval.h [5:5]
+ lib/sanitizer_common/sanitizer_glibc_version.h [5:5]
+ lib/sanitizer_common/sanitizer_hash.h [5:5]
+ lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc [5:5]
+ lib/sanitizer_common/sanitizer_interface_internal.h [5:5]
+ lib/sanitizer_common/sanitizer_internal_defs.h [5:5]
+ lib/sanitizer_common/sanitizer_leb128.h [5:5]
+ lib/sanitizer_common/sanitizer_lfstack.h [5:5]
+ lib/sanitizer_common/sanitizer_libc.cpp [5:5]
+ lib/sanitizer_common/sanitizer_libc.h [5:5]
+ lib/sanitizer_common/sanitizer_libignore.cpp [5:5]
+ lib/sanitizer_common/sanitizer_libignore.h [5:5]
+ lib/sanitizer_common/sanitizer_linux.cpp [5:5]
+ lib/sanitizer_common/sanitizer_linux.h [5:5]
+ lib/sanitizer_common/sanitizer_linux_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_linux_s390.cpp [5:5]
+ lib/sanitizer_common/sanitizer_list.h [5:5]
+ lib/sanitizer_common/sanitizer_local_address_space_view.h [5:5]
+ lib/sanitizer_common/sanitizer_lzw.h [5:5]
+ lib/sanitizer_common/sanitizer_mac.cpp [5:5]
+ lib/sanitizer_common/sanitizer_mac.h [5:5]
+ lib/sanitizer_common/sanitizer_mac_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_malloc_mac.inc [5:5]
+ lib/sanitizer_common/sanitizer_mutex.cpp [5:5]
+ lib/sanitizer_common/sanitizer_mutex.h [5:5]
+ lib/sanitizer_common/sanitizer_netbsd.cpp [5:5]
+ lib/sanitizer_common/sanitizer_placement_new.h [5:5]
+ lib/sanitizer_common/sanitizer_platform.h [5:5]
+ lib/sanitizer_common/sanitizer_platform_interceptors.h [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_freebsd.h [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_linux.cpp [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_netbsd.h [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_posix.cpp [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_posix.h [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_solaris.cpp [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_solaris.h [5:5]
+ lib/sanitizer_common/sanitizer_posix.cpp [5:5]
+ lib/sanitizer_common/sanitizer_posix.h [5:5]
+ lib/sanitizer_common/sanitizer_posix_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_printf.cpp [5:5]
+ lib/sanitizer_common/sanitizer_procmaps.h [5:5]
+ lib/sanitizer_common/sanitizer_procmaps_bsd.cpp [5:5]
+ lib/sanitizer_common/sanitizer_procmaps_common.cpp [5:5]
+ lib/sanitizer_common/sanitizer_procmaps_fuchsia.cpp [6:6]
+ lib/sanitizer_common/sanitizer_procmaps_linux.cpp [5:5]
+ lib/sanitizer_common/sanitizer_procmaps_mac.cpp [5:5]
+ lib/sanitizer_common/sanitizer_procmaps_solaris.cpp [5:5]
+ lib/sanitizer_common/sanitizer_ptrauth.h [5:5]
+ lib/sanitizer_common/sanitizer_quarantine.h [5:5]
+ lib/sanitizer_common/sanitizer_report_decorator.h [5:5]
+ lib/sanitizer_common/sanitizer_ring_buffer.h [5:5]
+ lib/sanitizer_common/sanitizer_signal_interceptors.inc [5:5]
+ lib/sanitizer_common/sanitizer_solaris.cpp [5:5]
+ lib/sanitizer_common/sanitizer_solaris.h [5:5]
+ lib/sanitizer_common/sanitizer_stack_store.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stack_store.h [5:5]
+ lib/sanitizer_common/sanitizer_stackdepot.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stackdepot.h [5:5]
+ lib/sanitizer_common/sanitizer_stackdepotbase.h [5:5]
+ lib/sanitizer_common/sanitizer_stacktrace.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stacktrace.h [5:5]
+ lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stacktrace_printer.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stacktrace_printer.h [5:5]
+ lib/sanitizer_common/sanitizer_stacktrace_sparc.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld.h [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.h [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld_mac.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld_win.cpp [5:5]
+ lib/sanitizer_common/sanitizer_suppressions.cpp [5:5]
+ lib/sanitizer_common/sanitizer_suppressions.h [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer.h [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_fuchsia.h [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_internal.h [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_mac.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_mac.h [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_markup.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_report.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_win.cpp [5:5]
+ lib/sanitizer_common/sanitizer_syscall_generic.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscall_linux_aarch64.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscall_linux_arm.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscall_linux_hexagon.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscall_linux_loongarch64.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscall_linux_riscv64.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscalls_netbsd.inc [5:5]
+ lib/sanitizer_common/sanitizer_termination.cpp [5:5]
+ lib/sanitizer_common/sanitizer_thread_registry.cpp [5:5]
+ lib/sanitizer_common/sanitizer_thread_registry.h [5:5]
+ lib/sanitizer_common/sanitizer_thread_safety.h [5:5]
+ lib/sanitizer_common/sanitizer_tls_get_addr.cpp [5:5]
+ lib/sanitizer_common/sanitizer_tls_get_addr.h [5:5]
+ lib/sanitizer_common/sanitizer_type_traits.cpp [5:5]
+ lib/sanitizer_common/sanitizer_type_traits.h [5:5]
+ lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_unwind_win.cpp [5:5]
+ lib/sanitizer_common/sanitizer_vector.h [5:5]
+ lib/sanitizer_common/sanitizer_win.cpp [5:5]
+ lib/sanitizer_common/sanitizer_win.h [5:5]
+ lib/sanitizer_common/sanitizer_win_defs.h [5:5]
+ lib/sanitizer_common/sanitizer_win_dll_thunk.h [5:5]
+ lib/sanitizer_common/sanitizer_win_weak_interception.h [5:5]
+ lib/scudo/standalone/allocator_config.h [5:5]
+ lib/scudo/standalone/atomic_helpers.h [5:5]
+ lib/scudo/standalone/bytemap.h [5:5]
+ lib/scudo/standalone/checksum.cpp [5:5]
+ lib/scudo/standalone/checksum.h [5:5]
+ lib/scudo/standalone/chunk.h [5:5]
+ lib/scudo/standalone/combined.h [5:5]
+ lib/scudo/standalone/common.cpp [5:5]
+ lib/scudo/standalone/common.h [5:5]
+ lib/scudo/standalone/crc32_hw.cpp [5:5]
+ lib/scudo/standalone/flags.cpp [5:5]
+ lib/scudo/standalone/flags.h [5:5]
+ lib/scudo/standalone/flags.inc [5:5]
+ lib/scudo/standalone/flags_parser.cpp [5:5]
+ lib/scudo/standalone/flags_parser.h [5:5]
+ lib/scudo/standalone/fuchsia.cpp [5:5]
+ lib/scudo/standalone/fuchsia.h [5:5]
+ lib/scudo/standalone/include/scudo/interface.h [5:5]
+ lib/scudo/standalone/internal_defs.h [5:5]
+ lib/scudo/standalone/linux.cpp [5:5]
+ lib/scudo/standalone/linux.h [5:5]
+ lib/scudo/standalone/list.h [5:5]
+ lib/scudo/standalone/local_cache.h [5:5]
+ lib/scudo/standalone/memtag.h [5:5]
+ lib/scudo/standalone/mutex.h [5:5]
+ lib/scudo/standalone/options.h [5:5]
+ lib/scudo/standalone/platform.h [5:5]
+ lib/scudo/standalone/primary32.h [5:5]
+ lib/scudo/standalone/primary64.h [5:5]
+ lib/scudo/standalone/quarantine.h [5:5]
+ lib/scudo/standalone/release.cpp [5:5]
+ lib/scudo/standalone/release.h [5:5]
+ lib/scudo/standalone/report.cpp [5:5]
+ lib/scudo/standalone/report.h [5:5]
+ lib/scudo/standalone/rss_limit_checker.cpp [5:5]
+ lib/scudo/standalone/rss_limit_checker.h [5:5]
+ lib/scudo/standalone/secondary.h [5:5]
+ lib/scudo/standalone/size_class_map.h [5:5]
+ lib/scudo/standalone/stack_depot.h [5:5]
+ lib/scudo/standalone/stats.h [5:5]
+ lib/scudo/standalone/string_utils.cpp [5:5]
+ lib/scudo/standalone/string_utils.h [5:5]
+ lib/scudo/standalone/trusty.h [5:5]
+ lib/scudo/standalone/tsd.h [5:5]
+ lib/scudo/standalone/tsd_exclusive.h [5:5]
+ lib/scudo/standalone/tsd_shared.h [5:5]
+ lib/scudo/standalone/vector.h [5:5]
+ lib/scudo/standalone/wrappers_c.cpp [5:5]
+ lib/scudo/standalone/wrappers_c.h [5:5]
+ lib/scudo/standalone/wrappers_c.inc [5:5]
+ lib/scudo/standalone/wrappers_c_checks.h [5:5]
+ lib/scudo/standalone/wrappers_cpp.cpp [5:5]
+ lib/stats/stats.cpp [5:5]
+ lib/stats/stats.h [5:5]
+ lib/stats/stats_client.cpp [5:5]
+ lib/tsan/dd/dd_interceptors.cpp [5:5]
+ lib/tsan/dd/dd_rtl.cpp [5:5]
+ lib/tsan/dd/dd_rtl.h [5:5]
+ lib/tsan/rtl/tsan_debugging.cpp [5:5]
+ lib/tsan/rtl/tsan_defs.h [5:5]
+ lib/tsan/rtl/tsan_dense_alloc.h [5:5]
+ lib/tsan/rtl/tsan_external.cpp [5:5]
+ lib/tsan/rtl/tsan_fd.cpp [5:5]
+ lib/tsan/rtl/tsan_fd.h [5:5]
+ lib/tsan/rtl/tsan_flags.cpp [5:5]
+ lib/tsan/rtl/tsan_flags.h [5:5]
+ lib/tsan/rtl/tsan_flags.inc [5:5]
+ lib/tsan/rtl/tsan_ignoreset.cpp [5:5]
+ lib/tsan/rtl/tsan_ignoreset.h [5:5]
+ lib/tsan/rtl/tsan_ilist.h [5:5]
+ lib/tsan/rtl/tsan_interceptors_libdispatch.cpp [5:5]
+ lib/tsan/rtl/tsan_interceptors_mac.cpp [5:5]
+ lib/tsan/rtl/tsan_interceptors_mach_vm.cpp [5:5]
+ lib/tsan/rtl/tsan_interceptors_posix.cpp [5:5]
+ lib/tsan/rtl/tsan_interface.cpp [5:5]
+ lib/tsan/rtl/tsan_interface.h [5:5]
+ lib/tsan/rtl/tsan_interface.inc [5:5]
+ lib/tsan/rtl/tsan_interface_ann.cpp [5:5]
+ lib/tsan/rtl/tsan_interface_ann.h [5:5]
+ lib/tsan/rtl/tsan_interface_atomic.cpp [5:5]
+ lib/tsan/rtl/tsan_interface_java.cpp [5:5]
+ lib/tsan/rtl/tsan_interface_java.h [5:5]
+ lib/tsan/rtl/tsan_malloc_mac.cpp [5:5]
+ lib/tsan/rtl/tsan_md5.cpp [5:5]
+ lib/tsan/rtl/tsan_mman.cpp [5:5]
+ lib/tsan/rtl/tsan_mman.h [5:5]
+ lib/tsan/rtl/tsan_mutexset.cpp [5:5]
+ lib/tsan/rtl/tsan_mutexset.h [5:5]
+ lib/tsan/rtl/tsan_new_delete.cpp [5:5]
+ lib/tsan/rtl/tsan_platform.h [5:5]
+ lib/tsan/rtl/tsan_platform_linux.cpp [5:5]
+ lib/tsan/rtl/tsan_platform_mac.cpp [5:5]
+ lib/tsan/rtl/tsan_platform_posix.cpp [5:5]
+ lib/tsan/rtl/tsan_platform_windows.cpp [5:5]
+ lib/tsan/rtl/tsan_preinit.cpp [5:5]
+ lib/tsan/rtl/tsan_report.cpp [5:5]
+ lib/tsan/rtl/tsan_report.h [5:5]
+ lib/tsan/rtl/tsan_rtl.cpp [5:5]
+ lib/tsan/rtl/tsan_rtl.h [5:5]
+ lib/tsan/rtl/tsan_rtl_access.cpp [5:5]
+ lib/tsan/rtl/tsan_rtl_mutex.cpp [5:5]
+ lib/tsan/rtl/tsan_rtl_proc.cpp [5:5]
+ lib/tsan/rtl/tsan_rtl_report.cpp [5:5]
+ lib/tsan/rtl/tsan_rtl_thread.cpp [5:5]
+ lib/tsan/rtl/tsan_shadow.h [5:5]
+ lib/tsan/rtl/tsan_stack_trace.cpp [5:5]
+ lib/tsan/rtl/tsan_stack_trace.h [5:5]
+ lib/tsan/rtl/tsan_suppressions.cpp [5:5]
+ lib/tsan/rtl/tsan_suppressions.h [5:5]
+ lib/tsan/rtl/tsan_symbolize.cpp [5:5]
+ lib/tsan/rtl/tsan_symbolize.h [5:5]
+ lib/tsan/rtl/tsan_sync.cpp [5:5]
+ lib/tsan/rtl/tsan_sync.h [5:5]
+ lib/tsan/rtl/tsan_trace.h [5:5]
+ lib/tsan/rtl/tsan_vector_clock.cpp [5:5]
+ lib/tsan/rtl/tsan_vector_clock.h [5:5]
+ lib/ubsan/ubsan_checks.inc [5:5]
+ lib/ubsan/ubsan_diag.cpp [5:5]
+ lib/ubsan/ubsan_diag.h [5:5]
+ lib/ubsan/ubsan_diag_standalone.cpp [5:5]
+ lib/ubsan/ubsan_flags.cpp [5:5]
+ lib/ubsan/ubsan_flags.h [5:5]
+ lib/ubsan/ubsan_flags.inc [5:5]
+ lib/ubsan/ubsan_handlers.cpp [5:5]
+ lib/ubsan/ubsan_handlers.h [5:5]
+ lib/ubsan/ubsan_handlers_cxx.cpp [5:5]
+ lib/ubsan/ubsan_handlers_cxx.h [5:5]
+ lib/ubsan/ubsan_init.cpp [5:5]
+ lib/ubsan/ubsan_init.h [5:5]
+ lib/ubsan/ubsan_init_standalone.cpp [5:5]
+ lib/ubsan/ubsan_init_standalone_preinit.cpp [5:5]
+ lib/ubsan/ubsan_monitor.cpp [5:5]
+ lib/ubsan/ubsan_monitor.h [5:5]
+ lib/ubsan/ubsan_platform.h [5:5]
+ lib/ubsan/ubsan_signals_standalone.cpp [5:5]
+ lib/ubsan/ubsan_signals_standalone.h [6:6]
+ lib/ubsan/ubsan_type_hash.cpp [5:5]
+ lib/ubsan/ubsan_type_hash.h [5:5]
+ lib/ubsan/ubsan_type_hash_itanium.cpp [5:5]
+ lib/ubsan/ubsan_type_hash_win.cpp [5:5]
+ lib/ubsan/ubsan_value.cpp [5:5]
+ lib/ubsan/ubsan_value.h [5:5]
+ Scancode info:
+ Original SPDX id: LLVM-exception
+ Score : 100.00
+ Match type : TAG
+ Links : http://llvm.org/foundation/relicensing/LICENSE.txt, https://spdx.org/licenses/LLVM-exception
+ Files with this license:
+ include/sanitizer/allocator_interface.h [5:5]
+ include/sanitizer/asan_interface.h [5:5]
+ include/sanitizer/common_interface_defs.h [5:5]
+ include/sanitizer/coverage_interface.h [5:5]
+ include/sanitizer/dfsan_interface.h [5:5]
+ include/sanitizer/hwasan_interface.h [5:5]
+ include/sanitizer/linux_syscall_hooks.h [5:5]
+ include/sanitizer/lsan_interface.h [5:5]
+ include/sanitizer/memprof_interface.h [5:5]
+ include/sanitizer/msan_interface.h [5:5]
+ include/sanitizer/netbsd_syscall_hooks.h [5:5]
+ include/sanitizer/scudo_interface.h [5:5]
+ include/sanitizer/tsan_interface.h [5:5]
+ include/sanitizer/tsan_interface_atomic.h [5:5]
+ include/sanitizer/ubsan_interface.h [5:5]
+ lib/asan/asan_activation.cpp [5:5]
+ lib/asan/asan_activation.h [5:5]
+ lib/asan/asan_activation_flags.inc [5:5]
+ lib/asan/asan_allocator.cpp [5:5]
+ lib/asan/asan_allocator.h [5:5]
+ lib/asan/asan_debugging.cpp [5:5]
+ lib/asan/asan_descriptions.cpp [5:5]
+ lib/asan/asan_descriptions.h [5:5]
+ lib/asan/asan_errors.cpp [5:5]
+ lib/asan/asan_errors.h [5:5]
+ lib/asan/asan_fake_stack.cpp [5:5]
+ lib/asan/asan_fake_stack.h [5:5]
+ lib/asan/asan_flags.cpp [5:5]
+ lib/asan/asan_flags.h [5:5]
+ lib/asan/asan_flags.inc [5:5]
+ lib/asan/asan_fuchsia.cpp [5:5]
+ lib/asan/asan_globals.cpp [5:5]
+ lib/asan/asan_globals_win.cpp [5:5]
+ lib/asan/asan_init_version.h [5:5]
+ lib/asan/asan_interceptors.cpp [5:5]
+ lib/asan/asan_interceptors.h [5:5]
+ lib/asan/asan_interceptors_memintrinsics.cpp [5:5]
+ lib/asan/asan_interceptors_memintrinsics.h [5:5]
+ lib/asan/asan_interface_internal.h [5:5]
+ lib/asan/asan_internal.h [5:5]
+ lib/asan/asan_linux.cpp [5:5]
+ lib/asan/asan_mac.cpp [5:5]
+ lib/asan/asan_malloc_linux.cpp [5:5]
+ lib/asan/asan_malloc_mac.cpp [5:5]
+ lib/asan/asan_malloc_win.cpp [5:5]
+ lib/asan/asan_mapping.h [5:5]
+ lib/asan/asan_mapping_sparc64.h [5:5]
+ lib/asan/asan_memory_profile.cpp [5:5]
+ lib/asan/asan_new_delete.cpp [5:5]
+ lib/asan/asan_poisoning.cpp [5:5]
+ lib/asan/asan_poisoning.h [5:5]
+ lib/asan/asan_posix.cpp [5:5]
+ lib/asan/asan_preinit.cpp [5:5]
+ lib/asan/asan_premap_shadow.cpp [5:5]
+ lib/asan/asan_premap_shadow.h [5:5]
+ lib/asan/asan_report.cpp [5:5]
+ lib/asan/asan_report.h [5:5]
+ lib/asan/asan_rtl.cpp [5:5]
+ lib/asan/asan_rtl_static.cpp [5:5]
+ lib/asan/asan_scariness_score.h [5:5]
+ lib/asan/asan_shadow_setup.cpp [5:5]
+ lib/asan/asan_stack.cpp [5:5]
+ lib/asan/asan_stack.h [5:5]
+ lib/asan/asan_stats.cpp [5:5]
+ lib/asan/asan_stats.h [5:5]
+ lib/asan/asan_suppressions.cpp [5:5]
+ lib/asan/asan_suppressions.h [5:5]
+ lib/asan/asan_thread.cpp [5:5]
+ lib/asan/asan_thread.h [5:5]
+ lib/asan/asan_win.cpp [6:6]
+ lib/builtins/assembly.h [5:5]
+ lib/cfi/cfi.cpp [5:5]
+ lib/dfsan/dfsan.cpp [5:5]
+ lib/dfsan/dfsan.h [5:5]
+ lib/dfsan/dfsan_allocator.cpp [5:5]
+ lib/dfsan/dfsan_allocator.h [5:5]
+ lib/dfsan/dfsan_chained_origin_depot.cpp [5:5]
+ lib/dfsan/dfsan_chained_origin_depot.h [5:5]
+ lib/dfsan/dfsan_custom.cpp [5:5]
+ lib/dfsan/dfsan_flags.h [5:5]
+ lib/dfsan/dfsan_flags.inc [5:5]
+ lib/dfsan/dfsan_interceptors.cpp [5:5]
+ lib/dfsan/dfsan_new_delete.cpp [5:5]
+ lib/dfsan/dfsan_origin.h [5:5]
+ lib/dfsan/dfsan_platform.h [5:5]
+ lib/dfsan/dfsan_thread.h [5:5]
+ lib/gwp_asan/common.cpp [5:5]
+ lib/gwp_asan/common.h [5:5]
+ lib/gwp_asan/crash_handler.cpp [5:5]
+ lib/gwp_asan/crash_handler.h [5:5]
+ lib/gwp_asan/definitions.h [5:5]
+ lib/gwp_asan/guarded_pool_allocator.cpp [5:5]
+ lib/gwp_asan/guarded_pool_allocator.h [5:5]
+ lib/gwp_asan/mutex.h [5:5]
+ lib/gwp_asan/optional/backtrace.h [5:5]
+ lib/gwp_asan/optional/backtrace_linux_libc.cpp [5:5]
+ lib/gwp_asan/optional/options_parser.cpp [5:5]
+ lib/gwp_asan/optional/options_parser.h [5:5]
+ lib/gwp_asan/optional/printf.h [5:5]
+ lib/gwp_asan/optional/segv_handler.h [5:5]
+ lib/gwp_asan/optional/segv_handler_posix.cpp [5:5]
+ lib/gwp_asan/options.h [5:5]
+ lib/gwp_asan/options.inc [5:5]
+ lib/gwp_asan/platform_specific/common_posix.cpp [5:5]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.h [5:5]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp [5:5]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.h [5:5]
+ lib/gwp_asan/platform_specific/guarded_pool_allocator_tls.h [5:5]
+ lib/gwp_asan/platform_specific/mutex_fuchsia.h [5:5]
+ lib/gwp_asan/platform_specific/mutex_posix.cpp [5:5]
+ lib/gwp_asan/platform_specific/mutex_posix.h [5:5]
+ lib/gwp_asan/platform_specific/utilities_posix.cpp [5:5]
+ lib/gwp_asan/stack_trace_compressor.cpp [5:5]
+ lib/gwp_asan/stack_trace_compressor.h [5:5]
+ lib/gwp_asan/utilities.h [5:5]
+ lib/hwasan/hwasan.cpp [5:5]
+ lib/hwasan/hwasan.h [5:5]
+ lib/hwasan/hwasan_allocation_functions.cpp [5:5]
+ lib/hwasan/hwasan_allocator.cpp [5:5]
+ lib/hwasan/hwasan_allocator.h [5:5]
+ lib/hwasan/hwasan_checks.h [5:5]
+ lib/hwasan/hwasan_dynamic_shadow.cpp [5:5]
+ lib/hwasan/hwasan_dynamic_shadow.h [5:5]
+ lib/hwasan/hwasan_exceptions.cpp [5:5]
+ lib/hwasan/hwasan_flags.h [5:5]
+ lib/hwasan/hwasan_flags.inc [5:5]
+ lib/hwasan/hwasan_fuchsia.cpp [5:5]
+ lib/hwasan/hwasan_globals.cpp [5:5]
+ lib/hwasan/hwasan_globals.h [5:5]
+ lib/hwasan/hwasan_interceptors.cpp [5:5]
+ lib/hwasan/hwasan_interface_internal.h [5:5]
+ lib/hwasan/hwasan_linux.cpp [5:5]
+ lib/hwasan/hwasan_malloc_bisect.h [5:5]
+ lib/hwasan/hwasan_mapping.h [5:5]
+ lib/hwasan/hwasan_memintrinsics.cpp [5:5]
+ lib/hwasan/hwasan_new_delete.cpp [5:5]
+ lib/hwasan/hwasan_poisoning.cpp [5:5]
+ lib/hwasan/hwasan_poisoning.h [5:5]
+ lib/hwasan/hwasan_preinit.cpp [5:5]
+ lib/hwasan/hwasan_report.cpp [5:5]
+ lib/hwasan/hwasan_report.h [5:5]
+ lib/hwasan/hwasan_setjmp_aarch64.S [5:5]
+ lib/hwasan/hwasan_setjmp_riscv64.S [5:5]
+ lib/hwasan/hwasan_setjmp_x86_64.S [5:5]
+ lib/hwasan/hwasan_thread.h [5:5]
+ lib/hwasan/hwasan_thread_list.h [5:5]
+ lib/hwasan/hwasan_type_test.cpp [5:5]
+ lib/interception/interception.h [5:5]
+ lib/interception/interception_linux.cpp [5:5]
+ lib/interception/interception_linux.h [5:5]
+ lib/interception/interception_mac.cpp [5:5]
+ lib/interception/interception_mac.h [5:5]
+ lib/interception/interception_type_test.cpp [5:5]
+ lib/interception/interception_win.cpp [5:5]
+ lib/interception/interception_win.h [5:5]
+ lib/lsan/lsan.cpp [5:5]
+ lib/lsan/lsan.h [5:5]
+ lib/lsan/lsan_allocator.cpp [5:5]
+ lib/lsan/lsan_allocator.h [5:5]
+ lib/lsan/lsan_common.cpp [5:5]
+ lib/lsan/lsan_common.h [5:5]
+ lib/lsan/lsan_common_fuchsia.cpp [5:5]
+ lib/lsan/lsan_common_linux.cpp [5:5]
+ lib/lsan/lsan_common_mac.cpp [5:5]
+ lib/lsan/lsan_flags.inc [5:5]
+ lib/lsan/lsan_fuchsia.cpp [5:5]
+ lib/lsan/lsan_fuchsia.h [5:5]
+ lib/lsan/lsan_interceptors.cpp [5:5]
+ lib/lsan/lsan_linux.cpp [5:5]
+ lib/lsan/lsan_mac.cpp [5:5]
+ lib/lsan/lsan_malloc_mac.cpp [5:5]
+ lib/lsan/lsan_posix.cpp [5:5]
+ lib/lsan/lsan_posix.h [5:5]
+ lib/lsan/lsan_preinit.cpp [5:5]
+ lib/lsan/lsan_thread.cpp [5:5]
+ lib/lsan/lsan_thread.h [5:5]
+ lib/memprof/memprof_allocator.cpp [5:5]
+ lib/memprof/memprof_allocator.h [5:5]
+ lib/memprof/memprof_descriptions.cpp [5:5]
+ lib/memprof/memprof_descriptions.h [5:5]
+ lib/memprof/memprof_flags.cpp [5:5]
+ lib/memprof/memprof_flags.h [5:5]
+ lib/memprof/memprof_flags.inc [5:5]
+ lib/memprof/memprof_init_version.h [5:5]
+ lib/memprof/memprof_interceptors.cpp [5:5]
+ lib/memprof/memprof_interceptors.h [5:5]
+ lib/memprof/memprof_interceptors_memintrinsics.cpp [5:5]
+ lib/memprof/memprof_interceptors_memintrinsics.h [5:5]
+ lib/memprof/memprof_interface_internal.h [5:5]
+ lib/memprof/memprof_internal.h [5:5]
+ lib/memprof/memprof_linux.cpp [5:5]
+ lib/memprof/memprof_malloc_linux.cpp [5:5]
+ lib/memprof/memprof_mapping.h [5:5]
+ lib/memprof/memprof_mibmap.cpp [5:5]
+ lib/memprof/memprof_new_delete.cpp [5:5]
+ lib/memprof/memprof_posix.cpp [5:5]
+ lib/memprof/memprof_preinit.cpp [5:5]
+ lib/memprof/memprof_rtl.cpp [5:5]
+ lib/memprof/memprof_shadow_setup.cpp [5:5]
+ lib/memprof/memprof_stack.cpp [5:5]
+ lib/memprof/memprof_stack.h [5:5]
+ lib/memprof/memprof_stats.cpp [5:5]
+ lib/memprof/memprof_stats.h [5:5]
+ lib/memprof/memprof_thread.cpp [5:5]
+ lib/memprof/memprof_thread.h [5:5]
+ lib/msan/msan.cpp [5:5]
+ lib/msan/msan.h [5:5]
+ lib/msan/msan_allocator.cpp [5:5]
+ lib/msan/msan_allocator.h [5:5]
+ lib/msan/msan_chained_origin_depot.cpp [5:5]
+ lib/msan/msan_chained_origin_depot.h [5:5]
+ lib/msan/msan_flags.h [5:5]
+ lib/msan/msan_flags.inc [5:5]
+ lib/msan/msan_interceptors.cpp [5:5]
+ lib/msan/msan_interface_internal.h [5:5]
+ lib/msan/msan_linux.cpp [5:5]
+ lib/msan/msan_new_delete.cpp [5:5]
+ lib/msan/msan_origin.h [5:5]
+ lib/msan/msan_poisoning.cpp [5:5]
+ lib/msan/msan_poisoning.h [5:5]
+ lib/msan/msan_report.cpp [5:5]
+ lib/msan/msan_report.h [5:5]
+ lib/msan/msan_thread.h [5:5]
+ lib/profile/InstrProfilingRuntime.cpp [5:5]
+ lib/safestack/safestack.cpp [5:5]
+ lib/safestack/safestack_platform.h [5:5]
+ lib/safestack/safestack_util.h [5:5]
+ lib/sanitizer_common/sancov_flags.cpp [5:5]
+ lib/sanitizer_common/sancov_flags.h [5:5]
+ lib/sanitizer_common/sancov_flags.inc [5:5]
+ lib/sanitizer_common/sanitizer_addrhashmap.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator.cpp [5:5]
+ lib/sanitizer_common/sanitizer_allocator.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_checks.cpp [5:5]
+ lib/sanitizer_common/sanitizer_allocator_checks.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_combined.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_dlsym.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_interface.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_internal.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_local_cache.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_primary32.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_primary64.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_report.cpp [5:5]
+ lib/sanitizer_common/sanitizer_allocator_report.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_secondary.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_size_class_map.h [5:5]
+ lib/sanitizer_common/sanitizer_allocator_stats.h [5:5]
+ lib/sanitizer_common/sanitizer_asm.h [5:5]
+ lib/sanitizer_common/sanitizer_atomic.h [5:5]
+ lib/sanitizer_common/sanitizer_atomic_clang.h [5:5]
+ lib/sanitizer_common/sanitizer_atomic_clang_mips.h [5:5]
+ lib/sanitizer_common/sanitizer_atomic_clang_other.h [5:5]
+ lib/sanitizer_common/sanitizer_atomic_clang_x86.h [5:5]
+ lib/sanitizer_common/sanitizer_atomic_msvc.h [5:5]
+ lib/sanitizer_common/sanitizer_bitvector.h [5:5]
+ lib/sanitizer_common/sanitizer_bvgraph.h [5:5]
+ lib/sanitizer_common/sanitizer_chained_origin_depot.cpp [5:5]
+ lib/sanitizer_common/sanitizer_chained_origin_depot.h [5:5]
+ lib/sanitizer_common/sanitizer_common.cpp [5:5]
+ lib/sanitizer_common/sanitizer_common.h [5:5]
+ lib/sanitizer_common/sanitizer_common_interceptors.inc [5:5]
+ lib/sanitizer_common/sanitizer_common_interceptors_format.inc [5:5]
+ lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc [5:5]
+ lib/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc [5:5]
+ lib/sanitizer_common/sanitizer_common_interface.inc [5:5]
+ lib/sanitizer_common/sanitizer_common_interface_posix.inc [5:5]
+ lib/sanitizer_common/sanitizer_common_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_common_syscalls.inc [5:5]
+ lib/sanitizer_common/sanitizer_coverage_fuchsia.cpp [5:5]
+ lib/sanitizer_common/sanitizer_coverage_interface.inc [5:5]
+ lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp [5:5]
+ lib/sanitizer_common/sanitizer_coverage_win_sections.cpp [5:5]
+ lib/sanitizer_common/sanitizer_dbghelp.h [5:5]
+ lib/sanitizer_common/sanitizer_deadlock_detector.h [5:5]
+ lib/sanitizer_common/sanitizer_deadlock_detector1.cpp [5:5]
+ lib/sanitizer_common/sanitizer_deadlock_detector2.cpp [5:5]
+ lib/sanitizer_common/sanitizer_deadlock_detector_interface.h [5:5]
+ lib/sanitizer_common/sanitizer_dense_map.h [5:5]
+ lib/sanitizer_common/sanitizer_dense_map_info.h [5:5]
+ lib/sanitizer_common/sanitizer_errno.cpp [5:5]
+ lib/sanitizer_common/sanitizer_errno.h [5:5]
+ lib/sanitizer_common/sanitizer_errno_codes.h [5:5]
+ lib/sanitizer_common/sanitizer_file.cpp [5:5]
+ lib/sanitizer_common/sanitizer_file.h [5:5]
+ lib/sanitizer_common/sanitizer_flag_parser.cpp [5:5]
+ lib/sanitizer_common/sanitizer_flag_parser.h [5:5]
+ lib/sanitizer_common/sanitizer_flags.cpp [5:5]
+ lib/sanitizer_common/sanitizer_flags.h [5:5]
+ lib/sanitizer_common/sanitizer_flags.inc [5:5]
+ lib/sanitizer_common/sanitizer_flat_map.h [5:5]
+ lib/sanitizer_common/sanitizer_freebsd.h [5:5]
+ lib/sanitizer_common/sanitizer_fuchsia.cpp [5:5]
+ lib/sanitizer_common/sanitizer_fuchsia.h [5:5]
+ lib/sanitizer_common/sanitizer_getauxval.h [5:5]
+ lib/sanitizer_common/sanitizer_glibc_version.h [5:5]
+ lib/sanitizer_common/sanitizer_hash.h [5:5]
+ lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc [5:5]
+ lib/sanitizer_common/sanitizer_interface_internal.h [5:5]
+ lib/sanitizer_common/sanitizer_internal_defs.h [5:5]
+ lib/sanitizer_common/sanitizer_leb128.h [5:5]
+ lib/sanitizer_common/sanitizer_lfstack.h [5:5]
+ lib/sanitizer_common/sanitizer_libc.cpp [5:5]
+ lib/sanitizer_common/sanitizer_libc.h [5:5]
+ lib/sanitizer_common/sanitizer_libignore.cpp [5:5]
+ lib/sanitizer_common/sanitizer_libignore.h [5:5]
+ lib/sanitizer_common/sanitizer_linux.cpp [5:5]
+ lib/sanitizer_common/sanitizer_linux.h [5:5]
+ lib/sanitizer_common/sanitizer_linux_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_linux_s390.cpp [5:5]
+ lib/sanitizer_common/sanitizer_list.h [5:5]
+ lib/sanitizer_common/sanitizer_local_address_space_view.h [5:5]
+ lib/sanitizer_common/sanitizer_lzw.h [5:5]
+ lib/sanitizer_common/sanitizer_mac.cpp [5:5]
+ lib/sanitizer_common/sanitizer_mac.h [5:5]
+ lib/sanitizer_common/sanitizer_mac_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_malloc_mac.inc [5:5]
+ lib/sanitizer_common/sanitizer_mutex.cpp [5:5]
+ lib/sanitizer_common/sanitizer_mutex.h [5:5]
+ lib/sanitizer_common/sanitizer_netbsd.cpp [5:5]
+ lib/sanitizer_common/sanitizer_placement_new.h [5:5]
+ lib/sanitizer_common/sanitizer_platform.h [5:5]
+ lib/sanitizer_common/sanitizer_platform_interceptors.h [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_freebsd.h [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_linux.cpp [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_netbsd.h [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_posix.cpp [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_posix.h [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_solaris.cpp [5:5]
+ lib/sanitizer_common/sanitizer_platform_limits_solaris.h [5:5]
+ lib/sanitizer_common/sanitizer_posix.cpp [5:5]
+ lib/sanitizer_common/sanitizer_posix.h [5:5]
+ lib/sanitizer_common/sanitizer_posix_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_printf.cpp [5:5]
+ lib/sanitizer_common/sanitizer_procmaps.h [5:5]
+ lib/sanitizer_common/sanitizer_procmaps_bsd.cpp [5:5]
+ lib/sanitizer_common/sanitizer_procmaps_common.cpp [5:5]
+ lib/sanitizer_common/sanitizer_procmaps_fuchsia.cpp [6:6]
+ lib/sanitizer_common/sanitizer_procmaps_linux.cpp [5:5]
+ lib/sanitizer_common/sanitizer_procmaps_mac.cpp [5:5]
+ lib/sanitizer_common/sanitizer_procmaps_solaris.cpp [5:5]
+ lib/sanitizer_common/sanitizer_ptrauth.h [5:5]
+ lib/sanitizer_common/sanitizer_quarantine.h [5:5]
+ lib/sanitizer_common/sanitizer_report_decorator.h [5:5]
+ lib/sanitizer_common/sanitizer_ring_buffer.h [5:5]
+ lib/sanitizer_common/sanitizer_signal_interceptors.inc [5:5]
+ lib/sanitizer_common/sanitizer_solaris.cpp [5:5]
+ lib/sanitizer_common/sanitizer_solaris.h [5:5]
+ lib/sanitizer_common/sanitizer_stack_store.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stack_store.h [5:5]
+ lib/sanitizer_common/sanitizer_stackdepot.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stackdepot.h [5:5]
+ lib/sanitizer_common/sanitizer_stackdepotbase.h [5:5]
+ lib/sanitizer_common/sanitizer_stacktrace.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stacktrace.h [5:5]
+ lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stacktrace_printer.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stacktrace_printer.h [5:5]
+ lib/sanitizer_common/sanitizer_stacktrace_sparc.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld.h [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.h [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld_mac.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_stoptheworld_win.cpp [5:5]
+ lib/sanitizer_common/sanitizer_suppressions.cpp [5:5]
+ lib/sanitizer_common/sanitizer_suppressions.h [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer.h [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_fuchsia.h [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_internal.h [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_mac.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_mac.h [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_markup.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_report.cpp [5:5]
+ lib/sanitizer_common/sanitizer_symbolizer_win.cpp [5:5]
+ lib/sanitizer_common/sanitizer_syscall_generic.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscall_linux_aarch64.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscall_linux_arm.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscall_linux_hexagon.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscall_linux_loongarch64.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscall_linux_riscv64.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc [5:5]
+ lib/sanitizer_common/sanitizer_syscalls_netbsd.inc [5:5]
+ lib/sanitizer_common/sanitizer_termination.cpp [5:5]
+ lib/sanitizer_common/sanitizer_thread_registry.cpp [5:5]
+ lib/sanitizer_common/sanitizer_thread_registry.h [5:5]
+ lib/sanitizer_common/sanitizer_thread_safety.h [5:5]
+ lib/sanitizer_common/sanitizer_tls_get_addr.cpp [5:5]
+ lib/sanitizer_common/sanitizer_tls_get_addr.h [5:5]
+ lib/sanitizer_common/sanitizer_type_traits.cpp [5:5]
+ lib/sanitizer_common/sanitizer_type_traits.h [5:5]
+ lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp [5:5]
+ lib/sanitizer_common/sanitizer_unwind_win.cpp [5:5]
+ lib/sanitizer_common/sanitizer_vector.h [5:5]
+ lib/sanitizer_common/sanitizer_win.cpp [5:5]
+ lib/sanitizer_common/sanitizer_win.h [5:5]
+ lib/sanitizer_common/sanitizer_win_defs.h [5:5]
+ lib/sanitizer_common/sanitizer_win_dll_thunk.h [5:5]
+ lib/sanitizer_common/sanitizer_win_weak_interception.h [5:5]
+ lib/scudo/standalone/allocator_config.h [5:5]
+ lib/scudo/standalone/atomic_helpers.h [5:5]
+ lib/scudo/standalone/bytemap.h [5:5]
+ lib/scudo/standalone/checksum.cpp [5:5]
+ lib/scudo/standalone/checksum.h [5:5]
+ lib/scudo/standalone/chunk.h [5:5]
+ lib/scudo/standalone/combined.h [5:5]
+ lib/scudo/standalone/common.cpp [5:5]
+ lib/scudo/standalone/common.h [5:5]
+ lib/scudo/standalone/crc32_hw.cpp [5:5]
+ lib/scudo/standalone/flags.cpp [5:5]
+ lib/scudo/standalone/flags.h [5:5]
+ lib/scudo/standalone/flags.inc [5:5]
+ lib/scudo/standalone/flags_parser.cpp [5:5]
+ lib/scudo/standalone/flags_parser.h [5:5]
+ lib/scudo/standalone/fuchsia.cpp [5:5]
+ lib/scudo/standalone/fuchsia.h [5:5]
+ lib/scudo/standalone/include/scudo/interface.h [5:5]
+ lib/scudo/standalone/internal_defs.h [5:5]
+ lib/scudo/standalone/linux.cpp [5:5]
+ lib/scudo/standalone/linux.h [5:5]
+ lib/scudo/standalone/list.h [5:5]
+ lib/scudo/standalone/local_cache.h [5:5]
+ lib/scudo/standalone/memtag.h [5:5]
+ lib/scudo/standalone/mutex.h [5:5]
+ lib/scudo/standalone/options.h [5:5]
+ lib/scudo/standalone/platform.h [5:5]
+ lib/scudo/standalone/primary32.h [5:5]
+ lib/scudo/standalone/primary64.h [5:5]
+ lib/scudo/standalone/quarantine.h [5:5]
+ lib/scudo/standalone/release.cpp [5:5]
+ lib/scudo/standalone/release.h [5:5]
+ lib/scudo/standalone/report.cpp [5:5]
+ lib/scudo/standalone/report.h [5:5]
+ lib/scudo/standalone/rss_limit_checker.cpp [5:5]
+ lib/scudo/standalone/rss_limit_checker.h [5:5]
+ lib/scudo/standalone/secondary.h [5:5]
+ lib/scudo/standalone/size_class_map.h [5:5]
+ lib/scudo/standalone/stack_depot.h [5:5]
+ lib/scudo/standalone/stats.h [5:5]
+ lib/scudo/standalone/string_utils.cpp [5:5]
+ lib/scudo/standalone/string_utils.h [5:5]
+ lib/scudo/standalone/trusty.h [5:5]
+ lib/scudo/standalone/tsd.h [5:5]
+ lib/scudo/standalone/tsd_exclusive.h [5:5]
+ lib/scudo/standalone/tsd_shared.h [5:5]
+ lib/scudo/standalone/vector.h [5:5]
+ lib/scudo/standalone/wrappers_c.cpp [5:5]
+ lib/scudo/standalone/wrappers_c.h [5:5]
+ lib/scudo/standalone/wrappers_c.inc [5:5]
+ lib/scudo/standalone/wrappers_c_checks.h [5:5]
+ lib/scudo/standalone/wrappers_cpp.cpp [5:5]
+ lib/stats/stats.cpp [5:5]
+ lib/stats/stats.h [5:5]
+ lib/stats/stats_client.cpp [5:5]
+ lib/tsan/dd/dd_interceptors.cpp [5:5]
+ lib/tsan/dd/dd_rtl.cpp [5:5]
+ lib/tsan/dd/dd_rtl.h [5:5]
+ lib/tsan/rtl/tsan_debugging.cpp [5:5]
+ lib/tsan/rtl/tsan_defs.h [5:5]
+ lib/tsan/rtl/tsan_dense_alloc.h [5:5]
+ lib/tsan/rtl/tsan_external.cpp [5:5]
+ lib/tsan/rtl/tsan_fd.cpp [5:5]
+ lib/tsan/rtl/tsan_fd.h [5:5]
+ lib/tsan/rtl/tsan_flags.cpp [5:5]
+ lib/tsan/rtl/tsan_flags.h [5:5]
+ lib/tsan/rtl/tsan_flags.inc [5:5]
+ lib/tsan/rtl/tsan_ignoreset.cpp [5:5]
+ lib/tsan/rtl/tsan_ignoreset.h [5:5]
+ lib/tsan/rtl/tsan_ilist.h [5:5]
+ lib/tsan/rtl/tsan_interceptors_libdispatch.cpp [5:5]
+ lib/tsan/rtl/tsan_interceptors_mac.cpp [5:5]
+ lib/tsan/rtl/tsan_interceptors_mach_vm.cpp [5:5]
+ lib/tsan/rtl/tsan_interceptors_posix.cpp [5:5]
+ lib/tsan/rtl/tsan_interface.cpp [5:5]
+ lib/tsan/rtl/tsan_interface.h [5:5]
+ lib/tsan/rtl/tsan_interface.inc [5:5]
+ lib/tsan/rtl/tsan_interface_ann.cpp [5:5]
+ lib/tsan/rtl/tsan_interface_ann.h [5:5]
+ lib/tsan/rtl/tsan_interface_atomic.cpp [5:5]
+ lib/tsan/rtl/tsan_interface_java.cpp [5:5]
+ lib/tsan/rtl/tsan_interface_java.h [5:5]
+ lib/tsan/rtl/tsan_malloc_mac.cpp [5:5]
+ lib/tsan/rtl/tsan_md5.cpp [5:5]
+ lib/tsan/rtl/tsan_mman.cpp [5:5]
+ lib/tsan/rtl/tsan_mman.h [5:5]
+ lib/tsan/rtl/tsan_mutexset.cpp [5:5]
+ lib/tsan/rtl/tsan_mutexset.h [5:5]
+ lib/tsan/rtl/tsan_new_delete.cpp [5:5]
+ lib/tsan/rtl/tsan_platform.h [5:5]
+ lib/tsan/rtl/tsan_platform_linux.cpp [5:5]
+ lib/tsan/rtl/tsan_platform_mac.cpp [5:5]
+ lib/tsan/rtl/tsan_platform_posix.cpp [5:5]
+ lib/tsan/rtl/tsan_platform_windows.cpp [5:5]
+ lib/tsan/rtl/tsan_preinit.cpp [5:5]
+ lib/tsan/rtl/tsan_report.cpp [5:5]
+ lib/tsan/rtl/tsan_report.h [5:5]
+ lib/tsan/rtl/tsan_rtl.cpp [5:5]
+ lib/tsan/rtl/tsan_rtl.h [5:5]
+ lib/tsan/rtl/tsan_rtl_access.cpp [5:5]
+ lib/tsan/rtl/tsan_rtl_mutex.cpp [5:5]
+ lib/tsan/rtl/tsan_rtl_proc.cpp [5:5]
+ lib/tsan/rtl/tsan_rtl_report.cpp [5:5]
+ lib/tsan/rtl/tsan_rtl_thread.cpp [5:5]
+ lib/tsan/rtl/tsan_shadow.h [5:5]
+ lib/tsan/rtl/tsan_stack_trace.cpp [5:5]
+ lib/tsan/rtl/tsan_stack_trace.h [5:5]
+ lib/tsan/rtl/tsan_suppressions.cpp [5:5]
+ lib/tsan/rtl/tsan_suppressions.h [5:5]
+ lib/tsan/rtl/tsan_symbolize.cpp [5:5]
+ lib/tsan/rtl/tsan_symbolize.h [5:5]
+ lib/tsan/rtl/tsan_sync.cpp [5:5]
+ lib/tsan/rtl/tsan_sync.h [5:5]
+ lib/tsan/rtl/tsan_trace.h [5:5]
+ lib/tsan/rtl/tsan_vector_clock.cpp [5:5]
+ lib/tsan/rtl/tsan_vector_clock.h [5:5]
+ lib/ubsan/ubsan_checks.inc [5:5]
+ lib/ubsan/ubsan_diag.cpp [5:5]
+ lib/ubsan/ubsan_diag.h [5:5]
+ lib/ubsan/ubsan_diag_standalone.cpp [5:5]
+ lib/ubsan/ubsan_flags.cpp [5:5]
+ lib/ubsan/ubsan_flags.h [5:5]
+ lib/ubsan/ubsan_flags.inc [5:5]
+ lib/ubsan/ubsan_handlers.cpp [5:5]
+ lib/ubsan/ubsan_handlers.h [5:5]
+ lib/ubsan/ubsan_handlers_cxx.cpp [5:5]
+ lib/ubsan/ubsan_handlers_cxx.h [5:5]
+ lib/ubsan/ubsan_init.cpp [5:5]
+ lib/ubsan/ubsan_init.h [5:5]
+ lib/ubsan/ubsan_init_standalone.cpp [5:5]
+ lib/ubsan/ubsan_init_standalone_preinit.cpp [5:5]
+ lib/ubsan/ubsan_monitor.cpp [5:5]
+ lib/ubsan/ubsan_monitor.h [5:5]
+ lib/ubsan/ubsan_platform.h [5:5]
+ lib/ubsan/ubsan_signals_standalone.cpp [5:5]
+ lib/ubsan/ubsan_signals_standalone.h [6:6]
+ lib/ubsan/ubsan_type_hash.cpp [5:5]
+ lib/ubsan/ubsan_type_hash.h [5:5]
+ lib/ubsan/ubsan_type_hash_itanium.cpp [5:5]
+ lib/ubsan/ubsan_type_hash_win.cpp [5:5]
+ lib/ubsan/ubsan_value.cpp [5:5]
+ lib/ubsan/ubsan_value.h [5:5]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/memprof-preinit/ya.make lib/memprof_cxx/ya.make lib/msan_cxx/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats_client/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP NCSA c26d0b72f92421989c4471ae0acbc943
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ License text:
+ University of Illinois/NCSA
+ Open Source License
+ Scancode info:
+ Original SPDX id: NCSA
+ Score : 100.00
+ Match type : REFERENCE
+ Links : http://www.otm.illinois.edu/faculty/forms/opensource.asp, https://spdx.org/licenses/NCSA
+ Files with this license:
+ LICENSE.TXT [249:250]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+
+KEEP Apache-2.0 WITH LLVM-exception df18889e552d44a4679aff552267f802
+BELONGS lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
+ License text:
+ The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+ Scancode info:
+ Original SPDX id: Apache-2.0
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0
+ Files with this license:
+ LICENSE.TXT [2:2]
+ Scancode info:
+ Original SPDX id: LLVM-exception
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://llvm.org/foundation/relicensing/LICENSE.txt, https://spdx.org/licenses/LLVM-exception
+ Files with this license:
+ LICENSE.TXT [2:2]
+ Belongs difference:
+ + lib/asan-preinit/ya.make lib/asan/ya.make lib/asan_cxx/ya.make lib/asan_static/ya.make lib/cfi/ya.make lib/cfi_diag/ya.make lib/dd/ya.make lib/dfsan/ya.make lib/gwp_asan/ya.make lib/hwasan/ya.make lib/hwasan_aliases/ya.make lib/hwasan_aliases_cxx/ya.make lib/hwasan_cxx/ya.make lib/lsan/ya.make lib/memprof-preinit/ya.make lib/memprof/ya.make lib/memprof_cxx/ya.make lib/msan/ya.make lib/msan_cxx/ya.make lib/profile/ya.make lib/safestack/ya.make lib/scudo_standalone/ya.make lib/scudo_standalone_cxx/ya.make lib/stats/ya.make lib/stats_client/ya.make lib/tsan/ya.make lib/tsan_cxx/ya.make lib/ubsan_minimal/ya.make lib/ubsan_standalone/ya.make lib/ubsan_standalone_cxx/ya.make
diff --git a/contrib/libs/clang16-rt/CODE_OWNERS.TXT b/contrib/libs/clang16-rt/CODE_OWNERS.TXT
new file mode 100644
index 00000000000..80f7a93efc3
--- /dev/null
+++ b/contrib/libs/clang16-rt/CODE_OWNERS.TXT
@@ -0,0 +1,61 @@
+This file is a list of the people responsible for ensuring that patches for a
+particular part of compiler-rt are reviewed, either by themself or by
+someone else. They are also the gatekeepers for their part of compiler-rt, with
+the final word on what goes in or not.
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Saleem Abdulrasool
+E: compnerd@compnerd.org
+D: builtins library
+
+N: Vitaly Buka
+E: vitalybuka@google.com
+D: Sanitizers
+
+N: Peter Collingbourne
+E: peter@pcc.me.uk
+D: CFI, SafeStack
+
+N: Lang Hames
+E: lhames@gmail.com
+D: ORC
+
+N: Petr Hosek
+E: phosek@google.com
+D: CRT, CMake build
+
+N: Teresa Johnson
+E: tejohnson@google.com
+D: MemProf
+
+N: Mitch Phillips
+E: mitchp@google.com
+D: GWP ASAN
+
+N: Alexander Potapenko
+E: glider@google.com
+D: Sanitizers
+
+N: Kostya Serebryany
+E: kcc@google.com
+D: AddressSanitizer, sanitizer_common, LeakSanitizer, LibFuzzer
+
+N: Richard Smith
+E: richard-llvm@metafoo.co.uk
+D: UndefinedBehaviorSanitizer
+
+N: Evgeniy Stepanov
+E: eugenis@google.com
+D: MemorySanitizer, Android port of sanitizers
+
+N: Dmitry Vyukov
+E: dvyukov@google.com
+D: ThreadSanitizer
+
+N: Bill Wendling
+E: isanbard@gmail.com
+D: Profile runtime library
diff --git a/contrib/libs/clang16-rt/CREDITS.TXT b/contrib/libs/clang16-rt/CREDITS.TXT
new file mode 100644
index 00000000000..6964eba020b
--- /dev/null
+++ b/contrib/libs/clang16-rt/CREDITS.TXT
@@ -0,0 +1,36 @@
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
diff --git a/contrib/libs/clang16-rt/LICENSE.TXT b/contrib/libs/clang16-rt/LICENSE.TXT
new file mode 100644
index 00000000000..5a79a1b9d5c
--- /dev/null
+++ b/contrib/libs/clang16-rt/LICENSE.TXT
@@ -0,0 +1,311 @@
+==============================================================================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+==============================================================================
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+==============================================================================
+Software from third parties included in the LLVM Project:
+==============================================================================
+The LLVM Project contains third party software which is under different license
+terms. All such code will be identified clearly using at least one of two
+mechanisms:
+1) It will be in a separate directory tree with its own `LICENSE.txt` or
+ `LICENSE` file at the top containing the specific license and restrictions
+ which apply to that software, or
+2) It will contain specific license and restriction terms at the top of every
+ file.
+
+==============================================================================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+==============================================================================
+
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
+
+==============================================================================
+
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+All rights reserved.
+
+Developed by:
+
+ LLVM Team
+
+ University of Illinois at Urbana-Champaign
+
+ http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/contrib/libs/clang16-rt/README.txt b/contrib/libs/clang16-rt/README.txt
new file mode 100644
index 00000000000..fc8843246e2
--- /dev/null
+++ b/contrib/libs/clang16-rt/README.txt
@@ -0,0 +1,11 @@
+Compiler-RT
+================================
+
+This directory and its subdirectories contain source code for the compiler
+support routines.
+
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+================================
+
diff --git a/contrib/libs/clang16-rt/include/profile/InstrProfData.inc b/contrib/libs/clang16-rt/include/profile/InstrProfData.inc
new file mode 100644
index 00000000000..05419bf01f5
--- /dev/null
+++ b/contrib/libs/clang16-rt/include/profile/InstrProfData.inc
@@ -0,0 +1,907 @@
+/*===-- InstrProfData.inc - instr profiling runtime structures -*- C++ -*-=== *\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+/*
+ * This is the main file that defines all the data structure, signature,
+ * constant literals that are shared across profiling runtime library,
+ * compiler (instrumentation), and host tools (reader/writer). The entities
+ * defined in this file affect the profile runtime ABI, the raw profile format,
+ * or both.
+ *
+ * The file has two identical copies. The primary copy lives in LLVM and
+ * the other one sits in compiler-rt/lib/profile directory. To make changes
+ * in this file, first modify the primary copy and copy it over to compiler-rt.
+ * Testing of any change in this file can start only after the two copies are
+ * synced up.
+ *
+ * The first part of the file includes macros that defines types, names, and
+ * initializers for the member fields of the core data structures. The field
+ * declarations for one structure is enabled by defining the field activation
+ * macro associated with that structure. Only one field activation record
+ * can be defined at one time and the rest definitions will be filtered out by
+ * the preprocessor.
+ *
+ * Examples of how the template is used to instantiate structure definition:
+ * 1. To declare a structure:
+ *
+ * struct ProfData {
+ * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \
+ * Type Name;
+ * #include "llvm/ProfileData/InstrProfData.inc"
+ * };
+ *
+ * 2. To construct LLVM type arrays for the struct type:
+ *
+ * Type *DataTypes[] = {
+ * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \
+ * LLVMType,
+ * #include "llvm/ProfileData/InstrProfData.inc"
+ * };
+ *
+ * 4. To construct constant array for the initializers:
+ * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \
+ * Initializer,
+ * Constant *ConstantVals[] = {
+ * #include "llvm/ProfileData/InstrProfData.inc"
+ * };
+ *
+ *
+ * The second part of the file includes definitions all other entities that
+ * are related to runtime ABI and format. When no field activation macro is
+ * defined, this file can be included to introduce the definitions.
+ *
+\*===----------------------------------------------------------------------===*/
+
+/* Functions marked with INSTR_PROF_VISIBILITY must have hidden visibility in
+ * the compiler runtime. */
+#ifndef INSTR_PROF_VISIBILITY
+#define INSTR_PROF_VISIBILITY
+#endif
+
+/* INSTR_PROF_DATA start. */
+/* Definition of member fields of the per-function control structure. */
+#ifndef INSTR_PROF_DATA
+#define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer)
+#else
+#define INSTR_PROF_DATA_DEFINED
+#endif
+INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \
+ ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \
+ IndexedInstrProf::ComputeHash(getPGOFuncNameVarInitializer(Inc->getName()))))
+INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \
+ ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \
+ Inc->getHash()->getZExtValue()))
+INSTR_PROF_DATA(const IntPtrT, IntPtrTy, CounterPtr, RelativeCounterPtr)
+/* This is used to map function pointers for the indirect call targets to
+ * function name hashes during the conversion from raw to merged profile
+ * data.
+ */
+INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), FunctionPointer, \
+ FunctionAddr)
+INSTR_PROF_DATA(IntPtrT, llvm::Type::getInt8PtrTy(Ctx), Values, \
+ ValuesPtrExpr)
+INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumCounters, \
+ ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumCounters))
+INSTR_PROF_DATA(const uint16_t, Int16ArrayTy, NumValueSites[IPVK_Last+1], \
+ ConstantArray::get(Int16ArrayTy, Int16ArrayVals))
+#undef INSTR_PROF_DATA
+/* INSTR_PROF_DATA end. */
+
+
+/* This is an internal data structure used by value profiler. It
+ * is defined here to allow serialization code sharing by LLVM
+ * to be used in unit test.
+ *
+ * typedef struct ValueProfNode {
+ * // InstrProfValueData VData;
+ * uint64_t Value;
+ * uint64_t Count;
+ * struct ValueProfNode *Next;
+ * } ValueProfNode;
+ */
+/* INSTR_PROF_VALUE_NODE start. */
+#ifndef INSTR_PROF_VALUE_NODE
+#define INSTR_PROF_VALUE_NODE(Type, LLVMType, Name, Initializer)
+#else
+#define INSTR_PROF_DATA_DEFINED
+#endif
+INSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Value, \
+ ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0))
+INSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Count, \
+ ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0))
+INSTR_PROF_VALUE_NODE(PtrToNodeT, llvm::Type::getInt8PtrTy(Ctx), Next, \
+ ConstantInt::get(llvm::Type::GetInt8PtrTy(Ctx), 0))
+#undef INSTR_PROF_VALUE_NODE
+/* INSTR_PROF_VALUE_NODE end. */
+
+/* INSTR_PROF_RAW_HEADER start */
+/* Definition of member fields of the raw profile header data structure. */
+#ifndef INSTR_PROF_RAW_HEADER
+#define INSTR_PROF_RAW_HEADER(Type, Name, Initializer)
+#else
+#define INSTR_PROF_DATA_DEFINED
+#endif
+INSTR_PROF_RAW_HEADER(uint64_t, Magic, __llvm_profile_get_magic())
+INSTR_PROF_RAW_HEADER(uint64_t, Version, __llvm_profile_get_version())
+INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL))
+/* FIXME: A more accurate name is NumData */
+INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize)
+INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesBeforeCounters, PaddingBytesBeforeCounters)
+/* FIXME: A more accurate name is NumCounters */
+INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize)
+INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesAfterCounters, PaddingBytesAfterCounters)
+INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
+INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta,
+ (uintptr_t)CountersBegin - (uintptr_t)DataBegin)
+INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
+INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
+#undef INSTR_PROF_RAW_HEADER
+/* INSTR_PROF_RAW_HEADER end */
+
+/* VALUE_PROF_FUNC_PARAM start */
+/* Definition of parameter types of the runtime API used to do value profiling
+ * for a given value site.
+ */
+#ifndef VALUE_PROF_FUNC_PARAM
+#define VALUE_PROF_FUNC_PARAM(ArgType, ArgName, ArgLLVMType)
+#define INSTR_PROF_COMMA
+#else
+#define INSTR_PROF_DATA_DEFINED
+#define INSTR_PROF_COMMA ,
+#endif
+VALUE_PROF_FUNC_PARAM(uint64_t, TargetValue, Type::getInt64Ty(Ctx)) \
+ INSTR_PROF_COMMA
+VALUE_PROF_FUNC_PARAM(void *, Data, Type::getInt8PtrTy(Ctx)) INSTR_PROF_COMMA
+VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx))
+#undef VALUE_PROF_FUNC_PARAM
+#undef INSTR_PROF_COMMA
+/* VALUE_PROF_FUNC_PARAM end */
+
+/* VALUE_PROF_KIND start */
+#ifndef VALUE_PROF_KIND
+#define VALUE_PROF_KIND(Enumerator, Value, Descr)
+#else
+#define INSTR_PROF_DATA_DEFINED
+#endif
+/* For indirect function call value profiling, the addresses of the target
+ * functions are profiled by the instrumented code. The target addresses are
+ * written in the raw profile data and converted to target function name's MD5
+ * hash by the profile reader during deserialization. Typically, this happens
+ * when the raw profile data is read during profile merging.
+ *
+ * For this remapping the ProfData is used. ProfData contains both the function
+ * name hash and the function address.
+ */
+VALUE_PROF_KIND(IPVK_IndirectCallTarget, 0, "indirect call target")
+/* For memory intrinsic functions size profiling. */
+VALUE_PROF_KIND(IPVK_MemOPSize, 1, "memory intrinsic functions size")
+/* These two kinds must be the last to be
+ * declared. This is to make sure the string
+ * array created with the template can be
+ * indexed with the kind value.
+ */
+VALUE_PROF_KIND(IPVK_First, IPVK_IndirectCallTarget, "first")
+VALUE_PROF_KIND(IPVK_Last, IPVK_MemOPSize, "last")
+
+#undef VALUE_PROF_KIND
+/* VALUE_PROF_KIND end */
+
+#undef COVMAP_V2_OR_V3
+#ifdef COVMAP_V2
+#define COVMAP_V2_OR_V3
+#endif
+#ifdef COVMAP_V3
+#define COVMAP_V2_OR_V3
+#endif
+
+/* COVMAP_FUNC_RECORD start */
+/* Definition of member fields of the function record structure in coverage
+ * map.
+ */
+#ifndef COVMAP_FUNC_RECORD
+#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Initializer)
+#else
+#define INSTR_PROF_DATA_DEFINED
+#endif
+#ifdef COVMAP_V1
+COVMAP_FUNC_RECORD(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), \
+ NamePtr, llvm::ConstantExpr::getBitCast(NamePtr, \
+ llvm::Type::getInt8PtrTy(Ctx)))
+COVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), NameSize, \
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), \
+ NameValue.size()))
+#endif
+#ifdef COVMAP_V2_OR_V3
+COVMAP_FUNC_RECORD(const int64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \
+ llvm::ConstantInt::get( \
+ llvm::Type::getInt64Ty(Ctx), NameHash))
+#endif
+COVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), DataSize, \
+ llvm::ConstantInt::get( \
+ llvm::Type::getInt32Ty(Ctx), CoverageMapping.size()))
+COVMAP_FUNC_RECORD(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \
+ llvm::ConstantInt::get( \
+ llvm::Type::getInt64Ty(Ctx), FuncHash))
+#ifdef COVMAP_V3
+COVMAP_FUNC_RECORD(const uint64_t, llvm::Type::getInt64Ty(Ctx), FilenamesRef, \
+ llvm::ConstantInt::get( \
+ llvm::Type::getInt64Ty(Ctx), FilenamesRef))
+COVMAP_FUNC_RECORD(const char, \
+ llvm::ArrayType::get(llvm::Type::getInt8Ty(Ctx), \
+ CoverageMapping.size()), \
+ CoverageMapping,
+ llvm::ConstantDataArray::getRaw( \
+ CoverageMapping, CoverageMapping.size(), \
+ llvm::Type::getInt8Ty(Ctx)))
+#endif
+#undef COVMAP_FUNC_RECORD
+/* COVMAP_FUNC_RECORD end. */
+
+/* COVMAP_HEADER start */
+/* Definition of member fields of coverage map header.
+ */
+#ifndef COVMAP_HEADER
+#define COVMAP_HEADER(Type, LLVMType, Name, Initializer)
+#else
+#define INSTR_PROF_DATA_DEFINED
+#endif
+COVMAP_HEADER(uint32_t, Int32Ty, NRecords, \
+ llvm::ConstantInt::get(Int32Ty, NRecords))
+COVMAP_HEADER(uint32_t, Int32Ty, FilenamesSize, \
+ llvm::ConstantInt::get(Int32Ty, FilenamesSize))
+COVMAP_HEADER(uint32_t, Int32Ty, CoverageSize, \
+ llvm::ConstantInt::get(Int32Ty, CoverageMappingSize))
+COVMAP_HEADER(uint32_t, Int32Ty, Version, \
+ llvm::ConstantInt::get(Int32Ty, CovMapVersion::CurrentVersion))
+#undef COVMAP_HEADER
+/* COVMAP_HEADER end. */
+
+
+#ifdef INSTR_PROF_SECT_ENTRY
+#define INSTR_PROF_DATA_DEFINED
+INSTR_PROF_SECT_ENTRY(IPSK_data, \
+ INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON), \
+ INSTR_PROF_DATA_COFF, "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_cnts, \
+ INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON), \
+ INSTR_PROF_CNTS_COFF, "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_name, \
+ INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON), \
+ INSTR_PROF_NAME_COFF, "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_vals, \
+ INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON), \
+ INSTR_PROF_VALS_COFF, "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_vnodes, \
+ INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON), \
+ INSTR_PROF_VNODES_COFF, "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_covmap, \
+ INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON), \
+ INSTR_PROF_COVMAP_COFF, "__LLVM_COV,")
+INSTR_PROF_SECT_ENTRY(IPSK_covfun, \
+ INSTR_PROF_QUOTE(INSTR_PROF_COVFUN_COMMON), \
+ INSTR_PROF_COVFUN_COFF, "__LLVM_COV,")
+INSTR_PROF_SECT_ENTRY(IPSK_orderfile, \
+ INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON), \
+ INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COFF), "__DATA,")
+
+#undef INSTR_PROF_SECT_ENTRY
+#endif
+
+
+#ifdef INSTR_PROF_VALUE_PROF_DATA
+#define INSTR_PROF_DATA_DEFINED
+
+#define INSTR_PROF_MAX_NUM_VAL_PER_SITE 255
+/*!
+ * This is the header of the data structure that defines the on-disk
+ * layout of the value profile data of a particular kind for one function.
+ */
+typedef struct ValueProfRecord {
+ /* The kind of the value profile record. */
+ uint32_t Kind;
+ /*
+ * The number of value profile sites. It is guaranteed to be non-zero;
+ * otherwise the record for this kind won't be emitted.
+ */
+ uint32_t NumValueSites;
+ /*
+ * The first element of the array that stores the number of profiled
+ * values for each value site. The size of the array is NumValueSites.
+ * Since NumValueSites is greater than zero, there is at least one
+ * element in the array.
+ */
+ uint8_t SiteCountArray[1];
+
+ /*
+ * The fake declaration is for documentation purpose only.
+ * Align the start of next field to be on 8 byte boundaries.
+ uint8_t Padding[X];
+ */
+
+ /* The array of value profile data. The size of the array is the sum
+ * of all elements in SiteCountArray[].
+ InstrProfValueData ValueData[];
+ */
+
+#ifdef __cplusplus
+ /*!
+ * Return the number of value sites.
+ */
+ uint32_t getNumValueSites() const { return NumValueSites; }
+ /*!
+ * Read data from this record and save it to Record.
+ */
+ void deserializeTo(InstrProfRecord &Record,
+ InstrProfSymtab *SymTab);
+ /*
+ * In-place byte swap:
+ * Do byte swap for this instance. \c Old is the original order before
+ * the swap, and \c New is the New byte order.
+ */
+ void swapBytes(support::endianness Old, support::endianness New);
+#endif
+} ValueProfRecord;
+
+/*!
+ * Per-function header/control data structure for value profiling
+ * data in indexed format.
+ */
+typedef struct ValueProfData {
+ /*
+ * Total size in bytes including this field. It must be a multiple
+ * of sizeof(uint64_t).
+ */
+ uint32_t TotalSize;
+ /*
+ *The number of value profile kinds that has value profile data.
+ * In this implementation, a value profile kind is considered to
+ * have profile data if the number of value profile sites for the
+ * kind is not zero. More aggressively, the implementation can
+ * choose to check the actual data value: if none of the value sites
+ * has any profiled values, the kind can be skipped.
+ */
+ uint32_t NumValueKinds;
+
+ /*
+ * Following are a sequence of variable length records. The prefix/header
+ * of each record is defined by ValueProfRecord type. The number of
+ * records is NumValueKinds.
+ * ValueProfRecord Record_1;
+ * ValueProfRecord Record_N;
+ */
+
+#if __cplusplus
+ /*!
+ * Return the total size in bytes of the on-disk value profile data
+ * given the data stored in Record.
+ */
+ static uint32_t getSize(const InstrProfRecord &Record);
+ /*!
+ * Return a pointer to \c ValueProfData instance ready to be streamed.
+ */
+ static std::unique_ptr<ValueProfData>
+ serializeFrom(const InstrProfRecord &Record);
+ /*!
+ * Check the integrity of the record.
+ */
+ Error checkIntegrity();
+ /*!
+ * Return a pointer to \c ValueProfileData instance ready to be read.
+ * All data in the instance are properly byte swapped. The input
+ * data is assumed to be in little endian order.
+ */
+ static Expected<std::unique_ptr<ValueProfData>>
+ getValueProfData(const unsigned char *SrcBuffer,
+ const unsigned char *const SrcBufferEnd,
+ support::endianness SrcDataEndianness);
+ /*!
+ * Swap byte order from \c Endianness order to host byte order.
+ */
+ void swapBytesToHost(support::endianness Endianness);
+ /*!
+ * Swap byte order from host byte order to \c Endianness order.
+ */
+ void swapBytesFromHost(support::endianness Endianness);
+ /*!
+ * Return the total size of \c ValueProfileData.
+ */
+ uint32_t getSize() const { return TotalSize; }
+ /*!
+ * Read data from this data and save it to \c Record.
+ */
+ void deserializeTo(InstrProfRecord &Record,
+ InstrProfSymtab *SymTab);
+ void operator delete(void *ptr) { ::operator delete(ptr); }
+#endif
+} ValueProfData;
+
+/*
+ * The closure is designed to abstact away two types of value profile data:
+ * - InstrProfRecord which is the primary data structure used to
+ * represent profile data in host tools (reader, writer, and profile-use)
+ * - value profile runtime data structure suitable to be used by C
+ * runtime library.
+ *
+ * Both sources of data need to serialize to disk/memory-buffer in common
+ * format: ValueProfData. The abstraction allows compiler-rt's raw profiler
+ * writer to share the same format and code with indexed profile writer.
+ *
+ * For documentation of the member methods below, refer to corresponding methods
+ * in class InstrProfRecord.
+ */
+typedef struct ValueProfRecordClosure {
+ const void *Record;
+ uint32_t (*GetNumValueKinds)(const void *Record);
+ uint32_t (*GetNumValueSites)(const void *Record, uint32_t VKind);
+ uint32_t (*GetNumValueData)(const void *Record, uint32_t VKind);
+ uint32_t (*GetNumValueDataForSite)(const void *R, uint32_t VK, uint32_t S);
+
+ /*
+ * After extracting the value profile data from the value profile record,
+ * this method is used to map the in-memory value to on-disk value. If
+ * the method is null, value will be written out untranslated.
+ */
+ uint64_t (*RemapValueData)(uint32_t, uint64_t Value);
+ void (*GetValueForSite)(const void *R, InstrProfValueData *Dst, uint32_t K,
+ uint32_t S);
+ ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes);
+} ValueProfRecordClosure;
+
+INSTR_PROF_VISIBILITY ValueProfRecord *
+getFirstValueProfRecord(ValueProfData *VPD);
+INSTR_PROF_VISIBILITY ValueProfRecord *
+getValueProfRecordNext(ValueProfRecord *VPR);
+INSTR_PROF_VISIBILITY InstrProfValueData *
+getValueProfRecordValueData(ValueProfRecord *VPR);
+INSTR_PROF_VISIBILITY uint32_t
+getValueProfRecordHeaderSize(uint32_t NumValueSites);
+
+#undef INSTR_PROF_VALUE_PROF_DATA
+#endif /* INSTR_PROF_VALUE_PROF_DATA */
+
+
+#ifdef INSTR_PROF_COMMON_API_IMPL
+#define INSTR_PROF_DATA_DEFINED
+#ifdef __cplusplus
+#define INSTR_PROF_INLINE inline
+#define INSTR_PROF_NULLPTR nullptr
+#else
+#define INSTR_PROF_INLINE
+#define INSTR_PROF_NULLPTR NULL
+#endif
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+/*!
+ * Return the \c ValueProfRecord header size including the
+ * padding bytes.
+ */
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
+uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites) {
+ uint32_t Size = offsetof(ValueProfRecord, SiteCountArray) +
+ sizeof(uint8_t) * NumValueSites;
+ /* Round the size to multiple of 8 bytes. */
+ Size = (Size + 7) & ~7;
+ return Size;
+}
+
+/*!
+ * Return the total size of the value profile record including the
+ * header and the value data.
+ */
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
+uint32_t getValueProfRecordSize(uint32_t NumValueSites,
+ uint32_t NumValueData) {
+ return getValueProfRecordHeaderSize(NumValueSites) +
+ sizeof(InstrProfValueData) * NumValueData;
+}
+
+/*!
+ * Return the pointer to the start of value data array.
+ */
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
+InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) {
+ return (InstrProfValueData *)((char *)This + getValueProfRecordHeaderSize(
+ This->NumValueSites));
+}
+
+/*!
+ * Return the total number of value data for \c This record.
+ */
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
+uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) {
+ uint32_t NumValueData = 0;
+ uint32_t I;
+ for (I = 0; I < This->NumValueSites; I++)
+ NumValueData += This->SiteCountArray[I];
+ return NumValueData;
+}
+
+/*!
+ * Use this method to advance to the next \c This \c ValueProfRecord.
+ */
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
+ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) {
+ uint32_t NumValueData = getValueProfRecordNumValueData(This);
+ return (ValueProfRecord *)((char *)This +
+ getValueProfRecordSize(This->NumValueSites,
+ NumValueData));
+}
+
+/*!
+ * Return the first \c ValueProfRecord instance.
+ */
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
+ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) {
+ return (ValueProfRecord *)((char *)This + sizeof(ValueProfData));
+}
+
+/* Closure based interfaces. */
+
+/*!
+ * Return the total size in bytes of the on-disk value profile data
+ * given the data stored in Record.
+ */
+INSTR_PROF_VISIBILITY uint32_t
+getValueProfDataSize(ValueProfRecordClosure *Closure) {
+ uint32_t Kind;
+ uint32_t TotalSize = sizeof(ValueProfData);
+ const void *Record = Closure->Record;
+
+ for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
+ uint32_t NumValueSites = Closure->GetNumValueSites(Record, Kind);
+ if (!NumValueSites)
+ continue;
+ TotalSize += getValueProfRecordSize(NumValueSites,
+ Closure->GetNumValueData(Record, Kind));
+ }
+ return TotalSize;
+}
+
+/*!
+ * Extract value profile data of a function for the profile kind \c ValueKind
+ * from the \c Closure and serialize the data into \c This record instance.
+ */
+INSTR_PROF_VISIBILITY void
+serializeValueProfRecordFrom(ValueProfRecord *This,
+ ValueProfRecordClosure *Closure,
+ uint32_t ValueKind, uint32_t NumValueSites) {
+ uint32_t S;
+ const void *Record = Closure->Record;
+ This->Kind = ValueKind;
+ This->NumValueSites = NumValueSites;
+ InstrProfValueData *DstVD = getValueProfRecordValueData(This);
+
+ for (S = 0; S < NumValueSites; S++) {
+ uint32_t ND = Closure->GetNumValueDataForSite(Record, ValueKind, S);
+ This->SiteCountArray[S] = ND;
+ Closure->GetValueForSite(Record, DstVD, ValueKind, S);
+ DstVD += ND;
+ }
+}
+
+/*!
+ * Extract value profile data of a function from the \c Closure
+ * and serialize the data into \c DstData if it is not NULL or heap
+ * memory allocated by the \c Closure's allocator method. If \c
+ * DstData is not null, the caller is expected to set the TotalSize
+ * in DstData.
+ */
+INSTR_PROF_VISIBILITY ValueProfData *
+serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
+ ValueProfData *DstData) {
+ uint32_t Kind;
+ uint32_t TotalSize =
+ DstData ? DstData->TotalSize : getValueProfDataSize(Closure);
+
+ ValueProfData *VPD =
+ DstData ? DstData : Closure->AllocValueProfData(TotalSize);
+
+ VPD->TotalSize = TotalSize;
+ VPD->NumValueKinds = Closure->GetNumValueKinds(Closure->Record);
+ ValueProfRecord *VR = getFirstValueProfRecord(VPD);
+ for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
+ uint32_t NumValueSites = Closure->GetNumValueSites(Closure->Record, Kind);
+ if (!NumValueSites)
+ continue;
+ serializeValueProfRecordFrom(VR, Closure, Kind, NumValueSites);
+ VR = getValueProfRecordNext(VR);
+ }
+ return VPD;
+}
+
+#undef INSTR_PROF_COMMON_API_IMPL
+#endif /* INSTR_PROF_COMMON_API_IMPL */
+
+/*============================================================================*/
+
+#ifndef INSTR_PROF_DATA_DEFINED
+
+#ifndef INSTR_PROF_DATA_INC
+#define INSTR_PROF_DATA_INC
+
+/* Helper macros. */
+#define INSTR_PROF_SIMPLE_QUOTE(x) #x
+#define INSTR_PROF_QUOTE(x) INSTR_PROF_SIMPLE_QUOTE(x)
+#define INSTR_PROF_SIMPLE_CONCAT(x,y) x ## y
+#define INSTR_PROF_CONCAT(x,y) INSTR_PROF_SIMPLE_CONCAT(x,y)
+
+/* Magic number to detect file format and endianness.
+ * Use 255 at one end, since no UTF-8 file can use that character. Avoid 0,
+ * so that utilities, like strings, don't grab it as a string. 129 is also
+ * invalid UTF-8, and high enough to be interesting.
+ * Use "lprofr" in the centre to stand for "LLVM Profile Raw", or "lprofR"
+ * for 32-bit platforms.
+ */
+#define INSTR_PROF_RAW_MAGIC_64 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \
+ (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \
+ (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129
+#define INSTR_PROF_RAW_MAGIC_32 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \
+ (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \
+ (uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129
+
+/* FIXME: Please remedy the fixme in the header before bumping the version. */
+/* Raw profile format version (start from 1). */
+#define INSTR_PROF_RAW_VERSION 8
+/* Indexed profile format version (start from 1). */
+#define INSTR_PROF_INDEX_VERSION 9
+/* Coverage mapping format version (start from 0). */
+#define INSTR_PROF_COVMAP_VERSION 5
+
+/* Profile version is always of type uint64_t. Reserve the upper 8 bits in the
+ * version for other variants of profile. We set the lowest bit of the upper 8
+ * bits (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentation
+ * generated profile, and 0 if this is a Clang FE generated profile.
+ * 1 in bit 57 indicates there are context-sensitive records in the profile.
+ * The 59th bit indicates whether to use debug info to correlate profiles.
+ * The 60th bit indicates single byte coverage instrumentation.
+ * The 61st bit indicates function entry instrumentation only.
+ * The 62nd bit indicates whether memory profile information is present.
+ */
+#define VARIANT_MASKS_ALL 0xff00000000000000ULL
+#define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL)
+#define VARIANT_MASK_IR_PROF (0x1ULL << 56)
+#define VARIANT_MASK_CSIR_PROF (0x1ULL << 57)
+#define VARIANT_MASK_INSTR_ENTRY (0x1ULL << 58)
+#define VARIANT_MASK_DBG_CORRELATE (0x1ULL << 59)
+#define VARIANT_MASK_BYTE_COVERAGE (0x1ULL << 60)
+#define VARIANT_MASK_FUNCTION_ENTRY_ONLY (0x1ULL << 61)
+#define VARIANT_MASK_MEMPROF (0x1ULL << 62)
+#define INSTR_PROF_RAW_VERSION_VAR __llvm_profile_raw_version
+#define INSTR_PROF_PROFILE_RUNTIME_VAR __llvm_profile_runtime
+#define INSTR_PROF_PROFILE_COUNTER_BIAS_VAR __llvm_profile_counter_bias
+
+/* The variable that holds the name of the profile data
+ * specified via command line. */
+#define INSTR_PROF_PROFILE_NAME_VAR __llvm_profile_filename
+
+/* section name strings common to all targets other
+ than WIN32 */
+#define INSTR_PROF_DATA_COMMON __llvm_prf_data
+#define INSTR_PROF_NAME_COMMON __llvm_prf_names
+#define INSTR_PROF_CNTS_COMMON __llvm_prf_cnts
+#define INSTR_PROF_VALS_COMMON __llvm_prf_vals
+#define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds
+#define INSTR_PROF_COVMAP_COMMON __llvm_covmap
+#define INSTR_PROF_COVFUN_COMMON __llvm_covfun
+#define INSTR_PROF_ORDERFILE_COMMON __llvm_orderfile
+/* Windows section names. Because these section names contain dollar characters,
+ * they must be quoted.
+ */
+#define INSTR_PROF_DATA_COFF ".lprfd$M"
+#define INSTR_PROF_NAME_COFF ".lprfn$M"
+#define INSTR_PROF_CNTS_COFF ".lprfc$M"
+#define INSTR_PROF_VALS_COFF ".lprfv$M"
+#define INSTR_PROF_VNODES_COFF ".lprfnd$M"
+#define INSTR_PROF_COVMAP_COFF ".lcovmap$M"
+#define INSTR_PROF_COVFUN_COFF ".lcovfun$M"
+#define INSTR_PROF_ORDERFILE_COFF ".lorderfile$M"
+
+#ifdef _WIN32
+/* Runtime section names and name strings. */
+#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF
+#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COFF
+#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COFF
+/* Array of pointers. Each pointer points to a list
+ * of value nodes associated with one value site.
+ */
+#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COFF
+/* Value profile nodes section. */
+#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COFF
+#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COFF
+#define INSTR_PROF_COVFUN_SECT_NAME INSTR_PROF_COVFUN_COFF
+#define INSTR_PROF_ORDERFILE_SECT_NAME INSTR_PROF_ORDERFILE_COFF
+#else
+/* Runtime section names and name strings. */
+#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON)
+#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON)
+#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON)
+/* Array of pointers. Each pointer points to a list
+ * of value nodes associated with one value site.
+ */
+#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON)
+/* Value profile nodes section. */
+#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON)
+#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON)
+#define INSTR_PROF_COVFUN_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVFUN_COMMON)
+/* Order file instrumentation. */
+#define INSTR_PROF_ORDERFILE_SECT_NAME \
+ INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON)
+#endif
+
+#define INSTR_PROF_ORDERFILE_BUFFER_NAME _llvm_order_file_buffer
+#define INSTR_PROF_ORDERFILE_BUFFER_NAME_STR \
+ INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_BUFFER_NAME)
+#define INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME _llvm_order_file_buffer_idx
+#define INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME_STR \
+ INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME)
+
+/* Macros to define start/stop section symbol for a given
+ * section on Linux. For instance
+ * INSTR_PROF_SECT_START(INSTR_PROF_DATA_SECT_NAME) will
+ * expand to __start___llvm_prof_data
+ */
+#define INSTR_PROF_SECT_START(Sect) \
+ INSTR_PROF_CONCAT(__start_,Sect)
+#define INSTR_PROF_SECT_STOP(Sect) \
+ INSTR_PROF_CONCAT(__stop_,Sect)
+
+/* Value Profiling API linkage name. */
+#define INSTR_PROF_VALUE_PROF_FUNC __llvm_profile_instrument_target
+#define INSTR_PROF_VALUE_PROF_FUNC_STR \
+ INSTR_PROF_QUOTE(INSTR_PROF_VALUE_PROF_FUNC)
+#define INSTR_PROF_VALUE_PROF_MEMOP_FUNC __llvm_profile_instrument_memop
+#define INSTR_PROF_VALUE_PROF_MEMOP_FUNC_STR \
+ INSTR_PROF_QUOTE(INSTR_PROF_VALUE_PROF_MEMOP_FUNC)
+
+/* InstrProfile per-function control data alignment. */
+#define INSTR_PROF_DATA_ALIGNMENT 8
+
+/* The data structure that represents a tracked value by the
+ * value profiler.
+ */
+typedef struct InstrProfValueData {
+ /* Profiled value. */
+ uint64_t Value;
+ /* Number of times the value appears in the training run. */
+ uint64_t Count;
+} InstrProfValueData;
+
+#endif /* INSTR_PROF_DATA_INC */
+
+#ifndef INSTR_ORDER_FILE_INC
+/* The maximal # of functions: 128*1024 (the buffer size will be 128*4 KB). */
+#define INSTR_ORDER_FILE_BUFFER_SIZE 131072
+#define INSTR_ORDER_FILE_BUFFER_BITS 17
+#define INSTR_ORDER_FILE_BUFFER_MASK 0x1ffff
+#endif /* INSTR_ORDER_FILE_INC */
+#else
+#undef INSTR_PROF_DATA_DEFINED
+#endif
+
+#undef COVMAP_V2_OR_V3
+
+#ifdef INSTR_PROF_VALUE_PROF_MEMOP_API
+
+#ifdef __cplusplus
+#define INSTR_PROF_INLINE inline
+#else
+#define INSTR_PROF_INLINE
+#endif
+
+/* The value range buckets (22 buckets) for the memop size value profiling looks
+ * like:
+ *
+ * [0, 0]
+ * [1, 1]
+ * [2, 2]
+ * [3, 3]
+ * [4, 4]
+ * [5, 5]
+ * [6, 6]
+ * [7, 7]
+ * [8, 8]
+ * [9, 15]
+ * [16, 16]
+ * [17, 31]
+ * [32, 32]
+ * [33, 63]
+ * [64, 64]
+ * [65, 127]
+ * [128, 128]
+ * [129, 255]
+ * [256, 256]
+ * [257, 511]
+ * [512, 512]
+ * [513, UINT64_MAX]
+ *
+ * Each range has a 'representative value' which is the lower end value of the
+ * range and used to store in the runtime profile data records and the VP
+ * metadata. For example, it's 2 for [2, 2] and 64 for [65, 127].
+ */
+#define INSTR_PROF_NUM_BUCKETS 22
+
+/*
+ * Clz and Popcount. This code was copied from
+ * compiler-rt/lib/fuzzer/{FuzzerBuiltins.h,FuzzerBuiltinsMsvc.h} and
+ * llvm/include/llvm/Support/MathExtras.h.
+ */
+#if defined(_MSC_VER) && !defined(__clang__)
+
+#include <intrin.h>
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
+int InstProfClzll(unsigned long long X) {
+ unsigned long LeadZeroIdx = 0;
+#if !defined(_M_ARM64) && !defined(_M_X64)
+ // Scan the high 32 bits.
+ if (_BitScanReverse(&LeadZeroIdx, (unsigned long)(X >> 32)))
+ return (int)(63 - (LeadZeroIdx + 32)); // Create a bit offset
+ // from the MSB.
+ // Scan the low 32 bits.
+ if (_BitScanReverse(&LeadZeroIdx, (unsigned long)(X)))
+ return (int)(63 - LeadZeroIdx);
+#else
+ if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx;
+#endif
+ return 64;
+}
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
+int InstProfPopcountll(unsigned long long X) {
+ // This code originates from https://reviews.llvm.org/rG30626254510f.
+ unsigned long long v = X;
+ v = v - ((v >> 1) & 0x5555555555555555ULL);
+ v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
+ v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
+ return (int)((unsigned long long)(v * 0x0101010101010101ULL) >> 56);
+}
+
+#else
+
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
+int InstProfClzll(unsigned long long X) { return __builtin_clzll(X); }
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE
+int InstProfPopcountll(unsigned long long X) { return __builtin_popcountll(X); }
+
+#endif /* defined(_MSC_VER) && !defined(__clang__) */
+
+/* Map an (observed) memop size value to the representative value of its range.
+ * For example, 5 -> 5, 22 -> 17, 99 -> 65, 256 -> 256, 1001 -> 513. */
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE uint64_t
+InstrProfGetRangeRepValue(uint64_t Value) {
+ if (Value <= 8)
+ // The first ranges are individually tracked. Use the value as is.
+ return Value;
+ else if (Value >= 513)
+ // The last range is mapped to its lowest value.
+ return 513;
+ else if (InstProfPopcountll(Value) == 1)
+ // If it's a power of two, use it as is.
+ return Value;
+ else
+ // Otherwise, take to the previous power of two + 1.
+ return (UINT64_C(1) << (64 - InstProfClzll(Value) - 1)) + 1;
+}
+
+/* Return true if the range that an (observed) memop size value belongs to has
+ * only a single value in the range. For example, 0 -> true, 8 -> true, 10 ->
+ * false, 64 -> true, 100 -> false, 513 -> false. */
+INSTR_PROF_VISIBILITY INSTR_PROF_INLINE unsigned
+InstrProfIsSingleValRange(uint64_t Value) {
+ if (Value <= 8)
+ // The first ranges are individually tracked.
+ return 1;
+ else if (InstProfPopcountll(Value) == 1)
+ // If it's a power of two, there's only one value.
+ return 1;
+ else
+ // Otherwise, there's more than one value in the range.
+ return 0;
+}
+
+#endif /* INSTR_PROF_VALUE_PROF_MEMOP_API */
diff --git a/contrib/libs/clang16-rt/include/profile/MIBEntryDef.inc b/contrib/libs/clang16-rt/include/profile/MIBEntryDef.inc
new file mode 100644
index 00000000000..794163ae103
--- /dev/null
+++ b/contrib/libs/clang16-rt/include/profile/MIBEntryDef.inc
@@ -0,0 +1,53 @@
+/*===-- MemEntryDef.inc - MemProf profiling runtime macros -*- C++ -*-======== *\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+/*
+ * This file defines the macros for memprof profiling data structures.
+ * Eg. usage to define the memprof meminfoblock struct:
+ *
+ * struct MemInfoBlock {
+ * #define MIBEntryDef(NameTag, Name, Type) Type Name;
+ * #include MIBEntryDef.inc
+ * #undef MIBEntryDef
+ * };
+ *
+ * This file has two identical copies. The primary copy lives in LLVM and
+ * the other one sits in compiler-rt/include/profile directory. To make changes
+ * in this file, first modify the primary copy and copy it over to compiler-rt.
+ * Testing of any change in this file can start only after the two copies are
+ * synced up.
+ *
+\*===----------------------------------------------------------------------===*/
+#ifndef MIBEntryDef
+#define MIBEntryDef(NameTag, Name, Type)
+#endif
+
+MIBEntryDef(AllocCount = 1, AllocCount, uint32_t)
+MIBEntryDef(TotalAccessCount = 2, TotalAccessCount, uint64_t)
+MIBEntryDef(MinAccessCount = 3, MinAccessCount, uint64_t)
+MIBEntryDef(MaxAccessCount = 4, MaxAccessCount, uint64_t)
+MIBEntryDef(TotalSize = 5, TotalSize, uint64_t)
+MIBEntryDef(MinSize = 6, MinSize, uint32_t)
+MIBEntryDef(MaxSize = 7, MaxSize, uint32_t)
+MIBEntryDef(AllocTimestamp = 8, AllocTimestamp, uint32_t)
+MIBEntryDef(DeallocTimestamp = 9, DeallocTimestamp, uint32_t)
+MIBEntryDef(TotalLifetime = 10, TotalLifetime, uint64_t)
+MIBEntryDef(MinLifetime = 11, MinLifetime, uint32_t)
+MIBEntryDef(MaxLifetime = 12, MaxLifetime, uint32_t)
+MIBEntryDef(AllocCpuId = 13, AllocCpuId, uint32_t)
+MIBEntryDef(DeallocCpuId = 14, DeallocCpuId, uint32_t)
+MIBEntryDef(NumMigratedCpu = 15, NumMigratedCpu, uint32_t)
+MIBEntryDef(NumLifetimeOverlaps = 16, NumLifetimeOverlaps, uint32_t)
+MIBEntryDef(NumSameAllocCpu = 17, NumSameAllocCpu, uint32_t)
+MIBEntryDef(NumSameDeallocCpu = 18, NumSameDeallocCpu, uint32_t)
+MIBEntryDef(DataTypeId = 19, DataTypeId, uint64_t)
+MIBEntryDef(TotalAccessDensity = 20, TotalAccessDensity, uint64_t)
+MIBEntryDef(MinAccessDensity = 21, MinAccessDensity, uint32_t)
+MIBEntryDef(MaxAccessDensity = 22, MaxAccessDensity, uint32_t)
+MIBEntryDef(TotalLifetimeAccessDensity = 23, TotalLifetimeAccessDensity, uint64_t)
+MIBEntryDef(MinLifetimeAccessDensity = 24, MinLifetimeAccessDensity, uint32_t)
+MIBEntryDef(MaxLifetimeAccessDensity = 25, MaxLifetimeAccessDensity, uint32_t)
diff --git a/contrib/libs/clang16-rt/include/profile/MemProfData.inc b/contrib/libs/clang16-rt/include/profile/MemProfData.inc
new file mode 100644
index 00000000000..c533073da75
--- /dev/null
+++ b/contrib/libs/clang16-rt/include/profile/MemProfData.inc
@@ -0,0 +1,202 @@
+#ifndef MEMPROF_DATA_INC
+#define MEMPROF_DATA_INC
+/*===-- MemProfData.inc - MemProf profiling runtime structures -*- C++ -*-=== *\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+/*
+ * This is the main file that defines all the data structure, signature,
+ * constant literals that are shared across profiling runtime library,
+ * and host tools (reader/writer).
+ *
+ * This file has two identical copies. The primary copy lives in LLVM and
+ * the other one sits in compiler-rt/include/profile directory. To make changes
+ * in this file, first modify the primary copy and copy it over to compiler-rt.
+ * Testing of any change in this file can start only after the two copies are
+ * synced up.
+ *
+\*===----------------------------------------------------------------------===*/
+
+#ifdef _MSC_VER
+#define PACKED(...) __pragma(pack(push,1)) __VA_ARGS__ __pragma(pack(pop))
+#else
+#define PACKED(...) __VA_ARGS__ __attribute__((__packed__))
+#endif
+
+// A 64-bit magic number to uniquely identify the raw binary memprof profile file.
+#define MEMPROF_RAW_MAGIC_64 \
+ ((uint64_t)255 << 56 | (uint64_t)'m' << 48 | (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | \
+ (uint64_t)'o' << 24 | (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129)
+
+// The version number of the raw binary format.
+#define MEMPROF_RAW_VERSION 2ULL
+
+namespace llvm {
+namespace memprof {
+// A struct describing the header used for the raw binary memprof profile format.
+PACKED(struct Header {
+ uint64_t Magic;
+ uint64_t Version;
+ uint64_t TotalSize;
+ uint64_t SegmentOffset;
+ uint64_t MIBOffset;
+ uint64_t StackOffset;
+});
+
+
+// A struct describing the information necessary to describe a /proc/maps
+// segment entry for a particular binary/library identified by its build id.
+PACKED(struct SegmentEntry {
+ uint64_t Start;
+ uint64_t End;
+ uint64_t Offset;
+ // This field is unused until sanitizer procmaps support for build ids for
+ // Linux-Elf is implemented.
+ uint8_t BuildId[32] = {0};
+
+ SegmentEntry(uint64_t S, uint64_t E, uint64_t O) :
+ Start(S), End(E), Offset(O) {}
+
+ SegmentEntry(const SegmentEntry& S) {
+ Start = S.Start;
+ End = S.End;
+ Offset = S.Offset;
+ }
+
+ SegmentEntry& operator=(const SegmentEntry& S) {
+ Start = S.Start;
+ End = S.End;
+ Offset = S.Offset;
+ return *this;
+ }
+
+ bool operator==(const SegmentEntry& S) const {
+ return Start == S.Start &&
+ End == S.End &&
+ Offset == S.Offset;
+ }
+});
+
+// Packed struct definition for MSVC. We can't use the PACKED macro defined in
+// MemProfData.inc since it would mean we are embedding a directive (the
+// #include for MIBEntryDef) into the macros which is undefined behaviour.
+#ifdef _MSC_VER
+__pragma(pack(push,1))
+#endif
+
+// A struct representing the heap allocation characteristics of a particular
+// runtime context. This struct is shared between the compiler-rt runtime and
+// the raw profile reader. The indexed format uses a separate, self-describing
+// backwards compatible format.
+struct MemInfoBlock{
+
+#define MIBEntryDef(NameTag, Name, Type) Type Name;
+#include "MIBEntryDef.inc"
+#undef MIBEntryDef
+
+bool operator==(const MemInfoBlock& Other) const {
+ bool IsEqual = true;
+#define MIBEntryDef(NameTag, Name, Type) \
+ IsEqual = (IsEqual && Name == Other.Name);
+#include "MIBEntryDef.inc"
+#undef MIBEntryDef
+ return IsEqual;
+}
+
+MemInfoBlock() {
+#define MIBEntryDef(NameTag, Name, Type) Name = Type();
+#include "MIBEntryDef.inc"
+#undef MIBEntryDef
+}
+
+MemInfoBlock(uint32_t Size, uint64_t AccessCount, uint32_t AllocTs,
+ uint32_t DeallocTs, uint32_t AllocCpu, uint32_t DeallocCpu)
+ : MemInfoBlock() {
+ AllocCount = 1U;
+ TotalAccessCount = AccessCount;
+ MinAccessCount = AccessCount;
+ MaxAccessCount = AccessCount;
+ TotalSize = Size;
+ MinSize = Size;
+ MaxSize = Size;
+ AllocTimestamp = AllocTs;
+ DeallocTimestamp = DeallocTs;
+ TotalLifetime = DeallocTimestamp - AllocTimestamp;
+ MinLifetime = TotalLifetime;
+ MaxLifetime = TotalLifetime;
+ // Access density is accesses per byte. Multiply by 100 to include the
+ // fractional part.
+ TotalAccessDensity = AccessCount * 100 / Size;
+ MinAccessDensity = TotalAccessDensity;
+ MaxAccessDensity = TotalAccessDensity;
+ // Lifetime access density is the access density per second of lifetime.
+ // Multiply by 1000 to convert denominator lifetime to seconds (using a
+ // minimum lifetime of 1ms to avoid divide by 0. Do the multiplication first
+ // to reduce truncations to 0.
+ TotalLifetimeAccessDensity =
+ TotalAccessDensity * 1000 / (TotalLifetime ? TotalLifetime : 1);
+ MinLifetimeAccessDensity = TotalLifetimeAccessDensity;
+ MaxLifetimeAccessDensity = TotalLifetimeAccessDensity;
+ AllocCpuId = AllocCpu;
+ DeallocCpuId = DeallocCpu;
+ NumMigratedCpu = AllocCpuId != DeallocCpuId;
+}
+
+void Merge(const MemInfoBlock &newMIB) {
+ AllocCount += newMIB.AllocCount;
+
+ TotalAccessCount += newMIB.TotalAccessCount;
+ MinAccessCount = newMIB.MinAccessCount < MinAccessCount ? newMIB.MinAccessCount : MinAccessCount;
+ MaxAccessCount = newMIB.MaxAccessCount > MaxAccessCount ? newMIB.MaxAccessCount : MaxAccessCount;
+
+ TotalSize += newMIB.TotalSize;
+ MinSize = newMIB.MinSize < MinSize ? newMIB.MinSize : MinSize;
+ MaxSize = newMIB.MaxSize > MaxSize ? newMIB.MaxSize : MaxSize;
+
+ TotalLifetime += newMIB.TotalLifetime;
+ MinLifetime = newMIB.MinLifetime < MinLifetime ? newMIB.MinLifetime : MinLifetime;
+ MaxLifetime = newMIB.MaxLifetime > MaxLifetime ? newMIB.MaxLifetime : MaxLifetime;
+
+ TotalAccessDensity += newMIB.TotalAccessDensity;
+ MinAccessDensity = newMIB.MinAccessDensity < MinAccessDensity
+ ? newMIB.MinAccessDensity
+ : MinAccessDensity;
+ MaxAccessDensity = newMIB.MaxAccessDensity > MaxAccessDensity
+ ? newMIB.MaxAccessDensity
+ : MaxAccessDensity;
+
+ TotalLifetimeAccessDensity += newMIB.TotalLifetimeAccessDensity;
+ MinLifetimeAccessDensity =
+ newMIB.MinLifetimeAccessDensity < MinLifetimeAccessDensity
+ ? newMIB.MinLifetimeAccessDensity
+ : MinLifetimeAccessDensity;
+ MaxLifetimeAccessDensity =
+ newMIB.MaxLifetimeAccessDensity > MaxLifetimeAccessDensity
+ ? newMIB.MaxLifetimeAccessDensity
+ : MaxLifetimeAccessDensity;
+
+ // We know newMIB was deallocated later, so just need to check if it was
+ // allocated before last one deallocated.
+ NumLifetimeOverlaps += newMIB.AllocTimestamp < DeallocTimestamp;
+ AllocTimestamp = newMIB.AllocTimestamp;
+ DeallocTimestamp = newMIB.DeallocTimestamp;
+
+ NumSameAllocCpu += AllocCpuId == newMIB.AllocCpuId;
+ NumSameDeallocCpu += DeallocCpuId == newMIB.DeallocCpuId;
+ AllocCpuId = newMIB.AllocCpuId;
+ DeallocCpuId = newMIB.DeallocCpuId;
+}
+
+#ifdef _MSC_VER
+} __pragma(pack(pop));
+#else
+} __attribute__((__packed__));
+#endif
+
+} // namespace memprof
+} // namespace llvm
+
+#endif
diff --git a/contrib/libs/clang16-rt/include/sanitizer/allocator_interface.h b/contrib/libs/clang16-rt/include/sanitizer/allocator_interface.h
new file mode 100644
index 00000000000..6226135ef84
--- /dev/null
+++ b/contrib/libs/clang16-rt/include/sanitizer/allocator_interface.h
@@ -0,0 +1,88 @@
+//===-- allocator_interface.h ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Public interface header for allocator used in sanitizers (ASan/TSan/MSan).
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_ALLOCATOR_INTERFACE_H
+#define SANITIZER_ALLOCATOR_INTERFACE_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ /* Returns the estimated number of bytes that will be reserved by allocator
+ for request of "size" bytes. If allocator can't allocate that much
+ memory, returns the maximal possible allocation size, otherwise returns
+ "size". */
+ size_t __sanitizer_get_estimated_allocated_size(size_t size);
+
+ /* Returns true if p was returned by the allocator and
+ is not yet freed. */
+ int __sanitizer_get_ownership(const volatile void *p);
+
+ /* Returns the number of bytes reserved for the pointer p.
+ Requires (get_ownership(p) == true) or (p == 0). */
+ size_t __sanitizer_get_allocated_size(const volatile void *p);
+
+ /* Number of bytes, allocated and not yet freed by the application. */
+ size_t __sanitizer_get_current_allocated_bytes(void);
+
+ /* Number of bytes, mmaped by the allocator to fulfill allocation requests.
+ Generally, for request of X bytes, allocator can reserve and add to free
+ lists a large number of chunks of size X to use them for future requests.
+ All these chunks count toward the heap size. Currently, allocator never
+ releases memory to OS (instead, it just puts freed chunks to free
+ lists). */
+ size_t __sanitizer_get_heap_size(void);
+
+ /* Number of bytes, mmaped by the allocator, which can be used to fulfill
+ allocation requests. When a user program frees memory chunk, it can first
+ fall into quarantine and will count toward __sanitizer_get_free_bytes()
+ later. */
+ size_t __sanitizer_get_free_bytes(void);
+
+ /* Number of bytes in unmapped pages, that are released to OS. Currently,
+ always returns 0. */
+ size_t __sanitizer_get_unmapped_bytes(void);
+
+ /* Malloc hooks that may be optionally provided by user.
+ __sanitizer_malloc_hook(ptr, size) is called immediately after
+ allocation of "size" bytes, which returned "ptr".
+ __sanitizer_free_hook(ptr) is called immediately before
+ deallocation of "ptr". */
+ void __sanitizer_malloc_hook(const volatile void *ptr, size_t size);
+ void __sanitizer_free_hook(const volatile void *ptr);
+
+ /* Installs a pair of hooks for malloc/free.
+ Several (currently, 5) hook pairs may be installed, they are executed
+ in the order they were installed and after calling
+ __sanitizer_malloc_hook/__sanitizer_free_hook.
+ Unlike __sanitizer_malloc_hook/__sanitizer_free_hook these hooks can be
+ chained and do not rely on weak symbols working on the platform, but
+ require __sanitizer_install_malloc_and_free_hooks to be called at startup
+ and thus will not be called on malloc/free very early in the process.
+ Returns the number of hooks currently installed or 0 on failure.
+ Not thread-safe, should be called in the main thread before starting
+ other threads.
+ */
+ int __sanitizer_install_malloc_and_free_hooks(
+ void (*malloc_hook)(const volatile void *, size_t),
+ void (*free_hook)(const volatile void *));
+
+ /* Drains allocator quarantines (calling thread's and global ones), returns
+ freed memory back to OS and releases other non-essential internal allocator
+ resources in attempt to reduce process RSS.
+ Currently available with ASan only.
+ */
+ void __sanitizer_purge_allocator(void);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif
diff --git a/contrib/libs/clang16-rt/include/sanitizer/coverage_interface.h b/contrib/libs/clang16-rt/include/sanitizer/coverage_interface.h
new file mode 100644
index 00000000000..c063cfe60c5
--- /dev/null
+++ b/contrib/libs/clang16-rt/include/sanitizer/coverage_interface.h
@@ -0,0 +1,35 @@
+//===-- sanitizer/coverage_interface.h --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Public interface for sanitizer coverage.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_COVERAG_INTERFACE_H
+#define SANITIZER_COVERAG_INTERFACE_H
+
+#include <sanitizer/common_interface_defs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ // Record and dump coverage info.
+ void __sanitizer_cov_dump(void);
+
+ // Clear collected coverage info.
+ void __sanitizer_cov_reset(void);
+
+ // Dump collected coverage info. Sorts pcs by module into individual .sancov
+ // files.
+ void __sanitizer_dump_coverage(const uintptr_t *pcs, uintptr_t len);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // SANITIZER_COVERAG_INTERFACE_H
diff --git a/contrib/libs/clang16-rt/include/sanitizer/dfsan_interface.h b/contrib/libs/clang16-rt/include/sanitizer/dfsan_interface.h
new file mode 100644
index 00000000000..519bfffa9a2
--- /dev/null
+++ b/contrib/libs/clang16-rt/include/sanitizer/dfsan_interface.h
@@ -0,0 +1,207 @@
+//===-- dfsan_interface.h -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataFlowSanitizer.
+//
+// Public interface header.
+//===----------------------------------------------------------------------===//
+#ifndef DFSAN_INTERFACE_H
+#define DFSAN_INTERFACE_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sanitizer/common_interface_defs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uint8_t dfsan_label;
+typedef uint32_t dfsan_origin;
+
+/// Signature of the callback argument to dfsan_set_write_callback().
+typedef void (*dfsan_write_callback_t)(int fd, const void *buf, size_t count);
+
+/// Signature of the callback argument to dfsan_set_conditional_callback().
+typedef void (*dfsan_conditional_callback_t)(dfsan_label label,
+ dfsan_origin origin);
+
+/// Signature of the callback argument to dfsan_set_reaches_function_callback().
+/// The description is intended to hold the name of the variable.
+typedef void (*dfsan_reaches_function_callback_t)(dfsan_label label,
+ dfsan_origin origin,
+ const char *file,
+ unsigned int line,
+ const char *function);
+
+/// Computes the union of \c l1 and \c l2, resulting in a union label.
+dfsan_label dfsan_union(dfsan_label l1, dfsan_label l2);
+
+/// Sets the label for each address in [addr,addr+size) to \c label.
+void dfsan_set_label(dfsan_label label, void *addr, size_t size);
+
+/// Sets the label for each address in [addr,addr+size) to the union of the
+/// current label for that address and \c label.
+void dfsan_add_label(dfsan_label label, void *addr, size_t size);
+
+/// Retrieves the label associated with the given data.
+///
+/// The type of 'data' is arbitrary. The function accepts a value of any type,
+/// which can be truncated or extended (implicitly or explicitly) as necessary.
+/// The truncation/extension operations will preserve the label of the original
+/// value.
+dfsan_label dfsan_get_label(long data);
+
+/// Retrieves the immediate origin associated with the given data. The returned
+/// origin may point to another origin.
+///
+/// The type of 'data' is arbitrary.
+dfsan_origin dfsan_get_origin(long data);
+
+/// Retrieves the label associated with the data at the given address.
+dfsan_label dfsan_read_label(const void *addr, size_t size);
+
+/// Return the origin associated with the first taint byte in the size bytes
+/// from the address addr.
+dfsan_origin dfsan_read_origin_of_first_taint(const void *addr, size_t size);
+
+/// Returns whether the given label label contains the label elem.
+int dfsan_has_label(dfsan_label label, dfsan_label elem);
+
+/// Flushes the DFSan shadow, i.e. forgets about all labels currently associated
+/// with the application memory. Use this call to start over the taint tracking
+/// within the same process.
+///
+/// Note: If another thread is working with tainted data during the flush, that
+/// taint could still be written to shadow after the flush.
+void dfsan_flush(void);
+
+/// Sets a callback to be invoked on calls to write(). The callback is invoked
+/// before the write is done. The write is not guaranteed to succeed when the
+/// callback executes. Pass in NULL to remove any callback.
+void dfsan_set_write_callback(dfsan_write_callback_t labeled_write_callback);
+
+/// Sets a callback to be invoked on any conditional expressions which have a
+/// taint label set. This can be used to find where tainted data influences
+/// the behavior of the program.
+/// These callbacks will only be added when -dfsan-conditional-callbacks=true.
+void dfsan_set_conditional_callback(dfsan_conditional_callback_t callback);
+
+/// Conditional expressions occur during signal handlers.
+/// Making callbacks that handle signals well is tricky, so when
+/// -dfsan-conditional-callbacks=true, conditional expressions used in signal
+/// handlers will add the labels they see into a global (bitwise-or together).
+/// This function returns all label bits seen in signal handler conditions.
+dfsan_label dfsan_get_labels_in_signal_conditional();
+
+/// Sets a callback to be invoked when tainted data reaches a function.
+/// This could occur at function entry, or at a load instruction.
+/// These callbacks will only be added if -dfsan-reaches-function-callbacks=1.
+void dfsan_set_reaches_function_callback(
+ dfsan_reaches_function_callback_t callback);
+
+/// Making callbacks that handle signals well is tricky, so when
+/// -dfsan-reaches-function-callbacks=true, functions reached in signal
+/// handlers will add the labels they see into a global (bitwise-or together).
+/// This function returns all label bits seen during signal handlers.
+dfsan_label dfsan_get_labels_in_signal_reaches_function();
+
+/// Interceptor hooks.
+/// Whenever a dfsan's custom function is called the corresponding
+/// hook is called it non-zero. The hooks should be defined by the user.
+/// The primary use case is taint-guided fuzzing, where the fuzzer
+/// needs to see the parameters of the function and the labels.
+/// FIXME: implement more hooks.
+void dfsan_weak_hook_memcmp(void *caller_pc, const void *s1, const void *s2,
+ size_t n, dfsan_label s1_label,
+ dfsan_label s2_label, dfsan_label n_label);
+void dfsan_weak_hook_strncmp(void *caller_pc, const char *s1, const char *s2,
+ size_t n, dfsan_label s1_label,
+ dfsan_label s2_label, dfsan_label n_label);
+
+/// Prints the origin trace of the label at the address addr to stderr. It also
+/// prints description at the beginning of the trace. If origin tracking is not
+/// on, or the address is not labeled, it prints nothing.
+void dfsan_print_origin_trace(const void *addr, const char *description);
+/// As above, but use an origin id from dfsan_get_origin() instead of address.
+/// Does not include header line with taint label and address information.
+void dfsan_print_origin_id_trace(dfsan_origin origin);
+
+/// Prints the origin trace of the label at the address \p addr to a
+/// pre-allocated output buffer. If origin tracking is not on, or the address is
+/// not labeled, it prints nothing.
+///
+/// Typical usage:
+/// \code
+/// char kDescription[] = "...";
+/// char buf[1024];
+/// dfsan_sprint_origin_trace(&tainted_var, kDescription, buf, sizeof(buf));
+/// \endcode
+///
+/// Typical usage that handles truncation:
+/// \code
+/// char buf[1024];
+/// int len = dfsan_sprint_origin_trace(&var, nullptr, buf, sizeof(buf));
+///
+/// if (len < sizeof(buf)) {
+/// ProcessOriginTrace(buf);
+/// } else {
+/// char *tmpbuf = new char[len + 1];
+/// dfsan_sprint_origin_trace(&var, nullptr, tmpbuf, len + 1);
+/// ProcessOriginTrace(tmpbuf);
+/// delete[] tmpbuf;
+/// }
+/// \endcode
+///
+/// \param addr The tainted memory address whose origin we are printing.
+/// \param description A description printed at the beginning of the trace.
+/// \param [out] out_buf The output buffer to write the results to.
+/// \param out_buf_size The size of \p out_buf.
+///
+/// \returns The number of symbols that should have been written to \p out_buf
+/// (not including trailing null byte '\0'). Thus, the string is truncated iff
+/// return value is not less than \p out_buf_size.
+size_t dfsan_sprint_origin_trace(const void *addr, const char *description,
+ char *out_buf, size_t out_buf_size);
+/// As above, but use an origin id from dfsan_get_origin() instead of address.
+/// Does not include header line with taint label and address information.
+size_t dfsan_sprint_origin_id_trace(dfsan_origin origin, char *out_buf,
+ size_t out_buf_size);
+
+/// Prints the stack trace leading to this call to a pre-allocated output
+/// buffer.
+///
+/// For usage examples, see dfsan_sprint_origin_trace.
+///
+/// \param [out] out_buf The output buffer to write the results to.
+/// \param out_buf_size The size of \p out_buf.
+///
+/// \returns The number of symbols that should have been written to \p out_buf
+/// (not including trailing null byte '\0'). Thus, the string is truncated iff
+/// return value is not less than \p out_buf_size.
+size_t dfsan_sprint_stack_trace(char *out_buf, size_t out_buf_size);
+
+/// Retrieves the very first origin associated with the data at the given
+/// address.
+dfsan_origin dfsan_get_init_origin(const void *addr);
+
+/// Returns the value of -dfsan-track-origins.
+/// * 0: do not track origins.
+/// * 1: track origins at memory store operations.
+/// * 2: track origins at memory load and store operations.
+int dfsan_get_track_origins(void);
+#ifdef __cplusplus
+} // extern "C"
+
+template <typename T> void dfsan_set_label(dfsan_label label, T &data) {
+ dfsan_set_label(label, (void *)&data, sizeof(T));
+}
+
+#endif
+
+#endif // DFSAN_INTERFACE_H
diff --git a/contrib/libs/clang16-rt/include/sanitizer/linux_syscall_hooks.h b/contrib/libs/clang16-rt/include/sanitizer/linux_syscall_hooks.h
new file mode 100644
index 00000000000..3f3f1e78dfb
--- /dev/null
+++ b/contrib/libs/clang16-rt/include/sanitizer/linux_syscall_hooks.h
@@ -0,0 +1,3100 @@
+//===-- linux_syscall_hooks.h ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of public sanitizer interface.
+//
+// System call handlers.
+//
+// Interface methods declared in this header implement pre- and post- syscall
+// actions for the active sanitizer.
+// Usage:
+// __sanitizer_syscall_pre_getfoo(...args...);
+// long res = syscall(__NR_getfoo, ...args...);
+// __sanitizer_syscall_post_getfoo(res, ...args...);
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_LINUX_SYSCALL_HOOKS_H
+#define SANITIZER_LINUX_SYSCALL_HOOKS_H
+
+#define __sanitizer_syscall_pre_time(tloc) \
+ __sanitizer_syscall_pre_impl_time((long)(tloc))
+#define __sanitizer_syscall_post_time(res, tloc) \
+ __sanitizer_syscall_post_impl_time(res, (long)(tloc))
+#define __sanitizer_syscall_pre_stime(tptr) \
+ __sanitizer_syscall_pre_impl_stime((long)(tptr))
+#define __sanitizer_syscall_post_stime(res, tptr) \
+ __sanitizer_syscall_post_impl_stime(res, (long)(tptr))
+#define __sanitizer_syscall_pre_gettimeofday(tv, tz) \
+ __sanitizer_syscall_pre_impl_gettimeofday((long)(tv), (long)(tz))
+#define __sanitizer_syscall_post_gettimeofday(res, tv, tz) \
+ __sanitizer_syscall_post_impl_gettimeofday(res, (long)(tv), (long)(tz))
+#define __sanitizer_syscall_pre_settimeofday(tv, tz) \
+ __sanitizer_syscall_pre_impl_settimeofday((long)(tv), (long)(tz))
+#define __sanitizer_syscall_post_settimeofday(res, tv, tz) \
+ __sanitizer_syscall_post_impl_settimeofday(res, (long)(tv), (long)(tz))
+#define __sanitizer_syscall_pre_adjtimex(txc_p) \
+ __sanitizer_syscall_pre_impl_adjtimex((long)(txc_p))
+#define __sanitizer_syscall_post_adjtimex(res, txc_p) \
+ __sanitizer_syscall_post_impl_adjtimex(res, (long)(txc_p))
+#define __sanitizer_syscall_pre_times(tbuf) \
+ __sanitizer_syscall_pre_impl_times((long)(tbuf))
+#define __sanitizer_syscall_post_times(res, tbuf) \
+ __sanitizer_syscall_post_impl_times(res, (long)(tbuf))
+#define __sanitizer_syscall_pre_gettid() __sanitizer_syscall_pre_impl_gettid()
+#define __sanitizer_syscall_post_gettid(res) \
+ __sanitizer_syscall_post_impl_gettid(res)
+#define __sanitizer_syscall_pre_nanosleep(rqtp, rmtp) \
+ __sanitizer_syscall_pre_impl_nanosleep((long)(rqtp), (long)(rmtp))
+#define __sanitizer_syscall_post_nanosleep(res, rqtp, rmtp) \
+ __sanitizer_syscall_post_impl_nanosleep(res, (long)(rqtp), (long)(rmtp))
+#define __sanitizer_syscall_pre_alarm(seconds) \
+ __sanitizer_syscall_pre_impl_alarm((long)(seconds))
+#define __sanitizer_syscall_post_alarm(res, seconds) \
+ __sanitizer_syscall_post_impl_alarm(res, (long)(seconds))
+#define __sanitizer_syscall_pre_getpid() __sanitizer_syscall_pre_impl_getpid()
+#define __sanitizer_syscall_post_getpid(res) \
+ __sanitizer_syscall_post_impl_getpid(res)
+#define __sanitizer_syscall_pre_getppid() __sanitizer_syscall_pre_impl_getppid()
+#define __sanitizer_syscall_post_getppid(res) \
+ __sanitizer_syscall_post_impl_getppid(res)
+#define __sanitizer_syscall_pre_getuid() __sanitizer_syscall_pre_impl_getuid()
+#define __sanitizer_syscall_post_getuid(res) \
+ __sanitizer_syscall_post_impl_getuid(res)
+#define __sanitizer_syscall_pre_geteuid() __sanitizer_syscall_pre_impl_geteuid()
+#define __sanitizer_syscall_post_geteuid(res) \
+ __sanitizer_syscall_post_impl_geteuid(res)
+#define __sanitizer_syscall_pre_getgid() __sanitizer_syscall_pre_impl_getgid()
+#define __sanitizer_syscall_post_getgid(res) \
+ __sanitizer_syscall_post_impl_getgid(res)
+#define __sanitizer_syscall_pre_getegid() __sanitizer_syscall_pre_impl_getegid()
+#define __sanitizer_syscall_post_getegid(res) \
+ __sanitizer_syscall_post_impl_getegid(res)
+#define __sanitizer_syscall_pre_getresuid(ruid, euid, suid) \
+ __sanitizer_syscall_pre_impl_getresuid((long)(ruid), (long)(euid), \
+ (long)(suid))
+#define __sanitizer_syscall_post_getresuid(res, ruid, euid, suid) \
+ __sanitizer_syscall_post_impl_getresuid(res, (long)(ruid), (long)(euid), \
+ (long)(suid))
+#define __sanitizer_syscall_pre_getresgid(rgid, egid, sgid) \
+ __sanitizer_syscall_pre_impl_getresgid((long)(rgid), (long)(egid), \
+ (long)(sgid))
+#define __sanitizer_syscall_post_getresgid(res, rgid, egid, sgid) \
+ __sanitizer_syscall_post_impl_getresgid(res, (long)(rgid), (long)(egid), \
+ (long)(sgid))
+#define __sanitizer_syscall_pre_getpgid(pid) \
+ __sanitizer_syscall_pre_impl_getpgid((long)(pid))
+#define __sanitizer_syscall_post_getpgid(res, pid) \
+ __sanitizer_syscall_post_impl_getpgid(res, (long)(pid))
+#define __sanitizer_syscall_pre_getpgrp() __sanitizer_syscall_pre_impl_getpgrp()
+#define __sanitizer_syscall_post_getpgrp(res) \
+ __sanitizer_syscall_post_impl_getpgrp(res)
+#define __sanitizer_syscall_pre_getsid(pid) \
+ __sanitizer_syscall_pre_impl_getsid((long)(pid))
+#define __sanitizer_syscall_post_getsid(res, pid) \
+ __sanitizer_syscall_post_impl_getsid(res, (long)(pid))
+#define __sanitizer_syscall_pre_getgroups(gidsetsize, grouplist) \
+ __sanitizer_syscall_pre_impl_getgroups((long)(gidsetsize), (long)(grouplist))
+#define __sanitizer_syscall_post_getgroups(res, gidsetsize, grouplist) \
+ __sanitizer_syscall_post_impl_getgroups(res, (long)(gidsetsize), \
+ (long)(grouplist))
+#define __sanitizer_syscall_pre_setregid(rgid, egid) \
+ __sanitizer_syscall_pre_impl_setregid((long)(rgid), (long)(egid))
+#define __sanitizer_syscall_post_setregid(res, rgid, egid) \
+ __sanitizer_syscall_post_impl_setregid(res, (long)(rgid), (long)(egid))
+#define __sanitizer_syscall_pre_setgid(gid) \
+ __sanitizer_syscall_pre_impl_setgid((long)(gid))
+#define __sanitizer_syscall_post_setgid(res, gid) \
+ __sanitizer_syscall_post_impl_setgid(res, (long)(gid))
+#define __sanitizer_syscall_pre_setreuid(ruid, euid) \
+ __sanitizer_syscall_pre_impl_setreuid((long)(ruid), (long)(euid))
+#define __sanitizer_syscall_post_setreuid(res, ruid, euid) \
+ __sanitizer_syscall_post_impl_setreuid(res, (long)(ruid), (long)(euid))
+#define __sanitizer_syscall_pre_setuid(uid) \
+ __sanitizer_syscall_pre_impl_setuid((long)(uid))
+#define __sanitizer_syscall_post_setuid(res, uid) \
+ __sanitizer_syscall_post_impl_setuid(res, (long)(uid))
+#define __sanitizer_syscall_pre_setresuid(ruid, euid, suid) \
+ __sanitizer_syscall_pre_impl_setresuid((long)(ruid), (long)(euid), \
+ (long)(suid))
+#define __sanitizer_syscall_post_setresuid(res, ruid, euid, suid) \
+ __sanitizer_syscall_post_impl_setresuid(res, (long)(ruid), (long)(euid), \
+ (long)(suid))
+#define __sanitizer_syscall_pre_setresgid(rgid, egid, sgid) \
+ __sanitizer_syscall_pre_impl_setresgid((long)(rgid), (long)(egid), \
+ (long)(sgid))
+#define __sanitizer_syscall_post_setresgid(res, rgid, egid, sgid) \
+ __sanitizer_syscall_post_impl_setresgid(res, (long)(rgid), (long)(egid), \
+ (long)(sgid))
+#define __sanitizer_syscall_pre_setfsuid(uid) \
+ __sanitizer_syscall_pre_impl_setfsuid((long)(uid))
+#define __sanitizer_syscall_post_setfsuid(res, uid) \
+ __sanitizer_syscall_post_impl_setfsuid(res, (long)(uid))
+#define __sanitizer_syscall_pre_setfsgid(gid) \
+ __sanitizer_syscall_pre_impl_setfsgid((long)(gid))
+#define __sanitizer_syscall_post_setfsgid(res, gid) \
+ __sanitizer_syscall_post_impl_setfsgid(res, (long)(gid))
+#define __sanitizer_syscall_pre_setpgid(pid, pgid) \
+ __sanitizer_syscall_pre_impl_setpgid((long)(pid), (long)(pgid))
+#define __sanitizer_syscall_post_setpgid(res, pid, pgid) \
+ __sanitizer_syscall_post_impl_setpgid(res, (long)(pid), (long)(pgid))
+#define __sanitizer_syscall_pre_setsid() __sanitizer_syscall_pre_impl_setsid()
+#define __sanitizer_syscall_post_setsid(res) \
+ __sanitizer_syscall_post_impl_setsid(res)
+#define __sanitizer_syscall_pre_setgroups(gidsetsize, grouplist) \
+ __sanitizer_syscall_pre_impl_setgroups((long)(gidsetsize), (long)(grouplist))
+#define __sanitizer_syscall_post_setgroups(res, gidsetsize, grouplist) \
+ __sanitizer_syscall_post_impl_setgroups(res, (long)(gidsetsize), \
+ (long)(grouplist))
+#define __sanitizer_syscall_pre_acct(name) \
+ __sanitizer_syscall_pre_impl_acct((long)(name))
+#define __sanitizer_syscall_post_acct(res, name) \
+ __sanitizer_syscall_post_impl_acct(res, (long)(name))
+#define __sanitizer_syscall_pre_capget(header, dataptr) \
+ __sanitizer_syscall_pre_impl_capget((long)(header), (long)(dataptr))
+#define __sanitizer_syscall_post_capget(res, header, dataptr) \
+ __sanitizer_syscall_post_impl_capget(res, (long)(header), (long)(dataptr))
+#define __sanitizer_syscall_pre_capset(header, data) \
+ __sanitizer_syscall_pre_impl_capset((long)(header), (long)(data))
+#define __sanitizer_syscall_post_capset(res, header, data) \
+ __sanitizer_syscall_post_impl_capset(res, (long)(header), (long)(data))
+#define __sanitizer_syscall_pre_personality(personality) \
+ __sanitizer_syscall_pre_impl_personality((long)(personality))
+#define __sanitizer_syscall_post_personality(res, personality) \
+ __sanitizer_syscall_post_impl_personality(res, (long)(personality))
+#define __sanitizer_syscall_pre_sigpending(set) \
+ __sanitizer_syscall_pre_impl_sigpending((long)(set))
+#define __sanitizer_syscall_post_sigpending(res, set) \
+ __sanitizer_syscall_post_impl_sigpending(res, (long)(set))
+#define __sanitizer_syscall_pre_sigprocmask(how, set, oset) \
+ __sanitizer_syscall_pre_impl_sigprocmask((long)(how), (long)(set), \
+ (long)(oset))
+#define __sanitizer_syscall_post_sigprocmask(res, how, set, oset) \
+ __sanitizer_syscall_post_impl_sigprocmask(res, (long)(how), (long)(set), \
+ (long)(oset))
+#define __sanitizer_syscall_pre_getitimer(which, value) \
+ __sanitizer_syscall_pre_impl_getitimer((long)(which), (long)(value))
+#define __sanitizer_syscall_post_getitimer(res, which, value) \
+ __sanitizer_syscall_post_impl_getitimer(res, (long)(which), (long)(value))
+#define __sanitizer_syscall_pre_setitimer(which, value, ovalue) \
+ __sanitizer_syscall_pre_impl_setitimer((long)(which), (long)(value), \
+ (long)(ovalue))
+#define __sanitizer_syscall_post_setitimer(res, which, value, ovalue) \
+ __sanitizer_syscall_post_impl_setitimer(res, (long)(which), (long)(value), \
+ (long)(ovalue))
+#define __sanitizer_syscall_pre_timer_create(which_clock, timer_event_spec, \
+ created_timer_id) \
+ __sanitizer_syscall_pre_impl_timer_create( \
+ (long)(which_clock), (long)(timer_event_spec), (long)(created_timer_id))
+#define __sanitizer_syscall_post_timer_create( \
+ res, which_clock, timer_event_spec, created_timer_id) \
+ __sanitizer_syscall_post_impl_timer_create(res, (long)(which_clock), \
+ (long)(timer_event_spec), \
+ (long)(created_timer_id))
+#define __sanitizer_syscall_pre_timer_gettime(timer_id, setting) \
+ __sanitizer_syscall_pre_impl_timer_gettime((long)(timer_id), (long)(setting))
+#define __sanitizer_syscall_post_timer_gettime(res, timer_id, setting) \
+ __sanitizer_syscall_post_impl_timer_gettime(res, (long)(timer_id), \
+ (long)(setting))
+#define __sanitizer_syscall_pre_timer_getoverrun(timer_id) \
+ __sanitizer_syscall_pre_impl_timer_getoverrun((long)(timer_id))
+#define __sanitizer_syscall_post_timer_getoverrun(res, timer_id) \
+ __sanitizer_syscall_post_impl_timer_getoverrun(res, (long)(timer_id))
+#define __sanitizer_syscall_pre_timer_settime(timer_id, flags, new_setting, \
+ old_setting) \
+ __sanitizer_syscall_pre_impl_timer_settime((long)(timer_id), (long)(flags), \
+ (long)(new_setting), \
+ (long)(old_setting))
+#define __sanitizer_syscall_post_timer_settime(res, timer_id, flags, \
+ new_setting, old_setting) \
+ __sanitizer_syscall_post_impl_timer_settime( \
+ res, (long)(timer_id), (long)(flags), (long)(new_setting), \
+ (long)(old_setting))
+#define __sanitizer_syscall_pre_timer_delete(timer_id) \
+ __sanitizer_syscall_pre_impl_timer_delete((long)(timer_id))
+#define __sanitizer_syscall_post_timer_delete(res, timer_id) \
+ __sanitizer_syscall_post_impl_timer_delete(res, (long)(timer_id))
+#define __sanitizer_syscall_pre_clock_settime(which_clock, tp) \
+ __sanitizer_syscall_pre_impl_clock_settime((long)(which_clock), (long)(tp))
+#define __sanitizer_syscall_post_clock_settime(res, which_clock, tp) \
+ __sanitizer_syscall_post_impl_clock_settime(res, (long)(which_clock), \
+ (long)(tp))
+#define __sanitizer_syscall_pre_clock_gettime(which_clock, tp) \
+ __sanitizer_syscall_pre_impl_clock_gettime((long)(which_clock), (long)(tp))
+#define __sanitizer_syscall_post_clock_gettime(res, which_clock, tp) \
+ __sanitizer_syscall_post_impl_clock_gettime(res, (long)(which_clock), \
+ (long)(tp))
+#define __sanitizer_syscall_pre_clock_adjtime(which_clock, tx) \
+ __sanitizer_syscall_pre_impl_clock_adjtime((long)(which_clock), (long)(tx))
+#define __sanitizer_syscall_post_clock_adjtime(res, which_clock, tx) \
+ __sanitizer_syscall_post_impl_clock_adjtime(res, (long)(which_clock), \
+ (long)(tx))
+#define __sanitizer_syscall_pre_clock_getres(which_clock, tp) \
+ __sanitizer_syscall_pre_impl_clock_getres((long)(which_clock), (long)(tp))
+#define __sanitizer_syscall_post_clock_getres(res, which_clock, tp) \
+ __sanitizer_syscall_post_impl_clock_getres(res, (long)(which_clock), \
+ (long)(tp))
+#define __sanitizer_syscall_pre_clock_nanosleep(which_clock, flags, rqtp, \
+ rmtp) \
+ __sanitizer_syscall_pre_impl_clock_nanosleep( \
+ (long)(which_clock), (long)(flags), (long)(rqtp), (long)(rmtp))
+#define __sanitizer_syscall_post_clock_nanosleep(res, which_clock, flags, \
+ rqtp, rmtp) \
+ __sanitizer_syscall_post_impl_clock_nanosleep( \
+ res, (long)(which_clock), (long)(flags), (long)(rqtp), (long)(rmtp))
+#define __sanitizer_syscall_pre_nice(increment) \
+ __sanitizer_syscall_pre_impl_nice((long)(increment))
+#define __sanitizer_syscall_post_nice(res, increment) \
+ __sanitizer_syscall_post_impl_nice(res, (long)(increment))
+#define __sanitizer_syscall_pre_sched_setscheduler(pid, policy, param) \
+ __sanitizer_syscall_pre_impl_sched_setscheduler((long)(pid), (long)(policy), \
+ (long)(param))
+#define __sanitizer_syscall_post_sched_setscheduler(res, pid, policy, param) \
+ __sanitizer_syscall_post_impl_sched_setscheduler( \
+ res, (long)(pid), (long)(policy), (long)(param))
+#define __sanitizer_syscall_pre_sched_setparam(pid, param) \
+ __sanitizer_syscall_pre_impl_sched_setparam((long)(pid), (long)(param))
+#define __sanitizer_syscall_post_sched_setparam(res, pid, param) \
+ __sanitizer_syscall_post_impl_sched_setparam(res, (long)(pid), (long)(param))
+#define __sanitizer_syscall_pre_sched_getscheduler(pid) \
+ __sanitizer_syscall_pre_impl_sched_getscheduler((long)(pid))
+#define __sanitizer_syscall_post_sched_getscheduler(res, pid) \
+ __sanitizer_syscall_post_impl_sched_getscheduler(res, (long)(pid))
+#define __sanitizer_syscall_pre_sched_getparam(pid, param) \
+ __sanitizer_syscall_pre_impl_sched_getparam((long)(pid), (long)(param))
+#define __sanitizer_syscall_post_sched_getparam(res, pid, param) \
+ __sanitizer_syscall_post_impl_sched_getparam(res, (long)(pid), (long)(param))
+#define __sanitizer_syscall_pre_sched_setaffinity(pid, len, user_mask_ptr) \
+ __sanitizer_syscall_pre_impl_sched_setaffinity((long)(pid), (long)(len), \
+ (long)(user_mask_ptr))
+#define __sanitizer_syscall_post_sched_setaffinity(res, pid, len, \
+ user_mask_ptr) \
+ __sanitizer_syscall_post_impl_sched_setaffinity( \
+ res, (long)(pid), (long)(len), (long)(user_mask_ptr))
+#define __sanitizer_syscall_pre_sched_getaffinity(pid, len, user_mask_ptr) \
+ __sanitizer_syscall_pre_impl_sched_getaffinity((long)(pid), (long)(len), \
+ (long)(user_mask_ptr))
+#define __sanitizer_syscall_post_sched_getaffinity(res, pid, len, \
+ user_mask_ptr) \
+ __sanitizer_syscall_post_impl_sched_getaffinity( \
+ res, (long)(pid), (long)(len), (long)(user_mask_ptr))
+#define __sanitizer_syscall_pre_sched_yield() \
+ __sanitizer_syscall_pre_impl_sched_yield()
+#define __sanitizer_syscall_post_sched_yield(res) \
+ __sanitizer_syscall_post_impl_sched_yield(res)
+#define __sanitizer_syscall_pre_sched_get_priority_max(policy) \
+ __sanitizer_syscall_pre_impl_sched_get_priority_max((long)(policy))
+#define __sanitizer_syscall_post_sched_get_priority_max(res, policy) \
+ __sanitizer_syscall_post_impl_sched_get_priority_max(res, (long)(policy))
+#define __sanitizer_syscall_pre_sched_get_priority_min(policy) \
+ __sanitizer_syscall_pre_impl_sched_get_priority_min((long)(policy))
+#define __sanitizer_syscall_post_sched_get_priority_min(res, policy) \
+ __sanitizer_syscall_post_impl_sched_get_priority_min(res, (long)(policy))
+#define __sanitizer_syscall_pre_sched_rr_get_interval(pid, interval) \
+ __sanitizer_syscall_pre_impl_sched_rr_get_interval((long)(pid), \
+ (long)(interval))
+#define __sanitizer_syscall_post_sched_rr_get_interval(res, pid, interval) \
+ __sanitizer_syscall_post_impl_sched_rr_get_interval(res, (long)(pid), \
+ (long)(interval))
+#define __sanitizer_syscall_pre_setpriority(which, who, niceval) \
+ __sanitizer_syscall_pre_impl_setpriority((long)(which), (long)(who), \
+ (long)(niceval))
+#define __sanitizer_syscall_post_setpriority(res, which, who, niceval) \
+ __sanitizer_syscall_post_impl_setpriority(res, (long)(which), (long)(who), \
+ (long)(niceval))
+#define __sanitizer_syscall_pre_getpriority(which, who) \
+ __sanitizer_syscall_pre_impl_getpriority((long)(which), (long)(who))
+#define __sanitizer_syscall_post_getpriority(res, which, who) \
+ __sanitizer_syscall_post_impl_getpriority(res, (long)(which), (long)(who))
+#define __sanitizer_syscall_pre_shutdown(arg0, arg1) \
+ __sanitizer_syscall_pre_impl_shutdown((long)(arg0), (long)(arg1))
+#define __sanitizer_syscall_post_shutdown(res, arg0, arg1) \
+ __sanitizer_syscall_post_impl_shutdown(res, (long)(arg0), (long)(arg1))
+#define __sanitizer_syscall_pre_reboot(magic1, magic2, cmd, arg) \
+ __sanitizer_syscall_pre_impl_reboot((long)(magic1), (long)(magic2), \
+ (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_post_reboot(res, magic1, magic2, cmd, arg) \
+ __sanitizer_syscall_post_impl_reboot(res, (long)(magic1), (long)(magic2), \
+ (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_pre_restart_syscall() \
+ __sanitizer_syscall_pre_impl_restart_syscall()
+#define __sanitizer_syscall_post_restart_syscall(res) \
+ __sanitizer_syscall_post_impl_restart_syscall(res)
+#define __sanitizer_syscall_pre_kexec_load(entry, nr_segments, segments, \
+ flags) \
+ __sanitizer_syscall_pre_impl_kexec_load((long)(entry), (long)(nr_segments), \
+ (long)(segments), (long)(flags))
+#define __sanitizer_syscall_post_kexec_load(res, entry, nr_segments, segments, \
+ flags) \
+ __sanitizer_syscall_post_impl_kexec_load(res, (long)(entry), \
+ (long)(nr_segments), \
+ (long)(segments), (long)(flags))
+#define __sanitizer_syscall_pre_exit(error_code) \
+ __sanitizer_syscall_pre_impl_exit((long)(error_code))
+#define __sanitizer_syscall_post_exit(res, error_code) \
+ __sanitizer_syscall_post_impl_exit(res, (long)(error_code))
+#define __sanitizer_syscall_pre_exit_group(error_code) \
+ __sanitizer_syscall_pre_impl_exit_group((long)(error_code))
+#define __sanitizer_syscall_post_exit_group(res, error_code) \
+ __sanitizer_syscall_post_impl_exit_group(res, (long)(error_code))
+#define __sanitizer_syscall_pre_wait4(pid, stat_addr, options, ru) \
+ __sanitizer_syscall_pre_impl_wait4((long)(pid), (long)(stat_addr), \
+ (long)(options), (long)(ru))
+#define __sanitizer_syscall_post_wait4(res, pid, stat_addr, options, ru) \
+ __sanitizer_syscall_post_impl_wait4(res, (long)(pid), (long)(stat_addr), \
+ (long)(options), (long)(ru))
+#define __sanitizer_syscall_pre_waitid(which, pid, infop, options, ru) \
+ __sanitizer_syscall_pre_impl_waitid( \
+ (long)(which), (long)(pid), (long)(infop), (long)(options), (long)(ru))
+#define __sanitizer_syscall_post_waitid(res, which, pid, infop, options, ru) \
+ __sanitizer_syscall_post_impl_waitid(res, (long)(which), (long)(pid), \
+ (long)(infop), (long)(options), \
+ (long)(ru))
+#define __sanitizer_syscall_pre_waitpid(pid, stat_addr, options) \
+ __sanitizer_syscall_pre_impl_waitpid((long)(pid), (long)(stat_addr), \
+ (long)(options))
+#define __sanitizer_syscall_post_waitpid(res, pid, stat_addr, options) \
+ __sanitizer_syscall_post_impl_waitpid(res, (long)(pid), (long)(stat_addr), \
+ (long)(options))
+#define __sanitizer_syscall_pre_set_tid_address(tidptr) \
+ __sanitizer_syscall_pre_impl_set_tid_address((long)(tidptr))
+#define __sanitizer_syscall_post_set_tid_address(res, tidptr) \
+ __sanitizer_syscall_post_impl_set_tid_address(res, (long)(tidptr))
+#define __sanitizer_syscall_pre_init_module(umod, len, uargs) \
+ __sanitizer_syscall_pre_impl_init_module((long)(umod), (long)(len), \
+ (long)(uargs))
+#define __sanitizer_syscall_post_init_module(res, umod, len, uargs) \
+ __sanitizer_syscall_post_impl_init_module(res, (long)(umod), (long)(len), \
+ (long)(uargs))
+#define __sanitizer_syscall_pre_delete_module(name_user, flags) \
+ __sanitizer_syscall_pre_impl_delete_module((long)(name_user), (long)(flags))
+#define __sanitizer_syscall_post_delete_module(res, name_user, flags) \
+ __sanitizer_syscall_post_impl_delete_module(res, (long)(name_user), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_rt_sigprocmask(how, set, oset, sigsetsize) \
+ __sanitizer_syscall_pre_impl_rt_sigprocmask( \
+ (long)(how), (long)(set), (long)(oset), (long)(sigsetsize))
+#define __sanitizer_syscall_post_rt_sigprocmask(res, how, set, oset, \
+ sigsetsize) \
+ __sanitizer_syscall_post_impl_rt_sigprocmask( \
+ res, (long)(how), (long)(set), (long)(oset), (long)(sigsetsize))
+#define __sanitizer_syscall_pre_rt_sigpending(set, sigsetsize) \
+ __sanitizer_syscall_pre_impl_rt_sigpending((long)(set), (long)(sigsetsize))
+#define __sanitizer_syscall_post_rt_sigpending(res, set, sigsetsize) \
+ __sanitizer_syscall_post_impl_rt_sigpending(res, (long)(set), \
+ (long)(sigsetsize))
+#define __sanitizer_syscall_pre_rt_sigtimedwait(uthese, uinfo, uts, \
+ sigsetsize) \
+ __sanitizer_syscall_pre_impl_rt_sigtimedwait( \
+ (long)(uthese), (long)(uinfo), (long)(uts), (long)(sigsetsize))
+#define __sanitizer_syscall_post_rt_sigtimedwait(res, uthese, uinfo, uts, \
+ sigsetsize) \
+ __sanitizer_syscall_post_impl_rt_sigtimedwait( \
+ res, (long)(uthese), (long)(uinfo), (long)(uts), (long)(sigsetsize))
+#define __sanitizer_syscall_pre_rt_tgsigqueueinfo(tgid, pid, sig, uinfo) \
+ __sanitizer_syscall_pre_impl_rt_tgsigqueueinfo((long)(tgid), (long)(pid), \
+ (long)(sig), (long)(uinfo))
+#define __sanitizer_syscall_post_rt_tgsigqueueinfo(res, tgid, pid, sig, uinfo) \
+ __sanitizer_syscall_post_impl_rt_tgsigqueueinfo( \
+ res, (long)(tgid), (long)(pid), (long)(sig), (long)(uinfo))
+#define __sanitizer_syscall_pre_kill(pid, sig) \
+ __sanitizer_syscall_pre_impl_kill((long)(pid), (long)(sig))
+#define __sanitizer_syscall_post_kill(res, pid, sig) \
+ __sanitizer_syscall_post_impl_kill(res, (long)(pid), (long)(sig))
+#define __sanitizer_syscall_pre_tgkill(tgid, pid, sig) \
+ __sanitizer_syscall_pre_impl_tgkill((long)(tgid), (long)(pid), (long)(sig))
+#define __sanitizer_syscall_post_tgkill(res, tgid, pid, sig) \
+ __sanitizer_syscall_post_impl_tgkill(res, (long)(tgid), (long)(pid), \
+ (long)(sig))
+#define __sanitizer_syscall_pre_tkill(pid, sig) \
+ __sanitizer_syscall_pre_impl_tkill((long)(pid), (long)(sig))
+#define __sanitizer_syscall_post_tkill(res, pid, sig) \
+ __sanitizer_syscall_post_impl_tkill(res, (long)(pid), (long)(sig))
+#define __sanitizer_syscall_pre_rt_sigqueueinfo(pid, sig, uinfo) \
+ __sanitizer_syscall_pre_impl_rt_sigqueueinfo((long)(pid), (long)(sig), \
+ (long)(uinfo))
+#define __sanitizer_syscall_post_rt_sigqueueinfo(res, pid, sig, uinfo) \
+ __sanitizer_syscall_post_impl_rt_sigqueueinfo(res, (long)(pid), (long)(sig), \
+ (long)(uinfo))
+#define __sanitizer_syscall_pre_sgetmask() \
+ __sanitizer_syscall_pre_impl_sgetmask()
+#define __sanitizer_syscall_post_sgetmask(res) \
+ __sanitizer_syscall_post_impl_sgetmask(res)
+#define __sanitizer_syscall_pre_ssetmask(newmask) \
+ __sanitizer_syscall_pre_impl_ssetmask((long)(newmask))
+#define __sanitizer_syscall_post_ssetmask(res, newmask) \
+ __sanitizer_syscall_post_impl_ssetmask(res, (long)(newmask))
+#define __sanitizer_syscall_pre_signal(sig, handler) \
+ __sanitizer_syscall_pre_impl_signal((long)(sig), (long)(handler))
+#define __sanitizer_syscall_post_signal(res, sig, handler) \
+ __sanitizer_syscall_post_impl_signal(res, (long)(sig), (long)(handler))
+#define __sanitizer_syscall_pre_pause() __sanitizer_syscall_pre_impl_pause()
+#define __sanitizer_syscall_post_pause(res) \
+ __sanitizer_syscall_post_impl_pause(res)
+#define __sanitizer_syscall_pre_sync() __sanitizer_syscall_pre_impl_sync()
+#define __sanitizer_syscall_post_sync(res) \
+ __sanitizer_syscall_post_impl_sync(res)
+#define __sanitizer_syscall_pre_fsync(fd) \
+ __sanitizer_syscall_pre_impl_fsync((long)(fd))
+#define __sanitizer_syscall_post_fsync(res, fd) \
+ __sanitizer_syscall_post_impl_fsync(res, (long)(fd))
+#define __sanitizer_syscall_pre_fdatasync(fd) \
+ __sanitizer_syscall_pre_impl_fdatasync((long)(fd))
+#define __sanitizer_syscall_post_fdatasync(res, fd) \
+ __sanitizer_syscall_post_impl_fdatasync(res, (long)(fd))
+#define __sanitizer_syscall_pre_bdflush(func, data) \
+ __sanitizer_syscall_pre_impl_bdflush((long)(func), (long)(data))
+#define __sanitizer_syscall_post_bdflush(res, func, data) \
+ __sanitizer_syscall_post_impl_bdflush(res, (long)(func), (long)(data))
+#define __sanitizer_syscall_pre_mount(dev_name, dir_name, type, flags, data) \
+ __sanitizer_syscall_pre_impl_mount((long)(dev_name), (long)(dir_name), \
+ (long)(type), (long)(flags), \
+ (long)(data))
+#define __sanitizer_syscall_post_mount(res, dev_name, dir_name, type, flags, \
+ data) \
+ __sanitizer_syscall_post_impl_mount(res, (long)(dev_name), (long)(dir_name), \
+ (long)(type), (long)(flags), \
+ (long)(data))
+#define __sanitizer_syscall_pre_umount(name, flags) \
+ __sanitizer_syscall_pre_impl_umount((long)(name), (long)(flags))
+#define __sanitizer_syscall_post_umount(res, name, flags) \
+ __sanitizer_syscall_post_impl_umount(res, (long)(name), (long)(flags))
+#define __sanitizer_syscall_pre_oldumount(name) \
+ __sanitizer_syscall_pre_impl_oldumount((long)(name))
+#define __sanitizer_syscall_post_oldumount(res, name) \
+ __sanitizer_syscall_post_impl_oldumount(res, (long)(name))
+#define __sanitizer_syscall_pre_truncate(path, length) \
+ __sanitizer_syscall_pre_impl_truncate((long)(path), (long)(length))
+#define __sanitizer_syscall_post_truncate(res, path, length) \
+ __sanitizer_syscall_post_impl_truncate(res, (long)(path), (long)(length))
+#define __sanitizer_syscall_pre_ftruncate(fd, length) \
+ __sanitizer_syscall_pre_impl_ftruncate((long)(fd), (long)(length))
+#define __sanitizer_syscall_post_ftruncate(res, fd, length) \
+ __sanitizer_syscall_post_impl_ftruncate(res, (long)(fd), (long)(length))
+#define __sanitizer_syscall_pre_stat(filename, statbuf) \
+ __sanitizer_syscall_pre_impl_stat((long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_post_stat(res, filename, statbuf) \
+ __sanitizer_syscall_post_impl_stat(res, (long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_pre_statfs(path, buf) \
+ __sanitizer_syscall_pre_impl_statfs((long)(path), (long)(buf))
+#define __sanitizer_syscall_post_statfs(res, path, buf) \
+ __sanitizer_syscall_post_impl_statfs(res, (long)(path), (long)(buf))
+#define __sanitizer_syscall_pre_statfs64(path, sz, buf) \
+ __sanitizer_syscall_pre_impl_statfs64((long)(path), (long)(sz), (long)(buf))
+#define __sanitizer_syscall_post_statfs64(res, path, sz, buf) \
+ __sanitizer_syscall_post_impl_statfs64(res, (long)(path), (long)(sz), \
+ (long)(buf))
+#define __sanitizer_syscall_pre_fstatfs(fd, buf) \
+ __sanitizer_syscall_pre_impl_fstatfs((long)(fd), (long)(buf))
+#define __sanitizer_syscall_post_fstatfs(res, fd, buf) \
+ __sanitizer_syscall_post_impl_fstatfs(res, (long)(fd), (long)(buf))
+#define __sanitizer_syscall_pre_fstatfs64(fd, sz, buf) \
+ __sanitizer_syscall_pre_impl_fstatfs64((long)(fd), (long)(sz), (long)(buf))
+#define __sanitizer_syscall_post_fstatfs64(res, fd, sz, buf) \
+ __sanitizer_syscall_post_impl_fstatfs64(res, (long)(fd), (long)(sz), \
+ (long)(buf))
+#define __sanitizer_syscall_pre_lstat(filename, statbuf) \
+ __sanitizer_syscall_pre_impl_lstat((long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_post_lstat(res, filename, statbuf) \
+ __sanitizer_syscall_post_impl_lstat(res, (long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_pre_fstat(fd, statbuf) \
+ __sanitizer_syscall_pre_impl_fstat((long)(fd), (long)(statbuf))
+#define __sanitizer_syscall_post_fstat(res, fd, statbuf) \
+ __sanitizer_syscall_post_impl_fstat(res, (long)(fd), (long)(statbuf))
+#define __sanitizer_syscall_pre_newstat(filename, statbuf) \
+ __sanitizer_syscall_pre_impl_newstat((long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_post_newstat(res, filename, statbuf) \
+ __sanitizer_syscall_post_impl_newstat(res, (long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_pre_newlstat(filename, statbuf) \
+ __sanitizer_syscall_pre_impl_newlstat((long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_post_newlstat(res, filename, statbuf) \
+ __sanitizer_syscall_post_impl_newlstat(res, (long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_pre_newfstat(fd, statbuf) \
+ __sanitizer_syscall_pre_impl_newfstat((long)(fd), (long)(statbuf))
+#define __sanitizer_syscall_post_newfstat(res, fd, statbuf) \
+ __sanitizer_syscall_post_impl_newfstat(res, (long)(fd), (long)(statbuf))
+#define __sanitizer_syscall_pre_ustat(dev, ubuf) \
+ __sanitizer_syscall_pre_impl_ustat((long)(dev), (long)(ubuf))
+#define __sanitizer_syscall_post_ustat(res, dev, ubuf) \
+ __sanitizer_syscall_post_impl_ustat(res, (long)(dev), (long)(ubuf))
+#define __sanitizer_syscall_pre_stat64(filename, statbuf) \
+ __sanitizer_syscall_pre_impl_stat64((long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_post_stat64(res, filename, statbuf) \
+ __sanitizer_syscall_post_impl_stat64(res, (long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_pre_fstat64(fd, statbuf) \
+ __sanitizer_syscall_pre_impl_fstat64((long)(fd), (long)(statbuf))
+#define __sanitizer_syscall_post_fstat64(res, fd, statbuf) \
+ __sanitizer_syscall_post_impl_fstat64(res, (long)(fd), (long)(statbuf))
+#define __sanitizer_syscall_pre_lstat64(filename, statbuf) \
+ __sanitizer_syscall_pre_impl_lstat64((long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_post_lstat64(res, filename, statbuf) \
+ __sanitizer_syscall_post_impl_lstat64(res, (long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_pre_setxattr(path, name, value, size, flags) \
+ __sanitizer_syscall_pre_impl_setxattr( \
+ (long)(path), (long)(name), (long)(value), (long)(size), (long)(flags))
+#define __sanitizer_syscall_post_setxattr(res, path, name, value, size, flags) \
+ __sanitizer_syscall_post_impl_setxattr(res, (long)(path), (long)(name), \
+ (long)(value), (long)(size), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_lsetxattr(path, name, value, size, flags) \
+ __sanitizer_syscall_pre_impl_lsetxattr( \
+ (long)(path), (long)(name), (long)(value), (long)(size), (long)(flags))
+#define __sanitizer_syscall_post_lsetxattr(res, path, name, value, size, \
+ flags) \
+ __sanitizer_syscall_post_impl_lsetxattr(res, (long)(path), (long)(name), \
+ (long)(value), (long)(size), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_fsetxattr(fd, name, value, size, flags) \
+ __sanitizer_syscall_pre_impl_fsetxattr( \
+ (long)(fd), (long)(name), (long)(value), (long)(size), (long)(flags))
+#define __sanitizer_syscall_post_fsetxattr(res, fd, name, value, size, flags) \
+ __sanitizer_syscall_post_impl_fsetxattr(res, (long)(fd), (long)(name), \
+ (long)(value), (long)(size), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_getxattr(path, name, value, size) \
+ __sanitizer_syscall_pre_impl_getxattr((long)(path), (long)(name), \
+ (long)(value), (long)(size))
+#define __sanitizer_syscall_post_getxattr(res, path, name, value, size) \
+ __sanitizer_syscall_post_impl_getxattr(res, (long)(path), (long)(name), \
+ (long)(value), (long)(size))
+#define __sanitizer_syscall_pre_lgetxattr(path, name, value, size) \
+ __sanitizer_syscall_pre_impl_lgetxattr((long)(path), (long)(name), \
+ (long)(value), (long)(size))
+#define __sanitizer_syscall_post_lgetxattr(res, path, name, value, size) \
+ __sanitizer_syscall_post_impl_lgetxattr(res, (long)(path), (long)(name), \
+ (long)(value), (long)(size))
+#define __sanitizer_syscall_pre_fgetxattr(fd, name, value, size) \
+ __sanitizer_syscall_pre_impl_fgetxattr((long)(fd), (long)(name), \
+ (long)(value), (long)(size))
+#define __sanitizer_syscall_post_fgetxattr(res, fd, name, value, size) \
+ __sanitizer_syscall_post_impl_fgetxattr(res, (long)(fd), (long)(name), \
+ (long)(value), (long)(size))
+#define __sanitizer_syscall_pre_listxattr(path, list, size) \
+ __sanitizer_syscall_pre_impl_listxattr((long)(path), (long)(list), \
+ (long)(size))
+#define __sanitizer_syscall_post_listxattr(res, path, list, size) \
+ __sanitizer_syscall_post_impl_listxattr(res, (long)(path), (long)(list), \
+ (long)(size))
+#define __sanitizer_syscall_pre_llistxattr(path, list, size) \
+ __sanitizer_syscall_pre_impl_llistxattr((long)(path), (long)(list), \
+ (long)(size))
+#define __sanitizer_syscall_post_llistxattr(res, path, list, size) \
+ __sanitizer_syscall_post_impl_llistxattr(res, (long)(path), (long)(list), \
+ (long)(size))
+#define __sanitizer_syscall_pre_flistxattr(fd, list, size) \
+ __sanitizer_syscall_pre_impl_flistxattr((long)(fd), (long)(list), \
+ (long)(size))
+#define __sanitizer_syscall_post_flistxattr(res, fd, list, size) \
+ __sanitizer_syscall_post_impl_flistxattr(res, (long)(fd), (long)(list), \
+ (long)(size))
+#define __sanitizer_syscall_pre_removexattr(path, name) \
+ __sanitizer_syscall_pre_impl_removexattr((long)(path), (long)(name))
+#define __sanitizer_syscall_post_removexattr(res, path, name) \
+ __sanitizer_syscall_post_impl_removexattr(res, (long)(path), (long)(name))
+#define __sanitizer_syscall_pre_lremovexattr(path, name) \
+ __sanitizer_syscall_pre_impl_lremovexattr((long)(path), (long)(name))
+#define __sanitizer_syscall_post_lremovexattr(res, path, name) \
+ __sanitizer_syscall_post_impl_lremovexattr(res, (long)(path), (long)(name))
+#define __sanitizer_syscall_pre_fremovexattr(fd, name) \
+ __sanitizer_syscall_pre_impl_fremovexattr((long)(fd), (long)(name))
+#define __sanitizer_syscall_post_fremovexattr(res, fd, name) \
+ __sanitizer_syscall_post_impl_fremovexattr(res, (long)(fd), (long)(name))
+#define __sanitizer_syscall_pre_brk(brk) \
+ __sanitizer_syscall_pre_impl_brk((long)(brk))
+#define __sanitizer_syscall_post_brk(res, brk) \
+ __sanitizer_syscall_post_impl_brk(res, (long)(brk))
+#define __sanitizer_syscall_pre_mprotect(start, len, prot) \
+ __sanitizer_syscall_pre_impl_mprotect((long)(start), (long)(len), \
+ (long)(prot))
+#define __sanitizer_syscall_post_mprotect(res, start, len, prot) \
+ __sanitizer_syscall_post_impl_mprotect(res, (long)(start), (long)(len), \
+ (long)(prot))
+#define __sanitizer_syscall_pre_mremap(addr, old_len, new_len, flags, \
+ new_addr) \
+ __sanitizer_syscall_pre_impl_mremap((long)(addr), (long)(old_len), \
+ (long)(new_len), (long)(flags), \
+ (long)(new_addr))
+#define __sanitizer_syscall_post_mremap(res, addr, old_len, new_len, flags, \
+ new_addr) \
+ __sanitizer_syscall_post_impl_mremap(res, (long)(addr), (long)(old_len), \
+ (long)(new_len), (long)(flags), \
+ (long)(new_addr))
+#define __sanitizer_syscall_pre_remap_file_pages(start, size, prot, pgoff, \
+ flags) \
+ __sanitizer_syscall_pre_impl_remap_file_pages( \
+ (long)(start), (long)(size), (long)(prot), (long)(pgoff), (long)(flags))
+#define __sanitizer_syscall_post_remap_file_pages(res, start, size, prot, \
+ pgoff, flags) \
+ __sanitizer_syscall_post_impl_remap_file_pages(res, (long)(start), \
+ (long)(size), (long)(prot), \
+ (long)(pgoff), (long)(flags))
+#define __sanitizer_syscall_pre_msync(start, len, flags) \
+ __sanitizer_syscall_pre_impl_msync((long)(start), (long)(len), (long)(flags))
+#define __sanitizer_syscall_post_msync(res, start, len, flags) \
+ __sanitizer_syscall_post_impl_msync(res, (long)(start), (long)(len), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_munmap(addr, len) \
+ __sanitizer_syscall_pre_impl_munmap((long)(addr), (long)(len))
+#define __sanitizer_syscall_post_munmap(res, addr, len) \
+ __sanitizer_syscall_post_impl_munmap(res, (long)(addr), (long)(len))
+#define __sanitizer_syscall_pre_mlock(start, len) \
+ __sanitizer_syscall_pre_impl_mlock((long)(start), (long)(len))
+#define __sanitizer_syscall_post_mlock(res, start, len) \
+ __sanitizer_syscall_post_impl_mlock(res, (long)(start), (long)(len))
+#define __sanitizer_syscall_pre_munlock(start, len) \
+ __sanitizer_syscall_pre_impl_munlock((long)(start), (long)(len))
+#define __sanitizer_syscall_post_munlock(res, start, len) \
+ __sanitizer_syscall_post_impl_munlock(res, (long)(start), (long)(len))
+#define __sanitizer_syscall_pre_mlockall(flags) \
+ __sanitizer_syscall_pre_impl_mlockall((long)(flags))
+#define __sanitizer_syscall_post_mlockall(res, flags) \
+ __sanitizer_syscall_post_impl_mlockall(res, (long)(flags))
+#define __sanitizer_syscall_pre_munlockall() \
+ __sanitizer_syscall_pre_impl_munlockall()
+#define __sanitizer_syscall_post_munlockall(res) \
+ __sanitizer_syscall_post_impl_munlockall(res)
+#define __sanitizer_syscall_pre_madvise(start, len, behavior) \
+ __sanitizer_syscall_pre_impl_madvise((long)(start), (long)(len), \
+ (long)(behavior))
+#define __sanitizer_syscall_post_madvise(res, start, len, behavior) \
+ __sanitizer_syscall_post_impl_madvise(res, (long)(start), (long)(len), \
+ (long)(behavior))
+#define __sanitizer_syscall_pre_mincore(start, len, vec) \
+ __sanitizer_syscall_pre_impl_mincore((long)(start), (long)(len), (long)(vec))
+#define __sanitizer_syscall_post_mincore(res, start, len, vec) \
+ __sanitizer_syscall_post_impl_mincore(res, (long)(start), (long)(len), \
+ (long)(vec))
+#define __sanitizer_syscall_pre_pivot_root(new_root, put_old) \
+ __sanitizer_syscall_pre_impl_pivot_root((long)(new_root), (long)(put_old))
+#define __sanitizer_syscall_post_pivot_root(res, new_root, put_old) \
+ __sanitizer_syscall_post_impl_pivot_root(res, (long)(new_root), \
+ (long)(put_old))
+#define __sanitizer_syscall_pre_chroot(filename) \
+ __sanitizer_syscall_pre_impl_chroot((long)(filename))
+#define __sanitizer_syscall_post_chroot(res, filename) \
+ __sanitizer_syscall_post_impl_chroot(res, (long)(filename))
+#define __sanitizer_syscall_pre_mknod(filename, mode, dev) \
+ __sanitizer_syscall_pre_impl_mknod((long)(filename), (long)(mode), \
+ (long)(dev))
+#define __sanitizer_syscall_post_mknod(res, filename, mode, dev) \
+ __sanitizer_syscall_post_impl_mknod(res, (long)(filename), (long)(mode), \
+ (long)(dev))
+#define __sanitizer_syscall_pre_link(oldname, newname) \
+ __sanitizer_syscall_pre_impl_link((long)(oldname), (long)(newname))
+#define __sanitizer_syscall_post_link(res, oldname, newname) \
+ __sanitizer_syscall_post_impl_link(res, (long)(oldname), (long)(newname))
+#define __sanitizer_syscall_pre_symlink(old, new_) \
+ __sanitizer_syscall_pre_impl_symlink((long)(old), (long)(new_))
+#define __sanitizer_syscall_post_symlink(res, old, new_) \
+ __sanitizer_syscall_post_impl_symlink(res, (long)(old), (long)(new_))
+#define __sanitizer_syscall_pre_unlink(pathname) \
+ __sanitizer_syscall_pre_impl_unlink((long)(pathname))
+#define __sanitizer_syscall_post_unlink(res, pathname) \
+ __sanitizer_syscall_post_impl_unlink(res, (long)(pathname))
+#define __sanitizer_syscall_pre_rename(oldname, newname) \
+ __sanitizer_syscall_pre_impl_rename((long)(oldname), (long)(newname))
+#define __sanitizer_syscall_post_rename(res, oldname, newname) \
+ __sanitizer_syscall_post_impl_rename(res, (long)(oldname), (long)(newname))
+#define __sanitizer_syscall_pre_chmod(filename, mode) \
+ __sanitizer_syscall_pre_impl_chmod((long)(filename), (long)(mode))
+#define __sanitizer_syscall_post_chmod(res, filename, mode) \
+ __sanitizer_syscall_post_impl_chmod(res, (long)(filename), (long)(mode))
+#define __sanitizer_syscall_pre_fchmod(fd, mode) \
+ __sanitizer_syscall_pre_impl_fchmod((long)(fd), (long)(mode))
+#define __sanitizer_syscall_post_fchmod(res, fd, mode) \
+ __sanitizer_syscall_post_impl_fchmod(res, (long)(fd), (long)(mode))
+#define __sanitizer_syscall_pre_fcntl(fd, cmd, arg) \
+ __sanitizer_syscall_pre_impl_fcntl((long)(fd), (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_post_fcntl(res, fd, cmd, arg) \
+ __sanitizer_syscall_post_impl_fcntl(res, (long)(fd), (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_pre_fcntl64(fd, cmd, arg) \
+ __sanitizer_syscall_pre_impl_fcntl64((long)(fd), (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_post_fcntl64(res, fd, cmd, arg) \
+ __sanitizer_syscall_post_impl_fcntl64(res, (long)(fd), (long)(cmd), \
+ (long)(arg))
+#define __sanitizer_syscall_pre_pipe(fildes) \
+ __sanitizer_syscall_pre_impl_pipe((long)(fildes))
+#define __sanitizer_syscall_post_pipe(res, fildes) \
+ __sanitizer_syscall_post_impl_pipe(res, (long)(fildes))
+#define __sanitizer_syscall_pre_pipe2(fildes, flags) \
+ __sanitizer_syscall_pre_impl_pipe2((long)(fildes), (long)(flags))
+#define __sanitizer_syscall_post_pipe2(res, fildes, flags) \
+ __sanitizer_syscall_post_impl_pipe2(res, (long)(fildes), (long)(flags))
+#define __sanitizer_syscall_pre_dup(fildes) \
+ __sanitizer_syscall_pre_impl_dup((long)(fildes))
+#define __sanitizer_syscall_post_dup(res, fildes) \
+ __sanitizer_syscall_post_impl_dup(res, (long)(fildes))
+#define __sanitizer_syscall_pre_dup2(oldfd, newfd) \
+ __sanitizer_syscall_pre_impl_dup2((long)(oldfd), (long)(newfd))
+#define __sanitizer_syscall_post_dup2(res, oldfd, newfd) \
+ __sanitizer_syscall_post_impl_dup2(res, (long)(oldfd), (long)(newfd))
+#define __sanitizer_syscall_pre_dup3(oldfd, newfd, flags) \
+ __sanitizer_syscall_pre_impl_dup3((long)(oldfd), (long)(newfd), (long)(flags))
+#define __sanitizer_syscall_post_dup3(res, oldfd, newfd, flags) \
+ __sanitizer_syscall_post_impl_dup3(res, (long)(oldfd), (long)(newfd), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_ioperm(from, num, on) \
+ __sanitizer_syscall_pre_impl_ioperm((long)(from), (long)(num), (long)(on))
+#define __sanitizer_syscall_post_ioperm(res, from, num, on) \
+ __sanitizer_syscall_post_impl_ioperm(res, (long)(from), (long)(num), \
+ (long)(on))
+#define __sanitizer_syscall_pre_ioctl(fd, cmd, arg) \
+ __sanitizer_syscall_pre_impl_ioctl((long)(fd), (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_post_ioctl(res, fd, cmd, arg) \
+ __sanitizer_syscall_post_impl_ioctl(res, (long)(fd), (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_pre_flock(fd, cmd) \
+ __sanitizer_syscall_pre_impl_flock((long)(fd), (long)(cmd))
+#define __sanitizer_syscall_post_flock(res, fd, cmd) \
+ __sanitizer_syscall_post_impl_flock(res, (long)(fd), (long)(cmd))
+#define __sanitizer_syscall_pre_io_setup(nr_reqs, ctx) \
+ __sanitizer_syscall_pre_impl_io_setup((long)(nr_reqs), (long)(ctx))
+#define __sanitizer_syscall_post_io_setup(res, nr_reqs, ctx) \
+ __sanitizer_syscall_post_impl_io_setup(res, (long)(nr_reqs), (long)(ctx))
+#define __sanitizer_syscall_pre_io_destroy(ctx) \
+ __sanitizer_syscall_pre_impl_io_destroy((long)(ctx))
+#define __sanitizer_syscall_post_io_destroy(res, ctx) \
+ __sanitizer_syscall_post_impl_io_destroy(res, (long)(ctx))
+#define __sanitizer_syscall_pre_io_getevents(ctx_id, min_nr, nr, events, \
+ timeout) \
+ __sanitizer_syscall_pre_impl_io_getevents((long)(ctx_id), (long)(min_nr), \
+ (long)(nr), (long)(events), \
+ (long)(timeout))
+#define __sanitizer_syscall_post_io_getevents(res, ctx_id, min_nr, nr, events, \
+ timeout) \
+ __sanitizer_syscall_post_impl_io_getevents(res, (long)(ctx_id), \
+ (long)(min_nr), (long)(nr), \
+ (long)(events), (long)(timeout))
+#define __sanitizer_syscall_pre_io_submit(ctx_id, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_io_submit((long)(ctx_id), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_post_io_submit(res, ctx_id, arg1, arg2) \
+ __sanitizer_syscall_post_impl_io_submit(res, (long)(ctx_id), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_io_cancel(ctx_id, iocb, result) \
+ __sanitizer_syscall_pre_impl_io_cancel((long)(ctx_id), (long)(iocb), \
+ (long)(result))
+#define __sanitizer_syscall_post_io_cancel(res, ctx_id, iocb, result) \
+ __sanitizer_syscall_post_impl_io_cancel(res, (long)(ctx_id), (long)(iocb), \
+ (long)(result))
+#define __sanitizer_syscall_pre_sendfile(out_fd, in_fd, offset, count) \
+ __sanitizer_syscall_pre_impl_sendfile((long)(out_fd), (long)(in_fd), \
+ (long)(offset), (long)(count))
+#define __sanitizer_syscall_post_sendfile(res, out_fd, in_fd, offset, count) \
+ __sanitizer_syscall_post_impl_sendfile(res, (long)(out_fd), (long)(in_fd), \
+ (long)(offset), (long)(count))
+#define __sanitizer_syscall_pre_sendfile64(out_fd, in_fd, offset, count) \
+ __sanitizer_syscall_pre_impl_sendfile64((long)(out_fd), (long)(in_fd), \
+ (long)(offset), (long)(count))
+#define __sanitizer_syscall_post_sendfile64(res, out_fd, in_fd, offset, count) \
+ __sanitizer_syscall_post_impl_sendfile64(res, (long)(out_fd), (long)(in_fd), \
+ (long)(offset), (long)(count))
+#define __sanitizer_syscall_pre_readlink(path, buf, bufsiz) \
+ __sanitizer_syscall_pre_impl_readlink((long)(path), (long)(buf), \
+ (long)(bufsiz))
+#define __sanitizer_syscall_post_readlink(res, path, buf, bufsiz) \
+ __sanitizer_syscall_post_impl_readlink(res, (long)(path), (long)(buf), \
+ (long)(bufsiz))
+#define __sanitizer_syscall_pre_creat(pathname, mode) \
+ __sanitizer_syscall_pre_impl_creat((long)(pathname), (long)(mode))
+#define __sanitizer_syscall_post_creat(res, pathname, mode) \
+ __sanitizer_syscall_post_impl_creat(res, (long)(pathname), (long)(mode))
+#define __sanitizer_syscall_pre_open(filename, flags, mode) \
+ __sanitizer_syscall_pre_impl_open((long)(filename), (long)(flags), \
+ (long)(mode))
+#define __sanitizer_syscall_post_open(res, filename, flags, mode) \
+ __sanitizer_syscall_post_impl_open(res, (long)(filename), (long)(flags), \
+ (long)(mode))
+#define __sanitizer_syscall_pre_close(fd) \
+ __sanitizer_syscall_pre_impl_close((long)(fd))
+#define __sanitizer_syscall_post_close(res, fd) \
+ __sanitizer_syscall_post_impl_close(res, (long)(fd))
+#define __sanitizer_syscall_pre_access(filename, mode) \
+ __sanitizer_syscall_pre_impl_access((long)(filename), (long)(mode))
+#define __sanitizer_syscall_post_access(res, filename, mode) \
+ __sanitizer_syscall_post_impl_access(res, (long)(filename), (long)(mode))
+#define __sanitizer_syscall_pre_vhangup() __sanitizer_syscall_pre_impl_vhangup()
+#define __sanitizer_syscall_post_vhangup(res) \
+ __sanitizer_syscall_post_impl_vhangup(res)
+#define __sanitizer_syscall_pre_chown(filename, user, group) \
+ __sanitizer_syscall_pre_impl_chown((long)(filename), (long)(user), \
+ (long)(group))
+#define __sanitizer_syscall_post_chown(res, filename, user, group) \
+ __sanitizer_syscall_post_impl_chown(res, (long)(filename), (long)(user), \
+ (long)(group))
+#define __sanitizer_syscall_pre_lchown(filename, user, group) \
+ __sanitizer_syscall_pre_impl_lchown((long)(filename), (long)(user), \
+ (long)(group))
+#define __sanitizer_syscall_post_lchown(res, filename, user, group) \
+ __sanitizer_syscall_post_impl_lchown(res, (long)(filename), (long)(user), \
+ (long)(group))
+#define __sanitizer_syscall_pre_fchown(fd, user, group) \
+ __sanitizer_syscall_pre_impl_fchown((long)(fd), (long)(user), (long)(group))
+#define __sanitizer_syscall_post_fchown(res, fd, user, group) \
+ __sanitizer_syscall_post_impl_fchown(res, (long)(fd), (long)(user), \
+ (long)(group))
+#define __sanitizer_syscall_pre_chown16(filename, user, group) \
+ __sanitizer_syscall_pre_impl_chown16((long)(filename), (long)user, \
+ (long)group)
+#define __sanitizer_syscall_post_chown16(res, filename, user, group) \
+ __sanitizer_syscall_post_impl_chown16(res, (long)(filename), (long)user, \
+ (long)group)
+#define __sanitizer_syscall_pre_lchown16(filename, user, group) \
+ __sanitizer_syscall_pre_impl_lchown16((long)(filename), (long)user, \
+ (long)group)
+#define __sanitizer_syscall_post_lchown16(res, filename, user, group) \
+ __sanitizer_syscall_post_impl_lchown16(res, (long)(filename), (long)user, \
+ (long)group)
+#define __sanitizer_syscall_pre_fchown16(fd, user, group) \
+ __sanitizer_syscall_pre_impl_fchown16((long)(fd), (long)user, (long)group)
+#define __sanitizer_syscall_post_fchown16(res, fd, user, group) \
+ __sanitizer_syscall_post_impl_fchown16(res, (long)(fd), (long)user, \
+ (long)group)
+#define __sanitizer_syscall_pre_setregid16(rgid, egid) \
+ __sanitizer_syscall_pre_impl_setregid16((long)rgid, (long)egid)
+#define __sanitizer_syscall_post_setregid16(res, rgid, egid) \
+ __sanitizer_syscall_post_impl_setregid16(res, (long)rgid, (long)egid)
+#define __sanitizer_syscall_pre_setgid16(gid) \
+ __sanitizer_syscall_pre_impl_setgid16((long)gid)
+#define __sanitizer_syscall_post_setgid16(res, gid) \
+ __sanitizer_syscall_post_impl_setgid16(res, (long)gid)
+#define __sanitizer_syscall_pre_setreuid16(ruid, euid) \
+ __sanitizer_syscall_pre_impl_setreuid16((long)ruid, (long)euid)
+#define __sanitizer_syscall_post_setreuid16(res, ruid, euid) \
+ __sanitizer_syscall_post_impl_setreuid16(res, (long)ruid, (long)euid)
+#define __sanitizer_syscall_pre_setuid16(uid) \
+ __sanitizer_syscall_pre_impl_setuid16((long)uid)
+#define __sanitizer_syscall_post_setuid16(res, uid) \
+ __sanitizer_syscall_post_impl_setuid16(res, (long)uid)
+#define __sanitizer_syscall_pre_setresuid16(ruid, euid, suid) \
+ __sanitizer_syscall_pre_impl_setresuid16((long)ruid, (long)euid, (long)suid)
+#define __sanitizer_syscall_post_setresuid16(res, ruid, euid, suid) \
+ __sanitizer_syscall_post_impl_setresuid16(res, (long)ruid, (long)euid, \
+ (long)suid)
+#define __sanitizer_syscall_pre_getresuid16(ruid, euid, suid) \
+ __sanitizer_syscall_pre_impl_getresuid16((long)(ruid), (long)(euid), \
+ (long)(suid))
+#define __sanitizer_syscall_post_getresuid16(res, ruid, euid, suid) \
+ __sanitizer_syscall_post_impl_getresuid16(res, (long)(ruid), (long)(euid), \
+ (long)(suid))
+#define __sanitizer_syscall_pre_setresgid16(rgid, egid, sgid) \
+ __sanitizer_syscall_pre_impl_setresgid16((long)rgid, (long)egid, (long)sgid)
+#define __sanitizer_syscall_post_setresgid16(res, rgid, egid, sgid) \
+ __sanitizer_syscall_post_impl_setresgid16(res, (long)rgid, (long)egid, \
+ (long)sgid)
+#define __sanitizer_syscall_pre_getresgid16(rgid, egid, sgid) \
+ __sanitizer_syscall_pre_impl_getresgid16((long)(rgid), (long)(egid), \
+ (long)(sgid))
+#define __sanitizer_syscall_post_getresgid16(res, rgid, egid, sgid) \
+ __sanitizer_syscall_post_impl_getresgid16(res, (long)(rgid), (long)(egid), \
+ (long)(sgid))
+#define __sanitizer_syscall_pre_setfsuid16(uid) \
+ __sanitizer_syscall_pre_impl_setfsuid16((long)uid)
+#define __sanitizer_syscall_post_setfsuid16(res, uid) \
+ __sanitizer_syscall_post_impl_setfsuid16(res, (long)uid)
+#define __sanitizer_syscall_pre_setfsgid16(gid) \
+ __sanitizer_syscall_pre_impl_setfsgid16((long)gid)
+#define __sanitizer_syscall_post_setfsgid16(res, gid) \
+ __sanitizer_syscall_post_impl_setfsgid16(res, (long)gid)
+#define __sanitizer_syscall_pre_getgroups16(gidsetsize, grouplist) \
+ __sanitizer_syscall_pre_impl_getgroups16((long)(gidsetsize), \
+ (long)(grouplist))
+#define __sanitizer_syscall_post_getgroups16(res, gidsetsize, grouplist) \
+ __sanitizer_syscall_post_impl_getgroups16(res, (long)(gidsetsize), \
+ (long)(grouplist))
+#define __sanitizer_syscall_pre_setgroups16(gidsetsize, grouplist) \
+ __sanitizer_syscall_pre_impl_setgroups16((long)(gidsetsize), \
+ (long)(grouplist))
+#define __sanitizer_syscall_post_setgroups16(res, gidsetsize, grouplist) \
+ __sanitizer_syscall_post_impl_setgroups16(res, (long)(gidsetsize), \
+ (long)(grouplist))
+#define __sanitizer_syscall_pre_getuid16() \
+ __sanitizer_syscall_pre_impl_getuid16()
+#define __sanitizer_syscall_post_getuid16(res) \
+ __sanitizer_syscall_post_impl_getuid16(res)
+#define __sanitizer_syscall_pre_geteuid16() \
+ __sanitizer_syscall_pre_impl_geteuid16()
+#define __sanitizer_syscall_post_geteuid16(res) \
+ __sanitizer_syscall_post_impl_geteuid16(res)
+#define __sanitizer_syscall_pre_getgid16() \
+ __sanitizer_syscall_pre_impl_getgid16()
+#define __sanitizer_syscall_post_getgid16(res) \
+ __sanitizer_syscall_post_impl_getgid16(res)
+#define __sanitizer_syscall_pre_getegid16() \
+ __sanitizer_syscall_pre_impl_getegid16()
+#define __sanitizer_syscall_post_getegid16(res) \
+ __sanitizer_syscall_post_impl_getegid16(res)
+#define __sanitizer_syscall_pre_utime(filename, times) \
+ __sanitizer_syscall_pre_impl_utime((long)(filename), (long)(times))
+#define __sanitizer_syscall_post_utime(res, filename, times) \
+ __sanitizer_syscall_post_impl_utime(res, (long)(filename), (long)(times))
+#define __sanitizer_syscall_pre_utimes(filename, utimes) \
+ __sanitizer_syscall_pre_impl_utimes((long)(filename), (long)(utimes))
+#define __sanitizer_syscall_post_utimes(res, filename, utimes) \
+ __sanitizer_syscall_post_impl_utimes(res, (long)(filename), (long)(utimes))
+#define __sanitizer_syscall_pre_lseek(fd, offset, origin) \
+ __sanitizer_syscall_pre_impl_lseek((long)(fd), (long)(offset), (long)(origin))
+#define __sanitizer_syscall_post_lseek(res, fd, offset, origin) \
+ __sanitizer_syscall_post_impl_lseek(res, (long)(fd), (long)(offset), \
+ (long)(origin))
+#define __sanitizer_syscall_pre_llseek(fd, offset_high, offset_low, result, \
+ origin) \
+ __sanitizer_syscall_pre_impl_llseek((long)(fd), (long)(offset_high), \
+ (long)(offset_low), (long)(result), \
+ (long)(origin))
+#define __sanitizer_syscall_post_llseek(res, fd, offset_high, offset_low, \
+ result, origin) \
+ __sanitizer_syscall_post_impl_llseek(res, (long)(fd), (long)(offset_high), \
+ (long)(offset_low), (long)(result), \
+ (long)(origin))
+#define __sanitizer_syscall_pre_read(fd, buf, count) \
+ __sanitizer_syscall_pre_impl_read((long)(fd), (long)(buf), (long)(count))
+#define __sanitizer_syscall_post_read(res, fd, buf, count) \
+ __sanitizer_syscall_post_impl_read(res, (long)(fd), (long)(buf), \
+ (long)(count))
+#define __sanitizer_syscall_pre_readv(fd, vec, vlen) \
+ __sanitizer_syscall_pre_impl_readv((long)(fd), (long)(vec), (long)(vlen))
+#define __sanitizer_syscall_post_readv(res, fd, vec, vlen) \
+ __sanitizer_syscall_post_impl_readv(res, (long)(fd), (long)(vec), \
+ (long)(vlen))
+#define __sanitizer_syscall_pre_write(fd, buf, count) \
+ __sanitizer_syscall_pre_impl_write((long)(fd), (long)(buf), (long)(count))
+#define __sanitizer_syscall_post_write(res, fd, buf, count) \
+ __sanitizer_syscall_post_impl_write(res, (long)(fd), (long)(buf), \
+ (long)(count))
+#define __sanitizer_syscall_pre_writev(fd, vec, vlen) \
+ __sanitizer_syscall_pre_impl_writev((long)(fd), (long)(vec), (long)(vlen))
+#define __sanitizer_syscall_post_writev(res, fd, vec, vlen) \
+ __sanitizer_syscall_post_impl_writev(res, (long)(fd), (long)(vec), \
+ (long)(vlen))
+
+#ifdef _LP64
+#define __sanitizer_syscall_pre_pread64(fd, buf, count, pos) \
+ __sanitizer_syscall_pre_impl_pread64((long)(fd), (long)(buf), (long)(count), \
+ (long)(pos))
+#define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos) \
+ __sanitizer_syscall_post_impl_pread64(res, (long)(fd), (long)(buf), \
+ (long)(count), (long)(pos))
+#define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos) \
+ __sanitizer_syscall_pre_impl_pwrite64((long)(fd), (long)(buf), \
+ (long)(count), (long)(pos))
+#define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos) \
+ __sanitizer_syscall_post_impl_pwrite64(res, (long)(fd), (long)(buf), \
+ (long)(count), (long)(pos))
+#else
+#define __sanitizer_syscall_pre_pread64(fd, buf, count, pos0, pos1) \
+ __sanitizer_syscall_pre_impl_pread64((long)(fd), (long)(buf), (long)(count), \
+ (long)(pos0), (long)(pos1))
+#define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos0, pos1) \
+ __sanitizer_syscall_post_impl_pread64( \
+ res, (long)(fd), (long)(buf), (long)(count), (long)(pos0), (long)(pos1))
+#define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos0, pos1) \
+ __sanitizer_syscall_pre_impl_pwrite64( \
+ (long)(fd), (long)(buf), (long)(count), (long)(pos0), (long)(pos1))
+#define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos0, pos1) \
+ __sanitizer_syscall_post_impl_pwrite64( \
+ res, (long)(fd), (long)(buf), (long)(count), (long)(pos0), (long)(pos1))
+#endif
+
+#define __sanitizer_syscall_pre_preadv(fd, vec, vlen, pos_l, pos_h) \
+ __sanitizer_syscall_pre_impl_preadv((long)(fd), (long)(vec), (long)(vlen), \
+ (long)(pos_l), (long)(pos_h))
+#define __sanitizer_syscall_post_preadv(res, fd, vec, vlen, pos_l, pos_h) \
+ __sanitizer_syscall_post_impl_preadv(res, (long)(fd), (long)(vec), \
+ (long)(vlen), (long)(pos_l), \
+ (long)(pos_h))
+#define __sanitizer_syscall_pre_pwritev(fd, vec, vlen, pos_l, pos_h) \
+ __sanitizer_syscall_pre_impl_pwritev((long)(fd), (long)(vec), (long)(vlen), \
+ (long)(pos_l), (long)(pos_h))
+#define __sanitizer_syscall_post_pwritev(res, fd, vec, vlen, pos_l, pos_h) \
+ __sanitizer_syscall_post_impl_pwritev(res, (long)(fd), (long)(vec), \
+ (long)(vlen), (long)(pos_l), \
+ (long)(pos_h))
+#define __sanitizer_syscall_pre_getcwd(buf, size) \
+ __sanitizer_syscall_pre_impl_getcwd((long)(buf), (long)(size))
+#define __sanitizer_syscall_post_getcwd(res, buf, size) \
+ __sanitizer_syscall_post_impl_getcwd(res, (long)(buf), (long)(size))
+#define __sanitizer_syscall_pre_mkdir(pathname, mode) \
+ __sanitizer_syscall_pre_impl_mkdir((long)(pathname), (long)(mode))
+#define __sanitizer_syscall_post_mkdir(res, pathname, mode) \
+ __sanitizer_syscall_post_impl_mkdir(res, (long)(pathname), (long)(mode))
+#define __sanitizer_syscall_pre_chdir(filename) \
+ __sanitizer_syscall_pre_impl_chdir((long)(filename))
+#define __sanitizer_syscall_post_chdir(res, filename) \
+ __sanitizer_syscall_post_impl_chdir(res, (long)(filename))
+#define __sanitizer_syscall_pre_fchdir(fd) \
+ __sanitizer_syscall_pre_impl_fchdir((long)(fd))
+#define __sanitizer_syscall_post_fchdir(res, fd) \
+ __sanitizer_syscall_post_impl_fchdir(res, (long)(fd))
+#define __sanitizer_syscall_pre_rmdir(pathname) \
+ __sanitizer_syscall_pre_impl_rmdir((long)(pathname))
+#define __sanitizer_syscall_post_rmdir(res, pathname) \
+ __sanitizer_syscall_post_impl_rmdir(res, (long)(pathname))
+#define __sanitizer_syscall_pre_lookup_dcookie(cookie64, buf, len) \
+ __sanitizer_syscall_pre_impl_lookup_dcookie((long)(cookie64), (long)(buf), \
+ (long)(len))
+#define __sanitizer_syscall_post_lookup_dcookie(res, cookie64, buf, len) \
+ __sanitizer_syscall_post_impl_lookup_dcookie(res, (long)(cookie64), \
+ (long)(buf), (long)(len))
+#define __sanitizer_syscall_pre_quotactl(cmd, special, id, addr) \
+ __sanitizer_syscall_pre_impl_quotactl((long)(cmd), (long)(special), \
+ (long)(id), (long)(addr))
+#define __sanitizer_syscall_post_quotactl(res, cmd, special, id, addr) \
+ __sanitizer_syscall_post_impl_quotactl(res, (long)(cmd), (long)(special), \
+ (long)(id), (long)(addr))
+#define __sanitizer_syscall_pre_getdents(fd, dirent, count) \
+ __sanitizer_syscall_pre_impl_getdents((long)(fd), (long)(dirent), \
+ (long)(count))
+#define __sanitizer_syscall_post_getdents(res, fd, dirent, count) \
+ __sanitizer_syscall_post_impl_getdents(res, (long)(fd), (long)(dirent), \
+ (long)(count))
+#define __sanitizer_syscall_pre_getdents64(fd, dirent, count) \
+ __sanitizer_syscall_pre_impl_getdents64((long)(fd), (long)(dirent), \
+ (long)(count))
+#define __sanitizer_syscall_post_getdents64(res, fd, dirent, count) \
+ __sanitizer_syscall_post_impl_getdents64(res, (long)(fd), (long)(dirent), \
+ (long)(count))
+#define __sanitizer_syscall_pre_setsockopt(fd, level, optname, optval, optlen) \
+ __sanitizer_syscall_pre_impl_setsockopt((long)(fd), (long)(level), \
+ (long)(optname), (long)(optval), \
+ (long)(optlen))
+#define __sanitizer_syscall_post_setsockopt(res, fd, level, optname, optval, \
+ optlen) \
+ __sanitizer_syscall_post_impl_setsockopt(res, (long)(fd), (long)(level), \
+ (long)(optname), (long)(optval), \
+ (long)(optlen))
+#define __sanitizer_syscall_pre_getsockopt(fd, level, optname, optval, optlen) \
+ __sanitizer_syscall_pre_impl_getsockopt((long)(fd), (long)(level), \
+ (long)(optname), (long)(optval), \
+ (long)(optlen))
+#define __sanitizer_syscall_post_getsockopt(res, fd, level, optname, optval, \
+ optlen) \
+ __sanitizer_syscall_post_impl_getsockopt(res, (long)(fd), (long)(level), \
+ (long)(optname), (long)(optval), \
+ (long)(optlen))
+#define __sanitizer_syscall_pre_bind(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_bind((long)(arg0), (long)(arg1), (long)(arg2))
+#define __sanitizer_syscall_post_bind(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_bind(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_connect(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_connect((long)(arg0), (long)(arg1), (long)(arg2))
+#define __sanitizer_syscall_post_connect(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_connect(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_accept(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_accept((long)(arg0), (long)(arg1), (long)(arg2))
+#define __sanitizer_syscall_post_accept(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_accept(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_accept4(arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_pre_impl_accept4((long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3))
+#define __sanitizer_syscall_post_accept4(res, arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_post_impl_accept4(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3))
+#define __sanitizer_syscall_pre_getsockname(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_getsockname((long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_post_getsockname(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_getsockname(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_getpeername(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_getpeername((long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_post_getpeername(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_getpeername(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_send(arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_pre_impl_send((long)(arg0), (long)(arg1), (long)(arg2), \
+ (long)(arg3))
+#define __sanitizer_syscall_post_send(res, arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_post_impl_send(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3))
+#define __sanitizer_syscall_pre_sendto(arg0, arg1, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_pre_impl_sendto((long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_post_sendto(res, arg0, arg1, arg2, arg3, arg4, \
+ arg5) \
+ __sanitizer_syscall_post_impl_sendto(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_pre_sendmsg(fd, msg, flags) \
+ __sanitizer_syscall_pre_impl_sendmsg((long)(fd), (long)(msg), (long)(flags))
+#define __sanitizer_syscall_post_sendmsg(res, fd, msg, flags) \
+ __sanitizer_syscall_post_impl_sendmsg(res, (long)(fd), (long)(msg), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_sendmmsg(fd, msg, vlen, flags) \
+ __sanitizer_syscall_pre_impl_sendmmsg((long)(fd), (long)(msg), (long)(vlen), \
+ (long)(flags))
+#define __sanitizer_syscall_post_sendmmsg(res, fd, msg, vlen, flags) \
+ __sanitizer_syscall_post_impl_sendmmsg(res, (long)(fd), (long)(msg), \
+ (long)(vlen), (long)(flags))
+#define __sanitizer_syscall_pre_recv(arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_pre_impl_recv((long)(arg0), (long)(arg1), (long)(arg2), \
+ (long)(arg3))
+#define __sanitizer_syscall_post_recv(res, arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_post_impl_recv(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3))
+#define __sanitizer_syscall_pre_recvfrom(arg0, arg1, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_pre_impl_recvfrom((long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_post_recvfrom(res, arg0, arg1, arg2, arg3, arg4, \
+ arg5) \
+ __sanitizer_syscall_post_impl_recvfrom(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_pre_recvmsg(fd, msg, flags) \
+ __sanitizer_syscall_pre_impl_recvmsg((long)(fd), (long)(msg), (long)(flags))
+#define __sanitizer_syscall_post_recvmsg(res, fd, msg, flags) \
+ __sanitizer_syscall_post_impl_recvmsg(res, (long)(fd), (long)(msg), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_recvmmsg(fd, msg, vlen, flags, timeout) \
+ __sanitizer_syscall_pre_impl_recvmmsg((long)(fd), (long)(msg), (long)(vlen), \
+ (long)(flags), (long)(timeout))
+#define __sanitizer_syscall_post_recvmmsg(res, fd, msg, vlen, flags, timeout) \
+ __sanitizer_syscall_post_impl_recvmmsg(res, (long)(fd), (long)(msg), \
+ (long)(vlen), (long)(flags), \
+ (long)(timeout))
+#define __sanitizer_syscall_pre_socket(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_socket((long)(arg0), (long)(arg1), (long)(arg2))
+#define __sanitizer_syscall_post_socket(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_socket(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_socketpair(arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_pre_impl_socketpair((long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3))
+#define __sanitizer_syscall_post_socketpair(res, arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_post_impl_socketpair(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3))
+#define __sanitizer_syscall_pre_socketcall(call, args) \
+ __sanitizer_syscall_pre_impl_socketcall((long)(call), (long)(args))
+#define __sanitizer_syscall_post_socketcall(res, call, args) \
+ __sanitizer_syscall_post_impl_socketcall(res, (long)(call), (long)(args))
+#define __sanitizer_syscall_pre_listen(arg0, arg1) \
+ __sanitizer_syscall_pre_impl_listen((long)(arg0), (long)(arg1))
+#define __sanitizer_syscall_post_listen(res, arg0, arg1) \
+ __sanitizer_syscall_post_impl_listen(res, (long)(arg0), (long)(arg1))
+#define __sanitizer_syscall_pre_poll(ufds, nfds, timeout) \
+ __sanitizer_syscall_pre_impl_poll((long)(ufds), (long)(nfds), (long)(timeout))
+#define __sanitizer_syscall_post_poll(res, ufds, nfds, timeout) \
+ __sanitizer_syscall_post_impl_poll(res, (long)(ufds), (long)(nfds), \
+ (long)(timeout))
+#define __sanitizer_syscall_pre_select(n, inp, outp, exp, tvp) \
+ __sanitizer_syscall_pre_impl_select((long)(n), (long)(inp), (long)(outp), \
+ (long)(exp), (long)(tvp))
+#define __sanitizer_syscall_post_select(res, n, inp, outp, exp, tvp) \
+ __sanitizer_syscall_post_impl_select(res, (long)(n), (long)(inp), \
+ (long)(outp), (long)(exp), (long)(tvp))
+#define __sanitizer_syscall_pre_old_select(arg) \
+ __sanitizer_syscall_pre_impl_old_select((long)(arg))
+#define __sanitizer_syscall_post_old_select(res, arg) \
+ __sanitizer_syscall_post_impl_old_select(res, (long)(arg))
+#define __sanitizer_syscall_pre_epoll_create(size) \
+ __sanitizer_syscall_pre_impl_epoll_create((long)(size))
+#define __sanitizer_syscall_post_epoll_create(res, size) \
+ __sanitizer_syscall_post_impl_epoll_create(res, (long)(size))
+#define __sanitizer_syscall_pre_epoll_create1(flags) \
+ __sanitizer_syscall_pre_impl_epoll_create1((long)(flags))
+#define __sanitizer_syscall_post_epoll_create1(res, flags) \
+ __sanitizer_syscall_post_impl_epoll_create1(res, (long)(flags))
+#define __sanitizer_syscall_pre_epoll_ctl(epfd, op, fd, event) \
+ __sanitizer_syscall_pre_impl_epoll_ctl((long)(epfd), (long)(op), (long)(fd), \
+ (long)(event))
+#define __sanitizer_syscall_post_epoll_ctl(res, epfd, op, fd, event) \
+ __sanitizer_syscall_post_impl_epoll_ctl(res, (long)(epfd), (long)(op), \
+ (long)(fd), (long)(event))
+#define __sanitizer_syscall_pre_epoll_wait(epfd, events, maxevents, timeout) \
+ __sanitizer_syscall_pre_impl_epoll_wait((long)(epfd), (long)(events), \
+ (long)(maxevents), (long)(timeout))
+#define __sanitizer_syscall_post_epoll_wait(res, epfd, events, maxevents, \
+ timeout) \
+ __sanitizer_syscall_post_impl_epoll_wait(res, (long)(epfd), (long)(events), \
+ (long)(maxevents), (long)(timeout))
+#define __sanitizer_syscall_pre_epoll_pwait(epfd, events, maxevents, timeout, \
+ sigmask, sigsetsize) \
+ __sanitizer_syscall_pre_impl_epoll_pwait( \
+ (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \
+ (long)(sigmask), (long)(sigsetsize))
+#define __sanitizer_syscall_post_epoll_pwait(res, epfd, events, maxevents, \
+ timeout, sigmask, sigsetsize) \
+ __sanitizer_syscall_post_impl_epoll_pwait( \
+ res, (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \
+ (long)(sigmask), (long)(sigsetsize))
+#define __sanitizer_syscall_pre_epoll_pwait2(epfd, events, maxevents, timeout, \
+ sigmask, sigsetsize) \
+ __sanitizer_syscall_pre_impl_epoll_pwait2( \
+ (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \
+ (long)(sigmask), (long)(sigsetsize))
+#define __sanitizer_syscall_post_epoll_pwait2(res, epfd, events, maxevents, \
+ timeout, sigmask, sigsetsize) \
+ __sanitizer_syscall_post_impl_epoll_pwait2( \
+ res, (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \
+ (long)(sigmask), (long)(sigsetsize))
+#define __sanitizer_syscall_pre_gethostname(name, len) \
+ __sanitizer_syscall_pre_impl_gethostname((long)(name), (long)(len))
+#define __sanitizer_syscall_post_gethostname(res, name, len) \
+ __sanitizer_syscall_post_impl_gethostname(res, (long)(name), (long)(len))
+#define __sanitizer_syscall_pre_sethostname(name, len) \
+ __sanitizer_syscall_pre_impl_sethostname((long)(name), (long)(len))
+#define __sanitizer_syscall_post_sethostname(res, name, len) \
+ __sanitizer_syscall_post_impl_sethostname(res, (long)(name), (long)(len))
+#define __sanitizer_syscall_pre_setdomainname(name, len) \
+ __sanitizer_syscall_pre_impl_setdomainname((long)(name), (long)(len))
+#define __sanitizer_syscall_post_setdomainname(res, name, len) \
+ __sanitizer_syscall_post_impl_setdomainname(res, (long)(name), (long)(len))
+#define __sanitizer_syscall_pre_newuname(name) \
+ __sanitizer_syscall_pre_impl_newuname((long)(name))
+#define __sanitizer_syscall_post_newuname(res, name) \
+ __sanitizer_syscall_post_impl_newuname(res, (long)(name))
+#define __sanitizer_syscall_pre_uname(arg0) \
+ __sanitizer_syscall_pre_impl_uname((long)(arg0))
+#define __sanitizer_syscall_post_uname(res, arg0) \
+ __sanitizer_syscall_post_impl_uname(res, (long)(arg0))
+#define __sanitizer_syscall_pre_olduname(arg0) \
+ __sanitizer_syscall_pre_impl_olduname((long)(arg0))
+#define __sanitizer_syscall_post_olduname(res, arg0) \
+ __sanitizer_syscall_post_impl_olduname(res, (long)(arg0))
+#define __sanitizer_syscall_pre_getrlimit(resource, rlim) \
+ __sanitizer_syscall_pre_impl_getrlimit((long)(resource), (long)(rlim))
+#define __sanitizer_syscall_post_getrlimit(res, resource, rlim) \
+ __sanitizer_syscall_post_impl_getrlimit(res, (long)(resource), (long)(rlim))
+#define __sanitizer_syscall_pre_old_getrlimit(resource, rlim) \
+ __sanitizer_syscall_pre_impl_old_getrlimit((long)(resource), (long)(rlim))
+#define __sanitizer_syscall_post_old_getrlimit(res, resource, rlim) \
+ __sanitizer_syscall_post_impl_old_getrlimit(res, (long)(resource), \
+ (long)(rlim))
+#define __sanitizer_syscall_pre_setrlimit(resource, rlim) \
+ __sanitizer_syscall_pre_impl_setrlimit((long)(resource), (long)(rlim))
+#define __sanitizer_syscall_post_setrlimit(res, resource, rlim) \
+ __sanitizer_syscall_post_impl_setrlimit(res, (long)(resource), (long)(rlim))
+#define __sanitizer_syscall_pre_prlimit64(pid, resource, new_rlim, old_rlim) \
+ __sanitizer_syscall_pre_impl_prlimit64((long)(pid), (long)(resource), \
+ (long)(new_rlim), (long)(old_rlim))
+#define __sanitizer_syscall_post_prlimit64(res, pid, resource, new_rlim, \
+ old_rlim) \
+ __sanitizer_syscall_post_impl_prlimit64(res, (long)(pid), (long)(resource), \
+ (long)(new_rlim), (long)(old_rlim))
+#define __sanitizer_syscall_pre_getrusage(who, ru) \
+ __sanitizer_syscall_pre_impl_getrusage((long)(who), (long)(ru))
+#define __sanitizer_syscall_post_getrusage(res, who, ru) \
+ __sanitizer_syscall_post_impl_getrusage(res, (long)(who), (long)(ru))
+#define __sanitizer_syscall_pre_umask(mask) \
+ __sanitizer_syscall_pre_impl_umask((long)(mask))
+#define __sanitizer_syscall_post_umask(res, mask) \
+ __sanitizer_syscall_post_impl_umask(res, (long)(mask))
+#define __sanitizer_syscall_pre_msgget(key, msgflg) \
+ __sanitizer_syscall_pre_impl_msgget((long)(key), (long)(msgflg))
+#define __sanitizer_syscall_post_msgget(res, key, msgflg) \
+ __sanitizer_syscall_post_impl_msgget(res, (long)(key), (long)(msgflg))
+#define __sanitizer_syscall_pre_msgsnd(msqid, msgp, msgsz, msgflg) \
+ __sanitizer_syscall_pre_impl_msgsnd((long)(msqid), (long)(msgp), \
+ (long)(msgsz), (long)(msgflg))
+#define __sanitizer_syscall_post_msgsnd(res, msqid, msgp, msgsz, msgflg) \
+ __sanitizer_syscall_post_impl_msgsnd(res, (long)(msqid), (long)(msgp), \
+ (long)(msgsz), (long)(msgflg))
+#define __sanitizer_syscall_pre_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) \
+ __sanitizer_syscall_pre_impl_msgrcv((long)(msqid), (long)(msgp), \
+ (long)(msgsz), (long)(msgtyp), \
+ (long)(msgflg))
+#define __sanitizer_syscall_post_msgrcv(res, msqid, msgp, msgsz, msgtyp, \
+ msgflg) \
+ __sanitizer_syscall_post_impl_msgrcv(res, (long)(msqid), (long)(msgp), \
+ (long)(msgsz), (long)(msgtyp), \
+ (long)(msgflg))
+#define __sanitizer_syscall_pre_msgctl(msqid, cmd, buf) \
+ __sanitizer_syscall_pre_impl_msgctl((long)(msqid), (long)(cmd), (long)(buf))
+#define __sanitizer_syscall_post_msgctl(res, msqid, cmd, buf) \
+ __sanitizer_syscall_post_impl_msgctl(res, (long)(msqid), (long)(cmd), \
+ (long)(buf))
+#define __sanitizer_syscall_pre_semget(key, nsems, semflg) \
+ __sanitizer_syscall_pre_impl_semget((long)(key), (long)(nsems), \
+ (long)(semflg))
+#define __sanitizer_syscall_post_semget(res, key, nsems, semflg) \
+ __sanitizer_syscall_post_impl_semget(res, (long)(key), (long)(nsems), \
+ (long)(semflg))
+#define __sanitizer_syscall_pre_semop(semid, sops, nsops) \
+ __sanitizer_syscall_pre_impl_semop((long)(semid), (long)(sops), (long)(nsops))
+#define __sanitizer_syscall_post_semop(res, semid, sops, nsops) \
+ __sanitizer_syscall_post_impl_semop(res, (long)(semid), (long)(sops), \
+ (long)(nsops))
+#define __sanitizer_syscall_pre_semctl(semid, semnum, cmd, arg) \
+ __sanitizer_syscall_pre_impl_semctl((long)(semid), (long)(semnum), \
+ (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_post_semctl(res, semid, semnum, cmd, arg) \
+ __sanitizer_syscall_post_impl_semctl(res, (long)(semid), (long)(semnum), \
+ (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_pre_semtimedop(semid, sops, nsops, timeout) \
+ __sanitizer_syscall_pre_impl_semtimedop((long)(semid), (long)(sops), \
+ (long)(nsops), (long)(timeout))
+#define __sanitizer_syscall_post_semtimedop(res, semid, sops, nsops, timeout) \
+ __sanitizer_syscall_post_impl_semtimedop(res, (long)(semid), (long)(sops), \
+ (long)(nsops), (long)(timeout))
+#define __sanitizer_syscall_pre_shmat(shmid, shmaddr, shmflg) \
+ __sanitizer_syscall_pre_impl_shmat((long)(shmid), (long)(shmaddr), \
+ (long)(shmflg))
+#define __sanitizer_syscall_post_shmat(res, shmid, shmaddr, shmflg) \
+ __sanitizer_syscall_post_impl_shmat(res, (long)(shmid), (long)(shmaddr), \
+ (long)(shmflg))
+#define __sanitizer_syscall_pre_shmget(key, size, flag) \
+ __sanitizer_syscall_pre_impl_shmget((long)(key), (long)(size), (long)(flag))
+#define __sanitizer_syscall_post_shmget(res, key, size, flag) \
+ __sanitizer_syscall_post_impl_shmget(res, (long)(key), (long)(size), \
+ (long)(flag))
+#define __sanitizer_syscall_pre_shmdt(shmaddr) \
+ __sanitizer_syscall_pre_impl_shmdt((long)(shmaddr))
+#define __sanitizer_syscall_post_shmdt(res, shmaddr) \
+ __sanitizer_syscall_post_impl_shmdt(res, (long)(shmaddr))
+#define __sanitizer_syscall_pre_shmctl(shmid, cmd, buf) \
+ __sanitizer_syscall_pre_impl_shmctl((long)(shmid), (long)(cmd), (long)(buf))
+#define __sanitizer_syscall_post_shmctl(res, shmid, cmd, buf) \
+ __sanitizer_syscall_post_impl_shmctl(res, (long)(shmid), (long)(cmd), \
+ (long)(buf))
+#define __sanitizer_syscall_pre_ipc(call, first, second, third, ptr, fifth) \
+ __sanitizer_syscall_pre_impl_ipc((long)(call), (long)(first), \
+ (long)(second), (long)(third), (long)(ptr), \
+ (long)(fifth))
+#define __sanitizer_syscall_post_ipc(res, call, first, second, third, ptr, \
+ fifth) \
+ __sanitizer_syscall_post_impl_ipc(res, (long)(call), (long)(first), \
+ (long)(second), (long)(third), \
+ (long)(ptr), (long)(fifth))
+#define __sanitizer_syscall_pre_mq_open(name, oflag, mode, attr) \
+ __sanitizer_syscall_pre_impl_mq_open((long)(name), (long)(oflag), \
+ (long)(mode), (long)(attr))
+#define __sanitizer_syscall_post_mq_open(res, name, oflag, mode, attr) \
+ __sanitizer_syscall_post_impl_mq_open(res, (long)(name), (long)(oflag), \
+ (long)(mode), (long)(attr))
+#define __sanitizer_syscall_pre_mq_unlink(name) \
+ __sanitizer_syscall_pre_impl_mq_unlink((long)(name))
+#define __sanitizer_syscall_post_mq_unlink(res, name) \
+ __sanitizer_syscall_post_impl_mq_unlink(res, (long)(name))
+#define __sanitizer_syscall_pre_mq_timedsend(mqdes, msg_ptr, msg_len, \
+ msg_prio, abs_timeout) \
+ __sanitizer_syscall_pre_impl_mq_timedsend((long)(mqdes), (long)(msg_ptr), \
+ (long)(msg_len), (long)(msg_prio), \
+ (long)(abs_timeout))
+#define __sanitizer_syscall_post_mq_timedsend(res, mqdes, msg_ptr, msg_len, \
+ msg_prio, abs_timeout) \
+ __sanitizer_syscall_post_impl_mq_timedsend( \
+ res, (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \
+ (long)(abs_timeout))
+#define __sanitizer_syscall_pre_mq_timedreceive(mqdes, msg_ptr, msg_len, \
+ msg_prio, abs_timeout) \
+ __sanitizer_syscall_pre_impl_mq_timedreceive( \
+ (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \
+ (long)(abs_timeout))
+#define __sanitizer_syscall_post_mq_timedreceive(res, mqdes, msg_ptr, msg_len, \
+ msg_prio, abs_timeout) \
+ __sanitizer_syscall_post_impl_mq_timedreceive( \
+ res, (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \
+ (long)(abs_timeout))
+#define __sanitizer_syscall_pre_mq_notify(mqdes, notification) \
+ __sanitizer_syscall_pre_impl_mq_notify((long)(mqdes), (long)(notification))
+#define __sanitizer_syscall_post_mq_notify(res, mqdes, notification) \
+ __sanitizer_syscall_post_impl_mq_notify(res, (long)(mqdes), \
+ (long)(notification))
+#define __sanitizer_syscall_pre_mq_getsetattr(mqdes, mqstat, omqstat) \
+ __sanitizer_syscall_pre_impl_mq_getsetattr((long)(mqdes), (long)(mqstat), \
+ (long)(omqstat))
+#define __sanitizer_syscall_post_mq_getsetattr(res, mqdes, mqstat, omqstat) \
+ __sanitizer_syscall_post_impl_mq_getsetattr(res, (long)(mqdes), \
+ (long)(mqstat), (long)(omqstat))
+#define __sanitizer_syscall_pre_pciconfig_iobase(which, bus, devfn) \
+ __sanitizer_syscall_pre_impl_pciconfig_iobase((long)(which), (long)(bus), \
+ (long)(devfn))
+#define __sanitizer_syscall_post_pciconfig_iobase(res, which, bus, devfn) \
+ __sanitizer_syscall_post_impl_pciconfig_iobase(res, (long)(which), \
+ (long)(bus), (long)(devfn))
+#define __sanitizer_syscall_pre_pciconfig_read(bus, dfn, off, len, buf) \
+ __sanitizer_syscall_pre_impl_pciconfig_read( \
+ (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf))
+#define __sanitizer_syscall_post_pciconfig_read(res, bus, dfn, off, len, buf) \
+ __sanitizer_syscall_post_impl_pciconfig_read( \
+ res, (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf))
+#define __sanitizer_syscall_pre_pciconfig_write(bus, dfn, off, len, buf) \
+ __sanitizer_syscall_pre_impl_pciconfig_write( \
+ (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf))
+#define __sanitizer_syscall_post_pciconfig_write(res, bus, dfn, off, len, buf) \
+ __sanitizer_syscall_post_impl_pciconfig_write( \
+ res, (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf))
+#define __sanitizer_syscall_pre_swapon(specialfile, swap_flags) \
+ __sanitizer_syscall_pre_impl_swapon((long)(specialfile), (long)(swap_flags))
+#define __sanitizer_syscall_post_swapon(res, specialfile, swap_flags) \
+ __sanitizer_syscall_post_impl_swapon(res, (long)(specialfile), \
+ (long)(swap_flags))
+#define __sanitizer_syscall_pre_swapoff(specialfile) \
+ __sanitizer_syscall_pre_impl_swapoff((long)(specialfile))
+#define __sanitizer_syscall_post_swapoff(res, specialfile) \
+ __sanitizer_syscall_post_impl_swapoff(res, (long)(specialfile))
+#define __sanitizer_syscall_pre_sysctl(args) \
+ __sanitizer_syscall_pre_impl_sysctl((long)(args))
+#define __sanitizer_syscall_post_sysctl(res, args) \
+ __sanitizer_syscall_post_impl_sysctl(res, (long)(args))
+#define __sanitizer_syscall_pre_sysinfo(info) \
+ __sanitizer_syscall_pre_impl_sysinfo((long)(info))
+#define __sanitizer_syscall_post_sysinfo(res, info) \
+ __sanitizer_syscall_post_impl_sysinfo(res, (long)(info))
+#define __sanitizer_syscall_pre_sysfs(option, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_sysfs((long)(option), (long)(arg1), (long)(arg2))
+#define __sanitizer_syscall_post_sysfs(res, option, arg1, arg2) \
+ __sanitizer_syscall_post_impl_sysfs(res, (long)(option), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_syslog(type, buf, len) \
+ __sanitizer_syscall_pre_impl_syslog((long)(type), (long)(buf), (long)(len))
+#define __sanitizer_syscall_post_syslog(res, type, buf, len) \
+ __sanitizer_syscall_post_impl_syslog(res, (long)(type), (long)(buf), \
+ (long)(len))
+#define __sanitizer_syscall_pre_uselib(library) \
+ __sanitizer_syscall_pre_impl_uselib((long)(library))
+#define __sanitizer_syscall_post_uselib(res, library) \
+ __sanitizer_syscall_post_impl_uselib(res, (long)(library))
+#define __sanitizer_syscall_pre_ni_syscall() \
+ __sanitizer_syscall_pre_impl_ni_syscall()
+#define __sanitizer_syscall_post_ni_syscall(res) \
+ __sanitizer_syscall_post_impl_ni_syscall(res)
+#define __sanitizer_syscall_pre_ptrace(request, pid, addr, data) \
+ __sanitizer_syscall_pre_impl_ptrace((long)(request), (long)(pid), \
+ (long)(addr), (long)(data))
+#define __sanitizer_syscall_post_ptrace(res, request, pid, addr, data) \
+ __sanitizer_syscall_post_impl_ptrace(res, (long)(request), (long)(pid), \
+ (long)(addr), (long)(data))
+#define __sanitizer_syscall_pre_add_key(_type, _description, _payload, plen, \
+ destringid) \
+ __sanitizer_syscall_pre_impl_add_key((long)(_type), (long)(_description), \
+ (long)(_payload), (long)(plen), \
+ (long)(destringid))
+#define __sanitizer_syscall_post_add_key(res, _type, _description, _payload, \
+ plen, destringid) \
+ __sanitizer_syscall_post_impl_add_key( \
+ res, (long)(_type), (long)(_description), (long)(_payload), \
+ (long)(plen), (long)(destringid))
+#define __sanitizer_syscall_pre_request_key(_type, _description, \
+ _callout_info, destringid) \
+ __sanitizer_syscall_pre_impl_request_key( \
+ (long)(_type), (long)(_description), (long)(_callout_info), \
+ (long)(destringid))
+#define __sanitizer_syscall_post_request_key(res, _type, _description, \
+ _callout_info, destringid) \
+ __sanitizer_syscall_post_impl_request_key( \
+ res, (long)(_type), (long)(_description), (long)(_callout_info), \
+ (long)(destringid))
+#define __sanitizer_syscall_pre_keyctl(cmd, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_pre_impl_keyctl((long)(cmd), (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_post_keyctl(res, cmd, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_post_impl_keyctl(res, (long)(cmd), (long)(arg2), \
+ (long)(arg3), (long)(arg4), \
+ (long)(arg5))
+#define __sanitizer_syscall_pre_ioprio_set(which, who, ioprio) \
+ __sanitizer_syscall_pre_impl_ioprio_set((long)(which), (long)(who), \
+ (long)(ioprio))
+#define __sanitizer_syscall_post_ioprio_set(res, which, who, ioprio) \
+ __sanitizer_syscall_post_impl_ioprio_set(res, (long)(which), (long)(who), \
+ (long)(ioprio))
+#define __sanitizer_syscall_pre_ioprio_get(which, who) \
+ __sanitizer_syscall_pre_impl_ioprio_get((long)(which), (long)(who))
+#define __sanitizer_syscall_post_ioprio_get(res, which, who) \
+ __sanitizer_syscall_post_impl_ioprio_get(res, (long)(which), (long)(who))
+#define __sanitizer_syscall_pre_set_mempolicy(mode, nmask, maxnode) \
+ __sanitizer_syscall_pre_impl_set_mempolicy((long)(mode), (long)(nmask), \
+ (long)(maxnode))
+#define __sanitizer_syscall_post_set_mempolicy(res, mode, nmask, maxnode) \
+ __sanitizer_syscall_post_impl_set_mempolicy(res, (long)(mode), \
+ (long)(nmask), (long)(maxnode))
+#define __sanitizer_syscall_pre_migrate_pages(pid, maxnode, from, to) \
+ __sanitizer_syscall_pre_impl_migrate_pages((long)(pid), (long)(maxnode), \
+ (long)(from), (long)(to))
+#define __sanitizer_syscall_post_migrate_pages(res, pid, maxnode, from, to) \
+ __sanitizer_syscall_post_impl_migrate_pages( \
+ res, (long)(pid), (long)(maxnode), (long)(from), (long)(to))
+#define __sanitizer_syscall_pre_move_pages(pid, nr_pages, pages, nodes, \
+ status, flags) \
+ __sanitizer_syscall_pre_impl_move_pages((long)(pid), (long)(nr_pages), \
+ (long)(pages), (long)(nodes), \
+ (long)(status), (long)(flags))
+#define __sanitizer_syscall_post_move_pages(res, pid, nr_pages, pages, nodes, \
+ status, flags) \
+ __sanitizer_syscall_post_impl_move_pages(res, (long)(pid), (long)(nr_pages), \
+ (long)(pages), (long)(nodes), \
+ (long)(status), (long)(flags))
+#define __sanitizer_syscall_pre_mbind(start, len, mode, nmask, maxnode, flags) \
+ __sanitizer_syscall_pre_impl_mbind((long)(start), (long)(len), (long)(mode), \
+ (long)(nmask), (long)(maxnode), \
+ (long)(flags))
+#define __sanitizer_syscall_post_mbind(res, start, len, mode, nmask, maxnode, \
+ flags) \
+ __sanitizer_syscall_post_impl_mbind(res, (long)(start), (long)(len), \
+ (long)(mode), (long)(nmask), \
+ (long)(maxnode), (long)(flags))
+#define __sanitizer_syscall_pre_get_mempolicy(policy, nmask, maxnode, addr, \
+ flags) \
+ __sanitizer_syscall_pre_impl_get_mempolicy((long)(policy), (long)(nmask), \
+ (long)(maxnode), (long)(addr), \
+ (long)(flags))
+#define __sanitizer_syscall_post_get_mempolicy(res, policy, nmask, maxnode, \
+ addr, flags) \
+ __sanitizer_syscall_post_impl_get_mempolicy(res, (long)(policy), \
+ (long)(nmask), (long)(maxnode), \
+ (long)(addr), (long)(flags))
+#define __sanitizer_syscall_pre_inotify_init() \
+ __sanitizer_syscall_pre_impl_inotify_init()
+#define __sanitizer_syscall_post_inotify_init(res) \
+ __sanitizer_syscall_post_impl_inotify_init(res)
+#define __sanitizer_syscall_pre_inotify_init1(flags) \
+ __sanitizer_syscall_pre_impl_inotify_init1((long)(flags))
+#define __sanitizer_syscall_post_inotify_init1(res, flags) \
+ __sanitizer_syscall_post_impl_inotify_init1(res, (long)(flags))
+#define __sanitizer_syscall_pre_inotify_add_watch(fd, path, mask) \
+ __sanitizer_syscall_pre_impl_inotify_add_watch((long)(fd), (long)(path), \
+ (long)(mask))
+#define __sanitizer_syscall_post_inotify_add_watch(res, fd, path, mask) \
+ __sanitizer_syscall_post_impl_inotify_add_watch(res, (long)(fd), \
+ (long)(path), (long)(mask))
+#define __sanitizer_syscall_pre_inotify_rm_watch(fd, wd) \
+ __sanitizer_syscall_pre_impl_inotify_rm_watch((long)(fd), (long)(wd))
+#define __sanitizer_syscall_post_inotify_rm_watch(res, fd, wd) \
+ __sanitizer_syscall_post_impl_inotify_rm_watch(res, (long)(fd), (long)(wd))
+#define __sanitizer_syscall_pre_spu_run(fd, unpc, ustatus) \
+ __sanitizer_syscall_pre_impl_spu_run((long)(fd), (long)(unpc), \
+ (long)(ustatus))
+#define __sanitizer_syscall_post_spu_run(res, fd, unpc, ustatus) \
+ __sanitizer_syscall_post_impl_spu_run(res, (long)(fd), (long)(unpc), \
+ (long)(ustatus))
+#define __sanitizer_syscall_pre_spu_create(name, flags, mode, fd) \
+ __sanitizer_syscall_pre_impl_spu_create((long)(name), (long)(flags), \
+ (long)(mode), (long)(fd))
+#define __sanitizer_syscall_post_spu_create(res, name, flags, mode, fd) \
+ __sanitizer_syscall_post_impl_spu_create(res, (long)(name), (long)(flags), \
+ (long)(mode), (long)(fd))
+#define __sanitizer_syscall_pre_mknodat(dfd, filename, mode, dev) \
+ __sanitizer_syscall_pre_impl_mknodat((long)(dfd), (long)(filename), \
+ (long)(mode), (long)(dev))
+#define __sanitizer_syscall_post_mknodat(res, dfd, filename, mode, dev) \
+ __sanitizer_syscall_post_impl_mknodat(res, (long)(dfd), (long)(filename), \
+ (long)(mode), (long)(dev))
+#define __sanitizer_syscall_pre_mkdirat(dfd, pathname, mode) \
+ __sanitizer_syscall_pre_impl_mkdirat((long)(dfd), (long)(pathname), \
+ (long)(mode))
+#define __sanitizer_syscall_post_mkdirat(res, dfd, pathname, mode) \
+ __sanitizer_syscall_post_impl_mkdirat(res, (long)(dfd), (long)(pathname), \
+ (long)(mode))
+#define __sanitizer_syscall_pre_unlinkat(dfd, pathname, flag) \
+ __sanitizer_syscall_pre_impl_unlinkat((long)(dfd), (long)(pathname), \
+ (long)(flag))
+#define __sanitizer_syscall_post_unlinkat(res, dfd, pathname, flag) \
+ __sanitizer_syscall_post_impl_unlinkat(res, (long)(dfd), (long)(pathname), \
+ (long)(flag))
+#define __sanitizer_syscall_pre_symlinkat(oldname, newdfd, newname) \
+ __sanitizer_syscall_pre_impl_symlinkat((long)(oldname), (long)(newdfd), \
+ (long)(newname))
+#define __sanitizer_syscall_post_symlinkat(res, oldname, newdfd, newname) \
+ __sanitizer_syscall_post_impl_symlinkat(res, (long)(oldname), \
+ (long)(newdfd), (long)(newname))
+#define __sanitizer_syscall_pre_linkat(olddfd, oldname, newdfd, newname, \
+ flags) \
+ __sanitizer_syscall_pre_impl_linkat((long)(olddfd), (long)(oldname), \
+ (long)(newdfd), (long)(newname), \
+ (long)(flags))
+#define __sanitizer_syscall_post_linkat(res, olddfd, oldname, newdfd, newname, \
+ flags) \
+ __sanitizer_syscall_post_impl_linkat(res, (long)(olddfd), (long)(oldname), \
+ (long)(newdfd), (long)(newname), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_renameat(olddfd, oldname, newdfd, newname) \
+ __sanitizer_syscall_pre_impl_renameat((long)(olddfd), (long)(oldname), \
+ (long)(newdfd), (long)(newname))
+#define __sanitizer_syscall_post_renameat(res, olddfd, oldname, newdfd, \
+ newname) \
+ __sanitizer_syscall_post_impl_renameat(res, (long)(olddfd), (long)(oldname), \
+ (long)(newdfd), (long)(newname))
+#define __sanitizer_syscall_pre_futimesat(dfd, filename, utimes) \
+ __sanitizer_syscall_pre_impl_futimesat((long)(dfd), (long)(filename), \
+ (long)(utimes))
+#define __sanitizer_syscall_post_futimesat(res, dfd, filename, utimes) \
+ __sanitizer_syscall_post_impl_futimesat(res, (long)(dfd), (long)(filename), \
+ (long)(utimes))
+#define __sanitizer_syscall_pre_faccessat(dfd, filename, mode) \
+ __sanitizer_syscall_pre_impl_faccessat((long)(dfd), (long)(filename), \
+ (long)(mode))
+#define __sanitizer_syscall_post_faccessat(res, dfd, filename, mode) \
+ __sanitizer_syscall_post_impl_faccessat(res, (long)(dfd), (long)(filename), \
+ (long)(mode))
+#define __sanitizer_syscall_pre_fchmodat(dfd, filename, mode) \
+ __sanitizer_syscall_pre_impl_fchmodat((long)(dfd), (long)(filename), \
+ (long)(mode))
+#define __sanitizer_syscall_post_fchmodat(res, dfd, filename, mode) \
+ __sanitizer_syscall_post_impl_fchmodat(res, (long)(dfd), (long)(filename), \
+ (long)(mode))
+#define __sanitizer_syscall_pre_fchownat(dfd, filename, user, group, flag) \
+ __sanitizer_syscall_pre_impl_fchownat((long)(dfd), (long)(filename), \
+ (long)(user), (long)(group), \
+ (long)(flag))
+#define __sanitizer_syscall_post_fchownat(res, dfd, filename, user, group, \
+ flag) \
+ __sanitizer_syscall_post_impl_fchownat(res, (long)(dfd), (long)(filename), \
+ (long)(user), (long)(group), \
+ (long)(flag))
+#define __sanitizer_syscall_pre_openat(dfd, filename, flags, mode) \
+ __sanitizer_syscall_pre_impl_openat((long)(dfd), (long)(filename), \
+ (long)(flags), (long)(mode))
+#define __sanitizer_syscall_post_openat(res, dfd, filename, flags, mode) \
+ __sanitizer_syscall_post_impl_openat(res, (long)(dfd), (long)(filename), \
+ (long)(flags), (long)(mode))
+#define __sanitizer_syscall_pre_newfstatat(dfd, filename, statbuf, flag) \
+ __sanitizer_syscall_pre_impl_newfstatat((long)(dfd), (long)(filename), \
+ (long)(statbuf), (long)(flag))
+#define __sanitizer_syscall_post_newfstatat(res, dfd, filename, statbuf, flag) \
+ __sanitizer_syscall_post_impl_newfstatat(res, (long)(dfd), (long)(filename), \
+ (long)(statbuf), (long)(flag))
+#define __sanitizer_syscall_pre_fstatat64(dfd, filename, statbuf, flag) \
+ __sanitizer_syscall_pre_impl_fstatat64((long)(dfd), (long)(filename), \
+ (long)(statbuf), (long)(flag))
+#define __sanitizer_syscall_post_fstatat64(res, dfd, filename, statbuf, flag) \
+ __sanitizer_syscall_post_impl_fstatat64(res, (long)(dfd), (long)(filename), \
+ (long)(statbuf), (long)(flag))
+#define __sanitizer_syscall_pre_readlinkat(dfd, path, buf, bufsiz) \
+ __sanitizer_syscall_pre_impl_readlinkat((long)(dfd), (long)(path), \
+ (long)(buf), (long)(bufsiz))
+#define __sanitizer_syscall_post_readlinkat(res, dfd, path, buf, bufsiz) \
+ __sanitizer_syscall_post_impl_readlinkat(res, (long)(dfd), (long)(path), \
+ (long)(buf), (long)(bufsiz))
+#define __sanitizer_syscall_pre_utimensat(dfd, filename, utimes, flags) \
+ __sanitizer_syscall_pre_impl_utimensat((long)(dfd), (long)(filename), \
+ (long)(utimes), (long)(flags))
+#define __sanitizer_syscall_post_utimensat(res, dfd, filename, utimes, flags) \
+ __sanitizer_syscall_post_impl_utimensat(res, (long)(dfd), (long)(filename), \
+ (long)(utimes), (long)(flags))
+#define __sanitizer_syscall_pre_unshare(unshare_flags) \
+ __sanitizer_syscall_pre_impl_unshare((long)(unshare_flags))
+#define __sanitizer_syscall_post_unshare(res, unshare_flags) \
+ __sanitizer_syscall_post_impl_unshare(res, (long)(unshare_flags))
+#define __sanitizer_syscall_pre_splice(fd_in, off_in, fd_out, off_out, len, \
+ flags) \
+ __sanitizer_syscall_pre_impl_splice((long)(fd_in), (long)(off_in), \
+ (long)(fd_out), (long)(off_out), \
+ (long)(len), (long)(flags))
+#define __sanitizer_syscall_post_splice(res, fd_in, off_in, fd_out, off_out, \
+ len, flags) \
+ __sanitizer_syscall_post_impl_splice(res, (long)(fd_in), (long)(off_in), \
+ (long)(fd_out), (long)(off_out), \
+ (long)(len), (long)(flags))
+#define __sanitizer_syscall_pre_vmsplice(fd, iov, nr_segs, flags) \
+ __sanitizer_syscall_pre_impl_vmsplice((long)(fd), (long)(iov), \
+ (long)(nr_segs), (long)(flags))
+#define __sanitizer_syscall_post_vmsplice(res, fd, iov, nr_segs, flags) \
+ __sanitizer_syscall_post_impl_vmsplice(res, (long)(fd), (long)(iov), \
+ (long)(nr_segs), (long)(flags))
+#define __sanitizer_syscall_pre_tee(fdin, fdout, len, flags) \
+ __sanitizer_syscall_pre_impl_tee((long)(fdin), (long)(fdout), (long)(len), \
+ (long)(flags))
+#define __sanitizer_syscall_post_tee(res, fdin, fdout, len, flags) \
+ __sanitizer_syscall_post_impl_tee(res, (long)(fdin), (long)(fdout), \
+ (long)(len), (long)(flags))
+#define __sanitizer_syscall_pre_get_robust_list(pid, head_ptr, len_ptr) \
+ __sanitizer_syscall_pre_impl_get_robust_list((long)(pid), (long)(head_ptr), \
+ (long)(len_ptr))
+#define __sanitizer_syscall_post_get_robust_list(res, pid, head_ptr, len_ptr) \
+ __sanitizer_syscall_post_impl_get_robust_list( \
+ res, (long)(pid), (long)(head_ptr), (long)(len_ptr))
+#define __sanitizer_syscall_pre_set_robust_list(head, len) \
+ __sanitizer_syscall_pre_impl_set_robust_list((long)(head), (long)(len))
+#define __sanitizer_syscall_post_set_robust_list(res, head, len) \
+ __sanitizer_syscall_post_impl_set_robust_list(res, (long)(head), (long)(len))
+#define __sanitizer_syscall_pre_getcpu(cpu, node, cache) \
+ __sanitizer_syscall_pre_impl_getcpu((long)(cpu), (long)(node), (long)(cache))
+#define __sanitizer_syscall_post_getcpu(res, cpu, node, cache) \
+ __sanitizer_syscall_post_impl_getcpu(res, (long)(cpu), (long)(node), \
+ (long)(cache))
+#define __sanitizer_syscall_pre_signalfd(ufd, user_mask, sizemask) \
+ __sanitizer_syscall_pre_impl_signalfd((long)(ufd), (long)(user_mask), \
+ (long)(sizemask))
+#define __sanitizer_syscall_post_signalfd(res, ufd, user_mask, sizemask) \
+ __sanitizer_syscall_post_impl_signalfd(res, (long)(ufd), (long)(user_mask), \
+ (long)(sizemask))
+#define __sanitizer_syscall_pre_signalfd4(ufd, user_mask, sizemask, flags) \
+ __sanitizer_syscall_pre_impl_signalfd4((long)(ufd), (long)(user_mask), \
+ (long)(sizemask), (long)(flags))
+#define __sanitizer_syscall_post_signalfd4(res, ufd, user_mask, sizemask, \
+ flags) \
+ __sanitizer_syscall_post_impl_signalfd4(res, (long)(ufd), (long)(user_mask), \
+ (long)(sizemask), (long)(flags))
+#define __sanitizer_syscall_pre_timerfd_create(clockid, flags) \
+ __sanitizer_syscall_pre_impl_timerfd_create((long)(clockid), (long)(flags))
+#define __sanitizer_syscall_post_timerfd_create(res, clockid, flags) \
+ __sanitizer_syscall_post_impl_timerfd_create(res, (long)(clockid), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_timerfd_settime(ufd, flags, utmr, otmr) \
+ __sanitizer_syscall_pre_impl_timerfd_settime((long)(ufd), (long)(flags), \
+ (long)(utmr), (long)(otmr))
+#define __sanitizer_syscall_post_timerfd_settime(res, ufd, flags, utmr, otmr) \
+ __sanitizer_syscall_post_impl_timerfd_settime( \
+ res, (long)(ufd), (long)(flags), (long)(utmr), (long)(otmr))
+#define __sanitizer_syscall_pre_timerfd_gettime(ufd, otmr) \
+ __sanitizer_syscall_pre_impl_timerfd_gettime((long)(ufd), (long)(otmr))
+#define __sanitizer_syscall_post_timerfd_gettime(res, ufd, otmr) \
+ __sanitizer_syscall_post_impl_timerfd_gettime(res, (long)(ufd), (long)(otmr))
+#define __sanitizer_syscall_pre_eventfd(count) \
+ __sanitizer_syscall_pre_impl_eventfd((long)(count))
+#define __sanitizer_syscall_post_eventfd(res, count) \
+ __sanitizer_syscall_post_impl_eventfd(res, (long)(count))
+#define __sanitizer_syscall_pre_eventfd2(count, flags) \
+ __sanitizer_syscall_pre_impl_eventfd2((long)(count), (long)(flags))
+#define __sanitizer_syscall_post_eventfd2(res, count, flags) \
+ __sanitizer_syscall_post_impl_eventfd2(res, (long)(count), (long)(flags))
+#define __sanitizer_syscall_pre_old_readdir(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_old_readdir((long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_post_old_readdir(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_old_readdir(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_pselect6(arg0, arg1, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_pre_impl_pselect6((long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_post_pselect6(res, arg0, arg1, arg2, arg3, arg4, \
+ arg5) \
+ __sanitizer_syscall_post_impl_pselect6(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_pre_ppoll(arg0, arg1, arg2, arg3, arg4) \
+ __sanitizer_syscall_pre_impl_ppoll((long)(arg0), (long)(arg1), (long)(arg2), \
+ (long)(arg3), (long)(arg4))
+#define __sanitizer_syscall_post_ppoll(res, arg0, arg1, arg2, arg3, arg4) \
+ __sanitizer_syscall_post_impl_ppoll(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4))
+#define __sanitizer_syscall_pre_syncfs(fd) \
+ __sanitizer_syscall_pre_impl_syncfs((long)(fd))
+#define __sanitizer_syscall_post_syncfs(res, fd) \
+ __sanitizer_syscall_post_impl_syncfs(res, (long)(fd))
+#define __sanitizer_syscall_pre_perf_event_open(attr_uptr, pid, cpu, group_fd, \
+ flags) \
+ __sanitizer_syscall_pre_impl_perf_event_open((long)(attr_uptr), (long)(pid), \
+ (long)(cpu), (long)(group_fd), \
+ (long)(flags))
+#define __sanitizer_syscall_post_perf_event_open(res, attr_uptr, pid, cpu, \
+ group_fd, flags) \
+ __sanitizer_syscall_post_impl_perf_event_open( \
+ res, (long)(attr_uptr), (long)(pid), (long)(cpu), (long)(group_fd), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_mmap_pgoff(addr, len, prot, flags, fd, pgoff) \
+ __sanitizer_syscall_pre_impl_mmap_pgoff((long)(addr), (long)(len), \
+ (long)(prot), (long)(flags), \
+ (long)(fd), (long)(pgoff))
+#define __sanitizer_syscall_post_mmap_pgoff(res, addr, len, prot, flags, fd, \
+ pgoff) \
+ __sanitizer_syscall_post_impl_mmap_pgoff(res, (long)(addr), (long)(len), \
+ (long)(prot), (long)(flags), \
+ (long)(fd), (long)(pgoff))
+#define __sanitizer_syscall_pre_old_mmap(arg) \
+ __sanitizer_syscall_pre_impl_old_mmap((long)(arg))
+#define __sanitizer_syscall_post_old_mmap(res, arg) \
+ __sanitizer_syscall_post_impl_old_mmap(res, (long)(arg))
+#define __sanitizer_syscall_pre_name_to_handle_at(dfd, name, handle, mnt_id, \
+ flag) \
+ __sanitizer_syscall_pre_impl_name_to_handle_at( \
+ (long)(dfd), (long)(name), (long)(handle), (long)(mnt_id), (long)(flag))
+#define __sanitizer_syscall_post_name_to_handle_at(res, dfd, name, handle, \
+ mnt_id, flag) \
+ __sanitizer_syscall_post_impl_name_to_handle_at( \
+ res, (long)(dfd), (long)(name), (long)(handle), (long)(mnt_id), \
+ (long)(flag))
+#define __sanitizer_syscall_pre_open_by_handle_at(mountdirfd, handle, flags) \
+ __sanitizer_syscall_pre_impl_open_by_handle_at( \
+ (long)(mountdirfd), (long)(handle), (long)(flags))
+#define __sanitizer_syscall_post_open_by_handle_at(res, mountdirfd, handle, \
+ flags) \
+ __sanitizer_syscall_post_impl_open_by_handle_at( \
+ res, (long)(mountdirfd), (long)(handle), (long)(flags))
+#define __sanitizer_syscall_pre_setns(fd, nstype) \
+ __sanitizer_syscall_pre_impl_setns((long)(fd), (long)(nstype))
+#define __sanitizer_syscall_post_setns(res, fd, nstype) \
+ __sanitizer_syscall_post_impl_setns(res, (long)(fd), (long)(nstype))
+#define __sanitizer_syscall_pre_process_vm_readv(pid, lvec, liovcnt, rvec, \
+ riovcnt, flags) \
+ __sanitizer_syscall_pre_impl_process_vm_readv( \
+ (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
+ (long)(riovcnt), (long)(flags))
+#define __sanitizer_syscall_post_process_vm_readv(res, pid, lvec, liovcnt, \
+ rvec, riovcnt, flags) \
+ __sanitizer_syscall_post_impl_process_vm_readv( \
+ res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
+ (long)(riovcnt), (long)(flags))
+#define __sanitizer_syscall_pre_process_vm_writev(pid, lvec, liovcnt, rvec, \
+ riovcnt, flags) \
+ __sanitizer_syscall_pre_impl_process_vm_writev( \
+ (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
+ (long)(riovcnt), (long)(flags))
+#define __sanitizer_syscall_post_process_vm_writev(res, pid, lvec, liovcnt, \
+ rvec, riovcnt, flags) \
+ __sanitizer_syscall_post_impl_process_vm_writev( \
+ res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
+ (long)(riovcnt), (long)(flags))
+#define __sanitizer_syscall_pre_fork() __sanitizer_syscall_pre_impl_fork()
+#define __sanitizer_syscall_post_fork(res) \
+ __sanitizer_syscall_post_impl_fork(res)
+#define __sanitizer_syscall_pre_vfork() __sanitizer_syscall_pre_impl_vfork()
+#define __sanitizer_syscall_post_vfork(res) \
+ __sanitizer_syscall_post_impl_vfork(res)
+#define __sanitizer_syscall_pre_sigaction(signum, act, oldact) \
+ __sanitizer_syscall_pre_impl_sigaction((long)signum, (long)act, (long)oldact)
+#define __sanitizer_syscall_post_sigaction(res, signum, act, oldact) \
+ __sanitizer_syscall_post_impl_sigaction(res, (long)signum, (long)act, \
+ (long)oldact)
+#define __sanitizer_syscall_pre_rt_sigaction(signum, act, oldact, sz) \
+ __sanitizer_syscall_pre_impl_rt_sigaction((long)signum, (long)act, \
+ (long)oldact, (long)sz)
+#define __sanitizer_syscall_post_rt_sigaction(res, signum, act, oldact, sz) \
+ __sanitizer_syscall_post_impl_rt_sigaction(res, (long)signum, (long)act, \
+ (long)oldact, (long)sz)
+#define __sanitizer_syscall_pre_sigaltstack(ss, oss) \
+ __sanitizer_syscall_pre_impl_sigaltstack((long)ss, (long)oss)
+#define __sanitizer_syscall_post_sigaltstack(res, ss, oss) \
+ __sanitizer_syscall_post_impl_sigaltstack(res, (long)ss, (long)oss)
+
+// And now a few syscalls we don't handle yet.
+#define __sanitizer_syscall_pre_afs_syscall(...)
+#define __sanitizer_syscall_pre_arch_prctl(...)
+#define __sanitizer_syscall_pre_break(...)
+#define __sanitizer_syscall_pre_chown32(...)
+#define __sanitizer_syscall_pre_clone(...)
+#define __sanitizer_syscall_pre_create_module(...)
+#define __sanitizer_syscall_pre_epoll_ctl_old(...)
+#define __sanitizer_syscall_pre_epoll_wait_old(...)
+#define __sanitizer_syscall_pre_execve(...)
+#define __sanitizer_syscall_pre_fadvise64(...)
+#define __sanitizer_syscall_pre_fadvise64_64(...)
+#define __sanitizer_syscall_pre_fallocate(...)
+#define __sanitizer_syscall_pre_fanotify_init(...)
+#define __sanitizer_syscall_pre_fanotify_mark(...)
+#define __sanitizer_syscall_pre_fchown32(...)
+#define __sanitizer_syscall_pre_ftime(...)
+#define __sanitizer_syscall_pre_ftruncate64(...)
+#define __sanitizer_syscall_pre_futex(...)
+#define __sanitizer_syscall_pre_getegid32(...)
+#define __sanitizer_syscall_pre_geteuid32(...)
+#define __sanitizer_syscall_pre_getgid32(...)
+#define __sanitizer_syscall_pre_getgroups32(...)
+#define __sanitizer_syscall_pre_get_kernel_syms(...)
+#define __sanitizer_syscall_pre_getpmsg(...)
+#define __sanitizer_syscall_pre_getresgid32(...)
+#define __sanitizer_syscall_pre_getresuid32(...)
+#define __sanitizer_syscall_pre_get_thread_area(...)
+#define __sanitizer_syscall_pre_getuid32(...)
+#define __sanitizer_syscall_pre_gtty(...)
+#define __sanitizer_syscall_pre_idle(...)
+#define __sanitizer_syscall_pre_iopl(...)
+#define __sanitizer_syscall_pre_lchown32(...)
+#define __sanitizer_syscall_pre__llseek(...)
+#define __sanitizer_syscall_pre_lock(...)
+#define __sanitizer_syscall_pre_madvise1(...)
+#define __sanitizer_syscall_pre_mmap(...)
+#define __sanitizer_syscall_pre_mmap2(...)
+#define __sanitizer_syscall_pre_modify_ldt(...)
+#define __sanitizer_syscall_pre_mpx(...)
+#define __sanitizer_syscall_pre__newselect(...)
+#define __sanitizer_syscall_pre_nfsservctl(...)
+#define __sanitizer_syscall_pre_oldfstat(...)
+#define __sanitizer_syscall_pre_oldlstat(...)
+#define __sanitizer_syscall_pre_oldolduname(...)
+#define __sanitizer_syscall_pre_oldstat(...)
+#define __sanitizer_syscall_pre_prctl(...)
+#define __sanitizer_syscall_pre_prof(...)
+#define __sanitizer_syscall_pre_profil(...)
+#define __sanitizer_syscall_pre_putpmsg(...)
+#define __sanitizer_syscall_pre_query_module(...)
+#define __sanitizer_syscall_pre_readahead(...)
+#define __sanitizer_syscall_pre_readdir(...)
+#define __sanitizer_syscall_pre_rt_sigreturn(...)
+#define __sanitizer_syscall_pre_rt_sigsuspend(...)
+#define __sanitizer_syscall_pre_security(...)
+#define __sanitizer_syscall_pre_setfsgid32(...)
+#define __sanitizer_syscall_pre_setfsuid32(...)
+#define __sanitizer_syscall_pre_setgid32(...)
+#define __sanitizer_syscall_pre_setgroups32(...)
+#define __sanitizer_syscall_pre_setregid32(...)
+#define __sanitizer_syscall_pre_setresgid32(...)
+#define __sanitizer_syscall_pre_setresuid32(...)
+#define __sanitizer_syscall_pre_setreuid32(...)
+#define __sanitizer_syscall_pre_set_thread_area(...)
+#define __sanitizer_syscall_pre_setuid32(...)
+#define __sanitizer_syscall_pre_sigreturn(...)
+#define __sanitizer_syscall_pre_sigsuspend(...)
+#define __sanitizer_syscall_pre_stty(...)
+#define __sanitizer_syscall_pre_sync_file_range(...)
+#define __sanitizer_syscall_pre__sysctl(...)
+#define __sanitizer_syscall_pre_truncate64(...)
+#define __sanitizer_syscall_pre_tuxcall(...)
+#define __sanitizer_syscall_pre_ugetrlimit(...)
+#define __sanitizer_syscall_pre_ulimit(...)
+#define __sanitizer_syscall_pre_umount2(...)
+#define __sanitizer_syscall_pre_vm86(...)
+#define __sanitizer_syscall_pre_vm86old(...)
+#define __sanitizer_syscall_pre_vserver(...)
+
+#define __sanitizer_syscall_post_afs_syscall(res, ...)
+#define __sanitizer_syscall_post_arch_prctl(res, ...)
+#define __sanitizer_syscall_post_break(res, ...)
+#define __sanitizer_syscall_post_chown32(res, ...)
+#define __sanitizer_syscall_post_clone(res, ...)
+#define __sanitizer_syscall_post_create_module(res, ...)
+#define __sanitizer_syscall_post_epoll_ctl_old(res, ...)
+#define __sanitizer_syscall_post_epoll_wait_old(res, ...)
+#define __sanitizer_syscall_post_execve(res, ...)
+#define __sanitizer_syscall_post_fadvise64(res, ...)
+#define __sanitizer_syscall_post_fadvise64_64(res, ...)
+#define __sanitizer_syscall_post_fallocate(res, ...)
+#define __sanitizer_syscall_post_fanotify_init(res, ...)
+#define __sanitizer_syscall_post_fanotify_mark(res, ...)
+#define __sanitizer_syscall_post_fchown32(res, ...)
+#define __sanitizer_syscall_post_ftime(res, ...)
+#define __sanitizer_syscall_post_ftruncate64(res, ...)
+#define __sanitizer_syscall_post_futex(res, ...)
+#define __sanitizer_syscall_post_getegid32(res, ...)
+#define __sanitizer_syscall_post_geteuid32(res, ...)
+#define __sanitizer_syscall_post_getgid32(res, ...)
+#define __sanitizer_syscall_post_getgroups32(res, ...)
+#define __sanitizer_syscall_post_get_kernel_syms(res, ...)
+#define __sanitizer_syscall_post_getpmsg(res, ...)
+#define __sanitizer_syscall_post_getresgid32(res, ...)
+#define __sanitizer_syscall_post_getresuid32(res, ...)
+#define __sanitizer_syscall_post_get_thread_area(res, ...)
+#define __sanitizer_syscall_post_getuid32(res, ...)
+#define __sanitizer_syscall_post_gtty(res, ...)
+#define __sanitizer_syscall_post_idle(res, ...)
+#define __sanitizer_syscall_post_iopl(res, ...)
+#define __sanitizer_syscall_post_lchown32(res, ...)
+#define __sanitizer_syscall_post__llseek(res, ...)
+#define __sanitizer_syscall_post_lock(res, ...)
+#define __sanitizer_syscall_post_madvise1(res, ...)
+#define __sanitizer_syscall_post_mmap2(res, ...)
+#define __sanitizer_syscall_post_mmap(res, ...)
+#define __sanitizer_syscall_post_modify_ldt(res, ...)
+#define __sanitizer_syscall_post_mpx(res, ...)
+#define __sanitizer_syscall_post__newselect(res, ...)
+#define __sanitizer_syscall_post_nfsservctl(res, ...)
+#define __sanitizer_syscall_post_oldfstat(res, ...)
+#define __sanitizer_syscall_post_oldlstat(res, ...)
+#define __sanitizer_syscall_post_oldolduname(res, ...)
+#define __sanitizer_syscall_post_oldstat(res, ...)
+#define __sanitizer_syscall_post_prctl(res, ...)
+#define __sanitizer_syscall_post_profil(res, ...)
+#define __sanitizer_syscall_post_prof(res, ...)
+#define __sanitizer_syscall_post_putpmsg(res, ...)
+#define __sanitizer_syscall_post_query_module(res, ...)
+#define __sanitizer_syscall_post_readahead(res, ...)
+#define __sanitizer_syscall_post_readdir(res, ...)
+#define __sanitizer_syscall_post_rt_sigreturn(res, ...)
+#define __sanitizer_syscall_post_rt_sigsuspend(res, ...)
+#define __sanitizer_syscall_post_security(res, ...)
+#define __sanitizer_syscall_post_setfsgid32(res, ...)
+#define __sanitizer_syscall_post_setfsuid32(res, ...)
+#define __sanitizer_syscall_post_setgid32(res, ...)
+#define __sanitizer_syscall_post_setgroups32(res, ...)
+#define __sanitizer_syscall_post_setregid32(res, ...)
+#define __sanitizer_syscall_post_setresgid32(res, ...)
+#define __sanitizer_syscall_post_setresuid32(res, ...)
+#define __sanitizer_syscall_post_setreuid32(res, ...)
+#define __sanitizer_syscall_post_set_thread_area(res, ...)
+#define __sanitizer_syscall_post_setuid32(res, ...)
+#define __sanitizer_syscall_post_sigreturn(res, ...)
+#define __sanitizer_syscall_post_sigsuspend(res, ...)
+#define __sanitizer_syscall_post_stty(res, ...)
+#define __sanitizer_syscall_post_sync_file_range(res, ...)
+#define __sanitizer_syscall_post__sysctl(res, ...)
+#define __sanitizer_syscall_post_truncate64(res, ...)
+#define __sanitizer_syscall_post_tuxcall(res, ...)
+#define __sanitizer_syscall_post_ugetrlimit(res, ...)
+#define __sanitizer_syscall_post_ulimit(res, ...)
+#define __sanitizer_syscall_post_umount2(res, ...)
+#define __sanitizer_syscall_post_vm86old(res, ...)
+#define __sanitizer_syscall_post_vm86(res, ...)
+#define __sanitizer_syscall_post_vserver(res, ...)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Private declarations. Do not call directly from user code. Use macros above.
+void __sanitizer_syscall_pre_impl_time(long tloc);
+void __sanitizer_syscall_post_impl_time(long res, long tloc);
+void __sanitizer_syscall_pre_impl_stime(long tptr);
+void __sanitizer_syscall_post_impl_stime(long res, long tptr);
+void __sanitizer_syscall_pre_impl_gettimeofday(long tv, long tz);
+void __sanitizer_syscall_post_impl_gettimeofday(long res, long tv, long tz);
+void __sanitizer_syscall_pre_impl_settimeofday(long tv, long tz);
+void __sanitizer_syscall_post_impl_settimeofday(long res, long tv, long tz);
+void __sanitizer_syscall_pre_impl_adjtimex(long txc_p);
+void __sanitizer_syscall_post_impl_adjtimex(long res, long txc_p);
+void __sanitizer_syscall_pre_impl_times(long tbuf);
+void __sanitizer_syscall_post_impl_times(long res, long tbuf);
+void __sanitizer_syscall_pre_impl_gettid();
+void __sanitizer_syscall_post_impl_gettid(long res);
+void __sanitizer_syscall_pre_impl_nanosleep(long rqtp, long rmtp);
+void __sanitizer_syscall_post_impl_nanosleep(long res, long rqtp, long rmtp);
+void __sanitizer_syscall_pre_impl_alarm(long seconds);
+void __sanitizer_syscall_post_impl_alarm(long res, long seconds);
+void __sanitizer_syscall_pre_impl_getpid();
+void __sanitizer_syscall_post_impl_getpid(long res);
+void __sanitizer_syscall_pre_impl_getppid();
+void __sanitizer_syscall_post_impl_getppid(long res);
+void __sanitizer_syscall_pre_impl_getuid();
+void __sanitizer_syscall_post_impl_getuid(long res);
+void __sanitizer_syscall_pre_impl_geteuid();
+void __sanitizer_syscall_post_impl_geteuid(long res);
+void __sanitizer_syscall_pre_impl_getgid();
+void __sanitizer_syscall_post_impl_getgid(long res);
+void __sanitizer_syscall_pre_impl_getegid();
+void __sanitizer_syscall_post_impl_getegid(long res);
+void __sanitizer_syscall_pre_impl_getresuid(long ruid, long euid, long suid);
+void __sanitizer_syscall_post_impl_getresuid(long res, long ruid, long euid,
+ long suid);
+void __sanitizer_syscall_pre_impl_getresgid(long rgid, long egid, long sgid);
+void __sanitizer_syscall_post_impl_getresgid(long res, long rgid, long egid,
+ long sgid);
+void __sanitizer_syscall_pre_impl_getpgid(long pid);
+void __sanitizer_syscall_post_impl_getpgid(long res, long pid);
+void __sanitizer_syscall_pre_impl_getpgrp();
+void __sanitizer_syscall_post_impl_getpgrp(long res);
+void __sanitizer_syscall_pre_impl_getsid(long pid);
+void __sanitizer_syscall_post_impl_getsid(long res, long pid);
+void __sanitizer_syscall_pre_impl_getgroups(long gidsetsize, long grouplist);
+void __sanitizer_syscall_post_impl_getgroups(long res, long gidsetsize,
+ long grouplist);
+void __sanitizer_syscall_pre_impl_setregid(long rgid, long egid);
+void __sanitizer_syscall_post_impl_setregid(long res, long rgid, long egid);
+void __sanitizer_syscall_pre_impl_setgid(long gid);
+void __sanitizer_syscall_post_impl_setgid(long res, long gid);
+void __sanitizer_syscall_pre_impl_setreuid(long ruid, long euid);
+void __sanitizer_syscall_post_impl_setreuid(long res, long ruid, long euid);
+void __sanitizer_syscall_pre_impl_setuid(long uid);
+void __sanitizer_syscall_post_impl_setuid(long res, long uid);
+void __sanitizer_syscall_pre_impl_setresuid(long ruid, long euid, long suid);
+void __sanitizer_syscall_post_impl_setresuid(long res, long ruid, long euid,
+ long suid);
+void __sanitizer_syscall_pre_impl_setresgid(long rgid, long egid, long sgid);
+void __sanitizer_syscall_post_impl_setresgid(long res, long rgid, long egid,
+ long sgid);
+void __sanitizer_syscall_pre_impl_setfsuid(long uid);
+void __sanitizer_syscall_post_impl_setfsuid(long res, long uid);
+void __sanitizer_syscall_pre_impl_setfsgid(long gid);
+void __sanitizer_syscall_post_impl_setfsgid(long res, long gid);
+void __sanitizer_syscall_pre_impl_setpgid(long pid, long pgid);
+void __sanitizer_syscall_post_impl_setpgid(long res, long pid, long pgid);
+void __sanitizer_syscall_pre_impl_setsid();
+void __sanitizer_syscall_post_impl_setsid(long res);
+void __sanitizer_syscall_pre_impl_setgroups(long gidsetsize, long grouplist);
+void __sanitizer_syscall_post_impl_setgroups(long res, long gidsetsize,
+ long grouplist);
+void __sanitizer_syscall_pre_impl_acct(long name);
+void __sanitizer_syscall_post_impl_acct(long res, long name);
+void __sanitizer_syscall_pre_impl_capget(long header, long dataptr);
+void __sanitizer_syscall_post_impl_capget(long res, long header, long dataptr);
+void __sanitizer_syscall_pre_impl_capset(long header, long data);
+void __sanitizer_syscall_post_impl_capset(long res, long header, long data);
+void __sanitizer_syscall_pre_impl_personality(long personality);
+void __sanitizer_syscall_post_impl_personality(long res, long personality);
+void __sanitizer_syscall_pre_impl_sigpending(long set);
+void __sanitizer_syscall_post_impl_sigpending(long res, long set);
+void __sanitizer_syscall_pre_impl_sigprocmask(long how, long set, long oset);
+void __sanitizer_syscall_post_impl_sigprocmask(long res, long how, long set,
+ long oset);
+void __sanitizer_syscall_pre_impl_getitimer(long which, long value);
+void __sanitizer_syscall_post_impl_getitimer(long res, long which, long value);
+void __sanitizer_syscall_pre_impl_setitimer(long which, long value,
+ long ovalue);
+void __sanitizer_syscall_post_impl_setitimer(long res, long which, long value,
+ long ovalue);
+void __sanitizer_syscall_pre_impl_timer_create(long which_clock,
+ long timer_event_spec,
+ long created_timer_id);
+void __sanitizer_syscall_post_impl_timer_create(long res, long which_clock,
+ long timer_event_spec,
+ long created_timer_id);
+void __sanitizer_syscall_pre_impl_timer_gettime(long timer_id, long setting);
+void __sanitizer_syscall_post_impl_timer_gettime(long res, long timer_id,
+ long setting);
+void __sanitizer_syscall_pre_impl_timer_getoverrun(long timer_id);
+void __sanitizer_syscall_post_impl_timer_getoverrun(long res, long timer_id);
+void __sanitizer_syscall_pre_impl_timer_settime(long timer_id, long flags,
+ long new_setting,
+ long old_setting);
+void __sanitizer_syscall_post_impl_timer_settime(long res, long timer_id,
+ long flags, long new_setting,
+ long old_setting);
+void __sanitizer_syscall_pre_impl_timer_delete(long timer_id);
+void __sanitizer_syscall_post_impl_timer_delete(long res, long timer_id);
+void __sanitizer_syscall_pre_impl_clock_settime(long which_clock, long tp);
+void __sanitizer_syscall_post_impl_clock_settime(long res, long which_clock,
+ long tp);
+void __sanitizer_syscall_pre_impl_clock_gettime(long which_clock, long tp);
+void __sanitizer_syscall_post_impl_clock_gettime(long res, long which_clock,
+ long tp);
+void __sanitizer_syscall_pre_impl_clock_adjtime(long which_clock, long tx);
+void __sanitizer_syscall_post_impl_clock_adjtime(long res, long which_clock,
+ long tx);
+void __sanitizer_syscall_pre_impl_clock_getres(long which_clock, long tp);
+void __sanitizer_syscall_post_impl_clock_getres(long res, long which_clock,
+ long tp);
+void __sanitizer_syscall_pre_impl_clock_nanosleep(long which_clock, long flags,
+ long rqtp, long rmtp);
+void __sanitizer_syscall_post_impl_clock_nanosleep(long res, long which_clock,
+ long flags, long rqtp,
+ long rmtp);
+void __sanitizer_syscall_pre_impl_nice(long increment);
+void __sanitizer_syscall_post_impl_nice(long res, long increment);
+void __sanitizer_syscall_pre_impl_sched_setscheduler(long pid, long policy,
+ long param);
+void __sanitizer_syscall_post_impl_sched_setscheduler(long res, long pid,
+ long policy, long param);
+void __sanitizer_syscall_pre_impl_sched_setparam(long pid, long param);
+void __sanitizer_syscall_post_impl_sched_setparam(long res, long pid,
+ long param);
+void __sanitizer_syscall_pre_impl_sched_getscheduler(long pid);
+void __sanitizer_syscall_post_impl_sched_getscheduler(long res, long pid);
+void __sanitizer_syscall_pre_impl_sched_getparam(long pid, long param);
+void __sanitizer_syscall_post_impl_sched_getparam(long res, long pid,
+ long param);
+void __sanitizer_syscall_pre_impl_sched_setaffinity(long pid, long len,
+ long user_mask_ptr);
+void __sanitizer_syscall_post_impl_sched_setaffinity(long res, long pid,
+ long len,
+ long user_mask_ptr);
+void __sanitizer_syscall_pre_impl_sched_getaffinity(long pid, long len,
+ long user_mask_ptr);
+void __sanitizer_syscall_post_impl_sched_getaffinity(long res, long pid,
+ long len,
+ long user_mask_ptr);
+void __sanitizer_syscall_pre_impl_sched_yield();
+void __sanitizer_syscall_post_impl_sched_yield(long res);
+void __sanitizer_syscall_pre_impl_sched_get_priority_max(long policy);
+void __sanitizer_syscall_post_impl_sched_get_priority_max(long res,
+ long policy);
+void __sanitizer_syscall_pre_impl_sched_get_priority_min(long policy);
+void __sanitizer_syscall_post_impl_sched_get_priority_min(long res,
+ long policy);
+void __sanitizer_syscall_pre_impl_sched_rr_get_interval(long pid,
+ long interval);
+void __sanitizer_syscall_post_impl_sched_rr_get_interval(long res, long pid,
+ long interval);
+void __sanitizer_syscall_pre_impl_setpriority(long which, long who,
+ long niceval);
+void __sanitizer_syscall_post_impl_setpriority(long res, long which, long who,
+ long niceval);
+void __sanitizer_syscall_pre_impl_getpriority(long which, long who);
+void __sanitizer_syscall_post_impl_getpriority(long res, long which, long who);
+void __sanitizer_syscall_pre_impl_shutdown(long arg0, long arg1);
+void __sanitizer_syscall_post_impl_shutdown(long res, long arg0, long arg1);
+void __sanitizer_syscall_pre_impl_reboot(long magic1, long magic2, long cmd,
+ long arg);
+void __sanitizer_syscall_post_impl_reboot(long res, long magic1, long magic2,
+ long cmd, long arg);
+void __sanitizer_syscall_pre_impl_restart_syscall();
+void __sanitizer_syscall_post_impl_restart_syscall(long res);
+void __sanitizer_syscall_pre_impl_kexec_load(long entry, long nr_segments,
+ long segments, long flags);
+void __sanitizer_syscall_post_impl_kexec_load(long res, long entry,
+ long nr_segments, long segments,
+ long flags);
+void __sanitizer_syscall_pre_impl_exit(long error_code);
+void __sanitizer_syscall_post_impl_exit(long res, long error_code);
+void __sanitizer_syscall_pre_impl_exit_group(long error_code);
+void __sanitizer_syscall_post_impl_exit_group(long res, long error_code);
+void __sanitizer_syscall_pre_impl_wait4(long pid, long stat_addr, long options,
+ long ru);
+void __sanitizer_syscall_post_impl_wait4(long res, long pid, long stat_addr,
+ long options, long ru);
+void __sanitizer_syscall_pre_impl_waitid(long which, long pid, long infop,
+ long options, long ru);
+void __sanitizer_syscall_post_impl_waitid(long res, long which, long pid,
+ long infop, long options, long ru);
+void __sanitizer_syscall_pre_impl_waitpid(long pid, long stat_addr,
+ long options);
+void __sanitizer_syscall_post_impl_waitpid(long res, long pid, long stat_addr,
+ long options);
+void __sanitizer_syscall_pre_impl_set_tid_address(long tidptr);
+void __sanitizer_syscall_post_impl_set_tid_address(long res, long tidptr);
+void __sanitizer_syscall_pre_impl_init_module(long umod, long len, long uargs);
+void __sanitizer_syscall_post_impl_init_module(long res, long umod, long len,
+ long uargs);
+void __sanitizer_syscall_pre_impl_delete_module(long name_user, long flags);
+void __sanitizer_syscall_post_impl_delete_module(long res, long name_user,
+ long flags);
+void __sanitizer_syscall_pre_impl_rt_sigprocmask(long how, long set, long oset,
+ long sigsetsize);
+void __sanitizer_syscall_post_impl_rt_sigprocmask(long res, long how, long set,
+ long oset, long sigsetsize);
+void __sanitizer_syscall_pre_impl_rt_sigpending(long set, long sigsetsize);
+void __sanitizer_syscall_post_impl_rt_sigpending(long res, long set,
+ long sigsetsize);
+void __sanitizer_syscall_pre_impl_rt_sigtimedwait(long uthese, long uinfo,
+ long uts, long sigsetsize);
+void __sanitizer_syscall_post_impl_rt_sigtimedwait(long res, long uthese,
+ long uinfo, long uts,
+ long sigsetsize);
+void __sanitizer_syscall_pre_impl_rt_tgsigqueueinfo(long tgid, long pid,
+ long sig, long uinfo);
+void __sanitizer_syscall_post_impl_rt_tgsigqueueinfo(long res, long tgid,
+ long pid, long sig,
+ long uinfo);
+void __sanitizer_syscall_pre_impl_kill(long pid, long sig);
+void __sanitizer_syscall_post_impl_kill(long res, long pid, long sig);
+void __sanitizer_syscall_pre_impl_tgkill(long tgid, long pid, long sig);
+void __sanitizer_syscall_post_impl_tgkill(long res, long tgid, long pid,
+ long sig);
+void __sanitizer_syscall_pre_impl_tkill(long pid, long sig);
+void __sanitizer_syscall_post_impl_tkill(long res, long pid, long sig);
+void __sanitizer_syscall_pre_impl_rt_sigqueueinfo(long pid, long sig,
+ long uinfo);
+void __sanitizer_syscall_post_impl_rt_sigqueueinfo(long res, long pid, long sig,
+ long uinfo);
+void __sanitizer_syscall_pre_impl_sgetmask();
+void __sanitizer_syscall_post_impl_sgetmask(long res);
+void __sanitizer_syscall_pre_impl_ssetmask(long newmask);
+void __sanitizer_syscall_post_impl_ssetmask(long res, long newmask);
+void __sanitizer_syscall_pre_impl_signal(long sig, long handler);
+void __sanitizer_syscall_post_impl_signal(long res, long sig, long handler);
+void __sanitizer_syscall_pre_impl_pause();
+void __sanitizer_syscall_post_impl_pause(long res);
+void __sanitizer_syscall_pre_impl_sync();
+void __sanitizer_syscall_post_impl_sync(long res);
+void __sanitizer_syscall_pre_impl_fsync(long fd);
+void __sanitizer_syscall_post_impl_fsync(long res, long fd);
+void __sanitizer_syscall_pre_impl_fdatasync(long fd);
+void __sanitizer_syscall_post_impl_fdatasync(long res, long fd);
+void __sanitizer_syscall_pre_impl_bdflush(long func, long data);
+void __sanitizer_syscall_post_impl_bdflush(long res, long func, long data);
+void __sanitizer_syscall_pre_impl_mount(long dev_name, long dir_name, long type,
+ long flags, long data);
+void __sanitizer_syscall_post_impl_mount(long res, long dev_name, long dir_name,
+ long type, long flags, long data);
+void __sanitizer_syscall_pre_impl_umount(long name, long flags);
+void __sanitizer_syscall_post_impl_umount(long res, long name, long flags);
+void __sanitizer_syscall_pre_impl_oldumount(long name);
+void __sanitizer_syscall_post_impl_oldumount(long res, long name);
+void __sanitizer_syscall_pre_impl_truncate(long path, long length);
+void __sanitizer_syscall_post_impl_truncate(long res, long path, long length);
+void __sanitizer_syscall_pre_impl_ftruncate(long fd, long length);
+void __sanitizer_syscall_post_impl_ftruncate(long res, long fd, long length);
+void __sanitizer_syscall_pre_impl_stat(long filename, long statbuf);
+void __sanitizer_syscall_post_impl_stat(long res, long filename, long statbuf);
+void __sanitizer_syscall_pre_impl_statfs(long path, long buf);
+void __sanitizer_syscall_post_impl_statfs(long res, long path, long buf);
+void __sanitizer_syscall_pre_impl_statfs64(long path, long sz, long buf);
+void __sanitizer_syscall_post_impl_statfs64(long res, long path, long sz,
+ long buf);
+void __sanitizer_syscall_pre_impl_fstatfs(long fd, long buf);
+void __sanitizer_syscall_post_impl_fstatfs(long res, long fd, long buf);
+void __sanitizer_syscall_pre_impl_fstatfs64(long fd, long sz, long buf);
+void __sanitizer_syscall_post_impl_fstatfs64(long res, long fd, long sz,
+ long buf);
+void __sanitizer_syscall_pre_impl_lstat(long filename, long statbuf);
+void __sanitizer_syscall_post_impl_lstat(long res, long filename, long statbuf);
+void __sanitizer_syscall_pre_impl_fstat(long fd, long statbuf);
+void __sanitizer_syscall_post_impl_fstat(long res, long fd, long statbuf);
+void __sanitizer_syscall_pre_impl_newstat(long filename, long statbuf);
+void __sanitizer_syscall_post_impl_newstat(long res, long filename,
+ long statbuf);
+void __sanitizer_syscall_pre_impl_newlstat(long filename, long statbuf);
+void __sanitizer_syscall_post_impl_newlstat(long res, long filename,
+ long statbuf);
+void __sanitizer_syscall_pre_impl_newfstat(long fd, long statbuf);
+void __sanitizer_syscall_post_impl_newfstat(long res, long fd, long statbuf);
+void __sanitizer_syscall_pre_impl_ustat(long dev, long ubuf);
+void __sanitizer_syscall_post_impl_ustat(long res, long dev, long ubuf);
+void __sanitizer_syscall_pre_impl_stat64(long filename, long statbuf);
+void __sanitizer_syscall_post_impl_stat64(long res, long filename,
+ long statbuf);
+void __sanitizer_syscall_pre_impl_fstat64(long fd, long statbuf);
+void __sanitizer_syscall_post_impl_fstat64(long res, long fd, long statbuf);
+void __sanitizer_syscall_pre_impl_lstat64(long filename, long statbuf);
+void __sanitizer_syscall_post_impl_lstat64(long res, long filename,
+ long statbuf);
+void __sanitizer_syscall_pre_impl_setxattr(long path, long name, long value,
+ long size, long flags);
+void __sanitizer_syscall_post_impl_setxattr(long res, long path, long name,
+ long value, long size, long flags);
+void __sanitizer_syscall_pre_impl_lsetxattr(long path, long name, long value,
+ long size, long flags);
+void __sanitizer_syscall_post_impl_lsetxattr(long res, long path, long name,
+ long value, long size, long flags);
+void __sanitizer_syscall_pre_impl_fsetxattr(long fd, long name, long value,
+ long size, long flags);
+void __sanitizer_syscall_post_impl_fsetxattr(long res, long fd, long name,
+ long value, long size, long flags);
+void __sanitizer_syscall_pre_impl_getxattr(long path, long name, long value,
+ long size);
+void __sanitizer_syscall_post_impl_getxattr(long res, long path, long name,
+ long value, long size);
+void __sanitizer_syscall_pre_impl_lgetxattr(long path, long name, long value,
+ long size);
+void __sanitizer_syscall_post_impl_lgetxattr(long res, long path, long name,
+ long value, long size);
+void __sanitizer_syscall_pre_impl_fgetxattr(long fd, long name, long value,
+ long size);
+void __sanitizer_syscall_post_impl_fgetxattr(long res, long fd, long name,
+ long value, long size);
+void __sanitizer_syscall_pre_impl_listxattr(long path, long list, long size);
+void __sanitizer_syscall_post_impl_listxattr(long res, long path, long list,
+ long size);
+void __sanitizer_syscall_pre_impl_llistxattr(long path, long list, long size);
+void __sanitizer_syscall_post_impl_llistxattr(long res, long path, long list,
+ long size);
+void __sanitizer_syscall_pre_impl_flistxattr(long fd, long list, long size);
+void __sanitizer_syscall_post_impl_flistxattr(long res, long fd, long list,
+ long size);
+void __sanitizer_syscall_pre_impl_removexattr(long path, long name);
+void __sanitizer_syscall_post_impl_removexattr(long res, long path, long name);
+void __sanitizer_syscall_pre_impl_lremovexattr(long path, long name);
+void __sanitizer_syscall_post_impl_lremovexattr(long res, long path, long name);
+void __sanitizer_syscall_pre_impl_fremovexattr(long fd, long name);
+void __sanitizer_syscall_post_impl_fremovexattr(long res, long fd, long name);
+void __sanitizer_syscall_pre_impl_brk(long brk);
+void __sanitizer_syscall_post_impl_brk(long res, long brk);
+void __sanitizer_syscall_pre_impl_mprotect(long start, long len, long prot);
+void __sanitizer_syscall_post_impl_mprotect(long res, long start, long len,
+ long prot);
+void __sanitizer_syscall_pre_impl_mremap(long addr, long old_len, long new_len,
+ long flags, long new_addr);
+void __sanitizer_syscall_post_impl_mremap(long res, long addr, long old_len,
+ long new_len, long flags,
+ long new_addr);
+void __sanitizer_syscall_pre_impl_remap_file_pages(long start, long size,
+ long prot, long pgoff,
+ long flags);
+void __sanitizer_syscall_post_impl_remap_file_pages(long res, long start,
+ long size, long prot,
+ long pgoff, long flags);
+void __sanitizer_syscall_pre_impl_msync(long start, long len, long flags);
+void __sanitizer_syscall_post_impl_msync(long res, long start, long len,
+ long flags);
+void __sanitizer_syscall_pre_impl_munmap(long addr, long len);
+void __sanitizer_syscall_post_impl_munmap(long res, long addr, long len);
+void __sanitizer_syscall_pre_impl_mlock(long start, long len);
+void __sanitizer_syscall_post_impl_mlock(long res, long start, long len);
+void __sanitizer_syscall_pre_impl_munlock(long start, long len);
+void __sanitizer_syscall_post_impl_munlock(long res, long start, long len);
+void __sanitizer_syscall_pre_impl_mlockall(long flags);
+void __sanitizer_syscall_post_impl_mlockall(long res, long flags);
+void __sanitizer_syscall_pre_impl_munlockall();
+void __sanitizer_syscall_post_impl_munlockall(long res);
+void __sanitizer_syscall_pre_impl_madvise(long start, long len, long behavior);
+void __sanitizer_syscall_post_impl_madvise(long res, long start, long len,
+ long behavior);
+void __sanitizer_syscall_pre_impl_mincore(long start, long len, long vec);
+void __sanitizer_syscall_post_impl_mincore(long res, long start, long len,
+ long vec);
+void __sanitizer_syscall_pre_impl_pivot_root(long new_root, long put_old);
+void __sanitizer_syscall_post_impl_pivot_root(long res, long new_root,
+ long put_old);
+void __sanitizer_syscall_pre_impl_chroot(long filename);
+void __sanitizer_syscall_post_impl_chroot(long res, long filename);
+void __sanitizer_syscall_pre_impl_mknod(long filename, long mode, long dev);
+void __sanitizer_syscall_post_impl_mknod(long res, long filename, long mode,
+ long dev);
+void __sanitizer_syscall_pre_impl_link(long oldname, long newname);
+void __sanitizer_syscall_post_impl_link(long res, long oldname, long newname);
+void __sanitizer_syscall_pre_impl_symlink(long old, long new_);
+void __sanitizer_syscall_post_impl_symlink(long res, long old, long new_);
+void __sanitizer_syscall_pre_impl_unlink(long pathname);
+void __sanitizer_syscall_post_impl_unlink(long res, long pathname);
+void __sanitizer_syscall_pre_impl_rename(long oldname, long newname);
+void __sanitizer_syscall_post_impl_rename(long res, long oldname, long newname);
+void __sanitizer_syscall_pre_impl_chmod(long filename, long mode);
+void __sanitizer_syscall_post_impl_chmod(long res, long filename, long mode);
+void __sanitizer_syscall_pre_impl_fchmod(long fd, long mode);
+void __sanitizer_syscall_post_impl_fchmod(long res, long fd, long mode);
+void __sanitizer_syscall_pre_impl_fcntl(long fd, long cmd, long arg);
+void __sanitizer_syscall_post_impl_fcntl(long res, long fd, long cmd, long arg);
+void __sanitizer_syscall_pre_impl_fcntl64(long fd, long cmd, long arg);
+void __sanitizer_syscall_post_impl_fcntl64(long res, long fd, long cmd,
+ long arg);
+void __sanitizer_syscall_pre_impl_pipe(long fildes);
+void __sanitizer_syscall_post_impl_pipe(long res, long fildes);
+void __sanitizer_syscall_pre_impl_pipe2(long fildes, long flags);
+void __sanitizer_syscall_post_impl_pipe2(long res, long fildes, long flags);
+void __sanitizer_syscall_pre_impl_dup(long fildes);
+void __sanitizer_syscall_post_impl_dup(long res, long fildes);
+void __sanitizer_syscall_pre_impl_dup2(long oldfd, long newfd);
+void __sanitizer_syscall_post_impl_dup2(long res, long oldfd, long newfd);
+void __sanitizer_syscall_pre_impl_dup3(long oldfd, long newfd, long flags);
+void __sanitizer_syscall_post_impl_dup3(long res, long oldfd, long newfd,
+ long flags);
+void __sanitizer_syscall_pre_impl_ioperm(long from, long num, long on);
+void __sanitizer_syscall_post_impl_ioperm(long res, long from, long num,
+ long on);
+void __sanitizer_syscall_pre_impl_ioctl(long fd, long cmd, long arg);
+void __sanitizer_syscall_post_impl_ioctl(long res, long fd, long cmd, long arg);
+void __sanitizer_syscall_pre_impl_flock(long fd, long cmd);
+void __sanitizer_syscall_post_impl_flock(long res, long fd, long cmd);
+void __sanitizer_syscall_pre_impl_io_setup(long nr_reqs, long ctx);
+void __sanitizer_syscall_post_impl_io_setup(long res, long nr_reqs, long ctx);
+void __sanitizer_syscall_pre_impl_io_destroy(long ctx);
+void __sanitizer_syscall_post_impl_io_destroy(long res, long ctx);
+void __sanitizer_syscall_pre_impl_io_getevents(long ctx_id, long min_nr,
+ long nr, long events,
+ long timeout);
+void __sanitizer_syscall_post_impl_io_getevents(long res, long ctx_id,
+ long min_nr, long nr,
+ long events, long timeout);
+void __sanitizer_syscall_pre_impl_io_submit(long ctx_id, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_io_submit(long res, long ctx_id, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_io_cancel(long ctx_id, long iocb,
+ long result);
+void __sanitizer_syscall_post_impl_io_cancel(long res, long ctx_id, long iocb,
+ long result);
+void __sanitizer_syscall_pre_impl_sendfile(long out_fd, long in_fd, long offset,
+ long count);
+void __sanitizer_syscall_post_impl_sendfile(long res, long out_fd, long in_fd,
+ long offset, long count);
+void __sanitizer_syscall_pre_impl_sendfile64(long out_fd, long in_fd,
+ long offset, long count);
+void __sanitizer_syscall_post_impl_sendfile64(long res, long out_fd, long in_fd,
+ long offset, long count);
+void __sanitizer_syscall_pre_impl_readlink(long path, long buf, long bufsiz);
+void __sanitizer_syscall_post_impl_readlink(long res, long path, long buf,
+ long bufsiz);
+void __sanitizer_syscall_pre_impl_creat(long pathname, long mode);
+void __sanitizer_syscall_post_impl_creat(long res, long pathname, long mode);
+void __sanitizer_syscall_pre_impl_open(long filename, long flags, long mode);
+void __sanitizer_syscall_post_impl_open(long res, long filename, long flags,
+ long mode);
+void __sanitizer_syscall_pre_impl_close(long fd);
+void __sanitizer_syscall_post_impl_close(long res, long fd);
+void __sanitizer_syscall_pre_impl_access(long filename, long mode);
+void __sanitizer_syscall_post_impl_access(long res, long filename, long mode);
+void __sanitizer_syscall_pre_impl_vhangup();
+void __sanitizer_syscall_post_impl_vhangup(long res);
+void __sanitizer_syscall_pre_impl_chown(long filename, long user, long group);
+void __sanitizer_syscall_post_impl_chown(long res, long filename, long user,
+ long group);
+void __sanitizer_syscall_pre_impl_lchown(long filename, long user, long group);
+void __sanitizer_syscall_post_impl_lchown(long res, long filename, long user,
+ long group);
+void __sanitizer_syscall_pre_impl_fchown(long fd, long user, long group);
+void __sanitizer_syscall_post_impl_fchown(long res, long fd, long user,
+ long group);
+void __sanitizer_syscall_pre_impl_chown16(long filename, long user, long group);
+void __sanitizer_syscall_post_impl_chown16(long res, long filename, long user,
+ long group);
+void __sanitizer_syscall_pre_impl_lchown16(long filename, long user,
+ long group);
+void __sanitizer_syscall_post_impl_lchown16(long res, long filename, long user,
+ long group);
+void __sanitizer_syscall_pre_impl_fchown16(long fd, long user, long group);
+void __sanitizer_syscall_post_impl_fchown16(long res, long fd, long user,
+ long group);
+void __sanitizer_syscall_pre_impl_setregid16(long rgid, long egid);
+void __sanitizer_syscall_post_impl_setregid16(long res, long rgid, long egid);
+void __sanitizer_syscall_pre_impl_setgid16(long gid);
+void __sanitizer_syscall_post_impl_setgid16(long res, long gid);
+void __sanitizer_syscall_pre_impl_setreuid16(long ruid, long euid);
+void __sanitizer_syscall_post_impl_setreuid16(long res, long ruid, long euid);
+void __sanitizer_syscall_pre_impl_setuid16(long uid);
+void __sanitizer_syscall_post_impl_setuid16(long res, long uid);
+void __sanitizer_syscall_pre_impl_setresuid16(long ruid, long euid, long suid);
+void __sanitizer_syscall_post_impl_setresuid16(long res, long ruid, long euid,
+ long suid);
+void __sanitizer_syscall_pre_impl_getresuid16(long ruid, long euid, long suid);
+void __sanitizer_syscall_post_impl_getresuid16(long res, long ruid, long euid,
+ long suid);
+void __sanitizer_syscall_pre_impl_setresgid16(long rgid, long egid, long sgid);
+void __sanitizer_syscall_post_impl_setresgid16(long res, long rgid, long egid,
+ long sgid);
+void __sanitizer_syscall_pre_impl_getresgid16(long rgid, long egid, long sgid);
+void __sanitizer_syscall_post_impl_getresgid16(long res, long rgid, long egid,
+ long sgid);
+void __sanitizer_syscall_pre_impl_setfsuid16(long uid);
+void __sanitizer_syscall_post_impl_setfsuid16(long res, long uid);
+void __sanitizer_syscall_pre_impl_setfsgid16(long gid);
+void __sanitizer_syscall_post_impl_setfsgid16(long res, long gid);
+void __sanitizer_syscall_pre_impl_getgroups16(long gidsetsize, long grouplist);
+void __sanitizer_syscall_post_impl_getgroups16(long res, long gidsetsize,
+ long grouplist);
+void __sanitizer_syscall_pre_impl_setgroups16(long gidsetsize, long grouplist);
+void __sanitizer_syscall_post_impl_setgroups16(long res, long gidsetsize,
+ long grouplist);
+void __sanitizer_syscall_pre_impl_getuid16();
+void __sanitizer_syscall_post_impl_getuid16(long res);
+void __sanitizer_syscall_pre_impl_geteuid16();
+void __sanitizer_syscall_post_impl_geteuid16(long res);
+void __sanitizer_syscall_pre_impl_getgid16();
+void __sanitizer_syscall_post_impl_getgid16(long res);
+void __sanitizer_syscall_pre_impl_getegid16();
+void __sanitizer_syscall_post_impl_getegid16(long res);
+void __sanitizer_syscall_pre_impl_utime(long filename, long times);
+void __sanitizer_syscall_post_impl_utime(long res, long filename, long times);
+void __sanitizer_syscall_pre_impl_utimes(long filename, long utimes);
+void __sanitizer_syscall_post_impl_utimes(long res, long filename, long utimes);
+void __sanitizer_syscall_pre_impl_lseek(long fd, long offset, long origin);
+void __sanitizer_syscall_post_impl_lseek(long res, long fd, long offset,
+ long origin);
+void __sanitizer_syscall_pre_impl_llseek(long fd, long offset_high,
+ long offset_low, long result,
+ long origin);
+void __sanitizer_syscall_post_impl_llseek(long res, long fd, long offset_high,
+ long offset_low, long result,
+ long origin);
+void __sanitizer_syscall_pre_impl_read(long fd, long buf, long count);
+void __sanitizer_syscall_post_impl_read(long res, long fd, long buf,
+ long count);
+void __sanitizer_syscall_pre_impl_readv(long fd, long vec, long vlen);
+void __sanitizer_syscall_post_impl_readv(long res, long fd, long vec,
+ long vlen);
+void __sanitizer_syscall_pre_impl_write(long fd, long buf, long count);
+void __sanitizer_syscall_post_impl_write(long res, long fd, long buf,
+ long count);
+void __sanitizer_syscall_pre_impl_writev(long fd, long vec, long vlen);
+void __sanitizer_syscall_post_impl_writev(long res, long fd, long vec,
+ long vlen);
+
+#ifdef _LP64
+void __sanitizer_syscall_pre_impl_pread64(long fd, long buf, long count,
+ long pos);
+void __sanitizer_syscall_post_impl_pread64(long res, long fd, long buf,
+ long count, long pos);
+void __sanitizer_syscall_pre_impl_pwrite64(long fd, long buf, long count,
+ long pos);
+void __sanitizer_syscall_post_impl_pwrite64(long res, long fd, long buf,
+ long count, long pos);
+#else
+void __sanitizer_syscall_pre_impl_pread64(long fd, long buf, long count,
+ long pos0, long pos1);
+void __sanitizer_syscall_post_impl_pread64(long res, long fd, long buf,
+ long count, long pos0, long pos1);
+void __sanitizer_syscall_pre_impl_pwrite64(long fd, long buf, long count,
+ long pos0, long pos1);
+void __sanitizer_syscall_post_impl_pwrite64(long res, long fd, long buf,
+ long count, long pos0, long pos1);
+#endif
+
+void __sanitizer_syscall_pre_impl_preadv(long fd, long vec, long vlen,
+ long pos_l, long pos_h);
+void __sanitizer_syscall_post_impl_preadv(long res, long fd, long vec,
+ long vlen, long pos_l, long pos_h);
+void __sanitizer_syscall_pre_impl_pwritev(long fd, long vec, long vlen,
+ long pos_l, long pos_h);
+void __sanitizer_syscall_post_impl_pwritev(long res, long fd, long vec,
+ long vlen, long pos_l, long pos_h);
+void __sanitizer_syscall_pre_impl_getcwd(long buf, long size);
+void __sanitizer_syscall_post_impl_getcwd(long res, long buf, long size);
+void __sanitizer_syscall_pre_impl_mkdir(long pathname, long mode);
+void __sanitizer_syscall_post_impl_mkdir(long res, long pathname, long mode);
+void __sanitizer_syscall_pre_impl_chdir(long filename);
+void __sanitizer_syscall_post_impl_chdir(long res, long filename);
+void __sanitizer_syscall_pre_impl_fchdir(long fd);
+void __sanitizer_syscall_post_impl_fchdir(long res, long fd);
+void __sanitizer_syscall_pre_impl_rmdir(long pathname);
+void __sanitizer_syscall_post_impl_rmdir(long res, long pathname);
+void __sanitizer_syscall_pre_impl_lookup_dcookie(long cookie64, long buf,
+ long len);
+void __sanitizer_syscall_post_impl_lookup_dcookie(long res, long cookie64,
+ long buf, long len);
+void __sanitizer_syscall_pre_impl_quotactl(long cmd, long special, long id,
+ long addr);
+void __sanitizer_syscall_post_impl_quotactl(long res, long cmd, long special,
+ long id, long addr);
+void __sanitizer_syscall_pre_impl_getdents(long fd, long dirent, long count);
+void __sanitizer_syscall_post_impl_getdents(long res, long fd, long dirent,
+ long count);
+void __sanitizer_syscall_pre_impl_getdents64(long fd, long dirent, long count);
+void __sanitizer_syscall_post_impl_getdents64(long res, long fd, long dirent,
+ long count);
+void __sanitizer_syscall_pre_impl_setsockopt(long fd, long level, long optname,
+ long optval, long optlen);
+void __sanitizer_syscall_post_impl_setsockopt(long res, long fd, long level,
+ long optname, long optval,
+ long optlen);
+void __sanitizer_syscall_pre_impl_getsockopt(long fd, long level, long optname,
+ long optval, long optlen);
+void __sanitizer_syscall_post_impl_getsockopt(long res, long fd, long level,
+ long optname, long optval,
+ long optlen);
+void __sanitizer_syscall_pre_impl_bind(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_bind(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_connect(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_connect(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_accept(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_accept(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_accept4(long arg0, long arg1, long arg2,
+ long arg3);
+void __sanitizer_syscall_post_impl_accept4(long res, long arg0, long arg1,
+ long arg2, long arg3);
+void __sanitizer_syscall_pre_impl_getsockname(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_getsockname(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_getpeername(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_getpeername(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_send(long arg0, long arg1, long arg2,
+ long arg3);
+void __sanitizer_syscall_post_impl_send(long res, long arg0, long arg1,
+ long arg2, long arg3);
+void __sanitizer_syscall_pre_impl_sendto(long arg0, long arg1, long arg2,
+ long arg3, long arg4, long arg5);
+void __sanitizer_syscall_post_impl_sendto(long res, long arg0, long arg1,
+ long arg2, long arg3, long arg4,
+ long arg5);
+void __sanitizer_syscall_pre_impl_sendmsg(long fd, long msg, long flags);
+void __sanitizer_syscall_post_impl_sendmsg(long res, long fd, long msg,
+ long flags);
+void __sanitizer_syscall_pre_impl_sendmmsg(long fd, long msg, long vlen,
+ long flags);
+void __sanitizer_syscall_post_impl_sendmmsg(long res, long fd, long msg,
+ long vlen, long flags);
+void __sanitizer_syscall_pre_impl_recv(long arg0, long arg1, long arg2,
+ long arg3);
+void __sanitizer_syscall_post_impl_recv(long res, long arg0, long arg1,
+ long arg2, long arg3);
+void __sanitizer_syscall_pre_impl_recvfrom(long arg0, long arg1, long arg2,
+ long arg3, long arg4, long arg5);
+void __sanitizer_syscall_post_impl_recvfrom(long res, long arg0, long arg1,
+ long arg2, long arg3, long arg4,
+ long arg5);
+void __sanitizer_syscall_pre_impl_recvmsg(long fd, long msg, long flags);
+void __sanitizer_syscall_post_impl_recvmsg(long res, long fd, long msg,
+ long flags);
+void __sanitizer_syscall_pre_impl_recvmmsg(long fd, long msg, long vlen,
+ long flags, long timeout);
+void __sanitizer_syscall_post_impl_recvmmsg(long res, long fd, long msg,
+ long vlen, long flags,
+ long timeout);
+void __sanitizer_syscall_pre_impl_socket(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_socket(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_socketpair(long arg0, long arg1, long arg2,
+ long arg3);
+void __sanitizer_syscall_post_impl_socketpair(long res, long arg0, long arg1,
+ long arg2, long arg3);
+void __sanitizer_syscall_pre_impl_socketcall(long call, long args);
+void __sanitizer_syscall_post_impl_socketcall(long res, long call, long args);
+void __sanitizer_syscall_pre_impl_listen(long arg0, long arg1);
+void __sanitizer_syscall_post_impl_listen(long res, long arg0, long arg1);
+void __sanitizer_syscall_pre_impl_poll(long ufds, long nfds, long timeout);
+void __sanitizer_syscall_post_impl_poll(long res, long ufds, long nfds,
+ long timeout);
+void __sanitizer_syscall_pre_impl_select(long n, long inp, long outp, long exp,
+ long tvp);
+void __sanitizer_syscall_post_impl_select(long res, long n, long inp, long outp,
+ long exp, long tvp);
+void __sanitizer_syscall_pre_impl_old_select(long arg);
+void __sanitizer_syscall_post_impl_old_select(long res, long arg);
+void __sanitizer_syscall_pre_impl_epoll_create(long size);
+void __sanitizer_syscall_post_impl_epoll_create(long res, long size);
+void __sanitizer_syscall_pre_impl_epoll_create1(long flags);
+void __sanitizer_syscall_post_impl_epoll_create1(long res, long flags);
+void __sanitizer_syscall_pre_impl_epoll_ctl(long epfd, long op, long fd,
+ long event);
+void __sanitizer_syscall_post_impl_epoll_ctl(long res, long epfd, long op,
+ long fd, long event);
+void __sanitizer_syscall_pre_impl_epoll_wait(long epfd, long events,
+ long maxevents, long timeout);
+void __sanitizer_syscall_post_impl_epoll_wait(long res, long epfd, long events,
+ long maxevents, long timeout);
+void __sanitizer_syscall_pre_impl_epoll_pwait(long epfd, long events,
+ long maxevents, long timeout,
+ long sigmask, long sigsetsize);
+void __sanitizer_syscall_post_impl_epoll_pwait(long res, long epfd, long events,
+ long maxevents, long timeout,
+ long sigmask, long sigsetsize);
+void __sanitizer_syscall_pre_impl_epoll_pwait2(long epfd, long events,
+ long maxevents, long timeout,
+ long sigmask, long sigsetsize);
+void __sanitizer_syscall_post_impl_epoll_pwait2(long res, long epfd,
+ long events, long maxevents,
+ long timeout, long sigmask,
+ long sigsetsize);
+void __sanitizer_syscall_pre_impl_gethostname(long name, long len);
+void __sanitizer_syscall_post_impl_gethostname(long res, long name, long len);
+void __sanitizer_syscall_pre_impl_sethostname(long name, long len);
+void __sanitizer_syscall_post_impl_sethostname(long res, long name, long len);
+void __sanitizer_syscall_pre_impl_setdomainname(long name, long len);
+void __sanitizer_syscall_post_impl_setdomainname(long res, long name, long len);
+void __sanitizer_syscall_pre_impl_newuname(long name);
+void __sanitizer_syscall_post_impl_newuname(long res, long name);
+void __sanitizer_syscall_pre_impl_uname(long arg0);
+void __sanitizer_syscall_post_impl_uname(long res, long arg0);
+void __sanitizer_syscall_pre_impl_olduname(long arg0);
+void __sanitizer_syscall_post_impl_olduname(long res, long arg0);
+void __sanitizer_syscall_pre_impl_getrlimit(long resource, long rlim);
+void __sanitizer_syscall_post_impl_getrlimit(long res, long resource,
+ long rlim);
+void __sanitizer_syscall_pre_impl_old_getrlimit(long resource, long rlim);
+void __sanitizer_syscall_post_impl_old_getrlimit(long res, long resource,
+ long rlim);
+void __sanitizer_syscall_pre_impl_setrlimit(long resource, long rlim);
+void __sanitizer_syscall_post_impl_setrlimit(long res, long resource,
+ long rlim);
+void __sanitizer_syscall_pre_impl_prlimit64(long pid, long resource,
+ long new_rlim, long old_rlim);
+void __sanitizer_syscall_post_impl_prlimit64(long res, long pid, long resource,
+ long new_rlim, long old_rlim);
+void __sanitizer_syscall_pre_impl_getrusage(long who, long ru);
+void __sanitizer_syscall_post_impl_getrusage(long res, long who, long ru);
+void __sanitizer_syscall_pre_impl_umask(long mask);
+void __sanitizer_syscall_post_impl_umask(long res, long mask);
+void __sanitizer_syscall_pre_impl_msgget(long key, long msgflg);
+void __sanitizer_syscall_post_impl_msgget(long res, long key, long msgflg);
+void __sanitizer_syscall_pre_impl_msgsnd(long msqid, long msgp, long msgsz,
+ long msgflg);
+void __sanitizer_syscall_post_impl_msgsnd(long res, long msqid, long msgp,
+ long msgsz, long msgflg);
+void __sanitizer_syscall_pre_impl_msgrcv(long msqid, long msgp, long msgsz,
+ long msgtyp, long msgflg);
+void __sanitizer_syscall_post_impl_msgrcv(long res, long msqid, long msgp,
+ long msgsz, long msgtyp, long msgflg);
+void __sanitizer_syscall_pre_impl_msgctl(long msqid, long cmd, long buf);
+void __sanitizer_syscall_post_impl_msgctl(long res, long msqid, long cmd,
+ long buf);
+void __sanitizer_syscall_pre_impl_semget(long key, long nsems, long semflg);
+void __sanitizer_syscall_post_impl_semget(long res, long key, long nsems,
+ long semflg);
+void __sanitizer_syscall_pre_impl_semop(long semid, long sops, long nsops);
+void __sanitizer_syscall_post_impl_semop(long res, long semid, long sops,
+ long nsops);
+void __sanitizer_syscall_pre_impl_semctl(long semid, long semnum, long cmd,
+ long arg);
+void __sanitizer_syscall_post_impl_semctl(long res, long semid, long semnum,
+ long cmd, long arg);
+void __sanitizer_syscall_pre_impl_semtimedop(long semid, long sops, long nsops,
+ long timeout);
+void __sanitizer_syscall_post_impl_semtimedop(long res, long semid, long sops,
+ long nsops, long timeout);
+void __sanitizer_syscall_pre_impl_shmat(long shmid, long shmaddr, long shmflg);
+void __sanitizer_syscall_post_impl_shmat(long res, long shmid, long shmaddr,
+ long shmflg);
+void __sanitizer_syscall_pre_impl_shmget(long key, long size, long flag);
+void __sanitizer_syscall_post_impl_shmget(long res, long key, long size,
+ long flag);
+void __sanitizer_syscall_pre_impl_shmdt(long shmaddr);
+void __sanitizer_syscall_post_impl_shmdt(long res, long shmaddr);
+void __sanitizer_syscall_pre_impl_shmctl(long shmid, long cmd, long buf);
+void __sanitizer_syscall_post_impl_shmctl(long res, long shmid, long cmd,
+ long buf);
+void __sanitizer_syscall_pre_impl_ipc(long call, long first, long second,
+ long third, long ptr, long fifth);
+void __sanitizer_syscall_post_impl_ipc(long res, long call, long first,
+ long second, long third, long ptr,
+ long fifth);
+void __sanitizer_syscall_pre_impl_mq_open(long name, long oflag, long mode,
+ long attr);
+void __sanitizer_syscall_post_impl_mq_open(long res, long name, long oflag,
+ long mode, long attr);
+void __sanitizer_syscall_pre_impl_mq_unlink(long name);
+void __sanitizer_syscall_post_impl_mq_unlink(long res, long name);
+void __sanitizer_syscall_pre_impl_mq_timedsend(long mqdes, long msg_ptr,
+ long msg_len, long msg_prio,
+ long abs_timeout);
+void __sanitizer_syscall_post_impl_mq_timedsend(long res, long mqdes,
+ long msg_ptr, long msg_len,
+ long msg_prio,
+ long abs_timeout);
+void __sanitizer_syscall_pre_impl_mq_timedreceive(long mqdes, long msg_ptr,
+ long msg_len, long msg_prio,
+ long abs_timeout);
+void __sanitizer_syscall_post_impl_mq_timedreceive(long res, long mqdes,
+ long msg_ptr, long msg_len,
+ long msg_prio,
+ long abs_timeout);
+void __sanitizer_syscall_pre_impl_mq_notify(long mqdes, long notification);
+void __sanitizer_syscall_post_impl_mq_notify(long res, long mqdes,
+ long notification);
+void __sanitizer_syscall_pre_impl_mq_getsetattr(long mqdes, long mqstat,
+ long omqstat);
+void __sanitizer_syscall_post_impl_mq_getsetattr(long res, long mqdes,
+ long mqstat, long omqstat);
+void __sanitizer_syscall_pre_impl_pciconfig_iobase(long which, long bus,
+ long devfn);
+void __sanitizer_syscall_post_impl_pciconfig_iobase(long res, long which,
+ long bus, long devfn);
+void __sanitizer_syscall_pre_impl_pciconfig_read(long bus, long dfn, long off,
+ long len, long buf);
+void __sanitizer_syscall_post_impl_pciconfig_read(long res, long bus, long dfn,
+ long off, long len, long buf);
+void __sanitizer_syscall_pre_impl_pciconfig_write(long bus, long dfn, long off,
+ long len, long buf);
+void __sanitizer_syscall_post_impl_pciconfig_write(long res, long bus, long dfn,
+ long off, long len,
+ long buf);
+void __sanitizer_syscall_pre_impl_swapon(long specialfile, long swap_flags);
+void __sanitizer_syscall_post_impl_swapon(long res, long specialfile,
+ long swap_flags);
+void __sanitizer_syscall_pre_impl_swapoff(long specialfile);
+void __sanitizer_syscall_post_impl_swapoff(long res, long specialfile);
+void __sanitizer_syscall_pre_impl_sysctl(long args);
+void __sanitizer_syscall_post_impl_sysctl(long res, long args);
+void __sanitizer_syscall_pre_impl_sysinfo(long info);
+void __sanitizer_syscall_post_impl_sysinfo(long res, long info);
+void __sanitizer_syscall_pre_impl_sysfs(long option, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_sysfs(long res, long option, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_syslog(long type, long buf, long len);
+void __sanitizer_syscall_post_impl_syslog(long res, long type, long buf,
+ long len);
+void __sanitizer_syscall_pre_impl_uselib(long library);
+void __sanitizer_syscall_post_impl_uselib(long res, long library);
+void __sanitizer_syscall_pre_impl_ni_syscall();
+void __sanitizer_syscall_post_impl_ni_syscall(long res);
+void __sanitizer_syscall_pre_impl_ptrace(long request, long pid, long addr,
+ long data);
+void __sanitizer_syscall_post_impl_ptrace(long res, long request, long pid,
+ long addr, long data);
+void __sanitizer_syscall_pre_impl_add_key(long _type, long _description,
+ long _payload, long plen,
+ long destringid);
+void __sanitizer_syscall_post_impl_add_key(long res, long _type,
+ long _description, long _payload,
+ long plen, long destringid);
+void __sanitizer_syscall_pre_impl_request_key(long _type, long _description,
+ long _callout_info,
+ long destringid);
+void __sanitizer_syscall_post_impl_request_key(long res, long _type,
+ long _description,
+ long _callout_info,
+ long destringid);
+void __sanitizer_syscall_pre_impl_keyctl(long cmd, long arg2, long arg3,
+ long arg4, long arg5);
+void __sanitizer_syscall_post_impl_keyctl(long res, long cmd, long arg2,
+ long arg3, long arg4, long arg5);
+void __sanitizer_syscall_pre_impl_ioprio_set(long which, long who, long ioprio);
+void __sanitizer_syscall_post_impl_ioprio_set(long res, long which, long who,
+ long ioprio);
+void __sanitizer_syscall_pre_impl_ioprio_get(long which, long who);
+void __sanitizer_syscall_post_impl_ioprio_get(long res, long which, long who);
+void __sanitizer_syscall_pre_impl_set_mempolicy(long mode, long nmask,
+ long maxnode);
+void __sanitizer_syscall_post_impl_set_mempolicy(long res, long mode,
+ long nmask, long maxnode);
+void __sanitizer_syscall_pre_impl_migrate_pages(long pid, long maxnode,
+ long from, long to);
+void __sanitizer_syscall_post_impl_migrate_pages(long res, long pid,
+ long maxnode, long from,
+ long to);
+void __sanitizer_syscall_pre_impl_move_pages(long pid, long nr_pages,
+ long pages, long nodes,
+ long status, long flags);
+void __sanitizer_syscall_post_impl_move_pages(long res, long pid, long nr_pages,
+ long pages, long nodes,
+ long status, long flags);
+void __sanitizer_syscall_pre_impl_mbind(long start, long len, long mode,
+ long nmask, long maxnode, long flags);
+void __sanitizer_syscall_post_impl_mbind(long res, long start, long len,
+ long mode, long nmask, long maxnode,
+ long flags);
+void __sanitizer_syscall_pre_impl_get_mempolicy(long policy, long nmask,
+ long maxnode, long addr,
+ long flags);
+void __sanitizer_syscall_post_impl_get_mempolicy(long res, long policy,
+ long nmask, long maxnode,
+ long addr, long flags);
+void __sanitizer_syscall_pre_impl_inotify_init();
+void __sanitizer_syscall_post_impl_inotify_init(long res);
+void __sanitizer_syscall_pre_impl_inotify_init1(long flags);
+void __sanitizer_syscall_post_impl_inotify_init1(long res, long flags);
+void __sanitizer_syscall_pre_impl_inotify_add_watch(long fd, long path,
+ long mask);
+void __sanitizer_syscall_post_impl_inotify_add_watch(long res, long fd,
+ long path, long mask);
+void __sanitizer_syscall_pre_impl_inotify_rm_watch(long fd, long wd);
+void __sanitizer_syscall_post_impl_inotify_rm_watch(long res, long fd, long wd);
+void __sanitizer_syscall_pre_impl_spu_run(long fd, long unpc, long ustatus);
+void __sanitizer_syscall_post_impl_spu_run(long res, long fd, long unpc,
+ long ustatus);
+void __sanitizer_syscall_pre_impl_spu_create(long name, long flags, long mode,
+ long fd);
+void __sanitizer_syscall_post_impl_spu_create(long res, long name, long flags,
+ long mode, long fd);
+void __sanitizer_syscall_pre_impl_mknodat(long dfd, long filename, long mode,
+ long dev);
+void __sanitizer_syscall_post_impl_mknodat(long res, long dfd, long filename,
+ long mode, long dev);
+void __sanitizer_syscall_pre_impl_mkdirat(long dfd, long pathname, long mode);
+void __sanitizer_syscall_post_impl_mkdirat(long res, long dfd, long pathname,
+ long mode);
+void __sanitizer_syscall_pre_impl_unlinkat(long dfd, long pathname, long flag);
+void __sanitizer_syscall_post_impl_unlinkat(long res, long dfd, long pathname,
+ long flag);
+void __sanitizer_syscall_pre_impl_symlinkat(long oldname, long newdfd,
+ long newname);
+void __sanitizer_syscall_post_impl_symlinkat(long res, long oldname,
+ long newdfd, long newname);
+void __sanitizer_syscall_pre_impl_linkat(long olddfd, long oldname, long newdfd,
+ long newname, long flags);
+void __sanitizer_syscall_post_impl_linkat(long res, long olddfd, long oldname,
+ long newdfd, long newname,
+ long flags);
+void __sanitizer_syscall_pre_impl_renameat(long olddfd, long oldname,
+ long newdfd, long newname);
+void __sanitizer_syscall_post_impl_renameat(long res, long olddfd, long oldname,
+ long newdfd, long newname);
+void __sanitizer_syscall_pre_impl_futimesat(long dfd, long filename,
+ long utimes);
+void __sanitizer_syscall_post_impl_futimesat(long res, long dfd, long filename,
+ long utimes);
+void __sanitizer_syscall_pre_impl_faccessat(long dfd, long filename, long mode);
+void __sanitizer_syscall_post_impl_faccessat(long res, long dfd, long filename,
+ long mode);
+void __sanitizer_syscall_pre_impl_fchmodat(long dfd, long filename, long mode);
+void __sanitizer_syscall_post_impl_fchmodat(long res, long dfd, long filename,
+ long mode);
+void __sanitizer_syscall_pre_impl_fchownat(long dfd, long filename, long user,
+ long group, long flag);
+void __sanitizer_syscall_post_impl_fchownat(long res, long dfd, long filename,
+ long user, long group, long flag);
+void __sanitizer_syscall_pre_impl_openat(long dfd, long filename, long flags,
+ long mode);
+void __sanitizer_syscall_post_impl_openat(long res, long dfd, long filename,
+ long flags, long mode);
+void __sanitizer_syscall_pre_impl_newfstatat(long dfd, long filename,
+ long statbuf, long flag);
+void __sanitizer_syscall_post_impl_newfstatat(long res, long dfd, long filename,
+ long statbuf, long flag);
+void __sanitizer_syscall_pre_impl_fstatat64(long dfd, long filename,
+ long statbuf, long flag);
+void __sanitizer_syscall_post_impl_fstatat64(long res, long dfd, long filename,
+ long statbuf, long flag);
+void __sanitizer_syscall_pre_impl_readlinkat(long dfd, long path, long buf,
+ long bufsiz);
+void __sanitizer_syscall_post_impl_readlinkat(long res, long dfd, long path,
+ long buf, long bufsiz);
+void __sanitizer_syscall_pre_impl_utimensat(long dfd, long filename,
+ long utimes, long flags);
+void __sanitizer_syscall_post_impl_utimensat(long res, long dfd, long filename,
+ long utimes, long flags);
+void __sanitizer_syscall_pre_impl_unshare(long unshare_flags);
+void __sanitizer_syscall_post_impl_unshare(long res, long unshare_flags);
+void __sanitizer_syscall_pre_impl_splice(long fd_in, long off_in, long fd_out,
+ long off_out, long len, long flags);
+void __sanitizer_syscall_post_impl_splice(long res, long fd_in, long off_in,
+ long fd_out, long off_out, long len,
+ long flags);
+void __sanitizer_syscall_pre_impl_vmsplice(long fd, long iov, long nr_segs,
+ long flags);
+void __sanitizer_syscall_post_impl_vmsplice(long res, long fd, long iov,
+ long nr_segs, long flags);
+void __sanitizer_syscall_pre_impl_tee(long fdin, long fdout, long len,
+ long flags);
+void __sanitizer_syscall_post_impl_tee(long res, long fdin, long fdout,
+ long len, long flags);
+void __sanitizer_syscall_pre_impl_get_robust_list(long pid, long head_ptr,
+ long len_ptr);
+void __sanitizer_syscall_post_impl_get_robust_list(long res, long pid,
+ long head_ptr, long len_ptr);
+void __sanitizer_syscall_pre_impl_set_robust_list(long head, long len);
+void __sanitizer_syscall_post_impl_set_robust_list(long res, long head,
+ long len);
+void __sanitizer_syscall_pre_impl_getcpu(long cpu, long node, long cache);
+void __sanitizer_syscall_post_impl_getcpu(long res, long cpu, long node,
+ long cache);
+void __sanitizer_syscall_pre_impl_signalfd(long ufd, long user_mask,
+ long sizemask);
+void __sanitizer_syscall_post_impl_signalfd(long res, long ufd, long user_mask,
+ long sizemask);
+void __sanitizer_syscall_pre_impl_signalfd4(long ufd, long user_mask,
+ long sizemask, long flags);
+void __sanitizer_syscall_post_impl_signalfd4(long res, long ufd, long user_mask,
+ long sizemask, long flags);
+void __sanitizer_syscall_pre_impl_timerfd_create(long clockid, long flags);
+void __sanitizer_syscall_post_impl_timerfd_create(long res, long clockid,
+ long flags);
+void __sanitizer_syscall_pre_impl_timerfd_settime(long ufd, long flags,
+ long utmr, long otmr);
+void __sanitizer_syscall_post_impl_timerfd_settime(long res, long ufd,
+ long flags, long utmr,
+ long otmr);
+void __sanitizer_syscall_pre_impl_timerfd_gettime(long ufd, long otmr);
+void __sanitizer_syscall_post_impl_timerfd_gettime(long res, long ufd,
+ long otmr);
+void __sanitizer_syscall_pre_impl_eventfd(long count);
+void __sanitizer_syscall_post_impl_eventfd(long res, long count);
+void __sanitizer_syscall_pre_impl_eventfd2(long count, long flags);
+void __sanitizer_syscall_post_impl_eventfd2(long res, long count, long flags);
+void __sanitizer_syscall_pre_impl_old_readdir(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_old_readdir(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_pselect6(long arg0, long arg1, long arg2,
+ long arg3, long arg4, long arg5);
+void __sanitizer_syscall_post_impl_pselect6(long res, long arg0, long arg1,
+ long arg2, long arg3, long arg4,
+ long arg5);
+void __sanitizer_syscall_pre_impl_ppoll(long arg0, long arg1, long arg2,
+ long arg3, long arg4);
+void __sanitizer_syscall_post_impl_ppoll(long res, long arg0, long arg1,
+ long arg2, long arg3, long arg4);
+void __sanitizer_syscall_pre_impl_fanotify_init(long flags, long event_f_flags);
+void __sanitizer_syscall_post_impl_fanotify_init(long res, long flags,
+ long event_f_flags);
+void __sanitizer_syscall_pre_impl_fanotify_mark(long fanotify_fd, long flags,
+ long mask, long fd,
+ long pathname);
+void __sanitizer_syscall_post_impl_fanotify_mark(long res, long fanotify_fd,
+ long flags, long mask, long fd,
+ long pathname);
+void __sanitizer_syscall_pre_impl_syncfs(long fd);
+void __sanitizer_syscall_post_impl_syncfs(long res, long fd);
+void __sanitizer_syscall_pre_impl_perf_event_open(long attr_uptr, long pid,
+ long cpu, long group_fd,
+ long flags);
+void __sanitizer_syscall_post_impl_perf_event_open(long res, long attr_uptr,
+ long pid, long cpu,
+ long group_fd, long flags);
+void __sanitizer_syscall_pre_impl_mmap_pgoff(long addr, long len, long prot,
+ long flags, long fd, long pgoff);
+void __sanitizer_syscall_post_impl_mmap_pgoff(long res, long addr, long len,
+ long prot, long flags, long fd,
+ long pgoff);
+void __sanitizer_syscall_pre_impl_old_mmap(long arg);
+void __sanitizer_syscall_post_impl_old_mmap(long res, long arg);
+void __sanitizer_syscall_pre_impl_name_to_handle_at(long dfd, long name,
+ long handle, long mnt_id,
+ long flag);
+void __sanitizer_syscall_post_impl_name_to_handle_at(long res, long dfd,
+ long name, long handle,
+ long mnt_id, long flag);
+void __sanitizer_syscall_pre_impl_open_by_handle_at(long mountdirfd,
+ long handle, long flags);
+void __sanitizer_syscall_post_impl_open_by_handle_at(long res, long mountdirfd,
+ long handle, long flags);
+void __sanitizer_syscall_pre_impl_setns(long fd, long nstype);
+void __sanitizer_syscall_post_impl_setns(long res, long fd, long nstype);
+void __sanitizer_syscall_pre_impl_process_vm_readv(long pid, long lvec,
+ long liovcnt, long rvec,
+ long riovcnt, long flags);
+void __sanitizer_syscall_post_impl_process_vm_readv(long res, long pid,
+ long lvec, long liovcnt,
+ long rvec, long riovcnt,
+ long flags);
+void __sanitizer_syscall_pre_impl_process_vm_writev(long pid, long lvec,
+ long liovcnt, long rvec,
+ long riovcnt, long flags);
+void __sanitizer_syscall_post_impl_process_vm_writev(long res, long pid,
+ long lvec, long liovcnt,
+ long rvec, long riovcnt,
+ long flags);
+void __sanitizer_syscall_pre_impl_fork();
+void __sanitizer_syscall_post_impl_fork(long res);
+void __sanitizer_syscall_pre_impl_vfork();
+void __sanitizer_syscall_post_impl_vfork(long res);
+void __sanitizer_syscall_pre_impl_sigaction(long signum, long act, long oldact);
+void __sanitizer_syscall_post_impl_sigaction(long res, long signum, long act,
+ long oldact);
+void __sanitizer_syscall_pre_impl_rt_sigaction(long signum, long act,
+ long oldact, long sz);
+void __sanitizer_syscall_post_impl_rt_sigaction(long res, long signum, long act,
+ long oldact, long sz);
+void __sanitizer_syscall_pre_impl_sigaltstack(long ss, long oss);
+void __sanitizer_syscall_post_impl_sigaltstack(long res, long ss, long oss);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // SANITIZER_LINUX_SYSCALL_HOOKS_H
diff --git a/contrib/libs/clang16-rt/include/sanitizer/memprof_interface.h b/contrib/libs/clang16-rt/include/sanitizer/memprof_interface.h
new file mode 100644
index 00000000000..76031de4014
--- /dev/null
+++ b/contrib/libs/clang16-rt/include/sanitizer/memprof_interface.h
@@ -0,0 +1,65 @@
+//===-- sanitizer/memprof_interface.h --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler (MemProf).
+//
+// Public interface header.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_MEMPROF_INTERFACE_H
+#define SANITIZER_MEMPROF_INTERFACE_H
+
+#include <sanitizer/common_interface_defs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/// Records access to a memory region (<c>[addr, addr+size)</c>).
+///
+/// This memory must be previously allocated by your program.
+///
+/// \param addr Start of memory region.
+/// \param size Size of memory region.
+void __memprof_record_access_range(void const volatile *addr, size_t size);
+
+/// Records access to a memory address <c><i>addr</i></c>.
+///
+/// This memory must be previously allocated by your program.
+///
+/// \param addr Accessed memory address
+void __memprof_record_access(void const volatile *addr);
+
+/// User-provided callback on MemProf errors.
+///
+/// You can provide a function that would be called immediately when MemProf
+/// detects an error. This is useful in cases when MemProf detects an error but
+/// your program crashes before the MemProf report is printed.
+void __memprof_on_error(void);
+
+/// Prints accumulated statistics to <c>stderr</c> (useful for calling from the
+/// debugger).
+void __memprof_print_accumulated_stats(void);
+
+/// User-provided default option settings.
+///
+/// You can provide your own implementation of this function to return a string
+/// containing MemProf runtime options (for example,
+/// <c>verbosity=1:print_stats=1</c>).
+///
+/// \returns Default options string.
+const char *__memprof_default_options(void);
+
+/// Prints the memory profile to the current profile file.
+///
+/// \returns 0 on success.
+int __memprof_profile_dump(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // SANITIZER_MEMPROF_INTERFACE_H
diff --git a/contrib/libs/clang16-rt/include/sanitizer/netbsd_syscall_hooks.h b/contrib/libs/clang16-rt/include/sanitizer/netbsd_syscall_hooks.h
new file mode 100644
index 00000000000..f661152ccba
--- /dev/null
+++ b/contrib/libs/clang16-rt/include/sanitizer/netbsd_syscall_hooks.h
@@ -0,0 +1,5005 @@
+//===-- netbsd_syscall_hooks.h --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of public sanitizer interface.
+//
+// System call handlers.
+//
+// Interface methods declared in this header implement pre- and post- syscall
+// actions for the active sanitizer.
+// Usage:
+// __sanitizer_syscall_pre_getfoo(...args...);
+// long long res = syscall(SYS_getfoo, ...args...);
+// __sanitizer_syscall_post_getfoo(res, ...args...);
+//
+// DO NOT EDIT! THIS FILE HAS BEEN GENERATED!
+//
+// Generated with: generate_netbsd_syscalls.awk
+// Generated date: 2020-09-10
+// Generated from: syscalls.master,v 1.306 2020/08/14 00:53:16 riastradh Exp
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_NETBSD_SYSCALL_HOOKS_H
+#define SANITIZER_NETBSD_SYSCALL_HOOKS_H
+
+#define __sanitizer_syscall_pre_syscall(code, arg0, arg1, arg2, arg3, arg4, \
+ arg5, arg6, arg7) \
+ __sanitizer_syscall_pre_impl_syscall( \
+ (long long)(code), (long long)(arg0), (long long)(arg1), \
+ (long long)(arg2), (long long)(arg3), (long long)(arg4), \
+ (long long)(arg5), (long long)(arg6), (long long)(arg7))
+#define __sanitizer_syscall_post_syscall(res, code, arg0, arg1, arg2, arg3, \
+ arg4, arg5, arg6, arg7) \
+ __sanitizer_syscall_post_impl_syscall( \
+ res, (long long)(code), (long long)(arg0), (long long)(arg1), \
+ (long long)(arg2), (long long)(arg3), (long long)(arg4), \
+ (long long)(arg5), (long long)(arg6), (long long)(arg7))
+#define __sanitizer_syscall_pre_exit(rval) \
+ __sanitizer_syscall_pre_impl_exit((long long)(rval))
+#define __sanitizer_syscall_post_exit(res, rval) \
+ __sanitizer_syscall_post_impl_exit(res, (long long)(rval))
+#define __sanitizer_syscall_pre_fork() __sanitizer_syscall_pre_impl_fork()
+#define __sanitizer_syscall_post_fork(res) \
+ __sanitizer_syscall_post_impl_fork(res)
+#define __sanitizer_syscall_pre_read(fd, buf, nbyte) \
+ __sanitizer_syscall_pre_impl_read((long long)(fd), (long long)(buf), \
+ (long long)(nbyte))
+#define __sanitizer_syscall_post_read(res, fd, buf, nbyte) \
+ __sanitizer_syscall_post_impl_read(res, (long long)(fd), (long long)(buf), \
+ (long long)(nbyte))
+#define __sanitizer_syscall_pre_write(fd, buf, nbyte) \
+ __sanitizer_syscall_pre_impl_write((long long)(fd), (long long)(buf), \
+ (long long)(nbyte))
+#define __sanitizer_syscall_post_write(res, fd, buf, nbyte) \
+ __sanitizer_syscall_post_impl_write(res, (long long)(fd), (long long)(buf), \
+ (long long)(nbyte))
+#define __sanitizer_syscall_pre_open(path, flags, mode) \
+ __sanitizer_syscall_pre_impl_open((long long)(path), (long long)(flags), \
+ (long long)(mode))
+#define __sanitizer_syscall_post_open(res, path, flags, mode) \
+ __sanitizer_syscall_post_impl_open(res, (long long)(path), \
+ (long long)(flags), (long long)(mode))
+#define __sanitizer_syscall_pre_close(fd) \
+ __sanitizer_syscall_pre_impl_close((long long)(fd))
+#define __sanitizer_syscall_post_close(res, fd) \
+ __sanitizer_syscall_post_impl_close(res, (long long)(fd))
+#define __sanitizer_syscall_pre_compat_50_wait4(pid, status, options, rusage) \
+ __sanitizer_syscall_pre_impl_compat_50_wait4( \
+ (long long)(pid), (long long)(status), (long long)(options), \
+ (long long)(rusage))
+#define __sanitizer_syscall_post_compat_50_wait4(res, pid, status, options, \
+ rusage) \
+ __sanitizer_syscall_post_impl_compat_50_wait4( \
+ res, (long long)(pid), (long long)(status), (long long)(options), \
+ (long long)(rusage))
+#define __sanitizer_syscall_pre_compat_43_ocreat(path, mode) \
+ __sanitizer_syscall_pre_impl_compat_43_ocreat((long long)(path), \
+ (long long)(mode))
+#define __sanitizer_syscall_post_compat_43_ocreat(res, path, mode) \
+ __sanitizer_syscall_post_impl_compat_43_ocreat(res, (long long)(path), \
+ (long long)(mode))
+#define __sanitizer_syscall_pre_link(path, link) \
+ __sanitizer_syscall_pre_impl_link((long long)(path), (long long)(link))
+#define __sanitizer_syscall_post_link(res, path, link) \
+ __sanitizer_syscall_post_impl_link(res, (long long)(path), (long long)(link))
+#define __sanitizer_syscall_pre_unlink(path) \
+ __sanitizer_syscall_pre_impl_unlink((long long)(path))
+#define __sanitizer_syscall_post_unlink(res, path) \
+ __sanitizer_syscall_post_impl_unlink(res, (long long)(path))
+/* syscall 11 has been skipped */
+#define __sanitizer_syscall_pre_chdir(path) \
+ __sanitizer_syscall_pre_impl_chdir((long long)(path))
+#define __sanitizer_syscall_post_chdir(res, path) \
+ __sanitizer_syscall_post_impl_chdir(res, (long long)(path))
+#define __sanitizer_syscall_pre_fchdir(fd) \
+ __sanitizer_syscall_pre_impl_fchdir((long long)(fd))
+#define __sanitizer_syscall_post_fchdir(res, fd) \
+ __sanitizer_syscall_post_impl_fchdir(res, (long long)(fd))
+#define __sanitizer_syscall_pre_compat_50_mknod(path, mode, dev) \
+ __sanitizer_syscall_pre_impl_compat_50_mknod( \
+ (long long)(path), (long long)(mode), (long long)(dev))
+#define __sanitizer_syscall_post_compat_50_mknod(res, path, mode, dev) \
+ __sanitizer_syscall_post_impl_compat_50_mknod( \
+ res, (long long)(path), (long long)(mode), (long long)(dev))
+#define __sanitizer_syscall_pre_chmod(path, mode) \
+ __sanitizer_syscall_pre_impl_chmod((long long)(path), (long long)(mode))
+#define __sanitizer_syscall_post_chmod(res, path, mode) \
+ __sanitizer_syscall_post_impl_chmod(res, (long long)(path), (long long)(mode))
+#define __sanitizer_syscall_pre_chown(path, uid, gid) \
+ __sanitizer_syscall_pre_impl_chown((long long)(path), (long long)(uid), \
+ (long long)(gid))
+#define __sanitizer_syscall_post_chown(res, path, uid, gid) \
+ __sanitizer_syscall_post_impl_chown(res, (long long)(path), \
+ (long long)(uid), (long long)(gid))
+#define __sanitizer_syscall_pre_break(nsize) \
+ __sanitizer_syscall_pre_impl_break((long long)(nsize))
+#define __sanitizer_syscall_post_break(res, nsize) \
+ __sanitizer_syscall_post_impl_break(res, (long long)(nsize))
+#define __sanitizer_syscall_pre_compat_20_getfsstat(buf, bufsize, flags) \
+ __sanitizer_syscall_pre_impl_compat_20_getfsstat( \
+ (long long)(buf), (long long)(bufsize), (long long)(flags))
+#define __sanitizer_syscall_post_compat_20_getfsstat(res, buf, bufsize, flags) \
+ __sanitizer_syscall_post_impl_compat_20_getfsstat( \
+ res, (long long)(buf), (long long)(bufsize), (long long)(flags))
+#define __sanitizer_syscall_pre_compat_43_olseek(fd, offset, whence) \
+ __sanitizer_syscall_pre_impl_compat_43_olseek( \
+ (long long)(fd), (long long)(offset), (long long)(whence))
+#define __sanitizer_syscall_post_compat_43_olseek(res, fd, offset, whence) \
+ __sanitizer_syscall_post_impl_compat_43_olseek( \
+ res, (long long)(fd), (long long)(offset), (long long)(whence))
+#define __sanitizer_syscall_pre_getpid() __sanitizer_syscall_pre_impl_getpid()
+#define __sanitizer_syscall_post_getpid(res) \
+ __sanitizer_syscall_post_impl_getpid(res)
+#define __sanitizer_syscall_pre_compat_40_mount(type, path, flags, data) \
+ __sanitizer_syscall_pre_impl_compat_40_mount( \
+ (long long)(type), (long long)(path), (long long)(flags), \
+ (long long)(data))
+#define __sanitizer_syscall_post_compat_40_mount(res, type, path, flags, data) \
+ __sanitizer_syscall_post_impl_compat_40_mount( \
+ res, (long long)(type), (long long)(path), (long long)(flags), \
+ (long long)(data))
+#define __sanitizer_syscall_pre_unmount(path, flags) \
+ __sanitizer_syscall_pre_impl_unmount((long long)(path), (long long)(flags))
+#define __sanitizer_syscall_post_unmount(res, path, flags) \
+ __sanitizer_syscall_post_impl_unmount(res, (long long)(path), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_setuid(uid) \
+ __sanitizer_syscall_pre_impl_setuid((long long)(uid))
+#define __sanitizer_syscall_post_setuid(res, uid) \
+ __sanitizer_syscall_post_impl_setuid(res, (long long)(uid))
+#define __sanitizer_syscall_pre_getuid() __sanitizer_syscall_pre_impl_getuid()
+#define __sanitizer_syscall_post_getuid(res) \
+ __sanitizer_syscall_post_impl_getuid(res)
+#define __sanitizer_syscall_pre_geteuid() __sanitizer_syscall_pre_impl_geteuid()
+#define __sanitizer_syscall_post_geteuid(res) \
+ __sanitizer_syscall_post_impl_geteuid(res)
+#define __sanitizer_syscall_pre_ptrace(req, pid, addr, data) \
+ __sanitizer_syscall_pre_impl_ptrace((long long)(req), (long long)(pid), \
+ (long long)(addr), (long long)(data))
+#define __sanitizer_syscall_post_ptrace(res, req, pid, addr, data) \
+ __sanitizer_syscall_post_impl_ptrace(res, (long long)(req), \
+ (long long)(pid), (long long)(addr), \
+ (long long)(data))
+#define __sanitizer_syscall_pre_recvmsg(s, msg, flags) \
+ __sanitizer_syscall_pre_impl_recvmsg((long long)(s), (long long)(msg), \
+ (long long)(flags))
+#define __sanitizer_syscall_post_recvmsg(res, s, msg, flags) \
+ __sanitizer_syscall_post_impl_recvmsg(res, (long long)(s), (long long)(msg), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_sendmsg(s, msg, flags) \
+ __sanitizer_syscall_pre_impl_sendmsg((long long)(s), (long long)(msg), \
+ (long long)(flags))
+#define __sanitizer_syscall_post_sendmsg(res, s, msg, flags) \
+ __sanitizer_syscall_post_impl_sendmsg(res, (long long)(s), (long long)(msg), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_recvfrom(s, buf, len, flags, from, \
+ fromlenaddr) \
+ __sanitizer_syscall_pre_impl_recvfrom( \
+ (long long)(s), (long long)(buf), (long long)(len), (long long)(flags), \
+ (long long)(from), (long long)(fromlenaddr))
+#define __sanitizer_syscall_post_recvfrom(res, s, buf, len, flags, from, \
+ fromlenaddr) \
+ __sanitizer_syscall_post_impl_recvfrom( \
+ res, (long long)(s), (long long)(buf), (long long)(len), \
+ (long long)(flags), (long long)(from), (long long)(fromlenaddr))
+#define __sanitizer_syscall_pre_accept(s, name, anamelen) \
+ __sanitizer_syscall_pre_impl_accept((long long)(s), (long long)(name), \
+ (long long)(anamelen))
+#define __sanitizer_syscall_post_accept(res, s, name, anamelen) \
+ __sanitizer_syscall_post_impl_accept(res, (long long)(s), (long long)(name), \
+ (long long)(anamelen))
+#define __sanitizer_syscall_pre_getpeername(fdes, asa, alen) \
+ __sanitizer_syscall_pre_impl_getpeername( \
+ (long long)(fdes), (long long)(asa), (long long)(alen))
+#define __sanitizer_syscall_post_getpeername(res, fdes, asa, alen) \
+ __sanitizer_syscall_post_impl_getpeername( \
+ res, (long long)(fdes), (long long)(asa), (long long)(alen))
+#define __sanitizer_syscall_pre_getsockname(fdes, asa, alen) \
+ __sanitizer_syscall_pre_impl_getsockname( \
+ (long long)(fdes), (long long)(asa), (long long)(alen))
+#define __sanitizer_syscall_post_getsockname(res, fdes, asa, alen) \
+ __sanitizer_syscall_post_impl_getsockname( \
+ res, (long long)(fdes), (long long)(asa), (long long)(alen))
+#define __sanitizer_syscall_pre_access(path, flags) \
+ __sanitizer_syscall_pre_impl_access((long long)(path), (long long)(flags))
+#define __sanitizer_syscall_post_access(res, path, flags) \
+ __sanitizer_syscall_post_impl_access(res, (long long)(path), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_chflags(path, flags) \
+ __sanitizer_syscall_pre_impl_chflags((long long)(path), (long long)(flags))
+#define __sanitizer_syscall_post_chflags(res, path, flags) \
+ __sanitizer_syscall_post_impl_chflags(res, (long long)(path), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_fchflags(fd, flags) \
+ __sanitizer_syscall_pre_impl_fchflags((long long)(fd), (long long)(flags))
+#define __sanitizer_syscall_post_fchflags(res, fd, flags) \
+ __sanitizer_syscall_post_impl_fchflags(res, (long long)(fd), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_sync() __sanitizer_syscall_pre_impl_sync()
+#define __sanitizer_syscall_post_sync(res) \
+ __sanitizer_syscall_post_impl_sync(res)
+#define __sanitizer_syscall_pre_kill(pid, signum) \
+ __sanitizer_syscall_pre_impl_kill((long long)(pid), (long long)(signum))
+#define __sanitizer_syscall_post_kill(res, pid, signum) \
+ __sanitizer_syscall_post_impl_kill(res, (long long)(pid), (long long)(signum))
+#define __sanitizer_syscall_pre_compat_43_stat43(path, ub) \
+ __sanitizer_syscall_pre_impl_compat_43_stat43((long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_post_compat_43_stat43(res, path, ub) \
+ __sanitizer_syscall_post_impl_compat_43_stat43(res, (long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_pre_getppid() __sanitizer_syscall_pre_impl_getppid()
+#define __sanitizer_syscall_post_getppid(res) \
+ __sanitizer_syscall_post_impl_getppid(res)
+#define __sanitizer_syscall_pre_compat_43_lstat43(path, ub) \
+ __sanitizer_syscall_pre_impl_compat_43_lstat43((long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_post_compat_43_lstat43(res, path, ub) \
+ __sanitizer_syscall_post_impl_compat_43_lstat43(res, (long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_pre_dup(fd) \
+ __sanitizer_syscall_pre_impl_dup((long long)(fd))
+#define __sanitizer_syscall_post_dup(res, fd) \
+ __sanitizer_syscall_post_impl_dup(res, (long long)(fd))
+#define __sanitizer_syscall_pre_pipe() __sanitizer_syscall_pre_impl_pipe()
+#define __sanitizer_syscall_post_pipe(res) \
+ __sanitizer_syscall_post_impl_pipe(res)
+#define __sanitizer_syscall_pre_getegid() __sanitizer_syscall_pre_impl_getegid()
+#define __sanitizer_syscall_post_getegid(res) \
+ __sanitizer_syscall_post_impl_getegid(res)
+#define __sanitizer_syscall_pre_profil(samples, size, offset, scale) \
+ __sanitizer_syscall_pre_impl_profil((long long)(samples), (long long)(size), \
+ (long long)(offset), (long long)(scale))
+#define __sanitizer_syscall_post_profil(res, samples, size, offset, scale) \
+ __sanitizer_syscall_post_impl_profil(res, (long long)(samples), \
+ (long long)(size), (long long)(offset), \
+ (long long)(scale))
+#define __sanitizer_syscall_pre_ktrace(fname, ops, facs, pid) \
+ __sanitizer_syscall_pre_impl_ktrace((long long)(fname), (long long)(ops), \
+ (long long)(facs), (long long)(pid))
+#define __sanitizer_syscall_post_ktrace(res, fname, ops, facs, pid) \
+ __sanitizer_syscall_post_impl_ktrace(res, (long long)(fname), \
+ (long long)(ops), (long long)(facs), \
+ (long long)(pid))
+#define __sanitizer_syscall_pre_compat_13_sigaction13(signum, nsa, osa) \
+ __sanitizer_syscall_pre_impl_compat_13_sigaction13( \
+ (long long)(signum), (long long)(nsa), (long long)(osa))
+#define __sanitizer_syscall_post_compat_13_sigaction13(res, signum, nsa, osa) \
+ __sanitizer_syscall_post_impl_compat_13_sigaction13( \
+ res, (long long)(signum), (long long)(nsa), (long long)(osa))
+#define __sanitizer_syscall_pre_getgid() __sanitizer_syscall_pre_impl_getgid()
+#define __sanitizer_syscall_post_getgid(res) \
+ __sanitizer_syscall_post_impl_getgid(res)
+#define __sanitizer_syscall_pre_compat_13_sigprocmask13(how, mask) \
+ __sanitizer_syscall_pre_impl_compat_13_sigprocmask13((long long)(how), \
+ (long long)(mask))
+#define __sanitizer_syscall_post_compat_13_sigprocmask13(res, how, mask) \
+ __sanitizer_syscall_post_impl_compat_13_sigprocmask13(res, (long long)(how), \
+ (long long)(mask))
+#define __sanitizer_syscall_pre___getlogin(namebuf, namelen) \
+ __sanitizer_syscall_pre_impl___getlogin((long long)(namebuf), \
+ (long long)(namelen))
+#define __sanitizer_syscall_post___getlogin(res, namebuf, namelen) \
+ __sanitizer_syscall_post_impl___getlogin(res, (long long)(namebuf), \
+ (long long)(namelen))
+#define __sanitizer_syscall_pre___setlogin(namebuf) \
+ __sanitizer_syscall_pre_impl___setlogin((long long)(namebuf))
+#define __sanitizer_syscall_post___setlogin(res, namebuf) \
+ __sanitizer_syscall_post_impl___setlogin(res, (long long)(namebuf))
+#define __sanitizer_syscall_pre_acct(path) \
+ __sanitizer_syscall_pre_impl_acct((long long)(path))
+#define __sanitizer_syscall_post_acct(res, path) \
+ __sanitizer_syscall_post_impl_acct(res, (long long)(path))
+#define __sanitizer_syscall_pre_compat_13_sigpending13() \
+ __sanitizer_syscall_pre_impl_compat_13_sigpending13()
+#define __sanitizer_syscall_post_compat_13_sigpending13(res) \
+ __sanitizer_syscall_post_impl_compat_13_sigpending13(res)
+#define __sanitizer_syscall_pre_compat_13_sigaltstack13(nss, oss) \
+ __sanitizer_syscall_pre_impl_compat_13_sigaltstack13((long long)(nss), \
+ (long long)(oss))
+#define __sanitizer_syscall_post_compat_13_sigaltstack13(res, nss, oss) \
+ __sanitizer_syscall_post_impl_compat_13_sigaltstack13(res, (long long)(nss), \
+ (long long)(oss))
+#define __sanitizer_syscall_pre_ioctl(fd, com, data) \
+ __sanitizer_syscall_pre_impl_ioctl((long long)(fd), (long long)(com), \
+ (long long)(data))
+#define __sanitizer_syscall_post_ioctl(res, fd, com, data) \
+ __sanitizer_syscall_post_impl_ioctl(res, (long long)(fd), (long long)(com), \
+ (long long)(data))
+#define __sanitizer_syscall_pre_compat_12_oreboot(opt) \
+ __sanitizer_syscall_pre_impl_compat_12_oreboot((long long)(opt))
+#define __sanitizer_syscall_post_compat_12_oreboot(res, opt) \
+ __sanitizer_syscall_post_impl_compat_12_oreboot(res, (long long)(opt))
+#define __sanitizer_syscall_pre_revoke(path) \
+ __sanitizer_syscall_pre_impl_revoke((long long)(path))
+#define __sanitizer_syscall_post_revoke(res, path) \
+ __sanitizer_syscall_post_impl_revoke(res, (long long)(path))
+#define __sanitizer_syscall_pre_symlink(path, link) \
+ __sanitizer_syscall_pre_impl_symlink((long long)(path), (long long)(link))
+#define __sanitizer_syscall_post_symlink(res, path, link) \
+ __sanitizer_syscall_post_impl_symlink(res, (long long)(path), \
+ (long long)(link))
+#define __sanitizer_syscall_pre_readlink(path, buf, count) \
+ __sanitizer_syscall_pre_impl_readlink((long long)(path), (long long)(buf), \
+ (long long)(count))
+#define __sanitizer_syscall_post_readlink(res, path, buf, count) \
+ __sanitizer_syscall_post_impl_readlink(res, (long long)(path), \
+ (long long)(buf), (long long)(count))
+#define __sanitizer_syscall_pre_execve(path, argp, envp) \
+ __sanitizer_syscall_pre_impl_execve((long long)(path), (long long)(argp), \
+ (long long)(envp))
+#define __sanitizer_syscall_post_execve(res, path, argp, envp) \
+ __sanitizer_syscall_post_impl_execve(res, (long long)(path), \
+ (long long)(argp), (long long)(envp))
+#define __sanitizer_syscall_pre_umask(newmask) \
+ __sanitizer_syscall_pre_impl_umask((long long)(newmask))
+#define __sanitizer_syscall_post_umask(res, newmask) \
+ __sanitizer_syscall_post_impl_umask(res, (long long)(newmask))
+#define __sanitizer_syscall_pre_chroot(path) \
+ __sanitizer_syscall_pre_impl_chroot((long long)(path))
+#define __sanitizer_syscall_post_chroot(res, path) \
+ __sanitizer_syscall_post_impl_chroot(res, (long long)(path))
+#define __sanitizer_syscall_pre_compat_43_fstat43(fd, sb) \
+ __sanitizer_syscall_pre_impl_compat_43_fstat43((long long)(fd), \
+ (long long)(sb))
+#define __sanitizer_syscall_post_compat_43_fstat43(res, fd, sb) \
+ __sanitizer_syscall_post_impl_compat_43_fstat43(res, (long long)(fd), \
+ (long long)(sb))
+#define __sanitizer_syscall_pre_compat_43_ogetkerninfo(op, where, size, arg) \
+ __sanitizer_syscall_pre_impl_compat_43_ogetkerninfo( \
+ (long long)(op), (long long)(where), (long long)(size), \
+ (long long)(arg))
+#define __sanitizer_syscall_post_compat_43_ogetkerninfo(res, op, where, size, \
+ arg) \
+ __sanitizer_syscall_post_impl_compat_43_ogetkerninfo( \
+ res, (long long)(op), (long long)(where), (long long)(size), \
+ (long long)(arg))
+#define __sanitizer_syscall_pre_compat_43_ogetpagesize() \
+ __sanitizer_syscall_pre_impl_compat_43_ogetpagesize()
+#define __sanitizer_syscall_post_compat_43_ogetpagesize(res) \
+ __sanitizer_syscall_post_impl_compat_43_ogetpagesize(res)
+#define __sanitizer_syscall_pre_compat_12_msync(addr, len) \
+ __sanitizer_syscall_pre_impl_compat_12_msync((long long)(addr), \
+ (long long)(len))
+#define __sanitizer_syscall_post_compat_12_msync(res, addr, len) \
+ __sanitizer_syscall_post_impl_compat_12_msync(res, (long long)(addr), \
+ (long long)(len))
+#define __sanitizer_syscall_pre_vfork() __sanitizer_syscall_pre_impl_vfork()
+#define __sanitizer_syscall_post_vfork(res) \
+ __sanitizer_syscall_post_impl_vfork(res)
+/* syscall 67 has been skipped */
+/* syscall 68 has been skipped */
+/* syscall 69 has been skipped */
+/* syscall 70 has been skipped */
+#define __sanitizer_syscall_pre_compat_43_ommap(addr, len, prot, flags, fd, \
+ pos) \
+ __sanitizer_syscall_pre_impl_compat_43_ommap( \
+ (long long)(addr), (long long)(len), (long long)(prot), \
+ (long long)(flags), (long long)(fd), (long long)(pos))
+#define __sanitizer_syscall_post_compat_43_ommap(res, addr, len, prot, flags, \
+ fd, pos) \
+ __sanitizer_syscall_post_impl_compat_43_ommap( \
+ res, (long long)(addr), (long long)(len), (long long)(prot), \
+ (long long)(flags), (long long)(fd), (long long)(pos))
+#define __sanitizer_syscall_pre_vadvise(anom) \
+ __sanitizer_syscall_pre_impl_vadvise((long long)(anom))
+#define __sanitizer_syscall_post_vadvise(res, anom) \
+ __sanitizer_syscall_post_impl_vadvise(res, (long long)(anom))
+#define __sanitizer_syscall_pre_munmap(addr, len) \
+ __sanitizer_syscall_pre_impl_munmap((long long)(addr), (long long)(len))
+#define __sanitizer_syscall_post_munmap(res, addr, len) \
+ __sanitizer_syscall_post_impl_munmap(res, (long long)(addr), (long long)(len))
+#define __sanitizer_syscall_pre_mprotect(addr, len, prot) \
+ __sanitizer_syscall_pre_impl_mprotect((long long)(addr), (long long)(len), \
+ (long long)(prot))
+#define __sanitizer_syscall_post_mprotect(res, addr, len, prot) \
+ __sanitizer_syscall_post_impl_mprotect(res, (long long)(addr), \
+ (long long)(len), (long long)(prot))
+#define __sanitizer_syscall_pre_madvise(addr, len, behav) \
+ __sanitizer_syscall_pre_impl_madvise((long long)(addr), (long long)(len), \
+ (long long)(behav))
+#define __sanitizer_syscall_post_madvise(res, addr, len, behav) \
+ __sanitizer_syscall_post_impl_madvise(res, (long long)(addr), \
+ (long long)(len), (long long)(behav))
+/* syscall 76 has been skipped */
+/* syscall 77 has been skipped */
+#define __sanitizer_syscall_pre_mincore(addr, len, vec) \
+ __sanitizer_syscall_pre_impl_mincore((long long)(addr), (long long)(len), \
+ (long long)(vec))
+#define __sanitizer_syscall_post_mincore(res, addr, len, vec) \
+ __sanitizer_syscall_post_impl_mincore(res, (long long)(addr), \
+ (long long)(len), (long long)(vec))
+#define __sanitizer_syscall_pre_getgroups(gidsetsize, gidset) \
+ __sanitizer_syscall_pre_impl_getgroups((long long)(gidsetsize), \
+ (long long)(gidset))
+#define __sanitizer_syscall_post_getgroups(res, gidsetsize, gidset) \
+ __sanitizer_syscall_post_impl_getgroups(res, (long long)(gidsetsize), \
+ (long long)(gidset))
+#define __sanitizer_syscall_pre_setgroups(gidsetsize, gidset) \
+ __sanitizer_syscall_pre_impl_setgroups((long long)(gidsetsize), \
+ (long long)(gidset))
+#define __sanitizer_syscall_post_setgroups(res, gidsetsize, gidset) \
+ __sanitizer_syscall_post_impl_setgroups(res, (long long)(gidsetsize), \
+ (long long)(gidset))
+#define __sanitizer_syscall_pre_getpgrp() __sanitizer_syscall_pre_impl_getpgrp()
+#define __sanitizer_syscall_post_getpgrp(res) \
+ __sanitizer_syscall_post_impl_getpgrp(res)
+#define __sanitizer_syscall_pre_setpgid(pid, pgid) \
+ __sanitizer_syscall_pre_impl_setpgid((long long)(pid), (long long)(pgid))
+#define __sanitizer_syscall_post_setpgid(res, pid, pgid) \
+ __sanitizer_syscall_post_impl_setpgid(res, (long long)(pid), \
+ (long long)(pgid))
+#define __sanitizer_syscall_pre_compat_50_setitimer(which, itv, oitv) \
+ __sanitizer_syscall_pre_impl_compat_50_setitimer( \
+ (long long)(which), (long long)(itv), (long long)(oitv))
+#define __sanitizer_syscall_post_compat_50_setitimer(res, which, itv, oitv) \
+ __sanitizer_syscall_post_impl_compat_50_setitimer( \
+ res, (long long)(which), (long long)(itv), (long long)(oitv))
+#define __sanitizer_syscall_pre_compat_43_owait() \
+ __sanitizer_syscall_pre_impl_compat_43_owait()
+#define __sanitizer_syscall_post_compat_43_owait(res) \
+ __sanitizer_syscall_post_impl_compat_43_owait(res)
+#define __sanitizer_syscall_pre_compat_12_oswapon(name) \
+ __sanitizer_syscall_pre_impl_compat_12_oswapon((long long)(name))
+#define __sanitizer_syscall_post_compat_12_oswapon(res, name) \
+ __sanitizer_syscall_post_impl_compat_12_oswapon(res, (long long)(name))
+#define __sanitizer_syscall_pre_compat_50_getitimer(which, itv) \
+ __sanitizer_syscall_pre_impl_compat_50_getitimer((long long)(which), \
+ (long long)(itv))
+#define __sanitizer_syscall_post_compat_50_getitimer(res, which, itv) \
+ __sanitizer_syscall_post_impl_compat_50_getitimer(res, (long long)(which), \
+ (long long)(itv))
+#define __sanitizer_syscall_pre_compat_43_ogethostname(hostname, len) \
+ __sanitizer_syscall_pre_impl_compat_43_ogethostname((long long)(hostname), \
+ (long long)(len))
+#define __sanitizer_syscall_post_compat_43_ogethostname(res, hostname, len) \
+ __sanitizer_syscall_post_impl_compat_43_ogethostname( \
+ res, (long long)(hostname), (long long)(len))
+#define __sanitizer_syscall_pre_compat_43_osethostname(hostname, len) \
+ __sanitizer_syscall_pre_impl_compat_43_osethostname((long long)(hostname), \
+ (long long)(len))
+#define __sanitizer_syscall_post_compat_43_osethostname(res, hostname, len) \
+ __sanitizer_syscall_post_impl_compat_43_osethostname( \
+ res, (long long)(hostname), (long long)(len))
+#define __sanitizer_syscall_pre_compat_43_ogetdtablesize() \
+ __sanitizer_syscall_pre_impl_compat_43_ogetdtablesize()
+#define __sanitizer_syscall_post_compat_43_ogetdtablesize(res) \
+ __sanitizer_syscall_post_impl_compat_43_ogetdtablesize(res)
+#define __sanitizer_syscall_pre_dup2(from, to) \
+ __sanitizer_syscall_pre_impl_dup2((long long)(from), (long long)(to))
+#define __sanitizer_syscall_post_dup2(res, from, to) \
+ __sanitizer_syscall_post_impl_dup2(res, (long long)(from), (long long)(to))
+#define __sanitizer_syscall_pre_getrandom(buf, buflen, flags) \
+ __sanitizer_syscall_pre_impl_getrandom( \
+ (long long)(buf), (long long)(buflen), (long long)(flags))
+#define __sanitizer_syscall_post_getrandom(res, buf, buflen, flags) \
+ __sanitizer_syscall_post_impl_getrandom( \
+ res, (long long)(buf), (long long)(buflen), (long long)(flags))
+#define __sanitizer_syscall_pre_fcntl(fd, cmd, arg) \
+ __sanitizer_syscall_pre_impl_fcntl((long long)(fd), (long long)(cmd), \
+ (long long)(arg))
+#define __sanitizer_syscall_post_fcntl(res, fd, cmd, arg) \
+ __sanitizer_syscall_post_impl_fcntl(res, (long long)(fd), (long long)(cmd), \
+ (long long)(arg))
+#define __sanitizer_syscall_pre_compat_50_select(nd, in, ou, ex, tv) \
+ __sanitizer_syscall_pre_impl_compat_50_select( \
+ (long long)(nd), (long long)(in), (long long)(ou), (long long)(ex), \
+ (long long)(tv))
+#define __sanitizer_syscall_post_compat_50_select(res, nd, in, ou, ex, tv) \
+ __sanitizer_syscall_post_impl_compat_50_select( \
+ res, (long long)(nd), (long long)(in), (long long)(ou), (long long)(ex), \
+ (long long)(tv))
+/* syscall 94 has been skipped */
+#define __sanitizer_syscall_pre_fsync(fd) \
+ __sanitizer_syscall_pre_impl_fsync((long long)(fd))
+#define __sanitizer_syscall_post_fsync(res, fd) \
+ __sanitizer_syscall_post_impl_fsync(res, (long long)(fd))
+#define __sanitizer_syscall_pre_setpriority(which, who, prio) \
+ __sanitizer_syscall_pre_impl_setpriority( \
+ (long long)(which), (long long)(who), (long long)(prio))
+#define __sanitizer_syscall_post_setpriority(res, which, who, prio) \
+ __sanitizer_syscall_post_impl_setpriority( \
+ res, (long long)(which), (long long)(who), (long long)(prio))
+#define __sanitizer_syscall_pre_compat_30_socket(domain, type, protocol) \
+ __sanitizer_syscall_pre_impl_compat_30_socket( \
+ (long long)(domain), (long long)(type), (long long)(protocol))
+#define __sanitizer_syscall_post_compat_30_socket(res, domain, type, protocol) \
+ __sanitizer_syscall_post_impl_compat_30_socket( \
+ res, (long long)(domain), (long long)(type), (long long)(protocol))
+#define __sanitizer_syscall_pre_connect(s, name, namelen) \
+ __sanitizer_syscall_pre_impl_connect((long long)(s), (long long)(name), \
+ (long long)(namelen))
+#define __sanitizer_syscall_post_connect(res, s, name, namelen) \
+ __sanitizer_syscall_post_impl_connect( \
+ res, (long long)(s), (long long)(name), (long long)(namelen))
+#define __sanitizer_syscall_pre_compat_43_oaccept(s, name, anamelen) \
+ __sanitizer_syscall_pre_impl_compat_43_oaccept( \
+ (long long)(s), (long long)(name), (long long)(anamelen))
+#define __sanitizer_syscall_post_compat_43_oaccept(res, s, name, anamelen) \
+ __sanitizer_syscall_post_impl_compat_43_oaccept( \
+ res, (long long)(s), (long long)(name), (long long)(anamelen))
+#define __sanitizer_syscall_pre_getpriority(which, who) \
+ __sanitizer_syscall_pre_impl_getpriority((long long)(which), (long long)(who))
+#define __sanitizer_syscall_post_getpriority(res, which, who) \
+ __sanitizer_syscall_post_impl_getpriority(res, (long long)(which), \
+ (long long)(who))
+#define __sanitizer_syscall_pre_compat_43_osend(s, buf, len, flags) \
+ __sanitizer_syscall_pre_impl_compat_43_osend( \
+ (long long)(s), (long long)(buf), (long long)(len), (long long)(flags))
+#define __sanitizer_syscall_post_compat_43_osend(res, s, buf, len, flags) \
+ __sanitizer_syscall_post_impl_compat_43_osend( \
+ res, (long long)(s), (long long)(buf), (long long)(len), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_compat_43_orecv(s, buf, len, flags) \
+ __sanitizer_syscall_pre_impl_compat_43_orecv( \
+ (long long)(s), (long long)(buf), (long long)(len), (long long)(flags))
+#define __sanitizer_syscall_post_compat_43_orecv(res, s, buf, len, flags) \
+ __sanitizer_syscall_post_impl_compat_43_orecv( \
+ res, (long long)(s), (long long)(buf), (long long)(len), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_compat_13_sigreturn13(sigcntxp) \
+ __sanitizer_syscall_pre_impl_compat_13_sigreturn13((long long)(sigcntxp))
+#define __sanitizer_syscall_post_compat_13_sigreturn13(res, sigcntxp) \
+ __sanitizer_syscall_post_impl_compat_13_sigreturn13(res, \
+ (long long)(sigcntxp))
+#define __sanitizer_syscall_pre_bind(s, name, namelen) \
+ __sanitizer_syscall_pre_impl_bind((long long)(s), (long long)(name), \
+ (long long)(namelen))
+#define __sanitizer_syscall_post_bind(res, s, name, namelen) \
+ __sanitizer_syscall_post_impl_bind(res, (long long)(s), (long long)(name), \
+ (long long)(namelen))
+#define __sanitizer_syscall_pre_setsockopt(s, level, name, val, valsize) \
+ __sanitizer_syscall_pre_impl_setsockopt((long long)(s), (long long)(level), \
+ (long long)(name), (long long)(val), \
+ (long long)(valsize))
+#define __sanitizer_syscall_post_setsockopt(res, s, level, name, val, valsize) \
+ __sanitizer_syscall_post_impl_setsockopt( \
+ res, (long long)(s), (long long)(level), (long long)(name), \
+ (long long)(val), (long long)(valsize))
+#define __sanitizer_syscall_pre_listen(s, backlog) \
+ __sanitizer_syscall_pre_impl_listen((long long)(s), (long long)(backlog))
+#define __sanitizer_syscall_post_listen(res, s, backlog) \
+ __sanitizer_syscall_post_impl_listen(res, (long long)(s), \
+ (long long)(backlog))
+/* syscall 107 has been skipped */
+#define __sanitizer_syscall_pre_compat_43_osigvec(signum, nsv, osv) \
+ __sanitizer_syscall_pre_impl_compat_43_osigvec( \
+ (long long)(signum), (long long)(nsv), (long long)(osv))
+#define __sanitizer_syscall_post_compat_43_osigvec(res, signum, nsv, osv) \
+ __sanitizer_syscall_post_impl_compat_43_osigvec( \
+ res, (long long)(signum), (long long)(nsv), (long long)(osv))
+#define __sanitizer_syscall_pre_compat_43_osigblock(mask) \
+ __sanitizer_syscall_pre_impl_compat_43_osigblock((long long)(mask))
+#define __sanitizer_syscall_post_compat_43_osigblock(res, mask) \
+ __sanitizer_syscall_post_impl_compat_43_osigblock(res, (long long)(mask))
+#define __sanitizer_syscall_pre_compat_43_osigsetmask(mask) \
+ __sanitizer_syscall_pre_impl_compat_43_osigsetmask((long long)(mask))
+#define __sanitizer_syscall_post_compat_43_osigsetmask(res, mask) \
+ __sanitizer_syscall_post_impl_compat_43_osigsetmask(res, (long long)(mask))
+#define __sanitizer_syscall_pre_compat_13_sigsuspend13(mask) \
+ __sanitizer_syscall_pre_impl_compat_13_sigsuspend13((long long)(mask))
+#define __sanitizer_syscall_post_compat_13_sigsuspend13(res, mask) \
+ __sanitizer_syscall_post_impl_compat_13_sigsuspend13(res, (long long)(mask))
+#define __sanitizer_syscall_pre_compat_43_osigstack(nss, oss) \
+ __sanitizer_syscall_pre_impl_compat_43_osigstack((long long)(nss), \
+ (long long)(oss))
+#define __sanitizer_syscall_post_compat_43_osigstack(res, nss, oss) \
+ __sanitizer_syscall_post_impl_compat_43_osigstack(res, (long long)(nss), \
+ (long long)(oss))
+#define __sanitizer_syscall_pre_compat_43_orecvmsg(s, msg, flags) \
+ __sanitizer_syscall_pre_impl_compat_43_orecvmsg( \
+ (long long)(s), (long long)(msg), (long long)(flags))
+#define __sanitizer_syscall_post_compat_43_orecvmsg(res, s, msg, flags) \
+ __sanitizer_syscall_post_impl_compat_43_orecvmsg( \
+ res, (long long)(s), (long long)(msg), (long long)(flags))
+#define __sanitizer_syscall_pre_compat_43_osendmsg(s, msg, flags) \
+ __sanitizer_syscall_pre_impl_compat_43_osendmsg( \
+ (long long)(s), (long long)(msg), (long long)(flags))
+#define __sanitizer_syscall_post_compat_43_osendmsg(res, s, msg, flags) \
+ __sanitizer_syscall_post_impl_compat_43_osendmsg( \
+ res, (long long)(s), (long long)(msg), (long long)(flags))
+/* syscall 115 has been skipped */
+#define __sanitizer_syscall_pre_compat_50_gettimeofday(tp, tzp) \
+ __sanitizer_syscall_pre_impl_compat_50_gettimeofday((long long)(tp), \
+ (long long)(tzp))
+#define __sanitizer_syscall_post_compat_50_gettimeofday(res, tp, tzp) \
+ __sanitizer_syscall_post_impl_compat_50_gettimeofday(res, (long long)(tp), \
+ (long long)(tzp))
+#define __sanitizer_syscall_pre_compat_50_getrusage(who, rusage) \
+ __sanitizer_syscall_pre_impl_compat_50_getrusage((long long)(who), \
+ (long long)(rusage))
+#define __sanitizer_syscall_post_compat_50_getrusage(res, who, rusage) \
+ __sanitizer_syscall_post_impl_compat_50_getrusage(res, (long long)(who), \
+ (long long)(rusage))
+#define __sanitizer_syscall_pre_getsockopt(s, level, name, val, avalsize) \
+ __sanitizer_syscall_pre_impl_getsockopt((long long)(s), (long long)(level), \
+ (long long)(name), (long long)(val), \
+ (long long)(avalsize))
+#define __sanitizer_syscall_post_getsockopt(res, s, level, name, val, \
+ avalsize) \
+ __sanitizer_syscall_post_impl_getsockopt( \
+ res, (long long)(s), (long long)(level), (long long)(name), \
+ (long long)(val), (long long)(avalsize))
+/* syscall 119 has been skipped */
+#define __sanitizer_syscall_pre_readv(fd, iovp, iovcnt) \
+ __sanitizer_syscall_pre_impl_readv((long long)(fd), (long long)(iovp), \
+ (long long)(iovcnt))
+#define __sanitizer_syscall_post_readv(res, fd, iovp, iovcnt) \
+ __sanitizer_syscall_post_impl_readv(res, (long long)(fd), (long long)(iovp), \
+ (long long)(iovcnt))
+#define __sanitizer_syscall_pre_writev(fd, iovp, iovcnt) \
+ __sanitizer_syscall_pre_impl_writev((long long)(fd), (long long)(iovp), \
+ (long long)(iovcnt))
+#define __sanitizer_syscall_post_writev(res, fd, iovp, iovcnt) \
+ __sanitizer_syscall_post_impl_writev(res, (long long)(fd), \
+ (long long)(iovp), (long long)(iovcnt))
+#define __sanitizer_syscall_pre_compat_50_settimeofday(tv, tzp) \
+ __sanitizer_syscall_pre_impl_compat_50_settimeofday((long long)(tv), \
+ (long long)(tzp))
+#define __sanitizer_syscall_post_compat_50_settimeofday(res, tv, tzp) \
+ __sanitizer_syscall_post_impl_compat_50_settimeofday(res, (long long)(tv), \
+ (long long)(tzp))
+#define __sanitizer_syscall_pre_fchown(fd, uid, gid) \
+ __sanitizer_syscall_pre_impl_fchown((long long)(fd), (long long)(uid), \
+ (long long)(gid))
+#define __sanitizer_syscall_post_fchown(res, fd, uid, gid) \
+ __sanitizer_syscall_post_impl_fchown(res, (long long)(fd), (long long)(uid), \
+ (long long)(gid))
+#define __sanitizer_syscall_pre_fchmod(fd, mode) \
+ __sanitizer_syscall_pre_impl_fchmod((long long)(fd), (long long)(mode))
+#define __sanitizer_syscall_post_fchmod(res, fd, mode) \
+ __sanitizer_syscall_post_impl_fchmod(res, (long long)(fd), (long long)(mode))
+#define __sanitizer_syscall_pre_compat_43_orecvfrom(s, buf, len, flags, from, \
+ fromlenaddr) \
+ __sanitizer_syscall_pre_impl_compat_43_orecvfrom( \
+ (long long)(s), (long long)(buf), (long long)(len), (long long)(flags), \
+ (long long)(from), (long long)(fromlenaddr))
+#define __sanitizer_syscall_post_compat_43_orecvfrom(res, s, buf, len, flags, \
+ from, fromlenaddr) \
+ __sanitizer_syscall_post_impl_compat_43_orecvfrom( \
+ res, (long long)(s), (long long)(buf), (long long)(len), \
+ (long long)(flags), (long long)(from), (long long)(fromlenaddr))
+#define __sanitizer_syscall_pre_setreuid(ruid, euid) \
+ __sanitizer_syscall_pre_impl_setreuid((long long)(ruid), (long long)(euid))
+#define __sanitizer_syscall_post_setreuid(res, ruid, euid) \
+ __sanitizer_syscall_post_impl_setreuid(res, (long long)(ruid), \
+ (long long)(euid))
+#define __sanitizer_syscall_pre_setregid(rgid, egid) \
+ __sanitizer_syscall_pre_impl_setregid((long long)(rgid), (long long)(egid))
+#define __sanitizer_syscall_post_setregid(res, rgid, egid) \
+ __sanitizer_syscall_post_impl_setregid(res, (long long)(rgid), \
+ (long long)(egid))
+#define __sanitizer_syscall_pre_rename(from, to) \
+ __sanitizer_syscall_pre_impl_rename((long long)(from), (long long)(to))
+#define __sanitizer_syscall_post_rename(res, from, to) \
+ __sanitizer_syscall_post_impl_rename(res, (long long)(from), (long long)(to))
+#define __sanitizer_syscall_pre_compat_43_otruncate(path, length) \
+ __sanitizer_syscall_pre_impl_compat_43_otruncate((long long)(path), \
+ (long long)(length))
+#define __sanitizer_syscall_post_compat_43_otruncate(res, path, length) \
+ __sanitizer_syscall_post_impl_compat_43_otruncate(res, (long long)(path), \
+ (long long)(length))
+#define __sanitizer_syscall_pre_compat_43_oftruncate(fd, length) \
+ __sanitizer_syscall_pre_impl_compat_43_oftruncate((long long)(fd), \
+ (long long)(length))
+#define __sanitizer_syscall_post_compat_43_oftruncate(res, fd, length) \
+ __sanitizer_syscall_post_impl_compat_43_oftruncate(res, (long long)(fd), \
+ (long long)(length))
+#define __sanitizer_syscall_pre_flock(fd, how) \
+ __sanitizer_syscall_pre_impl_flock((long long)(fd), (long long)(how))
+#define __sanitizer_syscall_post_flock(res, fd, how) \
+ __sanitizer_syscall_post_impl_flock(res, (long long)(fd), (long long)(how))
+#define __sanitizer_syscall_pre_mkfifo(path, mode) \
+ __sanitizer_syscall_pre_impl_mkfifo((long long)(path), (long long)(mode))
+#define __sanitizer_syscall_post_mkfifo(res, path, mode) \
+ __sanitizer_syscall_post_impl_mkfifo(res, (long long)(path), \
+ (long long)(mode))
+#define __sanitizer_syscall_pre_sendto(s, buf, len, flags, to, tolen) \
+ __sanitizer_syscall_pre_impl_sendto((long long)(s), (long long)(buf), \
+ (long long)(len), (long long)(flags), \
+ (long long)(to), (long long)(tolen))
+#define __sanitizer_syscall_post_sendto(res, s, buf, len, flags, to, tolen) \
+ __sanitizer_syscall_post_impl_sendto(res, (long long)(s), (long long)(buf), \
+ (long long)(len), (long long)(flags), \
+ (long long)(to), (long long)(tolen))
+#define __sanitizer_syscall_pre_shutdown(s, how) \
+ __sanitizer_syscall_pre_impl_shutdown((long long)(s), (long long)(how))
+#define __sanitizer_syscall_post_shutdown(res, s, how) \
+ __sanitizer_syscall_post_impl_shutdown(res, (long long)(s), (long long)(how))
+#define __sanitizer_syscall_pre_socketpair(domain, type, protocol, rsv) \
+ __sanitizer_syscall_pre_impl_socketpair( \
+ (long long)(domain), (long long)(type), (long long)(protocol), \
+ (long long)(rsv))
+#define __sanitizer_syscall_post_socketpair(res, domain, type, protocol, rsv) \
+ __sanitizer_syscall_post_impl_socketpair( \
+ res, (long long)(domain), (long long)(type), (long long)(protocol), \
+ (long long)(rsv))
+#define __sanitizer_syscall_pre_mkdir(path, mode) \
+ __sanitizer_syscall_pre_impl_mkdir((long long)(path), (long long)(mode))
+#define __sanitizer_syscall_post_mkdir(res, path, mode) \
+ __sanitizer_syscall_post_impl_mkdir(res, (long long)(path), (long long)(mode))
+#define __sanitizer_syscall_pre_rmdir(path) \
+ __sanitizer_syscall_pre_impl_rmdir((long long)(path))
+#define __sanitizer_syscall_post_rmdir(res, path) \
+ __sanitizer_syscall_post_impl_rmdir(res, (long long)(path))
+#define __sanitizer_syscall_pre_compat_50_utimes(path, tptr) \
+ __sanitizer_syscall_pre_impl_compat_50_utimes((long long)(path), \
+ (long long)(tptr))
+#define __sanitizer_syscall_post_compat_50_utimes(res, path, tptr) \
+ __sanitizer_syscall_post_impl_compat_50_utimes(res, (long long)(path), \
+ (long long)(tptr))
+/* syscall 139 has been skipped */
+#define __sanitizer_syscall_pre_compat_50_adjtime(delta, olddelta) \
+ __sanitizer_syscall_pre_impl_compat_50_adjtime((long long)(delta), \
+ (long long)(olddelta))
+#define __sanitizer_syscall_post_compat_50_adjtime(res, delta, olddelta) \
+ __sanitizer_syscall_post_impl_compat_50_adjtime(res, (long long)(delta), \
+ (long long)(olddelta))
+#define __sanitizer_syscall_pre_compat_43_ogetpeername(fdes, asa, alen) \
+ __sanitizer_syscall_pre_impl_compat_43_ogetpeername( \
+ (long long)(fdes), (long long)(asa), (long long)(alen))
+#define __sanitizer_syscall_post_compat_43_ogetpeername(res, fdes, asa, alen) \
+ __sanitizer_syscall_post_impl_compat_43_ogetpeername( \
+ res, (long long)(fdes), (long long)(asa), (long long)(alen))
+#define __sanitizer_syscall_pre_compat_43_ogethostid() \
+ __sanitizer_syscall_pre_impl_compat_43_ogethostid()
+#define __sanitizer_syscall_post_compat_43_ogethostid(res) \
+ __sanitizer_syscall_post_impl_compat_43_ogethostid(res)
+#define __sanitizer_syscall_pre_compat_43_osethostid(hostid) \
+ __sanitizer_syscall_pre_impl_compat_43_osethostid((long long)(hostid))
+#define __sanitizer_syscall_post_compat_43_osethostid(res, hostid) \
+ __sanitizer_syscall_post_impl_compat_43_osethostid(res, (long long)(hostid))
+#define __sanitizer_syscall_pre_compat_43_ogetrlimit(which, rlp) \
+ __sanitizer_syscall_pre_impl_compat_43_ogetrlimit((long long)(which), \
+ (long long)(rlp))
+#define __sanitizer_syscall_post_compat_43_ogetrlimit(res, which, rlp) \
+ __sanitizer_syscall_post_impl_compat_43_ogetrlimit(res, (long long)(which), \
+ (long long)(rlp))
+#define __sanitizer_syscall_pre_compat_43_osetrlimit(which, rlp) \
+ __sanitizer_syscall_pre_impl_compat_43_osetrlimit((long long)(which), \
+ (long long)(rlp))
+#define __sanitizer_syscall_post_compat_43_osetrlimit(res, which, rlp) \
+ __sanitizer_syscall_post_impl_compat_43_osetrlimit(res, (long long)(which), \
+ (long long)(rlp))
+#define __sanitizer_syscall_pre_compat_43_okillpg(pgid, signum) \
+ __sanitizer_syscall_pre_impl_compat_43_okillpg((long long)(pgid), \
+ (long long)(signum))
+#define __sanitizer_syscall_post_compat_43_okillpg(res, pgid, signum) \
+ __sanitizer_syscall_post_impl_compat_43_okillpg(res, (long long)(pgid), \
+ (long long)(signum))
+#define __sanitizer_syscall_pre_setsid() __sanitizer_syscall_pre_impl_setsid()
+#define __sanitizer_syscall_post_setsid(res) \
+ __sanitizer_syscall_post_impl_setsid(res)
+#define __sanitizer_syscall_pre_compat_50_quotactl(path, cmd, uid, arg) \
+ __sanitizer_syscall_pre_impl_compat_50_quotactl( \
+ (long long)(path), (long long)(cmd), (long long)(uid), (long long)(arg))
+#define __sanitizer_syscall_post_compat_50_quotactl(res, path, cmd, uid, arg) \
+ __sanitizer_syscall_post_impl_compat_50_quotactl( \
+ res, (long long)(path), (long long)(cmd), (long long)(uid), \
+ (long long)(arg))
+#define __sanitizer_syscall_pre_compat_43_oquota() \
+ __sanitizer_syscall_pre_impl_compat_43_oquota()
+#define __sanitizer_syscall_post_compat_43_oquota(res) \
+ __sanitizer_syscall_post_impl_compat_43_oquota(res)
+#define __sanitizer_syscall_pre_compat_43_ogetsockname(fdec, asa, alen) \
+ __sanitizer_syscall_pre_impl_compat_43_ogetsockname( \
+ (long long)(fdec), (long long)(asa), (long long)(alen))
+#define __sanitizer_syscall_post_compat_43_ogetsockname(res, fdec, asa, alen) \
+ __sanitizer_syscall_post_impl_compat_43_ogetsockname( \
+ res, (long long)(fdec), (long long)(asa), (long long)(alen))
+/* syscall 151 has been skipped */
+/* syscall 152 has been skipped */
+/* syscall 153 has been skipped */
+/* syscall 154 has been skipped */
+#define __sanitizer_syscall_pre_nfssvc(flag, argp) \
+ __sanitizer_syscall_pre_impl_nfssvc((long long)(flag), (long long)(argp))
+#define __sanitizer_syscall_post_nfssvc(res, flag, argp) \
+ __sanitizer_syscall_post_impl_nfssvc(res, (long long)(flag), \
+ (long long)(argp))
+#define __sanitizer_syscall_pre_compat_43_ogetdirentries(fd, buf, count, \
+ basep) \
+ __sanitizer_syscall_pre_impl_compat_43_ogetdirentries( \
+ (long long)(fd), (long long)(buf), (long long)(count), \
+ (long long)(basep))
+#define __sanitizer_syscall_post_compat_43_ogetdirentries(res, fd, buf, count, \
+ basep) \
+ __sanitizer_syscall_post_impl_compat_43_ogetdirentries( \
+ res, (long long)(fd), (long long)(buf), (long long)(count), \
+ (long long)(basep))
+#define __sanitizer_syscall_pre_compat_20_statfs(path, buf) \
+ __sanitizer_syscall_pre_impl_compat_20_statfs((long long)(path), \
+ (long long)(buf))
+#define __sanitizer_syscall_post_compat_20_statfs(res, path, buf) \
+ __sanitizer_syscall_post_impl_compat_20_statfs(res, (long long)(path), \
+ (long long)(buf))
+#define __sanitizer_syscall_pre_compat_20_fstatfs(fd, buf) \
+ __sanitizer_syscall_pre_impl_compat_20_fstatfs((long long)(fd), \
+ (long long)(buf))
+#define __sanitizer_syscall_post_compat_20_fstatfs(res, fd, buf) \
+ __sanitizer_syscall_post_impl_compat_20_fstatfs(res, (long long)(fd), \
+ (long long)(buf))
+/* syscall 159 has been skipped */
+/* syscall 160 has been skipped */
+#define __sanitizer_syscall_pre_compat_30_getfh(fname, fhp) \
+ __sanitizer_syscall_pre_impl_compat_30_getfh((long long)(fname), \
+ (long long)(fhp))
+#define __sanitizer_syscall_post_compat_30_getfh(res, fname, fhp) \
+ __sanitizer_syscall_post_impl_compat_30_getfh(res, (long long)(fname), \
+ (long long)(fhp))
+#define __sanitizer_syscall_pre_compat_09_ogetdomainname(domainname, len) \
+ __sanitizer_syscall_pre_impl_compat_09_ogetdomainname( \
+ (long long)(domainname), (long long)(len))
+#define __sanitizer_syscall_post_compat_09_ogetdomainname(res, domainname, \
+ len) \
+ __sanitizer_syscall_post_impl_compat_09_ogetdomainname( \
+ res, (long long)(domainname), (long long)(len))
+#define __sanitizer_syscall_pre_compat_09_osetdomainname(domainname, len) \
+ __sanitizer_syscall_pre_impl_compat_09_osetdomainname( \
+ (long long)(domainname), (long long)(len))
+#define __sanitizer_syscall_post_compat_09_osetdomainname(res, domainname, \
+ len) \
+ __sanitizer_syscall_post_impl_compat_09_osetdomainname( \
+ res, (long long)(domainname), (long long)(len))
+#define __sanitizer_syscall_pre_compat_09_ouname(name) \
+ __sanitizer_syscall_pre_impl_compat_09_ouname((long long)(name))
+#define __sanitizer_syscall_post_compat_09_ouname(res, name) \
+ __sanitizer_syscall_post_impl_compat_09_ouname(res, (long long)(name))
+#define __sanitizer_syscall_pre_sysarch(op, parms) \
+ __sanitizer_syscall_pre_impl_sysarch((long long)(op), (long long)(parms))
+#define __sanitizer_syscall_post_sysarch(res, op, parms) \
+ __sanitizer_syscall_post_impl_sysarch(res, (long long)(op), \
+ (long long)(parms))
+#define __sanitizer_syscall_pre___futex(uaddr, op, val, timeout, uaddr2, val2, \
+ val3) \
+ __sanitizer_syscall_pre_impl___futex((long long)(uaddr), (long long)(op), \
+ (long long)(val), (long long)(timeout), \
+ (long long)(uaddr2), (long long)(val2), \
+ (long long)(val3))
+#define __sanitizer_syscall_post___futex(res, uaddr, op, val, timeout, uaddr2, \
+ val2, val3) \
+ __sanitizer_syscall_post_impl___futex( \
+ res, (long long)(uaddr), (long long)(op), (long long)(val), \
+ (long long)(timeout), (long long)(uaddr2), (long long)(val2), \
+ (long long)(val3))
+#define __sanitizer_syscall_pre___futex_set_robust_list(head, len) \
+ __sanitizer_syscall_pre_impl___futex_set_robust_list((long long)(head), \
+ (long long)(len))
+#define __sanitizer_syscall_post___futex_set_robust_list(res, head, len) \
+ __sanitizer_syscall_post_impl___futex_set_robust_list( \
+ res, (long long)(head), (long long)(len))
+#define __sanitizer_syscall_pre___futex_get_robust_list(lwpid, headp, lenp) \
+ __sanitizer_syscall_pre_impl___futex_get_robust_list( \
+ (long long)(lwpid), (long long)(headp), (long long)(lenp))
+#define __sanitizer_syscall_post___futex_get_robust_list(res, lwpid, headp, \
+ lenp) \
+ __sanitizer_syscall_post_impl___futex_get_robust_list( \
+ res, (long long)(lwpid), (long long)(headp), (long long)(lenp))
+#if !defined(_LP64)
+#define __sanitizer_syscall_pre_compat_10_osemsys(which, a2, a3, a4, a5) \
+ __sanitizer_syscall_pre_impl_compat_10_osemsys( \
+ (long long)(which), (long long)(a2), (long long)(a3), (long long)(a4), \
+ (long long)(a5))
+#define __sanitizer_syscall_post_compat_10_osemsys(res, which, a2, a3, a4, a5) \
+ __sanitizer_syscall_post_impl_compat_10_osemsys( \
+ res, (long long)(which), (long long)(a2), (long long)(a3), \
+ (long long)(a4), (long long)(a5))
+#else
+/* syscall 169 has been skipped */
+#endif
+#if !defined(_LP64)
+#define __sanitizer_syscall_pre_compat_10_omsgsys(which, a2, a3, a4, a5, a6) \
+ __sanitizer_syscall_pre_impl_compat_10_omsgsys( \
+ (long long)(which), (long long)(a2), (long long)(a3), (long long)(a4), \
+ (long long)(a5), (long long)(a6))
+#define __sanitizer_syscall_post_compat_10_omsgsys(res, which, a2, a3, a4, a5, \
+ a6) \
+ __sanitizer_syscall_post_impl_compat_10_omsgsys( \
+ res, (long long)(which), (long long)(a2), (long long)(a3), \
+ (long long)(a4), (long long)(a5), (long long)(a6))
+#else
+/* syscall 170 has been skipped */
+#endif
+#if !defined(_LP64)
+#define __sanitizer_syscall_pre_compat_10_oshmsys(which, a2, a3, a4) \
+ __sanitizer_syscall_pre_impl_compat_10_oshmsys( \
+ (long long)(which), (long long)(a2), (long long)(a3), (long long)(a4))
+#define __sanitizer_syscall_post_compat_10_oshmsys(res, which, a2, a3, a4) \
+ __sanitizer_syscall_post_impl_compat_10_oshmsys( \
+ res, (long long)(which), (long long)(a2), (long long)(a3), \
+ (long long)(a4))
+#else
+/* syscall 171 has been skipped */
+#endif
+/* syscall 172 has been skipped */
+#define __sanitizer_syscall_pre_pread(fd, buf, nbyte, PAD, offset) \
+ __sanitizer_syscall_pre_impl_pread((long long)(fd), (long long)(buf), \
+ (long long)(nbyte), (long long)(PAD), \
+ (long long)(offset))
+#define __sanitizer_syscall_post_pread(res, fd, buf, nbyte, PAD, offset) \
+ __sanitizer_syscall_post_impl_pread(res, (long long)(fd), (long long)(buf), \
+ (long long)(nbyte), (long long)(PAD), \
+ (long long)(offset))
+#define __sanitizer_syscall_pre_pwrite(fd, buf, nbyte, PAD, offset) \
+ __sanitizer_syscall_pre_impl_pwrite((long long)(fd), (long long)(buf), \
+ (long long)(nbyte), (long long)(PAD), \
+ (long long)(offset))
+#define __sanitizer_syscall_post_pwrite(res, fd, buf, nbyte, PAD, offset) \
+ __sanitizer_syscall_post_impl_pwrite(res, (long long)(fd), (long long)(buf), \
+ (long long)(nbyte), (long long)(PAD), \
+ (long long)(offset))
+#define __sanitizer_syscall_pre_compat_30_ntp_gettime(ntvp) \
+ __sanitizer_syscall_pre_impl_compat_30_ntp_gettime((long long)(ntvp))
+#define __sanitizer_syscall_post_compat_30_ntp_gettime(res, ntvp) \
+ __sanitizer_syscall_post_impl_compat_30_ntp_gettime(res, (long long)(ntvp))
+#if defined(NTP) || !defined(_KERNEL_OPT)
+#define __sanitizer_syscall_pre_ntp_adjtime(tp) \
+ __sanitizer_syscall_pre_impl_ntp_adjtime((long long)(tp))
+#define __sanitizer_syscall_post_ntp_adjtime(res, tp) \
+ __sanitizer_syscall_post_impl_ntp_adjtime(res, (long long)(tp))
+#else
+/* syscall 176 has been skipped */
+#endif
+/* syscall 177 has been skipped */
+/* syscall 178 has been skipped */
+/* syscall 179 has been skipped */
+/* syscall 180 has been skipped */
+#define __sanitizer_syscall_pre_setgid(gid) \
+ __sanitizer_syscall_pre_impl_setgid((long long)(gid))
+#define __sanitizer_syscall_post_setgid(res, gid) \
+ __sanitizer_syscall_post_impl_setgid(res, (long long)(gid))
+#define __sanitizer_syscall_pre_setegid(egid) \
+ __sanitizer_syscall_pre_impl_setegid((long long)(egid))
+#define __sanitizer_syscall_post_setegid(res, egid) \
+ __sanitizer_syscall_post_impl_setegid(res, (long long)(egid))
+#define __sanitizer_syscall_pre_seteuid(euid) \
+ __sanitizer_syscall_pre_impl_seteuid((long long)(euid))
+#define __sanitizer_syscall_post_seteuid(res, euid) \
+ __sanitizer_syscall_post_impl_seteuid(res, (long long)(euid))
+#define __sanitizer_syscall_pre_lfs_bmapv(fsidp, blkiov, blkcnt) \
+ __sanitizer_syscall_pre_impl_lfs_bmapv( \
+ (long long)(fsidp), (long long)(blkiov), (long long)(blkcnt))
+#define __sanitizer_syscall_post_lfs_bmapv(res, fsidp, blkiov, blkcnt) \
+ __sanitizer_syscall_post_impl_lfs_bmapv( \
+ res, (long long)(fsidp), (long long)(blkiov), (long long)(blkcnt))
+#define __sanitizer_syscall_pre_lfs_markv(fsidp, blkiov, blkcnt) \
+ __sanitizer_syscall_pre_impl_lfs_markv( \
+ (long long)(fsidp), (long long)(blkiov), (long long)(blkcnt))
+#define __sanitizer_syscall_post_lfs_markv(res, fsidp, blkiov, blkcnt) \
+ __sanitizer_syscall_post_impl_lfs_markv( \
+ res, (long long)(fsidp), (long long)(blkiov), (long long)(blkcnt))
+#define __sanitizer_syscall_pre_lfs_segclean(fsidp, segment) \
+ __sanitizer_syscall_pre_impl_lfs_segclean((long long)(fsidp), \
+ (long long)(segment))
+#define __sanitizer_syscall_post_lfs_segclean(res, fsidp, segment) \
+ __sanitizer_syscall_post_impl_lfs_segclean(res, (long long)(fsidp), \
+ (long long)(segment))
+#define __sanitizer_syscall_pre_compat_50_lfs_segwait(fsidp, tv) \
+ __sanitizer_syscall_pre_impl_compat_50_lfs_segwait((long long)(fsidp), \
+ (long long)(tv))
+#define __sanitizer_syscall_post_compat_50_lfs_segwait(res, fsidp, tv) \
+ __sanitizer_syscall_post_impl_compat_50_lfs_segwait(res, (long long)(fsidp), \
+ (long long)(tv))
+#define __sanitizer_syscall_pre_compat_12_stat12(path, ub) \
+ __sanitizer_syscall_pre_impl_compat_12_stat12((long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_post_compat_12_stat12(res, path, ub) \
+ __sanitizer_syscall_post_impl_compat_12_stat12(res, (long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_pre_compat_12_fstat12(fd, sb) \
+ __sanitizer_syscall_pre_impl_compat_12_fstat12((long long)(fd), \
+ (long long)(sb))
+#define __sanitizer_syscall_post_compat_12_fstat12(res, fd, sb) \
+ __sanitizer_syscall_post_impl_compat_12_fstat12(res, (long long)(fd), \
+ (long long)(sb))
+#define __sanitizer_syscall_pre_compat_12_lstat12(path, ub) \
+ __sanitizer_syscall_pre_impl_compat_12_lstat12((long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_post_compat_12_lstat12(res, path, ub) \
+ __sanitizer_syscall_post_impl_compat_12_lstat12(res, (long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_pre_pathconf(path, name) \
+ __sanitizer_syscall_pre_impl_pathconf((long long)(path), (long long)(name))
+#define __sanitizer_syscall_post_pathconf(res, path, name) \
+ __sanitizer_syscall_post_impl_pathconf(res, (long long)(path), \
+ (long long)(name))
+#define __sanitizer_syscall_pre_fpathconf(fd, name) \
+ __sanitizer_syscall_pre_impl_fpathconf((long long)(fd), (long long)(name))
+#define __sanitizer_syscall_post_fpathconf(res, fd, name) \
+ __sanitizer_syscall_post_impl_fpathconf(res, (long long)(fd), \
+ (long long)(name))
+#define __sanitizer_syscall_pre_getsockopt2(s, level, name, val, avalsize) \
+ __sanitizer_syscall_pre_impl_getsockopt2( \
+ (long long)(s), (long long)(level), (long long)(name), (long long)(val), \
+ (long long)(avalsize))
+#define __sanitizer_syscall_post_getsockopt2(res, s, level, name, val, \
+ avalsize) \
+ __sanitizer_syscall_post_impl_getsockopt2( \
+ res, (long long)(s), (long long)(level), (long long)(name), \
+ (long long)(val), (long long)(avalsize))
+#define __sanitizer_syscall_pre_getrlimit(which, rlp) \
+ __sanitizer_syscall_pre_impl_getrlimit((long long)(which), (long long)(rlp))
+#define __sanitizer_syscall_post_getrlimit(res, which, rlp) \
+ __sanitizer_syscall_post_impl_getrlimit(res, (long long)(which), \
+ (long long)(rlp))
+#define __sanitizer_syscall_pre_setrlimit(which, rlp) \
+ __sanitizer_syscall_pre_impl_setrlimit((long long)(which), (long long)(rlp))
+#define __sanitizer_syscall_post_setrlimit(res, which, rlp) \
+ __sanitizer_syscall_post_impl_setrlimit(res, (long long)(which), \
+ (long long)(rlp))
+#define __sanitizer_syscall_pre_compat_12_getdirentries(fd, buf, count, basep) \
+ __sanitizer_syscall_pre_impl_compat_12_getdirentries( \
+ (long long)(fd), (long long)(buf), (long long)(count), \
+ (long long)(basep))
+#define __sanitizer_syscall_post_compat_12_getdirentries(res, fd, buf, count, \
+ basep) \
+ __sanitizer_syscall_post_impl_compat_12_getdirentries( \
+ res, (long long)(fd), (long long)(buf), (long long)(count), \
+ (long long)(basep))
+#define __sanitizer_syscall_pre_mmap(addr, len, prot, flags, fd, PAD, pos) \
+ __sanitizer_syscall_pre_impl_mmap( \
+ (long long)(addr), (long long)(len), (long long)(prot), \
+ (long long)(flags), (long long)(fd), (long long)(PAD), (long long)(pos))
+#define __sanitizer_syscall_post_mmap(res, addr, len, prot, flags, fd, PAD, \
+ pos) \
+ __sanitizer_syscall_post_impl_mmap( \
+ res, (long long)(addr), (long long)(len), (long long)(prot), \
+ (long long)(flags), (long long)(fd), (long long)(PAD), (long long)(pos))
+#define __sanitizer_syscall_pre___syscall(code, arg0, arg1, arg2, arg3, arg4, \
+ arg5, arg6, arg7) \
+ __sanitizer_syscall_pre_impl___syscall( \
+ (long long)(code), (long long)(arg0), (long long)(arg1), \
+ (long long)(arg2), (long long)(arg3), (long long)(arg4), \
+ (long long)(arg5), (long long)(arg6), (long long)(arg7))
+#define __sanitizer_syscall_post___syscall(res, code, arg0, arg1, arg2, arg3, \
+ arg4, arg5, arg6, arg7) \
+ __sanitizer_syscall_post_impl___syscall( \
+ res, (long long)(code), (long long)(arg0), (long long)(arg1), \
+ (long long)(arg2), (long long)(arg3), (long long)(arg4), \
+ (long long)(arg5), (long long)(arg6), (long long)(arg7))
+#define __sanitizer_syscall_pre_lseek(fd, PAD, offset, whence) \
+ __sanitizer_syscall_pre_impl_lseek((long long)(fd), (long long)(PAD), \
+ (long long)(offset), (long long)(whence))
+#define __sanitizer_syscall_post_lseek(res, fd, PAD, offset, whence) \
+ __sanitizer_syscall_post_impl_lseek(res, (long long)(fd), (long long)(PAD), \
+ (long long)(offset), \
+ (long long)(whence))
+#define __sanitizer_syscall_pre_truncate(path, PAD, length) \
+ __sanitizer_syscall_pre_impl_truncate((long long)(path), (long long)(PAD), \
+ (long long)(length))
+#define __sanitizer_syscall_post_truncate(res, path, PAD, length) \
+ __sanitizer_syscall_post_impl_truncate( \
+ res, (long long)(path), (long long)(PAD), (long long)(length))
+#define __sanitizer_syscall_pre_ftruncate(fd, PAD, length) \
+ __sanitizer_syscall_pre_impl_ftruncate((long long)(fd), (long long)(PAD), \
+ (long long)(length))
+#define __sanitizer_syscall_post_ftruncate(res, fd, PAD, length) \
+ __sanitizer_syscall_post_impl_ftruncate( \
+ res, (long long)(fd), (long long)(PAD), (long long)(length))
+#define __sanitizer_syscall_pre___sysctl(name, namelen, oldv, oldlenp, newv, \
+ newlen) \
+ __sanitizer_syscall_pre_impl___sysctl( \
+ (long long)(name), (long long)(namelen), (long long)(oldv), \
+ (long long)(oldlenp), (long long)(newv), (long long)(newlen))
+#define __sanitizer_syscall_post___sysctl(res, name, namelen, oldv, oldlenp, \
+ newv, newlen) \
+ __sanitizer_syscall_post_impl___sysctl( \
+ res, (long long)(name), (long long)(namelen), (long long)(oldv), \
+ (long long)(oldlenp), (long long)(newv), (long long)(newlen))
+#define __sanitizer_syscall_pre_mlock(addr, len) \
+ __sanitizer_syscall_pre_impl_mlock((long long)(addr), (long long)(len))
+#define __sanitizer_syscall_post_mlock(res, addr, len) \
+ __sanitizer_syscall_post_impl_mlock(res, (long long)(addr), (long long)(len))
+#define __sanitizer_syscall_pre_munlock(addr, len) \
+ __sanitizer_syscall_pre_impl_munlock((long long)(addr), (long long)(len))
+#define __sanitizer_syscall_post_munlock(res, addr, len) \
+ __sanitizer_syscall_post_impl_munlock(res, (long long)(addr), \
+ (long long)(len))
+#define __sanitizer_syscall_pre_undelete(path) \
+ __sanitizer_syscall_pre_impl_undelete((long long)(path))
+#define __sanitizer_syscall_post_undelete(res, path) \
+ __sanitizer_syscall_post_impl_undelete(res, (long long)(path))
+#define __sanitizer_syscall_pre_compat_50_futimes(fd, tptr) \
+ __sanitizer_syscall_pre_impl_compat_50_futimes((long long)(fd), \
+ (long long)(tptr))
+#define __sanitizer_syscall_post_compat_50_futimes(res, fd, tptr) \
+ __sanitizer_syscall_post_impl_compat_50_futimes(res, (long long)(fd), \
+ (long long)(tptr))
+#define __sanitizer_syscall_pre_getpgid(pid) \
+ __sanitizer_syscall_pre_impl_getpgid((long long)(pid))
+#define __sanitizer_syscall_post_getpgid(res, pid) \
+ __sanitizer_syscall_post_impl_getpgid(res, (long long)(pid))
+#define __sanitizer_syscall_pre_reboot(opt, bootstr) \
+ __sanitizer_syscall_pre_impl_reboot((long long)(opt), (long long)(bootstr))
+#define __sanitizer_syscall_post_reboot(res, opt, bootstr) \
+ __sanitizer_syscall_post_impl_reboot(res, (long long)(opt), \
+ (long long)(bootstr))
+#define __sanitizer_syscall_pre_poll(fds, nfds, timeout) \
+ __sanitizer_syscall_pre_impl_poll((long long)(fds), (long long)(nfds), \
+ (long long)(timeout))
+#define __sanitizer_syscall_post_poll(res, fds, nfds, timeout) \
+ __sanitizer_syscall_post_impl_poll(res, (long long)(fds), (long long)(nfds), \
+ (long long)(timeout))
+#define __sanitizer_syscall_pre_afssys(id, a1, a2, a3, a4, a5, a6) \
+ __sanitizer_syscall_pre_impl_afssys( \
+ (long long)(id), (long long)(a1), (long long)(a2), (long long)(a3), \
+ (long long)(a4), (long long)(a5), (long long)(a6))
+#define __sanitizer_syscall_post_afssys(res, id, a1, a2, a3, a4, a5, a6) \
+ __sanitizer_syscall_post_impl_afssys( \
+ res, (long long)(id), (long long)(a1), (long long)(a2), (long long)(a3), \
+ (long long)(a4), (long long)(a5), (long long)(a6))
+/* syscall 211 has been skipped */
+/* syscall 212 has been skipped */
+/* syscall 213 has been skipped */
+/* syscall 214 has been skipped */
+/* syscall 215 has been skipped */
+/* syscall 216 has been skipped */
+/* syscall 217 has been skipped */
+/* syscall 218 has been skipped */
+/* syscall 219 has been skipped */
+#define __sanitizer_syscall_pre_compat_14___semctl(semid, semnum, cmd, arg) \
+ __sanitizer_syscall_pre_impl_compat_14___semctl( \
+ (long long)(semid), (long long)(semnum), (long long)(cmd), \
+ (long long)(arg))
+#define __sanitizer_syscall_post_compat_14___semctl(res, semid, semnum, cmd, \
+ arg) \
+ __sanitizer_syscall_post_impl_compat_14___semctl( \
+ res, (long long)(semid), (long long)(semnum), (long long)(cmd), \
+ (long long)(arg))
+#define __sanitizer_syscall_pre_semget(key, nsems, semflg) \
+ __sanitizer_syscall_pre_impl_semget((long long)(key), (long long)(nsems), \
+ (long long)(semflg))
+#define __sanitizer_syscall_post_semget(res, key, nsems, semflg) \
+ __sanitizer_syscall_post_impl_semget( \
+ res, (long long)(key), (long long)(nsems), (long long)(semflg))
+#define __sanitizer_syscall_pre_semop(semid, sops, nsops) \
+ __sanitizer_syscall_pre_impl_semop((long long)(semid), (long long)(sops), \
+ (long long)(nsops))
+#define __sanitizer_syscall_post_semop(res, semid, sops, nsops) \
+ __sanitizer_syscall_post_impl_semop(res, (long long)(semid), \
+ (long long)(sops), (long long)(nsops))
+#define __sanitizer_syscall_pre_semconfig(flag) \
+ __sanitizer_syscall_pre_impl_semconfig((long long)(flag))
+#define __sanitizer_syscall_post_semconfig(res, flag) \
+ __sanitizer_syscall_post_impl_semconfig(res, (long long)(flag))
+#define __sanitizer_syscall_pre_compat_14_msgctl(msqid, cmd, buf) \
+ __sanitizer_syscall_pre_impl_compat_14_msgctl( \
+ (long long)(msqid), (long long)(cmd), (long long)(buf))
+#define __sanitizer_syscall_post_compat_14_msgctl(res, msqid, cmd, buf) \
+ __sanitizer_syscall_post_impl_compat_14_msgctl( \
+ res, (long long)(msqid), (long long)(cmd), (long long)(buf))
+#define __sanitizer_syscall_pre_msgget(key, msgflg) \
+ __sanitizer_syscall_pre_impl_msgget((long long)(key), (long long)(msgflg))
+#define __sanitizer_syscall_post_msgget(res, key, msgflg) \
+ __sanitizer_syscall_post_impl_msgget(res, (long long)(key), \
+ (long long)(msgflg))
+#define __sanitizer_syscall_pre_msgsnd(msqid, msgp, msgsz, msgflg) \
+ __sanitizer_syscall_pre_impl_msgsnd((long long)(msqid), (long long)(msgp), \
+ (long long)(msgsz), (long long)(msgflg))
+#define __sanitizer_syscall_post_msgsnd(res, msqid, msgp, msgsz, msgflg) \
+ __sanitizer_syscall_post_impl_msgsnd(res, (long long)(msqid), \
+ (long long)(msgp), (long long)(msgsz), \
+ (long long)(msgflg))
+#define __sanitizer_syscall_pre_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) \
+ __sanitizer_syscall_pre_impl_msgrcv((long long)(msqid), (long long)(msgp), \
+ (long long)(msgsz), (long long)(msgtyp), \
+ (long long)(msgflg))
+#define __sanitizer_syscall_post_msgrcv(res, msqid, msgp, msgsz, msgtyp, \
+ msgflg) \
+ __sanitizer_syscall_post_impl_msgrcv( \
+ res, (long long)(msqid), (long long)(msgp), (long long)(msgsz), \
+ (long long)(msgtyp), (long long)(msgflg))
+#define __sanitizer_syscall_pre_shmat(shmid, shmaddr, shmflg) \
+ __sanitizer_syscall_pre_impl_shmat((long long)(shmid), (long long)(shmaddr), \
+ (long long)(shmflg))
+#define __sanitizer_syscall_post_shmat(res, shmid, shmaddr, shmflg) \
+ __sanitizer_syscall_post_impl_shmat( \
+ res, (long long)(shmid), (long long)(shmaddr), (long long)(shmflg))
+#define __sanitizer_syscall_pre_compat_14_shmctl(shmid, cmd, buf) \
+ __sanitizer_syscall_pre_impl_compat_14_shmctl( \
+ (long long)(shmid), (long long)(cmd), (long long)(buf))
+#define __sanitizer_syscall_post_compat_14_shmctl(res, shmid, cmd, buf) \
+ __sanitizer_syscall_post_impl_compat_14_shmctl( \
+ res, (long long)(shmid), (long long)(cmd), (long long)(buf))
+#define __sanitizer_syscall_pre_shmdt(shmaddr) \
+ __sanitizer_syscall_pre_impl_shmdt((long long)(shmaddr))
+#define __sanitizer_syscall_post_shmdt(res, shmaddr) \
+ __sanitizer_syscall_post_impl_shmdt(res, (long long)(shmaddr))
+#define __sanitizer_syscall_pre_shmget(key, size, shmflg) \
+ __sanitizer_syscall_pre_impl_shmget((long long)(key), (long long)(size), \
+ (long long)(shmflg))
+#define __sanitizer_syscall_post_shmget(res, key, size, shmflg) \
+ __sanitizer_syscall_post_impl_shmget(res, (long long)(key), \
+ (long long)(size), (long long)(shmflg))
+#define __sanitizer_syscall_pre_compat_50_clock_gettime(clock_id, tp) \
+ __sanitizer_syscall_pre_impl_compat_50_clock_gettime((long long)(clock_id), \
+ (long long)(tp))
+#define __sanitizer_syscall_post_compat_50_clock_gettime(res, clock_id, tp) \
+ __sanitizer_syscall_post_impl_compat_50_clock_gettime( \
+ res, (long long)(clock_id), (long long)(tp))
+#define __sanitizer_syscall_pre_compat_50_clock_settime(clock_id, tp) \
+ __sanitizer_syscall_pre_impl_compat_50_clock_settime((long long)(clock_id), \
+ (long long)(tp))
+#define __sanitizer_syscall_post_compat_50_clock_settime(res, clock_id, tp) \
+ __sanitizer_syscall_post_impl_compat_50_clock_settime( \
+ res, (long long)(clock_id), (long long)(tp))
+#define __sanitizer_syscall_pre_compat_50_clock_getres(clock_id, tp) \
+ __sanitizer_syscall_pre_impl_compat_50_clock_getres((long long)(clock_id), \
+ (long long)(tp))
+#define __sanitizer_syscall_post_compat_50_clock_getres(res, clock_id, tp) \
+ __sanitizer_syscall_post_impl_compat_50_clock_getres( \
+ res, (long long)(clock_id), (long long)(tp))
+#define __sanitizer_syscall_pre_timer_create(clock_id, evp, timerid) \
+ __sanitizer_syscall_pre_impl_timer_create( \
+ (long long)(clock_id), (long long)(evp), (long long)(timerid))
+#define __sanitizer_syscall_post_timer_create(res, clock_id, evp, timerid) \
+ __sanitizer_syscall_post_impl_timer_create( \
+ res, (long long)(clock_id), (long long)(evp), (long long)(timerid))
+#define __sanitizer_syscall_pre_timer_delete(timerid) \
+ __sanitizer_syscall_pre_impl_timer_delete((long long)(timerid))
+#define __sanitizer_syscall_post_timer_delete(res, timerid) \
+ __sanitizer_syscall_post_impl_timer_delete(res, (long long)(timerid))
+#define __sanitizer_syscall_pre_compat_50_timer_settime(timerid, flags, value, \
+ ovalue) \
+ __sanitizer_syscall_pre_impl_compat_50_timer_settime( \
+ (long long)(timerid), (long long)(flags), (long long)(value), \
+ (long long)(ovalue))
+#define __sanitizer_syscall_post_compat_50_timer_settime(res, timerid, flags, \
+ value, ovalue) \
+ __sanitizer_syscall_post_impl_compat_50_timer_settime( \
+ res, (long long)(timerid), (long long)(flags), (long long)(value), \
+ (long long)(ovalue))
+#define __sanitizer_syscall_pre_compat_50_timer_gettime(timerid, value) \
+ __sanitizer_syscall_pre_impl_compat_50_timer_gettime((long long)(timerid), \
+ (long long)(value))
+#define __sanitizer_syscall_post_compat_50_timer_gettime(res, timerid, value) \
+ __sanitizer_syscall_post_impl_compat_50_timer_gettime( \
+ res, (long long)(timerid), (long long)(value))
+#define __sanitizer_syscall_pre_timer_getoverrun(timerid) \
+ __sanitizer_syscall_pre_impl_timer_getoverrun((long long)(timerid))
+#define __sanitizer_syscall_post_timer_getoverrun(res, timerid) \
+ __sanitizer_syscall_post_impl_timer_getoverrun(res, (long long)(timerid))
+#define __sanitizer_syscall_pre_compat_50_nanosleep(rqtp, rmtp) \
+ __sanitizer_syscall_pre_impl_compat_50_nanosleep((long long)(rqtp), \
+ (long long)(rmtp))
+#define __sanitizer_syscall_post_compat_50_nanosleep(res, rqtp, rmtp) \
+ __sanitizer_syscall_post_impl_compat_50_nanosleep(res, (long long)(rqtp), \
+ (long long)(rmtp))
+#define __sanitizer_syscall_pre_fdatasync(fd) \
+ __sanitizer_syscall_pre_impl_fdatasync((long long)(fd))
+#define __sanitizer_syscall_post_fdatasync(res, fd) \
+ __sanitizer_syscall_post_impl_fdatasync(res, (long long)(fd))
+#define __sanitizer_syscall_pre_mlockall(flags) \
+ __sanitizer_syscall_pre_impl_mlockall((long long)(flags))
+#define __sanitizer_syscall_post_mlockall(res, flags) \
+ __sanitizer_syscall_post_impl_mlockall(res, (long long)(flags))
+#define __sanitizer_syscall_pre_munlockall() \
+ __sanitizer_syscall_pre_impl_munlockall()
+#define __sanitizer_syscall_post_munlockall(res) \
+ __sanitizer_syscall_post_impl_munlockall(res)
+#define __sanitizer_syscall_pre_compat_50___sigtimedwait(set, info, timeout) \
+ __sanitizer_syscall_pre_impl_compat_50___sigtimedwait( \
+ (long long)(set), (long long)(info), (long long)(timeout))
+#define __sanitizer_syscall_post_compat_50___sigtimedwait(res, set, info, \
+ timeout) \
+ __sanitizer_syscall_post_impl_compat_50___sigtimedwait( \
+ res, (long long)(set), (long long)(info), (long long)(timeout))
+#define __sanitizer_syscall_pre_sigqueueinfo(pid, info) \
+ __sanitizer_syscall_pre_impl_sigqueueinfo((long long)(pid), (long long)(info))
+#define __sanitizer_syscall_post_sigqueueinfo(res, pid, info) \
+ __sanitizer_syscall_post_impl_sigqueueinfo(res, (long long)(pid), \
+ (long long)(info))
+#define __sanitizer_syscall_pre_modctl(cmd, arg) \
+ __sanitizer_syscall_pre_impl_modctl((long long)(cmd), (long long)(arg))
+#define __sanitizer_syscall_post_modctl(res, cmd, arg) \
+ __sanitizer_syscall_post_impl_modctl(res, (long long)(cmd), (long long)(arg))
+#define __sanitizer_syscall_pre__ksem_init(value, idp) \
+ __sanitizer_syscall_pre_impl__ksem_init((long long)(value), (long long)(idp))
+#define __sanitizer_syscall_post__ksem_init(res, value, idp) \
+ __sanitizer_syscall_post_impl__ksem_init(res, (long long)(value), \
+ (long long)(idp))
+#define __sanitizer_syscall_pre__ksem_open(name, oflag, mode, value, idp) \
+ __sanitizer_syscall_pre_impl__ksem_open( \
+ (long long)(name), (long long)(oflag), (long long)(mode), \
+ (long long)(value), (long long)(idp))
+#define __sanitizer_syscall_post__ksem_open(res, name, oflag, mode, value, \
+ idp) \
+ __sanitizer_syscall_post_impl__ksem_open( \
+ res, (long long)(name), (long long)(oflag), (long long)(mode), \
+ (long long)(value), (long long)(idp))
+#define __sanitizer_syscall_pre__ksem_unlink(name) \
+ __sanitizer_syscall_pre_impl__ksem_unlink((long long)(name))
+#define __sanitizer_syscall_post__ksem_unlink(res, name) \
+ __sanitizer_syscall_post_impl__ksem_unlink(res, (long long)(name))
+#define __sanitizer_syscall_pre__ksem_close(id) \
+ __sanitizer_syscall_pre_impl__ksem_close((long long)(id))
+#define __sanitizer_syscall_post__ksem_close(res, id) \
+ __sanitizer_syscall_post_impl__ksem_close(res, (long long)(id))
+#define __sanitizer_syscall_pre__ksem_post(id) \
+ __sanitizer_syscall_pre_impl__ksem_post((long long)(id))
+#define __sanitizer_syscall_post__ksem_post(res, id) \
+ __sanitizer_syscall_post_impl__ksem_post(res, (long long)(id))
+#define __sanitizer_syscall_pre__ksem_wait(id) \
+ __sanitizer_syscall_pre_impl__ksem_wait((long long)(id))
+#define __sanitizer_syscall_post__ksem_wait(res, id) \
+ __sanitizer_syscall_post_impl__ksem_wait(res, (long long)(id))
+#define __sanitizer_syscall_pre__ksem_trywait(id) \
+ __sanitizer_syscall_pre_impl__ksem_trywait((long long)(id))
+#define __sanitizer_syscall_post__ksem_trywait(res, id) \
+ __sanitizer_syscall_post_impl__ksem_trywait(res, (long long)(id))
+#define __sanitizer_syscall_pre__ksem_getvalue(id, value) \
+ __sanitizer_syscall_pre_impl__ksem_getvalue((long long)(id), \
+ (long long)(value))
+#define __sanitizer_syscall_post__ksem_getvalue(res, id, value) \
+ __sanitizer_syscall_post_impl__ksem_getvalue(res, (long long)(id), \
+ (long long)(value))
+#define __sanitizer_syscall_pre__ksem_destroy(id) \
+ __sanitizer_syscall_pre_impl__ksem_destroy((long long)(id))
+#define __sanitizer_syscall_post__ksem_destroy(res, id) \
+ __sanitizer_syscall_post_impl__ksem_destroy(res, (long long)(id))
+#define __sanitizer_syscall_pre__ksem_timedwait(id, abstime) \
+ __sanitizer_syscall_pre_impl__ksem_timedwait((long long)(id), \
+ (long long)(abstime))
+#define __sanitizer_syscall_post__ksem_timedwait(res, id, abstime) \
+ __sanitizer_syscall_post_impl__ksem_timedwait(res, (long long)(id), \
+ (long long)(abstime))
+#define __sanitizer_syscall_pre_mq_open(name, oflag, mode, attr) \
+ __sanitizer_syscall_pre_impl_mq_open((long long)(name), (long long)(oflag), \
+ (long long)(mode), (long long)(attr))
+#define __sanitizer_syscall_post_mq_open(res, name, oflag, mode, attr) \
+ __sanitizer_syscall_post_impl_mq_open(res, (long long)(name), \
+ (long long)(oflag), (long long)(mode), \
+ (long long)(attr))
+#define __sanitizer_syscall_pre_mq_close(mqdes) \
+ __sanitizer_syscall_pre_impl_mq_close((long long)(mqdes))
+#define __sanitizer_syscall_post_mq_close(res, mqdes) \
+ __sanitizer_syscall_post_impl_mq_close(res, (long long)(mqdes))
+#define __sanitizer_syscall_pre_mq_unlink(name) \
+ __sanitizer_syscall_pre_impl_mq_unlink((long long)(name))
+#define __sanitizer_syscall_post_mq_unlink(res, name) \
+ __sanitizer_syscall_post_impl_mq_unlink(res, (long long)(name))
+#define __sanitizer_syscall_pre_mq_getattr(mqdes, mqstat) \
+ __sanitizer_syscall_pre_impl_mq_getattr((long long)(mqdes), \
+ (long long)(mqstat))
+#define __sanitizer_syscall_post_mq_getattr(res, mqdes, mqstat) \
+ __sanitizer_syscall_post_impl_mq_getattr(res, (long long)(mqdes), \
+ (long long)(mqstat))
+#define __sanitizer_syscall_pre_mq_setattr(mqdes, mqstat, omqstat) \
+ __sanitizer_syscall_pre_impl_mq_setattr( \
+ (long long)(mqdes), (long long)(mqstat), (long long)(omqstat))
+#define __sanitizer_syscall_post_mq_setattr(res, mqdes, mqstat, omqstat) \
+ __sanitizer_syscall_post_impl_mq_setattr( \
+ res, (long long)(mqdes), (long long)(mqstat), (long long)(omqstat))
+#define __sanitizer_syscall_pre_mq_notify(mqdes, notification) \
+ __sanitizer_syscall_pre_impl_mq_notify((long long)(mqdes), \
+ (long long)(notification))
+#define __sanitizer_syscall_post_mq_notify(res, mqdes, notification) \
+ __sanitizer_syscall_post_impl_mq_notify(res, (long long)(mqdes), \
+ (long long)(notification))
+#define __sanitizer_syscall_pre_mq_send(mqdes, msg_ptr, msg_len, msg_prio) \
+ __sanitizer_syscall_pre_impl_mq_send( \
+ (long long)(mqdes), (long long)(msg_ptr), (long long)(msg_len), \
+ (long long)(msg_prio))
+#define __sanitizer_syscall_post_mq_send(res, mqdes, msg_ptr, msg_len, \
+ msg_prio) \
+ __sanitizer_syscall_post_impl_mq_send( \
+ res, (long long)(mqdes), (long long)(msg_ptr), (long long)(msg_len), \
+ (long long)(msg_prio))
+#define __sanitizer_syscall_pre_mq_receive(mqdes, msg_ptr, msg_len, msg_prio) \
+ __sanitizer_syscall_pre_impl_mq_receive( \
+ (long long)(mqdes), (long long)(msg_ptr), (long long)(msg_len), \
+ (long long)(msg_prio))
+#define __sanitizer_syscall_post_mq_receive(res, mqdes, msg_ptr, msg_len, \
+ msg_prio) \
+ __sanitizer_syscall_post_impl_mq_receive( \
+ res, (long long)(mqdes), (long long)(msg_ptr), (long long)(msg_len), \
+ (long long)(msg_prio))
+#define __sanitizer_syscall_pre_compat_50_mq_timedsend( \
+ mqdes, msg_ptr, msg_len, msg_prio, abs_timeout) \
+ __sanitizer_syscall_pre_impl_compat_50_mq_timedsend( \
+ (long long)(mqdes), (long long)(msg_ptr), (long long)(msg_len), \
+ (long long)(msg_prio), (long long)(abs_timeout))
+#define __sanitizer_syscall_post_compat_50_mq_timedsend( \
+ res, mqdes, msg_ptr, msg_len, msg_prio, abs_timeout) \
+ __sanitizer_syscall_post_impl_compat_50_mq_timedsend( \
+ res, (long long)(mqdes), (long long)(msg_ptr), (long long)(msg_len), \
+ (long long)(msg_prio), (long long)(abs_timeout))
+#define __sanitizer_syscall_pre_compat_50_mq_timedreceive( \
+ mqdes, msg_ptr, msg_len, msg_prio, abs_timeout) \
+ __sanitizer_syscall_pre_impl_compat_50_mq_timedreceive( \
+ (long long)(mqdes), (long long)(msg_ptr), (long long)(msg_len), \
+ (long long)(msg_prio), (long long)(abs_timeout))
+#define __sanitizer_syscall_post_compat_50_mq_timedreceive( \
+ res, mqdes, msg_ptr, msg_len, msg_prio, abs_timeout) \
+ __sanitizer_syscall_post_impl_compat_50_mq_timedreceive( \
+ res, (long long)(mqdes), (long long)(msg_ptr), (long long)(msg_len), \
+ (long long)(msg_prio), (long long)(abs_timeout))
+/* syscall 267 has been skipped */
+/* syscall 268 has been skipped */
+/* syscall 269 has been skipped */
+#define __sanitizer_syscall_pre___posix_rename(from, to) \
+ __sanitizer_syscall_pre_impl___posix_rename((long long)(from), \
+ (long long)(to))
+#define __sanitizer_syscall_post___posix_rename(res, from, to) \
+ __sanitizer_syscall_post_impl___posix_rename(res, (long long)(from), \
+ (long long)(to))
+#define __sanitizer_syscall_pre_swapctl(cmd, arg, misc) \
+ __sanitizer_syscall_pre_impl_swapctl((long long)(cmd), (long long)(arg), \
+ (long long)(misc))
+#define __sanitizer_syscall_post_swapctl(res, cmd, arg, misc) \
+ __sanitizer_syscall_post_impl_swapctl(res, (long long)(cmd), \
+ (long long)(arg), (long long)(misc))
+#define __sanitizer_syscall_pre_compat_30_getdents(fd, buf, count) \
+ __sanitizer_syscall_pre_impl_compat_30_getdents( \
+ (long long)(fd), (long long)(buf), (long long)(count))
+#define __sanitizer_syscall_post_compat_30_getdents(res, fd, buf, count) \
+ __sanitizer_syscall_post_impl_compat_30_getdents( \
+ res, (long long)(fd), (long long)(buf), (long long)(count))
+#define __sanitizer_syscall_pre_minherit(addr, len, inherit) \
+ __sanitizer_syscall_pre_impl_minherit((long long)(addr), (long long)(len), \
+ (long long)(inherit))
+#define __sanitizer_syscall_post_minherit(res, addr, len, inherit) \
+ __sanitizer_syscall_post_impl_minherit( \
+ res, (long long)(addr), (long long)(len), (long long)(inherit))
+#define __sanitizer_syscall_pre_lchmod(path, mode) \
+ __sanitizer_syscall_pre_impl_lchmod((long long)(path), (long long)(mode))
+#define __sanitizer_syscall_post_lchmod(res, path, mode) \
+ __sanitizer_syscall_post_impl_lchmod(res, (long long)(path), \
+ (long long)(mode))
+#define __sanitizer_syscall_pre_lchown(path, uid, gid) \
+ __sanitizer_syscall_pre_impl_lchown((long long)(path), (long long)(uid), \
+ (long long)(gid))
+#define __sanitizer_syscall_post_lchown(res, path, uid, gid) \
+ __sanitizer_syscall_post_impl_lchown(res, (long long)(path), \
+ (long long)(uid), (long long)(gid))
+#define __sanitizer_syscall_pre_compat_50_lutimes(path, tptr) \
+ __sanitizer_syscall_pre_impl_compat_50_lutimes((long long)(path), \
+ (long long)(tptr))
+#define __sanitizer_syscall_post_compat_50_lutimes(res, path, tptr) \
+ __sanitizer_syscall_post_impl_compat_50_lutimes(res, (long long)(path), \
+ (long long)(tptr))
+#define __sanitizer_syscall_pre___msync13(addr, len, flags) \
+ __sanitizer_syscall_pre_impl___msync13((long long)(addr), (long long)(len), \
+ (long long)(flags))
+#define __sanitizer_syscall_post___msync13(res, addr, len, flags) \
+ __sanitizer_syscall_post_impl___msync13( \
+ res, (long long)(addr), (long long)(len), (long long)(flags))
+#define __sanitizer_syscall_pre_compat_30___stat13(path, ub) \
+ __sanitizer_syscall_pre_impl_compat_30___stat13((long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_post_compat_30___stat13(res, path, ub) \
+ __sanitizer_syscall_post_impl_compat_30___stat13(res, (long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_pre_compat_30___fstat13(fd, sb) \
+ __sanitizer_syscall_pre_impl_compat_30___fstat13((long long)(fd), \
+ (long long)(sb))
+#define __sanitizer_syscall_post_compat_30___fstat13(res, fd, sb) \
+ __sanitizer_syscall_post_impl_compat_30___fstat13(res, (long long)(fd), \
+ (long long)(sb))
+#define __sanitizer_syscall_pre_compat_30___lstat13(path, ub) \
+ __sanitizer_syscall_pre_impl_compat_30___lstat13((long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_post_compat_30___lstat13(res, path, ub) \
+ __sanitizer_syscall_post_impl_compat_30___lstat13(res, (long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_pre___sigaltstack14(nss, oss) \
+ __sanitizer_syscall_pre_impl___sigaltstack14((long long)(nss), \
+ (long long)(oss))
+#define __sanitizer_syscall_post___sigaltstack14(res, nss, oss) \
+ __sanitizer_syscall_post_impl___sigaltstack14(res, (long long)(nss), \
+ (long long)(oss))
+#define __sanitizer_syscall_pre___vfork14() \
+ __sanitizer_syscall_pre_impl___vfork14()
+#define __sanitizer_syscall_post___vfork14(res) \
+ __sanitizer_syscall_post_impl___vfork14(res)
+#define __sanitizer_syscall_pre___posix_chown(path, uid, gid) \
+ __sanitizer_syscall_pre_impl___posix_chown( \
+ (long long)(path), (long long)(uid), (long long)(gid))
+#define __sanitizer_syscall_post___posix_chown(res, path, uid, gid) \
+ __sanitizer_syscall_post_impl___posix_chown( \
+ res, (long long)(path), (long long)(uid), (long long)(gid))
+#define __sanitizer_syscall_pre___posix_fchown(fd, uid, gid) \
+ __sanitizer_syscall_pre_impl___posix_fchown( \
+ (long long)(fd), (long long)(uid), (long long)(gid))
+#define __sanitizer_syscall_post___posix_fchown(res, fd, uid, gid) \
+ __sanitizer_syscall_post_impl___posix_fchown( \
+ res, (long long)(fd), (long long)(uid), (long long)(gid))
+#define __sanitizer_syscall_pre___posix_lchown(path, uid, gid) \
+ __sanitizer_syscall_pre_impl___posix_lchown( \
+ (long long)(path), (long long)(uid), (long long)(gid))
+#define __sanitizer_syscall_post___posix_lchown(res, path, uid, gid) \
+ __sanitizer_syscall_post_impl___posix_lchown( \
+ res, (long long)(path), (long long)(uid), (long long)(gid))
+#define __sanitizer_syscall_pre_getsid(pid) \
+ __sanitizer_syscall_pre_impl_getsid((long long)(pid))
+#define __sanitizer_syscall_post_getsid(res, pid) \
+ __sanitizer_syscall_post_impl_getsid(res, (long long)(pid))
+#define __sanitizer_syscall_pre___clone(flags, stack) \
+ __sanitizer_syscall_pre_impl___clone((long long)(flags), (long long)(stack))
+#define __sanitizer_syscall_post___clone(res, flags, stack) \
+ __sanitizer_syscall_post_impl___clone(res, (long long)(flags), \
+ (long long)(stack))
+#define __sanitizer_syscall_pre_fktrace(fd, ops, facs, pid) \
+ __sanitizer_syscall_pre_impl_fktrace((long long)(fd), (long long)(ops), \
+ (long long)(facs), (long long)(pid))
+#define __sanitizer_syscall_post_fktrace(res, fd, ops, facs, pid) \
+ __sanitizer_syscall_post_impl_fktrace(res, (long long)(fd), \
+ (long long)(ops), (long long)(facs), \
+ (long long)(pid))
+#define __sanitizer_syscall_pre_preadv(fd, iovp, iovcnt, PAD, offset) \
+ __sanitizer_syscall_pre_impl_preadv((long long)(fd), (long long)(iovp), \
+ (long long)(iovcnt), (long long)(PAD), \
+ (long long)(offset))
+#define __sanitizer_syscall_post_preadv(res, fd, iovp, iovcnt, PAD, offset) \
+ __sanitizer_syscall_post_impl_preadv(res, (long long)(fd), \
+ (long long)(iovp), (long long)(iovcnt), \
+ (long long)(PAD), (long long)(offset))
+#define __sanitizer_syscall_pre_pwritev(fd, iovp, iovcnt, PAD, offset) \
+ __sanitizer_syscall_pre_impl_pwritev((long long)(fd), (long long)(iovp), \
+ (long long)(iovcnt), (long long)(PAD), \
+ (long long)(offset))
+#define __sanitizer_syscall_post_pwritev(res, fd, iovp, iovcnt, PAD, offset) \
+ __sanitizer_syscall_post_impl_pwritev( \
+ res, (long long)(fd), (long long)(iovp), (long long)(iovcnt), \
+ (long long)(PAD), (long long)(offset))
+#define __sanitizer_syscall_pre_compat_16___sigaction14(signum, nsa, osa) \
+ __sanitizer_syscall_pre_impl_compat_16___sigaction14( \
+ (long long)(signum), (long long)(nsa), (long long)(osa))
+#define __sanitizer_syscall_post_compat_16___sigaction14(res, signum, nsa, \
+ osa) \
+ __sanitizer_syscall_post_impl_compat_16___sigaction14( \
+ res, (long long)(signum), (long long)(nsa), (long long)(osa))
+#define __sanitizer_syscall_pre___sigpending14(set) \
+ __sanitizer_syscall_pre_impl___sigpending14((long long)(set))
+#define __sanitizer_syscall_post___sigpending14(res, set) \
+ __sanitizer_syscall_post_impl___sigpending14(res, (long long)(set))
+#define __sanitizer_syscall_pre___sigprocmask14(how, set, oset) \
+ __sanitizer_syscall_pre_impl___sigprocmask14( \
+ (long long)(how), (long long)(set), (long long)(oset))
+#define __sanitizer_syscall_post___sigprocmask14(res, how, set, oset) \
+ __sanitizer_syscall_post_impl___sigprocmask14( \
+ res, (long long)(how), (long long)(set), (long long)(oset))
+#define __sanitizer_syscall_pre___sigsuspend14(set) \
+ __sanitizer_syscall_pre_impl___sigsuspend14((long long)(set))
+#define __sanitizer_syscall_post___sigsuspend14(res, set) \
+ __sanitizer_syscall_post_impl___sigsuspend14(res, (long long)(set))
+#define __sanitizer_syscall_pre_compat_16___sigreturn14(sigcntxp) \
+ __sanitizer_syscall_pre_impl_compat_16___sigreturn14((long long)(sigcntxp))
+#define __sanitizer_syscall_post_compat_16___sigreturn14(res, sigcntxp) \
+ __sanitizer_syscall_post_impl_compat_16___sigreturn14(res, \
+ (long long)(sigcntxp))
+#define __sanitizer_syscall_pre___getcwd(bufp, length) \
+ __sanitizer_syscall_pre_impl___getcwd((long long)(bufp), (long long)(length))
+#define __sanitizer_syscall_post___getcwd(res, bufp, length) \
+ __sanitizer_syscall_post_impl___getcwd(res, (long long)(bufp), \
+ (long long)(length))
+#define __sanitizer_syscall_pre_fchroot(fd) \
+ __sanitizer_syscall_pre_impl_fchroot((long long)(fd))
+#define __sanitizer_syscall_post_fchroot(res, fd) \
+ __sanitizer_syscall_post_impl_fchroot(res, (long long)(fd))
+#define __sanitizer_syscall_pre_compat_30_fhopen(fhp, flags) \
+ __sanitizer_syscall_pre_impl_compat_30_fhopen((long long)(fhp), \
+ (long long)(flags))
+#define __sanitizer_syscall_post_compat_30_fhopen(res, fhp, flags) \
+ __sanitizer_syscall_post_impl_compat_30_fhopen(res, (long long)(fhp), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_compat_30_fhstat(fhp, sb) \
+ __sanitizer_syscall_pre_impl_compat_30_fhstat((long long)(fhp), \
+ (long long)(sb))
+#define __sanitizer_syscall_post_compat_30_fhstat(res, fhp, sb) \
+ __sanitizer_syscall_post_impl_compat_30_fhstat(res, (long long)(fhp), \
+ (long long)(sb))
+#define __sanitizer_syscall_pre_compat_20_fhstatfs(fhp, buf) \
+ __sanitizer_syscall_pre_impl_compat_20_fhstatfs((long long)(fhp), \
+ (long long)(buf))
+#define __sanitizer_syscall_post_compat_20_fhstatfs(res, fhp, buf) \
+ __sanitizer_syscall_post_impl_compat_20_fhstatfs(res, (long long)(fhp), \
+ (long long)(buf))
+#define __sanitizer_syscall_pre_compat_50_____semctl13(semid, semnum, cmd, \
+ arg) \
+ __sanitizer_syscall_pre_impl_compat_50_____semctl13( \
+ (long long)(semid), (long long)(semnum), (long long)(cmd), \
+ (long long)(arg))
+#define __sanitizer_syscall_post_compat_50_____semctl13(res, semid, semnum, \
+ cmd, arg) \
+ __sanitizer_syscall_post_impl_compat_50_____semctl13( \
+ res, (long long)(semid), (long long)(semnum), (long long)(cmd), \
+ (long long)(arg))
+#define __sanitizer_syscall_pre_compat_50___msgctl13(msqid, cmd, buf) \
+ __sanitizer_syscall_pre_impl_compat_50___msgctl13( \
+ (long long)(msqid), (long long)(cmd), (long long)(buf))
+#define __sanitizer_syscall_post_compat_50___msgctl13(res, msqid, cmd, buf) \
+ __sanitizer_syscall_post_impl_compat_50___msgctl13( \
+ res, (long long)(msqid), (long long)(cmd), (long long)(buf))
+#define __sanitizer_syscall_pre_compat_50___shmctl13(shmid, cmd, buf) \
+ __sanitizer_syscall_pre_impl_compat_50___shmctl13( \
+ (long long)(shmid), (long long)(cmd), (long long)(buf))
+#define __sanitizer_syscall_post_compat_50___shmctl13(res, shmid, cmd, buf) \
+ __sanitizer_syscall_post_impl_compat_50___shmctl13( \
+ res, (long long)(shmid), (long long)(cmd), (long long)(buf))
+#define __sanitizer_syscall_pre_lchflags(path, flags) \
+ __sanitizer_syscall_pre_impl_lchflags((long long)(path), (long long)(flags))
+#define __sanitizer_syscall_post_lchflags(res, path, flags) \
+ __sanitizer_syscall_post_impl_lchflags(res, (long long)(path), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_issetugid() \
+ __sanitizer_syscall_pre_impl_issetugid()
+#define __sanitizer_syscall_post_issetugid(res) \
+ __sanitizer_syscall_post_impl_issetugid(res)
+#define __sanitizer_syscall_pre_utrace(label, addr, len) \
+ __sanitizer_syscall_pre_impl_utrace((long long)(label), (long long)(addr), \
+ (long long)(len))
+#define __sanitizer_syscall_post_utrace(res, label, addr, len) \
+ __sanitizer_syscall_post_impl_utrace(res, (long long)(label), \
+ (long long)(addr), (long long)(len))
+#define __sanitizer_syscall_pre_getcontext(ucp) \
+ __sanitizer_syscall_pre_impl_getcontext((long long)(ucp))
+#define __sanitizer_syscall_post_getcontext(res, ucp) \
+ __sanitizer_syscall_post_impl_getcontext(res, (long long)(ucp))
+#define __sanitizer_syscall_pre_setcontext(ucp) \
+ __sanitizer_syscall_pre_impl_setcontext((long long)(ucp))
+#define __sanitizer_syscall_post_setcontext(res, ucp) \
+ __sanitizer_syscall_post_impl_setcontext(res, (long long)(ucp))
+#define __sanitizer_syscall_pre__lwp_create(ucp, flags, new_lwp) \
+ __sanitizer_syscall_pre_impl__lwp_create( \
+ (long long)(ucp), (long long)(flags), (long long)(new_lwp))
+#define __sanitizer_syscall_post__lwp_create(res, ucp, flags, new_lwp) \
+ __sanitizer_syscall_post_impl__lwp_create( \
+ res, (long long)(ucp), (long long)(flags), (long long)(new_lwp))
+#define __sanitizer_syscall_pre__lwp_exit() \
+ __sanitizer_syscall_pre_impl__lwp_exit()
+#define __sanitizer_syscall_post__lwp_exit(res) \
+ __sanitizer_syscall_post_impl__lwp_exit(res)
+#define __sanitizer_syscall_pre__lwp_self() \
+ __sanitizer_syscall_pre_impl__lwp_self()
+#define __sanitizer_syscall_post__lwp_self(res) \
+ __sanitizer_syscall_post_impl__lwp_self(res)
+#define __sanitizer_syscall_pre__lwp_wait(wait_for, departed) \
+ __sanitizer_syscall_pre_impl__lwp_wait((long long)(wait_for), \
+ (long long)(departed))
+#define __sanitizer_syscall_post__lwp_wait(res, wait_for, departed) \
+ __sanitizer_syscall_post_impl__lwp_wait(res, (long long)(wait_for), \
+ (long long)(departed))
+#define __sanitizer_syscall_pre__lwp_suspend(target) \
+ __sanitizer_syscall_pre_impl__lwp_suspend((long long)(target))
+#define __sanitizer_syscall_post__lwp_suspend(res, target) \
+ __sanitizer_syscall_post_impl__lwp_suspend(res, (long long)(target))
+#define __sanitizer_syscall_pre__lwp_continue(target) \
+ __sanitizer_syscall_pre_impl__lwp_continue((long long)(target))
+#define __sanitizer_syscall_post__lwp_continue(res, target) \
+ __sanitizer_syscall_post_impl__lwp_continue(res, (long long)(target))
+#define __sanitizer_syscall_pre__lwp_wakeup(target) \
+ __sanitizer_syscall_pre_impl__lwp_wakeup((long long)(target))
+#define __sanitizer_syscall_post__lwp_wakeup(res, target) \
+ __sanitizer_syscall_post_impl__lwp_wakeup(res, (long long)(target))
+#define __sanitizer_syscall_pre__lwp_getprivate() \
+ __sanitizer_syscall_pre_impl__lwp_getprivate()
+#define __sanitizer_syscall_post__lwp_getprivate(res) \
+ __sanitizer_syscall_post_impl__lwp_getprivate(res)
+#define __sanitizer_syscall_pre__lwp_setprivate(ptr) \
+ __sanitizer_syscall_pre_impl__lwp_setprivate((long long)(ptr))
+#define __sanitizer_syscall_post__lwp_setprivate(res, ptr) \
+ __sanitizer_syscall_post_impl__lwp_setprivate(res, (long long)(ptr))
+#define __sanitizer_syscall_pre__lwp_kill(target, signo) \
+ __sanitizer_syscall_pre_impl__lwp_kill((long long)(target), \
+ (long long)(signo))
+#define __sanitizer_syscall_post__lwp_kill(res, target, signo) \
+ __sanitizer_syscall_post_impl__lwp_kill(res, (long long)(target), \
+ (long long)(signo))
+#define __sanitizer_syscall_pre__lwp_detach(target) \
+ __sanitizer_syscall_pre_impl__lwp_detach((long long)(target))
+#define __sanitizer_syscall_post__lwp_detach(res, target) \
+ __sanitizer_syscall_post_impl__lwp_detach(res, (long long)(target))
+#define __sanitizer_syscall_pre_compat_50__lwp_park(ts, unpark, hint, \
+ unparkhint) \
+ __sanitizer_syscall_pre_impl_compat_50__lwp_park( \
+ (long long)(ts), (long long)(unpark), (long long)(hint), \
+ (long long)(unparkhint))
+#define __sanitizer_syscall_post_compat_50__lwp_park(res, ts, unpark, hint, \
+ unparkhint) \
+ __sanitizer_syscall_post_impl_compat_50__lwp_park( \
+ res, (long long)(ts), (long long)(unpark), (long long)(hint), \
+ (long long)(unparkhint))
+#define __sanitizer_syscall_pre__lwp_unpark(target, hint) \
+ __sanitizer_syscall_pre_impl__lwp_unpark((long long)(target), \
+ (long long)(hint))
+#define __sanitizer_syscall_post__lwp_unpark(res, target, hint) \
+ __sanitizer_syscall_post_impl__lwp_unpark(res, (long long)(target), \
+ (long long)(hint))
+#define __sanitizer_syscall_pre__lwp_unpark_all(targets, ntargets, hint) \
+ __sanitizer_syscall_pre_impl__lwp_unpark_all( \
+ (long long)(targets), (long long)(ntargets), (long long)(hint))
+#define __sanitizer_syscall_post__lwp_unpark_all(res, targets, ntargets, hint) \
+ __sanitizer_syscall_post_impl__lwp_unpark_all( \
+ res, (long long)(targets), (long long)(ntargets), (long long)(hint))
+#define __sanitizer_syscall_pre__lwp_setname(target, name) \
+ __sanitizer_syscall_pre_impl__lwp_setname((long long)(target), \
+ (long long)(name))
+#define __sanitizer_syscall_post__lwp_setname(res, target, name) \
+ __sanitizer_syscall_post_impl__lwp_setname(res, (long long)(target), \
+ (long long)(name))
+#define __sanitizer_syscall_pre__lwp_getname(target, name, len) \
+ __sanitizer_syscall_pre_impl__lwp_getname( \
+ (long long)(target), (long long)(name), (long long)(len))
+#define __sanitizer_syscall_post__lwp_getname(res, target, name, len) \
+ __sanitizer_syscall_post_impl__lwp_getname( \
+ res, (long long)(target), (long long)(name), (long long)(len))
+#define __sanitizer_syscall_pre__lwp_ctl(features, address) \
+ __sanitizer_syscall_pre_impl__lwp_ctl((long long)(features), \
+ (long long)(address))
+#define __sanitizer_syscall_post__lwp_ctl(res, features, address) \
+ __sanitizer_syscall_post_impl__lwp_ctl(res, (long long)(features), \
+ (long long)(address))
+/* syscall 326 has been skipped */
+/* syscall 327 has been skipped */
+/* syscall 328 has been skipped */
+/* syscall 329 has been skipped */
+#define __sanitizer_syscall_pre_compat_60_sa_register(newv, oldv, flags, \
+ stackinfo_offset) \
+ __sanitizer_syscall_pre_impl_compat_60_sa_register( \
+ (long long)(newv), (long long)(oldv), (long long)(flags), \
+ (long long)(stackinfo_offset))
+#define __sanitizer_syscall_post_compat_60_sa_register(res, newv, oldv, flags, \
+ stackinfo_offset) \
+ __sanitizer_syscall_post_impl_compat_60_sa_register( \
+ res, (long long)(newv), (long long)(oldv), (long long)(flags), \
+ (long long)(stackinfo_offset))
+#define __sanitizer_syscall_pre_compat_60_sa_stacks(num, stacks) \
+ __sanitizer_syscall_pre_impl_compat_60_sa_stacks((long long)(num), \
+ (long long)(stacks))
+#define __sanitizer_syscall_post_compat_60_sa_stacks(res, num, stacks) \
+ __sanitizer_syscall_post_impl_compat_60_sa_stacks(res, (long long)(num), \
+ (long long)(stacks))
+#define __sanitizer_syscall_pre_compat_60_sa_enable() \
+ __sanitizer_syscall_pre_impl_compat_60_sa_enable()
+#define __sanitizer_syscall_post_compat_60_sa_enable(res) \
+ __sanitizer_syscall_post_impl_compat_60_sa_enable(res)
+#define __sanitizer_syscall_pre_compat_60_sa_setconcurrency(concurrency) \
+ __sanitizer_syscall_pre_impl_compat_60_sa_setconcurrency( \
+ (long long)(concurrency))
+#define __sanitizer_syscall_post_compat_60_sa_setconcurrency(res, concurrency) \
+ __sanitizer_syscall_post_impl_compat_60_sa_setconcurrency( \
+ res, (long long)(concurrency))
+#define __sanitizer_syscall_pre_compat_60_sa_yield() \
+ __sanitizer_syscall_pre_impl_compat_60_sa_yield()
+#define __sanitizer_syscall_post_compat_60_sa_yield(res) \
+ __sanitizer_syscall_post_impl_compat_60_sa_yield(res)
+#define __sanitizer_syscall_pre_compat_60_sa_preempt(sa_id) \
+ __sanitizer_syscall_pre_impl_compat_60_sa_preempt((long long)(sa_id))
+#define __sanitizer_syscall_post_compat_60_sa_preempt(res, sa_id) \
+ __sanitizer_syscall_post_impl_compat_60_sa_preempt(res, (long long)(sa_id))
+/* syscall 336 has been skipped */
+/* syscall 337 has been skipped */
+/* syscall 338 has been skipped */
+/* syscall 339 has been skipped */
+#define __sanitizer_syscall_pre___sigaction_sigtramp(signum, nsa, osa, tramp, \
+ vers) \
+ __sanitizer_syscall_pre_impl___sigaction_sigtramp( \
+ (long long)(signum), (long long)(nsa), (long long)(osa), \
+ (long long)(tramp), (long long)(vers))
+#define __sanitizer_syscall_post___sigaction_sigtramp(res, signum, nsa, osa, \
+ tramp, vers) \
+ __sanitizer_syscall_post_impl___sigaction_sigtramp( \
+ res, (long long)(signum), (long long)(nsa), (long long)(osa), \
+ (long long)(tramp), (long long)(vers))
+/* syscall 341 has been skipped */
+/* syscall 342 has been skipped */
+#define __sanitizer_syscall_pre_rasctl(addr, len, op) \
+ __sanitizer_syscall_pre_impl_rasctl((long long)(addr), (long long)(len), \
+ (long long)(op))
+#define __sanitizer_syscall_post_rasctl(res, addr, len, op) \
+ __sanitizer_syscall_post_impl_rasctl(res, (long long)(addr), \
+ (long long)(len), (long long)(op))
+#define __sanitizer_syscall_pre_kqueue() __sanitizer_syscall_pre_impl_kqueue()
+#define __sanitizer_syscall_post_kqueue(res) \
+ __sanitizer_syscall_post_impl_kqueue(res)
+#define __sanitizer_syscall_pre_compat_50_kevent(fd, changelist, nchanges, \
+ eventlist, nevents, timeout) \
+ __sanitizer_syscall_pre_impl_compat_50_kevent( \
+ (long long)(fd), (long long)(changelist), (long long)(nchanges), \
+ (long long)(eventlist), (long long)(nevents), (long long)(timeout))
+#define __sanitizer_syscall_post_compat_50_kevent( \
+ res, fd, changelist, nchanges, eventlist, nevents, timeout) \
+ __sanitizer_syscall_post_impl_compat_50_kevent( \
+ res, (long long)(fd), (long long)(changelist), (long long)(nchanges), \
+ (long long)(eventlist), (long long)(nevents), (long long)(timeout))
+#define __sanitizer_syscall_pre__sched_setparam(pid, lid, policy, params) \
+ __sanitizer_syscall_pre_impl__sched_setparam( \
+ (long long)(pid), (long long)(lid), (long long)(policy), \
+ (long long)(params))
+#define __sanitizer_syscall_post__sched_setparam(res, pid, lid, policy, \
+ params) \
+ __sanitizer_syscall_post_impl__sched_setparam( \
+ res, (long long)(pid), (long long)(lid), (long long)(policy), \
+ (long long)(params))
+#define __sanitizer_syscall_pre__sched_getparam(pid, lid, policy, params) \
+ __sanitizer_syscall_pre_impl__sched_getparam( \
+ (long long)(pid), (long long)(lid), (long long)(policy), \
+ (long long)(params))
+#define __sanitizer_syscall_post__sched_getparam(res, pid, lid, policy, \
+ params) \
+ __sanitizer_syscall_post_impl__sched_getparam( \
+ res, (long long)(pid), (long long)(lid), (long long)(policy), \
+ (long long)(params))
+#define __sanitizer_syscall_pre__sched_setaffinity(pid, lid, size, cpuset) \
+ __sanitizer_syscall_pre_impl__sched_setaffinity( \
+ (long long)(pid), (long long)(lid), (long long)(size), \
+ (long long)(cpuset))
+#define __sanitizer_syscall_post__sched_setaffinity(res, pid, lid, size, \
+ cpuset) \
+ __sanitizer_syscall_post_impl__sched_setaffinity( \
+ res, (long long)(pid), (long long)(lid), (long long)(size), \
+ (long long)(cpuset))
+#define __sanitizer_syscall_pre__sched_getaffinity(pid, lid, size, cpuset) \
+ __sanitizer_syscall_pre_impl__sched_getaffinity( \
+ (long long)(pid), (long long)(lid), (long long)(size), \
+ (long long)(cpuset))
+#define __sanitizer_syscall_post__sched_getaffinity(res, pid, lid, size, \
+ cpuset) \
+ __sanitizer_syscall_post_impl__sched_getaffinity( \
+ res, (long long)(pid), (long long)(lid), (long long)(size), \
+ (long long)(cpuset))
+#define __sanitizer_syscall_pre_sched_yield() \
+ __sanitizer_syscall_pre_impl_sched_yield()
+#define __sanitizer_syscall_post_sched_yield(res) \
+ __sanitizer_syscall_post_impl_sched_yield(res)
+#define __sanitizer_syscall_pre__sched_protect(priority) \
+ __sanitizer_syscall_pre_impl__sched_protect((long long)(priority))
+#define __sanitizer_syscall_post__sched_protect(res, priority) \
+ __sanitizer_syscall_post_impl__sched_protect(res, (long long)(priority))
+/* syscall 352 has been skipped */
+/* syscall 353 has been skipped */
+#define __sanitizer_syscall_pre_fsync_range(fd, flags, start, length) \
+ __sanitizer_syscall_pre_impl_fsync_range( \
+ (long long)(fd), (long long)(flags), (long long)(start), \
+ (long long)(length))
+#define __sanitizer_syscall_post_fsync_range(res, fd, flags, start, length) \
+ __sanitizer_syscall_post_impl_fsync_range( \
+ res, (long long)(fd), (long long)(flags), (long long)(start), \
+ (long long)(length))
+#define __sanitizer_syscall_pre_uuidgen(store, count) \
+ __sanitizer_syscall_pre_impl_uuidgen((long long)(store), (long long)(count))
+#define __sanitizer_syscall_post_uuidgen(res, store, count) \
+ __sanitizer_syscall_post_impl_uuidgen(res, (long long)(store), \
+ (long long)(count))
+#define __sanitizer_syscall_pre_compat_90_getvfsstat(buf, bufsize, flags) \
+ __sanitizer_syscall_pre_impl_compat_90_getvfsstat( \
+ (long long)(buf), (long long)(bufsize), (long long)(flags))
+#define __sanitizer_syscall_post_compat_90_getvfsstat(res, buf, bufsize, \
+ flags) \
+ __sanitizer_syscall_post_impl_compat_90_getvfsstat( \
+ res, (long long)(buf), (long long)(bufsize), (long long)(flags))
+#define __sanitizer_syscall_pre_compat_90_statvfs1(path, buf, flags) \
+ __sanitizer_syscall_pre_impl_compat_90_statvfs1( \
+ (long long)(path), (long long)(buf), (long long)(flags))
+#define __sanitizer_syscall_post_compat_90_statvfs1(res, path, buf, flags) \
+ __sanitizer_syscall_post_impl_compat_90_statvfs1( \
+ res, (long long)(path), (long long)(buf), (long long)(flags))
+#define __sanitizer_syscall_pre_compat_90_fstatvfs1(fd, buf, flags) \
+ __sanitizer_syscall_pre_impl_compat_90_fstatvfs1( \
+ (long long)(fd), (long long)(buf), (long long)(flags))
+#define __sanitizer_syscall_post_compat_90_fstatvfs1(res, fd, buf, flags) \
+ __sanitizer_syscall_post_impl_compat_90_fstatvfs1( \
+ res, (long long)(fd), (long long)(buf), (long long)(flags))
+#define __sanitizer_syscall_pre_compat_30_fhstatvfs1(fhp, buf, flags) \
+ __sanitizer_syscall_pre_impl_compat_30_fhstatvfs1( \
+ (long long)(fhp), (long long)(buf), (long long)(flags))
+#define __sanitizer_syscall_post_compat_30_fhstatvfs1(res, fhp, buf, flags) \
+ __sanitizer_syscall_post_impl_compat_30_fhstatvfs1( \
+ res, (long long)(fhp), (long long)(buf), (long long)(flags))
+#define __sanitizer_syscall_pre_extattrctl(path, cmd, filename, attrnamespace, \
+ attrname) \
+ __sanitizer_syscall_pre_impl_extattrctl( \
+ (long long)(path), (long long)(cmd), (long long)(filename), \
+ (long long)(attrnamespace), (long long)(attrname))
+#define __sanitizer_syscall_post_extattrctl(res, path, cmd, filename, \
+ attrnamespace, attrname) \
+ __sanitizer_syscall_post_impl_extattrctl( \
+ res, (long long)(path), (long long)(cmd), (long long)(filename), \
+ (long long)(attrnamespace), (long long)(attrname))
+#define __sanitizer_syscall_pre_extattr_set_file(path, attrnamespace, \
+ attrname, data, nbytes) \
+ __sanitizer_syscall_pre_impl_extattr_set_file( \
+ (long long)(path), (long long)(attrnamespace), (long long)(attrname), \
+ (long long)(data), (long long)(nbytes))
+#define __sanitizer_syscall_post_extattr_set_file(res, path, attrnamespace, \
+ attrname, data, nbytes) \
+ __sanitizer_syscall_post_impl_extattr_set_file( \
+ res, (long long)(path), (long long)(attrnamespace), \
+ (long long)(attrname), (long long)(data), (long long)(nbytes))
+#define __sanitizer_syscall_pre_extattr_get_file(path, attrnamespace, \
+ attrname, data, nbytes) \
+ __sanitizer_syscall_pre_impl_extattr_get_file( \
+ (long long)(path), (long long)(attrnamespace), (long long)(attrname), \
+ (long long)(data), (long long)(nbytes))
+#define __sanitizer_syscall_post_extattr_get_file(res, path, attrnamespace, \
+ attrname, data, nbytes) \
+ __sanitizer_syscall_post_impl_extattr_get_file( \
+ res, (long long)(path), (long long)(attrnamespace), \
+ (long long)(attrname), (long long)(data), (long long)(nbytes))
+#define __sanitizer_syscall_pre_extattr_delete_file(path, attrnamespace, \
+ attrname) \
+ __sanitizer_syscall_pre_impl_extattr_delete_file( \
+ (long long)(path), (long long)(attrnamespace), (long long)(attrname))
+#define __sanitizer_syscall_post_extattr_delete_file(res, path, attrnamespace, \
+ attrname) \
+ __sanitizer_syscall_post_impl_extattr_delete_file( \
+ res, (long long)(path), (long long)(attrnamespace), \
+ (long long)(attrname))
+#define __sanitizer_syscall_pre_extattr_set_fd(fd, attrnamespace, attrname, \
+ data, nbytes) \
+ __sanitizer_syscall_pre_impl_extattr_set_fd( \
+ (long long)(fd), (long long)(attrnamespace), (long long)(attrname), \
+ (long long)(data), (long long)(nbytes))
+#define __sanitizer_syscall_post_extattr_set_fd(res, fd, attrnamespace, \
+ attrname, data, nbytes) \
+ __sanitizer_syscall_post_impl_extattr_set_fd( \
+ res, (long long)(fd), (long long)(attrnamespace), (long long)(attrname), \
+ (long long)(data), (long long)(nbytes))
+#define __sanitizer_syscall_pre_extattr_get_fd(fd, attrnamespace, attrname, \
+ data, nbytes) \
+ __sanitizer_syscall_pre_impl_extattr_get_fd( \
+ (long long)(fd), (long long)(attrnamespace), (long long)(attrname), \
+ (long long)(data), (long long)(nbytes))
+#define __sanitizer_syscall_post_extattr_get_fd(res, fd, attrnamespace, \
+ attrname, data, nbytes) \
+ __sanitizer_syscall_post_impl_extattr_get_fd( \
+ res, (long long)(fd), (long long)(attrnamespace), (long long)(attrname), \
+ (long long)(data), (long long)(nbytes))
+#define __sanitizer_syscall_pre_extattr_delete_fd(fd, attrnamespace, attrname) \
+ __sanitizer_syscall_pre_impl_extattr_delete_fd( \
+ (long long)(fd), (long long)(attrnamespace), (long long)(attrname))
+#define __sanitizer_syscall_post_extattr_delete_fd(res, fd, attrnamespace, \
+ attrname) \
+ __sanitizer_syscall_post_impl_extattr_delete_fd( \
+ res, (long long)(fd), (long long)(attrnamespace), (long long)(attrname))
+#define __sanitizer_syscall_pre_extattr_set_link(path, attrnamespace, \
+ attrname, data, nbytes) \
+ __sanitizer_syscall_pre_impl_extattr_set_link( \
+ (long long)(path), (long long)(attrnamespace), (long long)(attrname), \
+ (long long)(data), (long long)(nbytes))
+#define __sanitizer_syscall_post_extattr_set_link(res, path, attrnamespace, \
+ attrname, data, nbytes) \
+ __sanitizer_syscall_post_impl_extattr_set_link( \
+ res, (long long)(path), (long long)(attrnamespace), \
+ (long long)(attrname), (long long)(data), (long long)(nbytes))
+#define __sanitizer_syscall_pre_extattr_get_link(path, attrnamespace, \
+ attrname, data, nbytes) \
+ __sanitizer_syscall_pre_impl_extattr_get_link( \
+ (long long)(path), (long long)(attrnamespace), (long long)(attrname), \
+ (long long)(data), (long long)(nbytes))
+#define __sanitizer_syscall_post_extattr_get_link(res, path, attrnamespace, \
+ attrname, data, nbytes) \
+ __sanitizer_syscall_post_impl_extattr_get_link( \
+ res, (long long)(path), (long long)(attrnamespace), \
+ (long long)(attrname), (long long)(data), (long long)(nbytes))
+#define __sanitizer_syscall_pre_extattr_delete_link(path, attrnamespace, \
+ attrname) \
+ __sanitizer_syscall_pre_impl_extattr_delete_link( \
+ (long long)(path), (long long)(attrnamespace), (long long)(attrname))
+#define __sanitizer_syscall_post_extattr_delete_link(res, path, attrnamespace, \
+ attrname) \
+ __sanitizer_syscall_post_impl_extattr_delete_link( \
+ res, (long long)(path), (long long)(attrnamespace), \
+ (long long)(attrname))
+#define __sanitizer_syscall_pre_extattr_list_fd(fd, attrnamespace, data, \
+ nbytes) \
+ __sanitizer_syscall_pre_impl_extattr_list_fd( \
+ (long long)(fd), (long long)(attrnamespace), (long long)(data), \
+ (long long)(nbytes))
+#define __sanitizer_syscall_post_extattr_list_fd(res, fd, attrnamespace, data, \
+ nbytes) \
+ __sanitizer_syscall_post_impl_extattr_list_fd( \
+ res, (long long)(fd), (long long)(attrnamespace), (long long)(data), \
+ (long long)(nbytes))
+#define __sanitizer_syscall_pre_extattr_list_file(path, attrnamespace, data, \
+ nbytes) \
+ __sanitizer_syscall_pre_impl_extattr_list_file( \
+ (long long)(path), (long long)(attrnamespace), (long long)(data), \
+ (long long)(nbytes))
+#define __sanitizer_syscall_post_extattr_list_file(res, path, attrnamespace, \
+ data, nbytes) \
+ __sanitizer_syscall_post_impl_extattr_list_file( \
+ res, (long long)(path), (long long)(attrnamespace), (long long)(data), \
+ (long long)(nbytes))
+#define __sanitizer_syscall_pre_extattr_list_link(path, attrnamespace, data, \
+ nbytes) \
+ __sanitizer_syscall_pre_impl_extattr_list_link( \
+ (long long)(path), (long long)(attrnamespace), (long long)(data), \
+ (long long)(nbytes))
+#define __sanitizer_syscall_post_extattr_list_link(res, path, attrnamespace, \
+ data, nbytes) \
+ __sanitizer_syscall_post_impl_extattr_list_link( \
+ res, (long long)(path), (long long)(attrnamespace), (long long)(data), \
+ (long long)(nbytes))
+#define __sanitizer_syscall_pre_compat_50_pselect(nd, in, ou, ex, ts, mask) \
+ __sanitizer_syscall_pre_impl_compat_50_pselect( \
+ (long long)(nd), (long long)(in), (long long)(ou), (long long)(ex), \
+ (long long)(ts), (long long)(mask))
+#define __sanitizer_syscall_post_compat_50_pselect(res, nd, in, ou, ex, ts, \
+ mask) \
+ __sanitizer_syscall_post_impl_compat_50_pselect( \
+ res, (long long)(nd), (long long)(in), (long long)(ou), (long long)(ex), \
+ (long long)(ts), (long long)(mask))
+#define __sanitizer_syscall_pre_compat_50_pollts(fds, nfds, ts, mask) \
+ __sanitizer_syscall_pre_impl_compat_50_pollts( \
+ (long long)(fds), (long long)(nfds), (long long)(ts), (long long)(mask))
+#define __sanitizer_syscall_post_compat_50_pollts(res, fds, nfds, ts, mask) \
+ __sanitizer_syscall_post_impl_compat_50_pollts( \
+ res, (long long)(fds), (long long)(nfds), (long long)(ts), \
+ (long long)(mask))
+#define __sanitizer_syscall_pre_setxattr(path, name, value, size, flags) \
+ __sanitizer_syscall_pre_impl_setxattr((long long)(path), (long long)(name), \
+ (long long)(value), (long long)(size), \
+ (long long)(flags))
+#define __sanitizer_syscall_post_setxattr(res, path, name, value, size, flags) \
+ __sanitizer_syscall_post_impl_setxattr( \
+ res, (long long)(path), (long long)(name), (long long)(value), \
+ (long long)(size), (long long)(flags))
+#define __sanitizer_syscall_pre_lsetxattr(path, name, value, size, flags) \
+ __sanitizer_syscall_pre_impl_lsetxattr( \
+ (long long)(path), (long long)(name), (long long)(value), \
+ (long long)(size), (long long)(flags))
+#define __sanitizer_syscall_post_lsetxattr(res, path, name, value, size, \
+ flags) \
+ __sanitizer_syscall_post_impl_lsetxattr( \
+ res, (long long)(path), (long long)(name), (long long)(value), \
+ (long long)(size), (long long)(flags))
+#define __sanitizer_syscall_pre_fsetxattr(fd, name, value, size, flags) \
+ __sanitizer_syscall_pre_impl_fsetxattr( \
+ (long long)(fd), (long long)(name), (long long)(value), \
+ (long long)(size), (long long)(flags))
+#define __sanitizer_syscall_post_fsetxattr(res, fd, name, value, size, flags) \
+ __sanitizer_syscall_post_impl_fsetxattr( \
+ res, (long long)(fd), (long long)(name), (long long)(value), \
+ (long long)(size), (long long)(flags))
+#define __sanitizer_syscall_pre_getxattr(path, name, value, size) \
+ __sanitizer_syscall_pre_impl_getxattr((long long)(path), (long long)(name), \
+ (long long)(value), (long long)(size))
+#define __sanitizer_syscall_post_getxattr(res, path, name, value, size) \
+ __sanitizer_syscall_post_impl_getxattr( \
+ res, (long long)(path), (long long)(name), (long long)(value), \
+ (long long)(size))
+#define __sanitizer_syscall_pre_lgetxattr(path, name, value, size) \
+ __sanitizer_syscall_pre_impl_lgetxattr((long long)(path), (long long)(name), \
+ (long long)(value), \
+ (long long)(size))
+#define __sanitizer_syscall_post_lgetxattr(res, path, name, value, size) \
+ __sanitizer_syscall_post_impl_lgetxattr( \
+ res, (long long)(path), (long long)(name), (long long)(value), \
+ (long long)(size))
+#define __sanitizer_syscall_pre_fgetxattr(fd, name, value, size) \
+ __sanitizer_syscall_pre_impl_fgetxattr((long long)(fd), (long long)(name), \
+ (long long)(value), \
+ (long long)(size))
+#define __sanitizer_syscall_post_fgetxattr(res, fd, name, value, size) \
+ __sanitizer_syscall_post_impl_fgetxattr( \
+ res, (long long)(fd), (long long)(name), (long long)(value), \
+ (long long)(size))
+#define __sanitizer_syscall_pre_listxattr(path, list, size) \
+ __sanitizer_syscall_pre_impl_listxattr((long long)(path), (long long)(list), \
+ (long long)(size))
+#define __sanitizer_syscall_post_listxattr(res, path, list, size) \
+ __sanitizer_syscall_post_impl_listxattr( \
+ res, (long long)(path), (long long)(list), (long long)(size))
+#define __sanitizer_syscall_pre_llistxattr(path, list, size) \
+ __sanitizer_syscall_pre_impl_llistxattr( \
+ (long long)(path), (long long)(list), (long long)(size))
+#define __sanitizer_syscall_post_llistxattr(res, path, list, size) \
+ __sanitizer_syscall_post_impl_llistxattr( \
+ res, (long long)(path), (long long)(list), (long long)(size))
+#define __sanitizer_syscall_pre_flistxattr(fd, list, size) \
+ __sanitizer_syscall_pre_impl_flistxattr((long long)(fd), (long long)(list), \
+ (long long)(size))
+#define __sanitizer_syscall_post_flistxattr(res, fd, list, size) \
+ __sanitizer_syscall_post_impl_flistxattr( \
+ res, (long long)(fd), (long long)(list), (long long)(size))
+#define __sanitizer_syscall_pre_removexattr(path, name) \
+ __sanitizer_syscall_pre_impl_removexattr((long long)(path), (long long)(name))
+#define __sanitizer_syscall_post_removexattr(res, path, name) \
+ __sanitizer_syscall_post_impl_removexattr(res, (long long)(path), \
+ (long long)(name))
+#define __sanitizer_syscall_pre_lremovexattr(path, name) \
+ __sanitizer_syscall_pre_impl_lremovexattr((long long)(path), \
+ (long long)(name))
+#define __sanitizer_syscall_post_lremovexattr(res, path, name) \
+ __sanitizer_syscall_post_impl_lremovexattr(res, (long long)(path), \
+ (long long)(name))
+#define __sanitizer_syscall_pre_fremovexattr(fd, name) \
+ __sanitizer_syscall_pre_impl_fremovexattr((long long)(fd), (long long)(name))
+#define __sanitizer_syscall_post_fremovexattr(res, fd, name) \
+ __sanitizer_syscall_post_impl_fremovexattr(res, (long long)(fd), \
+ (long long)(name))
+#define __sanitizer_syscall_pre_compat_50___stat30(path, ub) \
+ __sanitizer_syscall_pre_impl_compat_50___stat30((long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_post_compat_50___stat30(res, path, ub) \
+ __sanitizer_syscall_post_impl_compat_50___stat30(res, (long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_pre_compat_50___fstat30(fd, sb) \
+ __sanitizer_syscall_pre_impl_compat_50___fstat30((long long)(fd), \
+ (long long)(sb))
+#define __sanitizer_syscall_post_compat_50___fstat30(res, fd, sb) \
+ __sanitizer_syscall_post_impl_compat_50___fstat30(res, (long long)(fd), \
+ (long long)(sb))
+#define __sanitizer_syscall_pre_compat_50___lstat30(path, ub) \
+ __sanitizer_syscall_pre_impl_compat_50___lstat30((long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_post_compat_50___lstat30(res, path, ub) \
+ __sanitizer_syscall_post_impl_compat_50___lstat30(res, (long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_pre___getdents30(fd, buf, count) \
+ __sanitizer_syscall_pre_impl___getdents30((long long)(fd), (long long)(buf), \
+ (long long)(count))
+#define __sanitizer_syscall_post___getdents30(res, fd, buf, count) \
+ __sanitizer_syscall_post_impl___getdents30( \
+ res, (long long)(fd), (long long)(buf), (long long)(count))
+#define __sanitizer_syscall_pre_posix_fadvise() \
+ __sanitizer_syscall_pre_impl_posix_fadvise((long long)())
+#define __sanitizer_syscall_post_posix_fadvise(res) \
+ __sanitizer_syscall_post_impl_posix_fadvise(res, (long long)())
+#define __sanitizer_syscall_pre_compat_30___fhstat30(fhp, sb) \
+ __sanitizer_syscall_pre_impl_compat_30___fhstat30((long long)(fhp), \
+ (long long)(sb))
+#define __sanitizer_syscall_post_compat_30___fhstat30(res, fhp, sb) \
+ __sanitizer_syscall_post_impl_compat_30___fhstat30(res, (long long)(fhp), \
+ (long long)(sb))
+#define __sanitizer_syscall_pre_compat_50___ntp_gettime30(ntvp) \
+ __sanitizer_syscall_pre_impl_compat_50___ntp_gettime30((long long)(ntvp))
+#define __sanitizer_syscall_post_compat_50___ntp_gettime30(res, ntvp) \
+ __sanitizer_syscall_post_impl_compat_50___ntp_gettime30(res, \
+ (long long)(ntvp))
+#define __sanitizer_syscall_pre___socket30(domain, type, protocol) \
+ __sanitizer_syscall_pre_impl___socket30( \
+ (long long)(domain), (long long)(type), (long long)(protocol))
+#define __sanitizer_syscall_post___socket30(res, domain, type, protocol) \
+ __sanitizer_syscall_post_impl___socket30( \
+ res, (long long)(domain), (long long)(type), (long long)(protocol))
+#define __sanitizer_syscall_pre___getfh30(fname, fhp, fh_size) \
+ __sanitizer_syscall_pre_impl___getfh30((long long)(fname), (long long)(fhp), \
+ (long long)(fh_size))
+#define __sanitizer_syscall_post___getfh30(res, fname, fhp, fh_size) \
+ __sanitizer_syscall_post_impl___getfh30( \
+ res, (long long)(fname), (long long)(fhp), (long long)(fh_size))
+#define __sanitizer_syscall_pre___fhopen40(fhp, fh_size, flags) \
+ __sanitizer_syscall_pre_impl___fhopen40( \
+ (long long)(fhp), (long long)(fh_size), (long long)(flags))
+#define __sanitizer_syscall_post___fhopen40(res, fhp, fh_size, flags) \
+ __sanitizer_syscall_post_impl___fhopen40( \
+ res, (long long)(fhp), (long long)(fh_size), (long long)(flags))
+#define __sanitizer_syscall_pre_compat_90_fhstatvfs1(fhp, fh_size, buf, flags) \
+ __sanitizer_syscall_pre_impl_compat_90_fhstatvfs1( \
+ (long long)(fhp), (long long)(fh_size), (long long)(buf), \
+ (long long)(flags))
+#define __sanitizer_syscall_post_compat_90_fhstatvfs1(res, fhp, fh_size, buf, \
+ flags) \
+ __sanitizer_syscall_post_impl_compat_90_fhstatvfs1( \
+ res, (long long)(fhp), (long long)(fh_size), (long long)(buf), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_compat_50___fhstat40(fhp, fh_size, sb) \
+ __sanitizer_syscall_pre_impl_compat_50___fhstat40( \
+ (long long)(fhp), (long long)(fh_size), (long long)(sb))
+#define __sanitizer_syscall_post_compat_50___fhstat40(res, fhp, fh_size, sb) \
+ __sanitizer_syscall_post_impl_compat_50___fhstat40( \
+ res, (long long)(fhp), (long long)(fh_size), (long long)(sb))
+#define __sanitizer_syscall_pre_aio_cancel(fildes, aiocbp) \
+ __sanitizer_syscall_pre_impl_aio_cancel((long long)(fildes), \
+ (long long)(aiocbp))
+#define __sanitizer_syscall_post_aio_cancel(res, fildes, aiocbp) \
+ __sanitizer_syscall_post_impl_aio_cancel(res, (long long)(fildes), \
+ (long long)(aiocbp))
+#define __sanitizer_syscall_pre_aio_error(aiocbp) \
+ __sanitizer_syscall_pre_impl_aio_error((long long)(aiocbp))
+#define __sanitizer_syscall_post_aio_error(res, aiocbp) \
+ __sanitizer_syscall_post_impl_aio_error(res, (long long)(aiocbp))
+#define __sanitizer_syscall_pre_aio_fsync(op, aiocbp) \
+ __sanitizer_syscall_pre_impl_aio_fsync((long long)(op), (long long)(aiocbp))
+#define __sanitizer_syscall_post_aio_fsync(res, op, aiocbp) \
+ __sanitizer_syscall_post_impl_aio_fsync(res, (long long)(op), \
+ (long long)(aiocbp))
+#define __sanitizer_syscall_pre_aio_read(aiocbp) \
+ __sanitizer_syscall_pre_impl_aio_read((long long)(aiocbp))
+#define __sanitizer_syscall_post_aio_read(res, aiocbp) \
+ __sanitizer_syscall_post_impl_aio_read(res, (long long)(aiocbp))
+#define __sanitizer_syscall_pre_aio_return(aiocbp) \
+ __sanitizer_syscall_pre_impl_aio_return((long long)(aiocbp))
+#define __sanitizer_syscall_post_aio_return(res, aiocbp) \
+ __sanitizer_syscall_post_impl_aio_return(res, (long long)(aiocbp))
+#define __sanitizer_syscall_pre_compat_50_aio_suspend(list, nent, timeout) \
+ __sanitizer_syscall_pre_impl_compat_50_aio_suspend( \
+ (long long)(list), (long long)(nent), (long long)(timeout))
+#define __sanitizer_syscall_post_compat_50_aio_suspend(res, list, nent, \
+ timeout) \
+ __sanitizer_syscall_post_impl_compat_50_aio_suspend( \
+ res, (long long)(list), (long long)(nent), (long long)(timeout))
+#define __sanitizer_syscall_pre_aio_write(aiocbp) \
+ __sanitizer_syscall_pre_impl_aio_write((long long)(aiocbp))
+#define __sanitizer_syscall_post_aio_write(res, aiocbp) \
+ __sanitizer_syscall_post_impl_aio_write(res, (long long)(aiocbp))
+#define __sanitizer_syscall_pre_lio_listio(mode, list, nent, sig) \
+ __sanitizer_syscall_pre_impl_lio_listio((long long)(mode), \
+ (long long)(list), \
+ (long long)(nent), (long long)(sig))
+#define __sanitizer_syscall_post_lio_listio(res, mode, list, nent, sig) \
+ __sanitizer_syscall_post_impl_lio_listio( \
+ res, (long long)(mode), (long long)(list), (long long)(nent), \
+ (long long)(sig))
+/* syscall 407 has been skipped */
+/* syscall 408 has been skipped */
+/* syscall 409 has been skipped */
+#define __sanitizer_syscall_pre___mount50(type, path, flags, data, data_len) \
+ __sanitizer_syscall_pre_impl___mount50( \
+ (long long)(type), (long long)(path), (long long)(flags), \
+ (long long)(data), (long long)(data_len))
+#define __sanitizer_syscall_post___mount50(res, type, path, flags, data, \
+ data_len) \
+ __sanitizer_syscall_post_impl___mount50( \
+ res, (long long)(type), (long long)(path), (long long)(flags), \
+ (long long)(data), (long long)(data_len))
+#define __sanitizer_syscall_pre_mremap(old_address, old_size, new_address, \
+ new_size, flags) \
+ __sanitizer_syscall_pre_impl_mremap( \
+ (long long)(old_address), (long long)(old_size), \
+ (long long)(new_address), (long long)(new_size), (long long)(flags))
+#define __sanitizer_syscall_post_mremap(res, old_address, old_size, \
+ new_address, new_size, flags) \
+ __sanitizer_syscall_post_impl_mremap( \
+ res, (long long)(old_address), (long long)(old_size), \
+ (long long)(new_address), (long long)(new_size), (long long)(flags))
+#define __sanitizer_syscall_pre_pset_create(psid) \
+ __sanitizer_syscall_pre_impl_pset_create((long long)(psid))
+#define __sanitizer_syscall_post_pset_create(res, psid) \
+ __sanitizer_syscall_post_impl_pset_create(res, (long long)(psid))
+#define __sanitizer_syscall_pre_pset_destroy(psid) \
+ __sanitizer_syscall_pre_impl_pset_destroy((long long)(psid))
+#define __sanitizer_syscall_post_pset_destroy(res, psid) \
+ __sanitizer_syscall_post_impl_pset_destroy(res, (long long)(psid))
+#define __sanitizer_syscall_pre_pset_assign(psid, cpuid, opsid) \
+ __sanitizer_syscall_pre_impl_pset_assign( \
+ (long long)(psid), (long long)(cpuid), (long long)(opsid))
+#define __sanitizer_syscall_post_pset_assign(res, psid, cpuid, opsid) \
+ __sanitizer_syscall_post_impl_pset_assign( \
+ res, (long long)(psid), (long long)(cpuid), (long long)(opsid))
+#define __sanitizer_syscall_pre__pset_bind(idtype, first_id, second_id, psid, \
+ opsid) \
+ __sanitizer_syscall_pre_impl__pset_bind( \
+ (long long)(idtype), (long long)(first_id), (long long)(second_id), \
+ (long long)(psid), (long long)(opsid))
+#define __sanitizer_syscall_post__pset_bind(res, idtype, first_id, second_id, \
+ psid, opsid) \
+ __sanitizer_syscall_post_impl__pset_bind( \
+ res, (long long)(idtype), (long long)(first_id), (long long)(second_id), \
+ (long long)(psid), (long long)(opsid))
+#define __sanitizer_syscall_pre___posix_fadvise50(fd, PAD, offset, len, \
+ advice) \
+ __sanitizer_syscall_pre_impl___posix_fadvise50( \
+ (long long)(fd), (long long)(PAD), (long long)(offset), \
+ (long long)(len), (long long)(advice))
+#define __sanitizer_syscall_post___posix_fadvise50(res, fd, PAD, offset, len, \
+ advice) \
+ __sanitizer_syscall_post_impl___posix_fadvise50( \
+ res, (long long)(fd), (long long)(PAD), (long long)(offset), \
+ (long long)(len), (long long)(advice))
+#define __sanitizer_syscall_pre___select50(nd, in, ou, ex, tv) \
+ __sanitizer_syscall_pre_impl___select50((long long)(nd), (long long)(in), \
+ (long long)(ou), (long long)(ex), \
+ (long long)(tv))
+#define __sanitizer_syscall_post___select50(res, nd, in, ou, ex, tv) \
+ __sanitizer_syscall_post_impl___select50(res, (long long)(nd), \
+ (long long)(in), (long long)(ou), \
+ (long long)(ex), (long long)(tv))
+#define __sanitizer_syscall_pre___gettimeofday50(tp, tzp) \
+ __sanitizer_syscall_pre_impl___gettimeofday50((long long)(tp), \
+ (long long)(tzp))
+#define __sanitizer_syscall_post___gettimeofday50(res, tp, tzp) \
+ __sanitizer_syscall_post_impl___gettimeofday50(res, (long long)(tp), \
+ (long long)(tzp))
+#define __sanitizer_syscall_pre___settimeofday50(tv, tzp) \
+ __sanitizer_syscall_pre_impl___settimeofday50((long long)(tv), \
+ (long long)(tzp))
+#define __sanitizer_syscall_post___settimeofday50(res, tv, tzp) \
+ __sanitizer_syscall_post_impl___settimeofday50(res, (long long)(tv), \
+ (long long)(tzp))
+#define __sanitizer_syscall_pre___utimes50(path, tptr) \
+ __sanitizer_syscall_pre_impl___utimes50((long long)(path), (long long)(tptr))
+#define __sanitizer_syscall_post___utimes50(res, path, tptr) \
+ __sanitizer_syscall_post_impl___utimes50(res, (long long)(path), \
+ (long long)(tptr))
+#define __sanitizer_syscall_pre___adjtime50(delta, olddelta) \
+ __sanitizer_syscall_pre_impl___adjtime50((long long)(delta), \
+ (long long)(olddelta))
+#define __sanitizer_syscall_post___adjtime50(res, delta, olddelta) \
+ __sanitizer_syscall_post_impl___adjtime50(res, (long long)(delta), \
+ (long long)(olddelta))
+#define __sanitizer_syscall_pre___lfs_segwait50(fsidp, tv) \
+ __sanitizer_syscall_pre_impl___lfs_segwait50((long long)(fsidp), \
+ (long long)(tv))
+#define __sanitizer_syscall_post___lfs_segwait50(res, fsidp, tv) \
+ __sanitizer_syscall_post_impl___lfs_segwait50(res, (long long)(fsidp), \
+ (long long)(tv))
+#define __sanitizer_syscall_pre___futimes50(fd, tptr) \
+ __sanitizer_syscall_pre_impl___futimes50((long long)(fd), (long long)(tptr))
+#define __sanitizer_syscall_post___futimes50(res, fd, tptr) \
+ __sanitizer_syscall_post_impl___futimes50(res, (long long)(fd), \
+ (long long)(tptr))
+#define __sanitizer_syscall_pre___lutimes50(path, tptr) \
+ __sanitizer_syscall_pre_impl___lutimes50((long long)(path), (long long)(tptr))
+#define __sanitizer_syscall_post___lutimes50(res, path, tptr) \
+ __sanitizer_syscall_post_impl___lutimes50(res, (long long)(path), \
+ (long long)(tptr))
+#define __sanitizer_syscall_pre___setitimer50(which, itv, oitv) \
+ __sanitizer_syscall_pre_impl___setitimer50( \
+ (long long)(which), (long long)(itv), (long long)(oitv))
+#define __sanitizer_syscall_post___setitimer50(res, which, itv, oitv) \
+ __sanitizer_syscall_post_impl___setitimer50( \
+ res, (long long)(which), (long long)(itv), (long long)(oitv))
+#define __sanitizer_syscall_pre___getitimer50(which, itv) \
+ __sanitizer_syscall_pre_impl___getitimer50((long long)(which), \
+ (long long)(itv))
+#define __sanitizer_syscall_post___getitimer50(res, which, itv) \
+ __sanitizer_syscall_post_impl___getitimer50(res, (long long)(which), \
+ (long long)(itv))
+#define __sanitizer_syscall_pre___clock_gettime50(clock_id, tp) \
+ __sanitizer_syscall_pre_impl___clock_gettime50((long long)(clock_id), \
+ (long long)(tp))
+#define __sanitizer_syscall_post___clock_gettime50(res, clock_id, tp) \
+ __sanitizer_syscall_post_impl___clock_gettime50(res, (long long)(clock_id), \
+ (long long)(tp))
+#define __sanitizer_syscall_pre___clock_settime50(clock_id, tp) \
+ __sanitizer_syscall_pre_impl___clock_settime50((long long)(clock_id), \
+ (long long)(tp))
+#define __sanitizer_syscall_post___clock_settime50(res, clock_id, tp) \
+ __sanitizer_syscall_post_impl___clock_settime50(res, (long long)(clock_id), \
+ (long long)(tp))
+#define __sanitizer_syscall_pre___clock_getres50(clock_id, tp) \
+ __sanitizer_syscall_pre_impl___clock_getres50((long long)(clock_id), \
+ (long long)(tp))
+#define __sanitizer_syscall_post___clock_getres50(res, clock_id, tp) \
+ __sanitizer_syscall_post_impl___clock_getres50(res, (long long)(clock_id), \
+ (long long)(tp))
+#define __sanitizer_syscall_pre___nanosleep50(rqtp, rmtp) \
+ __sanitizer_syscall_pre_impl___nanosleep50((long long)(rqtp), \
+ (long long)(rmtp))
+#define __sanitizer_syscall_post___nanosleep50(res, rqtp, rmtp) \
+ __sanitizer_syscall_post_impl___nanosleep50(res, (long long)(rqtp), \
+ (long long)(rmtp))
+#define __sanitizer_syscall_pre_____sigtimedwait50(set, info, timeout) \
+ __sanitizer_syscall_pre_impl_____sigtimedwait50( \
+ (long long)(set), (long long)(info), (long long)(timeout))
+#define __sanitizer_syscall_post_____sigtimedwait50(res, set, info, timeout) \
+ __sanitizer_syscall_post_impl_____sigtimedwait50( \
+ res, (long long)(set), (long long)(info), (long long)(timeout))
+#define __sanitizer_syscall_pre___mq_timedsend50(mqdes, msg_ptr, msg_len, \
+ msg_prio, abs_timeout) \
+ __sanitizer_syscall_pre_impl___mq_timedsend50( \
+ (long long)(mqdes), (long long)(msg_ptr), (long long)(msg_len), \
+ (long long)(msg_prio), (long long)(abs_timeout))
+#define __sanitizer_syscall_post___mq_timedsend50( \
+ res, mqdes, msg_ptr, msg_len, msg_prio, abs_timeout) \
+ __sanitizer_syscall_post_impl___mq_timedsend50( \
+ res, (long long)(mqdes), (long long)(msg_ptr), (long long)(msg_len), \
+ (long long)(msg_prio), (long long)(abs_timeout))
+#define __sanitizer_syscall_pre___mq_timedreceive50(mqdes, msg_ptr, msg_len, \
+ msg_prio, abs_timeout) \
+ __sanitizer_syscall_pre_impl___mq_timedreceive50( \
+ (long long)(mqdes), (long long)(msg_ptr), (long long)(msg_len), \
+ (long long)(msg_prio), (long long)(abs_timeout))
+#define __sanitizer_syscall_post___mq_timedreceive50( \
+ res, mqdes, msg_ptr, msg_len, msg_prio, abs_timeout) \
+ __sanitizer_syscall_post_impl___mq_timedreceive50( \
+ res, (long long)(mqdes), (long long)(msg_ptr), (long long)(msg_len), \
+ (long long)(msg_prio), (long long)(abs_timeout))
+#define __sanitizer_syscall_pre_compat_60__lwp_park(ts, unpark, hint, \
+ unparkhint) \
+ __sanitizer_syscall_pre_impl_compat_60__lwp_park( \
+ (long long)(ts), (long long)(unpark), (long long)(hint), \
+ (long long)(unparkhint))
+#define __sanitizer_syscall_post_compat_60__lwp_park(res, ts, unpark, hint, \
+ unparkhint) \
+ __sanitizer_syscall_post_impl_compat_60__lwp_park( \
+ res, (long long)(ts), (long long)(unpark), (long long)(hint), \
+ (long long)(unparkhint))
+#define __sanitizer_syscall_pre___kevent50(fd, changelist, nchanges, \
+ eventlist, nevents, timeout) \
+ __sanitizer_syscall_pre_impl___kevent50( \
+ (long long)(fd), (long long)(changelist), (long long)(nchanges), \
+ (long long)(eventlist), (long long)(nevents), (long long)(timeout))
+#define __sanitizer_syscall_post___kevent50(res, fd, changelist, nchanges, \
+ eventlist, nevents, timeout) \
+ __sanitizer_syscall_post_impl___kevent50( \
+ res, (long long)(fd), (long long)(changelist), (long long)(nchanges), \
+ (long long)(eventlist), (long long)(nevents), (long long)(timeout))
+#define __sanitizer_syscall_pre___pselect50(nd, in, ou, ex, ts, mask) \
+ __sanitizer_syscall_pre_impl___pselect50((long long)(nd), (long long)(in), \
+ (long long)(ou), (long long)(ex), \
+ (long long)(ts), (long long)(mask))
+#define __sanitizer_syscall_post___pselect50(res, nd, in, ou, ex, ts, mask) \
+ __sanitizer_syscall_post_impl___pselect50( \
+ res, (long long)(nd), (long long)(in), (long long)(ou), (long long)(ex), \
+ (long long)(ts), (long long)(mask))
+#define __sanitizer_syscall_pre___pollts50(fds, nfds, ts, mask) \
+ __sanitizer_syscall_pre_impl___pollts50((long long)(fds), (long long)(nfds), \
+ (long long)(ts), (long long)(mask))
+#define __sanitizer_syscall_post___pollts50(res, fds, nfds, ts, mask) \
+ __sanitizer_syscall_post_impl___pollts50(res, (long long)(fds), \
+ (long long)(nfds), (long long)(ts), \
+ (long long)(mask))
+#define __sanitizer_syscall_pre___aio_suspend50(list, nent, timeout) \
+ __sanitizer_syscall_pre_impl___aio_suspend50( \
+ (long long)(list), (long long)(nent), (long long)(timeout))
+#define __sanitizer_syscall_post___aio_suspend50(res, list, nent, timeout) \
+ __sanitizer_syscall_post_impl___aio_suspend50( \
+ res, (long long)(list), (long long)(nent), (long long)(timeout))
+#define __sanitizer_syscall_pre___stat50(path, ub) \
+ __sanitizer_syscall_pre_impl___stat50((long long)(path), (long long)(ub))
+#define __sanitizer_syscall_post___stat50(res, path, ub) \
+ __sanitizer_syscall_post_impl___stat50(res, (long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_pre___fstat50(fd, sb) \
+ __sanitizer_syscall_pre_impl___fstat50((long long)(fd), (long long)(sb))
+#define __sanitizer_syscall_post___fstat50(res, fd, sb) \
+ __sanitizer_syscall_post_impl___fstat50(res, (long long)(fd), (long long)(sb))
+#define __sanitizer_syscall_pre___lstat50(path, ub) \
+ __sanitizer_syscall_pre_impl___lstat50((long long)(path), (long long)(ub))
+#define __sanitizer_syscall_post___lstat50(res, path, ub) \
+ __sanitizer_syscall_post_impl___lstat50(res, (long long)(path), \
+ (long long)(ub))
+#define __sanitizer_syscall_pre_____semctl50(semid, semnum, cmd, arg) \
+ __sanitizer_syscall_pre_impl_____semctl50( \
+ (long long)(semid), (long long)(semnum), (long long)(cmd), \
+ (long long)(arg))
+#define __sanitizer_syscall_post_____semctl50(res, semid, semnum, cmd, arg) \
+ __sanitizer_syscall_post_impl_____semctl50( \
+ res, (long long)(semid), (long long)(semnum), (long long)(cmd), \
+ (long long)(arg))
+#define __sanitizer_syscall_pre___shmctl50(shmid, cmd, buf) \
+ __sanitizer_syscall_pre_impl___shmctl50((long long)(shmid), \
+ (long long)(cmd), (long long)(buf))
+#define __sanitizer_syscall_post___shmctl50(res, shmid, cmd, buf) \
+ __sanitizer_syscall_post_impl___shmctl50(res, (long long)(shmid), \
+ (long long)(cmd), (long long)(buf))
+#define __sanitizer_syscall_pre___msgctl50(msqid, cmd, buf) \
+ __sanitizer_syscall_pre_impl___msgctl50((long long)(msqid), \
+ (long long)(cmd), (long long)(buf))
+#define __sanitizer_syscall_post___msgctl50(res, msqid, cmd, buf) \
+ __sanitizer_syscall_post_impl___msgctl50(res, (long long)(msqid), \
+ (long long)(cmd), (long long)(buf))
+#define __sanitizer_syscall_pre___getrusage50(who, rusage) \
+ __sanitizer_syscall_pre_impl___getrusage50((long long)(who), \
+ (long long)(rusage))
+#define __sanitizer_syscall_post___getrusage50(res, who, rusage) \
+ __sanitizer_syscall_post_impl___getrusage50(res, (long long)(who), \
+ (long long)(rusage))
+#define __sanitizer_syscall_pre___timer_settime50(timerid, flags, value, \
+ ovalue) \
+ __sanitizer_syscall_pre_impl___timer_settime50( \
+ (long long)(timerid), (long long)(flags), (long long)(value), \
+ (long long)(ovalue))
+#define __sanitizer_syscall_post___timer_settime50(res, timerid, flags, value, \
+ ovalue) \
+ __sanitizer_syscall_post_impl___timer_settime50( \
+ res, (long long)(timerid), (long long)(flags), (long long)(value), \
+ (long long)(ovalue))
+#define __sanitizer_syscall_pre___timer_gettime50(timerid, value) \
+ __sanitizer_syscall_pre_impl___timer_gettime50((long long)(timerid), \
+ (long long)(value))
+#define __sanitizer_syscall_post___timer_gettime50(res, timerid, value) \
+ __sanitizer_syscall_post_impl___timer_gettime50(res, (long long)(timerid), \
+ (long long)(value))
+#if defined(NTP) || !defined(_KERNEL_OPT)
+#define __sanitizer_syscall_pre___ntp_gettime50(ntvp) \
+ __sanitizer_syscall_pre_impl___ntp_gettime50((long long)(ntvp))
+#define __sanitizer_syscall_post___ntp_gettime50(res, ntvp) \
+ __sanitizer_syscall_post_impl___ntp_gettime50(res, (long long)(ntvp))
+#else
+/* syscall 448 has been skipped */
+#endif
+#define __sanitizer_syscall_pre___wait450(pid, status, options, rusage) \
+ __sanitizer_syscall_pre_impl___wait450( \
+ (long long)(pid), (long long)(status), (long long)(options), \
+ (long long)(rusage))
+#define __sanitizer_syscall_post___wait450(res, pid, status, options, rusage) \
+ __sanitizer_syscall_post_impl___wait450( \
+ res, (long long)(pid), (long long)(status), (long long)(options), \
+ (long long)(rusage))
+#define __sanitizer_syscall_pre___mknod50(path, mode, dev) \
+ __sanitizer_syscall_pre_impl___mknod50((long long)(path), (long long)(mode), \
+ (long long)(dev))
+#define __sanitizer_syscall_post___mknod50(res, path, mode, dev) \
+ __sanitizer_syscall_post_impl___mknod50(res, (long long)(path), \
+ (long long)(mode), (long long)(dev))
+#define __sanitizer_syscall_pre___fhstat50(fhp, fh_size, sb) \
+ __sanitizer_syscall_pre_impl___fhstat50( \
+ (long long)(fhp), (long long)(fh_size), (long long)(sb))
+#define __sanitizer_syscall_post___fhstat50(res, fhp, fh_size, sb) \
+ __sanitizer_syscall_post_impl___fhstat50( \
+ res, (long long)(fhp), (long long)(fh_size), (long long)(sb))
+/* syscall 452 has been skipped */
+#define __sanitizer_syscall_pre_pipe2(fildes, flags) \
+ __sanitizer_syscall_pre_impl_pipe2((long long)(fildes), (long long)(flags))
+#define __sanitizer_syscall_post_pipe2(res, fildes, flags) \
+ __sanitizer_syscall_post_impl_pipe2(res, (long long)(fildes), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_dup3(from, to, flags) \
+ __sanitizer_syscall_pre_impl_dup3((long long)(from), (long long)(to), \
+ (long long)(flags))
+#define __sanitizer_syscall_post_dup3(res, from, to, flags) \
+ __sanitizer_syscall_post_impl_dup3(res, (long long)(from), (long long)(to), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_kqueue1(flags) \
+ __sanitizer_syscall_pre_impl_kqueue1((long long)(flags))
+#define __sanitizer_syscall_post_kqueue1(res, flags) \
+ __sanitizer_syscall_post_impl_kqueue1(res, (long long)(flags))
+#define __sanitizer_syscall_pre_paccept(s, name, anamelen, mask, flags) \
+ __sanitizer_syscall_pre_impl_paccept((long long)(s), (long long)(name), \
+ (long long)(anamelen), \
+ (long long)(mask), (long long)(flags))
+#define __sanitizer_syscall_post_paccept(res, s, name, anamelen, mask, flags) \
+ __sanitizer_syscall_post_impl_paccept( \
+ res, (long long)(s), (long long)(name), (long long)(anamelen), \
+ (long long)(mask), (long long)(flags))
+#define __sanitizer_syscall_pre_linkat(fd1, name1, fd2, name2, flags) \
+ __sanitizer_syscall_pre_impl_linkat((long long)(fd1), (long long)(name1), \
+ (long long)(fd2), (long long)(name2), \
+ (long long)(flags))
+#define __sanitizer_syscall_post_linkat(res, fd1, name1, fd2, name2, flags) \
+ __sanitizer_syscall_post_impl_linkat(res, (long long)(fd1), \
+ (long long)(name1), (long long)(fd2), \
+ (long long)(name2), (long long)(flags))
+#define __sanitizer_syscall_pre_renameat(fromfd, from, tofd, to) \
+ __sanitizer_syscall_pre_impl_renameat((long long)(fromfd), \
+ (long long)(from), (long long)(tofd), \
+ (long long)(to))
+#define __sanitizer_syscall_post_renameat(res, fromfd, from, tofd, to) \
+ __sanitizer_syscall_post_impl_renameat(res, (long long)(fromfd), \
+ (long long)(from), (long long)(tofd), \
+ (long long)(to))
+#define __sanitizer_syscall_pre_mkfifoat(fd, path, mode) \
+ __sanitizer_syscall_pre_impl_mkfifoat((long long)(fd), (long long)(path), \
+ (long long)(mode))
+#define __sanitizer_syscall_post_mkfifoat(res, fd, path, mode) \
+ __sanitizer_syscall_post_impl_mkfifoat(res, (long long)(fd), \
+ (long long)(path), (long long)(mode))
+#define __sanitizer_syscall_pre_mknodat(fd, path, mode, PAD, dev) \
+ __sanitizer_syscall_pre_impl_mknodat((long long)(fd), (long long)(path), \
+ (long long)(mode), (long long)(PAD), \
+ (long long)(dev))
+#define __sanitizer_syscall_post_mknodat(res, fd, path, mode, PAD, dev) \
+ __sanitizer_syscall_post_impl_mknodat(res, (long long)(fd), \
+ (long long)(path), (long long)(mode), \
+ (long long)(PAD), (long long)(dev))
+#define __sanitizer_syscall_pre_mkdirat(fd, path, mode) \
+ __sanitizer_syscall_pre_impl_mkdirat((long long)(fd), (long long)(path), \
+ (long long)(mode))
+#define __sanitizer_syscall_post_mkdirat(res, fd, path, mode) \
+ __sanitizer_syscall_post_impl_mkdirat(res, (long long)(fd), \
+ (long long)(path), (long long)(mode))
+#define __sanitizer_syscall_pre_faccessat(fd, path, amode, flag) \
+ __sanitizer_syscall_pre_impl_faccessat((long long)(fd), (long long)(path), \
+ (long long)(amode), \
+ (long long)(flag))
+#define __sanitizer_syscall_post_faccessat(res, fd, path, amode, flag) \
+ __sanitizer_syscall_post_impl_faccessat( \
+ res, (long long)(fd), (long long)(path), (long long)(amode), \
+ (long long)(flag))
+#define __sanitizer_syscall_pre_fchmodat(fd, path, mode, flag) \
+ __sanitizer_syscall_pre_impl_fchmodat((long long)(fd), (long long)(path), \
+ (long long)(mode), (long long)(flag))
+#define __sanitizer_syscall_post_fchmodat(res, fd, path, mode, flag) \
+ __sanitizer_syscall_post_impl_fchmodat(res, (long long)(fd), \
+ (long long)(path), (long long)(mode), \
+ (long long)(flag))
+#define __sanitizer_syscall_pre_fchownat(fd, path, owner, group, flag) \
+ __sanitizer_syscall_pre_impl_fchownat((long long)(fd), (long long)(path), \
+ (long long)(owner), \
+ (long long)(group), (long long)(flag))
+#define __sanitizer_syscall_post_fchownat(res, fd, path, owner, group, flag) \
+ __sanitizer_syscall_post_impl_fchownat( \
+ res, (long long)(fd), (long long)(path), (long long)(owner), \
+ (long long)(group), (long long)(flag))
+#define __sanitizer_syscall_pre_fexecve(fd, argp, envp) \
+ __sanitizer_syscall_pre_impl_fexecve((long long)(fd), (long long)(argp), \
+ (long long)(envp))
+#define __sanitizer_syscall_post_fexecve(res, fd, argp, envp) \
+ __sanitizer_syscall_post_impl_fexecve(res, (long long)(fd), \
+ (long long)(argp), (long long)(envp))
+#define __sanitizer_syscall_pre_fstatat(fd, path, buf, flag) \
+ __sanitizer_syscall_pre_impl_fstatat((long long)(fd), (long long)(path), \
+ (long long)(buf), (long long)(flag))
+#define __sanitizer_syscall_post_fstatat(res, fd, path, buf, flag) \
+ __sanitizer_syscall_post_impl_fstatat(res, (long long)(fd), \
+ (long long)(path), (long long)(buf), \
+ (long long)(flag))
+#define __sanitizer_syscall_pre_utimensat(fd, path, tptr, flag) \
+ __sanitizer_syscall_pre_impl_utimensat((long long)(fd), (long long)(path), \
+ (long long)(tptr), (long long)(flag))
+#define __sanitizer_syscall_post_utimensat(res, fd, path, tptr, flag) \
+ __sanitizer_syscall_post_impl_utimensat( \
+ res, (long long)(fd), (long long)(path), (long long)(tptr), \
+ (long long)(flag))
+#define __sanitizer_syscall_pre_openat(fd, path, oflags, mode) \
+ __sanitizer_syscall_pre_impl_openat((long long)(fd), (long long)(path), \
+ (long long)(oflags), (long long)(mode))
+#define __sanitizer_syscall_post_openat(res, fd, path, oflags, mode) \
+ __sanitizer_syscall_post_impl_openat(res, (long long)(fd), \
+ (long long)(path), (long long)(oflags), \
+ (long long)(mode))
+#define __sanitizer_syscall_pre_readlinkat(fd, path, buf, bufsize) \
+ __sanitizer_syscall_pre_impl_readlinkat((long long)(fd), (long long)(path), \
+ (long long)(buf), \
+ (long long)(bufsize))
+#define __sanitizer_syscall_post_readlinkat(res, fd, path, buf, bufsize) \
+ __sanitizer_syscall_post_impl_readlinkat( \
+ res, (long long)(fd), (long long)(path), (long long)(buf), \
+ (long long)(bufsize))
+#define __sanitizer_syscall_pre_symlinkat(path1, fd, path2) \
+ __sanitizer_syscall_pre_impl_symlinkat((long long)(path1), (long long)(fd), \
+ (long long)(path2))
+#define __sanitizer_syscall_post_symlinkat(res, path1, fd, path2) \
+ __sanitizer_syscall_post_impl_symlinkat(res, (long long)(path1), \
+ (long long)(fd), (long long)(path2))
+#define __sanitizer_syscall_pre_unlinkat(fd, path, flag) \
+ __sanitizer_syscall_pre_impl_unlinkat((long long)(fd), (long long)(path), \
+ (long long)(flag))
+#define __sanitizer_syscall_post_unlinkat(res, fd, path, flag) \
+ __sanitizer_syscall_post_impl_unlinkat(res, (long long)(fd), \
+ (long long)(path), (long long)(flag))
+#define __sanitizer_syscall_pre_futimens(fd, tptr) \
+ __sanitizer_syscall_pre_impl_futimens((long long)(fd), (long long)(tptr))
+#define __sanitizer_syscall_post_futimens(res, fd, tptr) \
+ __sanitizer_syscall_post_impl_futimens(res, (long long)(fd), \
+ (long long)(tptr))
+#define __sanitizer_syscall_pre___quotactl(path, args) \
+ __sanitizer_syscall_pre_impl___quotactl((long long)(path), (long long)(args))
+#define __sanitizer_syscall_post___quotactl(res, path, args) \
+ __sanitizer_syscall_post_impl___quotactl(res, (long long)(path), \
+ (long long)(args))
+#define __sanitizer_syscall_pre_posix_spawn(pid, path, file_actions, attrp, \
+ argv, envp) \
+ __sanitizer_syscall_pre_impl_posix_spawn( \
+ (long long)(pid), (long long)(path), (long long)(file_actions), \
+ (long long)(attrp), (long long)(argv), (long long)(envp))
+#define __sanitizer_syscall_post_posix_spawn(res, pid, path, file_actions, \
+ attrp, argv, envp) \
+ __sanitizer_syscall_post_impl_posix_spawn( \
+ res, (long long)(pid), (long long)(path), (long long)(file_actions), \
+ (long long)(attrp), (long long)(argv), (long long)(envp))
+#define __sanitizer_syscall_pre_recvmmsg(s, mmsg, vlen, flags, timeout) \
+ __sanitizer_syscall_pre_impl_recvmmsg((long long)(s), (long long)(mmsg), \
+ (long long)(vlen), (long long)(flags), \
+ (long long)(timeout))
+#define __sanitizer_syscall_post_recvmmsg(res, s, mmsg, vlen, flags, timeout) \
+ __sanitizer_syscall_post_impl_recvmmsg( \
+ res, (long long)(s), (long long)(mmsg), (long long)(vlen), \
+ (long long)(flags), (long long)(timeout))
+#define __sanitizer_syscall_pre_sendmmsg(s, mmsg, vlen, flags) \
+ __sanitizer_syscall_pre_impl_sendmmsg((long long)(s), (long long)(mmsg), \
+ (long long)(vlen), (long long)(flags))
+#define __sanitizer_syscall_post_sendmmsg(res, s, mmsg, vlen, flags) \
+ __sanitizer_syscall_post_impl_sendmmsg(res, (long long)(s), \
+ (long long)(mmsg), (long long)(vlen), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre_clock_nanosleep(clock_id, flags, rqtp, rmtp) \
+ __sanitizer_syscall_pre_impl_clock_nanosleep( \
+ (long long)(clock_id), (long long)(flags), (long long)(rqtp), \
+ (long long)(rmtp))
+#define __sanitizer_syscall_post_clock_nanosleep(res, clock_id, flags, rqtp, \
+ rmtp) \
+ __sanitizer_syscall_post_impl_clock_nanosleep( \
+ res, (long long)(clock_id), (long long)(flags), (long long)(rqtp), \
+ (long long)(rmtp))
+#define __sanitizer_syscall_pre____lwp_park60(clock_id, flags, ts, unpark, \
+ hint, unparkhint) \
+ __sanitizer_syscall_pre_impl____lwp_park60( \
+ (long long)(clock_id), (long long)(flags), (long long)(ts), \
+ (long long)(unpark), (long long)(hint), (long long)(unparkhint))
+#define __sanitizer_syscall_post____lwp_park60(res, clock_id, flags, ts, \
+ unpark, hint, unparkhint) \
+ __sanitizer_syscall_post_impl____lwp_park60( \
+ res, (long long)(clock_id), (long long)(flags), (long long)(ts), \
+ (long long)(unpark), (long long)(hint), (long long)(unparkhint))
+#define __sanitizer_syscall_pre_posix_fallocate(fd, PAD, pos, len) \
+ __sanitizer_syscall_pre_impl_posix_fallocate( \
+ (long long)(fd), (long long)(PAD), (long long)(pos), (long long)(len))
+#define __sanitizer_syscall_post_posix_fallocate(res, fd, PAD, pos, len) \
+ __sanitizer_syscall_post_impl_posix_fallocate( \
+ res, (long long)(fd), (long long)(PAD), (long long)(pos), \
+ (long long)(len))
+#define __sanitizer_syscall_pre_fdiscard(fd, PAD, pos, len) \
+ __sanitizer_syscall_pre_impl_fdiscard((long long)(fd), (long long)(PAD), \
+ (long long)(pos), (long long)(len))
+#define __sanitizer_syscall_post_fdiscard(res, fd, PAD, pos, len) \
+ __sanitizer_syscall_post_impl_fdiscard(res, (long long)(fd), \
+ (long long)(PAD), (long long)(pos), \
+ (long long)(len))
+#define __sanitizer_syscall_pre_wait6(idtype, id, status, options, wru, info) \
+ __sanitizer_syscall_pre_impl_wait6( \
+ (long long)(idtype), (long long)(id), (long long)(status), \
+ (long long)(options), (long long)(wru), (long long)(info))
+#define __sanitizer_syscall_post_wait6(res, idtype, id, status, options, wru, \
+ info) \
+ __sanitizer_syscall_post_impl_wait6( \
+ res, (long long)(idtype), (long long)(id), (long long)(status), \
+ (long long)(options), (long long)(wru), (long long)(info))
+#define __sanitizer_syscall_pre_clock_getcpuclockid2(idtype, id, clock_id) \
+ __sanitizer_syscall_pre_impl_clock_getcpuclockid2( \
+ (long long)(idtype), (long long)(id), (long long)(clock_id))
+#define __sanitizer_syscall_post_clock_getcpuclockid2(res, idtype, id, \
+ clock_id) \
+ __sanitizer_syscall_post_impl_clock_getcpuclockid2( \
+ res, (long long)(idtype), (long long)(id), (long long)(clock_id))
+#define __sanitizer_syscall_pre___getvfsstat90(buf, bufsize, flags) \
+ __sanitizer_syscall_pre_impl___getvfsstat90( \
+ (long long)(buf), (long long)(bufsize), (long long)(flags))
+#define __sanitizer_syscall_post___getvfsstat90(res, buf, bufsize, flags) \
+ __sanitizer_syscall_post_impl___getvfsstat90( \
+ res, (long long)(buf), (long long)(bufsize), (long long)(flags))
+#define __sanitizer_syscall_pre___statvfs190(path, buf, flags) \
+ __sanitizer_syscall_pre_impl___statvfs190( \
+ (long long)(path), (long long)(buf), (long long)(flags))
+#define __sanitizer_syscall_post___statvfs190(res, path, buf, flags) \
+ __sanitizer_syscall_post_impl___statvfs190( \
+ res, (long long)(path), (long long)(buf), (long long)(flags))
+#define __sanitizer_syscall_pre___fstatvfs190(fd, buf, flags) \
+ __sanitizer_syscall_pre_impl___fstatvfs190( \
+ (long long)(fd), (long long)(buf), (long long)(flags))
+#define __sanitizer_syscall_post___fstatvfs190(res, fd, buf, flags) \
+ __sanitizer_syscall_post_impl___fstatvfs190( \
+ res, (long long)(fd), (long long)(buf), (long long)(flags))
+#define __sanitizer_syscall_pre___fhstatvfs190(fhp, fh_size, buf, flags) \
+ __sanitizer_syscall_pre_impl___fhstatvfs190( \
+ (long long)(fhp), (long long)(fh_size), (long long)(buf), \
+ (long long)(flags))
+#define __sanitizer_syscall_post___fhstatvfs190(res, fhp, fh_size, buf, flags) \
+ __sanitizer_syscall_post_impl___fhstatvfs190( \
+ res, (long long)(fhp), (long long)(fh_size), (long long)(buf), \
+ (long long)(flags))
+#define __sanitizer_syscall_pre___acl_get_link(path, type, aclp) \
+ __sanitizer_syscall_pre_impl___acl_get_link( \
+ (long long)(path), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_post___acl_get_link(res, path, type, aclp) \
+ __sanitizer_syscall_post_impl___acl_get_link( \
+ res, (long long)(path), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_pre___acl_set_link(path, type, aclp) \
+ __sanitizer_syscall_pre_impl___acl_set_link( \
+ (long long)(path), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_post___acl_set_link(res, path, type, aclp) \
+ __sanitizer_syscall_post_impl___acl_set_link( \
+ res, (long long)(path), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_pre___acl_delete_link(path, type) \
+ __sanitizer_syscall_pre_impl___acl_delete_link((long long)(path), \
+ (long long)(type))
+#define __sanitizer_syscall_post___acl_delete_link(res, path, type) \
+ __sanitizer_syscall_post_impl___acl_delete_link(res, (long long)(path), \
+ (long long)(type))
+#define __sanitizer_syscall_pre___acl_aclcheck_link(path, type, aclp) \
+ __sanitizer_syscall_pre_impl___acl_aclcheck_link( \
+ (long long)(path), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_post___acl_aclcheck_link(res, path, type, aclp) \
+ __sanitizer_syscall_post_impl___acl_aclcheck_link( \
+ res, (long long)(path), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_pre___acl_get_file(path, type, aclp) \
+ __sanitizer_syscall_pre_impl___acl_get_file( \
+ (long long)(path), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_post___acl_get_file(res, path, type, aclp) \
+ __sanitizer_syscall_post_impl___acl_get_file( \
+ res, (long long)(path), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_pre___acl_set_file(path, type, aclp) \
+ __sanitizer_syscall_pre_impl___acl_set_file( \
+ (long long)(path), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_post___acl_set_file(res, path, type, aclp) \
+ __sanitizer_syscall_post_impl___acl_set_file( \
+ res, (long long)(path), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_pre___acl_get_fd(filedes, type, aclp) \
+ __sanitizer_syscall_pre_impl___acl_get_fd( \
+ (long long)(filedes), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_post___acl_get_fd(res, filedes, type, aclp) \
+ __sanitizer_syscall_post_impl___acl_get_fd( \
+ res, (long long)(filedes), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_pre___acl_set_fd(filedes, type, aclp) \
+ __sanitizer_syscall_pre_impl___acl_set_fd( \
+ (long long)(filedes), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_post___acl_set_fd(res, filedes, type, aclp) \
+ __sanitizer_syscall_post_impl___acl_set_fd( \
+ res, (long long)(filedes), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_pre___acl_delete_file(path, type) \
+ __sanitizer_syscall_pre_impl___acl_delete_file((long long)(path), \
+ (long long)(type))
+#define __sanitizer_syscall_post___acl_delete_file(res, path, type) \
+ __sanitizer_syscall_post_impl___acl_delete_file(res, (long long)(path), \
+ (long long)(type))
+#define __sanitizer_syscall_pre___acl_delete_fd(filedes, type) \
+ __sanitizer_syscall_pre_impl___acl_delete_fd((long long)(filedes), \
+ (long long)(type))
+#define __sanitizer_syscall_post___acl_delete_fd(res, filedes, type) \
+ __sanitizer_syscall_post_impl___acl_delete_fd(res, (long long)(filedes), \
+ (long long)(type))
+#define __sanitizer_syscall_pre___acl_aclcheck_file(path, type, aclp) \
+ __sanitizer_syscall_pre_impl___acl_aclcheck_file( \
+ (long long)(path), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_post___acl_aclcheck_file(res, path, type, aclp) \
+ __sanitizer_syscall_post_impl___acl_aclcheck_file( \
+ res, (long long)(path), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_pre___acl_aclcheck_fd(filedes, type, aclp) \
+ __sanitizer_syscall_pre_impl___acl_aclcheck_fd( \
+ (long long)(filedes), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_post___acl_aclcheck_fd(res, filedes, type, aclp) \
+ __sanitizer_syscall_post_impl___acl_aclcheck_fd( \
+ res, (long long)(filedes), (long long)(type), (long long)(aclp))
+#define __sanitizer_syscall_pre_lpathconf(path, name) \
+ __sanitizer_syscall_pre_impl_lpathconf((long long)(path), (long long)(name))
+#define __sanitizer_syscall_post_lpathconf(res, path, name) \
+ __sanitizer_syscall_post_impl_lpathconf(res, (long long)(path), \
+ (long long)(name))
+
+/* Compat with older releases */
+#define __sanitizer_syscall_pre_getvfsstat \
+ __sanitizer_syscall_pre_compat_90_getvfsstat
+#define __sanitizer_syscall_post_getvfsstat \
+ __sanitizer_syscall_post_compat_90_getvfsstat
+
+#define __sanitizer_syscall_pre_statvfs1 \
+ __sanitizer_syscall_pre_compat_90_statvfs1
+#define __sanitizer_syscall_post_statvfs1 \
+ __sanitizer_syscall_post_compat_90_statvfs1
+
+#define __sanitizer_syscall_pre_fstatvfs1 \
+ __sanitizer_syscall_pre_compat_90_fstatvfs1
+#define __sanitizer_syscall_post_fstatvfs1 \
+ __sanitizer_syscall_post_compat_90_fstatvfs1
+
+#define __sanitizer_syscall_pre___fhstatvfs140 \
+ __sanitizer_syscall_pre_compat_90_fhstatvfs1
+#define __sanitizer_syscall_post___fhstatvfs140 \
+ __sanitizer_syscall_post_compat_90_fhstatvfs1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Private declarations. Do not call directly from user code. Use macros above.
+
+// DO NOT EDIT! THIS FILE HAS BEEN GENERATED!
+
+void __sanitizer_syscall_pre_impl_syscall(long long code, long long arg0,
+ long long arg1, long long arg2,
+ long long arg3, long long arg4,
+ long long arg5, long long arg6,
+ long long arg7);
+void __sanitizer_syscall_post_impl_syscall(long long res, long long code,
+ long long arg0, long long arg1,
+ long long arg2, long long arg3,
+ long long arg4, long long arg5,
+ long long arg6, long long arg7);
+void __sanitizer_syscall_pre_impl_exit(long long rval);
+void __sanitizer_syscall_post_impl_exit(long long res, long long rval);
+void __sanitizer_syscall_pre_impl_fork(void);
+void __sanitizer_syscall_post_impl_fork(long long res);
+void __sanitizer_syscall_pre_impl_read(long long fd, long long buf,
+ long long nbyte);
+void __sanitizer_syscall_post_impl_read(long long res, long long fd,
+ long long buf, long long nbyte);
+void __sanitizer_syscall_pre_impl_write(long long fd, long long buf,
+ long long nbyte);
+void __sanitizer_syscall_post_impl_write(long long res, long long fd,
+ long long buf, long long nbyte);
+void __sanitizer_syscall_pre_impl_open(long long path, long long flags,
+ long long mode);
+void __sanitizer_syscall_post_impl_open(long long res, long long path,
+ long long flags, long long mode);
+void __sanitizer_syscall_pre_impl_close(long long fd);
+void __sanitizer_syscall_post_impl_close(long long res, long long fd);
+void __sanitizer_syscall_pre_impl_compat_50_wait4(long long pid,
+ long long status,
+ long long options,
+ long long rusage);
+void __sanitizer_syscall_post_impl_compat_50_wait4(long long res, long long pid,
+ long long status,
+ long long options,
+ long long rusage);
+void __sanitizer_syscall_pre_impl_compat_43_ocreat(long long path,
+ long long mode);
+void __sanitizer_syscall_post_impl_compat_43_ocreat(long long res,
+ long long path,
+ long long mode);
+void __sanitizer_syscall_pre_impl_link(long long path, long long link);
+void __sanitizer_syscall_post_impl_link(long long res, long long path,
+ long long link);
+void __sanitizer_syscall_pre_impl_unlink(long long path);
+void __sanitizer_syscall_post_impl_unlink(long long res, long long path);
+/* syscall 11 has been skipped */
+void __sanitizer_syscall_pre_impl_chdir(long long path);
+void __sanitizer_syscall_post_impl_chdir(long long res, long long path);
+void __sanitizer_syscall_pre_impl_fchdir(long long fd);
+void __sanitizer_syscall_post_impl_fchdir(long long res, long long fd);
+void __sanitizer_syscall_pre_impl_compat_50_mknod(long long path,
+ long long mode,
+ long long dev);
+void __sanitizer_syscall_post_impl_compat_50_mknod(long long res,
+ long long path,
+ long long mode,
+ long long dev);
+void __sanitizer_syscall_pre_impl_chmod(long long path, long long mode);
+void __sanitizer_syscall_post_impl_chmod(long long res, long long path,
+ long long mode);
+void __sanitizer_syscall_pre_impl_chown(long long path, long long uid,
+ long long gid);
+void __sanitizer_syscall_post_impl_chown(long long res, long long path,
+ long long uid, long long gid);
+void __sanitizer_syscall_pre_impl_break(long long nsize);
+void __sanitizer_syscall_post_impl_break(long long res, long long nsize);
+void __sanitizer_syscall_pre_impl_compat_20_getfsstat(long long buf,
+ long long bufsize,
+ long long flags);
+void __sanitizer_syscall_post_impl_compat_20_getfsstat(long long res,
+ long long buf,
+ long long bufsize,
+ long long flags);
+void __sanitizer_syscall_pre_impl_compat_43_olseek(long long fd,
+ long long offset,
+ long long whence);
+void __sanitizer_syscall_post_impl_compat_43_olseek(long long res, long long fd,
+ long long offset,
+ long long whence);
+void __sanitizer_syscall_pre_impl_getpid(void);
+void __sanitizer_syscall_post_impl_getpid(long long res);
+void __sanitizer_syscall_pre_impl_compat_40_mount(long long type,
+ long long path,
+ long long flags,
+ long long data);
+void __sanitizer_syscall_post_impl_compat_40_mount(long long res,
+ long long type,
+ long long path,
+ long long flags,
+ long long data);
+void __sanitizer_syscall_pre_impl_unmount(long long path, long long flags);
+void __sanitizer_syscall_post_impl_unmount(long long res, long long path,
+ long long flags);
+void __sanitizer_syscall_pre_impl_setuid(long long uid);
+void __sanitizer_syscall_post_impl_setuid(long long res, long long uid);
+void __sanitizer_syscall_pre_impl_getuid(void);
+void __sanitizer_syscall_post_impl_getuid(long long res);
+void __sanitizer_syscall_pre_impl_geteuid(void);
+void __sanitizer_syscall_post_impl_geteuid(long long res);
+void __sanitizer_syscall_pre_impl_ptrace(long long req, long long pid,
+ long long addr, long long data);
+void __sanitizer_syscall_post_impl_ptrace(long long res, long long req,
+ long long pid, long long addr,
+ long long data);
+void __sanitizer_syscall_pre_impl_recvmsg(long long s, long long msg,
+ long long flags);
+void __sanitizer_syscall_post_impl_recvmsg(long long res, long long s,
+ long long msg, long long flags);
+void __sanitizer_syscall_pre_impl_sendmsg(long long s, long long msg,
+ long long flags);
+void __sanitizer_syscall_post_impl_sendmsg(long long res, long long s,
+ long long msg, long long flags);
+void __sanitizer_syscall_pre_impl_recvfrom(long long s, long long buf,
+ long long len, long long flags,
+ long long from,
+ long long fromlenaddr);
+void __sanitizer_syscall_post_impl_recvfrom(long long res, long long s,
+ long long buf, long long len,
+ long long flags, long long from,
+ long long fromlenaddr);
+void __sanitizer_syscall_pre_impl_accept(long long s, long long name,
+ long long anamelen);
+void __sanitizer_syscall_post_impl_accept(long long res, long long s,
+ long long name, long long anamelen);
+void __sanitizer_syscall_pre_impl_getpeername(long long fdes, long long asa,
+ long long alen);
+void __sanitizer_syscall_post_impl_getpeername(long long res, long long fdes,
+ long long asa, long long alen);
+void __sanitizer_syscall_pre_impl_getsockname(long long fdes, long long asa,
+ long long alen);
+void __sanitizer_syscall_post_impl_getsockname(long long res, long long fdes,
+ long long asa, long long alen);
+void __sanitizer_syscall_pre_impl_access(long long path, long long flags);
+void __sanitizer_syscall_post_impl_access(long long res, long long path,
+ long long flags);
+void __sanitizer_syscall_pre_impl_chflags(long long path, long long flags);
+void __sanitizer_syscall_post_impl_chflags(long long res, long long path,
+ long long flags);
+void __sanitizer_syscall_pre_impl_fchflags(long long fd, long long flags);
+void __sanitizer_syscall_post_impl_fchflags(long long res, long long fd,
+ long long flags);
+void __sanitizer_syscall_pre_impl_sync(void);
+void __sanitizer_syscall_post_impl_sync(long long res);
+void __sanitizer_syscall_pre_impl_kill(long long pid, long long signum);
+void __sanitizer_syscall_post_impl_kill(long long res, long long pid,
+ long long signum);
+void __sanitizer_syscall_pre_impl_compat_43_stat43(long long path,
+ long long ub);
+void __sanitizer_syscall_post_impl_compat_43_stat43(long long res,
+ long long path,
+ long long ub);
+void __sanitizer_syscall_pre_impl_getppid(void);
+void __sanitizer_syscall_post_impl_getppid(long long res);
+void __sanitizer_syscall_pre_impl_compat_43_lstat43(long long path,
+ long long ub);
+void __sanitizer_syscall_post_impl_compat_43_lstat43(long long res,
+ long long path,
+ long long ub);
+void __sanitizer_syscall_pre_impl_dup(long long fd);
+void __sanitizer_syscall_post_impl_dup(long long res, long long fd);
+void __sanitizer_syscall_pre_impl_pipe(void);
+void __sanitizer_syscall_post_impl_pipe(long long res);
+void __sanitizer_syscall_pre_impl_getegid(void);
+void __sanitizer_syscall_post_impl_getegid(long long res);
+void __sanitizer_syscall_pre_impl_profil(long long samples, long long size,
+ long long offset, long long scale);
+void __sanitizer_syscall_post_impl_profil(long long res, long long samples,
+ long long size, long long offset,
+ long long scale);
+void __sanitizer_syscall_pre_impl_ktrace(long long fname, long long ops,
+ long long facs, long long pid);
+void __sanitizer_syscall_post_impl_ktrace(long long res, long long fname,
+ long long ops, long long facs,
+ long long pid);
+void __sanitizer_syscall_pre_impl_compat_13_sigaction13(long long signum,
+ long long nsa,
+ long long osa);
+void __sanitizer_syscall_post_impl_compat_13_sigaction13(long long res,
+ long long signum,
+ long long nsa,
+ long long osa);
+void __sanitizer_syscall_pre_impl_getgid(void);
+void __sanitizer_syscall_post_impl_getgid(long long res);
+void __sanitizer_syscall_pre_impl_compat_13_sigprocmask13(long long how,
+ long long mask);
+void __sanitizer_syscall_post_impl_compat_13_sigprocmask13(long long res,
+ long long how,
+ long long mask);
+void __sanitizer_syscall_pre_impl___getlogin(long long namebuf,
+ long long namelen);
+void __sanitizer_syscall_post_impl___getlogin(long long res, long long namebuf,
+ long long namelen);
+void __sanitizer_syscall_pre_impl___setlogin(long long namebuf);
+void __sanitizer_syscall_post_impl___setlogin(long long res, long long namebuf);
+void __sanitizer_syscall_pre_impl_acct(long long path);
+void __sanitizer_syscall_post_impl_acct(long long res, long long path);
+void __sanitizer_syscall_pre_impl_compat_13_sigpending13(void);
+void __sanitizer_syscall_post_impl_compat_13_sigpending13(long long res);
+void __sanitizer_syscall_pre_impl_compat_13_sigaltstack13(long long nss,
+ long long oss);
+void __sanitizer_syscall_post_impl_compat_13_sigaltstack13(long long res,
+ long long nss,
+ long long oss);
+void __sanitizer_syscall_pre_impl_ioctl(long long fd, long long com,
+ long long data);
+void __sanitizer_syscall_post_impl_ioctl(long long res, long long fd,
+ long long com, long long data);
+void __sanitizer_syscall_pre_impl_compat_12_oreboot(long long opt);
+void __sanitizer_syscall_post_impl_compat_12_oreboot(long long res,
+ long long opt);
+void __sanitizer_syscall_pre_impl_revoke(long long path);
+void __sanitizer_syscall_post_impl_revoke(long long res, long long path);
+void __sanitizer_syscall_pre_impl_symlink(long long path, long long link);
+void __sanitizer_syscall_post_impl_symlink(long long res, long long path,
+ long long link);
+void __sanitizer_syscall_pre_impl_readlink(long long path, long long buf,
+ long long count);
+void __sanitizer_syscall_post_impl_readlink(long long res, long long path,
+ long long buf, long long count);
+void __sanitizer_syscall_pre_impl_execve(long long path, long long argp,
+ long long envp);
+void __sanitizer_syscall_post_impl_execve(long long res, long long path,
+ long long argp, long long envp);
+void __sanitizer_syscall_pre_impl_umask(long long newmask);
+void __sanitizer_syscall_post_impl_umask(long long res, long long newmask);
+void __sanitizer_syscall_pre_impl_chroot(long long path);
+void __sanitizer_syscall_post_impl_chroot(long long res, long long path);
+void __sanitizer_syscall_pre_impl_compat_43_fstat43(long long fd, long long sb);
+void __sanitizer_syscall_post_impl_compat_43_fstat43(long long res,
+ long long fd,
+ long long sb);
+void __sanitizer_syscall_pre_impl_compat_43_ogetkerninfo(long long op,
+ long long where,
+ long long size,
+ long long arg);
+void __sanitizer_syscall_post_impl_compat_43_ogetkerninfo(long long res,
+ long long op,
+ long long where,
+ long long size,
+ long long arg);
+void __sanitizer_syscall_pre_impl_compat_43_ogetpagesize(void);
+void __sanitizer_syscall_post_impl_compat_43_ogetpagesize(long long res);
+void __sanitizer_syscall_pre_impl_compat_12_msync(long long addr,
+ long long len);
+void __sanitizer_syscall_post_impl_compat_12_msync(long long res,
+ long long addr,
+ long long len);
+void __sanitizer_syscall_pre_impl_vfork(void);
+void __sanitizer_syscall_post_impl_vfork(long long res);
+/* syscall 67 has been skipped */
+/* syscall 68 has been skipped */
+/* syscall 69 has been skipped */
+/* syscall 70 has been skipped */
+void __sanitizer_syscall_pre_impl_compat_43_ommap(long long addr, long long len,
+ long long prot,
+ long long flags, long long fd,
+ long long pos);
+void __sanitizer_syscall_post_impl_compat_43_ommap(
+ long long res, long long addr, long long len, long long prot,
+ long long flags, long long fd, long long pos);
+void __sanitizer_syscall_pre_impl_vadvise(long long anom);
+void __sanitizer_syscall_post_impl_vadvise(long long res, long long anom);
+void __sanitizer_syscall_pre_impl_munmap(long long addr, long long len);
+void __sanitizer_syscall_post_impl_munmap(long long res, long long addr,
+ long long len);
+void __sanitizer_syscall_pre_impl_mprotect(long long addr, long long len,
+ long long prot);
+void __sanitizer_syscall_post_impl_mprotect(long long res, long long addr,
+ long long len, long long prot);
+void __sanitizer_syscall_pre_impl_madvise(long long addr, long long len,
+ long long behav);
+void __sanitizer_syscall_post_impl_madvise(long long res, long long addr,
+ long long len, long long behav);
+/* syscall 76 has been skipped */
+/* syscall 77 has been skipped */
+void __sanitizer_syscall_pre_impl_mincore(long long addr, long long len,
+ long long vec);
+void __sanitizer_syscall_post_impl_mincore(long long res, long long addr,
+ long long len, long long vec);
+void __sanitizer_syscall_pre_impl_getgroups(long long gidsetsize,
+ long long gidset);
+void __sanitizer_syscall_post_impl_getgroups(long long res,
+ long long gidsetsize,
+ long long gidset);
+void __sanitizer_syscall_pre_impl_setgroups(long long gidsetsize,
+ long long gidset);
+void __sanitizer_syscall_post_impl_setgroups(long long res,
+ long long gidsetsize,
+ long long gidset);
+void __sanitizer_syscall_pre_impl_getpgrp(void);
+void __sanitizer_syscall_post_impl_getpgrp(long long res);
+void __sanitizer_syscall_pre_impl_setpgid(long long pid, long long pgid);
+void __sanitizer_syscall_post_impl_setpgid(long long res, long long pid,
+ long long pgid);
+void __sanitizer_syscall_pre_impl_compat_50_setitimer(long long which,
+ long long itv,
+ long long oitv);
+void __sanitizer_syscall_post_impl_compat_50_setitimer(long long res,
+ long long which,
+ long long itv,
+ long long oitv);
+void __sanitizer_syscall_pre_impl_compat_43_owait(void);
+void __sanitizer_syscall_post_impl_compat_43_owait(long long res);
+void __sanitizer_syscall_pre_impl_compat_12_oswapon(long long name);
+void __sanitizer_syscall_post_impl_compat_12_oswapon(long long res,
+ long long name);
+void __sanitizer_syscall_pre_impl_compat_50_getitimer(long long which,
+ long long itv);
+void __sanitizer_syscall_post_impl_compat_50_getitimer(long long res,
+ long long which,
+ long long itv);
+void __sanitizer_syscall_pre_impl_compat_43_ogethostname(long long hostname,
+ long long len);
+void __sanitizer_syscall_post_impl_compat_43_ogethostname(long long res,
+ long long hostname,
+ long long len);
+void __sanitizer_syscall_pre_impl_compat_43_osethostname(long long hostname,
+ long long len);
+void __sanitizer_syscall_post_impl_compat_43_osethostname(long long res,
+ long long hostname,
+ long long len);
+void __sanitizer_syscall_pre_impl_compat_43_ogetdtablesize(void);
+void __sanitizer_syscall_post_impl_compat_43_ogetdtablesize(long long res);
+void __sanitizer_syscall_pre_impl_dup2(long long from, long long to);
+void __sanitizer_syscall_post_impl_dup2(long long res, long long from,
+ long long to);
+void __sanitizer_syscall_pre_impl_getrandom(long long buf, long long buflen,
+ long long flags);
+void __sanitizer_syscall_post_impl_getrandom(long long res, long long buf,
+ long long buflen, long long flags);
+void __sanitizer_syscall_pre_impl_fcntl(long long fd, long long cmd,
+ long long arg);
+void __sanitizer_syscall_post_impl_fcntl(long long res, long long fd,
+ long long cmd, long long arg);
+void __sanitizer_syscall_pre_impl_compat_50_select(long long nd, long long in,
+ long long ou, long long ex,
+ long long tv);
+void __sanitizer_syscall_post_impl_compat_50_select(long long res, long long nd,
+ long long in, long long ou,
+ long long ex, long long tv);
+/* syscall 94 has been skipped */
+void __sanitizer_syscall_pre_impl_fsync(long long fd);
+void __sanitizer_syscall_post_impl_fsync(long long res, long long fd);
+void __sanitizer_syscall_pre_impl_setpriority(long long which, long long who,
+ long long prio);
+void __sanitizer_syscall_post_impl_setpriority(long long res, long long which,
+ long long who, long long prio);
+void __sanitizer_syscall_pre_impl_compat_30_socket(long long domain,
+ long long type,
+ long long protocol);
+void __sanitizer_syscall_post_impl_compat_30_socket(long long res,
+ long long domain,
+ long long type,
+ long long protocol);
+void __sanitizer_syscall_pre_impl_connect(long long s, long long name,
+ long long namelen);
+void __sanitizer_syscall_post_impl_connect(long long res, long long s,
+ long long name, long long namelen);
+void __sanitizer_syscall_pre_impl_compat_43_oaccept(long long s, long long name,
+ long long anamelen);
+void __sanitizer_syscall_post_impl_compat_43_oaccept(long long res, long long s,
+ long long name,
+ long long anamelen);
+void __sanitizer_syscall_pre_impl_getpriority(long long which, long long who);
+void __sanitizer_syscall_post_impl_getpriority(long long res, long long which,
+ long long who);
+void __sanitizer_syscall_pre_impl_compat_43_osend(long long s, long long buf,
+ long long len,
+ long long flags);
+void __sanitizer_syscall_post_impl_compat_43_osend(long long res, long long s,
+ long long buf, long long len,
+ long long flags);
+void __sanitizer_syscall_pre_impl_compat_43_orecv(long long s, long long buf,
+ long long len,
+ long long flags);
+void __sanitizer_syscall_post_impl_compat_43_orecv(long long res, long long s,
+ long long buf, long long len,
+ long long flags);
+void __sanitizer_syscall_pre_impl_compat_13_sigreturn13(long long sigcntxp);
+void __sanitizer_syscall_post_impl_compat_13_sigreturn13(long long res,
+ long long sigcntxp);
+void __sanitizer_syscall_pre_impl_bind(long long s, long long name,
+ long long namelen);
+void __sanitizer_syscall_post_impl_bind(long long res, long long s,
+ long long name, long long namelen);
+void __sanitizer_syscall_pre_impl_setsockopt(long long s, long long level,
+ long long name, long long val,
+ long long valsize);
+void __sanitizer_syscall_post_impl_setsockopt(long long res, long long s,
+ long long level, long long name,
+ long long val, long long valsize);
+void __sanitizer_syscall_pre_impl_listen(long long s, long long backlog);
+void __sanitizer_syscall_post_impl_listen(long long res, long long s,
+ long long backlog);
+/* syscall 107 has been skipped */
+void __sanitizer_syscall_pre_impl_compat_43_osigvec(long long signum,
+ long long nsv,
+ long long osv);
+void __sanitizer_syscall_post_impl_compat_43_osigvec(long long res,
+ long long signum,
+ long long nsv,
+ long long osv);
+void __sanitizer_syscall_pre_impl_compat_43_osigblock(long long mask);
+void __sanitizer_syscall_post_impl_compat_43_osigblock(long long res,
+ long long mask);
+void __sanitizer_syscall_pre_impl_compat_43_osigsetmask(long long mask);
+void __sanitizer_syscall_post_impl_compat_43_osigsetmask(long long res,
+ long long mask);
+void __sanitizer_syscall_pre_impl_compat_13_sigsuspend13(long long mask);
+void __sanitizer_syscall_post_impl_compat_13_sigsuspend13(long long res,
+ long long mask);
+void __sanitizer_syscall_pre_impl_compat_43_osigstack(long long nss,
+ long long oss);
+void __sanitizer_syscall_post_impl_compat_43_osigstack(long long res,
+ long long nss,
+ long long oss);
+void __sanitizer_syscall_pre_impl_compat_43_orecvmsg(long long s, long long msg,
+ long long flags);
+void __sanitizer_syscall_post_impl_compat_43_orecvmsg(long long res,
+ long long s,
+ long long msg,
+ long long flags);
+void __sanitizer_syscall_pre_impl_compat_43_osendmsg(long long s, long long msg,
+ long long flags);
+void __sanitizer_syscall_post_impl_compat_43_osendmsg(long long res,
+ long long s,
+ long long msg,
+ long long flags);
+/* syscall 115 has been skipped */
+void __sanitizer_syscall_pre_impl_compat_50_gettimeofday(long long tp,
+ long long tzp);
+void __sanitizer_syscall_post_impl_compat_50_gettimeofday(long long res,
+ long long tp,
+ long long tzp);
+void __sanitizer_syscall_pre_impl_compat_50_getrusage(long long who,
+ long long rusage);
+void __sanitizer_syscall_post_impl_compat_50_getrusage(long long res,
+ long long who,
+ long long rusage);
+void __sanitizer_syscall_pre_impl_getsockopt(long long s, long long level,
+ long long name, long long val,
+ long long avalsize);
+void __sanitizer_syscall_post_impl_getsockopt(long long res, long long s,
+ long long level, long long name,
+ long long val,
+ long long avalsize);
+/* syscall 119 has been skipped */
+void __sanitizer_syscall_pre_impl_readv(long long fd, long long iovp,
+ long long iovcnt);
+void __sanitizer_syscall_post_impl_readv(long long res, long long fd,
+ long long iovp, long long iovcnt);
+void __sanitizer_syscall_pre_impl_writev(long long fd, long long iovp,
+ long long iovcnt);
+void __sanitizer_syscall_post_impl_writev(long long res, long long fd,
+ long long iovp, long long iovcnt);
+void __sanitizer_syscall_pre_impl_compat_50_settimeofday(long long tv,
+ long long tzp);
+void __sanitizer_syscall_post_impl_compat_50_settimeofday(long long res,
+ long long tv,
+ long long tzp);
+void __sanitizer_syscall_pre_impl_fchown(long long fd, long long uid,
+ long long gid);
+void __sanitizer_syscall_post_impl_fchown(long long res, long long fd,
+ long long uid, long long gid);
+void __sanitizer_syscall_pre_impl_fchmod(long long fd, long long mode);
+void __sanitizer_syscall_post_impl_fchmod(long long res, long long fd,
+ long long mode);
+void __sanitizer_syscall_pre_impl_compat_43_orecvfrom(
+ long long s, long long buf, long long len, long long flags, long long from,
+ long long fromlenaddr);
+void __sanitizer_syscall_post_impl_compat_43_orecvfrom(
+ long long res, long long s, long long buf, long long len, long long flags,
+ long long from, long long fromlenaddr);
+void __sanitizer_syscall_pre_impl_setreuid(long long ruid, long long euid);
+void __sanitizer_syscall_post_impl_setreuid(long long res, long long ruid,
+ long long euid);
+void __sanitizer_syscall_pre_impl_setregid(long long rgid, long long egid);
+void __sanitizer_syscall_post_impl_setregid(long long res, long long rgid,
+ long long egid);
+void __sanitizer_syscall_pre_impl_rename(long long from, long long to);
+void __sanitizer_syscall_post_impl_rename(long long res, long long from,
+ long long to);
+void __sanitizer_syscall_pre_impl_compat_43_otruncate(long long path,
+ long long length);
+void __sanitizer_syscall_post_impl_compat_43_otruncate(long long res,
+ long long path,
+ long long length);
+void __sanitizer_syscall_pre_impl_compat_43_oftruncate(long long fd,
+ long long length);
+void __sanitizer_syscall_post_impl_compat_43_oftruncate(long long res,
+ long long fd,
+ long long length);
+void __sanitizer_syscall_pre_impl_flock(long long fd, long long how);
+void __sanitizer_syscall_post_impl_flock(long long res, long long fd,
+ long long how);
+void __sanitizer_syscall_pre_impl_mkfifo(long long path, long long mode);
+void __sanitizer_syscall_post_impl_mkfifo(long long res, long long path,
+ long long mode);
+void __sanitizer_syscall_pre_impl_sendto(long long s, long long buf,
+ long long len, long long flags,
+ long long to, long long tolen);
+void __sanitizer_syscall_post_impl_sendto(long long res, long long s,
+ long long buf, long long len,
+ long long flags, long long to,
+ long long tolen);
+void __sanitizer_syscall_pre_impl_shutdown(long long s, long long how);
+void __sanitizer_syscall_post_impl_shutdown(long long res, long long s,
+ long long how);
+void __sanitizer_syscall_pre_impl_socketpair(long long domain, long long type,
+ long long protocol, long long rsv);
+void __sanitizer_syscall_post_impl_socketpair(long long res, long long domain,
+ long long type,
+ long long protocol,
+ long long rsv);
+void __sanitizer_syscall_pre_impl_mkdir(long long path, long long mode);
+void __sanitizer_syscall_post_impl_mkdir(long long res, long long path,
+ long long mode);
+void __sanitizer_syscall_pre_impl_rmdir(long long path);
+void __sanitizer_syscall_post_impl_rmdir(long long res, long long path);
+void __sanitizer_syscall_pre_impl_compat_50_utimes(long long path,
+ long long tptr);
+void __sanitizer_syscall_post_impl_compat_50_utimes(long long res,
+ long long path,
+ long long tptr);
+/* syscall 139 has been skipped */
+void __sanitizer_syscall_pre_impl_compat_50_adjtime(long long delta,
+ long long olddelta);
+void __sanitizer_syscall_post_impl_compat_50_adjtime(long long res,
+ long long delta,
+ long long olddelta);
+void __sanitizer_syscall_pre_impl_compat_43_ogetpeername(long long fdes,
+ long long asa,
+ long long alen);
+void __sanitizer_syscall_post_impl_compat_43_ogetpeername(long long res,
+ long long fdes,
+ long long asa,
+ long long alen);
+void __sanitizer_syscall_pre_impl_compat_43_ogethostid(void);
+void __sanitizer_syscall_post_impl_compat_43_ogethostid(long long res);
+void __sanitizer_syscall_pre_impl_compat_43_osethostid(long long hostid);
+void __sanitizer_syscall_post_impl_compat_43_osethostid(long long res,
+ long long hostid);
+void __sanitizer_syscall_pre_impl_compat_43_ogetrlimit(long long which,
+ long long rlp);
+void __sanitizer_syscall_post_impl_compat_43_ogetrlimit(long long res,
+ long long which,
+ long long rlp);
+void __sanitizer_syscall_pre_impl_compat_43_osetrlimit(long long which,
+ long long rlp);
+void __sanitizer_syscall_post_impl_compat_43_osetrlimit(long long res,
+ long long which,
+ long long rlp);
+void __sanitizer_syscall_pre_impl_compat_43_okillpg(long long pgid,
+ long long signum);
+void __sanitizer_syscall_post_impl_compat_43_okillpg(long long res,
+ long long pgid,
+ long long signum);
+void __sanitizer_syscall_pre_impl_setsid(void);
+void __sanitizer_syscall_post_impl_setsid(long long res);
+void __sanitizer_syscall_pre_impl_compat_50_quotactl(long long path,
+ long long cmd,
+ long long uid,
+ long long arg);
+void __sanitizer_syscall_post_impl_compat_50_quotactl(
+ long long res, long long path, long long cmd, long long uid, long long arg);
+void __sanitizer_syscall_pre_impl_compat_43_oquota(void);
+void __sanitizer_syscall_post_impl_compat_43_oquota(long long res);
+void __sanitizer_syscall_pre_impl_compat_43_ogetsockname(long long fdec,
+ long long asa,
+ long long alen);
+void __sanitizer_syscall_post_impl_compat_43_ogetsockname(long long res,
+ long long fdec,
+ long long asa,
+ long long alen);
+/* syscall 151 has been skipped */
+/* syscall 152 has been skipped */
+/* syscall 153 has been skipped */
+/* syscall 154 has been skipped */
+void __sanitizer_syscall_pre_impl_nfssvc(long long flag, long long argp);
+void __sanitizer_syscall_post_impl_nfssvc(long long res, long long flag,
+ long long argp);
+void __sanitizer_syscall_pre_impl_compat_43_ogetdirentries(long long fd,
+ long long buf,
+ long long count,
+ long long basep);
+void __sanitizer_syscall_post_impl_compat_43_ogetdirentries(long long res,
+ long long fd,
+ long long buf,
+ long long count,
+ long long basep);
+void __sanitizer_syscall_pre_impl_compat_20_statfs(long long path,
+ long long buf);
+void __sanitizer_syscall_post_impl_compat_20_statfs(long long res,
+ long long path,
+ long long buf);
+void __sanitizer_syscall_pre_impl_compat_20_fstatfs(long long fd,
+ long long buf);
+void __sanitizer_syscall_post_impl_compat_20_fstatfs(long long res,
+ long long fd,
+ long long buf);
+/* syscall 159 has been skipped */
+/* syscall 160 has been skipped */
+void __sanitizer_syscall_pre_impl_compat_30_getfh(long long fname,
+ long long fhp);
+void __sanitizer_syscall_post_impl_compat_30_getfh(long long res,
+ long long fname,
+ long long fhp);
+void __sanitizer_syscall_pre_impl_compat_09_ogetdomainname(long long domainname,
+ long long len);
+void __sanitizer_syscall_post_impl_compat_09_ogetdomainname(
+ long long res, long long domainname, long long len);
+void __sanitizer_syscall_pre_impl_compat_09_osetdomainname(long long domainname,
+ long long len);
+void __sanitizer_syscall_post_impl_compat_09_osetdomainname(
+ long long res, long long domainname, long long len);
+void __sanitizer_syscall_pre_impl_compat_09_ouname(long long name);
+void __sanitizer_syscall_post_impl_compat_09_ouname(long long res,
+ long long name);
+void __sanitizer_syscall_pre_impl_sysarch(long long op, long long parms);
+void __sanitizer_syscall_post_impl_sysarch(long long res, long long op,
+ long long parms);
+void __sanitizer_syscall_pre_impl___futex(long long uaddr, long long op,
+ long long val, long long timeout,
+ long long uaddr2, long long val2,
+ long long val3);
+void __sanitizer_syscall_post_impl___futex(long long res, long long uaddr,
+ long long op, long long val,
+ long long timeout, long long uaddr2,
+ long long val2, long long val3);
+void __sanitizer_syscall_pre_impl___futex_set_robust_list(long long head,
+ long long len);
+void __sanitizer_syscall_post_impl___futex_set_robust_list(long long res,
+ long long head,
+ long long len);
+void __sanitizer_syscall_pre_impl___futex_get_robust_list(long long lwpid,
+ long long headp,
+ long long lenp);
+void __sanitizer_syscall_post_impl___futex_get_robust_list(long long res,
+ long long lwpid,
+ long long headp,
+ long long lenp);
+#if !defined(_LP64)
+void __sanitizer_syscall_pre_impl_compat_10_osemsys(long long which,
+ long long a2, long long a3,
+ long long a4, long long a5);
+void __sanitizer_syscall_post_impl_compat_10_osemsys(long long res,
+ long long which,
+ long long a2, long long a3,
+ long long a4,
+ long long a5);
+#else
+/* syscall 169 has been skipped */
+#endif
+#if !defined(_LP64)
+void __sanitizer_syscall_pre_impl_compat_10_omsgsys(long long which,
+ long long a2, long long a3,
+ long long a4, long long a5,
+ long long a6);
+void __sanitizer_syscall_post_impl_compat_10_omsgsys(long long res,
+ long long which,
+ long long a2, long long a3,
+ long long a4, long long a5,
+ long long a6);
+#else
+/* syscall 170 has been skipped */
+#endif
+#if !defined(_LP64)
+void __sanitizer_syscall_pre_impl_compat_10_oshmsys(long long which,
+ long long a2, long long a3,
+ long long a4);
+void __sanitizer_syscall_post_impl_compat_10_oshmsys(long long res,
+ long long which,
+ long long a2, long long a3,
+ long long a4);
+#else
+/* syscall 171 has been skipped */
+#endif
+/* syscall 172 has been skipped */
+void __sanitizer_syscall_pre_impl_pread(long long fd, long long buf,
+ long long nbyte, long long PAD,
+ long long offset);
+void __sanitizer_syscall_post_impl_pread(long long res, long long fd,
+ long long buf, long long nbyte,
+ long long PAD, long long offset);
+void __sanitizer_syscall_pre_impl_pwrite(long long fd, long long buf,
+ long long nbyte, long long PAD,
+ long long offset);
+void __sanitizer_syscall_post_impl_pwrite(long long res, long long fd,
+ long long buf, long long nbyte,
+ long long PAD, long long offset);
+void __sanitizer_syscall_pre_impl_compat_30_ntp_gettime(long long ntvp);
+void __sanitizer_syscall_post_impl_compat_30_ntp_gettime(long long res,
+ long long ntvp);
+#if defined(NTP) || !defined(_KERNEL_OPT)
+void __sanitizer_syscall_pre_impl_ntp_adjtime(long long tp);
+void __sanitizer_syscall_post_impl_ntp_adjtime(long long res, long long tp);
+#else
+/* syscall 176 has been skipped */
+#endif
+/* syscall 177 has been skipped */
+/* syscall 178 has been skipped */
+/* syscall 179 has been skipped */
+/* syscall 180 has been skipped */
+void __sanitizer_syscall_pre_impl_setgid(long long gid);
+void __sanitizer_syscall_post_impl_setgid(long long res, long long gid);
+void __sanitizer_syscall_pre_impl_setegid(long long egid);
+void __sanitizer_syscall_post_impl_setegid(long long res, long long egid);
+void __sanitizer_syscall_pre_impl_seteuid(long long euid);
+void __sanitizer_syscall_post_impl_seteuid(long long res, long long euid);
+void __sanitizer_syscall_pre_impl_lfs_bmapv(long long fsidp, long long blkiov,
+ long long blkcnt);
+void __sanitizer_syscall_post_impl_lfs_bmapv(long long res, long long fsidp,
+ long long blkiov,
+ long long blkcnt);
+void __sanitizer_syscall_pre_impl_lfs_markv(long long fsidp, long long blkiov,
+ long long blkcnt);
+void __sanitizer_syscall_post_impl_lfs_markv(long long res, long long fsidp,
+ long long blkiov,
+ long long blkcnt);
+void __sanitizer_syscall_pre_impl_lfs_segclean(long long fsidp,
+ long long segment);
+void __sanitizer_syscall_post_impl_lfs_segclean(long long res, long long fsidp,
+ long long segment);
+void __sanitizer_syscall_pre_impl_compat_50_lfs_segwait(long long fsidp,
+ long long tv);
+void __sanitizer_syscall_post_impl_compat_50_lfs_segwait(long long res,
+ long long fsidp,
+ long long tv);
+void __sanitizer_syscall_pre_impl_compat_12_stat12(long long path,
+ long long ub);
+void __sanitizer_syscall_post_impl_compat_12_stat12(long long res,
+ long long path,
+ long long ub);
+void __sanitizer_syscall_pre_impl_compat_12_fstat12(long long fd, long long sb);
+void __sanitizer_syscall_post_impl_compat_12_fstat12(long long res,
+ long long fd,
+ long long sb);
+void __sanitizer_syscall_pre_impl_compat_12_lstat12(long long path,
+ long long ub);
+void __sanitizer_syscall_post_impl_compat_12_lstat12(long long res,
+ long long path,
+ long long ub);
+void __sanitizer_syscall_pre_impl_pathconf(long long path, long long name);
+void __sanitizer_syscall_post_impl_pathconf(long long res, long long path,
+ long long name);
+void __sanitizer_syscall_pre_impl_fpathconf(long long fd, long long name);
+void __sanitizer_syscall_post_impl_fpathconf(long long res, long long fd,
+ long long name);
+void __sanitizer_syscall_pre_impl_getsockopt2(long long s, long long level,
+ long long name, long long val,
+ long long avalsize);
+void __sanitizer_syscall_post_impl_getsockopt2(long long res, long long s,
+ long long level, long long name,
+ long long val,
+ long long avalsize);
+void __sanitizer_syscall_pre_impl_getrlimit(long long which, long long rlp);
+void __sanitizer_syscall_post_impl_getrlimit(long long res, long long which,
+ long long rlp);
+void __sanitizer_syscall_pre_impl_setrlimit(long long which, long long rlp);
+void __sanitizer_syscall_post_impl_setrlimit(long long res, long long which,
+ long long rlp);
+void __sanitizer_syscall_pre_impl_compat_12_getdirentries(long long fd,
+ long long buf,
+ long long count,
+ long long basep);
+void __sanitizer_syscall_post_impl_compat_12_getdirentries(long long res,
+ long long fd,
+ long long buf,
+ long long count,
+ long long basep);
+void __sanitizer_syscall_pre_impl_mmap(long long addr, long long len,
+ long long prot, long long flags,
+ long long fd, long long PAD,
+ long long pos);
+void __sanitizer_syscall_post_impl_mmap(long long res, long long addr,
+ long long len, long long prot,
+ long long flags, long long fd,
+ long long PAD, long long pos);
+void __sanitizer_syscall_pre_impl___syscall(long long code, long long arg0,
+ long long arg1, long long arg2,
+ long long arg3, long long arg4,
+ long long arg5, long long arg6,
+ long long arg7);
+void __sanitizer_syscall_post_impl___syscall(long long res, long long code,
+ long long arg0, long long arg1,
+ long long arg2, long long arg3,
+ long long arg4, long long arg5,
+ long long arg6, long long arg7);
+void __sanitizer_syscall_pre_impl_lseek(long long fd, long long PAD,
+ long long offset, long long whence);
+void __sanitizer_syscall_post_impl_lseek(long long res, long long fd,
+ long long PAD, long long offset,
+ long long whence);
+void __sanitizer_syscall_pre_impl_truncate(long long path, long long PAD,
+ long long length);
+void __sanitizer_syscall_post_impl_truncate(long long res, long long path,
+ long long PAD, long long length);
+void __sanitizer_syscall_pre_impl_ftruncate(long long fd, long long PAD,
+ long long length);
+void __sanitizer_syscall_post_impl_ftruncate(long long res, long long fd,
+ long long PAD, long long length);
+void __sanitizer_syscall_pre_impl___sysctl(long long name, long long namelen,
+ long long oldv, long long oldlenp,
+ long long newv, long long newlen);
+void __sanitizer_syscall_post_impl___sysctl(long long res, long long name,
+ long long namelen, long long oldv,
+ long long oldlenp, long long newv,
+ long long newlen);
+void __sanitizer_syscall_pre_impl_mlock(long long addr, long long len);
+void __sanitizer_syscall_post_impl_mlock(long long res, long long addr,
+ long long len);
+void __sanitizer_syscall_pre_impl_munlock(long long addr, long long len);
+void __sanitizer_syscall_post_impl_munlock(long long res, long long addr,
+ long long len);
+void __sanitizer_syscall_pre_impl_undelete(long long path);
+void __sanitizer_syscall_post_impl_undelete(long long res, long long path);
+void __sanitizer_syscall_pre_impl_compat_50_futimes(long long fd,
+ long long tptr);
+void __sanitizer_syscall_post_impl_compat_50_futimes(long long res,
+ long long fd,
+ long long tptr);
+void __sanitizer_syscall_pre_impl_getpgid(long long pid);
+void __sanitizer_syscall_post_impl_getpgid(long long res, long long pid);
+void __sanitizer_syscall_pre_impl_reboot(long long opt, long long bootstr);
+void __sanitizer_syscall_post_impl_reboot(long long res, long long opt,
+ long long bootstr);
+void __sanitizer_syscall_pre_impl_poll(long long fds, long long nfds,
+ long long timeout);
+void __sanitizer_syscall_post_impl_poll(long long res, long long fds,
+ long long nfds, long long timeout);
+void __sanitizer_syscall_pre_impl_afssys(long long id, long long a1,
+ long long a2, long long a3,
+ long long a4, long long a5,
+ long long a6);
+void __sanitizer_syscall_post_impl_afssys(long long res, long long id,
+ long long a1, long long a2,
+ long long a3, long long a4,
+ long long a5, long long a6);
+/* syscall 211 has been skipped */
+/* syscall 212 has been skipped */
+/* syscall 213 has been skipped */
+/* syscall 214 has been skipped */
+/* syscall 215 has been skipped */
+/* syscall 216 has been skipped */
+/* syscall 217 has been skipped */
+/* syscall 218 has been skipped */
+/* syscall 219 has been skipped */
+void __sanitizer_syscall_pre_impl_compat_14___semctl(long long semid,
+ long long semnum,
+ long long cmd,
+ long long arg);
+void __sanitizer_syscall_post_impl_compat_14___semctl(long long res,
+ long long semid,
+ long long semnum,
+ long long cmd,
+ long long arg);
+void __sanitizer_syscall_pre_impl_semget(long long key, long long nsems,
+ long long semflg);
+void __sanitizer_syscall_post_impl_semget(long long res, long long key,
+ long long nsems, long long semflg);
+void __sanitizer_syscall_pre_impl_semop(long long semid, long long sops,
+ long long nsops);
+void __sanitizer_syscall_post_impl_semop(long long res, long long semid,
+ long long sops, long long nsops);
+void __sanitizer_syscall_pre_impl_semconfig(long long flag);
+void __sanitizer_syscall_post_impl_semconfig(long long res, long long flag);
+void __sanitizer_syscall_pre_impl_compat_14_msgctl(long long msqid,
+ long long cmd,
+ long long buf);
+void __sanitizer_syscall_post_impl_compat_14_msgctl(long long res,
+ long long msqid,
+ long long cmd,
+ long long buf);
+void __sanitizer_syscall_pre_impl_msgget(long long key, long long msgflg);
+void __sanitizer_syscall_post_impl_msgget(long long res, long long key,
+ long long msgflg);
+void __sanitizer_syscall_pre_impl_msgsnd(long long msqid, long long msgp,
+ long long msgsz, long long msgflg);
+void __sanitizer_syscall_post_impl_msgsnd(long long res, long long msqid,
+ long long msgp, long long msgsz,
+ long long msgflg);
+void __sanitizer_syscall_pre_impl_msgrcv(long long msqid, long long msgp,
+ long long msgsz, long long msgtyp,
+ long long msgflg);
+void __sanitizer_syscall_post_impl_msgrcv(long long res, long long msqid,
+ long long msgp, long long msgsz,
+ long long msgtyp, long long msgflg);
+void __sanitizer_syscall_pre_impl_shmat(long long shmid, long long shmaddr,
+ long long shmflg);
+void __sanitizer_syscall_post_impl_shmat(long long res, long long shmid,
+ long long shmaddr, long long shmflg);
+void __sanitizer_syscall_pre_impl_compat_14_shmctl(long long shmid,
+ long long cmd,
+ long long buf);
+void __sanitizer_syscall_post_impl_compat_14_shmctl(long long res,
+ long long shmid,
+ long long cmd,
+ long long buf);
+void __sanitizer_syscall_pre_impl_shmdt(long long shmaddr);
+void __sanitizer_syscall_post_impl_shmdt(long long res, long long shmaddr);
+void __sanitizer_syscall_pre_impl_shmget(long long key, long long size,
+ long long shmflg);
+void __sanitizer_syscall_post_impl_shmget(long long res, long long key,
+ long long size, long long shmflg);
+void __sanitizer_syscall_pre_impl_compat_50_clock_gettime(long long clock_id,
+ long long tp);
+void __sanitizer_syscall_post_impl_compat_50_clock_gettime(long long res,
+ long long clock_id,
+ long long tp);
+void __sanitizer_syscall_pre_impl_compat_50_clock_settime(long long clock_id,
+ long long tp);
+void __sanitizer_syscall_post_impl_compat_50_clock_settime(long long res,
+ long long clock_id,
+ long long tp);
+void __sanitizer_syscall_pre_impl_compat_50_clock_getres(long long clock_id,
+ long long tp);
+void __sanitizer_syscall_post_impl_compat_50_clock_getres(long long res,
+ long long clock_id,
+ long long tp);
+void __sanitizer_syscall_pre_impl_timer_create(long long clock_id,
+ long long evp,
+ long long timerid);
+void __sanitizer_syscall_post_impl_timer_create(long long res,
+ long long clock_id,
+ long long evp,
+ long long timerid);
+void __sanitizer_syscall_pre_impl_timer_delete(long long timerid);
+void __sanitizer_syscall_post_impl_timer_delete(long long res,
+ long long timerid);
+void __sanitizer_syscall_pre_impl_compat_50_timer_settime(long long timerid,
+ long long flags,
+ long long value,
+ long long ovalue);
+void __sanitizer_syscall_post_impl_compat_50_timer_settime(long long res,
+ long long timerid,
+ long long flags,
+ long long value,
+ long long ovalue);
+void __sanitizer_syscall_pre_impl_compat_50_timer_gettime(long long timerid,
+ long long value);
+void __sanitizer_syscall_post_impl_compat_50_timer_gettime(long long res,
+ long long timerid,
+ long long value);
+void __sanitizer_syscall_pre_impl_timer_getoverrun(long long timerid);
+void __sanitizer_syscall_post_impl_timer_getoverrun(long long res,
+ long long timerid);
+void __sanitizer_syscall_pre_impl_compat_50_nanosleep(long long rqtp,
+ long long rmtp);
+void __sanitizer_syscall_post_impl_compat_50_nanosleep(long long res,
+ long long rqtp,
+ long long rmtp);
+void __sanitizer_syscall_pre_impl_fdatasync(long long fd);
+void __sanitizer_syscall_post_impl_fdatasync(long long res, long long fd);
+void __sanitizer_syscall_pre_impl_mlockall(long long flags);
+void __sanitizer_syscall_post_impl_mlockall(long long res, long long flags);
+void __sanitizer_syscall_pre_impl_munlockall(void);
+void __sanitizer_syscall_post_impl_munlockall(long long res);
+void __sanitizer_syscall_pre_impl_compat_50___sigtimedwait(long long set,
+ long long info,
+ long long timeout);
+void __sanitizer_syscall_post_impl_compat_50___sigtimedwait(long long res,
+ long long set,
+ long long info,
+ long long timeout);
+void __sanitizer_syscall_pre_impl_sigqueueinfo(long long pid, long long info);
+void __sanitizer_syscall_post_impl_sigqueueinfo(long long res, long long pid,
+ long long info);
+void __sanitizer_syscall_pre_impl_modctl(long long cmd, long long arg);
+void __sanitizer_syscall_post_impl_modctl(long long res, long long cmd,
+ long long arg);
+void __sanitizer_syscall_pre_impl__ksem_init(long long value, long long idp);
+void __sanitizer_syscall_post_impl__ksem_init(long long res, long long value,
+ long long idp);
+void __sanitizer_syscall_pre_impl__ksem_open(long long name, long long oflag,
+ long long mode, long long value,
+ long long idp);
+void __sanitizer_syscall_post_impl__ksem_open(long long res, long long name,
+ long long oflag, long long mode,
+ long long value, long long idp);
+void __sanitizer_syscall_pre_impl__ksem_unlink(long long name);
+void __sanitizer_syscall_post_impl__ksem_unlink(long long res, long long name);
+void __sanitizer_syscall_pre_impl__ksem_close(long long id);
+void __sanitizer_syscall_post_impl__ksem_close(long long res, long long id);
+void __sanitizer_syscall_pre_impl__ksem_post(long long id);
+void __sanitizer_syscall_post_impl__ksem_post(long long res, long long id);
+void __sanitizer_syscall_pre_impl__ksem_wait(long long id);
+void __sanitizer_syscall_post_impl__ksem_wait(long long res, long long id);
+void __sanitizer_syscall_pre_impl__ksem_trywait(long long id);
+void __sanitizer_syscall_post_impl__ksem_trywait(long long res, long long id);
+void __sanitizer_syscall_pre_impl__ksem_getvalue(long long id, long long value);
+void __sanitizer_syscall_post_impl__ksem_getvalue(long long res, long long id,
+ long long value);
+void __sanitizer_syscall_pre_impl__ksem_destroy(long long id);
+void __sanitizer_syscall_post_impl__ksem_destroy(long long res, long long id);
+void __sanitizer_syscall_pre_impl__ksem_timedwait(long long id,
+ long long abstime);
+void __sanitizer_syscall_post_impl__ksem_timedwait(long long res, long long id,
+ long long abstime);
+void __sanitizer_syscall_pre_impl_mq_open(long long name, long long oflag,
+ long long mode, long long attr);
+void __sanitizer_syscall_post_impl_mq_open(long long res, long long name,
+ long long oflag, long long mode,
+ long long attr);
+void __sanitizer_syscall_pre_impl_mq_close(long long mqdes);
+void __sanitizer_syscall_post_impl_mq_close(long long res, long long mqdes);
+void __sanitizer_syscall_pre_impl_mq_unlink(long long name);
+void __sanitizer_syscall_post_impl_mq_unlink(long long res, long long name);
+void __sanitizer_syscall_pre_impl_mq_getattr(long long mqdes, long long mqstat);
+void __sanitizer_syscall_post_impl_mq_getattr(long long res, long long mqdes,
+ long long mqstat);
+void __sanitizer_syscall_pre_impl_mq_setattr(long long mqdes, long long mqstat,
+ long long omqstat);
+void __sanitizer_syscall_post_impl_mq_setattr(long long res, long long mqdes,
+ long long mqstat,
+ long long omqstat);
+void __sanitizer_syscall_pre_impl_mq_notify(long long mqdes,
+ long long notification);
+void __sanitizer_syscall_post_impl_mq_notify(long long res, long long mqdes,
+ long long notification);
+void __sanitizer_syscall_pre_impl_mq_send(long long mqdes, long long msg_ptr,
+ long long msg_len,
+ long long msg_prio);
+void __sanitizer_syscall_post_impl_mq_send(long long res, long long mqdes,
+ long long msg_ptr, long long msg_len,
+ long long msg_prio);
+void __sanitizer_syscall_pre_impl_mq_receive(long long mqdes, long long msg_ptr,
+ long long msg_len,
+ long long msg_prio);
+void __sanitizer_syscall_post_impl_mq_receive(long long res, long long mqdes,
+ long long msg_ptr,
+ long long msg_len,
+ long long msg_prio);
+void __sanitizer_syscall_pre_impl_compat_50_mq_timedsend(long long mqdes,
+ long long msg_ptr,
+ long long msg_len,
+ long long msg_prio,
+ long long abs_timeout);
+void __sanitizer_syscall_post_impl_compat_50_mq_timedsend(
+ long long res, long long mqdes, long long msg_ptr, long long msg_len,
+ long long msg_prio, long long abs_timeout);
+void __sanitizer_syscall_pre_impl_compat_50_mq_timedreceive(
+ long long mqdes, long long msg_ptr, long long msg_len, long long msg_prio,
+ long long abs_timeout);
+void __sanitizer_syscall_post_impl_compat_50_mq_timedreceive(
+ long long res, long long mqdes, long long msg_ptr, long long msg_len,
+ long long msg_prio, long long abs_timeout);
+/* syscall 267 has been skipped */
+/* syscall 268 has been skipped */
+/* syscall 269 has been skipped */
+void __sanitizer_syscall_pre_impl___posix_rename(long long from, long long to);
+void __sanitizer_syscall_post_impl___posix_rename(long long res, long long from,
+ long long to);
+void __sanitizer_syscall_pre_impl_swapctl(long long cmd, long long arg,
+ long long misc);
+void __sanitizer_syscall_post_impl_swapctl(long long res, long long cmd,
+ long long arg, long long misc);
+void __sanitizer_syscall_pre_impl_compat_30_getdents(long long fd,
+ long long buf,
+ long long count);
+void __sanitizer_syscall_post_impl_compat_30_getdents(long long res,
+ long long fd,
+ long long buf,
+ long long count);
+void __sanitizer_syscall_pre_impl_minherit(long long addr, long long len,
+ long long inherit);
+void __sanitizer_syscall_post_impl_minherit(long long res, long long addr,
+ long long len, long long inherit);
+void __sanitizer_syscall_pre_impl_lchmod(long long path, long long mode);
+void __sanitizer_syscall_post_impl_lchmod(long long res, long long path,
+ long long mode);
+void __sanitizer_syscall_pre_impl_lchown(long long path, long long uid,
+ long long gid);
+void __sanitizer_syscall_post_impl_lchown(long long res, long long path,
+ long long uid, long long gid);
+void __sanitizer_syscall_pre_impl_compat_50_lutimes(long long path,
+ long long tptr);
+void __sanitizer_syscall_post_impl_compat_50_lutimes(long long res,
+ long long path,
+ long long tptr);
+void __sanitizer_syscall_pre_impl___msync13(long long addr, long long len,
+ long long flags);
+void __sanitizer_syscall_post_impl___msync13(long long res, long long addr,
+ long long len, long long flags);
+void __sanitizer_syscall_pre_impl_compat_30___stat13(long long path,
+ long long ub);
+void __sanitizer_syscall_post_impl_compat_30___stat13(long long res,
+ long long path,
+ long long ub);
+void __sanitizer_syscall_pre_impl_compat_30___fstat13(long long fd,
+ long long sb);
+void __sanitizer_syscall_post_impl_compat_30___fstat13(long long res,
+ long long fd,
+ long long sb);
+void __sanitizer_syscall_pre_impl_compat_30___lstat13(long long path,
+ long long ub);
+void __sanitizer_syscall_post_impl_compat_30___lstat13(long long res,
+ long long path,
+ long long ub);
+void __sanitizer_syscall_pre_impl___sigaltstack14(long long nss, long long oss);
+void __sanitizer_syscall_post_impl___sigaltstack14(long long res, long long nss,
+ long long oss);
+void __sanitizer_syscall_pre_impl___vfork14(void);
+void __sanitizer_syscall_post_impl___vfork14(long long res);
+void __sanitizer_syscall_pre_impl___posix_chown(long long path, long long uid,
+ long long gid);
+void __sanitizer_syscall_post_impl___posix_chown(long long res, long long path,
+ long long uid, long long gid);
+void __sanitizer_syscall_pre_impl___posix_fchown(long long fd, long long uid,
+ long long gid);
+void __sanitizer_syscall_post_impl___posix_fchown(long long res, long long fd,
+ long long uid, long long gid);
+void __sanitizer_syscall_pre_impl___posix_lchown(long long path, long long uid,
+ long long gid);
+void __sanitizer_syscall_post_impl___posix_lchown(long long res, long long path,
+ long long uid, long long gid);
+void __sanitizer_syscall_pre_impl_getsid(long long pid);
+void __sanitizer_syscall_post_impl_getsid(long long res, long long pid);
+void __sanitizer_syscall_pre_impl___clone(long long flags, long long stack);
+void __sanitizer_syscall_post_impl___clone(long long res, long long flags,
+ long long stack);
+void __sanitizer_syscall_pre_impl_fktrace(long long fd, long long ops,
+ long long facs, long long pid);
+void __sanitizer_syscall_post_impl_fktrace(long long res, long long fd,
+ long long ops, long long facs,
+ long long pid);
+void __sanitizer_syscall_pre_impl_preadv(long long fd, long long iovp,
+ long long iovcnt, long long PAD,
+ long long offset);
+void __sanitizer_syscall_post_impl_preadv(long long res, long long fd,
+ long long iovp, long long iovcnt,
+ long long PAD, long long offset);
+void __sanitizer_syscall_pre_impl_pwritev(long long fd, long long iovp,
+ long long iovcnt, long long PAD,
+ long long offset);
+void __sanitizer_syscall_post_impl_pwritev(long long res, long long fd,
+ long long iovp, long long iovcnt,
+ long long PAD, long long offset);
+void __sanitizer_syscall_pre_impl_compat_16___sigaction14(long long signum,
+ long long nsa,
+ long long osa);
+void __sanitizer_syscall_post_impl_compat_16___sigaction14(long long res,
+ long long signum,
+ long long nsa,
+ long long osa);
+void __sanitizer_syscall_pre_impl___sigpending14(long long set);
+void __sanitizer_syscall_post_impl___sigpending14(long long res, long long set);
+void __sanitizer_syscall_pre_impl___sigprocmask14(long long how, long long set,
+ long long oset);
+void __sanitizer_syscall_post_impl___sigprocmask14(long long res, long long how,
+ long long set,
+ long long oset);
+void __sanitizer_syscall_pre_impl___sigsuspend14(long long set);
+void __sanitizer_syscall_post_impl___sigsuspend14(long long res, long long set);
+void __sanitizer_syscall_pre_impl_compat_16___sigreturn14(long long sigcntxp);
+void __sanitizer_syscall_post_impl_compat_16___sigreturn14(long long res,
+ long long sigcntxp);
+void __sanitizer_syscall_pre_impl___getcwd(long long bufp, long long length);
+void __sanitizer_syscall_post_impl___getcwd(long long res, long long bufp,
+ long long length);
+void __sanitizer_syscall_pre_impl_fchroot(long long fd);
+void __sanitizer_syscall_post_impl_fchroot(long long res, long long fd);
+void __sanitizer_syscall_pre_impl_compat_30_fhopen(long long fhp,
+ long long flags);
+void __sanitizer_syscall_post_impl_compat_30_fhopen(long long res,
+ long long fhp,
+ long long flags);
+void __sanitizer_syscall_pre_impl_compat_30_fhstat(long long fhp, long long sb);
+void __sanitizer_syscall_post_impl_compat_30_fhstat(long long res,
+ long long fhp,
+ long long sb);
+void __sanitizer_syscall_pre_impl_compat_20_fhstatfs(long long fhp,
+ long long buf);
+void __sanitizer_syscall_post_impl_compat_20_fhstatfs(long long res,
+ long long fhp,
+ long long buf);
+void __sanitizer_syscall_pre_impl_compat_50_____semctl13(long long semid,
+ long long semnum,
+ long long cmd,
+ long long arg);
+void __sanitizer_syscall_post_impl_compat_50_____semctl13(long long res,
+ long long semid,
+ long long semnum,
+ long long cmd,
+ long long arg);
+void __sanitizer_syscall_pre_impl_compat_50___msgctl13(long long msqid,
+ long long cmd,
+ long long buf);
+void __sanitizer_syscall_post_impl_compat_50___msgctl13(long long res,
+ long long msqid,
+ long long cmd,
+ long long buf);
+void __sanitizer_syscall_pre_impl_compat_50___shmctl13(long long shmid,
+ long long cmd,
+ long long buf);
+void __sanitizer_syscall_post_impl_compat_50___shmctl13(long long res,
+ long long shmid,
+ long long cmd,
+ long long buf);
+void __sanitizer_syscall_pre_impl_lchflags(long long path, long long flags);
+void __sanitizer_syscall_post_impl_lchflags(long long res, long long path,
+ long long flags);
+void __sanitizer_syscall_pre_impl_issetugid(void);
+void __sanitizer_syscall_post_impl_issetugid(long long res);
+void __sanitizer_syscall_pre_impl_utrace(long long label, long long addr,
+ long long len);
+void __sanitizer_syscall_post_impl_utrace(long long res, long long label,
+ long long addr, long long len);
+void __sanitizer_syscall_pre_impl_getcontext(long long ucp);
+void __sanitizer_syscall_post_impl_getcontext(long long res, long long ucp);
+void __sanitizer_syscall_pre_impl_setcontext(long long ucp);
+void __sanitizer_syscall_post_impl_setcontext(long long res, long long ucp);
+void __sanitizer_syscall_pre_impl__lwp_create(long long ucp, long long flags,
+ long long new_lwp);
+void __sanitizer_syscall_post_impl__lwp_create(long long res, long long ucp,
+ long long flags,
+ long long new_lwp);
+void __sanitizer_syscall_pre_impl__lwp_exit(void);
+void __sanitizer_syscall_post_impl__lwp_exit(long long res);
+void __sanitizer_syscall_pre_impl__lwp_self(void);
+void __sanitizer_syscall_post_impl__lwp_self(long long res);
+void __sanitizer_syscall_pre_impl__lwp_wait(long long wait_for,
+ long long departed);
+void __sanitizer_syscall_post_impl__lwp_wait(long long res, long long wait_for,
+ long long departed);
+void __sanitizer_syscall_pre_impl__lwp_suspend(long long target);
+void __sanitizer_syscall_post_impl__lwp_suspend(long long res,
+ long long target);
+void __sanitizer_syscall_pre_impl__lwp_continue(long long target);
+void __sanitizer_syscall_post_impl__lwp_continue(long long res,
+ long long target);
+void __sanitizer_syscall_pre_impl__lwp_wakeup(long long target);
+void __sanitizer_syscall_post_impl__lwp_wakeup(long long res, long long target);
+void __sanitizer_syscall_pre_impl__lwp_getprivate(void);
+void __sanitizer_syscall_post_impl__lwp_getprivate(long long res);
+void __sanitizer_syscall_pre_impl__lwp_setprivate(long long ptr);
+void __sanitizer_syscall_post_impl__lwp_setprivate(long long res,
+ long long ptr);
+void __sanitizer_syscall_pre_impl__lwp_kill(long long target, long long signo);
+void __sanitizer_syscall_post_impl__lwp_kill(long long res, long long target,
+ long long signo);
+void __sanitizer_syscall_pre_impl__lwp_detach(long long target);
+void __sanitizer_syscall_post_impl__lwp_detach(long long res, long long target);
+void __sanitizer_syscall_pre_impl_compat_50__lwp_park(long long ts,
+ long long unpark,
+ long long hint,
+ long long unparkhint);
+void __sanitizer_syscall_post_impl_compat_50__lwp_park(long long res,
+ long long ts,
+ long long unpark,
+ long long hint,
+ long long unparkhint);
+void __sanitizer_syscall_pre_impl__lwp_unpark(long long target, long long hint);
+void __sanitizer_syscall_post_impl__lwp_unpark(long long res, long long target,
+ long long hint);
+void __sanitizer_syscall_pre_impl__lwp_unpark_all(long long targets,
+ long long ntargets,
+ long long hint);
+void __sanitizer_syscall_post_impl__lwp_unpark_all(long long res,
+ long long targets,
+ long long ntargets,
+ long long hint);
+void __sanitizer_syscall_pre_impl__lwp_setname(long long target,
+ long long name);
+void __sanitizer_syscall_post_impl__lwp_setname(long long res, long long target,
+ long long name);
+void __sanitizer_syscall_pre_impl__lwp_getname(long long target, long long name,
+ long long len);
+void __sanitizer_syscall_post_impl__lwp_getname(long long res, long long target,
+ long long name, long long len);
+void __sanitizer_syscall_pre_impl__lwp_ctl(long long features,
+ long long address);
+void __sanitizer_syscall_post_impl__lwp_ctl(long long res, long long features,
+ long long address);
+/* syscall 326 has been skipped */
+/* syscall 327 has been skipped */
+/* syscall 328 has been skipped */
+/* syscall 329 has been skipped */
+void __sanitizer_syscall_pre_impl_compat_60_sa_register(
+ long long newv, long long oldv, long long flags,
+ long long stackinfo_offset);
+void __sanitizer_syscall_post_impl_compat_60_sa_register(
+ long long res, long long newv, long long oldv, long long flags,
+ long long stackinfo_offset);
+void __sanitizer_syscall_pre_impl_compat_60_sa_stacks(long long num,
+ long long stacks);
+void __sanitizer_syscall_post_impl_compat_60_sa_stacks(long long res,
+ long long num,
+ long long stacks);
+void __sanitizer_syscall_pre_impl_compat_60_sa_enable(void);
+void __sanitizer_syscall_post_impl_compat_60_sa_enable(long long res);
+void __sanitizer_syscall_pre_impl_compat_60_sa_setconcurrency(
+ long long concurrency);
+void __sanitizer_syscall_post_impl_compat_60_sa_setconcurrency(
+ long long res, long long concurrency);
+void __sanitizer_syscall_pre_impl_compat_60_sa_yield(void);
+void __sanitizer_syscall_post_impl_compat_60_sa_yield(long long res);
+void __sanitizer_syscall_pre_impl_compat_60_sa_preempt(long long sa_id);
+void __sanitizer_syscall_post_impl_compat_60_sa_preempt(long long res,
+ long long sa_id);
+/* syscall 336 has been skipped */
+/* syscall 337 has been skipped */
+/* syscall 338 has been skipped */
+/* syscall 339 has been skipped */
+void __sanitizer_syscall_pre_impl___sigaction_sigtramp(long long signum,
+ long long nsa,
+ long long osa,
+ long long tramp,
+ long long vers);
+void __sanitizer_syscall_post_impl___sigaction_sigtramp(
+ long long res, long long signum, long long nsa, long long osa,
+ long long tramp, long long vers);
+/* syscall 341 has been skipped */
+/* syscall 342 has been skipped */
+void __sanitizer_syscall_pre_impl_rasctl(long long addr, long long len,
+ long long op);
+void __sanitizer_syscall_post_impl_rasctl(long long res, long long addr,
+ long long len, long long op);
+void __sanitizer_syscall_pre_impl_kqueue(void);
+void __sanitizer_syscall_post_impl_kqueue(long long res);
+void __sanitizer_syscall_pre_impl_compat_50_kevent(
+ long long fd, long long changelist, long long nchanges, long long eventlist,
+ long long nevents, long long timeout);
+void __sanitizer_syscall_post_impl_compat_50_kevent(
+ long long res, long long fd, long long changelist, long long nchanges,
+ long long eventlist, long long nevents, long long timeout);
+void __sanitizer_syscall_pre_impl__sched_setparam(long long pid, long long lid,
+ long long policy,
+ long long params);
+void __sanitizer_syscall_post_impl__sched_setparam(long long res, long long pid,
+ long long lid,
+ long long policy,
+ long long params);
+void __sanitizer_syscall_pre_impl__sched_getparam(long long pid, long long lid,
+ long long policy,
+ long long params);
+void __sanitizer_syscall_post_impl__sched_getparam(long long res, long long pid,
+ long long lid,
+ long long policy,
+ long long params);
+void __sanitizer_syscall_pre_impl__sched_setaffinity(long long pid,
+ long long lid,
+ long long size,
+ long long cpuset);
+void __sanitizer_syscall_post_impl__sched_setaffinity(long long res,
+ long long pid,
+ long long lid,
+ long long size,
+ long long cpuset);
+void __sanitizer_syscall_pre_impl__sched_getaffinity(long long pid,
+ long long lid,
+ long long size,
+ long long cpuset);
+void __sanitizer_syscall_post_impl__sched_getaffinity(long long res,
+ long long pid,
+ long long lid,
+ long long size,
+ long long cpuset);
+void __sanitizer_syscall_pre_impl_sched_yield(void);
+void __sanitizer_syscall_post_impl_sched_yield(long long res);
+void __sanitizer_syscall_pre_impl__sched_protect(long long priority);
+void __sanitizer_syscall_post_impl__sched_protect(long long res,
+ long long priority);
+/* syscall 352 has been skipped */
+/* syscall 353 has been skipped */
+void __sanitizer_syscall_pre_impl_fsync_range(long long fd, long long flags,
+ long long start,
+ long long length);
+void __sanitizer_syscall_post_impl_fsync_range(long long res, long long fd,
+ long long flags, long long start,
+ long long length);
+void __sanitizer_syscall_pre_impl_uuidgen(long long store, long long count);
+void __sanitizer_syscall_post_impl_uuidgen(long long res, long long store,
+ long long count);
+void __sanitizer_syscall_pre_impl_compat_90_getvfsstat(long long buf,
+ long long bufsize,
+ long long flags);
+void __sanitizer_syscall_post_impl_compat_90_getvfsstat(long long res,
+ long long buf,
+ long long bufsize,
+ long long flags);
+void __sanitizer_syscall_pre_impl_compat_90_statvfs1(long long path,
+ long long buf,
+ long long flags);
+void __sanitizer_syscall_post_impl_compat_90_statvfs1(long long res,
+ long long path,
+ long long buf,
+ long long flags);
+void __sanitizer_syscall_pre_impl_compat_90_fstatvfs1(long long fd,
+ long long buf,
+ long long flags);
+void __sanitizer_syscall_post_impl_compat_90_fstatvfs1(long long res,
+ long long fd,
+ long long buf,
+ long long flags);
+void __sanitizer_syscall_pre_impl_compat_30_fhstatvfs1(long long fhp,
+ long long buf,
+ long long flags);
+void __sanitizer_syscall_post_impl_compat_30_fhstatvfs1(long long res,
+ long long fhp,
+ long long buf,
+ long long flags);
+void __sanitizer_syscall_pre_impl_extattrctl(long long path, long long cmd,
+ long long filename,
+ long long attrnamespace,
+ long long attrname);
+void __sanitizer_syscall_post_impl_extattrctl(long long res, long long path,
+ long long cmd, long long filename,
+ long long attrnamespace,
+ long long attrname);
+void __sanitizer_syscall_pre_impl_extattr_set_file(long long path,
+ long long attrnamespace,
+ long long attrname,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_post_impl_extattr_set_file(
+ long long res, long long path, long long attrnamespace, long long attrname,
+ long long data, long long nbytes);
+void __sanitizer_syscall_pre_impl_extattr_get_file(long long path,
+ long long attrnamespace,
+ long long attrname,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_post_impl_extattr_get_file(
+ long long res, long long path, long long attrnamespace, long long attrname,
+ long long data, long long nbytes);
+void __sanitizer_syscall_pre_impl_extattr_delete_file(long long path,
+ long long attrnamespace,
+ long long attrname);
+void __sanitizer_syscall_post_impl_extattr_delete_file(long long res,
+ long long path,
+ long long attrnamespace,
+ long long attrname);
+void __sanitizer_syscall_pre_impl_extattr_set_fd(long long fd,
+ long long attrnamespace,
+ long long attrname,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_post_impl_extattr_set_fd(long long res, long long fd,
+ long long attrnamespace,
+ long long attrname,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_pre_impl_extattr_get_fd(long long fd,
+ long long attrnamespace,
+ long long attrname,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_post_impl_extattr_get_fd(long long res, long long fd,
+ long long attrnamespace,
+ long long attrname,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_pre_impl_extattr_delete_fd(long long fd,
+ long long attrnamespace,
+ long long attrname);
+void __sanitizer_syscall_post_impl_extattr_delete_fd(long long res,
+ long long fd,
+ long long attrnamespace,
+ long long attrname);
+void __sanitizer_syscall_pre_impl_extattr_set_link(long long path,
+ long long attrnamespace,
+ long long attrname,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_post_impl_extattr_set_link(
+ long long res, long long path, long long attrnamespace, long long attrname,
+ long long data, long long nbytes);
+void __sanitizer_syscall_pre_impl_extattr_get_link(long long path,
+ long long attrnamespace,
+ long long attrname,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_post_impl_extattr_get_link(
+ long long res, long long path, long long attrnamespace, long long attrname,
+ long long data, long long nbytes);
+void __sanitizer_syscall_pre_impl_extattr_delete_link(long long path,
+ long long attrnamespace,
+ long long attrname);
+void __sanitizer_syscall_post_impl_extattr_delete_link(long long res,
+ long long path,
+ long long attrnamespace,
+ long long attrname);
+void __sanitizer_syscall_pre_impl_extattr_list_fd(long long fd,
+ long long attrnamespace,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_post_impl_extattr_list_fd(long long res, long long fd,
+ long long attrnamespace,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_pre_impl_extattr_list_file(long long path,
+ long long attrnamespace,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_post_impl_extattr_list_file(long long res,
+ long long path,
+ long long attrnamespace,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_pre_impl_extattr_list_link(long long path,
+ long long attrnamespace,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_post_impl_extattr_list_link(long long res,
+ long long path,
+ long long attrnamespace,
+ long long data,
+ long long nbytes);
+void __sanitizer_syscall_pre_impl_compat_50_pselect(long long nd, long long in,
+ long long ou, long long ex,
+ long long ts,
+ long long mask);
+void __sanitizer_syscall_post_impl_compat_50_pselect(long long res,
+ long long nd, long long in,
+ long long ou, long long ex,
+ long long ts,
+ long long mask);
+void __sanitizer_syscall_pre_impl_compat_50_pollts(long long fds,
+ long long nfds, long long ts,
+ long long mask);
+void __sanitizer_syscall_post_impl_compat_50_pollts(
+ long long res, long long fds, long long nfds, long long ts, long long mask);
+void __sanitizer_syscall_pre_impl_setxattr(long long path, long long name,
+ long long value, long long size,
+ long long flags);
+void __sanitizer_syscall_post_impl_setxattr(long long res, long long path,
+ long long name, long long value,
+ long long size, long long flags);
+void __sanitizer_syscall_pre_impl_lsetxattr(long long path, long long name,
+ long long value, long long size,
+ long long flags);
+void __sanitizer_syscall_post_impl_lsetxattr(long long res, long long path,
+ long long name, long long value,
+ long long size, long long flags);
+void __sanitizer_syscall_pre_impl_fsetxattr(long long fd, long long name,
+ long long value, long long size,
+ long long flags);
+void __sanitizer_syscall_post_impl_fsetxattr(long long res, long long fd,
+ long long name, long long value,
+ long long size, long long flags);
+void __sanitizer_syscall_pre_impl_getxattr(long long path, long long name,
+ long long value, long long size);
+void __sanitizer_syscall_post_impl_getxattr(long long res, long long path,
+ long long name, long long value,
+ long long size);
+void __sanitizer_syscall_pre_impl_lgetxattr(long long path, long long name,
+ long long value, long long size);
+void __sanitizer_syscall_post_impl_lgetxattr(long long res, long long path,
+ long long name, long long value,
+ long long size);
+void __sanitizer_syscall_pre_impl_fgetxattr(long long fd, long long name,
+ long long value, long long size);
+void __sanitizer_syscall_post_impl_fgetxattr(long long res, long long fd,
+ long long name, long long value,
+ long long size);
+void __sanitizer_syscall_pre_impl_listxattr(long long path, long long list,
+ long long size);
+void __sanitizer_syscall_post_impl_listxattr(long long res, long long path,
+ long long list, long long size);
+void __sanitizer_syscall_pre_impl_llistxattr(long long path, long long list,
+ long long size);
+void __sanitizer_syscall_post_impl_llistxattr(long long res, long long path,
+ long long list, long long size);
+void __sanitizer_syscall_pre_impl_flistxattr(long long fd, long long list,
+ long long size);
+void __sanitizer_syscall_post_impl_flistxattr(long long res, long long fd,
+ long long list, long long size);
+void __sanitizer_syscall_pre_impl_removexattr(long long path, long long name);
+void __sanitizer_syscall_post_impl_removexattr(long long res, long long path,
+ long long name);
+void __sanitizer_syscall_pre_impl_lremovexattr(long long path, long long name);
+void __sanitizer_syscall_post_impl_lremovexattr(long long res, long long path,
+ long long name);
+void __sanitizer_syscall_pre_impl_fremovexattr(long long fd, long long name);
+void __sanitizer_syscall_post_impl_fremovexattr(long long res, long long fd,
+ long long name);
+void __sanitizer_syscall_pre_impl_compat_50___stat30(long long path,
+ long long ub);
+void __sanitizer_syscall_post_impl_compat_50___stat30(long long res,
+ long long path,
+ long long ub);
+void __sanitizer_syscall_pre_impl_compat_50___fstat30(long long fd,
+ long long sb);
+void __sanitizer_syscall_post_impl_compat_50___fstat30(long long res,
+ long long fd,
+ long long sb);
+void __sanitizer_syscall_pre_impl_compat_50___lstat30(long long path,
+ long long ub);
+void __sanitizer_syscall_post_impl_compat_50___lstat30(long long res,
+ long long path,
+ long long ub);
+void __sanitizer_syscall_pre_impl___getdents30(long long fd, long long buf,
+ long long count);
+void __sanitizer_syscall_post_impl___getdents30(long long res, long long fd,
+ long long buf, long long count);
+void __sanitizer_syscall_pre_impl_posix_fadvise(long long);
+void __sanitizer_syscall_post_impl_posix_fadvise(long long res, long long);
+void __sanitizer_syscall_pre_impl_compat_30___fhstat30(long long fhp,
+ long long sb);
+void __sanitizer_syscall_post_impl_compat_30___fhstat30(long long res,
+ long long fhp,
+ long long sb);
+void __sanitizer_syscall_pre_impl_compat_50___ntp_gettime30(long long ntvp);
+void __sanitizer_syscall_post_impl_compat_50___ntp_gettime30(long long res,
+ long long ntvp);
+void __sanitizer_syscall_pre_impl___socket30(long long domain, long long type,
+ long long protocol);
+void __sanitizer_syscall_post_impl___socket30(long long res, long long domain,
+ long long type,
+ long long protocol);
+void __sanitizer_syscall_pre_impl___getfh30(long long fname, long long fhp,
+ long long fh_size);
+void __sanitizer_syscall_post_impl___getfh30(long long res, long long fname,
+ long long fhp, long long fh_size);
+void __sanitizer_syscall_pre_impl___fhopen40(long long fhp, long long fh_size,
+ long long flags);
+void __sanitizer_syscall_post_impl___fhopen40(long long res, long long fhp,
+ long long fh_size,
+ long long flags);
+void __sanitizer_syscall_pre_impl_compat_90_fhstatvfs1(long long fhp,
+ long long fh_size,
+ long long buf,
+ long long flags);
+void __sanitizer_syscall_post_impl_compat_90_fhstatvfs1(long long res,
+ long long fhp,
+ long long fh_size,
+ long long buf,
+ long long flags);
+void __sanitizer_syscall_pre_impl_compat_50___fhstat40(long long fhp,
+ long long fh_size,
+ long long sb);
+void __sanitizer_syscall_post_impl_compat_50___fhstat40(long long res,
+ long long fhp,
+ long long fh_size,
+ long long sb);
+void __sanitizer_syscall_pre_impl_aio_cancel(long long fildes,
+ long long aiocbp);
+void __sanitizer_syscall_post_impl_aio_cancel(long long res, long long fildes,
+ long long aiocbp);
+void __sanitizer_syscall_pre_impl_aio_error(long long aiocbp);
+void __sanitizer_syscall_post_impl_aio_error(long long res, long long aiocbp);
+void __sanitizer_syscall_pre_impl_aio_fsync(long long op, long long aiocbp);
+void __sanitizer_syscall_post_impl_aio_fsync(long long res, long long op,
+ long long aiocbp);
+void __sanitizer_syscall_pre_impl_aio_read(long long aiocbp);
+void __sanitizer_syscall_post_impl_aio_read(long long res, long long aiocbp);
+void __sanitizer_syscall_pre_impl_aio_return(long long aiocbp);
+void __sanitizer_syscall_post_impl_aio_return(long long res, long long aiocbp);
+void __sanitizer_syscall_pre_impl_compat_50_aio_suspend(long long list,
+ long long nent,
+ long long timeout);
+void __sanitizer_syscall_post_impl_compat_50_aio_suspend(long long res,
+ long long list,
+ long long nent,
+ long long timeout);
+void __sanitizer_syscall_pre_impl_aio_write(long long aiocbp);
+void __sanitizer_syscall_post_impl_aio_write(long long res, long long aiocbp);
+void __sanitizer_syscall_pre_impl_lio_listio(long long mode, long long list,
+ long long nent, long long sig);
+void __sanitizer_syscall_post_impl_lio_listio(long long res, long long mode,
+ long long list, long long nent,
+ long long sig);
+/* syscall 407 has been skipped */
+/* syscall 408 has been skipped */
+/* syscall 409 has been skipped */
+void __sanitizer_syscall_pre_impl___mount50(long long type, long long path,
+ long long flags, long long data,
+ long long data_len);
+void __sanitizer_syscall_post_impl___mount50(long long res, long long type,
+ long long path, long long flags,
+ long long data,
+ long long data_len);
+void __sanitizer_syscall_pre_impl_mremap(long long old_address,
+ long long old_size,
+ long long new_address,
+ long long new_size, long long flags);
+void __sanitizer_syscall_post_impl_mremap(long long res, long long old_address,
+ long long old_size,
+ long long new_address,
+ long long new_size, long long flags);
+void __sanitizer_syscall_pre_impl_pset_create(long long psid);
+void __sanitizer_syscall_post_impl_pset_create(long long res, long long psid);
+void __sanitizer_syscall_pre_impl_pset_destroy(long long psid);
+void __sanitizer_syscall_post_impl_pset_destroy(long long res, long long psid);
+void __sanitizer_syscall_pre_impl_pset_assign(long long psid, long long cpuid,
+ long long opsid);
+void __sanitizer_syscall_post_impl_pset_assign(long long res, long long psid,
+ long long cpuid,
+ long long opsid);
+void __sanitizer_syscall_pre_impl__pset_bind(long long idtype,
+ long long first_id,
+ long long second_id,
+ long long psid, long long opsid);
+void __sanitizer_syscall_post_impl__pset_bind(long long res, long long idtype,
+ long long first_id,
+ long long second_id,
+ long long psid, long long opsid);
+void __sanitizer_syscall_pre_impl___posix_fadvise50(long long fd, long long PAD,
+ long long offset,
+ long long len,
+ long long advice);
+void __sanitizer_syscall_post_impl___posix_fadvise50(
+ long long res, long long fd, long long PAD, long long offset, long long len,
+ long long advice);
+void __sanitizer_syscall_pre_impl___select50(long long nd, long long in,
+ long long ou, long long ex,
+ long long tv);
+void __sanitizer_syscall_post_impl___select50(long long res, long long nd,
+ long long in, long long ou,
+ long long ex, long long tv);
+void __sanitizer_syscall_pre_impl___gettimeofday50(long long tp, long long tzp);
+void __sanitizer_syscall_post_impl___gettimeofday50(long long res, long long tp,
+ long long tzp);
+void __sanitizer_syscall_pre_impl___settimeofday50(long long tv, long long tzp);
+void __sanitizer_syscall_post_impl___settimeofday50(long long res, long long tv,
+ long long tzp);
+void __sanitizer_syscall_pre_impl___utimes50(long long path, long long tptr);
+void __sanitizer_syscall_post_impl___utimes50(long long res, long long path,
+ long long tptr);
+void __sanitizer_syscall_pre_impl___adjtime50(long long delta,
+ long long olddelta);
+void __sanitizer_syscall_post_impl___adjtime50(long long res, long long delta,
+ long long olddelta);
+void __sanitizer_syscall_pre_impl___lfs_segwait50(long long fsidp,
+ long long tv);
+void __sanitizer_syscall_post_impl___lfs_segwait50(long long res,
+ long long fsidp,
+ long long tv);
+void __sanitizer_syscall_pre_impl___futimes50(long long fd, long long tptr);
+void __sanitizer_syscall_post_impl___futimes50(long long res, long long fd,
+ long long tptr);
+void __sanitizer_syscall_pre_impl___lutimes50(long long path, long long tptr);
+void __sanitizer_syscall_post_impl___lutimes50(long long res, long long path,
+ long long tptr);
+void __sanitizer_syscall_pre_impl___setitimer50(long long which, long long itv,
+ long long oitv);
+void __sanitizer_syscall_post_impl___setitimer50(long long res, long long which,
+ long long itv, long long oitv);
+void __sanitizer_syscall_pre_impl___getitimer50(long long which, long long itv);
+void __sanitizer_syscall_post_impl___getitimer50(long long res, long long which,
+ long long itv);
+void __sanitizer_syscall_pre_impl___clock_gettime50(long long clock_id,
+ long long tp);
+void __sanitizer_syscall_post_impl___clock_gettime50(long long res,
+ long long clock_id,
+ long long tp);
+void __sanitizer_syscall_pre_impl___clock_settime50(long long clock_id,
+ long long tp);
+void __sanitizer_syscall_post_impl___clock_settime50(long long res,
+ long long clock_id,
+ long long tp);
+void __sanitizer_syscall_pre_impl___clock_getres50(long long clock_id,
+ long long tp);
+void __sanitizer_syscall_post_impl___clock_getres50(long long res,
+ long long clock_id,
+ long long tp);
+void __sanitizer_syscall_pre_impl___nanosleep50(long long rqtp, long long rmtp);
+void __sanitizer_syscall_post_impl___nanosleep50(long long res, long long rqtp,
+ long long rmtp);
+void __sanitizer_syscall_pre_impl_____sigtimedwait50(long long set,
+ long long info,
+ long long timeout);
+void __sanitizer_syscall_post_impl_____sigtimedwait50(long long res,
+ long long set,
+ long long info,
+ long long timeout);
+void __sanitizer_syscall_pre_impl___mq_timedsend50(long long mqdes,
+ long long msg_ptr,
+ long long msg_len,
+ long long msg_prio,
+ long long abs_timeout);
+void __sanitizer_syscall_post_impl___mq_timedsend50(
+ long long res, long long mqdes, long long msg_ptr, long long msg_len,
+ long long msg_prio, long long abs_timeout);
+void __sanitizer_syscall_pre_impl___mq_timedreceive50(long long mqdes,
+ long long msg_ptr,
+ long long msg_len,
+ long long msg_prio,
+ long long abs_timeout);
+void __sanitizer_syscall_post_impl___mq_timedreceive50(
+ long long res, long long mqdes, long long msg_ptr, long long msg_len,
+ long long msg_prio, long long abs_timeout);
+void __sanitizer_syscall_pre_impl_compat_60__lwp_park(long long ts,
+ long long unpark,
+ long long hint,
+ long long unparkhint);
+void __sanitizer_syscall_post_impl_compat_60__lwp_park(long long res,
+ long long ts,
+ long long unpark,
+ long long hint,
+ long long unparkhint);
+void __sanitizer_syscall_pre_impl___kevent50(long long fd, long long changelist,
+ long long nchanges,
+ long long eventlist,
+ long long nevents,
+ long long timeout);
+void __sanitizer_syscall_post_impl___kevent50(
+ long long res, long long fd, long long changelist, long long nchanges,
+ long long eventlist, long long nevents, long long timeout);
+void __sanitizer_syscall_pre_impl___pselect50(long long nd, long long in,
+ long long ou, long long ex,
+ long long ts, long long mask);
+void __sanitizer_syscall_post_impl___pselect50(long long res, long long nd,
+ long long in, long long ou,
+ long long ex, long long ts,
+ long long mask);
+void __sanitizer_syscall_pre_impl___pollts50(long long fds, long long nfds,
+ long long ts, long long mask);
+void __sanitizer_syscall_post_impl___pollts50(long long res, long long fds,
+ long long nfds, long long ts,
+ long long mask);
+void __sanitizer_syscall_pre_impl___aio_suspend50(long long list,
+ long long nent,
+ long long timeout);
+void __sanitizer_syscall_post_impl___aio_suspend50(long long res,
+ long long list,
+ long long nent,
+ long long timeout);
+void __sanitizer_syscall_pre_impl___stat50(long long path, long long ub);
+void __sanitizer_syscall_post_impl___stat50(long long res, long long path,
+ long long ub);
+void __sanitizer_syscall_pre_impl___fstat50(long long fd, long long sb);
+void __sanitizer_syscall_post_impl___fstat50(long long res, long long fd,
+ long long sb);
+void __sanitizer_syscall_pre_impl___lstat50(long long path, long long ub);
+void __sanitizer_syscall_post_impl___lstat50(long long res, long long path,
+ long long ub);
+void __sanitizer_syscall_pre_impl_____semctl50(long long semid,
+ long long semnum, long long cmd,
+ long long arg);
+void __sanitizer_syscall_post_impl_____semctl50(long long res, long long semid,
+ long long semnum, long long cmd,
+ long long arg);
+void __sanitizer_syscall_pre_impl___shmctl50(long long shmid, long long cmd,
+ long long buf);
+void __sanitizer_syscall_post_impl___shmctl50(long long res, long long shmid,
+ long long cmd, long long buf);
+void __sanitizer_syscall_pre_impl___msgctl50(long long msqid, long long cmd,
+ long long buf);
+void __sanitizer_syscall_post_impl___msgctl50(long long res, long long msqid,
+ long long cmd, long long buf);
+void __sanitizer_syscall_pre_impl___getrusage50(long long who,
+ long long rusage);
+void __sanitizer_syscall_post_impl___getrusage50(long long res, long long who,
+ long long rusage);
+void __sanitizer_syscall_pre_impl___timer_settime50(long long timerid,
+ long long flags,
+ long long value,
+ long long ovalue);
+void __sanitizer_syscall_post_impl___timer_settime50(long long res,
+ long long timerid,
+ long long flags,
+ long long value,
+ long long ovalue);
+void __sanitizer_syscall_pre_impl___timer_gettime50(long long timerid,
+ long long value);
+void __sanitizer_syscall_post_impl___timer_gettime50(long long res,
+ long long timerid,
+ long long value);
+#if defined(NTP) || !defined(_KERNEL_OPT)
+void __sanitizer_syscall_pre_impl___ntp_gettime50(long long ntvp);
+void __sanitizer_syscall_post_impl___ntp_gettime50(long long res,
+ long long ntvp);
+#else
+/* syscall 448 has been skipped */
+#endif
+void __sanitizer_syscall_pre_impl___wait450(long long pid, long long status,
+ long long options,
+ long long rusage);
+void __sanitizer_syscall_post_impl___wait450(long long res, long long pid,
+ long long status,
+ long long options,
+ long long rusage);
+void __sanitizer_syscall_pre_impl___mknod50(long long path, long long mode,
+ long long dev);
+void __sanitizer_syscall_post_impl___mknod50(long long res, long long path,
+ long long mode, long long dev);
+void __sanitizer_syscall_pre_impl___fhstat50(long long fhp, long long fh_size,
+ long long sb);
+void __sanitizer_syscall_post_impl___fhstat50(long long res, long long fhp,
+ long long fh_size, long long sb);
+/* syscall 452 has been skipped */
+void __sanitizer_syscall_pre_impl_pipe2(long long fildes, long long flags);
+void __sanitizer_syscall_post_impl_pipe2(long long res, long long fildes,
+ long long flags);
+void __sanitizer_syscall_pre_impl_dup3(long long from, long long to,
+ long long flags);
+void __sanitizer_syscall_post_impl_dup3(long long res, long long from,
+ long long to, long long flags);
+void __sanitizer_syscall_pre_impl_kqueue1(long long flags);
+void __sanitizer_syscall_post_impl_kqueue1(long long res, long long flags);
+void __sanitizer_syscall_pre_impl_paccept(long long s, long long name,
+ long long anamelen, long long mask,
+ long long flags);
+void __sanitizer_syscall_post_impl_paccept(long long res, long long s,
+ long long name, long long anamelen,
+ long long mask, long long flags);
+void __sanitizer_syscall_pre_impl_linkat(long long fd1, long long name1,
+ long long fd2, long long name2,
+ long long flags);
+void __sanitizer_syscall_post_impl_linkat(long long res, long long fd1,
+ long long name1, long long fd2,
+ long long name2, long long flags);
+void __sanitizer_syscall_pre_impl_renameat(long long fromfd, long long from,
+ long long tofd, long long to);
+void __sanitizer_syscall_post_impl_renameat(long long res, long long fromfd,
+ long long from, long long tofd,
+ long long to);
+void __sanitizer_syscall_pre_impl_mkfifoat(long long fd, long long path,
+ long long mode);
+void __sanitizer_syscall_post_impl_mkfifoat(long long res, long long fd,
+ long long path, long long mode);
+void __sanitizer_syscall_pre_impl_mknodat(long long fd, long long path,
+ long long mode, long long PAD,
+ long long dev);
+void __sanitizer_syscall_post_impl_mknodat(long long res, long long fd,
+ long long path, long long mode,
+ long long PAD, long long dev);
+void __sanitizer_syscall_pre_impl_mkdirat(long long fd, long long path,
+ long long mode);
+void __sanitizer_syscall_post_impl_mkdirat(long long res, long long fd,
+ long long path, long long mode);
+void __sanitizer_syscall_pre_impl_faccessat(long long fd, long long path,
+ long long amode, long long flag);
+void __sanitizer_syscall_post_impl_faccessat(long long res, long long fd,
+ long long path, long long amode,
+ long long flag);
+void __sanitizer_syscall_pre_impl_fchmodat(long long fd, long long path,
+ long long mode, long long flag);
+void __sanitizer_syscall_post_impl_fchmodat(long long res, long long fd,
+ long long path, long long mode,
+ long long flag);
+void __sanitizer_syscall_pre_impl_fchownat(long long fd, long long path,
+ long long owner, long long group,
+ long long flag);
+void __sanitizer_syscall_post_impl_fchownat(long long res, long long fd,
+ long long path, long long owner,
+ long long group, long long flag);
+void __sanitizer_syscall_pre_impl_fexecve(long long fd, long long argp,
+ long long envp);
+void __sanitizer_syscall_post_impl_fexecve(long long res, long long fd,
+ long long argp, long long envp);
+void __sanitizer_syscall_pre_impl_fstatat(long long fd, long long path,
+ long long buf, long long flag);
+void __sanitizer_syscall_post_impl_fstatat(long long res, long long fd,
+ long long path, long long buf,
+ long long flag);
+void __sanitizer_syscall_pre_impl_utimensat(long long fd, long long path,
+ long long tptr, long long flag);
+void __sanitizer_syscall_post_impl_utimensat(long long res, long long fd,
+ long long path, long long tptr,
+ long long flag);
+void __sanitizer_syscall_pre_impl_openat(long long fd, long long path,
+ long long oflags, long long mode);
+void __sanitizer_syscall_post_impl_openat(long long res, long long fd,
+ long long path, long long oflags,
+ long long mode);
+void __sanitizer_syscall_pre_impl_readlinkat(long long fd, long long path,
+ long long buf, long long bufsize);
+void __sanitizer_syscall_post_impl_readlinkat(long long res, long long fd,
+ long long path, long long buf,
+ long long bufsize);
+void __sanitizer_syscall_pre_impl_symlinkat(long long path1, long long fd,
+ long long path2);
+void __sanitizer_syscall_post_impl_symlinkat(long long res, long long path1,
+ long long fd, long long path2);
+void __sanitizer_syscall_pre_impl_unlinkat(long long fd, long long path,
+ long long flag);
+void __sanitizer_syscall_post_impl_unlinkat(long long res, long long fd,
+ long long path, long long flag);
+void __sanitizer_syscall_pre_impl_futimens(long long fd, long long tptr);
+void __sanitizer_syscall_post_impl_futimens(long long res, long long fd,
+ long long tptr);
+void __sanitizer_syscall_pre_impl___quotactl(long long path, long long args);
+void __sanitizer_syscall_post_impl___quotactl(long long res, long long path,
+ long long args);
+void __sanitizer_syscall_pre_impl_posix_spawn(long long pid, long long path,
+ long long file_actions,
+ long long attrp, long long argv,
+ long long envp);
+void __sanitizer_syscall_post_impl_posix_spawn(long long res, long long pid,
+ long long path,
+ long long file_actions,
+ long long attrp, long long argv,
+ long long envp);
+void __sanitizer_syscall_pre_impl_recvmmsg(long long s, long long mmsg,
+ long long vlen, long long flags,
+ long long timeout);
+void __sanitizer_syscall_post_impl_recvmmsg(long long res, long long s,
+ long long mmsg, long long vlen,
+ long long flags, long long timeout);
+void __sanitizer_syscall_pre_impl_sendmmsg(long long s, long long mmsg,
+ long long vlen, long long flags);
+void __sanitizer_syscall_post_impl_sendmmsg(long long res, long long s,
+ long long mmsg, long long vlen,
+ long long flags);
+void __sanitizer_syscall_pre_impl_clock_nanosleep(long long clock_id,
+ long long flags,
+ long long rqtp,
+ long long rmtp);
+void __sanitizer_syscall_post_impl_clock_nanosleep(long long res,
+ long long clock_id,
+ long long flags,
+ long long rqtp,
+ long long rmtp);
+void __sanitizer_syscall_pre_impl____lwp_park60(long long clock_id,
+ long long flags, long long ts,
+ long long unpark,
+ long long hint,
+ long long unparkhint);
+void __sanitizer_syscall_post_impl____lwp_park60(
+ long long res, long long clock_id, long long flags, long long ts,
+ long long unpark, long long hint, long long unparkhint);
+void __sanitizer_syscall_pre_impl_posix_fallocate(long long fd, long long PAD,
+ long long pos, long long len);
+void __sanitizer_syscall_post_impl_posix_fallocate(long long res, long long fd,
+ long long PAD, long long pos,
+ long long len);
+void __sanitizer_syscall_pre_impl_fdiscard(long long fd, long long PAD,
+ long long pos, long long len);
+void __sanitizer_syscall_post_impl_fdiscard(long long res, long long fd,
+ long long PAD, long long pos,
+ long long len);
+void __sanitizer_syscall_pre_impl_wait6(long long idtype, long long id,
+ long long status, long long options,
+ long long wru, long long info);
+void __sanitizer_syscall_post_impl_wait6(long long res, long long idtype,
+ long long id, long long status,
+ long long options, long long wru,
+ long long info);
+void __sanitizer_syscall_pre_impl_clock_getcpuclockid2(long long idtype,
+ long long id,
+ long long clock_id);
+void __sanitizer_syscall_post_impl_clock_getcpuclockid2(long long res,
+ long long idtype,
+ long long id,
+ long long clock_id);
+void __sanitizer_syscall_pre_impl___getvfsstat90(long long buf,
+ long long bufsize,
+ long long flags);
+void __sanitizer_syscall_post_impl___getvfsstat90(long long res, long long buf,
+ long long bufsize,
+ long long flags);
+void __sanitizer_syscall_pre_impl___statvfs190(long long path, long long buf,
+ long long flags);
+void __sanitizer_syscall_post_impl___statvfs190(long long res, long long path,
+ long long buf, long long flags);
+void __sanitizer_syscall_pre_impl___fstatvfs190(long long fd, long long buf,
+ long long flags);
+void __sanitizer_syscall_post_impl___fstatvfs190(long long res, long long fd,
+ long long buf,
+ long long flags);
+void __sanitizer_syscall_pre_impl___fhstatvfs190(long long fhp,
+ long long fh_size,
+ long long buf,
+ long long flags);
+void __sanitizer_syscall_post_impl___fhstatvfs190(long long res, long long fhp,
+ long long fh_size,
+ long long buf,
+ long long flags);
+void __sanitizer_syscall_pre_impl___acl_get_link(long long path, long long type,
+ long long aclp);
+void __sanitizer_syscall_post_impl___acl_get_link(long long res, long long path,
+ long long type,
+ long long aclp);
+void __sanitizer_syscall_pre_impl___acl_set_link(long long path, long long type,
+ long long aclp);
+void __sanitizer_syscall_post_impl___acl_set_link(long long res, long long path,
+ long long type,
+ long long aclp);
+void __sanitizer_syscall_pre_impl___acl_delete_link(long long path,
+ long long type);
+void __sanitizer_syscall_post_impl___acl_delete_link(long long res,
+ long long path,
+ long long type);
+void __sanitizer_syscall_pre_impl___acl_aclcheck_link(long long path,
+ long long type,
+ long long aclp);
+void __sanitizer_syscall_post_impl___acl_aclcheck_link(long long res,
+ long long path,
+ long long type,
+ long long aclp);
+void __sanitizer_syscall_pre_impl___acl_get_file(long long path, long long type,
+ long long aclp);
+void __sanitizer_syscall_post_impl___acl_get_file(long long res, long long path,
+ long long type,
+ long long aclp);
+void __sanitizer_syscall_pre_impl___acl_set_file(long long path, long long type,
+ long long aclp);
+void __sanitizer_syscall_post_impl___acl_set_file(long long res, long long path,
+ long long type,
+ long long aclp);
+void __sanitizer_syscall_pre_impl___acl_get_fd(long long filedes,
+ long long type, long long aclp);
+void __sanitizer_syscall_post_impl___acl_get_fd(long long res,
+ long long filedes,
+ long long type, long long aclp);
+void __sanitizer_syscall_pre_impl___acl_set_fd(long long filedes,
+ long long type, long long aclp);
+void __sanitizer_syscall_post_impl___acl_set_fd(long long res,
+ long long filedes,
+ long long type, long long aclp);
+void __sanitizer_syscall_pre_impl___acl_delete_file(long long path,
+ long long type);
+void __sanitizer_syscall_post_impl___acl_delete_file(long long res,
+ long long path,
+ long long type);
+void __sanitizer_syscall_pre_impl___acl_delete_fd(long long filedes,
+ long long type);
+void __sanitizer_syscall_post_impl___acl_delete_fd(long long res,
+ long long filedes,
+ long long type);
+void __sanitizer_syscall_pre_impl___acl_aclcheck_file(long long path,
+ long long type,
+ long long aclp);
+void __sanitizer_syscall_post_impl___acl_aclcheck_file(long long res,
+ long long path,
+ long long type,
+ long long aclp);
+void __sanitizer_syscall_pre_impl___acl_aclcheck_fd(long long filedes,
+ long long type,
+ long long aclp);
+void __sanitizer_syscall_post_impl___acl_aclcheck_fd(long long res,
+ long long filedes,
+ long long type,
+ long long aclp);
+void __sanitizer_syscall_pre_impl_lpathconf(long long path, long long name);
+void __sanitizer_syscall_post_impl_lpathconf(long long res, long long path,
+ long long name);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+// DO NOT EDIT! THIS FILE HAS BEEN GENERATED!
+
+#endif // SANITIZER_NETBSD_SYSCALL_HOOKS_H
diff --git a/contrib/libs/clang16-rt/include/sanitizer/scudo_interface.h b/contrib/libs/clang16-rt/include/sanitizer/scudo_interface.h
new file mode 100644
index 00000000000..dd522c1efc2
--- /dev/null
+++ b/contrib/libs/clang16-rt/include/sanitizer/scudo_interface.h
@@ -0,0 +1,38 @@
+//===-- sanitizer/scudo_interface.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// Public Scudo interface header.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SCUDO_INTERFACE_H_
+#define SANITIZER_SCUDO_INTERFACE_H_
+
+#include <sanitizer/common_interface_defs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ // This function may be optionally provided by a user and should return
+ // a string containing Scudo runtime options. See scudo_flags.h for details.
+ const char* __scudo_default_options(void);
+
+ // This function allows to set the RSS limit at runtime. This can be either
+ // the hard limit (HardLimit=1) or the soft limit (HardLimit=0). The limit
+ // can be removed by setting LimitMb to 0. This function's parameters should
+ // be fully trusted to avoid security mishaps.
+ void __scudo_set_rss_limit(size_t LimitMb, int HardLimit);
+
+ // This function outputs various allocator statistics for both the Primary
+ // and Secondary allocators, including memory usage, number of allocations
+ // and deallocations.
+ void __scudo_print_stats(void);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // SANITIZER_SCUDO_INTERFACE_H_
diff --git a/contrib/libs/clang16-rt/include/sanitizer/tsan_interface_atomic.h b/contrib/libs/clang16-rt/include/sanitizer/tsan_interface_atomic.h
new file mode 100644
index 00000000000..5e41e2256c3
--- /dev/null
+++ b/contrib/libs/clang16-rt/include/sanitizer/tsan_interface_atomic.h
@@ -0,0 +1,221 @@
+//===-- tsan_interface_atomic.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Public interface header for TSan atomics.
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_INTERFACE_ATOMIC_H
+#define TSAN_INTERFACE_ATOMIC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef char __tsan_atomic8;
+typedef short __tsan_atomic16;
+typedef int __tsan_atomic32;
+typedef long __tsan_atomic64;
+#if defined(__SIZEOF_INT128__) \
+ || (__clang_major__ * 100 + __clang_minor__ >= 302)
+__extension__ typedef __int128 __tsan_atomic128;
+# define __TSAN_HAS_INT128 1
+#else
+# define __TSAN_HAS_INT128 0
+#endif
+
+// Part of ABI, do not change.
+// https://github.com/llvm/llvm-project/blob/main/libcxx/include/atomic
+typedef enum {
+ __tsan_memory_order_relaxed,
+ __tsan_memory_order_consume,
+ __tsan_memory_order_acquire,
+ __tsan_memory_order_release,
+ __tsan_memory_order_acq_rel,
+ __tsan_memory_order_seq_cst
+} __tsan_memory_order;
+
+__tsan_atomic8 __tsan_atomic8_load(const volatile __tsan_atomic8 *a,
+ __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_load(const volatile __tsan_atomic16 *a,
+ __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_load(const volatile __tsan_atomic32 *a,
+ __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_load(const volatile __tsan_atomic64 *a,
+ __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
+__tsan_atomic128 __tsan_atomic128_load(const volatile __tsan_atomic128 *a,
+ __tsan_memory_order mo);
+#endif
+
+void __tsan_atomic8_store(volatile __tsan_atomic8 *a, __tsan_atomic8 v,
+ __tsan_memory_order mo);
+void __tsan_atomic16_store(volatile __tsan_atomic16 *a, __tsan_atomic16 v,
+ __tsan_memory_order mo);
+void __tsan_atomic32_store(volatile __tsan_atomic32 *a, __tsan_atomic32 v,
+ __tsan_memory_order mo);
+void __tsan_atomic64_store(volatile __tsan_atomic64 *a, __tsan_atomic64 v,
+ __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
+void __tsan_atomic128_store(volatile __tsan_atomic128 *a, __tsan_atomic128 v,
+ __tsan_memory_order mo);
+#endif
+
+__tsan_atomic8 __tsan_atomic8_exchange(volatile __tsan_atomic8 *a,
+ __tsan_atomic8 v, __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_exchange(volatile __tsan_atomic16 *a,
+ __tsan_atomic16 v, __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_exchange(volatile __tsan_atomic32 *a,
+ __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_exchange(volatile __tsan_atomic64 *a,
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
+__tsan_atomic128 __tsan_atomic128_exchange(volatile __tsan_atomic128 *a,
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
+
+__tsan_atomic8 __tsan_atomic8_fetch_add(volatile __tsan_atomic8 *a,
+ __tsan_atomic8 v, __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_fetch_add(volatile __tsan_atomic16 *a,
+ __tsan_atomic16 v, __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_fetch_add(volatile __tsan_atomic32 *a,
+ __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_fetch_add(volatile __tsan_atomic64 *a,
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
+__tsan_atomic128 __tsan_atomic128_fetch_add(volatile __tsan_atomic128 *a,
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
+
+__tsan_atomic8 __tsan_atomic8_fetch_sub(volatile __tsan_atomic8 *a,
+ __tsan_atomic8 v, __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_fetch_sub(volatile __tsan_atomic16 *a,
+ __tsan_atomic16 v, __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_fetch_sub(volatile __tsan_atomic32 *a,
+ __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_fetch_sub(volatile __tsan_atomic64 *a,
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
+__tsan_atomic128 __tsan_atomic128_fetch_sub(volatile __tsan_atomic128 *a,
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
+
+__tsan_atomic8 __tsan_atomic8_fetch_and(volatile __tsan_atomic8 *a,
+ __tsan_atomic8 v, __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_fetch_and(volatile __tsan_atomic16 *a,
+ __tsan_atomic16 v, __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_fetch_and(volatile __tsan_atomic32 *a,
+ __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_fetch_and(volatile __tsan_atomic64 *a,
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
+__tsan_atomic128 __tsan_atomic128_fetch_and(volatile __tsan_atomic128 *a,
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
+
+__tsan_atomic8 __tsan_atomic8_fetch_or(volatile __tsan_atomic8 *a,
+ __tsan_atomic8 v, __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_fetch_or(volatile __tsan_atomic16 *a,
+ __tsan_atomic16 v, __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_fetch_or(volatile __tsan_atomic32 *a,
+ __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_fetch_or(volatile __tsan_atomic64 *a,
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
+__tsan_atomic128 __tsan_atomic128_fetch_or(volatile __tsan_atomic128 *a,
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
+
+__tsan_atomic8 __tsan_atomic8_fetch_xor(volatile __tsan_atomic8 *a,
+ __tsan_atomic8 v, __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_fetch_xor(volatile __tsan_atomic16 *a,
+ __tsan_atomic16 v, __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_fetch_xor(volatile __tsan_atomic32 *a,
+ __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_fetch_xor(volatile __tsan_atomic64 *a,
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
+__tsan_atomic128 __tsan_atomic128_fetch_xor(volatile __tsan_atomic128 *a,
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
+
+__tsan_atomic8 __tsan_atomic8_fetch_nand(volatile __tsan_atomic8 *a,
+ __tsan_atomic8 v, __tsan_memory_order mo);
+__tsan_atomic16 __tsan_atomic16_fetch_nand(volatile __tsan_atomic16 *a,
+ __tsan_atomic16 v, __tsan_memory_order mo);
+__tsan_atomic32 __tsan_atomic32_fetch_nand(volatile __tsan_atomic32 *a,
+ __tsan_atomic32 v, __tsan_memory_order mo);
+__tsan_atomic64 __tsan_atomic64_fetch_nand(volatile __tsan_atomic64 *a,
+ __tsan_atomic64 v, __tsan_memory_order mo);
+#if __TSAN_HAS_INT128
+__tsan_atomic128 __tsan_atomic128_fetch_nand(volatile __tsan_atomic128 *a,
+ __tsan_atomic128 v, __tsan_memory_order mo);
+#endif
+
+int __tsan_atomic8_compare_exchange_weak(volatile __tsan_atomic8 *a,
+ __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo,
+ __tsan_memory_order fail_mo);
+int __tsan_atomic16_compare_exchange_weak(volatile __tsan_atomic16 *a,
+ __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo,
+ __tsan_memory_order fail_mo);
+int __tsan_atomic32_compare_exchange_weak(volatile __tsan_atomic32 *a,
+ __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo,
+ __tsan_memory_order fail_mo);
+int __tsan_atomic64_compare_exchange_weak(volatile __tsan_atomic64 *a,
+ __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo,
+ __tsan_memory_order fail_mo);
+#if __TSAN_HAS_INT128
+int __tsan_atomic128_compare_exchange_weak(volatile __tsan_atomic128 *a,
+ __tsan_atomic128 *c, __tsan_atomic128 v, __tsan_memory_order mo,
+ __tsan_memory_order fail_mo);
+#endif
+
+int __tsan_atomic8_compare_exchange_strong(volatile __tsan_atomic8 *a,
+ __tsan_atomic8 *c, __tsan_atomic8 v, __tsan_memory_order mo,
+ __tsan_memory_order fail_mo);
+int __tsan_atomic16_compare_exchange_strong(volatile __tsan_atomic16 *a,
+ __tsan_atomic16 *c, __tsan_atomic16 v, __tsan_memory_order mo,
+ __tsan_memory_order fail_mo);
+int __tsan_atomic32_compare_exchange_strong(volatile __tsan_atomic32 *a,
+ __tsan_atomic32 *c, __tsan_atomic32 v, __tsan_memory_order mo,
+ __tsan_memory_order fail_mo);
+int __tsan_atomic64_compare_exchange_strong(volatile __tsan_atomic64 *a,
+ __tsan_atomic64 *c, __tsan_atomic64 v, __tsan_memory_order mo,
+ __tsan_memory_order fail_mo);
+#if __TSAN_HAS_INT128
+int __tsan_atomic128_compare_exchange_strong(volatile __tsan_atomic128 *a,
+ __tsan_atomic128 *c, __tsan_atomic128 v, __tsan_memory_order mo,
+ __tsan_memory_order fail_mo);
+#endif
+
+__tsan_atomic8 __tsan_atomic8_compare_exchange_val(
+ volatile __tsan_atomic8 *a, __tsan_atomic8 c, __tsan_atomic8 v,
+ __tsan_memory_order mo, __tsan_memory_order fail_mo);
+__tsan_atomic16 __tsan_atomic16_compare_exchange_val(
+ volatile __tsan_atomic16 *a, __tsan_atomic16 c, __tsan_atomic16 v,
+ __tsan_memory_order mo, __tsan_memory_order fail_mo);
+__tsan_atomic32 __tsan_atomic32_compare_exchange_val(
+ volatile __tsan_atomic32 *a, __tsan_atomic32 c, __tsan_atomic32 v,
+ __tsan_memory_order mo, __tsan_memory_order fail_mo);
+__tsan_atomic64 __tsan_atomic64_compare_exchange_val(
+ volatile __tsan_atomic64 *a, __tsan_atomic64 c, __tsan_atomic64 v,
+ __tsan_memory_order mo, __tsan_memory_order fail_mo);
+#if __TSAN_HAS_INT128
+__tsan_atomic128 __tsan_atomic128_compare_exchange_val(
+ volatile __tsan_atomic128 *a, __tsan_atomic128 c, __tsan_atomic128 v,
+ __tsan_memory_order mo, __tsan_memory_order fail_mo);
+#endif
+
+void __tsan_atomic_thread_fence(__tsan_memory_order mo);
+void __tsan_atomic_signal_fence(__tsan_memory_order mo);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // TSAN_INTERFACE_ATOMIC_H
diff --git a/contrib/libs/clang16-rt/include/sanitizer/ubsan_interface.h b/contrib/libs/clang16-rt/include/sanitizer/ubsan_interface.h
new file mode 100644
index 00000000000..59fc6c3c184
--- /dev/null
+++ b/contrib/libs/clang16-rt/include/sanitizer/ubsan_interface.h
@@ -0,0 +1,32 @@
+//===-- sanitizer/ubsan_interface.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of UBSanitizer (UBSan).
+//
+// Public interface header.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_UBSAN_INTERFACE_H
+#define SANITIZER_UBSAN_INTERFACE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/// User-provided default option settings.
+///
+/// You can provide your own implementation of this function to return a string
+/// containing UBSan runtime options (for example,
+/// <c>verbosity=1:halt_on_error=0</c>).
+///
+/// \returns Default options string.
+const char* __ubsan_default_options(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // SANITIZER_UBSAN_INTERFACE_H
diff --git a/contrib/libs/clang16-rt/lib/asan-preinit/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/asan-preinit/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan-preinit/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/asan-preinit/ya.make b/contrib/libs/clang16-rt/lib/asan-preinit/ya.make
new file mode 100644
index 00000000000..dda444f43ac
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan-preinit/ya.make
@@ -0,0 +1,45 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.asan-preinit${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib/asan)
+
+SRCS(
+ asan_preinit.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/asan/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/asan/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/asan/README.txt b/contrib/libs/clang16-rt/lib/asan/README.txt
new file mode 100644
index 00000000000..bb6ff42c5cd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/README.txt
@@ -0,0 +1,26 @@
+AddressSanitizer RT
+================================
+This directory contains sources of the AddressSanitizer (ASan) runtime library.
+
+Directory structure:
+README.txt : This file.
+Makefile.mk : File for make-based build.
+CMakeLists.txt : File for cmake-based build.
+asan_*.{cc,h} : Sources of the asan runtime library.
+scripts/* : Helper scripts.
+tests/* : ASan unit tests.
+
+Also ASan runtime needs the following libraries:
+lib/interception/ : Machinery used to intercept function calls.
+lib/sanitizer_common/ : Code shared between various sanitizers.
+
+ASan runtime currently also embeds part of LeakSanitizer runtime for
+leak detection (lib/lsan/lsan_common.{cc,h}).
+
+ASan runtime can only be built by CMake. You can run ASan tests
+from the root of your CMake build tree:
+
+make check-asan
+
+For more instructions see:
+https://github.com/google/sanitizers/wiki/AddressSanitizerHowToBuild
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_activation.cpp b/contrib/libs/clang16-rt/lib/asan/asan_activation.cpp
new file mode 100644
index 00000000000..1757838600c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_activation.cpp
@@ -0,0 +1,143 @@
+//===-- asan_activation.cpp -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan activation/deactivation logic.
+//===----------------------------------------------------------------------===//
+
+#include "asan_activation.h"
+#include "asan_allocator.h"
+#include "asan_flags.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "asan_poisoning.h"
+#include "asan_stack.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
+
+namespace __asan {
+
+static struct AsanDeactivatedFlags {
+ AllocatorOptions allocator_options;
+ int malloc_context_size;
+ bool poison_heap;
+ bool coverage;
+ const char *coverage_dir;
+
+ void RegisterActivationFlags(FlagParser *parser, Flags *f, CommonFlags *cf) {
+#define ASAN_ACTIVATION_FLAG(Type, Name) \
+ RegisterFlag(parser, #Name, "", &f->Name);
+#define COMMON_ACTIVATION_FLAG(Type, Name) \
+ RegisterFlag(parser, #Name, "", &cf->Name);
+#include "asan_activation_flags.inc"
+#undef ASAN_ACTIVATION_FLAG
+#undef COMMON_ACTIVATION_FLAG
+
+ RegisterIncludeFlags(parser, cf);
+ }
+
+ void OverrideFromActivationFlags() {
+ Flags f;
+ CommonFlags cf;
+ FlagParser parser;
+ RegisterActivationFlags(&parser, &f, &cf);
+
+ cf.SetDefaults();
+ // Copy the current activation flags.
+ allocator_options.CopyTo(&f, &cf);
+ cf.malloc_context_size = malloc_context_size;
+ f.poison_heap = poison_heap;
+ cf.coverage = coverage;
+ cf.coverage_dir = coverage_dir;
+ cf.verbosity = Verbosity();
+ cf.help = false; // this is activation-specific help
+
+ // Check if activation flags need to be overriden.
+ if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) {
+ parser.ParseString(env);
+ }
+
+ InitializeCommonFlags(&cf);
+
+ if (Verbosity()) ReportUnrecognizedFlags();
+
+ if (cf.help) parser.PrintFlagDescriptions();
+
+ allocator_options.SetFrom(&f, &cf);
+ malloc_context_size = cf.malloc_context_size;
+ poison_heap = f.poison_heap;
+ coverage = cf.coverage;
+ coverage_dir = cf.coverage_dir;
+ }
+
+ void Print() {
+ Report(
+ "quarantine_size_mb %d, thread_local_quarantine_size_kb %d, "
+ "max_redzone %d, poison_heap %d, malloc_context_size %d, "
+ "alloc_dealloc_mismatch %d, allocator_may_return_null %d, coverage %d, "
+ "coverage_dir %s, allocator_release_to_os_interval_ms %d\n",
+ allocator_options.quarantine_size_mb,
+ allocator_options.thread_local_quarantine_size_kb,
+ allocator_options.max_redzone, poison_heap, malloc_context_size,
+ allocator_options.alloc_dealloc_mismatch,
+ allocator_options.may_return_null, coverage, coverage_dir,
+ allocator_options.release_to_os_interval_ms);
+ }
+} asan_deactivated_flags;
+
+static bool asan_is_deactivated;
+
+void AsanDeactivate() {
+ CHECK(!asan_is_deactivated);
+ VReport(1, "Deactivating ASan\n");
+
+ // Stash runtime state.
+ GetAllocatorOptions(&asan_deactivated_flags.allocator_options);
+ asan_deactivated_flags.malloc_context_size = GetMallocContextSize();
+ asan_deactivated_flags.poison_heap = CanPoisonMemory();
+ asan_deactivated_flags.coverage = common_flags()->coverage;
+ asan_deactivated_flags.coverage_dir = common_flags()->coverage_dir;
+
+ // Deactivate the runtime.
+ SetCanPoisonMemory(false);
+ SetMallocContextSize(1);
+
+ AllocatorOptions disabled = asan_deactivated_flags.allocator_options;
+ disabled.quarantine_size_mb = 0;
+ disabled.thread_local_quarantine_size_kb = 0;
+ // Redzone must be at least Max(16, granularity) bytes long.
+ disabled.min_redzone = Max(16, (int)ASAN_SHADOW_GRANULARITY);
+ disabled.max_redzone = disabled.min_redzone;
+ disabled.alloc_dealloc_mismatch = false;
+ disabled.may_return_null = true;
+ ReInitializeAllocator(disabled);
+
+ asan_is_deactivated = true;
+}
+
+void AsanActivate() {
+ if (!asan_is_deactivated) return;
+ VReport(1, "Activating ASan\n");
+
+ UpdateProcessName();
+
+ asan_deactivated_flags.OverrideFromActivationFlags();
+
+ SetCanPoisonMemory(asan_deactivated_flags.poison_heap);
+ SetMallocContextSize(asan_deactivated_flags.malloc_context_size);
+ ReInitializeAllocator(asan_deactivated_flags.allocator_options);
+
+ asan_is_deactivated = false;
+ if (Verbosity()) {
+ Report("Activated with flags:\n");
+ asan_deactivated_flags.Print();
+ }
+}
+
+} // namespace __asan
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_activation.h b/contrib/libs/clang16-rt/lib/asan/asan_activation.h
new file mode 100644
index 00000000000..93c290c2ae2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_activation.h
@@ -0,0 +1,22 @@
+//===-- asan_activation.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan activation/deactivation logic.
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_ACTIVATION_H
+#define ASAN_ACTIVATION_H
+
+namespace __asan {
+void AsanDeactivate();
+void AsanActivate();
+} // namespace __asan
+
+#endif // ASAN_ACTIVATION_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_activation_flags.inc b/contrib/libs/clang16-rt/lib/asan/asan_activation_flags.inc
new file mode 100644
index 00000000000..e0fdffc82ac
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_activation_flags.inc
@@ -0,0 +1,36 @@
+//===-- asan_activation_flags.inc -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// A subset of ASan (and common) runtime flags supported at activation time.
+//
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_ACTIVATION_FLAG
+# error "Define ASAN_ACTIVATION_FLAG prior to including this file!"
+#endif
+
+#ifndef COMMON_ACTIVATION_FLAG
+# error "Define COMMON_ACTIVATION_FLAG prior to including this file!"
+#endif
+
+// ASAN_ACTIVATION_FLAG(Type, Name)
+// See COMMON_FLAG in sanitizer_flags.inc for more details.
+
+ASAN_ACTIVATION_FLAG(int, redzone)
+ASAN_ACTIVATION_FLAG(int, max_redzone)
+ASAN_ACTIVATION_FLAG(int, quarantine_size_mb)
+ASAN_ACTIVATION_FLAG(int, thread_local_quarantine_size_kb)
+ASAN_ACTIVATION_FLAG(bool, alloc_dealloc_mismatch)
+ASAN_ACTIVATION_FLAG(bool, poison_heap)
+
+COMMON_ACTIVATION_FLAG(bool, allocator_may_return_null)
+COMMON_ACTIVATION_FLAG(int, malloc_context_size)
+COMMON_ACTIVATION_FLAG(bool, coverage)
+COMMON_ACTIVATION_FLAG(const char *, coverage_dir)
+COMMON_ACTIVATION_FLAG(int, verbosity)
+COMMON_ACTIVATION_FLAG(bool, help)
+COMMON_ACTIVATION_FLAG(s32, allocator_release_to_os_interval_ms)
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_allocator.cpp b/contrib/libs/clang16-rt/lib/asan/asan_allocator.cpp
new file mode 100644
index 00000000000..74183fcd242
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_allocator.cpp
@@ -0,0 +1,1194 @@
+//===-- asan_allocator.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Implementation of ASan's memory allocator, 2-nd version.
+// This variant uses the allocator from sanitizer_common, i.e. the one shared
+// with ThreadSanitizer and MemorySanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "asan_allocator.h"
+
+#include "asan_mapping.h"
+#include "asan_poisoning.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "asan_thread.h"
+#include "lsan/lsan_common.h"
+#include "sanitizer_common/sanitizer_allocator_checks.h"
+#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_errno.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_list.h"
+#include "sanitizer_common/sanitizer_quarantine.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+namespace __asan {
+
+// Valid redzone sizes are 16, 32, 64, ... 2048, so we encode them in 3 bits.
+// We use adaptive redzones: for larger allocation larger redzones are used.
+static u32 RZLog2Size(u32 rz_log) {
+ CHECK_LT(rz_log, 8);
+ return 16 << rz_log;
+}
+
+static u32 RZSize2Log(u32 rz_size) {
+ CHECK_GE(rz_size, 16);
+ CHECK_LE(rz_size, 2048);
+ CHECK(IsPowerOfTwo(rz_size));
+ u32 res = Log2(rz_size) - 4;
+ CHECK_EQ(rz_size, RZLog2Size(res));
+ return res;
+}
+
+static AsanAllocator &get_allocator();
+
+static void AtomicContextStore(volatile atomic_uint64_t *atomic_context,
+ u32 tid, u32 stack) {
+ u64 context = tid;
+ context <<= 32;
+ context += stack;
+ atomic_store(atomic_context, context, memory_order_relaxed);
+}
+
+static void AtomicContextLoad(const volatile atomic_uint64_t *atomic_context,
+ u32 &tid, u32 &stack) {
+ u64 context = atomic_load(atomic_context, memory_order_relaxed);
+ stack = context;
+ context >>= 32;
+ tid = context;
+}
+
+// The memory chunk allocated from the underlying allocator looks like this:
+// L L L L L L H H U U U U U U R R
+// L -- left redzone words (0 or more bytes)
+// H -- ChunkHeader (16 bytes), which is also a part of the left redzone.
+// U -- user memory.
+// R -- right redzone (0 or more bytes)
+// ChunkBase consists of ChunkHeader and other bytes that overlap with user
+// memory.
+
+// If the left redzone is greater than the ChunkHeader size we store a magic
+// value in the first uptr word of the memory block and store the address of
+// ChunkBase in the next uptr.
+// M B L L L L L L L L L H H U U U U U U
+// | ^
+// ---------------------|
+// M -- magic value kAllocBegMagic
+// B -- address of ChunkHeader pointing to the first 'H'
+
+class ChunkHeader {
+ public:
+ atomic_uint8_t chunk_state;
+ u8 alloc_type : 2;
+ u8 lsan_tag : 2;
+
+ // align < 8 -> 0
+ // else -> log2(min(align, 512)) - 2
+ u8 user_requested_alignment_log : 3;
+
+ private:
+ u16 user_requested_size_hi;
+ u32 user_requested_size_lo;
+ atomic_uint64_t alloc_context_id;
+
+ public:
+ uptr UsedSize() const {
+ static_assert(sizeof(user_requested_size_lo) == 4,
+ "Expression below requires this");
+ return FIRST_32_SECOND_64(0, ((uptr)user_requested_size_hi << 32)) +
+ user_requested_size_lo;
+ }
+
+ void SetUsedSize(uptr size) {
+ user_requested_size_lo = size;
+ static_assert(sizeof(user_requested_size_lo) == 4,
+ "Expression below requires this");
+ user_requested_size_hi = FIRST_32_SECOND_64(0, size >> 32);
+ CHECK_EQ(UsedSize(), size);
+ }
+
+ void SetAllocContext(u32 tid, u32 stack) {
+ AtomicContextStore(&alloc_context_id, tid, stack);
+ }
+
+ void GetAllocContext(u32 &tid, u32 &stack) const {
+ AtomicContextLoad(&alloc_context_id, tid, stack);
+ }
+};
+
+class ChunkBase : public ChunkHeader {
+ atomic_uint64_t free_context_id;
+
+ public:
+ void SetFreeContext(u32 tid, u32 stack) {
+ AtomicContextStore(&free_context_id, tid, stack);
+ }
+
+ void GetFreeContext(u32 &tid, u32 &stack) const {
+ AtomicContextLoad(&free_context_id, tid, stack);
+ }
+};
+
+static const uptr kChunkHeaderSize = sizeof(ChunkHeader);
+static const uptr kChunkHeader2Size = sizeof(ChunkBase) - kChunkHeaderSize;
+COMPILER_CHECK(kChunkHeaderSize == 16);
+COMPILER_CHECK(kChunkHeader2Size <= 16);
+
+enum {
+ // Either just allocated by underlying allocator, but AsanChunk is not yet
+ // ready, or almost returned to undelying allocator and AsanChunk is already
+ // meaningless.
+ CHUNK_INVALID = 0,
+ // The chunk is allocated and not yet freed.
+ CHUNK_ALLOCATED = 2,
+ // The chunk was freed and put into quarantine zone.
+ CHUNK_QUARANTINE = 3,
+};
+
+class AsanChunk : public ChunkBase {
+ public:
+ uptr Beg() { return reinterpret_cast<uptr>(this) + kChunkHeaderSize; }
+ bool AddrIsInside(uptr addr) {
+ return (addr >= Beg()) && (addr < Beg() + UsedSize());
+ }
+};
+
+class LargeChunkHeader {
+ static constexpr uptr kAllocBegMagic =
+ FIRST_32_SECOND_64(0xCC6E96B9, 0xCC6E96B9CC6E96B9ULL);
+ atomic_uintptr_t magic;
+ AsanChunk *chunk_header;
+
+ public:
+ AsanChunk *Get() const {
+ return atomic_load(&magic, memory_order_acquire) == kAllocBegMagic
+ ? chunk_header
+ : nullptr;
+ }
+
+ void Set(AsanChunk *p) {
+ if (p) {
+ chunk_header = p;
+ atomic_store(&magic, kAllocBegMagic, memory_order_release);
+ return;
+ }
+
+ uptr old = kAllocBegMagic;
+ if (!atomic_compare_exchange_strong(&magic, &old, 0,
+ memory_order_release)) {
+ CHECK_EQ(old, kAllocBegMagic);
+ }
+ }
+};
+
+struct QuarantineCallback {
+ QuarantineCallback(AllocatorCache *cache, BufferedStackTrace *stack)
+ : cache_(cache),
+ stack_(stack) {
+ }
+
+ void Recycle(AsanChunk *m) {
+ void *p = get_allocator().GetBlockBegin(m);
+ if (p != m) {
+ // Clear the magic value, as allocator internals may overwrite the
+ // contents of deallocated chunk, confusing GetAsanChunk lookup.
+ reinterpret_cast<LargeChunkHeader *>(p)->Set(nullptr);
+ }
+
+ u8 old_chunk_state = CHUNK_QUARANTINE;
+ if (!atomic_compare_exchange_strong(&m->chunk_state, &old_chunk_state,
+ CHUNK_INVALID, memory_order_acquire)) {
+ CHECK_EQ(old_chunk_state, CHUNK_QUARANTINE);
+ }
+
+ PoisonShadow(m->Beg(), RoundUpTo(m->UsedSize(), ASAN_SHADOW_GRANULARITY),
+ kAsanHeapLeftRedzoneMagic);
+
+ // Statistics.
+ AsanStats &thread_stats = GetCurrentThreadStats();
+ thread_stats.real_frees++;
+ thread_stats.really_freed += m->UsedSize();
+
+ get_allocator().Deallocate(cache_, p);
+ }
+
+ void *Allocate(uptr size) {
+ void *res = get_allocator().Allocate(cache_, size, 1);
+ // TODO(alekseys): Consider making quarantine OOM-friendly.
+ if (UNLIKELY(!res))
+ ReportOutOfMemory(size, stack_);
+ return res;
+ }
+
+ void Deallocate(void *p) {
+ get_allocator().Deallocate(cache_, p);
+ }
+
+ private:
+ AllocatorCache* const cache_;
+ BufferedStackTrace* const stack_;
+};
+
+typedef Quarantine<QuarantineCallback, AsanChunk> AsanQuarantine;
+typedef AsanQuarantine::Cache QuarantineCache;
+
+void AsanMapUnmapCallback::OnMap(uptr p, uptr size) const {
+ PoisonShadow(p, size, kAsanHeapLeftRedzoneMagic);
+ // Statistics.
+ AsanStats &thread_stats = GetCurrentThreadStats();
+ thread_stats.mmaps++;
+ thread_stats.mmaped += size;
+}
+void AsanMapUnmapCallback::OnUnmap(uptr p, uptr size) const {
+ PoisonShadow(p, size, 0);
+ // We are about to unmap a chunk of user memory.
+ // Mark the corresponding shadow memory as not needed.
+ FlushUnneededASanShadowMemory(p, size);
+ // Statistics.
+ AsanStats &thread_stats = GetCurrentThreadStats();
+ thread_stats.munmaps++;
+ thread_stats.munmaped += size;
+}
+
+// We can not use THREADLOCAL because it is not supported on some of the
+// platforms we care about (OSX 10.6, Android).
+// static THREADLOCAL AllocatorCache cache;
+AllocatorCache *GetAllocatorCache(AsanThreadLocalMallocStorage *ms) {
+ CHECK(ms);
+ return &ms->allocator_cache;
+}
+
+QuarantineCache *GetQuarantineCache(AsanThreadLocalMallocStorage *ms) {
+ CHECK(ms);
+ CHECK_LE(sizeof(QuarantineCache), sizeof(ms->quarantine_cache));
+ return reinterpret_cast<QuarantineCache *>(ms->quarantine_cache);
+}
+
+void AllocatorOptions::SetFrom(const Flags *f, const CommonFlags *cf) {
+ quarantine_size_mb = f->quarantine_size_mb;
+ thread_local_quarantine_size_kb = f->thread_local_quarantine_size_kb;
+ min_redzone = f->redzone;
+ max_redzone = f->max_redzone;
+ may_return_null = cf->allocator_may_return_null;
+ alloc_dealloc_mismatch = f->alloc_dealloc_mismatch;
+ release_to_os_interval_ms = cf->allocator_release_to_os_interval_ms;
+}
+
+void AllocatorOptions::CopyTo(Flags *f, CommonFlags *cf) {
+ f->quarantine_size_mb = quarantine_size_mb;
+ f->thread_local_quarantine_size_kb = thread_local_quarantine_size_kb;
+ f->redzone = min_redzone;
+ f->max_redzone = max_redzone;
+ cf->allocator_may_return_null = may_return_null;
+ f->alloc_dealloc_mismatch = alloc_dealloc_mismatch;
+ cf->allocator_release_to_os_interval_ms = release_to_os_interval_ms;
+}
+
+struct Allocator {
+ static const uptr kMaxAllowedMallocSize =
+ FIRST_32_SECOND_64(3UL << 30, 1ULL << 40);
+
+ AsanAllocator allocator;
+ AsanQuarantine quarantine;
+ StaticSpinMutex fallback_mutex;
+ AllocatorCache fallback_allocator_cache;
+ QuarantineCache fallback_quarantine_cache;
+
+ uptr max_user_defined_malloc_size;
+
+ // ------------------- Options --------------------------
+ atomic_uint16_t min_redzone;
+ atomic_uint16_t max_redzone;
+ atomic_uint8_t alloc_dealloc_mismatch;
+
+ // ------------------- Initialization ------------------------
+ explicit Allocator(LinkerInitialized)
+ : quarantine(LINKER_INITIALIZED),
+ fallback_quarantine_cache(LINKER_INITIALIZED) {}
+
+ void CheckOptions(const AllocatorOptions &options) const {
+ CHECK_GE(options.min_redzone, 16);
+ CHECK_GE(options.max_redzone, options.min_redzone);
+ CHECK_LE(options.max_redzone, 2048);
+ CHECK(IsPowerOfTwo(options.min_redzone));
+ CHECK(IsPowerOfTwo(options.max_redzone));
+ }
+
+ void SharedInitCode(const AllocatorOptions &options) {
+ CheckOptions(options);
+ quarantine.Init((uptr)options.quarantine_size_mb << 20,
+ (uptr)options.thread_local_quarantine_size_kb << 10);
+ atomic_store(&alloc_dealloc_mismatch, options.alloc_dealloc_mismatch,
+ memory_order_release);
+ atomic_store(&min_redzone, options.min_redzone, memory_order_release);
+ atomic_store(&max_redzone, options.max_redzone, memory_order_release);
+ }
+
+ void InitLinkerInitialized(const AllocatorOptions &options) {
+ SetAllocatorMayReturnNull(options.may_return_null);
+ allocator.InitLinkerInitialized(options.release_to_os_interval_ms);
+ SharedInitCode(options);
+ max_user_defined_malloc_size = common_flags()->max_allocation_size_mb
+ ? common_flags()->max_allocation_size_mb
+ << 20
+ : kMaxAllowedMallocSize;
+ }
+
+ void RePoisonChunk(uptr chunk) {
+ // This could be a user-facing chunk (with redzones), or some internal
+ // housekeeping chunk, like TransferBatch. Start by assuming the former.
+ AsanChunk *ac = GetAsanChunk((void *)chunk);
+ uptr allocated_size = allocator.GetActuallyAllocatedSize((void *)chunk);
+ if (ac && atomic_load(&ac->chunk_state, memory_order_acquire) ==
+ CHUNK_ALLOCATED) {
+ uptr beg = ac->Beg();
+ uptr end = ac->Beg() + ac->UsedSize();
+ uptr chunk_end = chunk + allocated_size;
+ if (chunk < beg && beg < end && end <= chunk_end) {
+ // Looks like a valid AsanChunk in use, poison redzones only.
+ PoisonShadow(chunk, beg - chunk, kAsanHeapLeftRedzoneMagic);
+ uptr end_aligned_down = RoundDownTo(end, ASAN_SHADOW_GRANULARITY);
+ FastPoisonShadowPartialRightRedzone(
+ end_aligned_down, end - end_aligned_down,
+ chunk_end - end_aligned_down, kAsanHeapLeftRedzoneMagic);
+ return;
+ }
+ }
+
+ // This is either not an AsanChunk or freed or quarantined AsanChunk.
+ // In either case, poison everything.
+ PoisonShadow(chunk, allocated_size, kAsanHeapLeftRedzoneMagic);
+ }
+
+ void ReInitialize(const AllocatorOptions &options) {
+ SetAllocatorMayReturnNull(options.may_return_null);
+ allocator.SetReleaseToOSIntervalMs(options.release_to_os_interval_ms);
+ SharedInitCode(options);
+
+ // Poison all existing allocation's redzones.
+ if (CanPoisonMemory()) {
+ allocator.ForceLock();
+ allocator.ForEachChunk(
+ [](uptr chunk, void *alloc) {
+ ((Allocator *)alloc)->RePoisonChunk(chunk);
+ },
+ this);
+ allocator.ForceUnlock();
+ }
+ }
+
+ void GetOptions(AllocatorOptions *options) const {
+ options->quarantine_size_mb = quarantine.GetSize() >> 20;
+ options->thread_local_quarantine_size_kb = quarantine.GetCacheSize() >> 10;
+ options->min_redzone = atomic_load(&min_redzone, memory_order_acquire);
+ options->max_redzone = atomic_load(&max_redzone, memory_order_acquire);
+ options->may_return_null = AllocatorMayReturnNull();
+ options->alloc_dealloc_mismatch =
+ atomic_load(&alloc_dealloc_mismatch, memory_order_acquire);
+ options->release_to_os_interval_ms = allocator.ReleaseToOSIntervalMs();
+ }
+
+ // -------------------- Helper methods. -------------------------
+ uptr ComputeRZLog(uptr user_requested_size) {
+ u32 rz_log = user_requested_size <= 64 - 16 ? 0
+ : user_requested_size <= 128 - 32 ? 1
+ : user_requested_size <= 512 - 64 ? 2
+ : user_requested_size <= 4096 - 128 ? 3
+ : user_requested_size <= (1 << 14) - 256 ? 4
+ : user_requested_size <= (1 << 15) - 512 ? 5
+ : user_requested_size <= (1 << 16) - 1024 ? 6
+ : 7;
+ u32 hdr_log = RZSize2Log(RoundUpToPowerOfTwo(sizeof(ChunkHeader)));
+ u32 min_log = RZSize2Log(atomic_load(&min_redzone, memory_order_acquire));
+ u32 max_log = RZSize2Log(atomic_load(&max_redzone, memory_order_acquire));
+ return Min(Max(rz_log, Max(min_log, hdr_log)), Max(max_log, hdr_log));
+ }
+
+ static uptr ComputeUserRequestedAlignmentLog(uptr user_requested_alignment) {
+ if (user_requested_alignment < 8)
+ return 0;
+ if (user_requested_alignment > 512)
+ user_requested_alignment = 512;
+ return Log2(user_requested_alignment) - 2;
+ }
+
+ static uptr ComputeUserAlignment(uptr user_requested_alignment_log) {
+ if (user_requested_alignment_log == 0)
+ return 0;
+ return 1LL << (user_requested_alignment_log + 2);
+ }
+
+ // We have an address between two chunks, and we want to report just one.
+ AsanChunk *ChooseChunk(uptr addr, AsanChunk *left_chunk,
+ AsanChunk *right_chunk) {
+ if (!left_chunk)
+ return right_chunk;
+ if (!right_chunk)
+ return left_chunk;
+ // Prefer an allocated chunk over freed chunk and freed chunk
+ // over available chunk.
+ u8 left_state = atomic_load(&left_chunk->chunk_state, memory_order_relaxed);
+ u8 right_state =
+ atomic_load(&right_chunk->chunk_state, memory_order_relaxed);
+ if (left_state != right_state) {
+ if (left_state == CHUNK_ALLOCATED)
+ return left_chunk;
+ if (right_state == CHUNK_ALLOCATED)
+ return right_chunk;
+ if (left_state == CHUNK_QUARANTINE)
+ return left_chunk;
+ if (right_state == CHUNK_QUARANTINE)
+ return right_chunk;
+ }
+ // Same chunk_state: choose based on offset.
+ sptr l_offset = 0, r_offset = 0;
+ CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset));
+ CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset));
+ if (l_offset < r_offset)
+ return left_chunk;
+ return right_chunk;
+ }
+
+ bool UpdateAllocationStack(uptr addr, BufferedStackTrace *stack) {
+ AsanChunk *m = GetAsanChunkByAddr(addr);
+ if (!m) return false;
+ if (atomic_load(&m->chunk_state, memory_order_acquire) != CHUNK_ALLOCATED)
+ return false;
+ if (m->Beg() != addr) return false;
+ AsanThread *t = GetCurrentThread();
+ m->SetAllocContext(t ? t->tid() : kMainTid, StackDepotPut(*stack));
+ return true;
+ }
+
+ // -------------------- Allocation/Deallocation routines ---------------
+ void *Allocate(uptr size, uptr alignment, BufferedStackTrace *stack,
+ AllocType alloc_type, bool can_fill) {
+ if (UNLIKELY(!asan_inited))
+ AsanInitFromRtl();
+ if (UNLIKELY(IsRssLimitExceeded())) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportRssLimitExceeded(stack);
+ }
+ Flags &fl = *flags();
+ CHECK(stack);
+ const uptr min_alignment = ASAN_SHADOW_GRANULARITY;
+ const uptr user_requested_alignment_log =
+ ComputeUserRequestedAlignmentLog(alignment);
+ if (alignment < min_alignment)
+ alignment = min_alignment;
+ if (size == 0) {
+ // We'd be happy to avoid allocating memory for zero-size requests, but
+ // some programs/tests depend on this behavior and assume that malloc
+ // would not return NULL even for zero-size allocations. Moreover, it
+ // looks like operator new should never return NULL, and results of
+ // consecutive "new" calls must be different even if the allocated size
+ // is zero.
+ size = 1;
+ }
+ CHECK(IsPowerOfTwo(alignment));
+ uptr rz_log = ComputeRZLog(size);
+ uptr rz_size = RZLog2Size(rz_log);
+ uptr rounded_size = RoundUpTo(Max(size, kChunkHeader2Size), alignment);
+ uptr needed_size = rounded_size + rz_size;
+ if (alignment > min_alignment)
+ needed_size += alignment;
+ // If we are allocating from the secondary allocator, there will be no
+ // automatic right redzone, so add the right redzone manually.
+ if (!PrimaryAllocator::CanAllocate(needed_size, alignment))
+ needed_size += rz_size;
+ CHECK(IsAligned(needed_size, min_alignment));
+ if (size > kMaxAllowedMallocSize || needed_size > kMaxAllowedMallocSize ||
+ size > max_user_defined_malloc_size) {
+ if (AllocatorMayReturnNull()) {
+ Report("WARNING: AddressSanitizer failed to allocate 0x%zx bytes\n",
+ size);
+ return nullptr;
+ }
+ uptr malloc_limit =
+ Min(kMaxAllowedMallocSize, max_user_defined_malloc_size);
+ ReportAllocationSizeTooBig(size, needed_size, malloc_limit, stack);
+ }
+
+ AsanThread *t = GetCurrentThread();
+ void *allocated;
+ if (t) {
+ AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
+ allocated = allocator.Allocate(cache, needed_size, 8);
+ } else {
+ SpinMutexLock l(&fallback_mutex);
+ AllocatorCache *cache = &fallback_allocator_cache;
+ allocated = allocator.Allocate(cache, needed_size, 8);
+ }
+ if (UNLIKELY(!allocated)) {
+ SetAllocatorOutOfMemory();
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportOutOfMemory(size, stack);
+ }
+
+ if (*(u8 *)MEM_TO_SHADOW((uptr)allocated) == 0 && CanPoisonMemory()) {
+ // Heap poisoning is enabled, but the allocator provides an unpoisoned
+ // chunk. This is possible if CanPoisonMemory() was false for some
+ // time, for example, due to flags()->start_disabled.
+ // Anyway, poison the block before using it for anything else.
+ uptr allocated_size = allocator.GetActuallyAllocatedSize(allocated);
+ PoisonShadow((uptr)allocated, allocated_size, kAsanHeapLeftRedzoneMagic);
+ }
+
+ uptr alloc_beg = reinterpret_cast<uptr>(allocated);
+ uptr alloc_end = alloc_beg + needed_size;
+ uptr user_beg = alloc_beg + rz_size;
+ if (!IsAligned(user_beg, alignment))
+ user_beg = RoundUpTo(user_beg, alignment);
+ uptr user_end = user_beg + size;
+ CHECK_LE(user_end, alloc_end);
+ uptr chunk_beg = user_beg - kChunkHeaderSize;
+ AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
+ m->alloc_type = alloc_type;
+ CHECK(size);
+ m->SetUsedSize(size);
+ m->user_requested_alignment_log = user_requested_alignment_log;
+
+ m->SetAllocContext(t ? t->tid() : kMainTid, StackDepotPut(*stack));
+
+ uptr size_rounded_down_to_granularity =
+ RoundDownTo(size, ASAN_SHADOW_GRANULARITY);
+ // Unpoison the bulk of the memory region.
+ if (size_rounded_down_to_granularity)
+ PoisonShadow(user_beg, size_rounded_down_to_granularity, 0);
+ // Deal with the end of the region if size is not aligned to granularity.
+ if (size != size_rounded_down_to_granularity && CanPoisonMemory()) {
+ u8 *shadow =
+ (u8 *)MemToShadow(user_beg + size_rounded_down_to_granularity);
+ *shadow = fl.poison_partial ? (size & (ASAN_SHADOW_GRANULARITY - 1)) : 0;
+ }
+
+ AsanStats &thread_stats = GetCurrentThreadStats();
+ thread_stats.mallocs++;
+ thread_stats.malloced += size;
+ thread_stats.malloced_redzones += needed_size - size;
+ if (needed_size > SizeClassMap::kMaxSize)
+ thread_stats.malloc_large++;
+ else
+ thread_stats.malloced_by_size[SizeClassMap::ClassID(needed_size)]++;
+
+ void *res = reinterpret_cast<void *>(user_beg);
+ if (can_fill && fl.max_malloc_fill_size) {
+ uptr fill_size = Min(size, (uptr)fl.max_malloc_fill_size);
+ REAL(memset)(res, fl.malloc_fill_byte, fill_size);
+ }
+#if CAN_SANITIZE_LEAKS
+ m->lsan_tag = __lsan::DisabledInThisThread() ? __lsan::kIgnored
+ : __lsan::kDirectlyLeaked;
+#endif
+ // Must be the last mutation of metadata in this function.
+ atomic_store(&m->chunk_state, CHUNK_ALLOCATED, memory_order_release);
+ if (alloc_beg != chunk_beg) {
+ CHECK_LE(alloc_beg + sizeof(LargeChunkHeader), chunk_beg);
+ reinterpret_cast<LargeChunkHeader *>(alloc_beg)->Set(m);
+ }
+ RunMallocHooks(res, size);
+ return res;
+ }
+
+ // Set quarantine flag if chunk is allocated, issue ASan error report on
+ // available and quarantined chunks. Return true on success, false otherwise.
+ bool AtomicallySetQuarantineFlagIfAllocated(AsanChunk *m, void *ptr,
+ BufferedStackTrace *stack) {
+ u8 old_chunk_state = CHUNK_ALLOCATED;
+ // Flip the chunk_state atomically to avoid race on double-free.
+ if (!atomic_compare_exchange_strong(&m->chunk_state, &old_chunk_state,
+ CHUNK_QUARANTINE,
+ memory_order_acquire)) {
+ ReportInvalidFree(ptr, old_chunk_state, stack);
+ // It's not safe to push a chunk in quarantine on invalid free.
+ return false;
+ }
+ CHECK_EQ(CHUNK_ALLOCATED, old_chunk_state);
+ // It was a user data.
+ m->SetFreeContext(kInvalidTid, 0);
+ return true;
+ }
+
+ // Expects the chunk to already be marked as quarantined by using
+ // AtomicallySetQuarantineFlagIfAllocated.
+ void QuarantineChunk(AsanChunk *m, void *ptr, BufferedStackTrace *stack) {
+ CHECK_EQ(atomic_load(&m->chunk_state, memory_order_relaxed),
+ CHUNK_QUARANTINE);
+ AsanThread *t = GetCurrentThread();
+ m->SetFreeContext(t ? t->tid() : 0, StackDepotPut(*stack));
+
+ Flags &fl = *flags();
+ if (fl.max_free_fill_size > 0) {
+ // We have to skip the chunk header, it contains free_context_id.
+ uptr scribble_start = (uptr)m + kChunkHeaderSize + kChunkHeader2Size;
+ if (m->UsedSize() >= kChunkHeader2Size) { // Skip Header2 in user area.
+ uptr size_to_fill = m->UsedSize() - kChunkHeader2Size;
+ size_to_fill = Min(size_to_fill, (uptr)fl.max_free_fill_size);
+ REAL(memset)((void *)scribble_start, fl.free_fill_byte, size_to_fill);
+ }
+ }
+
+ // Poison the region.
+ PoisonShadow(m->Beg(), RoundUpTo(m->UsedSize(), ASAN_SHADOW_GRANULARITY),
+ kAsanHeapFreeMagic);
+
+ AsanStats &thread_stats = GetCurrentThreadStats();
+ thread_stats.frees++;
+ thread_stats.freed += m->UsedSize();
+
+ // Push into quarantine.
+ if (t) {
+ AsanThreadLocalMallocStorage *ms = &t->malloc_storage();
+ AllocatorCache *ac = GetAllocatorCache(ms);
+ quarantine.Put(GetQuarantineCache(ms), QuarantineCallback(ac, stack), m,
+ m->UsedSize());
+ } else {
+ SpinMutexLock l(&fallback_mutex);
+ AllocatorCache *ac = &fallback_allocator_cache;
+ quarantine.Put(&fallback_quarantine_cache, QuarantineCallback(ac, stack),
+ m, m->UsedSize());
+ }
+ }
+
+ void Deallocate(void *ptr, uptr delete_size, uptr delete_alignment,
+ BufferedStackTrace *stack, AllocType alloc_type) {
+ uptr p = reinterpret_cast<uptr>(ptr);
+ if (p == 0) return;
+
+ uptr chunk_beg = p - kChunkHeaderSize;
+ AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
+
+ // On Windows, uninstrumented DLLs may allocate memory before ASan hooks
+ // malloc. Don't report an invalid free in this case.
+ if (SANITIZER_WINDOWS &&
+ !get_allocator().PointerIsMine(ptr)) {
+ if (!IsSystemHeapAddress(p))
+ ReportFreeNotMalloced(p, stack);
+ return;
+ }
+
+ RunFreeHooks(ptr);
+
+ // Must mark the chunk as quarantined before any changes to its metadata.
+ // Do not quarantine given chunk if we failed to set CHUNK_QUARANTINE flag.
+ if (!AtomicallySetQuarantineFlagIfAllocated(m, ptr, stack)) return;
+
+ if (m->alloc_type != alloc_type) {
+ if (atomic_load(&alloc_dealloc_mismatch, memory_order_acquire)) {
+ ReportAllocTypeMismatch((uptr)ptr, stack, (AllocType)m->alloc_type,
+ (AllocType)alloc_type);
+ }
+ } else {
+ if (flags()->new_delete_type_mismatch &&
+ (alloc_type == FROM_NEW || alloc_type == FROM_NEW_BR) &&
+ ((delete_size && delete_size != m->UsedSize()) ||
+ ComputeUserRequestedAlignmentLog(delete_alignment) !=
+ m->user_requested_alignment_log)) {
+ ReportNewDeleteTypeMismatch(p, delete_size, delete_alignment, stack);
+ }
+ }
+
+ QuarantineChunk(m, ptr, stack);
+ }
+
+ void *Reallocate(void *old_ptr, uptr new_size, BufferedStackTrace *stack) {
+ CHECK(old_ptr && new_size);
+ uptr p = reinterpret_cast<uptr>(old_ptr);
+ uptr chunk_beg = p - kChunkHeaderSize;
+ AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
+
+ AsanStats &thread_stats = GetCurrentThreadStats();
+ thread_stats.reallocs++;
+ thread_stats.realloced += new_size;
+
+ void *new_ptr = Allocate(new_size, 8, stack, FROM_MALLOC, true);
+ if (new_ptr) {
+ u8 chunk_state = atomic_load(&m->chunk_state, memory_order_acquire);
+ if (chunk_state != CHUNK_ALLOCATED)
+ ReportInvalidFree(old_ptr, chunk_state, stack);
+ CHECK_NE(REAL(memcpy), nullptr);
+ uptr memcpy_size = Min(new_size, m->UsedSize());
+ // If realloc() races with free(), we may start copying freed memory.
+ // However, we will report racy double-free later anyway.
+ REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
+ Deallocate(old_ptr, 0, 0, stack, FROM_MALLOC);
+ }
+ return new_ptr;
+ }
+
+ void *Calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) {
+ if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportCallocOverflow(nmemb, size, stack);
+ }
+ void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC, false);
+ // If the memory comes from the secondary allocator no need to clear it
+ // as it comes directly from mmap.
+ if (ptr && allocator.FromPrimary(ptr))
+ REAL(memset)(ptr, 0, nmemb * size);
+ return ptr;
+ }
+
+ void ReportInvalidFree(void *ptr, u8 chunk_state, BufferedStackTrace *stack) {
+ if (chunk_state == CHUNK_QUARANTINE)
+ ReportDoubleFree((uptr)ptr, stack);
+ else
+ ReportFreeNotMalloced((uptr)ptr, stack);
+ }
+
+ void CommitBack(AsanThreadLocalMallocStorage *ms, BufferedStackTrace *stack) {
+ AllocatorCache *ac = GetAllocatorCache(ms);
+ quarantine.Drain(GetQuarantineCache(ms), QuarantineCallback(ac, stack));
+ allocator.SwallowCache(ac);
+ }
+
+ // -------------------------- Chunk lookup ----------------------
+
+ // Assumes alloc_beg == allocator.GetBlockBegin(alloc_beg).
+ // Returns nullptr if AsanChunk is not yet initialized just after
+ // get_allocator().Allocate(), or is being destroyed just before
+ // get_allocator().Deallocate().
+ AsanChunk *GetAsanChunk(void *alloc_beg) {
+ if (!alloc_beg)
+ return nullptr;
+ AsanChunk *p = reinterpret_cast<LargeChunkHeader *>(alloc_beg)->Get();
+ if (!p) {
+ if (!allocator.FromPrimary(alloc_beg))
+ return nullptr;
+ p = reinterpret_cast<AsanChunk *>(alloc_beg);
+ }
+ u8 state = atomic_load(&p->chunk_state, memory_order_relaxed);
+ // It does not guaranty that Chunk is initialized, but it's
+ // definitely not for any other value.
+ if (state == CHUNK_ALLOCATED || state == CHUNK_QUARANTINE)
+ return p;
+ return nullptr;
+ }
+
+ AsanChunk *GetAsanChunkByAddr(uptr p) {
+ void *alloc_beg = allocator.GetBlockBegin(reinterpret_cast<void *>(p));
+ return GetAsanChunk(alloc_beg);
+ }
+
+ // Allocator must be locked when this function is called.
+ AsanChunk *GetAsanChunkByAddrFastLocked(uptr p) {
+ void *alloc_beg =
+ allocator.GetBlockBeginFastLocked(reinterpret_cast<void *>(p));
+ return GetAsanChunk(alloc_beg);
+ }
+
+ uptr AllocationSize(uptr p) {
+ AsanChunk *m = GetAsanChunkByAddr(p);
+ if (!m) return 0;
+ if (atomic_load(&m->chunk_state, memory_order_acquire) != CHUNK_ALLOCATED)
+ return 0;
+ if (m->Beg() != p) return 0;
+ return m->UsedSize();
+ }
+
+ AsanChunkView FindHeapChunkByAddress(uptr addr) {
+ AsanChunk *m1 = GetAsanChunkByAddr(addr);
+ sptr offset = 0;
+ if (!m1 || AsanChunkView(m1).AddrIsAtLeft(addr, 1, &offset)) {
+ // The address is in the chunk's left redzone, so maybe it is actually
+ // a right buffer overflow from the other chunk before.
+ // Search a bit before to see if there is another chunk.
+ AsanChunk *m2 = nullptr;
+ for (uptr l = 1; l < GetPageSizeCached(); l++) {
+ m2 = GetAsanChunkByAddr(addr - l);
+ if (m2 == m1) continue; // Still the same chunk.
+ break;
+ }
+ if (m2 && AsanChunkView(m2).AddrIsAtRight(addr, 1, &offset))
+ m1 = ChooseChunk(addr, m2, m1);
+ }
+ return AsanChunkView(m1);
+ }
+
+ void Purge(BufferedStackTrace *stack) {
+ AsanThread *t = GetCurrentThread();
+ if (t) {
+ AsanThreadLocalMallocStorage *ms = &t->malloc_storage();
+ quarantine.DrainAndRecycle(GetQuarantineCache(ms),
+ QuarantineCallback(GetAllocatorCache(ms),
+ stack));
+ }
+ {
+ SpinMutexLock l(&fallback_mutex);
+ quarantine.DrainAndRecycle(&fallback_quarantine_cache,
+ QuarantineCallback(&fallback_allocator_cache,
+ stack));
+ }
+
+ allocator.ForceReleaseToOS();
+ }
+
+ void PrintStats() {
+ allocator.PrintStats();
+ quarantine.PrintStats();
+ }
+
+ void ForceLock() SANITIZER_ACQUIRE(fallback_mutex) {
+ allocator.ForceLock();
+ fallback_mutex.Lock();
+ }
+
+ void ForceUnlock() SANITIZER_RELEASE(fallback_mutex) {
+ fallback_mutex.Unlock();
+ allocator.ForceUnlock();
+ }
+};
+
+static Allocator instance(LINKER_INITIALIZED);
+
+static AsanAllocator &get_allocator() {
+ return instance.allocator;
+}
+
+bool AsanChunkView::IsValid() const {
+ return chunk_ && atomic_load(&chunk_->chunk_state, memory_order_relaxed) !=
+ CHUNK_INVALID;
+}
+bool AsanChunkView::IsAllocated() const {
+ return chunk_ && atomic_load(&chunk_->chunk_state, memory_order_relaxed) ==
+ CHUNK_ALLOCATED;
+}
+bool AsanChunkView::IsQuarantined() const {
+ return chunk_ && atomic_load(&chunk_->chunk_state, memory_order_relaxed) ==
+ CHUNK_QUARANTINE;
+}
+uptr AsanChunkView::Beg() const { return chunk_->Beg(); }
+uptr AsanChunkView::End() const { return Beg() + UsedSize(); }
+uptr AsanChunkView::UsedSize() const { return chunk_->UsedSize(); }
+u32 AsanChunkView::UserRequestedAlignment() const {
+ return Allocator::ComputeUserAlignment(chunk_->user_requested_alignment_log);
+}
+
+uptr AsanChunkView::AllocTid() const {
+ u32 tid = 0;
+ u32 stack = 0;
+ chunk_->GetAllocContext(tid, stack);
+ return tid;
+}
+
+uptr AsanChunkView::FreeTid() const {
+ if (!IsQuarantined())
+ return kInvalidTid;
+ u32 tid = 0;
+ u32 stack = 0;
+ chunk_->GetFreeContext(tid, stack);
+ return tid;
+}
+
+AllocType AsanChunkView::GetAllocType() const {
+ return (AllocType)chunk_->alloc_type;
+}
+
+u32 AsanChunkView::GetAllocStackId() const {
+ u32 tid = 0;
+ u32 stack = 0;
+ chunk_->GetAllocContext(tid, stack);
+ return stack;
+}
+
+u32 AsanChunkView::GetFreeStackId() const {
+ if (!IsQuarantined())
+ return 0;
+ u32 tid = 0;
+ u32 stack = 0;
+ chunk_->GetFreeContext(tid, stack);
+ return stack;
+}
+
+void InitializeAllocator(const AllocatorOptions &options) {
+ instance.InitLinkerInitialized(options);
+}
+
+void ReInitializeAllocator(const AllocatorOptions &options) {
+ instance.ReInitialize(options);
+}
+
+void GetAllocatorOptions(AllocatorOptions *options) {
+ instance.GetOptions(options);
+}
+
+AsanChunkView FindHeapChunkByAddress(uptr addr) {
+ return instance.FindHeapChunkByAddress(addr);
+}
+AsanChunkView FindHeapChunkByAllocBeg(uptr addr) {
+ return AsanChunkView(instance.GetAsanChunk(reinterpret_cast<void*>(addr)));
+}
+
+void AsanThreadLocalMallocStorage::CommitBack() {
+ GET_STACK_TRACE_MALLOC;
+ instance.CommitBack(this, &stack);
+}
+
+void PrintInternalAllocatorStats() {
+ instance.PrintStats();
+}
+
+void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type) {
+ instance.Deallocate(ptr, 0, 0, stack, alloc_type);
+}
+
+void asan_delete(void *ptr, uptr size, uptr alignment,
+ BufferedStackTrace *stack, AllocType alloc_type) {
+ instance.Deallocate(ptr, size, alignment, stack, alloc_type);
+}
+
+void *asan_malloc(uptr size, BufferedStackTrace *stack) {
+ return SetErrnoOnNull(instance.Allocate(size, 8, stack, FROM_MALLOC, true));
+}
+
+void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) {
+ return SetErrnoOnNull(instance.Calloc(nmemb, size, stack));
+}
+
+void *asan_reallocarray(void *p, uptr nmemb, uptr size,
+ BufferedStackTrace *stack) {
+ if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+ errno = errno_ENOMEM;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportReallocArrayOverflow(nmemb, size, stack);
+ }
+ return asan_realloc(p, nmemb * size, stack);
+}
+
+void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack) {
+ if (!p)
+ return SetErrnoOnNull(instance.Allocate(size, 8, stack, FROM_MALLOC, true));
+ if (size == 0) {
+ if (flags()->allocator_frees_and_returns_null_on_realloc_zero) {
+ instance.Deallocate(p, 0, 0, stack, FROM_MALLOC);
+ return nullptr;
+ }
+ // Allocate a size of 1 if we shouldn't free() on Realloc to 0
+ size = 1;
+ }
+ return SetErrnoOnNull(instance.Reallocate(p, size, stack));
+}
+
+void *asan_valloc(uptr size, BufferedStackTrace *stack) {
+ return SetErrnoOnNull(
+ instance.Allocate(size, GetPageSizeCached(), stack, FROM_MALLOC, true));
+}
+
+void *asan_pvalloc(uptr size, BufferedStackTrace *stack) {
+ uptr PageSize = GetPageSizeCached();
+ if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) {
+ errno = errno_ENOMEM;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportPvallocOverflow(size, stack);
+ }
+ // pvalloc(0) should allocate one page.
+ size = size ? RoundUpTo(size, PageSize) : PageSize;
+ return SetErrnoOnNull(
+ instance.Allocate(size, PageSize, stack, FROM_MALLOC, true));
+}
+
+void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack,
+ AllocType alloc_type) {
+ if (UNLIKELY(!IsPowerOfTwo(alignment))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAllocationAlignment(alignment, stack);
+ }
+ return SetErrnoOnNull(
+ instance.Allocate(size, alignment, stack, alloc_type, true));
+}
+
+void *asan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack) {
+ if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAlignedAllocAlignment(size, alignment, stack);
+ }
+ return SetErrnoOnNull(
+ instance.Allocate(size, alignment, stack, FROM_MALLOC, true));
+}
+
+int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
+ BufferedStackTrace *stack) {
+ if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
+ if (AllocatorMayReturnNull())
+ return errno_EINVAL;
+ ReportInvalidPosixMemalignAlignment(alignment, stack);
+ }
+ void *ptr = instance.Allocate(size, alignment, stack, FROM_MALLOC, true);
+ if (UNLIKELY(!ptr))
+ // OOM error is already taken care of by Allocate.
+ return errno_ENOMEM;
+ CHECK(IsAligned((uptr)ptr, alignment));
+ *memptr = ptr;
+ return 0;
+}
+
+uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp) {
+ if (!ptr) return 0;
+ uptr usable_size = instance.AllocationSize(reinterpret_cast<uptr>(ptr));
+ if (flags()->check_malloc_usable_size && (usable_size == 0)) {
+ GET_STACK_TRACE_FATAL(pc, bp);
+ ReportMallocUsableSizeNotOwned((uptr)ptr, &stack);
+ }
+ return usable_size;
+}
+
+uptr asan_mz_size(const void *ptr) {
+ return instance.AllocationSize(reinterpret_cast<uptr>(ptr));
+}
+
+void asan_mz_force_lock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ instance.ForceLock();
+}
+
+void asan_mz_force_unlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ instance.ForceUnlock();
+}
+
+} // namespace __asan
+
+// --- Implementation of LSan-specific functions --- {{{1
+namespace __lsan {
+void LockAllocator() {
+ __asan::get_allocator().ForceLock();
+}
+
+void UnlockAllocator() {
+ __asan::get_allocator().ForceUnlock();
+}
+
+void GetAllocatorGlobalRange(uptr *begin, uptr *end) {
+ *begin = (uptr)&__asan::get_allocator();
+ *end = *begin + sizeof(__asan::get_allocator());
+}
+
+uptr PointsIntoChunk(void *p) {
+ uptr addr = reinterpret_cast<uptr>(p);
+ __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddrFastLocked(addr);
+ if (!m || atomic_load(&m->chunk_state, memory_order_acquire) !=
+ __asan::CHUNK_ALLOCATED)
+ return 0;
+ uptr chunk = m->Beg();
+ if (m->AddrIsInside(addr))
+ return chunk;
+ if (IsSpecialCaseOfOperatorNew0(chunk, m->UsedSize(), addr))
+ return chunk;
+ return 0;
+}
+
+uptr GetUserBegin(uptr chunk) {
+ // FIXME: All usecases provide chunk address, GetAsanChunkByAddrFastLocked is
+ // not needed.
+ __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddrFastLocked(chunk);
+ return m ? m->Beg() : 0;
+}
+
+LsanMetadata::LsanMetadata(uptr chunk) {
+ metadata_ = chunk ? reinterpret_cast<void *>(chunk - __asan::kChunkHeaderSize)
+ : nullptr;
+}
+
+bool LsanMetadata::allocated() const {
+ if (!metadata_)
+ return false;
+ __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
+ return atomic_load(&m->chunk_state, memory_order_relaxed) ==
+ __asan::CHUNK_ALLOCATED;
+}
+
+ChunkTag LsanMetadata::tag() const {
+ __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
+ return static_cast<ChunkTag>(m->lsan_tag);
+}
+
+void LsanMetadata::set_tag(ChunkTag value) {
+ __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
+ m->lsan_tag = value;
+}
+
+uptr LsanMetadata::requested_size() const {
+ __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
+ return m->UsedSize();
+}
+
+u32 LsanMetadata::stack_trace_id() const {
+ __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
+ u32 tid = 0;
+ u32 stack = 0;
+ m->GetAllocContext(tid, stack);
+ return stack;
+}
+
+void ForEachChunk(ForEachChunkCallback callback, void *arg) {
+ __asan::get_allocator().ForEachChunk(callback, arg);
+}
+
+IgnoreObjectResult IgnoreObjectLocked(const void *p) {
+ uptr addr = reinterpret_cast<uptr>(p);
+ __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddr(addr);
+ if (!m ||
+ (atomic_load(&m->chunk_state, memory_order_acquire) !=
+ __asan::CHUNK_ALLOCATED) ||
+ !m->AddrIsInside(addr)) {
+ return kIgnoreObjectInvalid;
+ }
+ if (m->lsan_tag == kIgnored)
+ return kIgnoreObjectAlreadyIgnored;
+ m->lsan_tag = __lsan::kIgnored;
+ return kIgnoreObjectSuccess;
+}
+
+} // namespace __lsan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan;
+
+// ASan allocator doesn't reserve extra bytes, so normally we would
+// just return "size". We don't want to expose our redzone sizes, etc here.
+uptr __sanitizer_get_estimated_allocated_size(uptr size) {
+ return size;
+}
+
+int __sanitizer_get_ownership(const void *p) {
+ uptr ptr = reinterpret_cast<uptr>(p);
+ return instance.AllocationSize(ptr) > 0;
+}
+
+uptr __sanitizer_get_allocated_size(const void *p) {
+ if (!p) return 0;
+ uptr ptr = reinterpret_cast<uptr>(p);
+ uptr allocated_size = instance.AllocationSize(ptr);
+ // Die if p is not malloced or if it is already freed.
+ if (allocated_size == 0) {
+ GET_STACK_TRACE_FATAL_HERE;
+ ReportSanitizerGetAllocatedSizeNotOwned(ptr, &stack);
+ }
+ return allocated_size;
+}
+
+void __sanitizer_purge_allocator() {
+ GET_STACK_TRACE_MALLOC;
+ instance.Purge(&stack);
+}
+
+int __asan_update_allocation_context(void* addr) {
+ GET_STACK_TRACE_MALLOC;
+ return instance.UpdateAllocationStack((uptr)addr, &stack);
+}
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_allocator.h b/contrib/libs/clang16-rt/lib/asan/asan_allocator.h
new file mode 100644
index 00000000000..0b4dbf03bb9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_allocator.h
@@ -0,0 +1,227 @@
+//===-- asan_allocator.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan-private header for asan_allocator.cpp.
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_ALLOCATOR_H
+#define ASAN_ALLOCATOR_H
+
+#include "asan_flags.h"
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_list.h"
+#include "sanitizer_common/sanitizer_platform.h"
+
+namespace __asan {
+
+enum AllocType {
+ FROM_MALLOC = 1, // Memory block came from malloc, calloc, realloc, etc.
+ FROM_NEW = 2, // Memory block came from operator new.
+ FROM_NEW_BR = 3 // Memory block came from operator new [ ]
+};
+
+class AsanChunk;
+
+struct AllocatorOptions {
+ u32 quarantine_size_mb;
+ u32 thread_local_quarantine_size_kb;
+ u16 min_redzone;
+ u16 max_redzone;
+ u8 may_return_null;
+ u8 alloc_dealloc_mismatch;
+ s32 release_to_os_interval_ms;
+
+ void SetFrom(const Flags *f, const CommonFlags *cf);
+ void CopyTo(Flags *f, CommonFlags *cf);
+};
+
+void InitializeAllocator(const AllocatorOptions &options);
+void ReInitializeAllocator(const AllocatorOptions &options);
+void GetAllocatorOptions(AllocatorOptions *options);
+
+class AsanChunkView {
+ public:
+ explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {}
+ bool IsValid() const; // Checks if AsanChunkView points to a valid
+ // allocated or quarantined chunk.
+ bool IsAllocated() const; // Checks if the memory is currently allocated.
+ bool IsQuarantined() const; // Checks if the memory is currently quarantined.
+ uptr Beg() const; // First byte of user memory.
+ uptr End() const; // Last byte of user memory.
+ uptr UsedSize() const; // Size requested by the user.
+ u32 UserRequestedAlignment() const; // Originally requested alignment.
+ uptr AllocTid() const;
+ uptr FreeTid() const;
+ bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; }
+ u32 GetAllocStackId() const;
+ u32 GetFreeStackId() const;
+ AllocType GetAllocType() const;
+ bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) const {
+ if (addr >= Beg() && (addr + access_size) <= End()) {
+ *offset = addr - Beg();
+ return true;
+ }
+ return false;
+ }
+ bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) const {
+ (void)access_size;
+ if (addr < Beg()) {
+ *offset = Beg() - addr;
+ return true;
+ }
+ return false;
+ }
+ bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) const {
+ if (addr + access_size > End()) {
+ *offset = addr - End();
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ AsanChunk *const chunk_;
+};
+
+AsanChunkView FindHeapChunkByAddress(uptr address);
+AsanChunkView FindHeapChunkByAllocBeg(uptr address);
+
+// List of AsanChunks with total size.
+class AsanChunkFifoList: public IntrusiveList<AsanChunk> {
+ public:
+ explicit AsanChunkFifoList(LinkerInitialized) { }
+ AsanChunkFifoList() { clear(); }
+ void Push(AsanChunk *n);
+ void PushList(AsanChunkFifoList *q);
+ AsanChunk *Pop();
+ uptr size() { return size_; }
+ void clear() {
+ IntrusiveList<AsanChunk>::clear();
+ size_ = 0;
+ }
+ private:
+ uptr size_;
+};
+
+struct AsanMapUnmapCallback {
+ void OnMap(uptr p, uptr size) const;
+ void OnUnmap(uptr p, uptr size) const;
+};
+
+#if SANITIZER_CAN_USE_ALLOCATOR64
+# if SANITIZER_FUCHSIA
+const uptr kAllocatorSpace = ~(uptr)0;
+const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
+typedef DefaultSizeClassMap SizeClassMap;
+# elif defined(__powerpc64__)
+const uptr kAllocatorSpace = ~(uptr)0;
+const uptr kAllocatorSize = 0x20000000000ULL; // 2T.
+typedef DefaultSizeClassMap SizeClassMap;
+# elif defined(__aarch64__) && SANITIZER_ANDROID
+// Android needs to support 39, 42 and 48 bit VMA.
+const uptr kAllocatorSpace = ~(uptr)0;
+const uptr kAllocatorSize = 0x2000000000ULL; // 128G.
+typedef VeryCompactSizeClassMap SizeClassMap;
+#elif SANITIZER_RISCV64
+const uptr kAllocatorSpace = ~(uptr)0;
+const uptr kAllocatorSize = 0x2000000000ULL; // 128G.
+typedef VeryDenseSizeClassMap SizeClassMap;
+#elif defined(__sparc__)
+const uptr kAllocatorSpace = ~(uptr)0;
+const uptr kAllocatorSize = 0x20000000000ULL; // 2T.
+typedef DefaultSizeClassMap SizeClassMap;
+# elif SANITIZER_WINDOWS
+const uptr kAllocatorSpace = ~(uptr)0;
+const uptr kAllocatorSize = 0x8000000000ULL; // 500G
+typedef DefaultSizeClassMap SizeClassMap;
+# else
+const uptr kAllocatorSpace = 0x600000000000ULL;
+const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
+typedef DefaultSizeClassMap SizeClassMap;
+# endif
+template <typename AddressSpaceViewTy>
+struct AP64 { // Allocator64 parameters. Deliberately using a short name.
+ static const uptr kSpaceBeg = kAllocatorSpace;
+ static const uptr kSpaceSize = kAllocatorSize;
+ static const uptr kMetadataSize = 0;
+ typedef __asan::SizeClassMap SizeClassMap;
+ typedef AsanMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+ using AddressSpaceView = AddressSpaceViewTy;
+};
+
+template <typename AddressSpaceView>
+using PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>;
+using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
+#else // Fallback to SizeClassAllocator32.
+typedef CompactSizeClassMap SizeClassMap;
+template <typename AddressSpaceViewTy>
+struct AP32 {
+ static const uptr kSpaceBeg = 0;
+ static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
+ static const uptr kMetadataSize = 0;
+ typedef __asan::SizeClassMap SizeClassMap;
+ static const uptr kRegionSizeLog = 20;
+ using AddressSpaceView = AddressSpaceViewTy;
+ typedef AsanMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+};
+template <typename AddressSpaceView>
+using PrimaryAllocatorASVT = SizeClassAllocator32<AP32<AddressSpaceView> >;
+using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
+#endif // SANITIZER_CAN_USE_ALLOCATOR64
+
+static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses;
+
+template <typename AddressSpaceView>
+using AsanAllocatorASVT =
+ CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>>;
+using AsanAllocator = AsanAllocatorASVT<LocalAddressSpaceView>;
+using AllocatorCache = AsanAllocator::AllocatorCache;
+
+struct AsanThreadLocalMallocStorage {
+ uptr quarantine_cache[16];
+ AllocatorCache allocator_cache;
+ void CommitBack();
+ private:
+ // These objects are allocated via mmap() and are zero-initialized.
+ AsanThreadLocalMallocStorage() {}
+};
+
+void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack,
+ AllocType alloc_type);
+void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type);
+void asan_delete(void *ptr, uptr size, uptr alignment,
+ BufferedStackTrace *stack, AllocType alloc_type);
+
+void *asan_malloc(uptr size, BufferedStackTrace *stack);
+void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack);
+void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack);
+void *asan_reallocarray(void *p, uptr nmemb, uptr size,
+ BufferedStackTrace *stack);
+void *asan_valloc(uptr size, BufferedStackTrace *stack);
+void *asan_pvalloc(uptr size, BufferedStackTrace *stack);
+
+void *asan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack);
+int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
+ BufferedStackTrace *stack);
+uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp);
+
+uptr asan_mz_size(const void *ptr);
+void asan_mz_force_lock();
+void asan_mz_force_unlock();
+
+void PrintInternalAllocatorStats();
+void AsanSoftRssLimitExceededCallback(bool exceeded);
+
+} // namespace __asan
+#endif // ASAN_ALLOCATOR_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_debugging.cpp b/contrib/libs/clang16-rt/lib/asan/asan_debugging.cpp
new file mode 100644
index 00000000000..f078f1041a8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_debugging.cpp
@@ -0,0 +1,147 @@
+//===-- asan_debugging.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// This file contains various functions that are generally useful to call when
+// using a debugger (LLDB, GDB).
+//===----------------------------------------------------------------------===//
+
+#include "asan_allocator.h"
+#include "asan_descriptions.h"
+#include "asan_flags.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "asan_report.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+namespace {
+using namespace __asan;
+
+static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset,
+ char *name, uptr name_size,
+ uptr *region_address, uptr *region_size) {
+ InternalMmapVector<StackVarDescr> vars;
+ vars.reserve(16);
+ if (!ParseFrameDescription(frame_descr, &vars)) {
+ return;
+ }
+
+ for (uptr i = 0; i < vars.size(); i++) {
+ if (offset <= vars[i].beg + vars[i].size) {
+ // We use name_len + 1 because strlcpy will guarantee a \0 at the end, so
+ // if we're limiting the copy due to name_len, we add 1 to ensure we copy
+ // the whole name and then terminate with '\0'.
+ internal_strlcpy(name, vars[i].name_pos,
+ Min(name_size, vars[i].name_len + 1));
+ *region_address = addr - (offset - vars[i].beg);
+ *region_size = vars[i].size;
+ return;
+ }
+ }
+}
+
+uptr AsanGetStack(uptr addr, uptr *trace, u32 size, u32 *thread_id,
+ bool alloc_stack) {
+ AsanChunkView chunk = FindHeapChunkByAddress(addr);
+ if (!chunk.IsValid()) return 0;
+
+ StackTrace stack(nullptr, 0);
+ if (alloc_stack) {
+ if (chunk.AllocTid() == kInvalidTid) return 0;
+ stack = StackDepotGet(chunk.GetAllocStackId());
+ if (thread_id) *thread_id = chunk.AllocTid();
+ } else {
+ if (chunk.FreeTid() == kInvalidTid) return 0;
+ stack = StackDepotGet(chunk.GetFreeStackId());
+ if (thread_id) *thread_id = chunk.FreeTid();
+ }
+
+ if (trace && size) {
+ size = Min(size, Min(stack.size, kStackTraceMax));
+ for (uptr i = 0; i < size; i++)
+ trace[i] = StackTrace::GetPreviousInstructionPc(stack.trace[i]);
+
+ return size;
+ }
+
+ return 0;
+}
+
+} // namespace
+
+SANITIZER_INTERFACE_ATTRIBUTE
+const char *__asan_locate_address(uptr addr, char *name, uptr name_size,
+ uptr *region_address_ptr,
+ uptr *region_size_ptr) {
+ AddressDescription descr(addr);
+ uptr region_address = 0;
+ uptr region_size = 0;
+ const char *region_kind = nullptr;
+ if (name && name_size > 0) name[0] = 0;
+
+ if (auto shadow = descr.AsShadow()) {
+ // region_{address,size} are already 0
+ switch (shadow->kind) {
+ case kShadowKindLow:
+ region_kind = "low shadow";
+ break;
+ case kShadowKindGap:
+ region_kind = "shadow gap";
+ break;
+ case kShadowKindHigh:
+ region_kind = "high shadow";
+ break;
+ }
+ } else if (auto heap = descr.AsHeap()) {
+ region_kind = "heap";
+ region_address = heap->chunk_access.chunk_begin;
+ region_size = heap->chunk_access.chunk_size;
+ } else if (auto stack = descr.AsStack()) {
+ region_kind = "stack";
+ if (!stack->frame_descr) {
+ // region_{address,size} are already 0
+ } else {
+ FindInfoForStackVar(addr, stack->frame_descr, stack->offset, name,
+ name_size, &region_address, &region_size);
+ }
+ } else if (auto global = descr.AsGlobal()) {
+ region_kind = "global";
+ auto &g = global->globals[0];
+ internal_strlcpy(name, g.name, name_size);
+ region_address = g.beg;
+ region_size = g.size;
+ } else {
+ // region_{address,size} are already 0
+ region_kind = "heap-invalid";
+ }
+
+ CHECK(region_kind);
+ if (region_address_ptr) *region_address_ptr = region_address;
+ if (region_size_ptr) *region_size_ptr = region_size;
+ return region_kind;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __asan_get_alloc_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id) {
+ return AsanGetStack(addr, trace, size, thread_id, /* alloc_stack */ true);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __asan_get_free_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id) {
+ return AsanGetStack(addr, trace, size, thread_id, /* alloc_stack */ false);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __asan_get_shadow_mapping(uptr *shadow_scale, uptr *shadow_offset) {
+ if (shadow_scale)
+ *shadow_scale = ASAN_SHADOW_SCALE;
+ if (shadow_offset)
+ *shadow_offset = ASAN_SHADOW_OFFSET;
+}
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_descriptions.cpp b/contrib/libs/clang16-rt/lib/asan/asan_descriptions.cpp
new file mode 100644
index 00000000000..fbe92572b55
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_descriptions.cpp
@@ -0,0 +1,507 @@
+//===-- asan_descriptions.cpp -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan functions for getting information about an address and/or printing it.
+//===----------------------------------------------------------------------===//
+
+#include "asan_descriptions.h"
+#include "asan_mapping.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+namespace __asan {
+
+AsanThreadIdAndName::AsanThreadIdAndName(AsanThreadContext *t) {
+ Init(t->tid, t->name);
+}
+
+AsanThreadIdAndName::AsanThreadIdAndName(u32 tid) {
+ if (tid == kInvalidTid) {
+ Init(tid, "");
+ } else {
+ asanThreadRegistry().CheckLocked();
+ AsanThreadContext *t = GetThreadContextByTidLocked(tid);
+ Init(tid, t->name);
+ }
+}
+
+void AsanThreadIdAndName::Init(u32 tid, const char *tname) {
+ int len = internal_snprintf(name, sizeof(name), "T%d", tid);
+ CHECK(((unsigned int)len) < sizeof(name));
+ if (tname[0] != '\0')
+ internal_snprintf(&name[len], sizeof(name) - len, " (%s)", tname);
+}
+
+void DescribeThread(AsanThreadContext *context) {
+ CHECK(context);
+ asanThreadRegistry().CheckLocked();
+ // No need to announce the main thread.
+ if (context->tid == kMainTid || context->announced) {
+ return;
+ }
+ context->announced = true;
+ InternalScopedString str;
+ str.append("Thread %s", AsanThreadIdAndName(context).c_str());
+ if (context->parent_tid == kInvalidTid) {
+ str.append(" created by unknown thread\n");
+ Printf("%s", str.data());
+ return;
+ }
+ str.append(" created by %s here:\n",
+ AsanThreadIdAndName(context->parent_tid).c_str());
+ Printf("%s", str.data());
+ StackDepotGet(context->stack_id).Print();
+ // Recursively described parent thread if needed.
+ if (flags()->print_full_thread_history) {
+ AsanThreadContext *parent_context =
+ GetThreadContextByTidLocked(context->parent_tid);
+ DescribeThread(parent_context);
+ }
+}
+
+// Shadow descriptions
+static bool GetShadowKind(uptr addr, ShadowKind *shadow_kind) {
+ CHECK(!AddrIsInMem(addr));
+ if (AddrIsInShadowGap(addr)) {
+ *shadow_kind = kShadowKindGap;
+ } else if (AddrIsInHighShadow(addr)) {
+ *shadow_kind = kShadowKindHigh;
+ } else if (AddrIsInLowShadow(addr)) {
+ *shadow_kind = kShadowKindLow;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool DescribeAddressIfShadow(uptr addr) {
+ ShadowAddressDescription descr;
+ if (!GetShadowAddressInformation(addr, &descr)) return false;
+ descr.Print();
+ return true;
+}
+
+bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr) {
+ if (AddrIsInMem(addr)) return false;
+ ShadowKind shadow_kind;
+ if (!GetShadowKind(addr, &shadow_kind)) return false;
+ if (shadow_kind != kShadowKindGap) descr->shadow_byte = *(u8 *)addr;
+ descr->addr = addr;
+ descr->kind = shadow_kind;
+ return true;
+}
+
+// Heap descriptions
+static void GetAccessToHeapChunkInformation(ChunkAccess *descr,
+ AsanChunkView chunk, uptr addr,
+ uptr access_size) {
+ descr->bad_addr = addr;
+ if (chunk.AddrIsAtLeft(addr, access_size, &descr->offset)) {
+ descr->access_type = kAccessTypeLeft;
+ } else if (chunk.AddrIsAtRight(addr, access_size, &descr->offset)) {
+ descr->access_type = kAccessTypeRight;
+ if (descr->offset < 0) {
+ descr->bad_addr -= descr->offset;
+ descr->offset = 0;
+ }
+ } else if (chunk.AddrIsInside(addr, access_size, &descr->offset)) {
+ descr->access_type = kAccessTypeInside;
+ } else {
+ descr->access_type = kAccessTypeUnknown;
+ }
+ descr->chunk_begin = chunk.Beg();
+ descr->chunk_size = chunk.UsedSize();
+ descr->user_requested_alignment = chunk.UserRequestedAlignment();
+ descr->alloc_type = chunk.GetAllocType();
+}
+
+static void PrintHeapChunkAccess(uptr addr, const ChunkAccess &descr) {
+ Decorator d;
+ InternalScopedString str;
+ str.append("%s", d.Location());
+ switch (descr.access_type) {
+ case kAccessTypeLeft:
+ str.append("%p is located %zd bytes before",
+ (void *)descr.bad_addr, descr.offset);
+ break;
+ case kAccessTypeRight:
+ str.append("%p is located %zd bytes after",
+ (void *)descr.bad_addr, descr.offset);
+ break;
+ case kAccessTypeInside:
+ str.append("%p is located %zd bytes inside of", (void *)descr.bad_addr,
+ descr.offset);
+ break;
+ case kAccessTypeUnknown:
+ str.append(
+ "%p is located somewhere around (this is AddressSanitizer bug!)",
+ (void *)descr.bad_addr);
+ }
+ str.append(" %zu-byte region [%p,%p)\n", descr.chunk_size,
+ (void *)descr.chunk_begin,
+ (void *)(descr.chunk_begin + descr.chunk_size));
+ str.append("%s", d.Default());
+ Printf("%s", str.data());
+}
+
+bool GetHeapAddressInformation(uptr addr, uptr access_size,
+ HeapAddressDescription *descr) {
+ AsanChunkView chunk = FindHeapChunkByAddress(addr);
+ if (!chunk.IsValid()) {
+ return false;
+ }
+ descr->addr = addr;
+ GetAccessToHeapChunkInformation(&descr->chunk_access, chunk, addr,
+ access_size);
+ CHECK_NE(chunk.AllocTid(), kInvalidTid);
+ descr->alloc_tid = chunk.AllocTid();
+ descr->alloc_stack_id = chunk.GetAllocStackId();
+ descr->free_tid = chunk.FreeTid();
+ if (descr->free_tid != kInvalidTid)
+ descr->free_stack_id = chunk.GetFreeStackId();
+ return true;
+}
+
+static StackTrace GetStackTraceFromId(u32 id) {
+ CHECK(id);
+ StackTrace res = StackDepotGet(id);
+ CHECK(res.trace);
+ return res;
+}
+
+bool DescribeAddressIfHeap(uptr addr, uptr access_size) {
+ HeapAddressDescription descr;
+ if (!GetHeapAddressInformation(addr, access_size, &descr)) {
+ Printf(
+ "AddressSanitizer can not describe address in more detail "
+ "(wild memory access suspected).\n");
+ return false;
+ }
+ descr.Print();
+ return true;
+}
+
+// Stack descriptions
+bool GetStackAddressInformation(uptr addr, uptr access_size,
+ StackAddressDescription *descr) {
+ AsanThread *t = FindThreadByStackAddress(addr);
+ if (!t) return false;
+
+ descr->addr = addr;
+ descr->tid = t->tid();
+ // Try to fetch precise stack frame for this access.
+ AsanThread::StackFrameAccess access;
+ if (!t->GetStackFrameAccessByAddr(addr, &access)) {
+ descr->frame_descr = nullptr;
+ return true;
+ }
+
+ descr->offset = access.offset;
+ descr->access_size = access_size;
+ descr->frame_pc = access.frame_pc;
+ descr->frame_descr = access.frame_descr;
+
+#if SANITIZER_PPC64V1
+ // On PowerPC64 ELFv1, the address of a function actually points to a
+ // three-doubleword data structure with the first field containing
+ // the address of the function's code.
+ descr->frame_pc = *reinterpret_cast<uptr *>(descr->frame_pc);
+#endif
+ descr->frame_pc += 16;
+
+ return true;
+}
+
+static void PrintAccessAndVarIntersection(const StackVarDescr &var, uptr addr,
+ uptr access_size, uptr prev_var_end,
+ uptr next_var_beg) {
+ uptr var_end = var.beg + var.size;
+ uptr addr_end = addr + access_size;
+ const char *pos_descr = nullptr;
+ // If the variable [var.beg, var_end) is the nearest variable to the
+ // current memory access, indicate it in the log.
+ if (addr >= var.beg) {
+ if (addr_end <= var_end)
+ pos_descr = "is inside"; // May happen if this is a use-after-return.
+ else if (addr < var_end)
+ pos_descr = "partially overflows";
+ else if (addr_end <= next_var_beg &&
+ next_var_beg - addr_end >= addr - var_end)
+ pos_descr = "overflows";
+ } else {
+ if (addr_end > var.beg)
+ pos_descr = "partially underflows";
+ else if (addr >= prev_var_end && addr - prev_var_end >= var.beg - addr_end)
+ pos_descr = "underflows";
+ }
+ InternalScopedString str;
+ str.append(" [%zd, %zd)", var.beg, var_end);
+ // Render variable name.
+ str.append(" '");
+ for (uptr i = 0; i < var.name_len; ++i) {
+ str.append("%c", var.name_pos[i]);
+ }
+ str.append("'");
+ if (var.line > 0) {
+ str.append(" (line %zd)", var.line);
+ }
+ if (pos_descr) {
+ Decorator d;
+ // FIXME: we may want to also print the size of the access here,
+ // but in case of accesses generated by memset it may be confusing.
+ str.append("%s <== Memory access at offset %zd %s this variable%s\n",
+ d.Location(), addr, pos_descr, d.Default());
+ } else {
+ str.append("\n");
+ }
+ Printf("%s", str.data());
+}
+
+bool DescribeAddressIfStack(uptr addr, uptr access_size) {
+ StackAddressDescription descr;
+ if (!GetStackAddressInformation(addr, access_size, &descr)) return false;
+ descr.Print();
+ return true;
+}
+
+// Global descriptions
+static void DescribeAddressRelativeToGlobal(uptr addr, uptr access_size,
+ const __asan_global &g) {
+ InternalScopedString str;
+ Decorator d;
+ str.append("%s", d.Location());
+ if (addr < g.beg) {
+ str.append("%p is located %zd bytes before", (void *)addr,
+ g.beg - addr);
+ } else if (addr + access_size > g.beg + g.size) {
+ if (addr < g.beg + g.size) addr = g.beg + g.size;
+ str.append("%p is located %zd bytes after", (void *)addr,
+ addr - (g.beg + g.size));
+ } else {
+ // Can it happen?
+ str.append("%p is located %zd bytes inside of", (void *)addr, addr - g.beg);
+ }
+ str.append(" global variable '%s' defined in '",
+ MaybeDemangleGlobalName(g.name));
+ PrintGlobalLocation(&str, g);
+ str.append("' (0x%zx) of size %zu\n", g.beg, g.size);
+ str.append("%s", d.Default());
+ PrintGlobalNameIfASCII(&str, g);
+ Printf("%s", str.data());
+}
+
+bool GetGlobalAddressInformation(uptr addr, uptr access_size,
+ GlobalAddressDescription *descr) {
+ descr->addr = addr;
+ int globals_num = GetGlobalsForAddress(addr, descr->globals, descr->reg_sites,
+ ARRAY_SIZE(descr->globals));
+ descr->size = globals_num;
+ descr->access_size = access_size;
+ return globals_num != 0;
+}
+
+bool DescribeAddressIfGlobal(uptr addr, uptr access_size,
+ const char *bug_type) {
+ GlobalAddressDescription descr;
+ if (!GetGlobalAddressInformation(addr, access_size, &descr)) return false;
+
+ descr.Print(bug_type);
+ return true;
+}
+
+void ShadowAddressDescription::Print() const {
+ Printf("Address %p is located in the %s area.\n", (void *)addr,
+ ShadowNames[kind]);
+}
+
+void GlobalAddressDescription::Print(const char *bug_type) const {
+ for (int i = 0; i < size; i++) {
+ DescribeAddressRelativeToGlobal(addr, access_size, globals[i]);
+ if (bug_type &&
+ 0 == internal_strcmp(bug_type, "initialization-order-fiasco") &&
+ reg_sites[i]) {
+ Printf(" registered at:\n");
+ StackDepotGet(reg_sites[i]).Print();
+ }
+ }
+}
+
+bool GlobalAddressDescription::PointsInsideTheSameVariable(
+ const GlobalAddressDescription &other) const {
+ if (size == 0 || other.size == 0) return false;
+
+ for (uptr i = 0; i < size; i++) {
+ const __asan_global &a = globals[i];
+ for (uptr j = 0; j < other.size; j++) {
+ const __asan_global &b = other.globals[j];
+ if (a.beg == b.beg &&
+ a.beg <= addr &&
+ b.beg <= other.addr &&
+ (addr + access_size) < (a.beg + a.size) &&
+ (other.addr + other.access_size) < (b.beg + b.size))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void StackAddressDescription::Print() const {
+ Decorator d;
+ Printf("%s", d.Location());
+ Printf("Address %p is located in stack of thread %s", (void *)addr,
+ AsanThreadIdAndName(tid).c_str());
+
+ if (!frame_descr) {
+ Printf("%s\n", d.Default());
+ return;
+ }
+ Printf(" at offset %zu in frame%s\n", offset, d.Default());
+
+ // Now we print the frame where the alloca has happened.
+ // We print this frame as a stack trace with one element.
+ // The symbolizer may print more than one frame if inlining was involved.
+ // The frame numbers may be different than those in the stack trace printed
+ // previously. That's unfortunate, but I have no better solution,
+ // especially given that the alloca may be from entirely different place
+ // (e.g. use-after-scope, or different thread's stack).
+ Printf("%s", d.Default());
+ StackTrace alloca_stack(&frame_pc, 1);
+ alloca_stack.Print();
+
+ InternalMmapVector<StackVarDescr> vars;
+ vars.reserve(16);
+ if (!ParseFrameDescription(frame_descr, &vars)) {
+ Printf(
+ "AddressSanitizer can't parse the stack frame "
+ "descriptor: |%s|\n",
+ frame_descr);
+ // 'addr' is a stack address, so return true even if we can't parse frame
+ return;
+ }
+ uptr n_objects = vars.size();
+ // Report the number of stack objects.
+ Printf(" This frame has %zu object(s):\n", n_objects);
+
+ // Report all objects in this frame.
+ for (uptr i = 0; i < n_objects; i++) {
+ uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0;
+ uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL);
+ PrintAccessAndVarIntersection(vars[i], offset, access_size, prev_var_end,
+ next_var_beg);
+ }
+ Printf(
+ "HINT: this may be a false positive if your program uses "
+ "some custom stack unwind mechanism, swapcontext or vfork\n");
+ if (SANITIZER_WINDOWS)
+ Printf(" (longjmp, SEH and C++ exceptions *are* supported)\n");
+ else
+ Printf(" (longjmp and C++ exceptions *are* supported)\n");
+
+ DescribeThread(GetThreadContextByTidLocked(tid));
+}
+
+void HeapAddressDescription::Print() const {
+ PrintHeapChunkAccess(addr, chunk_access);
+
+ asanThreadRegistry().CheckLocked();
+ AsanThreadContext *alloc_thread = GetThreadContextByTidLocked(alloc_tid);
+ StackTrace alloc_stack = GetStackTraceFromId(alloc_stack_id);
+
+ Decorator d;
+ AsanThreadContext *free_thread = nullptr;
+ if (free_tid != kInvalidTid) {
+ free_thread = GetThreadContextByTidLocked(free_tid);
+ Printf("%sfreed by thread %s here:%s\n", d.Allocation(),
+ AsanThreadIdAndName(free_thread).c_str(), d.Default());
+ StackTrace free_stack = GetStackTraceFromId(free_stack_id);
+ free_stack.Print();
+ Printf("%spreviously allocated by thread %s here:%s\n", d.Allocation(),
+ AsanThreadIdAndName(alloc_thread).c_str(), d.Default());
+ } else {
+ Printf("%sallocated by thread %s here:%s\n", d.Allocation(),
+ AsanThreadIdAndName(alloc_thread).c_str(), d.Default());
+ }
+ alloc_stack.Print();
+ DescribeThread(GetCurrentThread());
+ if (free_thread) DescribeThread(free_thread);
+ DescribeThread(alloc_thread);
+}
+
+AddressDescription::AddressDescription(uptr addr, uptr access_size,
+ bool shouldLockThreadRegistry) {
+ if (GetShadowAddressInformation(addr, &data.shadow)) {
+ data.kind = kAddressKindShadow;
+ return;
+ }
+ if (GetHeapAddressInformation(addr, access_size, &data.heap)) {
+ data.kind = kAddressKindHeap;
+ return;
+ }
+
+ bool isStackMemory = false;
+ if (shouldLockThreadRegistry) {
+ ThreadRegistryLock l(&asanThreadRegistry());
+ isStackMemory = GetStackAddressInformation(addr, access_size, &data.stack);
+ } else {
+ isStackMemory = GetStackAddressInformation(addr, access_size, &data.stack);
+ }
+ if (isStackMemory) {
+ data.kind = kAddressKindStack;
+ return;
+ }
+
+ if (GetGlobalAddressInformation(addr, access_size, &data.global)) {
+ data.kind = kAddressKindGlobal;
+ return;
+ }
+ data.kind = kAddressKindWild;
+ data.wild.addr = addr;
+ data.wild.access_size = access_size;
+}
+
+void WildAddressDescription::Print() const {
+ Printf("Address %p is a wild pointer inside of access range of size %p.\n",
+ (void *)addr, (void *)access_size);
+}
+
+void PrintAddressDescription(uptr addr, uptr access_size,
+ const char *bug_type) {
+ ShadowAddressDescription shadow_descr;
+ if (GetShadowAddressInformation(addr, &shadow_descr)) {
+ shadow_descr.Print();
+ return;
+ }
+
+ GlobalAddressDescription global_descr;
+ if (GetGlobalAddressInformation(addr, access_size, &global_descr)) {
+ global_descr.Print(bug_type);
+ return;
+ }
+
+ StackAddressDescription stack_descr;
+ if (GetStackAddressInformation(addr, access_size, &stack_descr)) {
+ stack_descr.Print();
+ return;
+ }
+
+ HeapAddressDescription heap_descr;
+ if (GetHeapAddressInformation(addr, access_size, &heap_descr)) {
+ heap_descr.Print();
+ return;
+ }
+
+ // We exhausted our possibilities. Bail out.
+ Printf(
+ "AddressSanitizer can not describe address in more detail "
+ "(wild memory access suspected).\n");
+}
+} // namespace __asan
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_descriptions.h b/contrib/libs/clang16-rt/lib/asan/asan_descriptions.h
new file mode 100644
index 00000000000..650e2eb9173
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_descriptions.h
@@ -0,0 +1,269 @@
+//===-- asan_descriptions.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan-private header for asan_descriptions.cpp.
+// TODO(filcab): Most struct definitions should move to the interface headers.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_DESCRIPTIONS_H
+#define ASAN_DESCRIPTIONS_H
+
+#include "asan_allocator.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
+
+namespace __asan {
+
+void DescribeThread(AsanThreadContext *context);
+static inline void DescribeThread(AsanThread *t) {
+ if (t) DescribeThread(t->context());
+}
+
+class AsanThreadIdAndName {
+ public:
+ explicit AsanThreadIdAndName(AsanThreadContext *t);
+ explicit AsanThreadIdAndName(u32 tid);
+
+ // Contains "T%tid (%name)" or "T%tid" if the name is empty.
+ const char *c_str() const { return &name[0]; }
+
+ private:
+ void Init(u32 tid, const char *tname);
+
+ char name[128];
+};
+
+class Decorator : public __sanitizer::SanitizerCommonDecorator {
+ public:
+ Decorator() : SanitizerCommonDecorator() {}
+ const char *Access() { return Blue(); }
+ const char *Location() { return Green(); }
+ const char *Allocation() { return Magenta(); }
+
+ const char *ShadowByte(u8 byte) {
+ switch (byte) {
+ case kAsanHeapLeftRedzoneMagic:
+ case kAsanArrayCookieMagic:
+ return Red();
+ case kAsanHeapFreeMagic:
+ return Magenta();
+ case kAsanStackLeftRedzoneMagic:
+ case kAsanStackMidRedzoneMagic:
+ case kAsanStackRightRedzoneMagic:
+ return Red();
+ case kAsanStackAfterReturnMagic:
+ return Magenta();
+ case kAsanInitializationOrderMagic:
+ return Cyan();
+ case kAsanUserPoisonedMemoryMagic:
+ case kAsanContiguousContainerOOBMagic:
+ case kAsanAllocaLeftMagic:
+ case kAsanAllocaRightMagic:
+ return Blue();
+ case kAsanStackUseAfterScopeMagic:
+ return Magenta();
+ case kAsanGlobalRedzoneMagic:
+ return Red();
+ case kAsanInternalHeapMagic:
+ return Yellow();
+ case kAsanIntraObjectRedzone:
+ return Yellow();
+ default:
+ return Default();
+ }
+ }
+};
+
+enum ShadowKind : u8 {
+ kShadowKindLow,
+ kShadowKindGap,
+ kShadowKindHigh,
+};
+static const char *const ShadowNames[] = {"low shadow", "shadow gap",
+ "high shadow"};
+
+struct ShadowAddressDescription {
+ uptr addr;
+ ShadowKind kind;
+ u8 shadow_byte;
+
+ void Print() const;
+};
+
+bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
+bool DescribeAddressIfShadow(uptr addr);
+
+enum AccessType {
+ kAccessTypeLeft,
+ kAccessTypeRight,
+ kAccessTypeInside,
+ kAccessTypeUnknown, // This means we have an AddressSanitizer bug!
+};
+
+struct ChunkAccess {
+ uptr bad_addr;
+ sptr offset;
+ uptr chunk_begin;
+ uptr chunk_size;
+ u32 user_requested_alignment : 12;
+ u32 access_type : 2;
+ u32 alloc_type : 2;
+};
+
+struct HeapAddressDescription {
+ uptr addr;
+ uptr alloc_tid;
+ uptr free_tid;
+ u32 alloc_stack_id;
+ u32 free_stack_id;
+ ChunkAccess chunk_access;
+
+ void Print() const;
+};
+
+bool GetHeapAddressInformation(uptr addr, uptr access_size,
+ HeapAddressDescription *descr);
+bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);
+
+struct StackAddressDescription {
+ uptr addr;
+ uptr tid;
+ uptr offset;
+ uptr frame_pc;
+ uptr access_size;
+ const char *frame_descr;
+
+ void Print() const;
+};
+
+bool GetStackAddressInformation(uptr addr, uptr access_size,
+ StackAddressDescription *descr);
+
+struct WildAddressDescription {
+ uptr addr;
+ uptr access_size;
+
+ void Print() const;
+};
+
+struct GlobalAddressDescription {
+ uptr addr;
+ // Assume address is close to at most four globals.
+ static const int kMaxGlobals = 4;
+ __asan_global globals[kMaxGlobals];
+ u32 reg_sites[kMaxGlobals];
+ uptr access_size;
+ u8 size;
+
+ void Print(const char *bug_type = "") const;
+
+ // Returns true when this descriptions points inside the same global variable
+ // as other. Descriptions can have different address within the variable
+ bool PointsInsideTheSameVariable(const GlobalAddressDescription &other) const;
+};
+
+bool GetGlobalAddressInformation(uptr addr, uptr access_size,
+ GlobalAddressDescription *descr);
+bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type);
+
+// General function to describe an address. Will try to describe the address as
+// a shadow, global (variable), stack, or heap address.
+// bug_type is optional and is used for checking if we're reporting an
+// initialization-order-fiasco
+// The proper access_size should be passed for stack, global, and heap
+// addresses. Defaults to 1.
+// Each of the *AddressDescription functions has its own Print() member, which
+// may take access_size and bug_type parameters if needed.
+void PrintAddressDescription(uptr addr, uptr access_size = 1,
+ const char *bug_type = "");
+
+enum AddressKind {
+ kAddressKindWild,
+ kAddressKindShadow,
+ kAddressKindHeap,
+ kAddressKindStack,
+ kAddressKindGlobal,
+};
+
+class AddressDescription {
+ struct AddressDescriptionData {
+ AddressKind kind;
+ union {
+ ShadowAddressDescription shadow;
+ HeapAddressDescription heap;
+ StackAddressDescription stack;
+ GlobalAddressDescription global;
+ WildAddressDescription wild;
+ };
+ };
+
+ AddressDescriptionData data;
+
+ public:
+ AddressDescription() = default;
+ // shouldLockThreadRegistry allows us to skip locking if we're sure we already
+ // have done it.
+ explicit AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
+ : AddressDescription(addr, 1, shouldLockThreadRegistry) {}
+ AddressDescription(uptr addr, uptr access_size,
+ bool shouldLockThreadRegistry = true);
+
+ uptr Address() const {
+ switch (data.kind) {
+ case kAddressKindWild:
+ return data.wild.addr;
+ case kAddressKindShadow:
+ return data.shadow.addr;
+ case kAddressKindHeap:
+ return data.heap.addr;
+ case kAddressKindStack:
+ return data.stack.addr;
+ case kAddressKindGlobal:
+ return data.global.addr;
+ }
+ UNREACHABLE("AddressInformation kind is invalid");
+ }
+ void Print(const char *bug_descr = nullptr) const {
+ switch (data.kind) {
+ case kAddressKindWild:
+ data.wild.Print();
+ return;
+ case kAddressKindShadow:
+ return data.shadow.Print();
+ case kAddressKindHeap:
+ return data.heap.Print();
+ case kAddressKindStack:
+ return data.stack.Print();
+ case kAddressKindGlobal:
+ // initialization-order-fiasco has a special Print()
+ return data.global.Print(bug_descr);
+ }
+ UNREACHABLE("AddressInformation kind is invalid");
+ }
+
+ void StoreTo(AddressDescriptionData *dst) const { *dst = data; }
+
+ const ShadowAddressDescription *AsShadow() const {
+ return data.kind == kAddressKindShadow ? &data.shadow : nullptr;
+ }
+ const HeapAddressDescription *AsHeap() const {
+ return data.kind == kAddressKindHeap ? &data.heap : nullptr;
+ }
+ const StackAddressDescription *AsStack() const {
+ return data.kind == kAddressKindStack ? &data.stack : nullptr;
+ }
+ const GlobalAddressDescription *AsGlobal() const {
+ return data.kind == kAddressKindGlobal ? &data.global : nullptr;
+ }
+};
+
+} // namespace __asan
+
+#endif // ASAN_DESCRIPTIONS_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_errors.cpp b/contrib/libs/clang16-rt/lib/asan/asan_errors.cpp
new file mode 100644
index 00000000000..cc8dc26f5b7
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_errors.cpp
@@ -0,0 +1,620 @@
+//===-- asan_errors.cpp -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan implementation for error structures.
+//===----------------------------------------------------------------------===//
+
+#include "asan_errors.h"
+#include "asan_descriptions.h"
+#include "asan_mapping.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+namespace __asan {
+
+static void OnStackUnwind(const SignalContext &sig,
+ const void *callback_context,
+ BufferedStackTrace *stack) {
+ bool fast = common_flags()->fast_unwind_on_fatal;
+#if SANITIZER_FREEBSD || SANITIZER_NETBSD
+ // On FreeBSD the slow unwinding that leverages _Unwind_Backtrace()
+ // yields the call stack of the signal's handler and not of the code
+ // that raised the signal (as it does on Linux).
+ fast = true;
+#endif
+ // Tests and maybe some users expect that scariness is going to be printed
+ // just before the stack. As only asan has scariness score we have no
+ // corresponding code in the sanitizer_common and we use this callback to
+ // print it.
+ static_cast<const ScarinessScoreBase *>(callback_context)->Print();
+ stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
+ fast);
+}
+
+void ErrorDeadlySignal::Print() {
+ ReportDeadlySignal(signal, tid, &OnStackUnwind, &scariness);
+}
+
+void ErrorDoubleFree::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report("ERROR: AddressSanitizer: attempting %s on %p in thread %s:\n",
+ scariness.GetDescription(), (void *)addr_description.addr,
+ AsanThreadIdAndName(tid).c_str());
+ Printf("%s", d.Default());
+ scariness.Print();
+ GET_STACK_TRACE_FATAL(second_free_stack->trace[0],
+ second_free_stack->top_frame_bp);
+ stack.Print();
+ addr_description.Print();
+ ReportErrorSummary(scariness.GetDescription(), &stack);
+}
+
+void ErrorNewDeleteTypeMismatch::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report("ERROR: AddressSanitizer: %s on %p in thread %s:\n",
+ scariness.GetDescription(), (void *)addr_description.addr,
+ AsanThreadIdAndName(tid).c_str());
+ Printf("%s object passed to delete has wrong type:\n", d.Default());
+ if (delete_size != 0) {
+ Printf(
+ " size of the allocated type: %zd bytes;\n"
+ " size of the deallocated type: %zd bytes.\n",
+ addr_description.chunk_access.chunk_size, delete_size);
+ }
+ const uptr user_alignment =
+ addr_description.chunk_access.user_requested_alignment;
+ if (delete_alignment != user_alignment) {
+ char user_alignment_str[32];
+ char delete_alignment_str[32];
+ internal_snprintf(user_alignment_str, sizeof(user_alignment_str),
+ "%zd bytes", user_alignment);
+ internal_snprintf(delete_alignment_str, sizeof(delete_alignment_str),
+ "%zd bytes", delete_alignment);
+ static const char *kDefaultAlignment = "default-aligned";
+ Printf(
+ " alignment of the allocated type: %s;\n"
+ " alignment of the deallocated type: %s.\n",
+ user_alignment > 0 ? user_alignment_str : kDefaultAlignment,
+ delete_alignment > 0 ? delete_alignment_str : kDefaultAlignment);
+ }
+ CHECK_GT(free_stack->size, 0);
+ scariness.Print();
+ GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
+ stack.Print();
+ addr_description.Print();
+ ReportErrorSummary(scariness.GetDescription(), &stack);
+ Report(
+ "HINT: if you don't care about these errors you may set "
+ "ASAN_OPTIONS=new_delete_type_mismatch=0\n");
+}
+
+void ErrorFreeNotMalloced::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report(
+ "ERROR: AddressSanitizer: attempting free on address "
+ "which was not malloc()-ed: %p in thread %s\n",
+ (void *)addr_description.Address(), AsanThreadIdAndName(tid).c_str());
+ Printf("%s", d.Default());
+ CHECK_GT(free_stack->size, 0);
+ scariness.Print();
+ GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
+ stack.Print();
+ addr_description.Print();
+ ReportErrorSummary(scariness.GetDescription(), &stack);
+}
+
+void ErrorAllocTypeMismatch::Print() {
+ static const char *alloc_names[] = {"INVALID", "malloc", "operator new",
+ "operator new []"};
+ static const char *dealloc_names[] = {"INVALID", "free", "operator delete",
+ "operator delete []"};
+ CHECK_NE(alloc_type, dealloc_type);
+ Decorator d;
+ Printf("%s", d.Error());
+ Report("ERROR: AddressSanitizer: %s (%s vs %s) on %p\n",
+ scariness.GetDescription(), alloc_names[alloc_type],
+ dealloc_names[dealloc_type], (void *)addr_description.Address());
+ Printf("%s", d.Default());
+ CHECK_GT(dealloc_stack->size, 0);
+ scariness.Print();
+ GET_STACK_TRACE_FATAL(dealloc_stack->trace[0], dealloc_stack->top_frame_bp);
+ stack.Print();
+ addr_description.Print();
+ ReportErrorSummary(scariness.GetDescription(), &stack);
+ Report(
+ "HINT: if you don't care about these errors you may set "
+ "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
+}
+
+void ErrorMallocUsableSizeNotOwned::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report(
+ "ERROR: AddressSanitizer: attempting to call malloc_usable_size() for "
+ "pointer which is not owned: %p\n",
+ (void *)addr_description.Address());
+ Printf("%s", d.Default());
+ stack->Print();
+ addr_description.Print();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorSanitizerGetAllocatedSizeNotOwned::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report(
+ "ERROR: AddressSanitizer: attempting to call "
+ "__sanitizer_get_allocated_size() for pointer which is not owned: %p\n",
+ (void *)addr_description.Address());
+ Printf("%s", d.Default());
+ stack->Print();
+ addr_description.Print();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorCallocOverflow::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report(
+ "ERROR: AddressSanitizer: calloc parameters overflow: count * size "
+ "(%zd * %zd) cannot be represented in type size_t (thread %s)\n",
+ count, size, AsanThreadIdAndName(tid).c_str());
+ Printf("%s", d.Default());
+ stack->Print();
+ PrintHintAllocatorCannotReturnNull();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorReallocArrayOverflow::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report(
+ "ERROR: AddressSanitizer: reallocarray parameters overflow: count * size "
+ "(%zd * %zd) cannot be represented in type size_t (thread %s)\n",
+ count, size, AsanThreadIdAndName(tid).c_str());
+ Printf("%s", d.Default());
+ stack->Print();
+ PrintHintAllocatorCannotReturnNull();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorPvallocOverflow::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report(
+ "ERROR: AddressSanitizer: pvalloc parameters overflow: size 0x%zx "
+ "rounded up to system page size 0x%zx cannot be represented in type "
+ "size_t (thread %s)\n",
+ size, GetPageSizeCached(), AsanThreadIdAndName(tid).c_str());
+ Printf("%s", d.Default());
+ stack->Print();
+ PrintHintAllocatorCannotReturnNull();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorInvalidAllocationAlignment::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report(
+ "ERROR: AddressSanitizer: invalid allocation alignment: %zd, "
+ "alignment must be a power of two (thread %s)\n",
+ alignment, AsanThreadIdAndName(tid).c_str());
+ Printf("%s", d.Default());
+ stack->Print();
+ PrintHintAllocatorCannotReturnNull();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorInvalidAlignedAllocAlignment::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+#if SANITIZER_POSIX
+ Report("ERROR: AddressSanitizer: invalid alignment requested in "
+ "aligned_alloc: %zd, alignment must be a power of two and the "
+ "requested size 0x%zx must be a multiple of alignment "
+ "(thread %s)\n", alignment, size, AsanThreadIdAndName(tid).c_str());
+#else
+ Report("ERROR: AddressSanitizer: invalid alignment requested in "
+ "aligned_alloc: %zd, the requested size 0x%zx must be a multiple of "
+ "alignment (thread %s)\n", alignment, size,
+ AsanThreadIdAndName(tid).c_str());
+#endif
+ Printf("%s", d.Default());
+ stack->Print();
+ PrintHintAllocatorCannotReturnNull();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorInvalidPosixMemalignAlignment::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report(
+ "ERROR: AddressSanitizer: invalid alignment requested in posix_memalign: "
+ "%zd, alignment must be a power of two and a multiple of sizeof(void*) "
+ "== %zd (thread %s)\n",
+ alignment, sizeof(void *), AsanThreadIdAndName(tid).c_str());
+ Printf("%s", d.Default());
+ stack->Print();
+ PrintHintAllocatorCannotReturnNull();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorAllocationSizeTooBig::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report(
+ "ERROR: AddressSanitizer: requested allocation size 0x%zx (0x%zx after "
+ "adjustments for alignment, red zones etc.) exceeds maximum supported "
+ "size of 0x%zx (thread %s)\n",
+ user_size, total_size, max_size, AsanThreadIdAndName(tid).c_str());
+ Printf("%s", d.Default());
+ stack->Print();
+ PrintHintAllocatorCannotReturnNull();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorRssLimitExceeded::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report(
+ "ERROR: AddressSanitizer: specified RSS limit exceeded, currently set to "
+ "soft_rss_limit_mb=%zd\n", common_flags()->soft_rss_limit_mb);
+ Printf("%s", d.Default());
+ stack->Print();
+ PrintHintAllocatorCannotReturnNull();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorOutOfMemory::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ ERROR_OOM("allocator is trying to allocate 0x%zx bytes\n", requested_size);
+ Printf("%s", d.Default());
+ stack->Print();
+ PrintHintAllocatorCannotReturnNull();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorStringFunctionMemoryRangesOverlap::Print() {
+ Decorator d;
+ char bug_type[100];
+ internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
+ Printf("%s", d.Error());
+ Report(
+ "ERROR: AddressSanitizer: %s: memory ranges [%p,%p) and [%p, %p) "
+ "overlap\n",
+ bug_type, (void *)addr1_description.Address(),
+ (void *)(addr1_description.Address() + length1),
+ (void *)addr2_description.Address(),
+ (void *)(addr2_description.Address() + length2));
+ Printf("%s", d.Default());
+ scariness.Print();
+ stack->Print();
+ addr1_description.Print();
+ addr2_description.Print();
+ ReportErrorSummary(bug_type, stack);
+}
+
+void ErrorStringFunctionSizeOverflow::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report("ERROR: AddressSanitizer: %s: (size=%zd)\n",
+ scariness.GetDescription(), size);
+ Printf("%s", d.Default());
+ scariness.Print();
+ stack->Print();
+ addr_description.Print();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorBadParamsToAnnotateContiguousContainer::Print() {
+ Report(
+ "ERROR: AddressSanitizer: bad parameters to "
+ "__sanitizer_annotate_contiguous_container:\n"
+ " beg : %p\n"
+ " end : %p\n"
+ " old_mid : %p\n"
+ " new_mid : %p\n",
+ (void *)beg, (void *)end, (void *)old_mid, (void *)new_mid);
+ uptr granularity = ASAN_SHADOW_GRANULARITY;
+ if (!IsAligned(beg, granularity))
+ Report("ERROR: beg is not aligned by %zu\n", granularity);
+ stack->Print();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorBadParamsToAnnotateDoubleEndedContiguousContainer::Print() {
+ Report(
+ "ERROR: AddressSanitizer: bad parameters to "
+ "__sanitizer_annotate_double_ended_contiguous_container:\n"
+ " storage_beg : %p\n"
+ " storage_end : %p\n"
+ " old_container_beg : %p\n"
+ " old_container_end : %p\n"
+ " new_container_beg : %p\n"
+ " new_container_end : %p\n",
+ (void *)storage_beg, (void *)storage_end, (void *)old_container_beg,
+ (void *)old_container_end, (void *)new_container_beg,
+ (void *)new_container_end);
+ uptr granularity = ASAN_SHADOW_GRANULARITY;
+ if (!IsAligned(storage_beg, granularity))
+ Report("ERROR: storage_beg is not aligned by %zu\n", granularity);
+ stack->Print();
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorODRViolation::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report("ERROR: AddressSanitizer: %s (%p):\n", scariness.GetDescription(),
+ (void *)global1.beg);
+ Printf("%s", d.Default());
+ InternalScopedString g1_loc;
+ InternalScopedString g2_loc;
+ PrintGlobalLocation(&g1_loc, global1);
+ PrintGlobalLocation(&g2_loc, global2);
+ Printf(" [1] size=%zd '%s' %s\n", global1.size,
+ MaybeDemangleGlobalName(global1.name), g1_loc.data());
+ Printf(" [2] size=%zd '%s' %s\n", global2.size,
+ MaybeDemangleGlobalName(global2.name), g2_loc.data());
+ if (stack_id1 && stack_id2) {
+ Printf("These globals were registered at these points:\n");
+ Printf(" [1]:\n");
+ StackDepotGet(stack_id1).Print();
+ Printf(" [2]:\n");
+ StackDepotGet(stack_id2).Print();
+ }
+ Report(
+ "HINT: if you don't care about these errors you may set "
+ "ASAN_OPTIONS=detect_odr_violation=0\n");
+ InternalScopedString error_msg;
+ error_msg.append("%s: global '%s' at %s", scariness.GetDescription(),
+ MaybeDemangleGlobalName(global1.name), g1_loc.data());
+ ReportErrorSummary(error_msg.data());
+}
+
+void ErrorInvalidPointerPair::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ Report("ERROR: AddressSanitizer: %s: %p %p\n", scariness.GetDescription(),
+ (void *)addr1_description.Address(),
+ (void *)addr2_description.Address());
+ Printf("%s", d.Default());
+ GET_STACK_TRACE_FATAL(pc, bp);
+ stack.Print();
+ addr1_description.Print();
+ addr2_description.Print();
+ ReportErrorSummary(scariness.GetDescription(), &stack);
+}
+
+static bool AdjacentShadowValuesAreFullyPoisoned(u8 *s) {
+ return s[-1] > 127 && s[1] > 127;
+}
+
+ErrorGeneric::ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr,
+ bool is_write_, uptr access_size_)
+ : ErrorBase(tid),
+ addr_description(addr, access_size_, /*shouldLockThreadRegistry=*/false),
+ pc(pc_),
+ bp(bp_),
+ sp(sp_),
+ access_size(access_size_),
+ is_write(is_write_),
+ shadow_val(0) {
+ scariness.Clear();
+ if (access_size) {
+ if (access_size <= 9) {
+ char desr[] = "?-byte";
+ desr[0] = '0' + access_size;
+ scariness.Scare(access_size + access_size / 2, desr);
+ } else if (access_size >= 10) {
+ scariness.Scare(15, "multi-byte");
+ }
+ is_write ? scariness.Scare(20, "write") : scariness.Scare(1, "read");
+
+ // Determine the error type.
+ bug_descr = "unknown-crash";
+ if (AddrIsInMem(addr)) {
+ u8 *shadow_addr = (u8 *)MemToShadow(addr);
+ // If we are accessing 16 bytes, look at the second shadow byte.
+ if (*shadow_addr == 0 && access_size > ASAN_SHADOW_GRANULARITY)
+ shadow_addr++;
+ // If we are in the partial right redzone, look at the next shadow byte.
+ if (*shadow_addr > 0 && *shadow_addr < 128) shadow_addr++;
+ bool far_from_bounds = false;
+ shadow_val = *shadow_addr;
+ int bug_type_score = 0;
+ // For use-after-frees reads are almost as bad as writes.
+ int read_after_free_bonus = 0;
+ switch (shadow_val) {
+ case kAsanHeapLeftRedzoneMagic:
+ case kAsanArrayCookieMagic:
+ bug_descr = "heap-buffer-overflow";
+ bug_type_score = 10;
+ far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
+ break;
+ case kAsanHeapFreeMagic:
+ bug_descr = "heap-use-after-free";
+ bug_type_score = 20;
+ if (!is_write) read_after_free_bonus = 18;
+ break;
+ case kAsanStackLeftRedzoneMagic:
+ bug_descr = "stack-buffer-underflow";
+ bug_type_score = 25;
+ far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
+ break;
+ case kAsanInitializationOrderMagic:
+ bug_descr = "initialization-order-fiasco";
+ bug_type_score = 1;
+ break;
+ case kAsanStackMidRedzoneMagic:
+ case kAsanStackRightRedzoneMagic:
+ bug_descr = "stack-buffer-overflow";
+ bug_type_score = 25;
+ far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
+ break;
+ case kAsanStackAfterReturnMagic:
+ bug_descr = "stack-use-after-return";
+ bug_type_score = 30;
+ if (!is_write) read_after_free_bonus = 18;
+ break;
+ case kAsanUserPoisonedMemoryMagic:
+ bug_descr = "use-after-poison";
+ bug_type_score = 20;
+ break;
+ case kAsanContiguousContainerOOBMagic:
+ bug_descr = "container-overflow";
+ bug_type_score = 10;
+ break;
+ case kAsanStackUseAfterScopeMagic:
+ bug_descr = "stack-use-after-scope";
+ bug_type_score = 10;
+ break;
+ case kAsanGlobalRedzoneMagic:
+ bug_descr = "global-buffer-overflow";
+ bug_type_score = 10;
+ far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
+ break;
+ case kAsanIntraObjectRedzone:
+ bug_descr = "intra-object-overflow";
+ bug_type_score = 10;
+ break;
+ case kAsanAllocaLeftMagic:
+ case kAsanAllocaRightMagic:
+ bug_descr = "dynamic-stack-buffer-overflow";
+ bug_type_score = 25;
+ far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
+ break;
+ }
+ scariness.Scare(bug_type_score + read_after_free_bonus, bug_descr);
+ if (far_from_bounds) scariness.Scare(10, "far-from-bounds");
+ }
+ }
+}
+
+static void PrintContainerOverflowHint() {
+ Printf("HINT: if you don't care about these errors you may set "
+ "ASAN_OPTIONS=detect_container_overflow=0.\n"
+ "If you suspect a false positive see also: "
+ "https://github.com/google/sanitizers/wiki/"
+ "AddressSanitizerContainerOverflow.\n");
+}
+
+static void PrintShadowByte(InternalScopedString *str, const char *before,
+ u8 byte, const char *after = "\n") {
+ PrintMemoryByte(str, before, byte, /*in_shadow*/true, after);
+}
+
+static void PrintLegend(InternalScopedString *str) {
+ str->append(
+ "Shadow byte legend (one shadow byte represents %d "
+ "application bytes):\n",
+ (int)ASAN_SHADOW_GRANULARITY);
+ PrintShadowByte(str, " Addressable: ", 0);
+ str->append(" Partially addressable: ");
+ for (u8 i = 1; i < ASAN_SHADOW_GRANULARITY; i++)
+ PrintShadowByte(str, "", i, " ");
+ str->append("\n");
+ PrintShadowByte(str, " Heap left redzone: ",
+ kAsanHeapLeftRedzoneMagic);
+ PrintShadowByte(str, " Freed heap region: ", kAsanHeapFreeMagic);
+ PrintShadowByte(str, " Stack left redzone: ",
+ kAsanStackLeftRedzoneMagic);
+ PrintShadowByte(str, " Stack mid redzone: ",
+ kAsanStackMidRedzoneMagic);
+ PrintShadowByte(str, " Stack right redzone: ",
+ kAsanStackRightRedzoneMagic);
+ PrintShadowByte(str, " Stack after return: ",
+ kAsanStackAfterReturnMagic);
+ PrintShadowByte(str, " Stack use after scope: ",
+ kAsanStackUseAfterScopeMagic);
+ PrintShadowByte(str, " Global redzone: ", kAsanGlobalRedzoneMagic);
+ PrintShadowByte(str, " Global init order: ",
+ kAsanInitializationOrderMagic);
+ PrintShadowByte(str, " Poisoned by user: ",
+ kAsanUserPoisonedMemoryMagic);
+ PrintShadowByte(str, " Container overflow: ",
+ kAsanContiguousContainerOOBMagic);
+ PrintShadowByte(str, " Array cookie: ",
+ kAsanArrayCookieMagic);
+ PrintShadowByte(str, " Intra object redzone: ",
+ kAsanIntraObjectRedzone);
+ PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic);
+ PrintShadowByte(str, " Left alloca redzone: ", kAsanAllocaLeftMagic);
+ PrintShadowByte(str, " Right alloca redzone: ", kAsanAllocaRightMagic);
+}
+
+static void PrintShadowBytes(InternalScopedString *str, const char *before,
+ u8 *bytes, u8 *guilty, uptr n) {
+ Decorator d;
+ if (before)
+ str->append("%s%p:", before,
+ (void *)ShadowToMem(reinterpret_cast<uptr>(bytes)));
+ for (uptr i = 0; i < n; i++) {
+ u8 *p = bytes + i;
+ const char *before =
+ p == guilty ? "[" : (p - 1 == guilty && i != 0) ? "" : " ";
+ const char *after = p == guilty ? "]" : "";
+ PrintShadowByte(str, before, *p, after);
+ }
+ str->append("\n");
+}
+
+static void PrintShadowMemoryForAddress(uptr addr) {
+ if (!AddrIsInMem(addr)) return;
+ uptr shadow_addr = MemToShadow(addr);
+ const uptr n_bytes_per_row = 16;
+ uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
+ InternalScopedString str;
+ str.append("Shadow bytes around the buggy address:\n");
+ for (int i = -5; i <= 5; i++) {
+ uptr row_shadow_addr = aligned_shadow + i * n_bytes_per_row;
+ // Skip rows that would be outside the shadow range. This can happen when
+ // the user address is near the bottom, top, or shadow gap of the address
+ // space.
+ if (!AddrIsInShadow(row_shadow_addr)) continue;
+ const char *prefix = (i == 0) ? "=>" : " ";
+ PrintShadowBytes(&str, prefix, (u8 *)row_shadow_addr, (u8 *)shadow_addr,
+ n_bytes_per_row);
+ }
+ if (flags()->print_legend) PrintLegend(&str);
+ Printf("%s", str.data());
+}
+
+void ErrorGeneric::Print() {
+ Decorator d;
+ Printf("%s", d.Error());
+ uptr addr = addr_description.Address();
+ Report("ERROR: AddressSanitizer: %s on address %p at pc %p bp %p sp %p\n",
+ bug_descr, (void *)addr, (void *)pc, (void *)bp, (void *)sp);
+ Printf("%s", d.Default());
+
+ Printf("%s%s of size %zu at %p thread %s%s\n", d.Access(),
+ access_size ? (is_write ? "WRITE" : "READ") : "ACCESS", access_size,
+ (void *)addr, AsanThreadIdAndName(tid).c_str(), d.Default());
+
+ scariness.Print();
+ GET_STACK_TRACE_FATAL(pc, bp);
+ stack.Print();
+
+ // Pass bug_descr because we have a special case for
+ // initialization-order-fiasco
+ addr_description.Print(bug_descr);
+ if (shadow_val == kAsanContiguousContainerOOBMagic)
+ PrintContainerOverflowHint();
+ ReportErrorSummary(bug_descr, &stack);
+ PrintShadowMemoryForAddress(addr);
+}
+
+} // namespace __asan
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_errors.h b/contrib/libs/clang16-rt/lib/asan/asan_errors.h
new file mode 100644
index 00000000000..634f6da5443
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_errors.h
@@ -0,0 +1,479 @@
+//===-- asan_errors.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan-private header for error structures.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_ERRORS_H
+#define ASAN_ERRORS_H
+
+#include "asan_descriptions.h"
+#include "asan_scariness_score.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace __asan {
+
+// (*) VS2013 does not implement unrestricted unions, so we need a trivial
+// default constructor explicitly defined for each particular error.
+
+// None of the error classes own the stack traces mentioned in them.
+
+struct ErrorBase {
+ ScarinessScoreBase scariness;
+ u32 tid;
+
+ ErrorBase() = default; // (*)
+ explicit ErrorBase(u32 tid_) : tid(tid_) {}
+ ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) {
+ scariness.Clear();
+ scariness.Scare(initial_score, reason);
+ }
+};
+
+struct ErrorDeadlySignal : ErrorBase {
+ SignalContext signal;
+
+ ErrorDeadlySignal() = default; // (*)
+ ErrorDeadlySignal(u32 tid, const SignalContext &sig)
+ : ErrorBase(tid),
+ signal(sig) {
+ scariness.Clear();
+ if (signal.IsStackOverflow()) {
+ scariness.Scare(10, "stack-overflow");
+ } else if (!signal.is_memory_access) {
+ scariness.Scare(10, "signal");
+ } else if (signal.is_true_faulting_addr &&
+ signal.addr < GetPageSizeCached()) {
+ scariness.Scare(10, "null-deref");
+ } else if (signal.addr == signal.pc) {
+ scariness.Scare(60, "wild-jump");
+ } else if (signal.write_flag == SignalContext::Write) {
+ scariness.Scare(30, "wild-addr-write");
+ } else if (signal.write_flag == SignalContext::Read) {
+ scariness.Scare(20, "wild-addr-read");
+ } else {
+ scariness.Scare(25, "wild-addr");
+ }
+ }
+ void Print();
+};
+
+struct ErrorDoubleFree : ErrorBase {
+ const BufferedStackTrace *second_free_stack;
+ HeapAddressDescription addr_description;
+
+ ErrorDoubleFree() = default; // (*)
+ ErrorDoubleFree(u32 tid, BufferedStackTrace *stack, uptr addr)
+ : ErrorBase(tid, 42, "double-free"),
+ second_free_stack(stack) {
+ CHECK_GT(second_free_stack->size, 0);
+ GetHeapAddressInformation(addr, 1, &addr_description);
+ }
+ void Print();
+};
+
+struct ErrorNewDeleteTypeMismatch : ErrorBase {
+ const BufferedStackTrace *free_stack;
+ HeapAddressDescription addr_description;
+ uptr delete_size;
+ uptr delete_alignment;
+
+ ErrorNewDeleteTypeMismatch() = default; // (*)
+ ErrorNewDeleteTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
+ uptr delete_size_, uptr delete_alignment_)
+ : ErrorBase(tid, 10, "new-delete-type-mismatch"),
+ free_stack(stack),
+ delete_size(delete_size_),
+ delete_alignment(delete_alignment_) {
+ GetHeapAddressInformation(addr, 1, &addr_description);
+ }
+ void Print();
+};
+
+struct ErrorFreeNotMalloced : ErrorBase {
+ const BufferedStackTrace *free_stack;
+ AddressDescription addr_description;
+
+ ErrorFreeNotMalloced() = default; // (*)
+ ErrorFreeNotMalloced(u32 tid, BufferedStackTrace *stack, uptr addr)
+ : ErrorBase(tid, 40, "bad-free"),
+ free_stack(stack),
+ addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
+ void Print();
+};
+
+struct ErrorAllocTypeMismatch : ErrorBase {
+ const BufferedStackTrace *dealloc_stack;
+ AllocType alloc_type, dealloc_type;
+ AddressDescription addr_description;
+
+ ErrorAllocTypeMismatch() = default; // (*)
+ ErrorAllocTypeMismatch(u32 tid, BufferedStackTrace *stack, uptr addr,
+ AllocType alloc_type_, AllocType dealloc_type_)
+ : ErrorBase(tid, 10, "alloc-dealloc-mismatch"),
+ dealloc_stack(stack),
+ alloc_type(alloc_type_),
+ dealloc_type(dealloc_type_),
+ addr_description(addr, 1, false) {}
+ void Print();
+};
+
+struct ErrorMallocUsableSizeNotOwned : ErrorBase {
+ const BufferedStackTrace *stack;
+ AddressDescription addr_description;
+
+ ErrorMallocUsableSizeNotOwned() = default; // (*)
+ ErrorMallocUsableSizeNotOwned(u32 tid, BufferedStackTrace *stack_, uptr addr)
+ : ErrorBase(tid, 10, "bad-malloc_usable_size"),
+ stack(stack_),
+ addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
+ void Print();
+};
+
+struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
+ const BufferedStackTrace *stack;
+ AddressDescription addr_description;
+
+ ErrorSanitizerGetAllocatedSizeNotOwned() = default; // (*)
+ ErrorSanitizerGetAllocatedSizeNotOwned(u32 tid, BufferedStackTrace *stack_,
+ uptr addr)
+ : ErrorBase(tid, 10, "bad-__sanitizer_get_allocated_size"),
+ stack(stack_),
+ addr_description(addr, /*shouldLockThreadRegistry=*/false) {}
+ void Print();
+};
+
+struct ErrorCallocOverflow : ErrorBase {
+ const BufferedStackTrace *stack;
+ uptr count;
+ uptr size;
+
+ ErrorCallocOverflow() = default; // (*)
+ ErrorCallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
+ uptr size_)
+ : ErrorBase(tid, 10, "calloc-overflow"),
+ stack(stack_),
+ count(count_),
+ size(size_) {}
+ void Print();
+};
+
+struct ErrorReallocArrayOverflow : ErrorBase {
+ const BufferedStackTrace *stack;
+ uptr count;
+ uptr size;
+
+ ErrorReallocArrayOverflow() = default; // (*)
+ ErrorReallocArrayOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
+ uptr size_)
+ : ErrorBase(tid, 10, "reallocarray-overflow"),
+ stack(stack_),
+ count(count_),
+ size(size_) {}
+ void Print();
+};
+
+struct ErrorPvallocOverflow : ErrorBase {
+ const BufferedStackTrace *stack;
+ uptr size;
+
+ ErrorPvallocOverflow() = default; // (*)
+ ErrorPvallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr size_)
+ : ErrorBase(tid, 10, "pvalloc-overflow"),
+ stack(stack_),
+ size(size_) {}
+ void Print();
+};
+
+struct ErrorInvalidAllocationAlignment : ErrorBase {
+ const BufferedStackTrace *stack;
+ uptr alignment;
+
+ ErrorInvalidAllocationAlignment() = default; // (*)
+ ErrorInvalidAllocationAlignment(u32 tid, BufferedStackTrace *stack_,
+ uptr alignment_)
+ : ErrorBase(tid, 10, "invalid-allocation-alignment"),
+ stack(stack_),
+ alignment(alignment_) {}
+ void Print();
+};
+
+struct ErrorInvalidAlignedAllocAlignment : ErrorBase {
+ const BufferedStackTrace *stack;
+ uptr size;
+ uptr alignment;
+
+ ErrorInvalidAlignedAllocAlignment() = default; // (*)
+ ErrorInvalidAlignedAllocAlignment(u32 tid, BufferedStackTrace *stack_,
+ uptr size_, uptr alignment_)
+ : ErrorBase(tid, 10, "invalid-aligned-alloc-alignment"),
+ stack(stack_),
+ size(size_),
+ alignment(alignment_) {}
+ void Print();
+};
+
+struct ErrorInvalidPosixMemalignAlignment : ErrorBase {
+ const BufferedStackTrace *stack;
+ uptr alignment;
+
+ ErrorInvalidPosixMemalignAlignment() = default; // (*)
+ ErrorInvalidPosixMemalignAlignment(u32 tid, BufferedStackTrace *stack_,
+ uptr alignment_)
+ : ErrorBase(tid, 10, "invalid-posix-memalign-alignment"),
+ stack(stack_),
+ alignment(alignment_) {}
+ void Print();
+};
+
+struct ErrorAllocationSizeTooBig : ErrorBase {
+ const BufferedStackTrace *stack;
+ uptr user_size;
+ uptr total_size;
+ uptr max_size;
+
+ ErrorAllocationSizeTooBig() = default; // (*)
+ ErrorAllocationSizeTooBig(u32 tid, BufferedStackTrace *stack_,
+ uptr user_size_, uptr total_size_, uptr max_size_)
+ : ErrorBase(tid, 10, "allocation-size-too-big"),
+ stack(stack_),
+ user_size(user_size_),
+ total_size(total_size_),
+ max_size(max_size_) {}
+ void Print();
+};
+
+struct ErrorRssLimitExceeded : ErrorBase {
+ const BufferedStackTrace *stack;
+
+ ErrorRssLimitExceeded() = default; // (*)
+ ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_)
+ : ErrorBase(tid, 10, "rss-limit-exceeded"),
+ stack(stack_) {}
+ void Print();
+};
+
+struct ErrorOutOfMemory : ErrorBase {
+ const BufferedStackTrace *stack;
+ uptr requested_size;
+
+ ErrorOutOfMemory() = default; // (*)
+ ErrorOutOfMemory(u32 tid, BufferedStackTrace *stack_, uptr requested_size_)
+ : ErrorBase(tid, 10, "out-of-memory"),
+ stack(stack_),
+ requested_size(requested_size_) {}
+ void Print();
+};
+
+struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
+ const BufferedStackTrace *stack;
+ uptr length1, length2;
+ AddressDescription addr1_description;
+ AddressDescription addr2_description;
+ const char *function;
+
+ ErrorStringFunctionMemoryRangesOverlap() = default; // (*)
+ ErrorStringFunctionMemoryRangesOverlap(u32 tid, BufferedStackTrace *stack_,
+ uptr addr1, uptr length1_, uptr addr2,
+ uptr length2_, const char *function_)
+ : ErrorBase(tid),
+ stack(stack_),
+ length1(length1_),
+ length2(length2_),
+ addr1_description(addr1, length1, /*shouldLockThreadRegistry=*/false),
+ addr2_description(addr2, length2, /*shouldLockThreadRegistry=*/false),
+ function(function_) {
+ char bug_type[100];
+ internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
+ scariness.Clear();
+ scariness.Scare(10, bug_type);
+ }
+ void Print();
+};
+
+struct ErrorStringFunctionSizeOverflow : ErrorBase {
+ const BufferedStackTrace *stack;
+ AddressDescription addr_description;
+ uptr size;
+
+ ErrorStringFunctionSizeOverflow() = default; // (*)
+ ErrorStringFunctionSizeOverflow(u32 tid, BufferedStackTrace *stack_,
+ uptr addr, uptr size_)
+ : ErrorBase(tid, 10, "negative-size-param"),
+ stack(stack_),
+ addr_description(addr, /*shouldLockThreadRegistry=*/false),
+ size(size_) {}
+ void Print();
+};
+
+struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
+ const BufferedStackTrace *stack;
+ uptr beg, end, old_mid, new_mid;
+
+ ErrorBadParamsToAnnotateContiguousContainer() = default; // (*)
+ // PS4: Do we want an AddressDescription for beg?
+ ErrorBadParamsToAnnotateContiguousContainer(u32 tid,
+ BufferedStackTrace *stack_,
+ uptr beg_, uptr end_,
+ uptr old_mid_, uptr new_mid_)
+ : ErrorBase(tid, 10, "bad-__sanitizer_annotate_contiguous_container"),
+ stack(stack_),
+ beg(beg_),
+ end(end_),
+ old_mid(old_mid_),
+ new_mid(new_mid_) {}
+ void Print();
+};
+
+struct ErrorBadParamsToAnnotateDoubleEndedContiguousContainer : ErrorBase {
+ const BufferedStackTrace *stack;
+ uptr storage_beg, storage_end, old_container_beg, old_container_end,
+ new_container_beg, new_container_end;
+
+ ErrorBadParamsToAnnotateDoubleEndedContiguousContainer() = default; // (*)
+ ErrorBadParamsToAnnotateDoubleEndedContiguousContainer(
+ u32 tid, BufferedStackTrace *stack_, uptr storage_beg_, uptr storage_end_,
+ uptr old_container_beg_, uptr old_container_end_, uptr new_container_beg_,
+ uptr new_container_end_)
+ : ErrorBase(tid, 10,
+ "bad-__sanitizer_annotate_double_ended_contiguous_container"),
+ stack(stack_),
+ storage_beg(storage_beg_),
+ storage_end(storage_end_),
+ old_container_beg(old_container_beg_),
+ old_container_end(old_container_end_),
+ new_container_beg(new_container_beg_),
+ new_container_end(new_container_end_) {}
+ void Print();
+};
+
+struct ErrorODRViolation : ErrorBase {
+ __asan_global global1, global2;
+ u32 stack_id1, stack_id2;
+
+ ErrorODRViolation() = default; // (*)
+ ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_,
+ const __asan_global *g2, u32 stack_id2_)
+ : ErrorBase(tid, 10, "odr-violation"),
+ global1(*g1),
+ global2(*g2),
+ stack_id1(stack_id1_),
+ stack_id2(stack_id2_) {}
+ void Print();
+};
+
+struct ErrorInvalidPointerPair : ErrorBase {
+ uptr pc, bp, sp;
+ AddressDescription addr1_description;
+ AddressDescription addr2_description;
+
+ ErrorInvalidPointerPair() = default; // (*)
+ ErrorInvalidPointerPair(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr p1,
+ uptr p2)
+ : ErrorBase(tid, 10, "invalid-pointer-pair"),
+ pc(pc_),
+ bp(bp_),
+ sp(sp_),
+ addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
+ addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
+ void Print();
+};
+
+struct ErrorGeneric : ErrorBase {
+ AddressDescription addr_description;
+ uptr pc, bp, sp;
+ uptr access_size;
+ const char *bug_descr;
+ bool is_write;
+ u8 shadow_val;
+
+ ErrorGeneric() = default; // (*)
+ ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr, bool is_write_,
+ uptr access_size_);
+ void Print();
+};
+
+// clang-format off
+#define ASAN_FOR_EACH_ERROR_KIND(macro) \
+ macro(DeadlySignal) \
+ macro(DoubleFree) \
+ macro(NewDeleteTypeMismatch) \
+ macro(FreeNotMalloced) \
+ macro(AllocTypeMismatch) \
+ macro(MallocUsableSizeNotOwned) \
+ macro(SanitizerGetAllocatedSizeNotOwned) \
+ macro(CallocOverflow) \
+ macro(ReallocArrayOverflow) \
+ macro(PvallocOverflow) \
+ macro(InvalidAllocationAlignment) \
+ macro(InvalidAlignedAllocAlignment) \
+ macro(InvalidPosixMemalignAlignment) \
+ macro(AllocationSizeTooBig) \
+ macro(RssLimitExceeded) \
+ macro(OutOfMemory) \
+ macro(StringFunctionMemoryRangesOverlap) \
+ macro(StringFunctionSizeOverflow) \
+ macro(BadParamsToAnnotateContiguousContainer) \
+ macro(BadParamsToAnnotateDoubleEndedContiguousContainer) \
+ macro(ODRViolation) \
+ macro(InvalidPointerPair) \
+ macro(Generic)
+// clang-format on
+
+#define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,
+#define ASAN_ERROR_DESCRIPTION_MEMBER(name) Error##name name;
+#define ASAN_ERROR_DESCRIPTION_CONSTRUCTOR(name) \
+ ErrorDescription(Error##name const &e) : kind(kErrorKind##name) { \
+ internal_memcpy(&name, &e, sizeof(name)); \
+ }
+#define ASAN_ERROR_DESCRIPTION_PRINT(name) \
+ case kErrorKind##name: \
+ return name.Print();
+
+enum ErrorKind {
+ kErrorKindInvalid = 0,
+ ASAN_FOR_EACH_ERROR_KIND(ASAN_DEFINE_ERROR_KIND)
+};
+
+struct ErrorDescription {
+ ErrorKind kind;
+ // We're using a tagged union because it allows us to have a trivially
+ // copiable type and use the same structures as the public interface.
+ //
+ // We can add a wrapper around it to make it "more c++-like", but that would
+ // add a lot of code and the benefit wouldn't be that big.
+ union {
+ ErrorBase Base;
+ ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
+ };
+
+ ErrorDescription() { internal_memset(this, 0, sizeof(*this)); }
+ explicit ErrorDescription(LinkerInitialized) {}
+ ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_CONSTRUCTOR)
+
+ bool IsValid() { return kind != kErrorKindInvalid; }
+ void Print() {
+ switch (kind) {
+ ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_PRINT)
+ case kErrorKindInvalid:
+ CHECK(0);
+ }
+ CHECK(0);
+ }
+};
+
+#undef ASAN_FOR_EACH_ERROR_KIND
+#undef ASAN_DEFINE_ERROR_KIND
+#undef ASAN_ERROR_DESCRIPTION_MEMBER
+#undef ASAN_ERROR_DESCRIPTION_CONSTRUCTOR
+#undef ASAN_ERROR_DESCRIPTION_PRINT
+
+} // namespace __asan
+
+#endif // ASAN_ERRORS_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_fake_stack.cpp b/contrib/libs/clang16-rt/lib/asan/asan_fake_stack.cpp
new file mode 100644
index 00000000000..74a039b6579
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_fake_stack.cpp
@@ -0,0 +1,310 @@
+//===-- asan_fake_stack.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// FakeStack is used to detect use-after-return bugs.
+//===----------------------------------------------------------------------===//
+
+#include "asan_allocator.h"
+#include "asan_poisoning.h"
+#include "asan_thread.h"
+
+namespace __asan {
+
+static const u64 kMagic1 = kAsanStackAfterReturnMagic;
+static const u64 kMagic2 = (kMagic1 << 8) | kMagic1;
+static const u64 kMagic4 = (kMagic2 << 16) | kMagic2;
+static const u64 kMagic8 = (kMagic4 << 32) | kMagic4;
+
+static const u64 kAllocaRedzoneSize = 32UL;
+static const u64 kAllocaRedzoneMask = 31UL;
+
+// For small size classes inline PoisonShadow for better performance.
+ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) {
+ u64 *shadow = reinterpret_cast<u64*>(MemToShadow(ptr));
+ if (ASAN_SHADOW_SCALE == 3 && class_id <= 6) {
+ // This code expects ASAN_SHADOW_SCALE=3.
+ for (uptr i = 0; i < (((uptr)1) << class_id); i++) {
+ shadow[i] = magic;
+ // Make sure this does not become memset.
+ SanitizerBreakOptimization(nullptr);
+ }
+ } else {
+ // The size class is too big, it's cheaper to poison only size bytes.
+ PoisonShadow(ptr, size, static_cast<u8>(magic));
+ }
+}
+
+FakeStack *FakeStack::Create(uptr stack_size_log) {
+ static uptr kMinStackSizeLog = 16;
+ static uptr kMaxStackSizeLog = FIRST_32_SECOND_64(24, 28);
+ if (stack_size_log < kMinStackSizeLog)
+ stack_size_log = kMinStackSizeLog;
+ if (stack_size_log > kMaxStackSizeLog)
+ stack_size_log = kMaxStackSizeLog;
+ uptr size = RequiredSize(stack_size_log);
+ FakeStack *res = reinterpret_cast<FakeStack *>(
+ flags()->uar_noreserve ? MmapNoReserveOrDie(size, "FakeStack")
+ : MmapOrDie(size, "FakeStack"));
+ res->stack_size_log_ = stack_size_log;
+ u8 *p = reinterpret_cast<u8 *>(res);
+ VReport(1,
+ "T%d: FakeStack created: %p -- %p stack_size_log: %zd; "
+ "mmapped %zdK, noreserve=%d \n",
+ GetCurrentTidOrInvalid(), (void *)p,
+ (void *)(p + FakeStack::RequiredSize(stack_size_log)), stack_size_log,
+ size >> 10, flags()->uar_noreserve);
+ return res;
+}
+
+void FakeStack::Destroy(int tid) {
+ PoisonAll(0);
+ if (Verbosity() >= 2) {
+ InternalScopedString str;
+ for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++)
+ str.append("%zd: %zd/%zd; ", class_id, hint_position_[class_id],
+ NumberOfFrames(stack_size_log(), class_id));
+ Report("T%d: FakeStack destroyed: %s\n", tid, str.data());
+ }
+ uptr size = RequiredSize(stack_size_log_);
+ FlushUnneededASanShadowMemory(reinterpret_cast<uptr>(this), size);
+ UnmapOrDie(this, size);
+}
+
+void FakeStack::PoisonAll(u8 magic) {
+ PoisonShadow(reinterpret_cast<uptr>(this), RequiredSize(stack_size_log()),
+ magic);
+}
+
+#if !defined(_MSC_VER) || defined(__clang__)
+ALWAYS_INLINE USED
+#endif
+FakeFrame *FakeStack::Allocate(uptr stack_size_log, uptr class_id,
+ uptr real_stack) {
+ CHECK_LT(class_id, kNumberOfSizeClasses);
+ if (needs_gc_)
+ GC(real_stack);
+ uptr &hint_position = hint_position_[class_id];
+ const int num_iter = NumberOfFrames(stack_size_log, class_id);
+ u8 *flags = GetFlags(stack_size_log, class_id);
+ for (int i = 0; i < num_iter; i++) {
+ uptr pos = ModuloNumberOfFrames(stack_size_log, class_id, hint_position++);
+ // This part is tricky. On one hand, checking and setting flags[pos]
+ // should be atomic to ensure async-signal safety. But on the other hand,
+ // if the signal arrives between checking and setting flags[pos], the
+ // signal handler's fake stack will start from a different hint_position
+ // and so will not touch this particular byte. So, it is safe to do this
+ // with regular non-atomic load and store (at least I was not able to make
+ // this code crash).
+ if (flags[pos]) continue;
+ flags[pos] = 1;
+ FakeFrame *res = reinterpret_cast<FakeFrame *>(
+ GetFrame(stack_size_log, class_id, pos));
+ res->real_stack = real_stack;
+ *SavedFlagPtr(reinterpret_cast<uptr>(res), class_id) = &flags[pos];
+ return res;
+ }
+ return nullptr; // We are out of fake stack.
+}
+
+uptr FakeStack::AddrIsInFakeStack(uptr ptr, uptr *frame_beg, uptr *frame_end) {
+ uptr stack_size_log = this->stack_size_log();
+ uptr beg = reinterpret_cast<uptr>(GetFrame(stack_size_log, 0, 0));
+ uptr end = reinterpret_cast<uptr>(this) + RequiredSize(stack_size_log);
+ if (ptr < beg || ptr >= end) return 0;
+ uptr class_id = (ptr - beg) >> stack_size_log;
+ uptr base = beg + (class_id << stack_size_log);
+ CHECK_LE(base, ptr);
+ CHECK_LT(ptr, base + (((uptr)1) << stack_size_log));
+ uptr pos = (ptr - base) >> (kMinStackFrameSizeLog + class_id);
+ uptr res = base + pos * BytesInSizeClass(class_id);
+ *frame_end = res + BytesInSizeClass(class_id);
+ *frame_beg = res + sizeof(FakeFrame);
+ return res;
+}
+
+void FakeStack::HandleNoReturn() {
+ needs_gc_ = true;
+}
+
+// When throw, longjmp or some such happens we don't call OnFree() and
+// as the result may leak one or more fake frames, but the good news is that
+// we are notified about all such events by HandleNoReturn().
+// If we recently had such no-return event we need to collect garbage frames.
+// We do it based on their 'real_stack' values -- everything that is lower
+// than the current real_stack is garbage.
+NOINLINE void FakeStack::GC(uptr real_stack) {
+ for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++) {
+ u8 *flags = GetFlags(stack_size_log(), class_id);
+ for (uptr i = 0, n = NumberOfFrames(stack_size_log(), class_id); i < n;
+ i++) {
+ if (flags[i] == 0) continue; // not allocated.
+ FakeFrame *ff = reinterpret_cast<FakeFrame *>(
+ GetFrame(stack_size_log(), class_id, i));
+ if (ff->real_stack < real_stack) {
+ flags[i] = 0;
+ }
+ }
+ }
+ needs_gc_ = false;
+}
+
+void FakeStack::ForEachFakeFrame(RangeIteratorCallback callback, void *arg) {
+ for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++) {
+ u8 *flags = GetFlags(stack_size_log(), class_id);
+ for (uptr i = 0, n = NumberOfFrames(stack_size_log(), class_id); i < n;
+ i++) {
+ if (flags[i] == 0) continue; // not allocated.
+ FakeFrame *ff = reinterpret_cast<FakeFrame *>(
+ GetFrame(stack_size_log(), class_id, i));
+ uptr begin = reinterpret_cast<uptr>(ff);
+ callback(begin, begin + FakeStack::BytesInSizeClass(class_id), arg);
+ }
+ }
+}
+
+#if (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_FUCHSIA
+static THREADLOCAL FakeStack *fake_stack_tls;
+
+FakeStack *GetTLSFakeStack() {
+ return fake_stack_tls;
+}
+void SetTLSFakeStack(FakeStack *fs) {
+ fake_stack_tls = fs;
+}
+#else
+FakeStack *GetTLSFakeStack() { return 0; }
+void SetTLSFakeStack(FakeStack *fs) { }
+#endif // (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_FUCHSIA
+
+static FakeStack *GetFakeStack() {
+ AsanThread *t = GetCurrentThread();
+ if (!t) return nullptr;
+ return t->get_or_create_fake_stack();
+}
+
+static FakeStack *GetFakeStackFast() {
+ if (FakeStack *fs = GetTLSFakeStack())
+ return fs;
+ if (!__asan_option_detect_stack_use_after_return)
+ return nullptr;
+ return GetFakeStack();
+}
+
+static FakeStack *GetFakeStackFastAlways() {
+ if (FakeStack *fs = GetTLSFakeStack())
+ return fs;
+ return GetFakeStack();
+}
+
+static ALWAYS_INLINE uptr OnMalloc(uptr class_id, uptr size) {
+ FakeStack *fs = GetFakeStackFast();
+ if (!fs) return 0;
+ uptr local_stack;
+ uptr real_stack = reinterpret_cast<uptr>(&local_stack);
+ FakeFrame *ff = fs->Allocate(fs->stack_size_log(), class_id, real_stack);
+ if (!ff) return 0; // Out of fake stack.
+ uptr ptr = reinterpret_cast<uptr>(ff);
+ SetShadow(ptr, size, class_id, 0);
+ return ptr;
+}
+
+static ALWAYS_INLINE uptr OnMallocAlways(uptr class_id, uptr size) {
+ FakeStack *fs = GetFakeStackFastAlways();
+ if (!fs)
+ return 0;
+ uptr local_stack;
+ uptr real_stack = reinterpret_cast<uptr>(&local_stack);
+ FakeFrame *ff = fs->Allocate(fs->stack_size_log(), class_id, real_stack);
+ if (!ff)
+ return 0; // Out of fake stack.
+ uptr ptr = reinterpret_cast<uptr>(ff);
+ SetShadow(ptr, size, class_id, 0);
+ return ptr;
+}
+
+static ALWAYS_INLINE void OnFree(uptr ptr, uptr class_id, uptr size) {
+ FakeStack::Deallocate(ptr, class_id);
+ SetShadow(ptr, size, class_id, kMagic8);
+}
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan;
+#define DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(class_id) \
+ extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr \
+ __asan_stack_malloc_##class_id(uptr size) { \
+ return OnMalloc(class_id, size); \
+ } \
+ extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr \
+ __asan_stack_malloc_always_##class_id(uptr size) { \
+ return OnMallocAlways(class_id, size); \
+ } \
+ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __asan_stack_free_##class_id( \
+ uptr ptr, uptr size) { \
+ OnFree(ptr, class_id, size); \
+ }
+
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(0)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(1)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(2)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(3)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(4)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(5)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(6)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(7)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(8)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(9)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(10)
+
+extern "C" {
+// TODO: remove this method and fix tests that use it by setting
+// -asan-use-after-return=never, after modal UAR flag lands
+// (https://github.com/google/sanitizers/issues/1394)
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__asan_get_current_fake_stack() { return GetFakeStackFast(); }
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,
+ void **end) {
+ FakeStack *fs = reinterpret_cast<FakeStack*>(fake_stack);
+ if (!fs) return nullptr;
+ uptr frame_beg, frame_end;
+ FakeFrame *frame = reinterpret_cast<FakeFrame *>(fs->AddrIsInFakeStack(
+ reinterpret_cast<uptr>(addr), &frame_beg, &frame_end));
+ if (!frame) return nullptr;
+ if (frame->magic != kCurrentStackFrameMagic)
+ return nullptr;
+ if (beg) *beg = reinterpret_cast<void*>(frame_beg);
+ if (end) *end = reinterpret_cast<void*>(frame_end);
+ return reinterpret_cast<void*>(frame->real_stack);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __asan_alloca_poison(uptr addr, uptr size) {
+ uptr LeftRedzoneAddr = addr - kAllocaRedzoneSize;
+ uptr PartialRzAddr = addr + size;
+ uptr RightRzAddr = (PartialRzAddr + kAllocaRedzoneMask) & ~kAllocaRedzoneMask;
+ uptr PartialRzAligned = PartialRzAddr & ~(ASAN_SHADOW_GRANULARITY - 1);
+ FastPoisonShadow(LeftRedzoneAddr, kAllocaRedzoneSize, kAsanAllocaLeftMagic);
+ FastPoisonShadowPartialRightRedzone(
+ PartialRzAligned, PartialRzAddr % ASAN_SHADOW_GRANULARITY,
+ RightRzAddr - PartialRzAligned, kAsanAllocaRightMagic);
+ FastPoisonShadow(RightRzAddr, kAllocaRedzoneSize, kAsanAllocaRightMagic);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __asan_allocas_unpoison(uptr top, uptr bottom) {
+ if ((!top) || (top > bottom)) return;
+ REAL(memset)
+ (reinterpret_cast<void *>(MemToShadow(top)), 0,
+ (bottom - top) / ASAN_SHADOW_GRANULARITY);
+}
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_fake_stack.h b/contrib/libs/clang16-rt/lib/asan/asan_fake_stack.h
new file mode 100644
index 00000000000..270a19816d6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_fake_stack.h
@@ -0,0 +1,175 @@
+//===-- asan_fake_stack.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan-private header for asan_fake_stack.cpp, implements FakeStack.
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_FAKE_STACK_H
+#define ASAN_FAKE_STACK_H
+
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace __asan {
+
+// Fake stack frame contains local variables of one function.
+struct FakeFrame {
+ uptr magic; // Modified by the instrumented code.
+ uptr descr; // Modified by the instrumented code.
+ uptr pc; // Modified by the instrumented code.
+ uptr real_stack;
+};
+
+// For each thread we create a fake stack and place stack objects on this fake
+// stack instead of the real stack. The fake stack is not really a stack but
+// a fast malloc-like allocator so that when a function exits the fake stack
+// is not popped but remains there for quite some time until gets used again.
+// So, we poison the objects on the fake stack when function returns.
+// It helps us find use-after-return bugs.
+//
+// The FakeStack objects is allocated by a single mmap call and has no other
+// pointers. The size of the fake stack depends on the actual thread stack size
+// and thus can not be a constant.
+// stack_size is a power of two greater or equal to the thread's stack size;
+// we store it as its logarithm (stack_size_log).
+// FakeStack has kNumberOfSizeClasses (11) size classes, each size class
+// is a power of two, starting from 64 bytes. Each size class occupies
+// stack_size bytes and thus can allocate
+// NumberOfFrames=(stack_size/BytesInSizeClass) fake frames (also a power of 2).
+// For each size class we have NumberOfFrames allocation flags,
+// each flag indicates whether the given frame is currently allocated.
+// All flags for size classes 0 .. 10 are stored in a single contiguous region
+// followed by another contiguous region which contains the actual memory for
+// size classes. The addresses are computed by GetFlags and GetFrame without
+// any memory accesses solely based on 'this' and stack_size_log.
+// Allocate() flips the appropriate allocation flag atomically, thus achieving
+// async-signal safety.
+// This allocator does not have quarantine per se, but it tries to allocate the
+// frames in round robin fashion to maximize the delay between a deallocation
+// and the next allocation.
+class FakeStack {
+ static const uptr kMinStackFrameSizeLog = 6; // Min frame is 64B.
+ static const uptr kMaxStackFrameSizeLog = 16; // Max stack frame is 64K.
+
+ public:
+ static const uptr kNumberOfSizeClasses =
+ kMaxStackFrameSizeLog - kMinStackFrameSizeLog + 1;
+
+ // CTOR: create the FakeStack as a single mmap-ed object.
+ static FakeStack *Create(uptr stack_size_log);
+
+ void Destroy(int tid);
+
+ // stack_size_log is at least 15 (stack_size >= 32K).
+ static uptr SizeRequiredForFlags(uptr stack_size_log) {
+ return ((uptr)1) << (stack_size_log + 1 - kMinStackFrameSizeLog);
+ }
+
+ // Each size class occupies stack_size bytes.
+ static uptr SizeRequiredForFrames(uptr stack_size_log) {
+ return (((uptr)1) << stack_size_log) * kNumberOfSizeClasses;
+ }
+
+ // Number of bytes requires for the whole object.
+ static uptr RequiredSize(uptr stack_size_log) {
+ return kFlagsOffset + SizeRequiredForFlags(stack_size_log) +
+ SizeRequiredForFrames(stack_size_log);
+ }
+
+ // Offset of the given flag from the first flag.
+ // The flags for class 0 begin at offset 000000000
+ // The flags for class 1 begin at offset 100000000
+ // ....................2................ 110000000
+ // ....................3................ 111000000
+ // and so on.
+ static uptr FlagsOffset(uptr stack_size_log, uptr class_id) {
+ uptr t = kNumberOfSizeClasses - 1 - class_id;
+ const uptr all_ones = (((uptr)1) << (kNumberOfSizeClasses - 1)) - 1;
+ return ((all_ones >> t) << t) << (stack_size_log - 15);
+ }
+
+ static uptr NumberOfFrames(uptr stack_size_log, uptr class_id) {
+ return ((uptr)1) << (stack_size_log - kMinStackFrameSizeLog - class_id);
+ }
+
+ // Divide n by the number of frames in size class.
+ static uptr ModuloNumberOfFrames(uptr stack_size_log, uptr class_id, uptr n) {
+ return n & (NumberOfFrames(stack_size_log, class_id) - 1);
+ }
+
+ // The pointer to the flags of the given class_id.
+ u8 *GetFlags(uptr stack_size_log, uptr class_id) {
+ return reinterpret_cast<u8 *>(this) + kFlagsOffset +
+ FlagsOffset(stack_size_log, class_id);
+ }
+
+ // Get frame by class_id and pos.
+ u8 *GetFrame(uptr stack_size_log, uptr class_id, uptr pos) {
+ return reinterpret_cast<u8 *>(this) + kFlagsOffset +
+ SizeRequiredForFlags(stack_size_log) +
+ (((uptr)1) << stack_size_log) * class_id +
+ BytesInSizeClass(class_id) * pos;
+ }
+
+ // Allocate the fake frame.
+ FakeFrame *Allocate(uptr stack_size_log, uptr class_id, uptr real_stack);
+
+ // Deallocate the fake frame: read the saved flag address and write 0 there.
+ static void Deallocate(uptr x, uptr class_id) {
+ **SavedFlagPtr(x, class_id) = 0;
+ }
+
+ // Poison the entire FakeStack's shadow with the magic value.
+ void PoisonAll(u8 magic);
+
+ // Return the beginning of the FakeFrame or 0 if the address is not ours.
+ uptr AddrIsInFakeStack(uptr addr, uptr *frame_beg, uptr *frame_end);
+ USED uptr AddrIsInFakeStack(uptr addr) {
+ uptr t1, t2;
+ return AddrIsInFakeStack(addr, &t1, &t2);
+ }
+
+ // Number of bytes in a fake frame of this size class.
+ static uptr BytesInSizeClass(uptr class_id) {
+ return ((uptr)1) << (class_id + kMinStackFrameSizeLog);
+ }
+
+ // The fake frame is guaranteed to have a right redzone.
+ // We use the last word of that redzone to store the address of the flag
+ // that corresponds to the current frame to make faster deallocation.
+ static u8 **SavedFlagPtr(uptr x, uptr class_id) {
+ return reinterpret_cast<u8 **>(x + BytesInSizeClass(class_id) - sizeof(x));
+ }
+
+ uptr stack_size_log() const { return stack_size_log_; }
+
+ void HandleNoReturn();
+ void GC(uptr real_stack);
+
+ void ForEachFakeFrame(RangeIteratorCallback callback, void *arg);
+
+ private:
+ FakeStack() { }
+ static const uptr kFlagsOffset = 4096; // This is were the flags begin.
+ // Must match the number of uses of DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID
+ COMPILER_CHECK(kNumberOfSizeClasses == 11);
+ static const uptr kMaxStackMallocSize = ((uptr)1) << kMaxStackFrameSizeLog;
+
+ uptr hint_position_[kNumberOfSizeClasses];
+ uptr stack_size_log_;
+ // a bit is set if something was allocated from the corresponding size class.
+ bool needs_gc_;
+};
+
+FakeStack *GetTLSFakeStack();
+void SetTLSFakeStack(FakeStack *fs);
+
+} // namespace __asan
+
+#endif // ASAN_FAKE_STACK_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_flags.cpp b/contrib/libs/clang16-rt/lib/asan/asan_flags.cpp
new file mode 100644
index 00000000000..23989843323
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_flags.cpp
@@ -0,0 +1,206 @@
+//===-- asan_flags.cpp ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan flag parsing logic.
+//===----------------------------------------------------------------------===//
+
+#include "asan_activation.h"
+#include "asan_flags.h"
+#include "asan_interface_internal.h"
+#include "asan_stack.h"
+#include "lsan/lsan_common.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "ubsan/ubsan_flags.h"
+#include "ubsan/ubsan_platform.h"
+
+namespace __asan {
+
+Flags asan_flags_dont_use_directly; // use via flags().
+
+static const char *MaybeUseAsanDefaultOptionsCompileDefinition() {
+#ifdef ASAN_DEFAULT_OPTIONS
+ return SANITIZER_STRINGIFY(ASAN_DEFAULT_OPTIONS);
+#else
+ return "";
+#endif
+}
+
+void Flags::SetDefaults() {
+#define ASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "asan_flags.inc"
+#undef ASAN_FLAG
+}
+
+static void RegisterAsanFlags(FlagParser *parser, Flags *f) {
+#define ASAN_FLAG(Type, Name, DefaultValue, Description) \
+ RegisterFlag(parser, #Name, Description, &f->Name);
+#include "asan_flags.inc"
+#undef ASAN_FLAG
+}
+
+void InitializeFlags() {
+ // Set the default values and prepare for parsing ASan and common flags.
+ SetCommonFlagsDefaults();
+ {
+ CommonFlags cf;
+ cf.CopyFrom(*common_flags());
+ cf.detect_leaks = cf.detect_leaks && CAN_SANITIZE_LEAKS;
+ cf.external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH");
+ cf.malloc_context_size = kDefaultMallocContextSize;
+ cf.intercept_tls_get_addr = true;
+ cf.exitcode = 1;
+ OverrideCommonFlags(cf);
+ }
+ Flags *f = flags();
+ f->SetDefaults();
+
+ FlagParser asan_parser;
+ RegisterAsanFlags(&asan_parser, f);
+ RegisterCommonFlags(&asan_parser);
+
+ // Set the default values and prepare for parsing LSan and UBSan flags
+ // (which can also overwrite common flags).
+#if CAN_SANITIZE_LEAKS
+ __lsan::Flags *lf = __lsan::flags();
+ lf->SetDefaults();
+
+ FlagParser lsan_parser;
+ __lsan::RegisterLsanFlags(&lsan_parser, lf);
+ RegisterCommonFlags(&lsan_parser);
+#endif
+
+#if CAN_SANITIZE_UB
+ __ubsan::Flags *uf = __ubsan::flags();
+ uf->SetDefaults();
+
+ FlagParser ubsan_parser;
+ __ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
+ RegisterCommonFlags(&ubsan_parser);
+#endif
+
+ if (SANITIZER_APPLE) {
+ // Support macOS MallocScribble and MallocPreScribble:
+ // <https://developer.apple.com/library/content/documentation/Performance/
+ // Conceptual/ManagingMemory/Articles/MallocDebug.html>
+ if (GetEnv("MallocScribble")) {
+ f->max_free_fill_size = 0x1000;
+ }
+ if (GetEnv("MallocPreScribble")) {
+ f->malloc_fill_byte = 0xaa;
+ }
+ }
+
+ // Override from ASan compile definition.
+ const char *asan_compile_def = MaybeUseAsanDefaultOptionsCompileDefinition();
+ asan_parser.ParseString(asan_compile_def);
+
+ // Override from user-specified string.
+ const char *asan_default_options = __asan_default_options();
+ asan_parser.ParseString(asan_default_options);
+#if CAN_SANITIZE_UB
+ const char *ubsan_default_options = __ubsan_default_options();
+ ubsan_parser.ParseString(ubsan_default_options);
+#endif
+#if CAN_SANITIZE_LEAKS
+ const char *lsan_default_options = __lsan_default_options();
+ lsan_parser.ParseString(lsan_default_options);
+#endif
+
+ // Override from command line.
+ asan_parser.ParseStringFromEnv("ASAN_OPTIONS");
+#if CAN_SANITIZE_LEAKS
+ lsan_parser.ParseStringFromEnv("LSAN_OPTIONS");
+#endif
+#if CAN_SANITIZE_UB
+ ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
+#endif
+
+ InitializeCommonFlags();
+
+ // TODO(eugenis): dump all flags at verbosity>=2?
+ if (Verbosity()) ReportUnrecognizedFlags();
+
+ if (common_flags()->help) {
+ // TODO(samsonov): print all of the flags (ASan, LSan, common).
+ asan_parser.PrintFlagDescriptions();
+ }
+
+ // Flag validation:
+ if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) {
+ Report("%s: detect_leaks is not supported on this platform.\n",
+ SanitizerToolName);
+ Die();
+ }
+ // Ensure that redzone is at least ASAN_SHADOW_GRANULARITY.
+ if (f->redzone < (int)ASAN_SHADOW_GRANULARITY)
+ f->redzone = ASAN_SHADOW_GRANULARITY;
+ // Make "strict_init_order" imply "check_initialization_order".
+ // TODO(samsonov): Use a single runtime flag for an init-order checker.
+ if (f->strict_init_order) {
+ f->check_initialization_order = true;
+ }
+ CHECK_LE((uptr)common_flags()->malloc_context_size, kStackTraceMax);
+ CHECK_LE(f->min_uar_stack_size_log, f->max_uar_stack_size_log);
+ CHECK_GE(f->redzone, 16);
+ CHECK_GE(f->max_redzone, f->redzone);
+ CHECK_LE(f->max_redzone, 2048);
+ CHECK(IsPowerOfTwo(f->redzone));
+ CHECK(IsPowerOfTwo(f->max_redzone));
+
+ // quarantine_size is deprecated but we still honor it.
+ // quarantine_size can not be used together with quarantine_size_mb.
+ if (f->quarantine_size >= 0 && f->quarantine_size_mb >= 0) {
+ Report("%s: please use either 'quarantine_size' (deprecated) or "
+ "quarantine_size_mb, but not both\n", SanitizerToolName);
+ Die();
+ }
+ if (f->quarantine_size >= 0)
+ f->quarantine_size_mb = f->quarantine_size >> 20;
+ if (f->quarantine_size_mb < 0) {
+ const int kDefaultQuarantineSizeMb =
+ (ASAN_LOW_MEMORY) ? 1UL << 4 : 1UL << 8;
+ f->quarantine_size_mb = kDefaultQuarantineSizeMb;
+ }
+ if (f->thread_local_quarantine_size_kb < 0) {
+ const u32 kDefaultThreadLocalQuarantineSizeKb =
+ // It is not advised to go lower than 64Kb, otherwise quarantine batches
+ // pushed from thread local quarantine to global one will create too
+ // much overhead. One quarantine batch size is 8Kb and it holds up to
+ // 1021 chunk, which amounts to 1/8 memory overhead per batch when
+ // thread local quarantine is set to 64Kb.
+ (ASAN_LOW_MEMORY) ? 1 << 6 : FIRST_32_SECOND_64(1 << 8, 1 << 10);
+ f->thread_local_quarantine_size_kb = kDefaultThreadLocalQuarantineSizeKb;
+ }
+ if (f->thread_local_quarantine_size_kb == 0 && f->quarantine_size_mb > 0) {
+ Report("%s: thread_local_quarantine_size_kb can be set to 0 only when "
+ "quarantine_size_mb is set to 0\n", SanitizerToolName);
+ Die();
+ }
+ if (!f->replace_str && common_flags()->intercept_strlen) {
+ Report("WARNING: strlen interceptor is enabled even though replace_str=0. "
+ "Use intercept_strlen=0 to disable it.");
+ }
+ if (!f->replace_str && common_flags()->intercept_strchr) {
+ Report("WARNING: strchr* interceptors are enabled even though "
+ "replace_str=0. Use intercept_strchr=0 to disable them.");
+ }
+ if (!f->replace_str && common_flags()->intercept_strndup) {
+ Report("WARNING: strndup* interceptors are enabled even though "
+ "replace_str=0. Use intercept_strndup=0 to disable them.");
+ }
+}
+
+} // namespace __asan
+
+SANITIZER_INTERFACE_WEAK_DEF(const char*, __asan_default_options, void) {
+ return "";
+}
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_flags.h b/contrib/libs/clang16-rt/lib/asan/asan_flags.h
new file mode 100644
index 00000000000..b55c81f07d4
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_flags.h
@@ -0,0 +1,48 @@
+//===-- asan_flags.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan runtime flags.
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_FLAGS_H
+#define ASAN_FLAGS_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+
+// ASan flag values can be defined in four ways:
+// 1) initialized with default values at startup.
+// 2) overriden during compilation of ASan runtime by providing
+// compile definition ASAN_DEFAULT_OPTIONS.
+// 3) overriden from string returned by user-specified function
+// __asan_default_options().
+// 4) overriden from env variable ASAN_OPTIONS.
+// 5) overriden during ASan activation (for now used on Android only).
+
+namespace __asan {
+
+struct Flags {
+#define ASAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "asan_flags.inc"
+#undef ASAN_FLAG
+
+ void SetDefaults();
+};
+
+extern Flags asan_flags_dont_use_directly;
+inline Flags *flags() {
+ return &asan_flags_dont_use_directly;
+}
+
+void InitializeFlags();
+
+} // namespace __asan
+
+#endif // ASAN_FLAGS_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_flags.inc b/contrib/libs/clang16-rt/lib/asan/asan_flags.inc
new file mode 100644
index 00000000000..fad1577d912
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_flags.inc
@@ -0,0 +1,167 @@
+//===-- asan_flags.inc ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// ASan runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_FLAG
+# error "Define ASAN_FLAG prior to including this file!"
+#endif
+
+// ASAN_FLAG(Type, Name, DefaultValue, Description)
+// See COMMON_FLAG in sanitizer_flags.inc for more details.
+
+ASAN_FLAG(int, quarantine_size, -1,
+ "Deprecated, please use quarantine_size_mb.")
+ASAN_FLAG(int, quarantine_size_mb, -1,
+ "Size (in Mb) of quarantine used to detect use-after-free "
+ "errors. Lower value may reduce memory usage but increase the "
+ "chance of false negatives.")
+ASAN_FLAG(int, thread_local_quarantine_size_kb, -1,
+ "Size (in Kb) of thread local quarantine used to detect "
+ "use-after-free errors. Lower value may reduce memory usage but "
+ "increase the chance of false negatives. It is not advised to go "
+ "lower than 64Kb, otherwise frequent transfers to global quarantine "
+ "might affect performance.")
+ASAN_FLAG(int, redzone, 16,
+ "Minimal size (in bytes) of redzones around heap objects. "
+ "Requirement: redzone >= 16, is a power of two.")
+ASAN_FLAG(int, max_redzone, 2048,
+ "Maximal size (in bytes) of redzones around heap objects.")
+ASAN_FLAG(
+ bool, debug, false,
+ "If set, prints some debugging information and does additional checks.")
+ASAN_FLAG(
+ int, report_globals, 1,
+ "Controls the way to handle globals (0 - don't detect buffer overflow on "
+ "globals, 1 - detect buffer overflow, 2 - print data about registered "
+ "globals).")
+ASAN_FLAG(bool, check_initialization_order, false,
+ "If set, attempts to catch initialization order issues.")
+ASAN_FLAG(
+ bool, replace_str, true,
+ "If set, uses custom wrappers and replacements for libc string functions "
+ "to find more errors.")
+ASAN_FLAG(bool, replace_intrin, true,
+ "If set, uses custom wrappers for memset/memcpy/memmove intrinsics.")
+ASAN_FLAG(bool, detect_stack_use_after_return,
+ SANITIZER_LINUX && !SANITIZER_ANDROID,
+ "Enables stack-use-after-return checking at run-time.")
+ASAN_FLAG(int, min_uar_stack_size_log, 16, // We can't do smaller anyway.
+ "Minimum fake stack size log.")
+ASAN_FLAG(int, max_uar_stack_size_log,
+ 20, // 1Mb per size class, i.e. ~11Mb per thread
+ "Maximum fake stack size log.")
+ASAN_FLAG(bool, uar_noreserve, false,
+ "Use mmap with 'noreserve' flag to allocate fake stack.")
+ASAN_FLAG(
+ int, max_malloc_fill_size, 0x1000, // By default, fill only the first 4K.
+ "ASan allocator flag. max_malloc_fill_size is the maximal amount of "
+ "bytes that will be filled with malloc_fill_byte on malloc.")
+ASAN_FLAG(
+ int, max_free_fill_size, 0,
+ "ASan allocator flag. max_free_fill_size is the maximal amount of "
+ "bytes that will be filled with free_fill_byte during free.")
+ASAN_FLAG(int, malloc_fill_byte, 0xbe,
+ "Value used to fill the newly allocated memory.")
+ASAN_FLAG(int, free_fill_byte, 0x55,
+ "Value used to fill deallocated memory.")
+ASAN_FLAG(bool, allow_user_poisoning, true,
+ "If set, user may manually mark memory regions as poisoned or "
+ "unpoisoned.")
+ASAN_FLAG(
+ int, sleep_before_dying, 0,
+ "Number of seconds to sleep between printing an error report and "
+ "terminating the program. Useful for debugging purposes (e.g. when one "
+ "needs to attach gdb).")
+ASAN_FLAG(
+ int, sleep_after_init, 0,
+ "Number of seconds to sleep after AddressSanitizer is initialized. "
+ "Useful for debugging purposes (e.g. when one needs to attach gdb).")
+ASAN_FLAG(
+ int, sleep_before_init, 0,
+ "Number of seconds to sleep before AddressSanitizer starts initializing. "
+ "Useful for debugging purposes (e.g. when one needs to attach gdb).")
+ASAN_FLAG(bool, check_malloc_usable_size, true,
+ "Allows the users to work around the bug in Nvidia drivers prior to "
+ "295.*.")
+ASAN_FLAG(bool, unmap_shadow_on_exit, false,
+ "If set, explicitly unmaps the (huge) shadow at exit.")
+ASAN_FLAG(bool, protect_shadow_gap, true, "If set, mprotect the shadow gap")
+ASAN_FLAG(bool, print_stats, false,
+ "Print various statistics after printing an error message or if "
+ "atexit=1.")
+ASAN_FLAG(bool, print_legend, true, "Print the legend for the shadow bytes.")
+ASAN_FLAG(bool, print_scariness, false,
+ "Print the scariness score. Experimental.")
+ASAN_FLAG(bool, atexit, false,
+ "If set, prints ASan exit stats even after program terminates "
+ "successfully.")
+ASAN_FLAG(
+ bool, print_full_thread_history, true,
+ "If set, prints thread creation stacks for the threads involved in the "
+ "report and their ancestors up to the main thread.")
+ASAN_FLAG(
+ bool, poison_heap, true,
+ "Poison (or not) the heap memory on [de]allocation. Zero value is useful "
+ "for benchmarking the allocator or instrumentator.")
+ASAN_FLAG(bool, poison_partial, true,
+ "If true, poison partially addressable 8-byte aligned words "
+ "(default=true). This flag affects heap and global buffers, but not "
+ "stack buffers.")
+ASAN_FLAG(bool, poison_array_cookie, true,
+ "Poison (or not) the array cookie after operator new[].")
+
+// Turn off alloc/dealloc mismatch checker on Mac and Windows for now.
+// https://github.com/google/sanitizers/issues/131
+// https://github.com/google/sanitizers/issues/309
+// TODO(glider,timurrrr): Fix known issues and enable this back.
+ASAN_FLAG(bool, alloc_dealloc_mismatch,
+ !SANITIZER_APPLE && !SANITIZER_WINDOWS && !SANITIZER_ANDROID,
+ "Report errors on malloc/delete, new/free, new/delete[], etc.")
+
+ASAN_FLAG(bool, new_delete_type_mismatch, true,
+ "Report errors on mismatch between size of new and delete.")
+ASAN_FLAG(
+ bool, strict_init_order, false,
+ "If true, assume that dynamic initializers can never access globals from "
+ "other modules, even if the latter are already initialized.")
+ASAN_FLAG(
+ bool, start_deactivated, false,
+ "If true, ASan tweaks a bunch of other flags (quarantine, redzone, heap "
+ "poisoning) to reduce memory consumption as much as possible, and "
+ "restores them to original values when the first instrumented module is "
+ "loaded into the process. This is mainly intended to be used on "
+ "Android. ")
+ASAN_FLAG(
+ int, detect_invalid_pointer_pairs, 0,
+ "If >= 2, detect operations like <, <=, >, >= and - on invalid pointer "
+ "pairs (e.g. when pointers belong to different objects); "
+ "If == 1, detect invalid operations only when both pointers are non-null.")
+ASAN_FLAG(bool, detect_container_overflow, true,
+ "If true, honor the container overflow annotations. See "
+ "https://github.com/google/sanitizers/wiki/"
+ "AddressSanitizerContainerOverflow")
+ASAN_FLAG(int, detect_odr_violation, 2,
+ "If >=2, detect violation of One-Definition-Rule (ODR); "
+ "If ==1, detect ODR-violation only if the two variables "
+ "have different sizes")
+ASAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
+ASAN_FLAG(bool, halt_on_error, true,
+ "Crash the program after printing the first error report "
+ "(WARNING: USE AT YOUR OWN RISK!)")
+ASAN_FLAG(bool, allocator_frees_and_returns_null_on_realloc_zero, true,
+ "realloc(p, 0) is equivalent to free(p) by default (Same as the "
+ "POSIX standard). If set to false, realloc(p, 0) will return a "
+ "pointer to an allocated space which can not be used.")
+ASAN_FLAG(bool, verify_asan_link_order, true,
+ "Check position of ASan runtime in library list (needs to be disabled"
+ " when other library has to be preloaded system-wide)")
+ASAN_FLAG(
+ bool, windows_hook_rtl_allocators, false,
+ "(Windows only) enable hooking of Rtl(Allocate|Free|Size|ReAllocate)Heap.")
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_fuchsia.cpp b/contrib/libs/clang16-rt/lib/asan/asan_fuchsia.cpp
new file mode 100644
index 00000000000..dd3d06fd2f0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_fuchsia.cpp
@@ -0,0 +1,274 @@
+//===-- asan_fuchsia.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Fuchsia-specific details.
+//===---------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_fuchsia.h"
+#if SANITIZER_FUCHSIA
+
+#include <limits.h>
+#error #include <zircon/sanitizer.h>
+#error #include <zircon/syscalls.h>
+#error #include <zircon/threads.h>
+
+# include "asan_interceptors.h"
+# include "asan_internal.h"
+# include "asan_stack.h"
+# include "asan_thread.h"
+# include "lsan/lsan_common.h"
+
+namespace __asan {
+
+// The system already set up the shadow memory for us.
+// __sanitizer::GetMaxUserVirtualAddress has already been called by
+// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cpp).
+// Just do some additional sanity checks here.
+void InitializeShadowMemory() {
+ if (Verbosity())
+ PrintAddressSpaceLayout();
+
+ // Make sure SHADOW_OFFSET doesn't use __asan_shadow_memory_dynamic_address.
+ __asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
+ DCHECK(kLowShadowBeg != kDefaultShadowSentinel);
+ __asan_shadow_memory_dynamic_address = kLowShadowBeg;
+
+ CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
+ CHECK_EQ(kHighMemEnd, __sanitizer::ShadowBounds.memory_limit - 1);
+ CHECK_EQ(kHighMemBeg, __sanitizer::ShadowBounds.shadow_limit);
+ CHECK_EQ(kHighShadowBeg, __sanitizer::ShadowBounds.shadow_base);
+ CHECK_EQ(kShadowGapEnd, __sanitizer::ShadowBounds.shadow_base - 1);
+ CHECK_EQ(kLowShadowEnd, 0);
+ CHECK_EQ(kLowShadowBeg, 0);
+}
+
+void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
+ UNIMPLEMENTED();
+}
+
+void AsanCheckDynamicRTPrereqs() {}
+void AsanCheckIncompatibleRT() {}
+void InitializeAsanInterceptors() {}
+
+void *AsanDoesNotSupportStaticLinkage() { return nullptr; }
+
+void InitializePlatformExceptionHandlers() {}
+void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
+ UNIMPLEMENTED();
+}
+
+bool PlatformUnpoisonStacks() {
+ // The current sp might not point to the default stack. This
+ // could be because we are in a crash stack from fuzzing for example.
+ // Unpoison the default stack and the current stack page.
+ AsanThread *curr_thread = GetCurrentThread();
+ CHECK(curr_thread != nullptr);
+ uptr top = curr_thread->stack_top();
+ uptr bottom = curr_thread->stack_bottom();
+ // The default stack grows from top to bottom. (bottom < top).
+
+ uptr local_stack = reinterpret_cast<uptr>(__builtin_frame_address(0));
+ if (local_stack >= bottom && local_stack <= top) {
+ // The current stack is the default stack.
+ // We only need to unpoison from where we are using until the end.
+ bottom = RoundDownTo(local_stack, GetPageSize());
+ UnpoisonStack(bottom, top, "default");
+ } else {
+ // The current stack is not the default stack.
+ // Unpoison the entire default stack and the current stack page.
+ UnpoisonStack(bottom, top, "default");
+ bottom = RoundDownTo(local_stack, GetPageSize());
+ top = bottom + GetPageSize();
+ UnpoisonStack(bottom, top, "unknown");
+ return true;
+ }
+
+ return false;
+}
+
+// We can use a plain thread_local variable for TSD.
+static thread_local void *per_thread;
+
+void *AsanTSDGet() { return per_thread; }
+
+void AsanTSDSet(void *tsd) { per_thread = tsd; }
+
+// There's no initialization needed, and the passed-in destructor
+// will never be called. Instead, our own thread destruction hook
+// (below) will call AsanThread::TSDDtor directly.
+void AsanTSDInit(void (*destructor)(void *tsd)) {
+ DCHECK(destructor == &PlatformTSDDtor);
+}
+
+void PlatformTSDDtor(void *tsd) { UNREACHABLE(__func__); }
+
+static inline size_t AsanThreadMmapSize() {
+ return RoundUpTo(sizeof(AsanThread), _zx_system_get_page_size());
+}
+
+struct AsanThread::InitOptions {
+ uptr stack_bottom, stack_size;
+};
+
+// Shared setup between thread creation and startup for the initial thread.
+static AsanThread *CreateAsanThread(StackTrace *stack, u32 parent_tid,
+ bool detached, const char *name) {
+ // In lieu of AsanThread::Create.
+ AsanThread *thread = (AsanThread *)MmapOrDie(AsanThreadMmapSize(), __func__);
+
+ AsanThreadContext::CreateThreadContextArgs args = {thread, stack};
+ u32 tid = asanThreadRegistry().CreateThread(0, detached, parent_tid, &args);
+ asanThreadRegistry().SetThreadName(tid, name);
+
+ return thread;
+}
+
+// This gets the same arguments passed to Init by CreateAsanThread, above.
+// We're in the creator thread before the new thread is actually started,
+// but its stack address range is already known. We don't bother tracking
+// the static TLS address range because the system itself already uses an
+// ASan-aware allocator for that.
+void AsanThread::SetThreadStackAndTls(const AsanThread::InitOptions *options) {
+ DCHECK_NE(GetCurrentThread(), this);
+ DCHECK_NE(GetCurrentThread(), nullptr);
+ CHECK_NE(options->stack_bottom, 0);
+ CHECK_NE(options->stack_size, 0);
+ stack_bottom_ = options->stack_bottom;
+ stack_top_ = options->stack_bottom + options->stack_size;
+}
+
+// Called by __asan::AsanInitInternal (asan_rtl.c).
+AsanThread *CreateMainThread() {
+ thrd_t self = thrd_current();
+ char name[ZX_MAX_NAME_LEN];
+ CHECK_NE(__sanitizer::MainThreadStackBase, 0);
+ CHECK_GT(__sanitizer::MainThreadStackSize, 0);
+ AsanThread *t = CreateAsanThread(
+ nullptr, 0, true,
+ _zx_object_get_property(thrd_get_zx_handle(self), ZX_PROP_NAME, name,
+ sizeof(name)) == ZX_OK
+ ? name
+ : nullptr);
+ // We need to set the current thread before calling AsanThread::Init() below,
+ // since it reads the thread ID.
+ SetCurrentThread(t);
+ DCHECK_EQ(t->tid(), 0);
+
+ const AsanThread::InitOptions options = {__sanitizer::MainThreadStackBase,
+ __sanitizer::MainThreadStackSize};
+ t->Init(&options);
+
+ return t;
+}
+
+// This is called before each thread creation is attempted. So, in
+// its first call, the calling thread is the initial and sole thread.
+static void *BeforeThreadCreateHook(uptr user_id, bool detached,
+ const char *name, uptr stack_bottom,
+ uptr stack_size) {
+ EnsureMainThreadIDIsCorrect();
+ // Strict init-order checking is thread-hostile.
+ if (flags()->strict_init_order)
+ StopInitOrderChecking();
+
+ GET_STACK_TRACE_THREAD;
+ u32 parent_tid = GetCurrentTidOrInvalid();
+
+ AsanThread *thread = CreateAsanThread(&stack, parent_tid, detached, name);
+
+ // On other systems, AsanThread::Init() is called from the new
+ // thread itself. But on Fuchsia we already know the stack address
+ // range beforehand, so we can do most of the setup right now.
+ const AsanThread::InitOptions options = {stack_bottom, stack_size};
+ thread->Init(&options);
+ return thread;
+}
+
+// This is called after creating a new thread (in the creating thread),
+// with the pointer returned by BeforeThreadCreateHook (above).
+static void ThreadCreateHook(void *hook, bool aborted) {
+ AsanThread *thread = static_cast<AsanThread *>(hook);
+ if (!aborted) {
+ // The thread was created successfully.
+ // ThreadStartHook is already running in the new thread.
+ } else {
+ // The thread wasn't created after all.
+ // Clean up everything we set up in BeforeThreadCreateHook.
+ asanThreadRegistry().FinishThread(thread->tid());
+ UnmapOrDie(thread, AsanThreadMmapSize());
+ }
+}
+
+// This is called in the newly-created thread before it runs anything else,
+// with the pointer returned by BeforeThreadCreateHook (above).
+// cf. asan_interceptors.cpp:asan_thread_start
+static void ThreadStartHook(void *hook, uptr os_id) {
+ AsanThread *thread = static_cast<AsanThread *>(hook);
+ SetCurrentThread(thread);
+
+ // In lieu of AsanThread::ThreadStart.
+ asanThreadRegistry().StartThread(thread->tid(), os_id, ThreadType::Regular,
+ nullptr);
+}
+
+// Each thread runs this just before it exits,
+// with the pointer returned by BeforeThreadCreateHook (above).
+// All per-thread destructors have already been called.
+static void ThreadExitHook(void *hook, uptr os_id) {
+ AsanThread::TSDDtor(per_thread);
+}
+
+bool HandleDlopenInit() {
+ // Not supported on this platform.
+ static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
+ "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
+ return false;
+}
+
+void FlushUnneededASanShadowMemory(uptr p, uptr size) {
+ __sanitizer_fill_shadow(p, size, 0, 0);
+}
+
+// On Fuchsia, leak detection is done by a special hook after atexit hooks.
+// So this doesn't install any atexit hook like on other platforms.
+void InstallAtExitCheckLeaks() {}
+
+} // namespace __asan
+
+namespace __lsan {
+
+bool UseExitcodeOnLeak() { return __asan::flags()->halt_on_error; }
+
+} // namespace __lsan
+
+// These are declared (in extern "C") by <zircon/sanitizer.h>.
+// The system runtime will call our definitions directly.
+
+void *__sanitizer_before_thread_create_hook(thrd_t thread, bool detached,
+ const char *name, void *stack_base,
+ size_t stack_size) {
+ return __asan::BeforeThreadCreateHook(
+ reinterpret_cast<uptr>(thread), detached, name,
+ reinterpret_cast<uptr>(stack_base), stack_size);
+}
+
+void __sanitizer_thread_create_hook(void *hook, thrd_t thread, int error) {
+ __asan::ThreadCreateHook(hook, error != thrd_success);
+}
+
+void __sanitizer_thread_start_hook(void *hook, thrd_t self) {
+ __asan::ThreadStartHook(hook, reinterpret_cast<uptr>(self));
+}
+
+void __sanitizer_thread_exit_hook(void *hook, thrd_t self) {
+ __asan::ThreadExitHook(hook, reinterpret_cast<uptr>(self));
+}
+
+#endif // SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_globals.cpp b/contrib/libs/clang16-rt/lib/asan/asan_globals.cpp
new file mode 100644
index 00000000000..b780128c9ad
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_globals.cpp
@@ -0,0 +1,460 @@
+//===-- asan_globals.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Handle globals.
+//===----------------------------------------------------------------------===//
+
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "asan_poisoning.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "asan_stats.h"
+#include "asan_suppressions.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+
+namespace __asan {
+
+typedef __asan_global Global;
+
+struct ListOfGlobals {
+ const Global *g;
+ ListOfGlobals *next;
+};
+
+static Mutex mu_for_globals;
+static LowLevelAllocator allocator_for_globals;
+static ListOfGlobals *list_of_all_globals;
+
+static const int kDynamicInitGlobalsInitialCapacity = 512;
+struct DynInitGlobal {
+ Global g;
+ bool initialized;
+};
+typedef InternalMmapVector<DynInitGlobal> VectorOfGlobals;
+// Lazy-initialized and never deleted.
+static VectorOfGlobals *dynamic_init_globals;
+
+// We want to remember where a certain range of globals was registered.
+struct GlobalRegistrationSite {
+ u32 stack_id;
+ Global *g_first, *g_last;
+};
+typedef InternalMmapVector<GlobalRegistrationSite> GlobalRegistrationSiteVector;
+static GlobalRegistrationSiteVector *global_registration_site_vector;
+
+ALWAYS_INLINE void PoisonShadowForGlobal(const Global *g, u8 value) {
+ FastPoisonShadow(g->beg, g->size_with_redzone, value);
+}
+
+ALWAYS_INLINE void PoisonRedZones(const Global &g) {
+ uptr aligned_size = RoundUpTo(g.size, ASAN_SHADOW_GRANULARITY);
+ FastPoisonShadow(g.beg + aligned_size, g.size_with_redzone - aligned_size,
+ kAsanGlobalRedzoneMagic);
+ if (g.size != aligned_size) {
+ FastPoisonShadowPartialRightRedzone(
+ g.beg + RoundDownTo(g.size, ASAN_SHADOW_GRANULARITY),
+ g.size % ASAN_SHADOW_GRANULARITY, ASAN_SHADOW_GRANULARITY,
+ kAsanGlobalRedzoneMagic);
+ }
+}
+
+const uptr kMinimalDistanceFromAnotherGlobal = 64;
+
+static bool IsAddressNearGlobal(uptr addr, const __asan_global &g) {
+ if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false;
+ if (addr >= g.beg + g.size_with_redzone) return false;
+ return true;
+}
+
+static void ReportGlobal(const Global &g, const char *prefix) {
+ Report(
+ "%s Global[%p]: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu "
+ "odr_indicator=%p\n",
+ prefix, (void *)&g, (void *)g.beg, g.size, g.size_with_redzone, g.name,
+ g.module_name, g.has_dynamic_init, (void *)g.odr_indicator);
+
+ DataInfo info;
+ Symbolizer::GetOrInit()->SymbolizeData(g.beg, &info);
+ if (info.line != 0) {
+ Report(" location: name=%s, %d\n", info.file, static_cast<int>(info.line));
+ }
+}
+
+static u32 FindRegistrationSite(const Global *g) {
+ mu_for_globals.CheckLocked();
+ CHECK(global_registration_site_vector);
+ for (uptr i = 0, n = global_registration_site_vector->size(); i < n; i++) {
+ GlobalRegistrationSite &grs = (*global_registration_site_vector)[i];
+ if (g >= grs.g_first && g <= grs.g_last)
+ return grs.stack_id;
+ }
+ return 0;
+}
+
+int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites,
+ int max_globals) {
+ if (!flags()->report_globals) return 0;
+ Lock lock(&mu_for_globals);
+ int res = 0;
+ for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
+ const Global &g = *l->g;
+ if (flags()->report_globals >= 2)
+ ReportGlobal(g, "Search");
+ if (IsAddressNearGlobal(addr, g)) {
+ internal_memcpy(&globals[res], &g, sizeof(g));
+ if (reg_sites)
+ reg_sites[res] = FindRegistrationSite(&g);
+ res++;
+ if (res == max_globals)
+ break;
+ }
+ }
+ return res;
+}
+
+enum GlobalSymbolState {
+ UNREGISTERED = 0,
+ REGISTERED = 1
+};
+
+// Check ODR violation for given global G via special ODR indicator. We use
+// this method in case compiler instruments global variables through their
+// local aliases.
+static void CheckODRViolationViaIndicator(const Global *g) {
+ // Instrumentation requests to skip ODR check.
+ if (g->odr_indicator == UINTPTR_MAX)
+ return;
+ u8 *odr_indicator = reinterpret_cast<u8 *>(g->odr_indicator);
+ if (*odr_indicator == UNREGISTERED) {
+ *odr_indicator = REGISTERED;
+ return;
+ }
+ // If *odr_indicator is DEFINED, some module have already registered
+ // externally visible symbol with the same name. This is an ODR violation.
+ for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
+ if (g->odr_indicator == l->g->odr_indicator &&
+ (flags()->detect_odr_violation >= 2 || g->size != l->g->size) &&
+ !IsODRViolationSuppressed(g->name))
+ ReportODRViolation(g, FindRegistrationSite(g),
+ l->g, FindRegistrationSite(l->g));
+ }
+}
+
+// Check ODR violation for given global G by checking if it's already poisoned.
+// We use this method in case compiler doesn't use private aliases for global
+// variables.
+static void CheckODRViolationViaPoisoning(const Global *g) {
+ if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
+ // This check may not be enough: if the first global is much larger
+ // the entire redzone of the second global may be within the first global.
+ for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
+ if (g->beg == l->g->beg &&
+ (flags()->detect_odr_violation >= 2 || g->size != l->g->size) &&
+ !IsODRViolationSuppressed(g->name))
+ ReportODRViolation(g, FindRegistrationSite(g),
+ l->g, FindRegistrationSite(l->g));
+ }
+ }
+}
+
+// Clang provides two different ways for global variables protection:
+// it can poison the global itself or its private alias. In former
+// case we may poison same symbol multiple times, that can help us to
+// cheaply detect ODR violation: if we try to poison an already poisoned
+// global, we have ODR violation error.
+// In latter case, we poison each symbol exactly once, so we use special
+// indicator symbol to perform similar check.
+// In either case, compiler provides a special odr_indicator field to Global
+// structure, that can contain two kinds of values:
+// 1) Non-zero value. In this case, odr_indicator is an address of
+// corresponding indicator variable for given global.
+// 2) Zero. This means that we don't use private aliases for global variables
+// and can freely check ODR violation with the first method.
+//
+// This routine chooses between two different methods of ODR violation
+// detection.
+static inline bool UseODRIndicator(const Global *g) {
+ return g->odr_indicator > 0;
+}
+
+// Register a global variable.
+// This function may be called more than once for every global
+// so we store the globals in a map.
+static void RegisterGlobal(const Global *g) {
+ CHECK(asan_inited);
+ if (flags()->report_globals >= 2)
+ ReportGlobal(*g, "Added");
+ CHECK(flags()->report_globals);
+ CHECK(AddrIsInMem(g->beg));
+ if (!AddrIsAlignedByGranularity(g->beg)) {
+ Report("The following global variable is not properly aligned.\n");
+ Report("This may happen if another global with the same name\n");
+ Report("resides in another non-instrumented module.\n");
+ Report("Or the global comes from a C file built w/o -fno-common.\n");
+ Report("In either case this is likely an ODR violation bug,\n");
+ Report("but AddressSanitizer can not provide more details.\n");
+ ReportODRViolation(g, FindRegistrationSite(g), g, FindRegistrationSite(g));
+ CHECK(AddrIsAlignedByGranularity(g->beg));
+ }
+ CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
+ if (flags()->detect_odr_violation) {
+ // Try detecting ODR (One Definition Rule) violation, i.e. the situation
+ // where two globals with the same name are defined in different modules.
+ if (UseODRIndicator(g))
+ CheckODRViolationViaIndicator(g);
+ else
+ CheckODRViolationViaPoisoning(g);
+ }
+ if (CanPoisonMemory())
+ PoisonRedZones(*g);
+ ListOfGlobals *l = new(allocator_for_globals) ListOfGlobals;
+ l->g = g;
+ l->next = list_of_all_globals;
+ list_of_all_globals = l;
+ if (g->has_dynamic_init) {
+ if (!dynamic_init_globals) {
+ dynamic_init_globals = new (allocator_for_globals) VectorOfGlobals;
+ dynamic_init_globals->reserve(kDynamicInitGlobalsInitialCapacity);
+ }
+ DynInitGlobal dyn_global = { *g, false };
+ dynamic_init_globals->push_back(dyn_global);
+ }
+}
+
+static void UnregisterGlobal(const Global *g) {
+ CHECK(asan_inited);
+ if (flags()->report_globals >= 2)
+ ReportGlobal(*g, "Removed");
+ CHECK(flags()->report_globals);
+ CHECK(AddrIsInMem(g->beg));
+ CHECK(AddrIsAlignedByGranularity(g->beg));
+ CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
+ if (CanPoisonMemory())
+ PoisonShadowForGlobal(g, 0);
+ // We unpoison the shadow memory for the global but we do not remove it from
+ // the list because that would require O(n^2) time with the current list
+ // implementation. It might not be worth doing anyway.
+
+ // Release ODR indicator.
+ if (UseODRIndicator(g) && g->odr_indicator != UINTPTR_MAX) {
+ u8 *odr_indicator = reinterpret_cast<u8 *>(g->odr_indicator);
+ *odr_indicator = UNREGISTERED;
+ }
+}
+
+void StopInitOrderChecking() {
+ Lock lock(&mu_for_globals);
+ if (!flags()->check_initialization_order || !dynamic_init_globals)
+ return;
+ flags()->check_initialization_order = false;
+ for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
+ DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
+ const Global *g = &dyn_g.g;
+ // Unpoison the whole global.
+ PoisonShadowForGlobal(g, 0);
+ // Poison redzones back.
+ PoisonRedZones(*g);
+ }
+}
+
+static bool IsASCII(unsigned char c) { return /*0x00 <= c &&*/ c <= 0x7F; }
+
+const char *MaybeDemangleGlobalName(const char *name) {
+ // We can spoil names of globals with C linkage, so use an heuristic
+ // approach to check if the name should be demangled.
+ bool should_demangle = false;
+ if (name[0] == '_' && name[1] == 'Z')
+ should_demangle = true;
+ else if (SANITIZER_WINDOWS && name[0] == '\01' && name[1] == '?')
+ should_demangle = true;
+
+ return should_demangle ? Symbolizer::GetOrInit()->Demangle(name) : name;
+}
+
+// Check if the global is a zero-terminated ASCII string. If so, print it.
+void PrintGlobalNameIfASCII(InternalScopedString *str, const __asan_global &g) {
+ for (uptr p = g.beg; p < g.beg + g.size - 1; p++) {
+ unsigned char c = *(unsigned char *)p;
+ if (c == '\0' || !IsASCII(c)) return;
+ }
+ if (*(char *)(g.beg + g.size - 1) != '\0') return;
+ str->append(" '%s' is ascii string '%s'\n", MaybeDemangleGlobalName(g.name),
+ (char *)g.beg);
+}
+
+void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g) {
+ DataInfo info;
+ Symbolizer::GetOrInit()->SymbolizeData(g.beg, &info);
+
+ if (info.line != 0) {
+ str->append("%s:%d", info.file, static_cast<int>(info.line));
+ } else {
+ str->append("%s", g.module_name);
+ }
+}
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan;
+
+// Apply __asan_register_globals to all globals found in the same loaded
+// executable or shared library as `flag'. The flag tracks whether globals have
+// already been registered or not for this image.
+void __asan_register_image_globals(uptr *flag) {
+ if (*flag)
+ return;
+ AsanApplyToGlobals(__asan_register_globals, flag);
+ *flag = 1;
+}
+
+// This mirrors __asan_register_image_globals.
+void __asan_unregister_image_globals(uptr *flag) {
+ if (!*flag)
+ return;
+ AsanApplyToGlobals(__asan_unregister_globals, flag);
+ *flag = 0;
+}
+
+void __asan_register_elf_globals(uptr *flag, void *start, void *stop) {
+ if (*flag) return;
+ if (!start) return;
+ CHECK_EQ(0, ((uptr)stop - (uptr)start) % sizeof(__asan_global));
+ __asan_global *globals_start = (__asan_global*)start;
+ __asan_global *globals_stop = (__asan_global*)stop;
+ __asan_register_globals(globals_start, globals_stop - globals_start);
+ *flag = 1;
+}
+
+void __asan_unregister_elf_globals(uptr *flag, void *start, void *stop) {
+ if (!*flag) return;
+ if (!start) return;
+ CHECK_EQ(0, ((uptr)stop - (uptr)start) % sizeof(__asan_global));
+ __asan_global *globals_start = (__asan_global*)start;
+ __asan_global *globals_stop = (__asan_global*)stop;
+ __asan_unregister_globals(globals_start, globals_stop - globals_start);
+ *flag = 0;
+}
+
+// Register an array of globals.
+void __asan_register_globals(__asan_global *globals, uptr n) {
+ if (!flags()->report_globals) return;
+ GET_STACK_TRACE_MALLOC;
+ u32 stack_id = StackDepotPut(stack);
+ Lock lock(&mu_for_globals);
+ if (!global_registration_site_vector) {
+ global_registration_site_vector =
+ new (allocator_for_globals) GlobalRegistrationSiteVector;
+ global_registration_site_vector->reserve(128);
+ }
+ GlobalRegistrationSite site = {stack_id, &globals[0], &globals[n - 1]};
+ global_registration_site_vector->push_back(site);
+ if (flags()->report_globals >= 2) {
+ PRINT_CURRENT_STACK();
+ Printf("=== ID %d; %p %p\n", stack_id, (void *)&globals[0],
+ (void *)&globals[n - 1]);
+ }
+ for (uptr i = 0; i < n; i++) {
+ if (SANITIZER_WINDOWS && globals[i].beg == 0) {
+ // The MSVC incremental linker may pad globals out to 256 bytes. As long
+ // as __asan_global is less than 256 bytes large and its size is a power
+ // of two, we can skip over the padding.
+ static_assert(
+ sizeof(__asan_global) < 256 &&
+ (sizeof(__asan_global) & (sizeof(__asan_global) - 1)) == 0,
+ "sizeof(__asan_global) incompatible with incremental linker padding");
+ // If these are padding bytes, the rest of the global should be zero.
+ CHECK(globals[i].size == 0 && globals[i].size_with_redzone == 0 &&
+ globals[i].name == nullptr && globals[i].module_name == nullptr &&
+ globals[i].odr_indicator == 0);
+ continue;
+ }
+ RegisterGlobal(&globals[i]);
+ }
+
+ // Poison the metadata. It should not be accessible to user code.
+ PoisonShadow(reinterpret_cast<uptr>(globals), n * sizeof(__asan_global),
+ kAsanGlobalRedzoneMagic);
+}
+
+// Unregister an array of globals.
+// We must do this when a shared objects gets dlclosed.
+void __asan_unregister_globals(__asan_global *globals, uptr n) {
+ if (!flags()->report_globals) return;
+ Lock lock(&mu_for_globals);
+ for (uptr i = 0; i < n; i++) {
+ if (SANITIZER_WINDOWS && globals[i].beg == 0) {
+ // Skip globals that look like padding from the MSVC incremental linker.
+ // See comment in __asan_register_globals.
+ continue;
+ }
+ UnregisterGlobal(&globals[i]);
+ }
+
+ // Unpoison the metadata.
+ PoisonShadow(reinterpret_cast<uptr>(globals), n * sizeof(__asan_global), 0);
+}
+
+// This method runs immediately prior to dynamic initialization in each TU,
+// when all dynamically initialized globals are unpoisoned. This method
+// poisons all global variables not defined in this TU, so that a dynamic
+// initializer can only touch global variables in the same TU.
+void __asan_before_dynamic_init(const char *module_name) {
+ if (!flags()->check_initialization_order ||
+ !CanPoisonMemory() ||
+ !dynamic_init_globals)
+ return;
+ bool strict_init_order = flags()->strict_init_order;
+ CHECK(module_name);
+ CHECK(asan_inited);
+ Lock lock(&mu_for_globals);
+ if (flags()->report_globals >= 3)
+ Printf("DynInitPoison module: %s\n", module_name);
+ for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
+ DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
+ const Global *g = &dyn_g.g;
+ if (dyn_g.initialized)
+ continue;
+ if (g->module_name != module_name)
+ PoisonShadowForGlobal(g, kAsanInitializationOrderMagic);
+ else if (!strict_init_order)
+ dyn_g.initialized = true;
+ }
+}
+
+// This method runs immediately after dynamic initialization in each TU, when
+// all dynamically initialized globals except for those defined in the current
+// TU are poisoned. It simply unpoisons all dynamically initialized globals.
+void __asan_after_dynamic_init() {
+ if (!flags()->check_initialization_order ||
+ !CanPoisonMemory() ||
+ !dynamic_init_globals)
+ return;
+ CHECK(asan_inited);
+ Lock lock(&mu_for_globals);
+ // FIXME: Optionally report that we're unpoisoning globals from a module.
+ for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
+ DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
+ const Global *g = &dyn_g.g;
+ if (!dyn_g.initialized) {
+ // Unpoison the whole global.
+ PoisonShadowForGlobal(g, 0);
+ // Poison redzones back.
+ PoisonRedZones(*g);
+ }
+ }
+}
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_globals_win.cpp b/contrib/libs/clang16-rt/lib/asan/asan_globals_win.cpp
new file mode 100644
index 00000000000..19af88ab12b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_globals_win.cpp
@@ -0,0 +1,61 @@
+//===-- asan_globals_win.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Global registration code that is linked into every Windows DLL and EXE.
+//
+//===----------------------------------------------------------------------===//
+
+#include "asan_interface_internal.h"
+#if SANITIZER_WINDOWS
+
+namespace __asan {
+
+#pragma section(".ASAN$GA", read, write)
+#pragma section(".ASAN$GZ", read, write)
+extern "C" __declspec(allocate(".ASAN$GA"))
+ ALIGNED(sizeof(__asan_global)) __asan_global __asan_globals_start = {};
+extern "C" __declspec(allocate(".ASAN$GZ"))
+ ALIGNED(sizeof(__asan_global)) __asan_global __asan_globals_end = {};
+#pragma comment(linker, "/merge:.ASAN=.data")
+
+static void call_on_globals(void (*hook)(__asan_global *, uptr)) {
+ __asan_global *start = &__asan_globals_start + 1;
+ __asan_global *end = &__asan_globals_end;
+ uptr bytediff = (uptr)end - (uptr)start;
+ if (bytediff % sizeof(__asan_global) != 0) {
+#if defined(SANITIZER_DLL_THUNK) || defined(SANITIZER_DYNAMIC_RUNTIME_THUNK)
+ __debugbreak();
+#else
+ CHECK("corrupt asan global array");
+#endif
+ }
+ // We know end >= start because the linker sorts the portion after the dollar
+ // sign alphabetically.
+ uptr n = end - start;
+ hook(start, n);
+}
+
+static void register_dso_globals() {
+ call_on_globals(&__asan_register_globals);
+}
+
+static void unregister_dso_globals() {
+ call_on_globals(&__asan_unregister_globals);
+}
+
+// Register globals
+#pragma section(".CRT$XCU", long, read)
+#pragma section(".CRT$XTX", long, read)
+extern "C" __declspec(allocate(".CRT$XCU"))
+void (*const __asan_dso_reg_hook)() = &register_dso_globals;
+extern "C" __declspec(allocate(".CRT$XTX"))
+void (*const __asan_dso_unreg_hook)() = &unregister_dso_globals;
+
+} // namespace __asan
+
+#endif // SANITIZER_WINDOWS
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_init_version.h b/contrib/libs/clang16-rt/lib/asan/asan_init_version.h
new file mode 100644
index 00000000000..b806d794e05
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_init_version.h
@@ -0,0 +1,44 @@
+//===-- asan_init_version.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// This header defines a versioned __asan_init function to be called at the
+// startup of the instrumented program.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_INIT_VERSION_H
+#define ASAN_INIT_VERSION_H
+
+#include "sanitizer_common/sanitizer_platform.h"
+
+extern "C" {
+ // Every time the ASan ABI changes we also change the version number in the
+ // __asan_init function name. Objects built with incompatible ASan ABI
+ // versions will not link with run-time.
+ //
+ // Changes between ABI versions:
+ // v1=>v2: added 'module_name' to __asan_global
+ // v2=>v3: stack frame description (created by the compiler)
+ // contains the function PC as the 3rd field (see
+ // DescribeAddressIfStack)
+ // v3=>v4: added '__asan_global_source_location' to __asan_global
+ // v4=>v5: changed the semantics and format of __asan_stack_malloc_ and
+ // __asan_stack_free_ functions
+ // v5=>v6: changed the name of the version check symbol
+ // v6=>v7: added 'odr_indicator' to __asan_global
+ // v7=>v8: added '__asan_(un)register_image_globals' functions for dead
+ // stripping support on Mach-O platforms
+#if SANITIZER_WORDSIZE == 32 && SANITIZER_ANDROID
+ // v8=>v9: 32-bit Android switched to dynamic shadow
+ #define __asan_version_mismatch_check __asan_version_mismatch_check_v9
+#else
+ #define __asan_version_mismatch_check __asan_version_mismatch_check_v8
+#endif
+}
+
+#endif // ASAN_INIT_VERSION_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_interceptors.cpp b/contrib/libs/clang16-rt/lib/asan/asan_interceptors.cpp
new file mode 100644
index 00000000000..776f512d08a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_interceptors.cpp
@@ -0,0 +1,747 @@
+//===-- asan_interceptors.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Intercept various libc functions.
+//===----------------------------------------------------------------------===//
+
+#include "asan_interceptors.h"
+#include "asan_allocator.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "asan_poisoning.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "asan_stats.h"
+#include "asan_suppressions.h"
+#include "lsan/lsan_common.h"
+#include "sanitizer_common/sanitizer_libc.h"
+
+// There is no general interception at all on Fuchsia.
+// Only the functions in asan_interceptors_memintrinsics.cpp are
+// really defined to replace libc functions.
+#if !SANITIZER_FUCHSIA
+
+# if SANITIZER_POSIX
+# include "sanitizer_common/sanitizer_posix.h"
+# endif
+
+# if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION || \
+ ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
+# include <unwind.h>
+# endif
+
+# if defined(__i386) && SANITIZER_LINUX
+# define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
+# elif defined(__mips__) && SANITIZER_LINUX
+# define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2"
+# endif
+
+namespace __asan {
+
+#define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \
+ ASAN_READ_RANGE((ctx), (s), \
+ common_flags()->strict_string_checks ? (len) + 1 : (n))
+
+# define ASAN_READ_STRING(ctx, s, n) \
+ ASAN_READ_STRING_OF_LEN((ctx), (s), internal_strlen(s), (n))
+
+static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
+#if SANITIZER_INTERCEPT_STRNLEN
+ if (REAL(strnlen)) {
+ return REAL(strnlen)(s, maxlen);
+ }
+#endif
+ return internal_strnlen(s, maxlen);
+}
+
+void SetThreadName(const char *name) {
+ AsanThread *t = GetCurrentThread();
+ if (t)
+ asanThreadRegistry().SetThreadName(t->tid(), name);
+}
+
+int OnExit() {
+ if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks &&
+ __lsan::HasReportedLeaks()) {
+ return common_flags()->exitcode;
+ }
+ // FIXME: ask frontend whether we need to return failure.
+ return 0;
+}
+
+} // namespace __asan
+
+// ---------------------- Wrappers ---------------- {{{1
+using namespace __asan;
+
+DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
+DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
+
+#define ASAN_INTERCEPTOR_ENTER(ctx, func) \
+ AsanInterceptorContext _ctx = {#func}; \
+ ctx = (void *)&_ctx; \
+ (void) ctx; \
+
+#define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
+#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
+ ASAN_INTERCEPT_FUNC_VER(name, ver)
+#define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
+ ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
+#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
+ ASAN_WRITE_RANGE(ctx, ptr, size)
+#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
+ ASAN_READ_RANGE(ctx, ptr, size)
+#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
+ ASAN_INTERCEPTOR_ENTER(ctx, func); \
+ do { \
+ if (asan_init_is_running) \
+ return REAL(func)(__VA_ARGS__); \
+ if (SANITIZER_APPLE && UNLIKELY(!asan_inited)) \
+ return REAL(func)(__VA_ARGS__); \
+ ENSURE_ASAN_INITED(); \
+ } while (false)
+#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
+// Should be asanThreadRegistry().SetThreadNameByUserId(thread, name)
+// But asan does not remember UserId's for threads (pthread_t);
+// and remembers all ever existed threads, so the linear search by UserId
+// can be slow.
+#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
+// Strict init-order checking is dlopen-hostile:
+// https://github.com/google/sanitizers/issues/178
+# define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
+ ({ \
+ if (flags()->strict_init_order) \
+ StopInitOrderChecking(); \
+ CheckNoDeepBind(filename, flag); \
+ REAL(dlopen)(filename, flag); \
+ })
+# define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
+# define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
+# define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
+# define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited)
+# define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
+ if (AsanThread *t = GetCurrentThread()) { \
+ *begin = t->tls_begin(); \
+ *end = t->tls_end(); \
+ } else { \
+ *begin = *end = 0; \
+ }
+
+#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
+ do { \
+ ASAN_INTERCEPTOR_ENTER(ctx, memmove); \
+ ASAN_MEMMOVE_IMPL(ctx, to, from, size); \
+ } while (false)
+
+#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
+ do { \
+ ASAN_INTERCEPTOR_ENTER(ctx, memcpy); \
+ ASAN_MEMCPY_IMPL(ctx, to, from, size); \
+ } while (false)
+
+#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
+ do { \
+ ASAN_INTERCEPTOR_ENTER(ctx, memset); \
+ ASAN_MEMSET_IMPL(ctx, block, c, size); \
+ } while (false)
+
+#if CAN_SANITIZE_LEAKS
+#define COMMON_INTERCEPTOR_STRERROR() \
+ __lsan::ScopedInterceptorDisabler disabler
+#endif
+
+#include "sanitizer_common/sanitizer_common_interceptors.inc"
+#include "sanitizer_common/sanitizer_signal_interceptors.inc"
+
+// Syscall interceptors don't have contexts, we don't support suppressions
+// for them.
+#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s)
+#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s)
+#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
+ do { \
+ (void)(p); \
+ (void)(s); \
+ } while (false)
+#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
+ do { \
+ (void)(p); \
+ (void)(s); \
+ } while (false)
+#include "sanitizer_common/sanitizer_common_syscalls.inc"
+#include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
+
+#if ASAN_INTERCEPT_PTHREAD_CREATE
+static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
+ AsanThread *t = (AsanThread *)arg;
+ SetCurrentThread(t);
+ return t->ThreadStart(GetTid());
+}
+
+INTERCEPTOR(int, pthread_create, void *thread,
+ void *attr, void *(*start_routine)(void*), void *arg) {
+ EnsureMainThreadIDIsCorrect();
+ // Strict init-order checking is thread-hostile.
+ if (flags()->strict_init_order)
+ StopInitOrderChecking();
+ GET_STACK_TRACE_THREAD;
+ int detached = 0;
+ if (attr)
+ REAL(pthread_attr_getdetachstate)(attr, &detached);
+
+ u32 current_tid = GetCurrentTidOrInvalid();
+ AsanThread *t =
+ AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
+
+ int result;
+ {
+ // Ignore all allocations made by pthread_create: thread stack/TLS may be
+ // stored by pthread for future reuse even after thread destruction, and
+ // the linked list it's stored in doesn't even hold valid pointers to the
+ // objects, the latter are calculated by obscure pointer arithmetic.
+#if CAN_SANITIZE_LEAKS
+ __lsan::ScopedInterceptorDisabler disabler;
+#endif
+ result = REAL(pthread_create)(thread, attr, asan_thread_start, t);
+ }
+ if (result != 0) {
+ // If the thread didn't start delete the AsanThread to avoid leaking it.
+ // Note AsanThreadContexts never get destroyed so the AsanThreadContext
+ // that was just created for the AsanThread is wasted.
+ t->Destroy();
+ }
+ return result;
+}
+
+INTERCEPTOR(int, pthread_join, void *t, void **arg) {
+ return real_pthread_join(t, arg);
+}
+
+DEFINE_REAL_PTHREAD_FUNCTIONS
+#endif // ASAN_INTERCEPT_PTHREAD_CREATE
+
+#if ASAN_INTERCEPT_SWAPCONTEXT
+static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
+ // Only clear if we know the stack. This should be true only for contexts
+ // created with makecontext().
+ if (!ssize)
+ return;
+ // Align to page size.
+ uptr PageSize = GetPageSizeCached();
+ uptr bottom = RoundDownTo(stack, PageSize);
+ if (!AddrIsInMem(bottom))
+ return;
+ ssize += stack - bottom;
+ ssize = RoundUpTo(ssize, PageSize);
+ PoisonShadow(bottom, ssize, 0);
+}
+
+INTERCEPTOR(void, makecontext, struct ucontext_t *ucp, void (*func)(), int argc,
+ ...) {
+ va_list ap;
+ uptr args[64];
+ // We don't know a better way to forward ... into REAL function. We can
+ // increase args size if neccecary.
+ CHECK_LE(argc, ARRAY_SIZE(args));
+ internal_memset(args, 0, sizeof(args));
+ va_start(ap, argc);
+ for (int i = 0; i < argc; ++i) args[i] = va_arg(ap, uptr);
+ va_end(ap);
+
+# define ENUMERATE_ARRAY_4(start) \
+ args[start], args[start + 1], args[start + 2], args[start + 3]
+# define ENUMERATE_ARRAY_16(start) \
+ ENUMERATE_ARRAY_4(start), ENUMERATE_ARRAY_4(start + 4), \
+ ENUMERATE_ARRAY_4(start + 8), ENUMERATE_ARRAY_4(start + 12)
+# define ENUMERATE_ARRAY_64() \
+ ENUMERATE_ARRAY_16(0), ENUMERATE_ARRAY_16(16), ENUMERATE_ARRAY_16(32), \
+ ENUMERATE_ARRAY_16(48)
+
+ REAL(makecontext)
+ ((struct ucontext_t *)ucp, func, argc, ENUMERATE_ARRAY_64());
+
+# undef ENUMERATE_ARRAY_4
+# undef ENUMERATE_ARRAY_16
+# undef ENUMERATE_ARRAY_64
+
+ // Sign the stack so we can identify it for unpoisoning.
+ SignContextStack(ucp);
+}
+
+INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
+ struct ucontext_t *ucp) {
+ static bool reported_warning = false;
+ if (!reported_warning) {
+ Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
+ "functions and may produce false positives in some cases!\n");
+ reported_warning = true;
+ }
+ // Clear shadow memory for new context (it may share stack
+ // with current context).
+ uptr stack, ssize;
+ ReadContextStack(ucp, &stack, &ssize);
+ ClearShadowMemoryForContextStack(stack, ssize);
+
+# if __has_attribute(__indirect_return__) && \
+ (defined(__x86_64__) || defined(__i386__))
+ int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *)
+ __attribute__((__indirect_return__)) = REAL(swapcontext);
+ int res = real_swapcontext(oucp, ucp);
+# else
+ int res = REAL(swapcontext)(oucp, ucp);
+# endif
+ // swapcontext technically does not return, but program may swap context to
+ // "oucp" later, that would look as if swapcontext() returned 0.
+ // We need to clear shadow for ucp once again, as it may be in arbitrary
+ // state.
+ ClearShadowMemoryForContextStack(stack, ssize);
+ return res;
+}
+#endif // ASAN_INTERCEPT_SWAPCONTEXT
+
+#if SANITIZER_NETBSD
+#define longjmp __longjmp14
+#define siglongjmp __siglongjmp14
+#endif
+
+INTERCEPTOR(void, longjmp, void *env, int val) {
+ __asan_handle_no_return();
+ REAL(longjmp)(env, val);
+}
+
+#if ASAN_INTERCEPT__LONGJMP
+INTERCEPTOR(void, _longjmp, void *env, int val) {
+ __asan_handle_no_return();
+ REAL(_longjmp)(env, val);
+}
+#endif
+
+#if ASAN_INTERCEPT___LONGJMP_CHK
+INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
+ __asan_handle_no_return();
+ REAL(__longjmp_chk)(env, val);
+}
+#endif
+
+#if ASAN_INTERCEPT_SIGLONGJMP
+INTERCEPTOR(void, siglongjmp, void *env, int val) {
+ __asan_handle_no_return();
+ REAL(siglongjmp)(env, val);
+}
+#endif
+
+#if ASAN_INTERCEPT___CXA_THROW
+INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
+ CHECK(REAL(__cxa_throw));
+ __asan_handle_no_return();
+ REAL(__cxa_throw)(a, b, c);
+}
+#endif
+
+#if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
+INTERCEPTOR(void, __cxa_rethrow_primary_exception, void *a) {
+ CHECK(REAL(__cxa_rethrow_primary_exception));
+ __asan_handle_no_return();
+ REAL(__cxa_rethrow_primary_exception)(a);
+}
+#endif
+
+#if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
+INTERCEPTOR(_Unwind_Reason_Code, _Unwind_RaiseException,
+ _Unwind_Exception *object) {
+ CHECK(REAL(_Unwind_RaiseException));
+ __asan_handle_no_return();
+ return REAL(_Unwind_RaiseException)(object);
+}
+#endif
+
+#if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION
+INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException,
+ _Unwind_Exception *object) {
+ CHECK(REAL(_Unwind_SjLj_RaiseException));
+ __asan_handle_no_return();
+ return REAL(_Unwind_SjLj_RaiseException)(object);
+}
+#endif
+
+#if ASAN_INTERCEPT_INDEX
+# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
+INTERCEPTOR(char*, index, const char *string, int c)
+ ALIAS(WRAPPER_NAME(strchr));
+# else
+# if SANITIZER_APPLE
+DECLARE_REAL(char*, index, const char *string, int c)
+OVERRIDE_FUNCTION(index, strchr);
+# else
+DEFINE_REAL(char*, index, const char *string, int c)
+# endif
+# endif
+#endif // ASAN_INTERCEPT_INDEX
+
+// For both strcat() and strncat() we need to check the validity of |to|
+// argument irrespective of the |from| length.
+ INTERCEPTOR(char *, strcat, char *to, const char *from) {
+ void *ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, strcat);
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_str) {
+ uptr from_length = internal_strlen(from);
+ ASAN_READ_RANGE(ctx, from, from_length + 1);
+ uptr to_length = internal_strlen(to);
+ ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
+ ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
+ // If the copying actually happens, the |from| string should not overlap
+ // with the resulting string starting at |to|, which has a length of
+ // to_length + from_length + 1.
+ if (from_length > 0) {
+ CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from,
+ from_length + 1);
+ }
+ }
+ return REAL(strcat)(to, from);
+ }
+
+INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
+ void *ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, strncat);
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_str) {
+ uptr from_length = MaybeRealStrnlen(from, size);
+ uptr copy_length = Min(size, from_length + 1);
+ ASAN_READ_RANGE(ctx, from, copy_length);
+ uptr to_length = internal_strlen(to);
+ ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length);
+ ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1);
+ if (from_length > 0) {
+ CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1,
+ from, copy_length);
+ }
+ }
+ return REAL(strncat)(to, from, size);
+}
+
+INTERCEPTOR(char *, strcpy, char *to, const char *from) {
+ void *ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, strcpy);
+#if SANITIZER_APPLE
+ if (UNLIKELY(!asan_inited))
+ return REAL(strcpy)(to, from);
+#endif
+ // strcpy is called from malloc_default_purgeable_zone()
+ // in __asan::ReplaceSystemAlloc() on Mac.
+ if (asan_init_is_running) {
+ return REAL(strcpy)(to, from);
+ }
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_str) {
+ uptr from_size = internal_strlen(from) + 1;
+ CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size);
+ ASAN_READ_RANGE(ctx, from, from_size);
+ ASAN_WRITE_RANGE(ctx, to, from_size);
+ }
+ return REAL(strcpy)(to, from);
+}
+
+INTERCEPTOR(char*, strdup, const char *s) {
+ void *ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, strdup);
+ if (UNLIKELY(!asan_inited)) return internal_strdup(s);
+ ENSURE_ASAN_INITED();
+ uptr length = internal_strlen(s);
+ if (flags()->replace_str) {
+ ASAN_READ_RANGE(ctx, s, length + 1);
+ }
+ GET_STACK_TRACE_MALLOC;
+ void *new_mem = asan_malloc(length + 1, &stack);
+ REAL(memcpy)(new_mem, s, length + 1);
+ return reinterpret_cast<char*>(new_mem);
+}
+
+#if ASAN_INTERCEPT___STRDUP
+INTERCEPTOR(char*, __strdup, const char *s) {
+ void *ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, strdup);
+ if (UNLIKELY(!asan_inited)) return internal_strdup(s);
+ ENSURE_ASAN_INITED();
+ uptr length = internal_strlen(s);
+ if (flags()->replace_str) {
+ ASAN_READ_RANGE(ctx, s, length + 1);
+ }
+ GET_STACK_TRACE_MALLOC;
+ void *new_mem = asan_malloc(length + 1, &stack);
+ REAL(memcpy)(new_mem, s, length + 1);
+ return reinterpret_cast<char*>(new_mem);
+}
+#endif // ASAN_INTERCEPT___STRDUP
+
+INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
+ void *ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
+ ENSURE_ASAN_INITED();
+ if (flags()->replace_str) {
+ uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
+ CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size);
+ ASAN_READ_RANGE(ctx, from, from_size);
+ ASAN_WRITE_RANGE(ctx, to, size);
+ }
+ return REAL(strncpy)(to, from, size);
+}
+
+INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) {
+ void *ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, strtol);
+ ENSURE_ASAN_INITED();
+ if (!flags()->replace_str) {
+ return REAL(strtol)(nptr, endptr, base);
+ }
+ char *real_endptr;
+ long result = REAL(strtol)(nptr, &real_endptr, base);
+ StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
+ return result;
+}
+
+INTERCEPTOR(int, atoi, const char *nptr) {
+ void *ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, atoi);
+#if SANITIZER_APPLE
+ if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr);
+#endif
+ ENSURE_ASAN_INITED();
+ if (!flags()->replace_str) {
+ return REAL(atoi)(nptr);
+ }
+ char *real_endptr;
+ // "man atoi" tells that behavior of atoi(nptr) is the same as
+ // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
+ // parsed integer can't be stored in *long* type (even if it's
+ // different from int). So, we just imitate this behavior.
+ int result = REAL(strtol)(nptr, &real_endptr, 10);
+ FixRealStrtolEndptr(nptr, &real_endptr);
+ ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
+ return result;
+}
+
+INTERCEPTOR(long, atol, const char *nptr) {
+ void *ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, atol);
+#if SANITIZER_APPLE
+ if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr);
+#endif
+ ENSURE_ASAN_INITED();
+ if (!flags()->replace_str) {
+ return REAL(atol)(nptr);
+ }
+ char *real_endptr;
+ long result = REAL(strtol)(nptr, &real_endptr, 10);
+ FixRealStrtolEndptr(nptr, &real_endptr);
+ ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
+ return result;
+}
+
+#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) {
+ void *ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
+ ENSURE_ASAN_INITED();
+ if (!flags()->replace_str) {
+ return REAL(strtoll)(nptr, endptr, base);
+ }
+ char *real_endptr;
+ long long result = REAL(strtoll)(nptr, &real_endptr, base);
+ StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
+ return result;
+}
+
+INTERCEPTOR(long long, atoll, const char *nptr) {
+ void *ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, atoll);
+ ENSURE_ASAN_INITED();
+ if (!flags()->replace_str) {
+ return REAL(atoll)(nptr);
+ }
+ char *real_endptr;
+ long long result = REAL(strtoll)(nptr, &real_endptr, 10);
+ FixRealStrtolEndptr(nptr, &real_endptr);
+ ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
+ return result;
+}
+#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+
+#if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
+static void AtCxaAtexit(void *unused) {
+ (void)unused;
+ StopInitOrderChecking();
+}
+#endif
+
+#if ASAN_INTERCEPT___CXA_ATEXIT
+INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
+ void *dso_handle) {
+#if SANITIZER_APPLE
+ if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle);
+#endif
+ ENSURE_ASAN_INITED();
+#if CAN_SANITIZE_LEAKS
+ __lsan::ScopedInterceptorDisabler disabler;
+#endif
+ int res = REAL(__cxa_atexit)(func, arg, dso_handle);
+ REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
+ return res;
+}
+#endif // ASAN_INTERCEPT___CXA_ATEXIT
+
+#if ASAN_INTERCEPT_ATEXIT
+INTERCEPTOR(int, atexit, void (*func)()) {
+ ENSURE_ASAN_INITED();
+#if CAN_SANITIZE_LEAKS
+ __lsan::ScopedInterceptorDisabler disabler;
+#endif
+ // Avoid calling real atexit as it is unreachable on at least on Linux.
+ int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr);
+ REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr);
+ return res;
+}
+#endif
+
+#if ASAN_INTERCEPT_PTHREAD_ATFORK
+extern "C" {
+extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
+ void (*child)());
+};
+
+INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
+ void (*child)()) {
+#if CAN_SANITIZE_LEAKS
+ __lsan::ScopedInterceptorDisabler disabler;
+#endif
+ // REAL(pthread_atfork) cannot be called due to symbol indirections at least
+ // on NetBSD
+ return _pthread_atfork(prepare, parent, child);
+}
+#endif
+
+#if ASAN_INTERCEPT_VFORK
+DEFINE_REAL(int, vfork)
+DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
+#endif
+
+// ---------------------- InitializeAsanInterceptors ---------------- {{{1
+namespace __asan {
+void InitializeAsanInterceptors() {
+ static bool was_called_once;
+ CHECK(!was_called_once);
+ was_called_once = true;
+ InitializeCommonInterceptors();
+ InitializeSignalInterceptors();
+
+ // Intercept str* functions.
+ ASAN_INTERCEPT_FUNC(strcat);
+ ASAN_INTERCEPT_FUNC(strcpy);
+ ASAN_INTERCEPT_FUNC(strncat);
+ ASAN_INTERCEPT_FUNC(strncpy);
+ ASAN_INTERCEPT_FUNC(strdup);
+#if ASAN_INTERCEPT___STRDUP
+ ASAN_INTERCEPT_FUNC(__strdup);
+#endif
+#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX
+ ASAN_INTERCEPT_FUNC(index);
+#endif
+
+ ASAN_INTERCEPT_FUNC(atoi);
+ ASAN_INTERCEPT_FUNC(atol);
+ ASAN_INTERCEPT_FUNC(strtol);
+#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+ ASAN_INTERCEPT_FUNC(atoll);
+ ASAN_INTERCEPT_FUNC(strtoll);
+#endif
+
+ // Intecept jump-related functions.
+ ASAN_INTERCEPT_FUNC(longjmp);
+
+# if ASAN_INTERCEPT_SWAPCONTEXT
+ ASAN_INTERCEPT_FUNC(swapcontext);
+ ASAN_INTERCEPT_FUNC(makecontext);
+# endif
+# if ASAN_INTERCEPT__LONGJMP
+ ASAN_INTERCEPT_FUNC(_longjmp);
+#endif
+#if ASAN_INTERCEPT___LONGJMP_CHK
+ ASAN_INTERCEPT_FUNC(__longjmp_chk);
+#endif
+#if ASAN_INTERCEPT_SIGLONGJMP
+ ASAN_INTERCEPT_FUNC(siglongjmp);
+#endif
+
+ // Intercept exception handling functions.
+#if ASAN_INTERCEPT___CXA_THROW
+ ASAN_INTERCEPT_FUNC(__cxa_throw);
+#endif
+#if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
+ ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception);
+#endif
+ // Indirectly intercept std::rethrow_exception.
+#if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION
+ INTERCEPT_FUNCTION(_Unwind_RaiseException);
+#endif
+ // Indirectly intercept std::rethrow_exception.
+#if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION
+ INTERCEPT_FUNCTION(_Unwind_SjLj_RaiseException);
+#endif
+
+ // Intercept threading-related functions
+#if ASAN_INTERCEPT_PTHREAD_CREATE
+// TODO: this should probably have an unversioned fallback for newer arches?
+#if defined(ASAN_PTHREAD_CREATE_VERSION)
+ ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
+#else
+ ASAN_INTERCEPT_FUNC(pthread_create);
+#endif
+ ASAN_INTERCEPT_FUNC(pthread_join);
+#endif
+
+ // Intercept atexit function.
+#if ASAN_INTERCEPT___CXA_ATEXIT
+ ASAN_INTERCEPT_FUNC(__cxa_atexit);
+#endif
+
+#if ASAN_INTERCEPT_ATEXIT
+ ASAN_INTERCEPT_FUNC(atexit);
+#endif
+
+#if ASAN_INTERCEPT_PTHREAD_ATFORK
+ ASAN_INTERCEPT_FUNC(pthread_atfork);
+#endif
+
+#if ASAN_INTERCEPT_VFORK
+ ASAN_INTERCEPT_FUNC(vfork);
+#endif
+
+ InitializePlatformInterceptors();
+
+ VReport(1, "AddressSanitizer: libc interceptors initialized\n");
+}
+
+} // namespace __asan
+
+#endif // !SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_interceptors.h b/contrib/libs/clang16-rt/lib/asan/asan_interceptors.h
new file mode 100644
index 00000000000..c4bf087ea17
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_interceptors.h
@@ -0,0 +1,163 @@
+//===-- asan_interceptors.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan-private header for asan_interceptors.cpp
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_INTERCEPTORS_H
+#define ASAN_INTERCEPTORS_H
+
+#include "asan_interceptors_memintrinsics.h"
+#include "asan_internal.h"
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_platform.h"
+#include "sanitizer_common/sanitizer_platform_interceptors.h"
+
+namespace __asan {
+
+void InitializeAsanInterceptors();
+void InitializePlatformInterceptors();
+
+#define ENSURE_ASAN_INITED() \
+ do { \
+ CHECK(!asan_init_is_running); \
+ if (UNLIKELY(!asan_inited)) { \
+ AsanInitFromRtl(); \
+ } \
+ } while (0)
+
+} // namespace __asan
+
+// There is no general interception at all on Fuchsia.
+// Only the functions in asan_interceptors_memintrinsics.h are
+// really defined to replace libc functions.
+#if !SANITIZER_FUCHSIA
+
+// Use macro to describe if specific function should be
+// intercepted on a given platform.
+#if !SANITIZER_WINDOWS
+# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1
+# define ASAN_INTERCEPT__LONGJMP 1
+# define ASAN_INTERCEPT_INDEX 1
+# define ASAN_INTERCEPT_PTHREAD_CREATE 1
+#else
+# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0
+# define ASAN_INTERCEPT__LONGJMP 0
+# define ASAN_INTERCEPT_INDEX 0
+# define ASAN_INTERCEPT_PTHREAD_CREATE 0
+#endif
+
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
+ SANITIZER_SOLARIS
+# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 1
+#else
+# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 0
+#endif
+
+#if SANITIZER_GLIBC || SANITIZER_SOLARIS
+# define ASAN_INTERCEPT_SWAPCONTEXT 1
+#else
+# define ASAN_INTERCEPT_SWAPCONTEXT 0
+#endif
+
+#if !SANITIZER_WINDOWS
+# define ASAN_INTERCEPT_SIGLONGJMP 1
+#else
+# define ASAN_INTERCEPT_SIGLONGJMP 0
+#endif
+
+#if SANITIZER_GLIBC
+# define ASAN_INTERCEPT___LONGJMP_CHK 1
+#else
+# define ASAN_INTERCEPT___LONGJMP_CHK 0
+#endif
+
+#if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS && !SANITIZER_SOLARIS && \
+ !SANITIZER_NETBSD
+# define ASAN_INTERCEPT___CXA_THROW 1
+# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
+# if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && defined(__arm__))
+# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1
+# else
+# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 1
+# endif
+#else
+# define ASAN_INTERCEPT___CXA_THROW 0
+# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 0
+# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 0
+# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 0
+#endif
+
+#if !SANITIZER_WINDOWS
+# define ASAN_INTERCEPT___CXA_ATEXIT 1
+#else
+# define ASAN_INTERCEPT___CXA_ATEXIT 0
+#endif
+
+#if SANITIZER_NETBSD
+# define ASAN_INTERCEPT_ATEXIT 1
+#else
+# define ASAN_INTERCEPT_ATEXIT 0
+#endif
+
+#if SANITIZER_GLIBC
+# define ASAN_INTERCEPT___STRDUP 1
+#else
+# define ASAN_INTERCEPT___STRDUP 0
+#endif
+
+#if SANITIZER_LINUX && \
+ (defined(__arm__) || defined(__aarch64__) || defined(__i386__) || \
+ defined(__x86_64__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64)
+# define ASAN_INTERCEPT_VFORK 1
+#else
+# define ASAN_INTERCEPT_VFORK 0
+#endif
+
+#if SANITIZER_NETBSD
+# define ASAN_INTERCEPT_PTHREAD_ATFORK 1
+#else
+# define ASAN_INTERCEPT_PTHREAD_ATFORK 0
+#endif
+
+DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size)
+DECLARE_REAL(char*, strchr, const char *str, int c)
+DECLARE_REAL(SIZE_T, strlen, const char *s)
+DECLARE_REAL(char*, strncpy, char *to, const char *from, uptr size)
+DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen)
+DECLARE_REAL(char*, strstr, const char *s1, const char *s2)
+
+# if !SANITIZER_APPLE
+# define ASAN_INTERCEPT_FUNC(name) \
+ do { \
+ if (!INTERCEPT_FUNCTION(name)) \
+ VReport(1, "AddressSanitizer: failed to intercept '%s'\n", #name); \
+ } while (0)
+# define ASAN_INTERCEPT_FUNC_VER(name, ver) \
+ do { \
+ if (!INTERCEPT_FUNCTION_VER(name, ver)) \
+ VReport(1, "AddressSanitizer: failed to intercept '%s@@%s'\n", \
+ #name, ver); \
+ } while (0)
+# define ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
+ do { \
+ if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
+ VReport(1, \
+ "AddressSanitizer: failed to intercept '%s@@%s' or '%s'\n", \
+ #name, ver, #name); \
+ } while (0)
+
+# else
+// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
+# define ASAN_INTERCEPT_FUNC(name)
+# endif // SANITIZER_APPLE
+
+#endif // !SANITIZER_FUCHSIA
+
+#endif // ASAN_INTERCEPTORS_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_interceptors_memintrinsics.cpp b/contrib/libs/clang16-rt/lib/asan/asan_interceptors_memintrinsics.cpp
new file mode 100644
index 00000000000..9c316bb9574
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_interceptors_memintrinsics.cpp
@@ -0,0 +1,43 @@
+//===-- asan_interceptors_memintrinsics.cpp -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan versions of memcpy, memmove, and memset.
+//===---------------------------------------------------------------------===//
+
+#include "asan_interceptors_memintrinsics.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "asan_suppressions.h"
+
+using namespace __asan;
+
+void *__asan_memcpy(void *to, const void *from, uptr size) {
+ ASAN_MEMCPY_IMPL(nullptr, to, from, size);
+}
+
+void *__asan_memset(void *block, int c, uptr size) {
+ ASAN_MEMSET_IMPL(nullptr, block, c, size);
+}
+
+void *__asan_memmove(void *to, const void *from, uptr size) {
+ ASAN_MEMMOVE_IMPL(nullptr, to, from, size);
+}
+
+#if SANITIZER_FUCHSIA
+
+// Fuchsia doesn't use sanitizer_common_interceptors.inc, but
+// the only things there it wants are these three. Just define them
+// as aliases here rather than repeating the contents.
+
+extern "C" decltype(__asan_memcpy) memcpy[[gnu::alias("__asan_memcpy")]];
+extern "C" decltype(__asan_memmove) memmove[[gnu::alias("__asan_memmove")]];
+extern "C" decltype(__asan_memset) memset[[gnu::alias("__asan_memset")]];
+
+#endif // SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_interceptors_memintrinsics.h b/contrib/libs/clang16-rt/lib/asan/asan_interceptors_memintrinsics.h
new file mode 100644
index 00000000000..bbc5390ceaa
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_interceptors_memintrinsics.h
@@ -0,0 +1,150 @@
+//===-- asan_interceptors_memintrinsics.h -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan-private header for asan_interceptors_memintrinsics.cpp
+//===---------------------------------------------------------------------===//
+#ifndef ASAN_MEMINTRIN_H
+#define ASAN_MEMINTRIN_H
+
+#include "asan_interface_internal.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "interception/interception.h"
+
+DECLARE_REAL(void *, memcpy, void *to, const void *from, uptr size)
+DECLARE_REAL(void *, memset, void *block, int c, uptr size)
+
+namespace __asan {
+
+// Return true if we can quickly decide that the region is unpoisoned.
+// We assume that a redzone is at least 16 bytes.
+static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
+ if (UNLIKELY(size == 0 || size > sizeof(uptr) * ASAN_SHADOW_GRANULARITY))
+ return !size;
+
+ uptr last = beg + size - 1;
+ uptr shadow_first = MEM_TO_SHADOW(beg);
+ uptr shadow_last = MEM_TO_SHADOW(last);
+ uptr uptr_first = RoundDownTo(shadow_first, sizeof(uptr));
+ uptr uptr_last = RoundDownTo(shadow_last, sizeof(uptr));
+ if (LIKELY(((*reinterpret_cast<const uptr *>(uptr_first) |
+ *reinterpret_cast<const uptr *>(uptr_last)) == 0)))
+ return true;
+ u8 shadow = AddressIsPoisoned(last);
+ for (; shadow_first < shadow_last; ++shadow_first)
+ shadow |= *((u8 *)shadow_first);
+ return !shadow;
+}
+
+struct AsanInterceptorContext {
+ const char *interceptor_name;
+};
+
+// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
+// and ASAN_WRITE_RANGE as macro instead of function so
+// that no extra frames are created, and stack trace contains
+// relevant information only.
+// We check all shadow bytes.
+#define ACCESS_MEMORY_RANGE(ctx, offset, size, isWrite) \
+ do { \
+ uptr __offset = (uptr)(offset); \
+ uptr __size = (uptr)(size); \
+ uptr __bad = 0; \
+ if (UNLIKELY(__offset > __offset + __size)) { \
+ GET_STACK_TRACE_FATAL_HERE; \
+ ReportStringFunctionSizeOverflow(__offset, __size, &stack); \
+ } \
+ if (UNLIKELY(!QuickCheckForUnpoisonedRegion(__offset, __size)) && \
+ (__bad = __asan_region_is_poisoned(__offset, __size))) { \
+ AsanInterceptorContext *_ctx = (AsanInterceptorContext *)ctx; \
+ bool suppressed = false; \
+ if (_ctx) { \
+ suppressed = IsInterceptorSuppressed(_ctx->interceptor_name); \
+ if (!suppressed && HaveStackTraceBasedSuppressions()) { \
+ GET_STACK_TRACE_FATAL_HERE; \
+ suppressed = IsStackTraceSuppressed(&stack); \
+ } \
+ } \
+ if (!suppressed) { \
+ GET_CURRENT_PC_BP_SP; \
+ ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false); \
+ } \
+ } \
+ } while (0)
+
+// memcpy is called during __asan_init() from the internals of printf(...).
+// We do not treat memcpy with to==from as a bug.
+// See http://llvm.org/bugs/show_bug.cgi?id=11763.
+#define ASAN_MEMCPY_IMPL(ctx, to, from, size) \
+ do { \
+ if (LIKELY(replace_intrin_cached)) { \
+ if (LIKELY(to != from)) { \
+ CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); \
+ } \
+ ASAN_READ_RANGE(ctx, from, size); \
+ ASAN_WRITE_RANGE(ctx, to, size); \
+ } else if (UNLIKELY(!asan_inited)) { \
+ return internal_memcpy(to, from, size); \
+ } \
+ return REAL(memcpy)(to, from, size); \
+ } while (0)
+
+// memset is called inside Printf.
+#define ASAN_MEMSET_IMPL(ctx, block, c, size) \
+ do { \
+ if (LIKELY(replace_intrin_cached)) { \
+ ASAN_WRITE_RANGE(ctx, block, size); \
+ } else if (UNLIKELY(!asan_inited)) { \
+ return internal_memset(block, c, size); \
+ } \
+ return REAL(memset)(block, c, size); \
+ } while (0)
+
+#define ASAN_MEMMOVE_IMPL(ctx, to, from, size) \
+ do { \
+ if (LIKELY(replace_intrin_cached)) { \
+ ASAN_READ_RANGE(ctx, from, size); \
+ ASAN_WRITE_RANGE(ctx, to, size); \
+ } \
+ return internal_memmove(to, from, size); \
+ } while (0)
+
+#define ASAN_READ_RANGE(ctx, offset, size) \
+ ACCESS_MEMORY_RANGE(ctx, offset, size, false)
+#define ASAN_WRITE_RANGE(ctx, offset, size) \
+ ACCESS_MEMORY_RANGE(ctx, offset, size, true)
+
+// Behavior of functions like "memcpy" or "strcpy" is undefined
+// if memory intervals overlap. We report error in this case.
+// Macro is used to avoid creation of new frames.
+static inline bool RangesOverlap(const char *offset1, uptr length1,
+ const char *offset2, uptr length2) {
+ return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1));
+}
+#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) \
+ do { \
+ const char *offset1 = (const char *)_offset1; \
+ const char *offset2 = (const char *)_offset2; \
+ if (UNLIKELY(RangesOverlap(offset1, length1, offset2, length2))) { \
+ GET_STACK_TRACE_FATAL_HERE; \
+ bool suppressed = IsInterceptorSuppressed(name); \
+ if (!suppressed && HaveStackTraceBasedSuppressions()) { \
+ suppressed = IsStackTraceSuppressed(&stack); \
+ } \
+ if (!suppressed) { \
+ ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \
+ offset2, length2, &stack); \
+ } \
+ } \
+ } while (0)
+
+} // namespace __asan
+
+#endif // ASAN_MEMINTRIN_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_interceptors_vfork.S b/contrib/libs/clang16-rt/lib/asan/asan_interceptors_vfork.S
new file mode 100644
index 00000000000..ec29adc7b13
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_interceptors_vfork.S
@@ -0,0 +1,14 @@
+#include "sanitizer_common/sanitizer_asm.h"
+
+#if defined(__linux__)
+#define COMMON_INTERCEPTOR_SPILL_AREA __asan_extra_spill_area
+#define COMMON_INTERCEPTOR_HANDLE_VFORK __asan_handle_vfork
+#include "sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S"
+#include "sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S"
+#include "sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S"
+#include "sanitizer_common/sanitizer_common_interceptors_vfork_loongarch64.inc.S"
+#include "sanitizer_common/sanitizer_common_interceptors_vfork_riscv64.inc.S"
+#include "sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S"
+#endif
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_interface_internal.h b/contrib/libs/clang16-rt/lib/asan/asan_interface_internal.h
new file mode 100644
index 00000000000..987f855c0f9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_interface_internal.h
@@ -0,0 +1,274 @@
+//===-- asan_interface_internal.h -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// This header declares the AddressSanitizer runtime interface functions.
+// The runtime library has to define these functions so the instrumented program
+// could call them.
+//
+// See also include/sanitizer/asan_interface.h
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_INTERFACE_INTERNAL_H
+#define ASAN_INTERFACE_INTERNAL_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+#include "asan_init_version.h"
+
+using __sanitizer::uptr;
+using __sanitizer::u64;
+using __sanitizer::u32;
+
+extern "C" {
+ // This function should be called at the very beginning of the process,
+ // before any instrumented code is executed and before any call to malloc.
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_init();
+
+ // This function exists purely to get a linker/loader error when using
+ // incompatible versions of instrumentation and runtime library. Please note
+ // that __asan_version_mismatch_check is a macro that is replaced with
+ // __asan_version_mismatch_check_vXXX at compile-time.
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_version_mismatch_check();
+
+ // This structure is used to describe the source location of a place where
+ // global was defined.
+ struct __asan_global_source_location {
+ const char *filename;
+ int line_no;
+ int column_no;
+ };
+
+ // This structure describes an instrumented global variable.
+ struct __asan_global {
+ uptr beg; // The address of the global.
+ uptr size; // The original size of the global.
+ uptr size_with_redzone; // The size with the redzone.
+ const char *name; // Name as a C string.
+ const char *module_name; // Module name as a C string. This pointer is a
+ // unique identifier of a module.
+ uptr has_dynamic_init; // Non-zero if the global has dynamic initializer.
+ uptr windows_padding; // TODO: Figure out how to remove this padding
+ // that's simply here to make the MSVC incremental
+ // linker happy...
+ uptr odr_indicator; // The address of the ODR indicator symbol.
+ };
+
+ // These functions can be called on some platforms to find globals in the same
+ // loaded image as `flag' and apply __asan_(un)register_globals to them,
+ // filtering out redundant calls.
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_register_image_globals(uptr *flag);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_unregister_image_globals(uptr *flag);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_register_elf_globals(uptr *flag, void *start, void *stop);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_unregister_elf_globals(uptr *flag, void *start, void *stop);
+
+ // These two functions should be called by the instrumented code.
+ // 'globals' is an array of structures describing 'n' globals.
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_register_globals(__asan_global *globals, uptr n);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_unregister_globals(__asan_global *globals, uptr n);
+
+ // These two functions should be called before and after dynamic initializers
+ // of a single module run, respectively.
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_before_dynamic_init(const char *module_name);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_after_dynamic_init();
+
+ // Sets bytes of the given range of the shadow memory into specific value.
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_shadow_00(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_shadow_01(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_shadow_02(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_shadow_03(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_shadow_04(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_shadow_05(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_shadow_06(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_shadow_07(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_shadow_f1(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_shadow_f2(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_shadow_f3(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_shadow_f5(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_shadow_f8(uptr addr, uptr size);
+
+ // These two functions are used by instrumented code in the
+ // use-after-scope mode. They mark memory for local variables as
+ // unaddressable when they leave scope and addressable before the
+ // function exits.
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_poison_stack_memory(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_unpoison_stack_memory(uptr addr, uptr size);
+
+ // Performs cleanup before a NoReturn function. Must be called before things
+ // like _exit and execl to avoid false positives on stack.
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_handle_no_return();
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_poison_memory_region(void const volatile *addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_unpoison_memory_region(void const volatile *addr, uptr size);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ int __asan_address_is_poisoned(void const volatile *addr);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ uptr __asan_region_is_poisoned(uptr beg, uptr size);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_describe_address(uptr addr);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ int __asan_report_present();
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ uptr __asan_get_report_pc();
+ SANITIZER_INTERFACE_ATTRIBUTE
+ uptr __asan_get_report_bp();
+ SANITIZER_INTERFACE_ATTRIBUTE
+ uptr __asan_get_report_sp();
+ SANITIZER_INTERFACE_ATTRIBUTE
+ uptr __asan_get_report_address();
+ SANITIZER_INTERFACE_ATTRIBUTE
+ int __asan_get_report_access_type();
+ SANITIZER_INTERFACE_ATTRIBUTE
+ uptr __asan_get_report_access_size();
+ SANITIZER_INTERFACE_ATTRIBUTE
+ const char * __asan_get_report_description();
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ const char * __asan_locate_address(uptr addr, char *name, uptr name_size,
+ uptr *region_address, uptr *region_size);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ uptr __asan_get_alloc_stack(uptr addr, uptr *trace, uptr size,
+ u32 *thread_id);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ uptr __asan_get_free_stack(uptr addr, uptr *trace, uptr size,
+ u32 *thread_id);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_get_shadow_mapping(uptr *shadow_scale, uptr *shadow_offset);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_report_error(uptr pc, uptr bp, uptr sp,
+ uptr addr, int is_write, uptr access_size, u32 exp);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_death_callback(void (*callback)(void));
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_error_report_callback(void (*callback)(const char*));
+
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ void __asan_on_error();
+
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_print_accumulated_stats();
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ const char *__asan_default_options();
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ extern uptr __asan_shadow_memory_dynamic_address;
+
+ // Global flag, copy of ASAN_OPTIONS=detect_stack_use_after_return
+ SANITIZER_INTERFACE_ATTRIBUTE
+ extern int __asan_option_detect_stack_use_after_return;
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ extern uptr *__asan_test_only_reported_buggy_pointer;
+
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load1(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load2(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load4(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load8(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load16(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store1(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store2(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store4(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store8(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store16(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN(uptr p, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN(uptr p, uptr size);
+
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load1_noabort(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load2_noabort(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load4_noabort(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load8_noabort(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_load16_noabort(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store1_noabort(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store2_noabort(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store4_noabort(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store8_noabort(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_store16_noabort(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN_noabort(uptr p, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN_noabort(uptr p, uptr size);
+
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load1(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load2(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load4(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load8(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load16(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store1(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store2(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store4(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store8(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_store16(uptr p, u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_loadN(uptr p, uptr size,
+ u32 exp);
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_storeN(uptr p, uptr size,
+ u32 exp);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void* __asan_memcpy(void *dst, const void *src, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void* __asan_memset(void *s, int c, uptr n);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void* __asan_memmove(void* dest, const void* src, uptr n);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_poison_cxx_array_cookie(uptr p);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ uptr __asan_load_cxx_array_cookie(uptr *p);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_poison_intra_object_redzone(uptr p, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_unpoison_intra_object_redzone(uptr p, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_alloca_poison(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_allocas_unpoison(uptr top, uptr bottom);
+
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ const char* __asan_default_suppressions();
+
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_handle_vfork(void *sp);
+
+ SANITIZER_INTERFACE_ATTRIBUTE int __asan_update_allocation_context(
+ void *addr);
+} // extern "C"
+
+#endif // ASAN_INTERFACE_INTERNAL_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_internal.h b/contrib/libs/clang16-rt/lib/asan/asan_internal.h
new file mode 100644
index 00000000000..a5348e35b29
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_internal.h
@@ -0,0 +1,162 @@
+//===-- asan_internal.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan-private header which defines various general utilities.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_INTERNAL_H
+#define ASAN_INTERNAL_H
+
+#include "asan_flags.h"
+#include "asan_interface_internal.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+
+#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+# error \
+ "The AddressSanitizer run-time should not be instrumented by AddressSanitizer"
+#endif
+
+// Build-time configuration options.
+
+// If set, asan will intercept C++ exception api call(s).
+#ifndef ASAN_HAS_EXCEPTIONS
+# define ASAN_HAS_EXCEPTIONS 1
+#endif
+
+// If set, values like allocator chunk size, as well as defaults for some flags
+// will be changed towards less memory overhead.
+#ifndef ASAN_LOW_MEMORY
+# if SANITIZER_IOS || SANITIZER_ANDROID
+# define ASAN_LOW_MEMORY 1
+# else
+# define ASAN_LOW_MEMORY 0
+# endif
+#endif
+
+#ifndef ASAN_DYNAMIC
+# ifdef PIC
+# define ASAN_DYNAMIC 1
+# else
+# define ASAN_DYNAMIC 0
+# endif
+#endif
+
+// All internal functions in asan reside inside the __asan namespace
+// to avoid namespace collisions with the user programs.
+// Separate namespace also makes it simpler to distinguish the asan run-time
+// functions from the instrumented user code in a profile.
+namespace __asan {
+
+class AsanThread;
+using __sanitizer::StackTrace;
+
+void AsanInitFromRtl();
+
+// asan_win.cpp
+void InitializePlatformExceptionHandlers();
+// Returns whether an address is a valid allocated system heap block.
+// 'addr' must point to the beginning of the block.
+bool IsSystemHeapAddress(uptr addr);
+
+// asan_rtl.cpp
+void PrintAddressSpaceLayout();
+void NORETURN ShowStatsAndAbort();
+
+// asan_shadow_setup.cpp
+void InitializeShadowMemory();
+
+// asan_malloc_linux.cpp / asan_malloc_mac.cpp
+void ReplaceSystemMalloc();
+
+// asan_linux.cpp / asan_mac.cpp / asan_win.cpp
+uptr FindDynamicShadowStart();
+void *AsanDoesNotSupportStaticLinkage();
+void AsanCheckDynamicRTPrereqs();
+void AsanCheckIncompatibleRT();
+
+// Unpoisons platform-specific stacks.
+// Returns true if all stacks have been unpoisoned.
+bool PlatformUnpoisonStacks();
+
+// asan_rtl.cpp
+// Unpoison a region containing a stack.
+// Performs a sanity check and warns if the bounds don't look right.
+// The warning contains the type string to identify the stack type.
+void UnpoisonStack(uptr bottom, uptr top, const char *type);
+
+// asan_thread.cpp
+AsanThread *CreateMainThread();
+
+// Support function for __asan_(un)register_image_globals. Searches for the
+// loaded image containing `needle' and then enumerates all global metadata
+// structures declared in that image, applying `op' (e.g.,
+// __asan_(un)register_globals) to them.
+typedef void (*globals_op_fptr)(__asan_global *, uptr);
+void AsanApplyToGlobals(globals_op_fptr op, const void *needle);
+
+void AsanOnDeadlySignal(int, void *siginfo, void *context);
+
+void SignContextStack(void *context);
+void ReadContextStack(void *context, uptr *stack, uptr *ssize);
+void StopInitOrderChecking();
+
+// Wrapper for TLS/TSD.
+void AsanTSDInit(void (*destructor)(void *tsd));
+void *AsanTSDGet();
+void AsanTSDSet(void *tsd);
+void PlatformTSDDtor(void *tsd);
+
+void AppendToErrorMessageBuffer(const char *buffer);
+
+void *AsanDlSymNext(const char *sym);
+
+// Returns `true` iff most of ASan init process should be skipped due to the
+// ASan library being loaded via `dlopen()`. Platforms may perform any
+// `dlopen()` specific initialization inside this function.
+bool HandleDlopenInit();
+
+void InstallAtExitCheckLeaks();
+
+#define ASAN_ON_ERROR() \
+ if (&__asan_on_error) \
+ __asan_on_error()
+
+extern int asan_inited;
+// Used to avoid infinite recursion in __asan_init().
+extern bool asan_init_is_running;
+extern bool replace_intrin_cached;
+extern void (*death_callback)(void);
+// These magic values are written to shadow for better error
+// reporting.
+const int kAsanHeapLeftRedzoneMagic = 0xfa;
+const int kAsanHeapFreeMagic = 0xfd;
+const int kAsanStackLeftRedzoneMagic = 0xf1;
+const int kAsanStackMidRedzoneMagic = 0xf2;
+const int kAsanStackRightRedzoneMagic = 0xf3;
+const int kAsanStackAfterReturnMagic = 0xf5;
+const int kAsanInitializationOrderMagic = 0xf6;
+const int kAsanUserPoisonedMemoryMagic = 0xf7;
+const int kAsanContiguousContainerOOBMagic = 0xfc;
+const int kAsanStackUseAfterScopeMagic = 0xf8;
+const int kAsanGlobalRedzoneMagic = 0xf9;
+const int kAsanInternalHeapMagic = 0xfe;
+const int kAsanArrayCookieMagic = 0xac;
+const int kAsanIntraObjectRedzone = 0xbb;
+const int kAsanAllocaLeftMagic = 0xca;
+const int kAsanAllocaRightMagic = 0xcb;
+
+static const uptr kCurrentStackFrameMagic = 0x41B58AB3;
+static const uptr kRetiredStackFrameMagic = 0x45E0360E;
+
+} // namespace __asan
+
+#endif // ASAN_INTERNAL_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_linux.cpp b/contrib/libs/clang16-rt/lib/asan/asan_linux.cpp
new file mode 100644
index 00000000000..c8c723217a4
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_linux.cpp
@@ -0,0 +1,253 @@
+//===-- asan_linux.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Linux-specific details.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
+ SANITIZER_SOLARIS
+
+# include <dlfcn.h>
+# include <fcntl.h>
+# include <limits.h>
+# include <pthread.h>
+# include <stdio.h>
+# include <sys/mman.h>
+# include <sys/resource.h>
+# include <sys/syscall.h>
+# include <sys/time.h>
+# include <sys/types.h>
+# include <unistd.h>
+# include <unwind.h>
+
+# include "asan_interceptors.h"
+# include "asan_internal.h"
+# include "asan_premap_shadow.h"
+# include "asan_thread.h"
+# include "sanitizer_common/sanitizer_flags.h"
+# include "sanitizer_common/sanitizer_freebsd.h"
+# include "sanitizer_common/sanitizer_hash.h"
+# include "sanitizer_common/sanitizer_libc.h"
+# include "sanitizer_common/sanitizer_procmaps.h"
+
+# if SANITIZER_FREEBSD
+# error #include <sys/link_elf.h>
+# endif
+
+# if SANITIZER_SOLARIS
+# include <link.h>
+# endif
+
+# if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS
+# include <ucontext.h>
+extern "C" void *_DYNAMIC;
+# elif SANITIZER_NETBSD
+# error #include <link_elf.h>
+# include <ucontext.h>
+extern Elf_Dyn _DYNAMIC;
+# else
+# include <link.h>
+# include <sys/ucontext.h>
+extern ElfW(Dyn) _DYNAMIC[];
+# endif
+
+// x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in
+// 32-bit mode.
+# if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \
+ __FreeBSD_version <= 902001 // v9.2
+# define ucontext_t xucontext_t
+# endif
+
+typedef enum {
+ ASAN_RT_VERSION_UNDEFINED = 0,
+ ASAN_RT_VERSION_DYNAMIC,
+ ASAN_RT_VERSION_STATIC,
+} asan_rt_version_t;
+
+// FIXME: perhaps also store abi version here?
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+asan_rt_version_t __asan_rt_version;
+}
+
+namespace __asan {
+
+void InitializePlatformInterceptors() {}
+void InitializePlatformExceptionHandlers() {}
+bool IsSystemHeapAddress(uptr addr) { return false; }
+
+void *AsanDoesNotSupportStaticLinkage() {
+ // This will fail to link with -static.
+ return &_DYNAMIC;
+}
+
+# if ASAN_PREMAP_SHADOW
+uptr FindPremappedShadowStart(uptr shadow_size_bytes) {
+ uptr granularity = GetMmapGranularity();
+ uptr shadow_start = reinterpret_cast<uptr>(&__asan_shadow);
+ uptr premap_shadow_size = PremapShadowSize();
+ uptr shadow_size = RoundUpTo(shadow_size_bytes, granularity);
+ // We may have mapped too much. Release extra memory.
+ UnmapFromTo(shadow_start + shadow_size, shadow_start + premap_shadow_size);
+ return shadow_start;
+}
+# endif
+
+uptr FindDynamicShadowStart() {
+ uptr shadow_size_bytes = MemToShadowSize(kHighMemEnd);
+# if ASAN_PREMAP_SHADOW
+ if (!PremapShadowFailed())
+ return FindPremappedShadowStart(shadow_size_bytes);
+# endif
+
+ return MapDynamicShadow(shadow_size_bytes, ASAN_SHADOW_SCALE,
+ /*min_shadow_base_alignment*/ 0, kHighMemEnd);
+}
+
+void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
+ UNIMPLEMENTED();
+}
+
+void FlushUnneededASanShadowMemory(uptr p, uptr size) {
+ // Since asan's mapping is compacting, the shadow chunk may be
+ // not page-aligned, so we only flush the page-aligned portion.
+ ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
+}
+
+# if SANITIZER_ANDROID
+// FIXME: should we do anything for Android?
+void AsanCheckDynamicRTPrereqs() {}
+void AsanCheckIncompatibleRT() {}
+# else
+static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size,
+ void *data) {
+ VReport(2, "info->dlpi_name = %s\tinfo->dlpi_addr = %p\n", info->dlpi_name,
+ (void *)info->dlpi_addr);
+
+ const char **name = (const char **)data;
+
+ // Ignore first entry (the main program)
+ if (!*name) {
+ *name = "";
+ return 0;
+ }
+
+# if SANITIZER_LINUX
+ // Ignore vDSO. glibc versions earlier than 2.15 (and some patched
+ // by distributors) return an empty name for the vDSO entry, so
+ // detect this as well.
+ if (!info->dlpi_name[0] ||
+ internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
+ return 0;
+# endif
+
+ *name = info->dlpi_name;
+ return 1;
+}
+
+static bool IsDynamicRTName(const char *libname) {
+ return internal_strstr(libname, "libclang_rt.asan") ||
+ internal_strstr(libname, "libasan.so");
+}
+
+static void ReportIncompatibleRT() {
+ Report("Your application is linked against incompatible ASan runtimes.\n");
+ Die();
+}
+
+void AsanCheckDynamicRTPrereqs() {
+ if (!ASAN_DYNAMIC || !flags()->verify_asan_link_order)
+ return;
+
+ // Ensure that dynamic RT is the first DSO in the list
+ const char *first_dso_name = nullptr;
+ dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
+ if (first_dso_name && first_dso_name[0] && !IsDynamicRTName(first_dso_name)) {
+ Report(
+ "ASan runtime does not come first in initial library list; "
+ "you should either link runtime to your application or "
+ "manually preload it with LD_PRELOAD.\n");
+ Die();
+ }
+}
+
+void AsanCheckIncompatibleRT() {
+ if (ASAN_DYNAMIC) {
+ if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
+ __asan_rt_version = ASAN_RT_VERSION_DYNAMIC;
+ } else if (__asan_rt_version != ASAN_RT_VERSION_DYNAMIC) {
+ ReportIncompatibleRT();
+ }
+ } else {
+ if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
+ // Ensure that dynamic runtime is not present. We should detect it
+ // as early as possible, otherwise ASan interceptors could bind to
+ // the functions in dynamic ASan runtime instead of the functions in
+ // system libraries, causing crashes later in ASan initialization.
+ MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
+ char filename[PATH_MAX];
+ MemoryMappedSegment segment(filename, sizeof(filename));
+ while (proc_maps.Next(&segment)) {
+ if (IsDynamicRTName(segment.filename)) {
+ Report(
+ "Your application is linked against "
+ "incompatible ASan runtimes.\n");
+ Die();
+ }
+ }
+ __asan_rt_version = ASAN_RT_VERSION_STATIC;
+ } else if (__asan_rt_version != ASAN_RT_VERSION_STATIC) {
+ ReportIncompatibleRT();
+ }
+ }
+}
+# endif // SANITIZER_ANDROID
+
+# if ASAN_INTERCEPT_SWAPCONTEXT
+constexpr u32 kAsanContextStackFlagsMagic = 0x51260eea;
+
+static int HashContextStack(const ucontext_t &ucp) {
+ MurMur2Hash64Builder hash(kAsanContextStackFlagsMagic);
+ hash.add(reinterpret_cast<uptr>(ucp.uc_stack.ss_sp));
+ hash.add(ucp.uc_stack.ss_size);
+ return static_cast<int>(hash.get());
+}
+
+void SignContextStack(void *context) {
+ ucontext_t *ucp = reinterpret_cast<ucontext_t *>(context);
+ ucp->uc_stack.ss_flags = HashContextStack(*ucp);
+}
+
+void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
+ const ucontext_t *ucp = reinterpret_cast<const ucontext_t *>(context);
+ if (HashContextStack(*ucp) == ucp->uc_stack.ss_flags) {
+ *stack = reinterpret_cast<uptr>(ucp->uc_stack.ss_sp);
+ *ssize = ucp->uc_stack.ss_size;
+ return;
+ }
+ *stack = 0;
+ *ssize = 0;
+}
+# endif // ASAN_INTERCEPT_SWAPCONTEXT
+
+void *AsanDlSymNext(const char *sym) { return dlsym(RTLD_NEXT, sym); }
+
+bool HandleDlopenInit() {
+ // Not supported on this platform.
+ static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
+ "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
+ return false;
+}
+
+} // namespace __asan
+
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
+ // SANITIZER_SOLARIS
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_lock.h b/contrib/libs/clang16-rt/lib/asan/asan_lock.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_lock.h
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_mac.cpp b/contrib/libs/clang16-rt/lib/asan/asan_mac.cpp
new file mode 100644
index 00000000000..c9bd5fb8e1a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_mac.cpp
@@ -0,0 +1,295 @@
+//===-- asan_mac.cpp ------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Mac-specific details.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_APPLE
+
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "asan_stack.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_mac.h"
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <libkern/OSAtomic.h>
+#include <mach-o/dyld.h>
+#include <mach-o/getsect.h>
+#include <mach-o/loader.h>
+#include <pthread.h>
+#include <stdlib.h> // for free()
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
+#include <sys/ucontext.h>
+#include <unistd.h>
+
+// from <crt_externs.h>, but we don't have that file on iOS
+extern "C" {
+ extern char ***_NSGetArgv(void);
+ extern char ***_NSGetEnviron(void);
+}
+
+namespace __asan {
+
+void InitializePlatformInterceptors() {}
+void InitializePlatformExceptionHandlers() {}
+bool IsSystemHeapAddress (uptr addr) { return false; }
+
+// No-op. Mac does not support static linkage anyway.
+void *AsanDoesNotSupportStaticLinkage() {
+ return 0;
+}
+
+uptr FindDynamicShadowStart() {
+ return MapDynamicShadow(MemToShadowSize(kHighMemEnd), ASAN_SHADOW_SCALE,
+ /*min_shadow_base_alignment*/ 0, kHighMemEnd);
+}
+
+// No-op. Mac does not support static linkage anyway.
+void AsanCheckDynamicRTPrereqs() {}
+
+// No-op. Mac does not support static linkage anyway.
+void AsanCheckIncompatibleRT() {}
+
+void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
+ // Find the Mach-O header for the image containing the needle
+ Dl_info info;
+ int err = dladdr(needle, &info);
+ if (err == 0) return;
+
+#if __LP64__
+ const struct mach_header_64 *mh = (struct mach_header_64 *)info.dli_fbase;
+#else
+ const struct mach_header *mh = (struct mach_header *)info.dli_fbase;
+#endif
+
+ // Look up the __asan_globals section in that image and register its globals
+ unsigned long size = 0;
+ __asan_global *globals = (__asan_global *)getsectiondata(
+ mh,
+ "__DATA", "__asan_globals",
+ &size);
+
+ if (!globals) return;
+ if (size % sizeof(__asan_global) != 0) return;
+ op(globals, size / sizeof(__asan_global));
+}
+
+void FlushUnneededASanShadowMemory(uptr p, uptr size) {
+ // Since asan's mapping is compacting, the shadow chunk may be
+ // not page-aligned, so we only flush the page-aligned portion.
+ ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
+}
+
+// Support for the following functions from libdispatch on Mac OS:
+// dispatch_async_f()
+// dispatch_async()
+// dispatch_sync_f()
+// dispatch_sync()
+// dispatch_after_f()
+// dispatch_after()
+// dispatch_group_async_f()
+// dispatch_group_async()
+// TODO(glider): libdispatch API contains other functions that we don't support
+// yet.
+//
+// dispatch_sync() and dispatch_sync_f() are synchronous, although chances are
+// they can cause jobs to run on a thread different from the current one.
+// TODO(glider): if so, we need a test for this (otherwise we should remove
+// them).
+//
+// The following functions use dispatch_barrier_async_f() (which isn't a library
+// function but is exported) and are thus supported:
+// dispatch_source_set_cancel_handler_f()
+// dispatch_source_set_cancel_handler()
+// dispatch_source_set_event_handler_f()
+// dispatch_source_set_event_handler()
+//
+// The reference manual for Grand Central Dispatch is available at
+// http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html
+// The implementation details are at
+// http://libdispatch.macosforge.org/trac/browser/trunk/src/queue.c
+
+typedef void* dispatch_group_t;
+typedef void* dispatch_queue_t;
+typedef void* dispatch_source_t;
+typedef u64 dispatch_time_t;
+typedef void (*dispatch_function_t)(void *block);
+typedef void* (*worker_t)(void *block);
+
+// A wrapper for the ObjC blocks used to support libdispatch.
+typedef struct {
+ void *block;
+ dispatch_function_t func;
+ u32 parent_tid;
+} asan_block_context_t;
+
+ALWAYS_INLINE
+void asan_register_worker_thread(int parent_tid, StackTrace *stack) {
+ AsanThread *t = GetCurrentThread();
+ if (!t) {
+ t = AsanThread::Create(/* start_routine */ nullptr, /* arg */ nullptr,
+ parent_tid, stack, /* detached */ true);
+ t->Init();
+ asanThreadRegistry().StartThread(t->tid(), GetTid(), ThreadType::Worker,
+ nullptr);
+ SetCurrentThread(t);
+ }
+}
+
+// For use by only those functions that allocated the context via
+// alloc_asan_context().
+extern "C"
+void asan_dispatch_call_block_and_release(void *block) {
+ GET_STACK_TRACE_THREAD;
+ asan_block_context_t *context = (asan_block_context_t*)block;
+ VReport(2,
+ "asan_dispatch_call_block_and_release(): "
+ "context: %p, pthread_self: %p\n",
+ block, pthread_self());
+ asan_register_worker_thread(context->parent_tid, &stack);
+ // Call the original dispatcher for the block.
+ context->func(context->block);
+ asan_free(context, &stack, FROM_MALLOC);
+}
+
+} // namespace __asan
+
+using namespace __asan;
+
+// Wrap |ctxt| and |func| into an asan_block_context_t.
+// The caller retains control of the allocated context.
+extern "C"
+asan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func,
+ BufferedStackTrace *stack) {
+ asan_block_context_t *asan_ctxt =
+ (asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), stack);
+ asan_ctxt->block = ctxt;
+ asan_ctxt->func = func;
+ asan_ctxt->parent_tid = GetCurrentTidOrInvalid();
+ return asan_ctxt;
+}
+
+// Define interceptor for dispatch_*_f function with the three most common
+// parameters: dispatch_queue_t, context, dispatch_function_t.
+#define INTERCEPT_DISPATCH_X_F_3(dispatch_x_f) \
+ INTERCEPTOR(void, dispatch_x_f, dispatch_queue_t dq, void *ctxt, \
+ dispatch_function_t func) { \
+ GET_STACK_TRACE_THREAD; \
+ asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack); \
+ if (Verbosity() >= 2) { \
+ Report(#dispatch_x_f "(): context: %p, pthread_self: %p\n", \
+ asan_ctxt, pthread_self()); \
+ PRINT_CURRENT_STACK(); \
+ } \
+ return REAL(dispatch_x_f)(dq, (void*)asan_ctxt, \
+ asan_dispatch_call_block_and_release); \
+ }
+
+INTERCEPT_DISPATCH_X_F_3(dispatch_async_f)
+INTERCEPT_DISPATCH_X_F_3(dispatch_sync_f)
+INTERCEPT_DISPATCH_X_F_3(dispatch_barrier_async_f)
+
+INTERCEPTOR(void, dispatch_after_f, dispatch_time_t when,
+ dispatch_queue_t dq, void *ctxt,
+ dispatch_function_t func) {
+ GET_STACK_TRACE_THREAD;
+ asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack);
+ if (Verbosity() >= 2) {
+ Report("dispatch_after_f: %p\n", asan_ctxt);
+ PRINT_CURRENT_STACK();
+ }
+ return REAL(dispatch_after_f)(when, dq, (void*)asan_ctxt,
+ asan_dispatch_call_block_and_release);
+}
+
+INTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group,
+ dispatch_queue_t dq, void *ctxt,
+ dispatch_function_t func) {
+ GET_STACK_TRACE_THREAD;
+ asan_block_context_t *asan_ctxt = alloc_asan_context(ctxt, func, &stack);
+ if (Verbosity() >= 2) {
+ Report("dispatch_group_async_f(): context: %p, pthread_self: %p\n",
+ asan_ctxt, pthread_self());
+ PRINT_CURRENT_STACK();
+ }
+ REAL(dispatch_group_async_f)(group, dq, (void*)asan_ctxt,
+ asan_dispatch_call_block_and_release);
+}
+
+#if !defined(MISSING_BLOCKS_SUPPORT)
+extern "C" {
+void dispatch_async(dispatch_queue_t dq, void(^work)(void));
+void dispatch_group_async(dispatch_group_t dg, dispatch_queue_t dq,
+ void(^work)(void));
+void dispatch_after(dispatch_time_t when, dispatch_queue_t queue,
+ void(^work)(void));
+void dispatch_source_set_cancel_handler(dispatch_source_t ds,
+ void(^work)(void));
+void dispatch_source_set_event_handler(dispatch_source_t ds, void(^work)(void));
+}
+
+#define GET_ASAN_BLOCK(work) \
+ void (^asan_block)(void); \
+ int parent_tid = GetCurrentTidOrInvalid(); \
+ asan_block = ^(void) { \
+ GET_STACK_TRACE_THREAD; \
+ asan_register_worker_thread(parent_tid, &stack); \
+ work(); \
+ }
+
+INTERCEPTOR(void, dispatch_async,
+ dispatch_queue_t dq, void(^work)(void)) {
+ ENABLE_FRAME_POINTER;
+ GET_ASAN_BLOCK(work);
+ REAL(dispatch_async)(dq, asan_block);
+}
+
+INTERCEPTOR(void, dispatch_group_async,
+ dispatch_group_t dg, dispatch_queue_t dq, void(^work)(void)) {
+ ENABLE_FRAME_POINTER;
+ GET_ASAN_BLOCK(work);
+ REAL(dispatch_group_async)(dg, dq, asan_block);
+}
+
+INTERCEPTOR(void, dispatch_after,
+ dispatch_time_t when, dispatch_queue_t queue, void(^work)(void)) {
+ ENABLE_FRAME_POINTER;
+ GET_ASAN_BLOCK(work);
+ REAL(dispatch_after)(when, queue, asan_block);
+}
+
+INTERCEPTOR(void, dispatch_source_set_cancel_handler,
+ dispatch_source_t ds, void(^work)(void)) {
+ if (!work) {
+ REAL(dispatch_source_set_cancel_handler)(ds, work);
+ return;
+ }
+ ENABLE_FRAME_POINTER;
+ GET_ASAN_BLOCK(work);
+ REAL(dispatch_source_set_cancel_handler)(ds, asan_block);
+}
+
+INTERCEPTOR(void, dispatch_source_set_event_handler,
+ dispatch_source_t ds, void(^work)(void)) {
+ ENABLE_FRAME_POINTER;
+ GET_ASAN_BLOCK(work);
+ REAL(dispatch_source_set_event_handler)(ds, asan_block);
+}
+#endif
+
+#endif // SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_malloc_linux.cpp b/contrib/libs/clang16-rt/lib/asan/asan_malloc_linux.cpp
new file mode 100644
index 00000000000..bab80b96f58
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_malloc_linux.cpp
@@ -0,0 +1,226 @@
+//===-- asan_malloc_linux.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Linux-specific malloc interception.
+// We simply define functions like malloc, free, realloc, etc.
+// They will replace the corresponding libc functions automagically.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX || \
+ SANITIZER_NETBSD || SANITIZER_SOLARIS
+
+# include "asan_allocator.h"
+# include "asan_interceptors.h"
+# include "asan_internal.h"
+# include "asan_stack.h"
+# include "lsan/lsan_common.h"
+# include "sanitizer_common/sanitizer_allocator_checks.h"
+# include "sanitizer_common/sanitizer_allocator_dlsym.h"
+# include "sanitizer_common/sanitizer_errno.h"
+# include "sanitizer_common/sanitizer_tls_get_addr.h"
+
+// ---------------------- Replacement functions ---------------- {{{1
+using namespace __asan;
+
+struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
+ static bool UseImpl() { return asan_init_is_running; }
+ static void OnAllocate(const void *ptr, uptr size) {
+# if CAN_SANITIZE_LEAKS
+ // Suppress leaks from dlerror(). Previously dlsym hack on global array was
+ // used by leak sanitizer as a root region.
+ __lsan_register_root_region(ptr, size);
+# endif
+ }
+ static void OnFree(const void *ptr, uptr size) {
+# if CAN_SANITIZE_LEAKS
+ __lsan_unregister_root_region(ptr, size);
+# endif
+ }
+};
+
+INTERCEPTOR(void, free, void *ptr) {
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+ GET_STACK_TRACE_FREE;
+ asan_free(ptr, &stack, FROM_MALLOC);
+}
+
+#if SANITIZER_INTERCEPT_CFREE
+INTERCEPTOR(void, cfree, void *ptr) {
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+ GET_STACK_TRACE_FREE;
+ asan_free(ptr, &stack, FROM_MALLOC);
+}
+#endif // SANITIZER_INTERCEPT_CFREE
+
+INTERCEPTOR(void*, malloc, uptr size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Allocate(size);
+ ENSURE_ASAN_INITED();
+ GET_STACK_TRACE_MALLOC;
+ return asan_malloc(size, &stack);
+}
+
+INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Callocate(nmemb, size);
+ ENSURE_ASAN_INITED();
+ GET_STACK_TRACE_MALLOC;
+ return asan_calloc(nmemb, size, &stack);
+}
+
+INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
+ if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Realloc(ptr, size);
+ ENSURE_ASAN_INITED();
+ GET_STACK_TRACE_MALLOC;
+ return asan_realloc(ptr, size, &stack);
+}
+
+#if SANITIZER_INTERCEPT_REALLOCARRAY
+INTERCEPTOR(void*, reallocarray, void *ptr, uptr nmemb, uptr size) {
+ ENSURE_ASAN_INITED();
+ GET_STACK_TRACE_MALLOC;
+ return asan_reallocarray(ptr, nmemb, size, &stack);
+}
+#endif // SANITIZER_INTERCEPT_REALLOCARRAY
+
+#if SANITIZER_INTERCEPT_MEMALIGN
+INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_memalign(boundary, size, &stack, FROM_MALLOC);
+}
+
+INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC);
+ DTLS_on_libc_memalign(res, size);
+ return res;
+}
+#endif // SANITIZER_INTERCEPT_MEMALIGN
+
+#if SANITIZER_INTERCEPT_ALIGNED_ALLOC
+INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_aligned_alloc(boundary, size, &stack);
+}
+#endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC
+
+INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
+ GET_CURRENT_PC_BP_SP;
+ (void)sp;
+ return asan_malloc_usable_size(ptr, pc, bp);
+}
+
+#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
+// We avoid including malloc.h for portability reasons.
+// man mallinfo says the fields are "long", but the implementation uses int.
+// It doesn't matter much -- we just need to make sure that the libc's mallinfo
+// is not called.
+struct fake_mallinfo {
+ int x[10];
+};
+
+INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
+ struct fake_mallinfo res;
+ REAL(memset)(&res, 0, sizeof(res));
+ return res;
+}
+
+INTERCEPTOR(int, mallopt, int cmd, int value) {
+ return 0;
+}
+#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
+
+INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_posix_memalign(memptr, alignment, size, &stack);
+}
+
+INTERCEPTOR(void*, valloc, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_valloc(size, &stack);
+}
+
+#if SANITIZER_INTERCEPT_PVALLOC
+INTERCEPTOR(void*, pvalloc, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_pvalloc(size, &stack);
+}
+#endif // SANITIZER_INTERCEPT_PVALLOC
+
+INTERCEPTOR(void, malloc_stats, void) {
+ __asan_print_accumulated_stats();
+}
+
+#if SANITIZER_ANDROID
+// Format of __libc_malloc_dispatch has changed in Android L.
+// While we are moving towards a solution that does not depend on bionic
+// internals, here is something to support both K* and L releases.
+struct MallocDebugK {
+ void *(*malloc)(uptr bytes);
+ void (*free)(void *mem);
+ void *(*calloc)(uptr n_elements, uptr elem_size);
+ void *(*realloc)(void *oldMem, uptr bytes);
+ void *(*memalign)(uptr alignment, uptr bytes);
+ uptr (*malloc_usable_size)(void *mem);
+};
+
+struct MallocDebugL {
+ void *(*calloc)(uptr n_elements, uptr elem_size);
+ void (*free)(void *mem);
+ fake_mallinfo (*mallinfo)(void);
+ void *(*malloc)(uptr bytes);
+ uptr (*malloc_usable_size)(void *mem);
+ void *(*memalign)(uptr alignment, uptr bytes);
+ int (*posix_memalign)(void **memptr, uptr alignment, uptr size);
+ void* (*pvalloc)(uptr size);
+ void *(*realloc)(void *oldMem, uptr bytes);
+ void* (*valloc)(uptr size);
+};
+
+ALIGNED(32) const MallocDebugK asan_malloc_dispatch_k = {
+ WRAP(malloc), WRAP(free), WRAP(calloc),
+ WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)};
+
+ALIGNED(32) const MallocDebugL asan_malloc_dispatch_l = {
+ WRAP(calloc), WRAP(free), WRAP(mallinfo),
+ WRAP(malloc), WRAP(malloc_usable_size), WRAP(memalign),
+ WRAP(posix_memalign), WRAP(pvalloc), WRAP(realloc),
+ WRAP(valloc)};
+
+namespace __asan {
+void ReplaceSystemMalloc() {
+ void **__libc_malloc_dispatch_p =
+ (void **)AsanDlSymNext("__libc_malloc_dispatch");
+ if (__libc_malloc_dispatch_p) {
+ // Decide on K vs L dispatch format by the presence of
+ // __libc_malloc_default_dispatch export in libc.
+ void *default_dispatch_p = AsanDlSymNext("__libc_malloc_default_dispatch");
+ if (default_dispatch_p)
+ *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_k;
+ else
+ *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_l;
+ }
+}
+} // namespace __asan
+
+#else // SANITIZER_ANDROID
+
+namespace __asan {
+void ReplaceSystemMalloc() {
+}
+} // namespace __asan
+#endif // SANITIZER_ANDROID
+
+#endif // SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX ||
+ // SANITIZER_NETBSD || SANITIZER_SOLARIS
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_malloc_mac.cpp b/contrib/libs/clang16-rt/lib/asan/asan_malloc_mac.cpp
new file mode 100644
index 00000000000..924d1f12640
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_malloc_mac.cpp
@@ -0,0 +1,102 @@
+//===-- asan_malloc_mac.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Mac-specific malloc interception.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_APPLE
+
+#include "asan_interceptors.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "asan_stats.h"
+#include "lsan/lsan_common.h"
+
+using namespace __asan;
+#define COMMON_MALLOC_ZONE_NAME "asan"
+#define COMMON_MALLOC_ENTER() ENSURE_ASAN_INITED()
+#define COMMON_MALLOC_SANITIZER_INITIALIZED asan_inited
+#define COMMON_MALLOC_FORCE_LOCK() asan_mz_force_lock()
+#define COMMON_MALLOC_FORCE_UNLOCK() asan_mz_force_unlock()
+#define COMMON_MALLOC_MEMALIGN(alignment, size) \
+ GET_STACK_TRACE_MALLOC; \
+ void *p = asan_memalign(alignment, size, &stack, FROM_MALLOC)
+#define COMMON_MALLOC_MALLOC(size) \
+ GET_STACK_TRACE_MALLOC; \
+ void *p = asan_malloc(size, &stack)
+#define COMMON_MALLOC_REALLOC(ptr, size) \
+ GET_STACK_TRACE_MALLOC; \
+ void *p = asan_realloc(ptr, size, &stack);
+#define COMMON_MALLOC_CALLOC(count, size) \
+ GET_STACK_TRACE_MALLOC; \
+ void *p = asan_calloc(count, size, &stack);
+#define COMMON_MALLOC_POSIX_MEMALIGN(memptr, alignment, size) \
+ GET_STACK_TRACE_MALLOC; \
+ int res = asan_posix_memalign(memptr, alignment, size, &stack);
+#define COMMON_MALLOC_VALLOC(size) \
+ GET_STACK_TRACE_MALLOC; \
+ void *p = asan_memalign(GetPageSizeCached(), size, &stack, FROM_MALLOC);
+#define COMMON_MALLOC_FREE(ptr) \
+ GET_STACK_TRACE_FREE; \
+ asan_free(ptr, &stack, FROM_MALLOC);
+#define COMMON_MALLOC_SIZE(ptr) \
+ uptr size = asan_mz_size(ptr);
+#define COMMON_MALLOC_FILL_STATS(zone, stats) \
+ AsanMallocStats malloc_stats; \
+ FillMallocStatistics(&malloc_stats); \
+ CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats)); \
+ internal_memcpy(stats, &malloc_stats, sizeof(malloc_statistics_t));
+#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \
+ GET_STACK_TRACE_FREE; \
+ ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack);
+#define COMMON_MALLOC_NAMESPACE __asan
+#define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0
+#define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 1
+
+#include "sanitizer_common/sanitizer_malloc_mac.inc"
+
+namespace COMMON_MALLOC_NAMESPACE {
+
+bool HandleDlopenInit() {
+ static_assert(SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
+ "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be true");
+ // We have no reliable way of knowing how we are being loaded
+ // so make it a requirement on Apple platforms to set this environment
+ // variable to indicate that we want to perform initialization via
+ // dlopen().
+ auto init_str = GetEnv("APPLE_ASAN_INIT_FOR_DLOPEN");
+ if (!init_str)
+ return false;
+ if (internal_strncmp(init_str, "1", 1) != 0)
+ return false;
+ // When we are loaded via `dlopen()` path we still initialize the malloc zone
+ // so Symbolication clients (e.g. `leaks`) that load the ASan allocator can
+ // find an initialized malloc zone.
+ InitMallocZoneFields();
+ return true;
+}
+} // namespace COMMON_MALLOC_NAMESPACE
+
+namespace {
+
+void mi_extra_init(sanitizer_malloc_introspection_t *mi) {
+ uptr last_byte_plus_one = 0;
+ mi->allocator_ptr = 0;
+ // Range is [begin_ptr, end_ptr)
+ __lsan::GetAllocatorGlobalRange(&(mi->allocator_ptr), &last_byte_plus_one);
+ CHECK_NE(mi->allocator_ptr, 0);
+ CHECK_GT(last_byte_plus_one, mi->allocator_ptr);
+ mi->allocator_size = last_byte_plus_one - (mi->allocator_ptr);
+ CHECK_GT(mi->allocator_size, 0);
+}
+} // namespace
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_malloc_win.cpp b/contrib/libs/clang16-rt/lib/asan/asan_malloc_win.cpp
new file mode 100644
index 00000000000..4b76d4ebd3e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_malloc_win.cpp
@@ -0,0 +1,551 @@
+//===-- asan_malloc_win.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific malloc interception.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_WINDOWS
+#include "asan_allocator.h"
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_stack.h"
+#include "interception/interception.h"
+#include <stddef.h>
+
+// Intentionally not including windows.h here, to avoid the risk of
+// pulling in conflicting declarations of these functions. (With mingw-w64,
+// there's a risk of windows.h pulling in stdint.h.)
+typedef int BOOL;
+typedef void *HANDLE;
+typedef const void *LPCVOID;
+typedef void *LPVOID;
+
+typedef unsigned long DWORD;
+constexpr unsigned long HEAP_ZERO_MEMORY = 0x00000008;
+constexpr unsigned long HEAP_REALLOC_IN_PLACE_ONLY = 0x00000010;
+constexpr unsigned long HEAP_ALLOCATE_SUPPORTED_FLAGS = (HEAP_ZERO_MEMORY);
+constexpr unsigned long HEAP_ALLOCATE_UNSUPPORTED_FLAGS =
+ (~HEAP_ALLOCATE_SUPPORTED_FLAGS);
+constexpr unsigned long HEAP_FREE_UNSUPPORTED_FLAGS =
+ (~HEAP_ALLOCATE_SUPPORTED_FLAGS);
+constexpr unsigned long HEAP_REALLOC_UNSUPPORTED_FLAGS =
+ (~HEAP_ALLOCATE_SUPPORTED_FLAGS);
+
+
+extern "C" {
+LPVOID WINAPI HeapAlloc(HANDLE hHeap, DWORD dwFlags, size_t dwBytes);
+LPVOID WINAPI HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem,
+ size_t dwBytes);
+BOOL WINAPI HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
+size_t WINAPI HeapSize(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem);
+
+BOOL WINAPI HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem);
+}
+
+using namespace __asan;
+
+// MT: Simply defining functions with the same signature in *.obj
+// files overrides the standard functions in the CRT.
+// MD: Memory allocation functions are defined in the CRT .dll,
+// so we have to intercept them before they are called for the first time.
+
+#if ASAN_DYNAMIC
+# define ALLOCATION_FUNCTION_ATTRIBUTE
+#else
+# define ALLOCATION_FUNCTION_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
+#endif
+
+extern "C" {
+ALLOCATION_FUNCTION_ATTRIBUTE
+size_t _msize(void *ptr) {
+ GET_CURRENT_PC_BP_SP;
+ (void)sp;
+ return asan_malloc_usable_size(ptr, pc, bp);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+size_t _msize_base(void *ptr) {
+ return _msize(ptr);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void free(void *ptr) {
+ GET_STACK_TRACE_FREE;
+ return asan_free(ptr, &stack, FROM_MALLOC);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void _free_dbg(void *ptr, int) {
+ free(ptr);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void _free_base(void *ptr) {
+ free(ptr);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *malloc(size_t size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_malloc(size, &stack);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *_malloc_base(size_t size) {
+ return malloc(size);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *_malloc_dbg(size_t size, int, const char *, int) {
+ return malloc(size);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *calloc(size_t nmemb, size_t size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_calloc(nmemb, size, &stack);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *_calloc_base(size_t nmemb, size_t size) {
+ return calloc(nmemb, size);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *_calloc_dbg(size_t nmemb, size_t size, int, const char *, int) {
+ return calloc(nmemb, size);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *_calloc_impl(size_t nmemb, size_t size, int *errno_tmp) {
+ return calloc(nmemb, size);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *realloc(void *ptr, size_t size) {
+ GET_STACK_TRACE_MALLOC;
+ return asan_realloc(ptr, size, &stack);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *_realloc_dbg(void *ptr, size_t size, int) {
+ UNREACHABLE("_realloc_dbg should not exist!");
+ return 0;
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *_realloc_base(void *ptr, size_t size) {
+ return realloc(ptr, size);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *_recalloc(void *p, size_t n, size_t elem_size) {
+ if (!p)
+ return calloc(n, elem_size);
+ const size_t size = n * elem_size;
+ if (elem_size != 0 && size / elem_size != n)
+ return 0;
+
+ size_t old_size = _msize(p);
+ void *new_alloc = malloc(size);
+ if (new_alloc) {
+ REAL(memcpy)(new_alloc, p, Min<size_t>(size, old_size));
+ if (old_size < size)
+ REAL(memset)(((u8 *)new_alloc) + old_size, 0, size - old_size);
+ free(p);
+ }
+ return new_alloc;
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *_recalloc_base(void *p, size_t n, size_t elem_size) {
+ return _recalloc(p, n, elem_size);
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *_expand(void *memblock, size_t size) {
+ // _expand is used in realloc-like functions to resize the buffer if possible.
+ // We don't want memory to stand still while resizing buffers, so return 0.
+ return 0;
+}
+
+ALLOCATION_FUNCTION_ATTRIBUTE
+void *_expand_dbg(void *memblock, size_t size) {
+ return _expand(memblock, size);
+}
+
+// TODO(timurrrr): Might want to add support for _aligned_* allocation
+// functions to detect a bit more bugs. Those functions seem to wrap malloc().
+
+int _CrtDbgReport(int, const char*, int,
+ const char*, const char*, ...) {
+ ShowStatsAndAbort();
+}
+
+int _CrtDbgReportW(int reportType, const wchar_t*, int,
+ const wchar_t*, const wchar_t*, ...) {
+ ShowStatsAndAbort();
+}
+
+int _CrtSetReportMode(int, int) {
+ return 0;
+}
+} // extern "C"
+
+#define OWNED_BY_RTL(heap, memory) \
+ (!__sanitizer_get_ownership(memory) && HeapValidate(heap, 0, memory))
+
+INTERCEPTOR_WINAPI(size_t, HeapSize, HANDLE hHeap, DWORD dwFlags,
+ LPCVOID lpMem) {
+ // If the RTL allocators are hooked we need to check whether the ASAN
+ // allocator owns the pointer we're about to use. Allocations occur before
+ // interception takes place, so if it is not owned by the RTL heap we can
+ // pass it to the ASAN heap for inspection.
+ if (flags()->windows_hook_rtl_allocators) {
+ if (!asan_inited || OWNED_BY_RTL(hHeap, lpMem))
+ return REAL(HeapSize)(hHeap, dwFlags, lpMem);
+ } else {
+ CHECK(dwFlags == 0 && "unsupported heap flags");
+ }
+ GET_CURRENT_PC_BP_SP;
+ (void)sp;
+ return asan_malloc_usable_size(lpMem, pc, bp);
+}
+
+INTERCEPTOR_WINAPI(LPVOID, HeapAlloc, HANDLE hHeap, DWORD dwFlags,
+ size_t dwBytes) {
+ // If the ASAN runtime is not initialized, or we encounter an unsupported
+ // flag, fall back to the original allocator.
+ if (flags()->windows_hook_rtl_allocators) {
+ if (UNLIKELY(!asan_inited ||
+ (dwFlags & HEAP_ALLOCATE_UNSUPPORTED_FLAGS) != 0)) {
+ return REAL(HeapAlloc)(hHeap, dwFlags, dwBytes);
+ }
+ } else {
+ // In the case that we don't hook the rtl allocators,
+ // this becomes an assert since there is no failover to the original
+ // allocator.
+ CHECK((HEAP_ALLOCATE_UNSUPPORTED_FLAGS & dwFlags) != 0 &&
+ "unsupported flags");
+ }
+ GET_STACK_TRACE_MALLOC;
+ void *p = asan_malloc(dwBytes, &stack);
+ // Reading MSDN suggests that the *entire* usable allocation is zeroed out.
+ // Otherwise it is difficult to HeapReAlloc with HEAP_ZERO_MEMORY.
+ // https://blogs.msdn.microsoft.com/oldnewthing/20120316-00/?p=8083
+ if (p && (dwFlags & HEAP_ZERO_MEMORY)) {
+ GET_CURRENT_PC_BP_SP;
+ (void)sp;
+ auto usable_size = asan_malloc_usable_size(p, pc, bp);
+ internal_memset(p, 0, usable_size);
+ }
+ return p;
+}
+
+INTERCEPTOR_WINAPI(BOOL, HeapFree, HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) {
+ // Heap allocations happen before this function is hooked, so we must fall
+ // back to the original function if the pointer is not from the ASAN heap,
+ // or unsupported flags are provided.
+ if (flags()->windows_hook_rtl_allocators) {
+ if (OWNED_BY_RTL(hHeap, lpMem))
+ return REAL(HeapFree)(hHeap, dwFlags, lpMem);
+ } else {
+ CHECK((HEAP_FREE_UNSUPPORTED_FLAGS & dwFlags) != 0 && "unsupported flags");
+ }
+ GET_STACK_TRACE_FREE;
+ asan_free(lpMem, &stack, FROM_MALLOC);
+ return true;
+}
+
+namespace __asan {
+using AllocFunction = LPVOID(WINAPI *)(HANDLE, DWORD, size_t);
+using ReAllocFunction = LPVOID(WINAPI *)(HANDLE, DWORD, LPVOID, size_t);
+using SizeFunction = size_t(WINAPI *)(HANDLE, DWORD, LPVOID);
+using FreeFunction = BOOL(WINAPI *)(HANDLE, DWORD, LPVOID);
+
+void *SharedReAlloc(ReAllocFunction reallocFunc, SizeFunction heapSizeFunc,
+ FreeFunction freeFunc, AllocFunction allocFunc,
+ HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, size_t dwBytes) {
+ CHECK(reallocFunc && heapSizeFunc && freeFunc && allocFunc);
+ GET_STACK_TRACE_MALLOC;
+ GET_CURRENT_PC_BP_SP;
+ (void)sp;
+ if (flags()->windows_hook_rtl_allocators) {
+ enum AllocationOwnership { NEITHER = 0, ASAN = 1, RTL = 2 };
+ AllocationOwnership ownershipState;
+ bool owned_rtlalloc = false;
+ bool owned_asan = __sanitizer_get_ownership(lpMem);
+
+ if (!owned_asan)
+ owned_rtlalloc = HeapValidate(hHeap, 0, lpMem);
+
+ if (owned_asan && !owned_rtlalloc)
+ ownershipState = ASAN;
+ else if (!owned_asan && owned_rtlalloc)
+ ownershipState = RTL;
+ else if (!owned_asan && !owned_rtlalloc)
+ ownershipState = NEITHER;
+
+ // If this heap block which was allocated before the ASAN
+ // runtime came up, use the real HeapFree function.
+ if (UNLIKELY(!asan_inited)) {
+ return reallocFunc(hHeap, dwFlags, lpMem, dwBytes);
+ }
+ bool only_asan_supported_flags =
+ (HEAP_REALLOC_UNSUPPORTED_FLAGS & dwFlags) == 0;
+
+ if (ownershipState == RTL ||
+ (ownershipState == NEITHER && !only_asan_supported_flags)) {
+ if (only_asan_supported_flags) {
+ // if this is a conversion to ASAN upported flags, transfer this
+ // allocation to the ASAN allocator
+ void *replacement_alloc;
+ if (dwFlags & HEAP_ZERO_MEMORY)
+ replacement_alloc = asan_calloc(1, dwBytes, &stack);
+ else
+ replacement_alloc = asan_malloc(dwBytes, &stack);
+ if (replacement_alloc) {
+ size_t old_size = heapSizeFunc(hHeap, dwFlags, lpMem);
+ if (old_size == ((size_t)0) - 1) {
+ asan_free(replacement_alloc, &stack, FROM_MALLOC);
+ return nullptr;
+ }
+ REAL(memcpy)(replacement_alloc, lpMem, old_size);
+ freeFunc(hHeap, dwFlags, lpMem);
+ }
+ return replacement_alloc;
+ } else {
+ // owned by rtl or neither with unsupported ASAN flags,
+ // just pass back to original allocator
+ CHECK(ownershipState == RTL || ownershipState == NEITHER);
+ CHECK(!only_asan_supported_flags);
+ return reallocFunc(hHeap, dwFlags, lpMem, dwBytes);
+ }
+ }
+
+ if (ownershipState == ASAN && !only_asan_supported_flags) {
+ // Conversion to unsupported flags allocation,
+ // transfer this allocation back to the original allocator.
+ void *replacement_alloc = allocFunc(hHeap, dwFlags, dwBytes);
+ size_t old_usable_size = 0;
+ if (replacement_alloc) {
+ old_usable_size = asan_malloc_usable_size(lpMem, pc, bp);
+ REAL(memcpy)(replacement_alloc, lpMem,
+ Min<size_t>(dwBytes, old_usable_size));
+ asan_free(lpMem, &stack, FROM_MALLOC);
+ }
+ return replacement_alloc;
+ }
+
+ CHECK((ownershipState == ASAN || ownershipState == NEITHER) &&
+ only_asan_supported_flags);
+ // At this point we should either be ASAN owned with ASAN supported flags
+ // or we owned by neither and have supported flags.
+ // Pass through even when it's neither since this could be a null realloc or
+ // UAF that ASAN needs to catch.
+ } else {
+ CHECK((HEAP_REALLOC_UNSUPPORTED_FLAGS & dwFlags) != 0 &&
+ "unsupported flags");
+ }
+ // asan_realloc will never reallocate in place, so for now this flag is
+ // unsupported until we figure out a way to fake this.
+ if (dwFlags & HEAP_REALLOC_IN_PLACE_ONLY)
+ return nullptr;
+
+ // HeapReAlloc and HeapAlloc both happily accept 0 sized allocations.
+ // passing a 0 size into asan_realloc will free the allocation.
+ // To avoid this and keep behavior consistent, fudge the size if 0.
+ // (asan_malloc already does this)
+ if (dwBytes == 0)
+ dwBytes = 1;
+
+ size_t old_size;
+ if (dwFlags & HEAP_ZERO_MEMORY)
+ old_size = asan_malloc_usable_size(lpMem, pc, bp);
+
+ void *ptr = asan_realloc(lpMem, dwBytes, &stack);
+ if (ptr == nullptr)
+ return nullptr;
+
+ if (dwFlags & HEAP_ZERO_MEMORY) {
+ size_t new_size = asan_malloc_usable_size(ptr, pc, bp);
+ if (old_size < new_size)
+ REAL(memset)(((u8 *)ptr) + old_size, 0, new_size - old_size);
+ }
+
+ return ptr;
+}
+} // namespace __asan
+
+INTERCEPTOR_WINAPI(LPVOID, HeapReAlloc, HANDLE hHeap, DWORD dwFlags,
+ LPVOID lpMem, size_t dwBytes) {
+ return SharedReAlloc(REAL(HeapReAlloc), (SizeFunction)REAL(HeapSize),
+ REAL(HeapFree), REAL(HeapAlloc), hHeap, dwFlags, lpMem,
+ dwBytes);
+}
+
+// The following functions are undocumented and subject to change.
+// However, hooking them is necessary to hook Windows heap
+// allocations with detours and their definitions are unlikely to change.
+// Comments in /minkernel/ntos/rtl/heappublic.c indicate that these functions
+// are part of the heap's public interface.
+typedef unsigned long LOGICAL;
+
+// This function is documented as part of the Driver Development Kit but *not*
+// the Windows Development Kit.
+LOGICAL RtlFreeHeap(void* HeapHandle, DWORD Flags,
+ void* BaseAddress);
+
+// This function is documented as part of the Driver Development Kit but *not*
+// the Windows Development Kit.
+void* RtlAllocateHeap(void* HeapHandle, DWORD Flags, size_t Size);
+
+// This function is completely undocumented.
+void*
+RtlReAllocateHeap(void* HeapHandle, DWORD Flags, void* BaseAddress,
+ size_t Size);
+
+// This function is completely undocumented.
+size_t RtlSizeHeap(void* HeapHandle, DWORD Flags, void* BaseAddress);
+
+INTERCEPTOR_WINAPI(size_t, RtlSizeHeap, HANDLE HeapHandle, DWORD Flags,
+ void* BaseAddress) {
+ if (!flags()->windows_hook_rtl_allocators ||
+ UNLIKELY(!asan_inited || OWNED_BY_RTL(HeapHandle, BaseAddress))) {
+ return REAL(RtlSizeHeap)(HeapHandle, Flags, BaseAddress);
+ }
+ GET_CURRENT_PC_BP_SP;
+ (void)sp;
+ return asan_malloc_usable_size(BaseAddress, pc, bp);
+}
+
+INTERCEPTOR_WINAPI(BOOL, RtlFreeHeap, HANDLE HeapHandle, DWORD Flags,
+ void* BaseAddress) {
+ // Heap allocations happen before this function is hooked, so we must fall
+ // back to the original function if the pointer is not from the ASAN heap, or
+ // unsupported flags are provided.
+ if (!flags()->windows_hook_rtl_allocators ||
+ UNLIKELY((HEAP_FREE_UNSUPPORTED_FLAGS & Flags) != 0 ||
+ OWNED_BY_RTL(HeapHandle, BaseAddress))) {
+ return REAL(RtlFreeHeap)(HeapHandle, Flags, BaseAddress);
+ }
+ GET_STACK_TRACE_FREE;
+ asan_free(BaseAddress, &stack, FROM_MALLOC);
+ return true;
+}
+
+INTERCEPTOR_WINAPI(void*, RtlAllocateHeap, HANDLE HeapHandle, DWORD Flags,
+ size_t Size) {
+ // If the ASAN runtime is not initialized, or we encounter an unsupported
+ // flag, fall back to the original allocator.
+ if (!flags()->windows_hook_rtl_allocators ||
+ UNLIKELY(!asan_inited ||
+ (Flags & HEAP_ALLOCATE_UNSUPPORTED_FLAGS) != 0)) {
+ return REAL(RtlAllocateHeap)(HeapHandle, Flags, Size);
+ }
+ GET_STACK_TRACE_MALLOC;
+ void *p;
+ // Reading MSDN suggests that the *entire* usable allocation is zeroed out.
+ // Otherwise it is difficult to HeapReAlloc with HEAP_ZERO_MEMORY.
+ // https://blogs.msdn.microsoft.com/oldnewthing/20120316-00/?p=8083
+ if (Flags & HEAP_ZERO_MEMORY) {
+ p = asan_calloc(Size, 1, &stack);
+ } else {
+ p = asan_malloc(Size, &stack);
+ }
+ return p;
+}
+
+INTERCEPTOR_WINAPI(void*, RtlReAllocateHeap, HANDLE HeapHandle, DWORD Flags,
+ void* BaseAddress, size_t Size) {
+ // If it's actually a heap block which was allocated before the ASAN runtime
+ // came up, use the real RtlFreeHeap function.
+ if (!flags()->windows_hook_rtl_allocators)
+ return REAL(RtlReAllocateHeap)(HeapHandle, Flags, BaseAddress, Size);
+
+ return SharedReAlloc(REAL(RtlReAllocateHeap), REAL(RtlSizeHeap),
+ REAL(RtlFreeHeap), REAL(RtlAllocateHeap), HeapHandle,
+ Flags, BaseAddress, Size);
+}
+
+namespace __asan {
+
+static void TryToOverrideFunction(const char *fname, uptr new_func) {
+ // Failure here is not fatal. The CRT may not be present, and different CRT
+ // versions use different symbols.
+ if (!__interception::OverrideFunction(fname, new_func))
+ VPrintf(2, "Failed to override function %s\n", fname);
+}
+
+void ReplaceSystemMalloc() {
+#if defined(ASAN_DYNAMIC)
+ TryToOverrideFunction("free", (uptr)free);
+ TryToOverrideFunction("_free_base", (uptr)free);
+ TryToOverrideFunction("malloc", (uptr)malloc);
+ TryToOverrideFunction("_malloc_base", (uptr)malloc);
+ TryToOverrideFunction("_malloc_crt", (uptr)malloc);
+ TryToOverrideFunction("calloc", (uptr)calloc);
+ TryToOverrideFunction("_calloc_base", (uptr)calloc);
+ TryToOverrideFunction("_calloc_crt", (uptr)calloc);
+ TryToOverrideFunction("realloc", (uptr)realloc);
+ TryToOverrideFunction("_realloc_base", (uptr)realloc);
+ TryToOverrideFunction("_realloc_crt", (uptr)realloc);
+ TryToOverrideFunction("_recalloc", (uptr)_recalloc);
+ TryToOverrideFunction("_recalloc_base", (uptr)_recalloc);
+ TryToOverrideFunction("_recalloc_crt", (uptr)_recalloc);
+ TryToOverrideFunction("_msize", (uptr)_msize);
+ TryToOverrideFunction("_msize_base", (uptr)_msize);
+ TryToOverrideFunction("_expand", (uptr)_expand);
+ TryToOverrideFunction("_expand_base", (uptr)_expand);
+
+ if (flags()->windows_hook_rtl_allocators) {
+ INTERCEPT_FUNCTION(HeapSize);
+ INTERCEPT_FUNCTION(HeapFree);
+ INTERCEPT_FUNCTION(HeapReAlloc);
+ INTERCEPT_FUNCTION(HeapAlloc);
+
+ // Undocumented functions must be intercepted by name, not by symbol.
+ __interception::OverrideFunction("RtlSizeHeap", (uptr)WRAP(RtlSizeHeap),
+ (uptr *)&REAL(RtlSizeHeap));
+ __interception::OverrideFunction("RtlFreeHeap", (uptr)WRAP(RtlFreeHeap),
+ (uptr *)&REAL(RtlFreeHeap));
+ __interception::OverrideFunction("RtlReAllocateHeap",
+ (uptr)WRAP(RtlReAllocateHeap),
+ (uptr *)&REAL(RtlReAllocateHeap));
+ __interception::OverrideFunction("RtlAllocateHeap",
+ (uptr)WRAP(RtlAllocateHeap),
+ (uptr *)&REAL(RtlAllocateHeap));
+ } else {
+#define INTERCEPT_UCRT_FUNCTION(func) \
+ if (!INTERCEPT_FUNCTION_DLLIMPORT( \
+ "ucrtbase.dll", "api-ms-win-core-heap-l1-1-0.dll", func)) { \
+ VPrintf(2, "Failed to intercept ucrtbase.dll import %s\n", #func); \
+ }
+ INTERCEPT_UCRT_FUNCTION(HeapAlloc);
+ INTERCEPT_UCRT_FUNCTION(HeapFree);
+ INTERCEPT_UCRT_FUNCTION(HeapReAlloc);
+ INTERCEPT_UCRT_FUNCTION(HeapSize);
+#undef INTERCEPT_UCRT_FUNCTION
+ }
+ // Recent versions of ucrtbase.dll appear to be built with PGO and LTCG, which
+ // enable cross-module inlining. This means our _malloc_base hook won't catch
+ // all CRT allocations. This code here patches the import table of
+ // ucrtbase.dll so that all attempts to use the lower-level win32 heap
+ // allocation API will be directed to ASan's heap. We don't currently
+ // intercept all calls to HeapAlloc. If we did, we would have to check on
+ // HeapFree whether the pointer came from ASan of from the system.
+
+#endif // defined(ASAN_DYNAMIC)
+}
+} // namespace __asan
+
+#endif // _WIN32
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_mapping.h b/contrib/libs/clang16-rt/lib/asan/asan_mapping.h
new file mode 100644
index 00000000000..c5f95c07a21
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_mapping.h
@@ -0,0 +1,412 @@
+//===-- asan_mapping.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Defines ASan memory mapping.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_MAPPING_H
+#define ASAN_MAPPING_H
+
+#include "sanitizer_common/sanitizer_platform.h"
+
+// The full explanation of the memory mapping could be found here:
+// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm
+//
+// Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000:
+// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem ||
+// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow ||
+// || `[0x00008fff7000, 0x02008fff6fff]` || ShadowGap ||
+// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow ||
+// || `[0x000000000000, 0x00007fff7fff]` || LowMem ||
+//
+// When SHADOW_OFFSET is zero (-pie):
+// || `[0x100000000000, 0x7fffffffffff]` || HighMem ||
+// || `[0x020000000000, 0x0fffffffffff]` || HighShadow ||
+// || `[0x000000040000, 0x01ffffffffff]` || ShadowGap ||
+//
+// Special case when something is already mapped between
+// 0x003000000000 and 0x005000000000 (e.g. when prelink is installed):
+// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem ||
+// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow ||
+// || `[0x005000000000, 0x02008fff6fff]` || ShadowGap3 ||
+// || `[0x003000000000, 0x004fffffffff]` || MidMem ||
+// || `[0x000a7fff8000, 0x002fffffffff]` || ShadowGap2 ||
+// || `[0x00067fff8000, 0x000a7fff7fff]` || MidShadow ||
+// || `[0x00008fff7000, 0x00067fff7fff]` || ShadowGap ||
+// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow ||
+// || `[0x000000000000, 0x00007fff7fff]` || LowMem ||
+//
+// Default Linux/i386 mapping on x86_64 machine:
+// || `[0x40000000, 0xffffffff]` || HighMem ||
+// || `[0x28000000, 0x3fffffff]` || HighShadow ||
+// || `[0x24000000, 0x27ffffff]` || ShadowGap ||
+// || `[0x20000000, 0x23ffffff]` || LowShadow ||
+// || `[0x00000000, 0x1fffffff]` || LowMem ||
+//
+// Default Linux/i386 mapping on i386 machine
+// (addresses starting with 0xc0000000 are reserved
+// for kernel and thus not sanitized):
+// || `[0x38000000, 0xbfffffff]` || HighMem ||
+// || `[0x27000000, 0x37ffffff]` || HighShadow ||
+// || `[0x24000000, 0x26ffffff]` || ShadowGap ||
+// || `[0x20000000, 0x23ffffff]` || LowShadow ||
+// || `[0x00000000, 0x1fffffff]` || LowMem ||
+//
+// Default Linux/MIPS32 mapping:
+// || `[0x2aaa0000, 0xffffffff]` || HighMem ||
+// || `[0x0fff4000, 0x2aa9ffff]` || HighShadow ||
+// || `[0x0bff4000, 0x0fff3fff]` || ShadowGap ||
+// || `[0x0aaa0000, 0x0bff3fff]` || LowShadow ||
+// || `[0x00000000, 0x0aa9ffff]` || LowMem ||
+//
+// Default Linux/MIPS64 mapping:
+// || `[0x4000000000, 0xffffffffff]` || HighMem ||
+// || `[0x2800000000, 0x3fffffffff]` || HighShadow ||
+// || `[0x2400000000, 0x27ffffffff]` || ShadowGap ||
+// || `[0x2000000000, 0x23ffffffff]` || LowShadow ||
+// || `[0x0000000000, 0x1fffffffff]` || LowMem ||
+//
+// Default Linux/RISCV64 Sv39 mapping:
+// || `[0x1555550000, 0x3fffffffff]` || HighMem ||
+// || `[0x0fffffa000, 0x1555555fff]` || HighShadow ||
+// || `[0x0effffa000, 0x0fffff9fff]` || ShadowGap ||
+// || `[0x0d55550000, 0x0effff9fff]` || LowShadow ||
+// || `[0x0000000000, 0x0d5554ffff]` || LowMem ||
+//
+// Default Linux/AArch64 (39-bit VMA) mapping:
+// || `[0x2000000000, 0x7fffffffff]` || highmem ||
+// || `[0x1400000000, 0x1fffffffff]` || highshadow ||
+// || `[0x1200000000, 0x13ffffffff]` || shadowgap ||
+// || `[0x1000000000, 0x11ffffffff]` || lowshadow ||
+// || `[0x0000000000, 0x0fffffffff]` || lowmem ||
+//
+// Default Linux/AArch64 (42-bit VMA) mapping:
+// || `[0x10000000000, 0x3ffffffffff]` || highmem ||
+// || `[0x0a000000000, 0x0ffffffffff]` || highshadow ||
+// || `[0x09000000000, 0x09fffffffff]` || shadowgap ||
+// || `[0x08000000000, 0x08fffffffff]` || lowshadow ||
+// || `[0x00000000000, 0x07fffffffff]` || lowmem ||
+//
+// Default Linux/S390 mapping:
+// || `[0x30000000, 0x7fffffff]` || HighMem ||
+// || `[0x26000000, 0x2fffffff]` || HighShadow ||
+// || `[0x24000000, 0x25ffffff]` || ShadowGap ||
+// || `[0x20000000, 0x23ffffff]` || LowShadow ||
+// || `[0x00000000, 0x1fffffff]` || LowMem ||
+//
+// Default Linux/SystemZ mapping:
+// || `[0x14000000000000, 0x1fffffffffffff]` || HighMem ||
+// || `[0x12800000000000, 0x13ffffffffffff]` || HighShadow ||
+// || `[0x12000000000000, 0x127fffffffffff]` || ShadowGap ||
+// || `[0x10000000000000, 0x11ffffffffffff]` || LowShadow ||
+// || `[0x00000000000000, 0x0fffffffffffff]` || LowMem ||
+//
+// Default Linux/SPARC64 (52-bit VMA) mapping:
+// || `[0x8000000000000, 0xfffffffffffff]` || HighMem ||
+// || `[0x1080000000000, 0x207ffffffffff]` || HighShadow ||
+// || `[0x0090000000000, 0x107ffffffffff]` || ShadowGap ||
+// || `[0x0080000000000, 0x008ffffffffff]` || LowShadow ||
+// || `[0x0000000000000, 0x007ffffffffff]` || LowMem ||
+//
+// Default Linux/LoongArch64 (47-bit VMA) mapping:
+// || `[0x500000000000, 0x7fffffffffff]` || HighMem ||
+// || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow ||
+// || `[0x480000000000, 0x49ffffffffff]` || ShadowGap ||
+// || `[0x400000000000, 0x47ffffffffff]` || LowShadow ||
+// || `[0x000000000000, 0x3fffffffffff]` || LowMem ||
+//
+// Shadow mapping on FreeBSD/x86-64 with SHADOW_OFFSET == 0x400000000000:
+// || `[0x500000000000, 0x7fffffffffff]` || HighMem ||
+// || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow ||
+// || `[0x480000000000, 0x49ffffffffff]` || ShadowGap ||
+// || `[0x400000000000, 0x47ffffffffff]` || LowShadow ||
+// || `[0x000000000000, 0x3fffffffffff]` || LowMem ||
+//
+// Shadow mapping on FreeBSD/i386 with SHADOW_OFFSET == 0x40000000:
+// || `[0x60000000, 0xffffffff]` || HighMem ||
+// || `[0x4c000000, 0x5fffffff]` || HighShadow ||
+// || `[0x48000000, 0x4bffffff]` || ShadowGap ||
+// || `[0x40000000, 0x47ffffff]` || LowShadow ||
+// || `[0x00000000, 0x3fffffff]` || LowMem ||
+//
+// Shadow mapping on NetBSD/x86-64 with SHADOW_OFFSET == 0x400000000000:
+// || `[0x4feffffffe01, 0x7f7ffffff000]` || HighMem ||
+// || `[0x49fdffffffc0, 0x4feffffffe00]` || HighShadow ||
+// || `[0x480000000000, 0x49fdffffffbf]` || ShadowGap ||
+// || `[0x400000000000, 0x47ffffffffff]` || LowShadow ||
+// || `[0x000000000000, 0x3fffffffffff]` || LowMem ||
+//
+// Shadow mapping on NetBSD/i386 with SHADOW_OFFSET == 0x40000000:
+// || `[0x60000000, 0xfffff000]` || HighMem ||
+// || `[0x4c000000, 0x5fffffff]` || HighShadow ||
+// || `[0x48000000, 0x4bffffff]` || ShadowGap ||
+// || `[0x40000000, 0x47ffffff]` || LowShadow ||
+// || `[0x00000000, 0x3fffffff]` || LowMem ||
+//
+// Default Windows/i386 mapping:
+// (the exact location of HighShadow/HighMem may vary depending
+// on WoW64, /LARGEADDRESSAWARE, etc).
+// || `[0x50000000, 0xffffffff]` || HighMem ||
+// || `[0x3a000000, 0x4fffffff]` || HighShadow ||
+// || `[0x36000000, 0x39ffffff]` || ShadowGap ||
+// || `[0x30000000, 0x35ffffff]` || LowShadow ||
+// || `[0x00000000, 0x2fffffff]` || LowMem ||
+
+#define ASAN_SHADOW_SCALE 3
+
+#if SANITIZER_FUCHSIA
+# define ASAN_SHADOW_OFFSET_CONST (0)
+#elif SANITIZER_WORDSIZE == 32
+# if SANITIZER_ANDROID
+# define ASAN_SHADOW_OFFSET_DYNAMIC
+# elif defined(__mips__)
+# define ASAN_SHADOW_OFFSET_CONST 0x0aaa0000
+# elif SANITIZER_FREEBSD
+# define ASAN_SHADOW_OFFSET_CONST 0x40000000
+# elif SANITIZER_NETBSD
+# define ASAN_SHADOW_OFFSET_CONST 0x40000000
+# elif SANITIZER_WINDOWS
+# define ASAN_SHADOW_OFFSET_CONST 0x30000000
+# elif SANITIZER_IOS
+# define ASAN_SHADOW_OFFSET_DYNAMIC
+# else
+# define ASAN_SHADOW_OFFSET_CONST 0x20000000
+# endif
+#else
+# if SANITIZER_IOS
+# define ASAN_SHADOW_OFFSET_DYNAMIC
+# elif SANITIZER_APPLE && defined(__aarch64__)
+# define ASAN_SHADOW_OFFSET_DYNAMIC
+# elif SANITIZER_FREEBSD && defined(__aarch64__)
+# define ASAN_SHADOW_OFFSET_CONST 0x0000800000000000
+# elif SANITIZER_RISCV64
+# define ASAN_SHADOW_OFFSET_CONST 0x0000000d55550000
+# elif defined(__aarch64__)
+# define ASAN_SHADOW_OFFSET_CONST 0x0000001000000000
+# elif defined(__powerpc64__)
+# define ASAN_SHADOW_OFFSET_CONST 0x0000100000000000
+# elif defined(__s390x__)
+# define ASAN_SHADOW_OFFSET_CONST 0x0010000000000000
+# elif SANITIZER_FREEBSD
+# define ASAN_SHADOW_OFFSET_CONST 0x0000400000000000
+# elif SANITIZER_NETBSD
+# define ASAN_SHADOW_OFFSET_CONST 0x0000400000000000
+# elif SANITIZER_APPLE
+# define ASAN_SHADOW_OFFSET_CONST 0x0000100000000000
+# elif defined(__mips64)
+# define ASAN_SHADOW_OFFSET_CONST 0x0000002000000000
+# elif defined(__sparc__)
+# define ASAN_SHADOW_OFFSET_CONST 0x0000080000000000
+# elif SANITIZER_LOONGARCH64
+# define ASAN_SHADOW_OFFSET_CONST 0x0000400000000000
+# elif SANITIZER_WINDOWS64
+# define ASAN_SHADOW_OFFSET_DYNAMIC
+# else
+# if ASAN_SHADOW_SCALE != 3
+# error "Value below is based on shadow scale = 3."
+# error "Original formula was: 0x7FFFFFFF & (~0xFFFULL << SHADOW_SCALE)."
+# endif
+# define ASAN_SHADOW_OFFSET_CONST 0x000000007fff8000
+# endif
+#endif
+
+#if defined(__cplusplus)
+# include "asan_internal.h"
+
+static const u64 kDefaultShadowSentinel = ~(uptr)0;
+
+# if defined(ASAN_SHADOW_OFFSET_CONST)
+static const u64 kConstShadowOffset = ASAN_SHADOW_OFFSET_CONST;
+# define ASAN_SHADOW_OFFSET kConstShadowOffset
+# elif defined(ASAN_SHADOW_OFFSET_DYNAMIC)
+# define ASAN_SHADOW_OFFSET __asan_shadow_memory_dynamic_address
+# else
+# error "ASAN_SHADOW_OFFSET can't be determined."
+# endif
+
+# if SANITIZER_ANDROID && defined(__arm__)
+# define ASAN_PREMAP_SHADOW 1
+# else
+# define ASAN_PREMAP_SHADOW 0
+# endif
+
+# define ASAN_SHADOW_GRANULARITY (1ULL << ASAN_SHADOW_SCALE)
+
+# define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below.
+
+# if DO_ASAN_MAPPING_PROFILE
+# define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++;
+# else
+# define PROFILE_ASAN_MAPPING()
+# endif
+
+// If 1, all shadow boundaries are constants.
+// Don't set to 1 other than for testing.
+# define ASAN_FIXED_MAPPING 0
+
+namespace __asan {
+
+extern uptr AsanMappingProfile[];
+
+# if ASAN_FIXED_MAPPING
+// Fixed mapping for 64-bit Linux. Mostly used for performance comparison
+// with non-fixed mapping. As of r175253 (Feb 2013) the performance
+// difference between fixed and non-fixed mapping is below the noise level.
+static uptr kHighMemEnd = 0x7fffffffffffULL;
+static uptr kMidMemBeg = 0x3000000000ULL;
+static uptr kMidMemEnd = 0x4fffffffffULL;
+# else
+extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init.
+# endif
+
+} // namespace __asan
+
+# if defined(__sparc__) && SANITIZER_WORDSIZE == 64
+# include "asan_mapping_sparc64.h"
+# else
+# define MEM_TO_SHADOW(mem) \
+ (((mem) >> ASAN_SHADOW_SCALE) + (ASAN_SHADOW_OFFSET))
+# define SHADOW_TO_MEM(mem) \
+ (((mem) - (ASAN_SHADOW_OFFSET)) << (ASAN_SHADOW_SCALE))
+
+# define kLowMemBeg 0
+# define kLowMemEnd (ASAN_SHADOW_OFFSET ? ASAN_SHADOW_OFFSET - 1 : 0)
+
+# define kLowShadowBeg ASAN_SHADOW_OFFSET
+# define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd)
+
+# define kHighMemBeg (MEM_TO_SHADOW(kHighMemEnd) + 1)
+
+# define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg)
+# define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd)
+
+# define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg)
+# define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd)
+
+// With the zero shadow base we can not actually map pages starting from 0.
+// This constant is somewhat arbitrary.
+# define kZeroBaseShadowStart 0
+# define kZeroBaseMaxShadowStart (1 << 18)
+
+# define kShadowGapBeg \
+ (kLowShadowEnd ? kLowShadowEnd + 1 : kZeroBaseShadowStart)
+# define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1)
+
+# define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0)
+# define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0)
+
+# define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0)
+# define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0)
+
+namespace __asan {
+
+static inline bool AddrIsInLowMem(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return a <= kLowMemEnd;
+}
+
+static inline bool AddrIsInLowShadow(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return a >= kLowShadowBeg && a <= kLowShadowEnd;
+}
+
+static inline bool AddrIsInMidMem(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd;
+}
+
+static inline bool AddrIsInMidShadow(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return kMidMemBeg && a >= kMidShadowBeg && a <= kMidShadowEnd;
+}
+
+static inline bool AddrIsInHighMem(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return kHighMemBeg && a >= kHighMemBeg && a <= kHighMemEnd;
+}
+
+static inline bool AddrIsInHighShadow(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return kHighMemBeg && a >= kHighShadowBeg && a <= kHighShadowEnd;
+}
+
+static inline bool AddrIsInShadowGap(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ if (kMidMemBeg) {
+ if (a <= kShadowGapEnd)
+ return ASAN_SHADOW_OFFSET == 0 || a >= kShadowGapBeg;
+ return (a >= kShadowGap2Beg && a <= kShadowGap2End) ||
+ (a >= kShadowGap3Beg && a <= kShadowGap3End);
+ }
+ // In zero-based shadow mode we treat addresses near zero as addresses
+ // in shadow gap as well.
+ if (ASAN_SHADOW_OFFSET == 0)
+ return a <= kShadowGapEnd;
+ return a >= kShadowGapBeg && a <= kShadowGapEnd;
+}
+
+} // namespace __asan
+
+# endif
+
+namespace __asan {
+
+static inline uptr MemToShadowSize(uptr size) {
+ return size >> ASAN_SHADOW_SCALE;
+}
+
+static inline bool AddrIsInMem(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a) ||
+ (flags()->protect_shadow_gap == 0 && AddrIsInShadowGap(a));
+}
+
+static inline uptr MemToShadow(uptr p) {
+ PROFILE_ASAN_MAPPING();
+ CHECK(AddrIsInMem(p));
+ return MEM_TO_SHADOW(p);
+}
+
+static inline bool AddrIsInShadow(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a);
+}
+
+static inline uptr ShadowToMem(uptr p) {
+ PROFILE_ASAN_MAPPING();
+ CHECK(AddrIsInShadow(p));
+ return SHADOW_TO_MEM(p);
+}
+
+static inline bool AddrIsAlignedByGranularity(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return (a & (ASAN_SHADOW_GRANULARITY - 1)) == 0;
+}
+
+static inline bool AddressIsPoisoned(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ const uptr kAccessSize = 1;
+ u8 *shadow_address = (u8 *)MEM_TO_SHADOW(a);
+ s8 shadow_value = *shadow_address;
+ if (shadow_value) {
+ u8 last_accessed_byte =
+ (a & (ASAN_SHADOW_GRANULARITY - 1)) + kAccessSize - 1;
+ return (last_accessed_byte >= shadow_value);
+ }
+ return false;
+}
+
+// Must be after all calls to PROFILE_ASAN_MAPPING().
+static const uptr kAsanMappingProfileSize = __LINE__;
+
+} // namespace __asan
+
+#endif // __cplusplus
+
+#endif // ASAN_MAPPING_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_mapping_sparc64.h b/contrib/libs/clang16-rt/lib/asan/asan_mapping_sparc64.h
new file mode 100644
index 00000000000..e310c12fe30
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_mapping_sparc64.h
@@ -0,0 +1,121 @@
+//===-- asan_mapping_sparc64.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// SPARC64-specific definitions for ASan memory mapping.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_MAPPING_SPARC64_H
+#define ASAN_MAPPING_SPARC64_H
+
+// This is tailored to the 52-bit VM layout on SPARC-T4 and later.
+// The VM space is split into two 51-bit halves at both ends: the low part
+// has all the bits above the 51st cleared, while the high part has them set.
+// 0xfff8000000000000 - 0xffffffffffffffff
+// 0x0000000000000000 - 0x0007ffffffffffff
+
+#define VMA_BITS 52
+#define HIGH_BITS (64 - VMA_BITS)
+
+// The idea is to chop the high bits before doing the scaling, so the two
+// parts become contiguous again and the usual scheme can be applied.
+
+#define MEM_TO_SHADOW(mem) \
+ ((((mem) << HIGH_BITS) >> (HIGH_BITS + (ASAN_SHADOW_SCALE))) + \
+ (ASAN_SHADOW_OFFSET))
+#define SHADOW_TO_MEM(ptr) (__asan::ShadowToMemSparc64(ptr))
+
+#define kLowMemBeg 0
+#define kLowMemEnd (ASAN_SHADOW_OFFSET - 1)
+
+#define kLowShadowBeg ASAN_SHADOW_OFFSET
+#define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd)
+
+// But of course there is the huge hole between the high shadow memory,
+// which is in the low part, and the beginning of the high part.
+
+#define kHighMemBeg (-(1ULL << (VMA_BITS - 1)))
+
+#define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg)
+#define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd)
+
+#define kMidShadowBeg 0
+#define kMidShadowEnd 0
+
+// With the zero shadow base we can not actually map pages starting from 0.
+// This constant is somewhat arbitrary.
+#define kZeroBaseShadowStart 0
+#define kZeroBaseMaxShadowStart (1 << 18)
+
+#define kShadowGapBeg (kLowShadowEnd + 1)
+#define kShadowGapEnd (kHighShadowBeg - 1)
+
+#define kShadowGap2Beg 0
+#define kShadowGap2End 0
+
+#define kShadowGap3Beg 0
+#define kShadowGap3End 0
+
+namespace __asan {
+
+static inline bool AddrIsInLowMem(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return a <= kLowMemEnd;
+}
+
+static inline bool AddrIsInLowShadow(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return a >= kLowShadowBeg && a <= kLowShadowEnd;
+}
+
+static inline bool AddrIsInMidMem(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return false;
+}
+
+static inline bool AddrIsInMidShadow(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return false;
+}
+
+static inline bool AddrIsInHighMem(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return kHighMemBeg && a >= kHighMemBeg && a <= kHighMemEnd;
+}
+
+static inline bool AddrIsInHighShadow(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return kHighMemBeg && a >= kHighShadowBeg && a <= kHighShadowEnd;
+}
+
+static inline bool AddrIsInShadowGap(uptr a) {
+ PROFILE_ASAN_MAPPING();
+ return a >= kShadowGapBeg && a <= kShadowGapEnd;
+}
+
+static inline constexpr uptr ShadowToMemSparc64(uptr p) {
+ PROFILE_ASAN_MAPPING();
+ p -= ASAN_SHADOW_OFFSET;
+ p <<= ASAN_SHADOW_SCALE;
+ if (p >= 0x8000000000000) {
+ p |= (~0ULL) << VMA_BITS;
+ }
+ return p;
+}
+
+static_assert(ShadowToMemSparc64(MEM_TO_SHADOW(0x0000000000000000)) ==
+ 0x0000000000000000);
+static_assert(ShadowToMemSparc64(MEM_TO_SHADOW(0xfff8000000000000)) ==
+ 0xfff8000000000000);
+// Gets aligned down.
+static_assert(ShadowToMemSparc64(MEM_TO_SHADOW(0x0007ffffffffffff)) ==
+ 0x0007fffffffffff8);
+
+} // namespace __asan
+
+#endif // ASAN_MAPPING_SPARC64_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_memory_profile.cpp b/contrib/libs/clang16-rt/lib/asan/asan_memory_profile.cpp
new file mode 100644
index 00000000000..4fcd5600ed1
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_memory_profile.cpp
@@ -0,0 +1,129 @@
+//===-- asan_memory_profile.cpp ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// This file implements __sanitizer_print_memory_profile.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_stoptheworld.h"
+#include "lsan/lsan_common.h"
+#include "asan/asan_allocator.h"
+
+#if CAN_SANITIZE_LEAKS
+
+namespace __asan {
+
+struct AllocationSite {
+ u32 id;
+ uptr total_size;
+ uptr count;
+};
+
+class HeapProfile {
+ public:
+ HeapProfile() { allocations_.reserve(1024); }
+
+ void ProcessChunk(const AsanChunkView &cv) {
+ if (cv.IsAllocated()) {
+ total_allocated_user_size_ += cv.UsedSize();
+ total_allocated_count_++;
+ u32 id = cv.GetAllocStackId();
+ if (id)
+ Insert(id, cv.UsedSize());
+ } else if (cv.IsQuarantined()) {
+ total_quarantined_user_size_ += cv.UsedSize();
+ total_quarantined_count_++;
+ } else {
+ total_other_count_++;
+ }
+ }
+
+ void Print(uptr top_percent, uptr max_number_of_contexts) {
+ Sort(allocations_.data(), allocations_.size(),
+ [](const AllocationSite &a, const AllocationSite &b) {
+ return a.total_size > b.total_size;
+ });
+ CHECK(total_allocated_user_size_);
+ uptr total_shown = 0;
+ Printf("Live Heap Allocations: %zd bytes in %zd chunks; quarantined: "
+ "%zd bytes in %zd chunks; %zd other chunks; total chunks: %zd; "
+ "showing top %zd%% (at most %zd unique contexts)\n",
+ total_allocated_user_size_, total_allocated_count_,
+ total_quarantined_user_size_, total_quarantined_count_,
+ total_other_count_, total_allocated_count_ +
+ total_quarantined_count_ + total_other_count_, top_percent,
+ max_number_of_contexts);
+ for (uptr i = 0; i < Min(allocations_.size(), max_number_of_contexts);
+ i++) {
+ auto &a = allocations_[i];
+ Printf("%zd byte(s) (%zd%%) in %zd allocation(s)\n", a.total_size,
+ a.total_size * 100 / total_allocated_user_size_, a.count);
+ StackDepotGet(a.id).Print();
+ total_shown += a.total_size;
+ if (total_shown * 100 / total_allocated_user_size_ > top_percent)
+ break;
+ }
+ }
+
+ private:
+ uptr total_allocated_user_size_ = 0;
+ uptr total_allocated_count_ = 0;
+ uptr total_quarantined_user_size_ = 0;
+ uptr total_quarantined_count_ = 0;
+ uptr total_other_count_ = 0;
+ InternalMmapVector<AllocationSite> allocations_;
+
+ void Insert(u32 id, uptr size) {
+ // Linear lookup will be good enough for most cases (although not all).
+ for (uptr i = 0; i < allocations_.size(); i++) {
+ if (allocations_[i].id == id) {
+ allocations_[i].total_size += size;
+ allocations_[i].count++;
+ return;
+ }
+ }
+ allocations_.push_back({id, size, 1});
+ }
+};
+
+static void ChunkCallback(uptr chunk, void *arg) {
+ reinterpret_cast<HeapProfile*>(arg)->ProcessChunk(
+ FindHeapChunkByAllocBeg(chunk));
+}
+
+static void MemoryProfileCB(const SuspendedThreadsList &suspended_threads_list,
+ void *argument) {
+ HeapProfile hp;
+ __lsan::ForEachChunk(ChunkCallback, &hp);
+ uptr *Arg = reinterpret_cast<uptr*>(argument);
+ hp.Print(Arg[0], Arg[1]);
+
+ if (Verbosity())
+ __asan_print_accumulated_stats();
+}
+
+} // namespace __asan
+
+#endif // CAN_SANITIZE_LEAKS
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_print_memory_profile(uptr top_percent,
+ uptr max_number_of_contexts) {
+#if CAN_SANITIZE_LEAKS
+ uptr Arg[2];
+ Arg[0] = top_percent;
+ Arg[1] = max_number_of_contexts;
+ __sanitizer::StopTheWorld(__asan::MemoryProfileCB, Arg);
+#endif // CAN_SANITIZE_LEAKS
+}
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_new_delete.cpp b/contrib/libs/clang16-rt/lib/asan/asan_new_delete.cpp
new file mode 100644
index 00000000000..17280129c75
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_new_delete.cpp
@@ -0,0 +1,196 @@
+//===-- asan_interceptors.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Interceptors for operators new and delete.
+//===----------------------------------------------------------------------===//
+
+#include <stddef.h>
+
+#include "asan_allocator.h"
+#include "asan_internal.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "interception/interception.h"
+
+// C++ operators can't have dllexport attributes on Windows. We export them
+// anyway by passing extra -export flags to the linker, which is exactly that
+// dllexport would normally do. We need to export them in order to make the
+// VS2015 dynamic CRT (MD) work.
+#if SANITIZER_WINDOWS && defined(_MSC_VER)
+#define CXX_OPERATOR_ATTRIBUTE
+#define COMMENT_EXPORT(sym) __pragma(comment(linker, "/export:" sym))
+#ifdef _WIN64
+COMMENT_EXPORT("??2@YAPEAX_K@Z") // operator new
+COMMENT_EXPORT("??2@YAPEAX_KAEBUnothrow_t@std@@@Z") // operator new nothrow
+COMMENT_EXPORT("??3@YAXPEAX@Z") // operator delete
+COMMENT_EXPORT("??3@YAXPEAX_K@Z") // sized operator delete
+COMMENT_EXPORT("??_U@YAPEAX_K@Z") // operator new[]
+COMMENT_EXPORT("??_V@YAXPEAX@Z") // operator delete[]
+#else
+COMMENT_EXPORT("??2@YAPAXI@Z") // operator new
+COMMENT_EXPORT("??2@YAPAXIABUnothrow_t@std@@@Z") // operator new nothrow
+COMMENT_EXPORT("??3@YAXPAX@Z") // operator delete
+COMMENT_EXPORT("??3@YAXPAXI@Z") // sized operator delete
+COMMENT_EXPORT("??_U@YAPAXI@Z") // operator new[]
+COMMENT_EXPORT("??_V@YAXPAX@Z") // operator delete[]
+#endif
+#undef COMMENT_EXPORT
+#else
+#define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+#endif
+
+using namespace __asan;
+
+// FreeBSD prior v9.2 have wrong definition of 'size_t'.
+// http://svnweb.freebsd.org/base?view=revision&revision=232261
+#if SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32
+#include <sys/param.h>
+#if __FreeBSD_version <= 902001 // v9.2
+#define size_t unsigned
+#endif // __FreeBSD_version
+#endif // SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32
+
+// This code has issues on OSX.
+// See https://github.com/google/sanitizers/issues/131.
+
+// Fake std::nothrow_t and std::align_val_t to avoid including <new>.
+namespace std {
+struct nothrow_t {};
+enum class align_val_t: size_t {};
+} // namespace std
+
+// TODO(alekseyshl): throw std::bad_alloc instead of dying on OOM.
+// For local pool allocation, align to SHADOW_GRANULARITY to match asan
+// allocator behavior.
+#define OPERATOR_NEW_BODY(type, nothrow) \
+ GET_STACK_TRACE_MALLOC; \
+ void *res = asan_memalign(0, size, &stack, type); \
+ if (!nothrow && UNLIKELY(!res)) \
+ ReportOutOfMemory(size, &stack); \
+ return res;
+#define OPERATOR_NEW_BODY_ALIGN(type, nothrow) \
+ GET_STACK_TRACE_MALLOC; \
+ void *res = asan_memalign((uptr)align, size, &stack, type); \
+ if (!nothrow && UNLIKELY(!res)) \
+ ReportOutOfMemory(size, &stack); \
+ return res;
+
+// On OS X it's not enough to just provide our own 'operator new' and
+// 'operator delete' implementations, because they're going to be in the
+// runtime dylib, and the main executable will depend on both the runtime
+// dylib and libstdc++, each of those'll have its implementation of new and
+// delete.
+// To make sure that C++ allocation/deallocation operators are overridden on
+// OS X we need to intercept them using their mangled names.
+#if !SANITIZER_APPLE
+CXX_OPERATOR_ATTRIBUTE
+void *operator new(size_t size)
+{ OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/); }
+CXX_OPERATOR_ATTRIBUTE
+void *operator new[](size_t size)
+{ OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/); }
+CXX_OPERATOR_ATTRIBUTE
+void *operator new(size_t size, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/); }
+CXX_OPERATOR_ATTRIBUTE
+void *operator new[](size_t size, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/); }
+CXX_OPERATOR_ATTRIBUTE
+void *operator new(size_t size, std::align_val_t align)
+{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/); }
+CXX_OPERATOR_ATTRIBUTE
+void *operator new[](size_t size, std::align_val_t align)
+{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/); }
+CXX_OPERATOR_ATTRIBUTE
+void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/); }
+CXX_OPERATOR_ATTRIBUTE
+void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/); }
+
+#else // SANITIZER_APPLE
+INTERCEPTOR(void *, _Znwm, size_t size) {
+ OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/);
+}
+INTERCEPTOR(void *, _Znam, size_t size) {
+ OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/);
+}
+INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
+ OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/);
+}
+INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
+ OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/);
+}
+#endif // !SANITIZER_APPLE
+
+#define OPERATOR_DELETE_BODY(type) \
+ GET_STACK_TRACE_FREE; \
+ asan_delete(ptr, 0, 0, &stack, type);
+
+#define OPERATOR_DELETE_BODY_SIZE(type) \
+ GET_STACK_TRACE_FREE; \
+ asan_delete(ptr, size, 0, &stack, type);
+
+#define OPERATOR_DELETE_BODY_ALIGN(type) \
+ GET_STACK_TRACE_FREE; \
+ asan_delete(ptr, 0, static_cast<uptr>(align), &stack, type);
+
+#define OPERATOR_DELETE_BODY_SIZE_ALIGN(type) \
+ GET_STACK_TRACE_FREE; \
+ asan_delete(ptr, size, static_cast<uptr>(align), &stack, type);
+
+#if !SANITIZER_APPLE
+CXX_OPERATOR_ATTRIBUTE
+void operator delete(void *ptr) NOEXCEPT
+{ OPERATOR_DELETE_BODY(FROM_NEW); }
+CXX_OPERATOR_ATTRIBUTE
+void operator delete[](void *ptr) NOEXCEPT
+{ OPERATOR_DELETE_BODY(FROM_NEW_BR); }
+CXX_OPERATOR_ATTRIBUTE
+void operator delete(void *ptr, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY(FROM_NEW); }
+CXX_OPERATOR_ATTRIBUTE
+void operator delete[](void *ptr, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY(FROM_NEW_BR); }
+CXX_OPERATOR_ATTRIBUTE
+void operator delete(void *ptr, size_t size) NOEXCEPT
+{ OPERATOR_DELETE_BODY_SIZE(FROM_NEW); }
+CXX_OPERATOR_ATTRIBUTE
+void operator delete[](void *ptr, size_t size) NOEXCEPT
+{ OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR); }
+CXX_OPERATOR_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); }
+CXX_OPERATOR_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); }
+CXX_OPERATOR_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); }
+CXX_OPERATOR_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); }
+CXX_OPERATOR_ATTRIBUTE
+void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW); }
+CXX_OPERATOR_ATTRIBUTE
+void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR); }
+
+#else // SANITIZER_APPLE
+INTERCEPTOR(void, _ZdlPv, void *ptr)
+{ OPERATOR_DELETE_BODY(FROM_NEW); }
+INTERCEPTOR(void, _ZdaPv, void *ptr)
+{ OPERATOR_DELETE_BODY(FROM_NEW_BR); }
+INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY(FROM_NEW); }
+INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY(FROM_NEW_BR); }
+#endif // !SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_poisoning.cpp b/contrib/libs/clang16-rt/lib/asan/asan_poisoning.cpp
new file mode 100644
index 00000000000..5164b7d860f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_poisoning.cpp
@@ -0,0 +1,685 @@
+//===-- asan_poisoning.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Shadow memory poisoning by ASan RTL and by user application.
+//===----------------------------------------------------------------------===//
+
+#include "asan_poisoning.h"
+
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_interface_internal.h"
+#include "sanitizer_common/sanitizer_libc.h"
+
+namespace __asan {
+
+static atomic_uint8_t can_poison_memory;
+
+void SetCanPoisonMemory(bool value) {
+ atomic_store(&can_poison_memory, value, memory_order_release);
+}
+
+bool CanPoisonMemory() {
+ return atomic_load(&can_poison_memory, memory_order_acquire);
+}
+
+void PoisonShadow(uptr addr, uptr size, u8 value) {
+ if (value && !CanPoisonMemory()) return;
+ CHECK(AddrIsAlignedByGranularity(addr));
+ CHECK(AddrIsInMem(addr));
+ CHECK(AddrIsAlignedByGranularity(addr + size));
+ CHECK(AddrIsInMem(addr + size - ASAN_SHADOW_GRANULARITY));
+ CHECK(REAL(memset));
+ FastPoisonShadow(addr, size, value);
+}
+
+void PoisonShadowPartialRightRedzone(uptr addr,
+ uptr size,
+ uptr redzone_size,
+ u8 value) {
+ if (!CanPoisonMemory()) return;
+ CHECK(AddrIsAlignedByGranularity(addr));
+ CHECK(AddrIsInMem(addr));
+ FastPoisonShadowPartialRightRedzone(addr, size, redzone_size, value);
+}
+
+struct ShadowSegmentEndpoint {
+ u8 *chunk;
+ s8 offset; // in [0, ASAN_SHADOW_GRANULARITY)
+ s8 value; // = *chunk;
+
+ explicit ShadowSegmentEndpoint(uptr address) {
+ chunk = (u8*)MemToShadow(address);
+ offset = address & (ASAN_SHADOW_GRANULARITY - 1);
+ value = *chunk;
+ }
+};
+
+void AsanPoisonOrUnpoisonIntraObjectRedzone(uptr ptr, uptr size, bool poison) {
+ uptr end = ptr + size;
+ if (Verbosity()) {
+ Printf("__asan_%spoison_intra_object_redzone [%p,%p) %zd\n",
+ poison ? "" : "un", (void *)ptr, (void *)end, size);
+ if (Verbosity() >= 2)
+ PRINT_CURRENT_STACK();
+ }
+ CHECK(size);
+ CHECK_LE(size, 4096);
+ CHECK(IsAligned(end, ASAN_SHADOW_GRANULARITY));
+ if (!IsAligned(ptr, ASAN_SHADOW_GRANULARITY)) {
+ *(u8 *)MemToShadow(ptr) =
+ poison ? static_cast<u8>(ptr % ASAN_SHADOW_GRANULARITY) : 0;
+ ptr |= ASAN_SHADOW_GRANULARITY - 1;
+ ptr++;
+ }
+ for (; ptr < end; ptr += ASAN_SHADOW_GRANULARITY)
+ *(u8*)MemToShadow(ptr) = poison ? kAsanIntraObjectRedzone : 0;
+}
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan;
+
+// Current implementation of __asan_(un)poison_memory_region doesn't check
+// that user program (un)poisons the memory it owns. It poisons memory
+// conservatively, and unpoisons progressively to make sure asan shadow
+// mapping invariant is preserved (see detailed mapping description here:
+// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm).
+//
+// * if user asks to poison region [left, right), the program poisons
+// at least [left, AlignDown(right)).
+// * if user asks to unpoison region [left, right), the program unpoisons
+// at most [AlignDown(left), right).
+void __asan_poison_memory_region(void const volatile *addr, uptr size) {
+ if (!flags()->allow_user_poisoning || size == 0) return;
+ uptr beg_addr = (uptr)addr;
+ uptr end_addr = beg_addr + size;
+ VPrintf(3, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr,
+ (void *)end_addr);
+ ShadowSegmentEndpoint beg(beg_addr);
+ ShadowSegmentEndpoint end(end_addr);
+ if (beg.chunk == end.chunk) {
+ CHECK_LT(beg.offset, end.offset);
+ s8 value = beg.value;
+ CHECK_EQ(value, end.value);
+ // We can only poison memory if the byte in end.offset is unaddressable.
+ // No need to re-poison memory if it is poisoned already.
+ if (value > 0 && value <= end.offset) {
+ if (beg.offset > 0) {
+ *beg.chunk = Min(value, beg.offset);
+ } else {
+ *beg.chunk = kAsanUserPoisonedMemoryMagic;
+ }
+ }
+ return;
+ }
+ CHECK_LT(beg.chunk, end.chunk);
+ if (beg.offset > 0) {
+ // Mark bytes from beg.offset as unaddressable.
+ if (beg.value == 0) {
+ *beg.chunk = beg.offset;
+ } else {
+ *beg.chunk = Min(beg.value, beg.offset);
+ }
+ beg.chunk++;
+ }
+ REAL(memset)(beg.chunk, kAsanUserPoisonedMemoryMagic, end.chunk - beg.chunk);
+ // Poison if byte in end.offset is unaddressable.
+ if (end.value > 0 && end.value <= end.offset) {
+ *end.chunk = kAsanUserPoisonedMemoryMagic;
+ }
+}
+
+void __asan_unpoison_memory_region(void const volatile *addr, uptr size) {
+ if (!flags()->allow_user_poisoning || size == 0) return;
+ uptr beg_addr = (uptr)addr;
+ uptr end_addr = beg_addr + size;
+ VPrintf(3, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr,
+ (void *)end_addr);
+ ShadowSegmentEndpoint beg(beg_addr);
+ ShadowSegmentEndpoint end(end_addr);
+ if (beg.chunk == end.chunk) {
+ CHECK_LT(beg.offset, end.offset);
+ s8 value = beg.value;
+ CHECK_EQ(value, end.value);
+ // We unpoison memory bytes up to enbytes up to end.offset if it is not
+ // unpoisoned already.
+ if (value != 0) {
+ *beg.chunk = Max(value, end.offset);
+ }
+ return;
+ }
+ CHECK_LT(beg.chunk, end.chunk);
+ if (beg.offset > 0) {
+ *beg.chunk = 0;
+ beg.chunk++;
+ }
+ REAL(memset)(beg.chunk, 0, end.chunk - beg.chunk);
+ if (end.offset > 0 && end.value != 0) {
+ *end.chunk = Max(end.value, end.offset);
+ }
+}
+
+int __asan_address_is_poisoned(void const volatile *addr) {
+ return __asan::AddressIsPoisoned((uptr)addr);
+}
+
+uptr __asan_region_is_poisoned(uptr beg, uptr size) {
+ if (!size)
+ return 0;
+ uptr end = beg + size;
+ if (!AddrIsInMem(beg))
+ return beg;
+ if (!AddrIsInMem(end))
+ return end;
+ CHECK_LT(beg, end);
+ uptr aligned_b = RoundUpTo(beg, ASAN_SHADOW_GRANULARITY);
+ uptr aligned_e = RoundDownTo(end, ASAN_SHADOW_GRANULARITY);
+ uptr shadow_beg = MemToShadow(aligned_b);
+ uptr shadow_end = MemToShadow(aligned_e);
+ // First check the first and the last application bytes,
+ // then check the ASAN_SHADOW_GRANULARITY-aligned region by calling
+ // mem_is_zero on the corresponding shadow.
+ if (!__asan::AddressIsPoisoned(beg) && !__asan::AddressIsPoisoned(end - 1) &&
+ (shadow_end <= shadow_beg ||
+ __sanitizer::mem_is_zero((const char *)shadow_beg,
+ shadow_end - shadow_beg)))
+ return 0;
+ // The fast check failed, so we have a poisoned byte somewhere.
+ // Find it slowly.
+ for (; beg < end; beg++)
+ if (__asan::AddressIsPoisoned(beg))
+ return beg;
+ UNREACHABLE("mem_is_zero returned false, but poisoned byte was not found");
+ return 0;
+}
+
+#define CHECK_SMALL_REGION(p, size, isWrite) \
+ do { \
+ uptr __p = reinterpret_cast<uptr>(p); \
+ uptr __size = size; \
+ if (UNLIKELY(__asan::AddressIsPoisoned(__p) || \
+ __asan::AddressIsPoisoned(__p + __size - 1))) { \
+ GET_CURRENT_PC_BP_SP; \
+ uptr __bad = __asan_region_is_poisoned(__p, __size); \
+ __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0);\
+ } \
+ } while (false)
+
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+u16 __sanitizer_unaligned_load16(const uu16 *p) {
+ CHECK_SMALL_REGION(p, sizeof(*p), false);
+ return *p;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+u32 __sanitizer_unaligned_load32(const uu32 *p) {
+ CHECK_SMALL_REGION(p, sizeof(*p), false);
+ return *p;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+u64 __sanitizer_unaligned_load64(const uu64 *p) {
+ CHECK_SMALL_REGION(p, sizeof(*p), false);
+ return *p;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store16(uu16 *p, u16 x) {
+ CHECK_SMALL_REGION(p, sizeof(*p), true);
+ *p = x;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store32(uu32 *p, u32 x) {
+ CHECK_SMALL_REGION(p, sizeof(*p), true);
+ *p = x;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store64(uu64 *p, u64 x) {
+ CHECK_SMALL_REGION(p, sizeof(*p), true);
+ *p = x;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __asan_poison_cxx_array_cookie(uptr p) {
+ if (SANITIZER_WORDSIZE != 64) return;
+ if (!flags()->poison_array_cookie) return;
+ uptr s = MEM_TO_SHADOW(p);
+ *reinterpret_cast<u8*>(s) = kAsanArrayCookieMagic;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+uptr __asan_load_cxx_array_cookie(uptr *p) {
+ if (SANITIZER_WORDSIZE != 64) return *p;
+ if (!flags()->poison_array_cookie) return *p;
+ uptr s = MEM_TO_SHADOW(reinterpret_cast<uptr>(p));
+ u8 sval = *reinterpret_cast<u8*>(s);
+ if (sval == kAsanArrayCookieMagic) return *p;
+ // If sval is not kAsanArrayCookieMagic it can only be freed memory,
+ // which means that we are going to get double-free. So, return 0 to avoid
+ // infinite loop of destructors. We don't want to report a double-free here
+ // though, so print a warning just in case.
+ // CHECK_EQ(sval, kAsanHeapFreeMagic);
+ if (sval == kAsanHeapFreeMagic) {
+ Report("AddressSanitizer: loaded array cookie from free-d memory; "
+ "expect a double-free report\n");
+ return 0;
+ }
+ // The cookie may remain unpoisoned if e.g. it comes from a custom
+ // operator new defined inside a class.
+ return *p;
+}
+
+// This is a simplified version of __asan_(un)poison_memory_region, which
+// assumes that left border of region to be poisoned is properly aligned.
+static void PoisonAlignedStackMemory(uptr addr, uptr size, bool do_poison) {
+ if (size == 0) return;
+ uptr aligned_size = size & ~(ASAN_SHADOW_GRANULARITY - 1);
+ PoisonShadow(addr, aligned_size,
+ do_poison ? kAsanStackUseAfterScopeMagic : 0);
+ if (size == aligned_size)
+ return;
+ s8 end_offset = (s8)(size - aligned_size);
+ s8* shadow_end = (s8*)MemToShadow(addr + aligned_size);
+ s8 end_value = *shadow_end;
+ if (do_poison) {
+ // If possible, mark all the bytes mapping to last shadow byte as
+ // unaddressable.
+ if (end_value > 0 && end_value <= end_offset)
+ *shadow_end = (s8)kAsanStackUseAfterScopeMagic;
+ } else {
+ // If necessary, mark few first bytes mapping to last shadow byte
+ // as addressable
+ if (end_value != 0)
+ *shadow_end = Max(end_value, end_offset);
+ }
+}
+
+void __asan_set_shadow_00(uptr addr, uptr size) {
+ REAL(memset)((void *)addr, 0, size);
+}
+
+void __asan_set_shadow_01(uptr addr, uptr size) {
+ REAL(memset)((void *)addr, 0x01, size);
+}
+
+void __asan_set_shadow_02(uptr addr, uptr size) {
+ REAL(memset)((void *)addr, 0x02, size);
+}
+
+void __asan_set_shadow_03(uptr addr, uptr size) {
+ REAL(memset)((void *)addr, 0x03, size);
+}
+
+void __asan_set_shadow_04(uptr addr, uptr size) {
+ REAL(memset)((void *)addr, 0x04, size);
+}
+
+void __asan_set_shadow_05(uptr addr, uptr size) {
+ REAL(memset)((void *)addr, 0x05, size);
+}
+
+void __asan_set_shadow_06(uptr addr, uptr size) {
+ REAL(memset)((void *)addr, 0x06, size);
+}
+
+void __asan_set_shadow_07(uptr addr, uptr size) {
+ REAL(memset)((void *)addr, 0x07, size);
+}
+
+void __asan_set_shadow_f1(uptr addr, uptr size) {
+ REAL(memset)((void *)addr, 0xf1, size);
+}
+
+void __asan_set_shadow_f2(uptr addr, uptr size) {
+ REAL(memset)((void *)addr, 0xf2, size);
+}
+
+void __asan_set_shadow_f3(uptr addr, uptr size) {
+ REAL(memset)((void *)addr, 0xf3, size);
+}
+
+void __asan_set_shadow_f5(uptr addr, uptr size) {
+ REAL(memset)((void *)addr, 0xf5, size);
+}
+
+void __asan_set_shadow_f8(uptr addr, uptr size) {
+ REAL(memset)((void *)addr, 0xf8, size);
+}
+
+void __asan_poison_stack_memory(uptr addr, uptr size) {
+ VReport(1, "poisoning: %p %zx\n", (void *)addr, size);
+ PoisonAlignedStackMemory(addr, size, true);
+}
+
+void __asan_unpoison_stack_memory(uptr addr, uptr size) {
+ VReport(1, "unpoisoning: %p %zx\n", (void *)addr, size);
+ PoisonAlignedStackMemory(addr, size, false);
+}
+
+static void FixUnalignedStorage(uptr storage_beg, uptr storage_end,
+ uptr &old_beg, uptr &old_end, uptr &new_beg,
+ uptr &new_end) {
+ constexpr uptr granularity = ASAN_SHADOW_GRANULARITY;
+ if (UNLIKELY(!AddrIsAlignedByGranularity(storage_end))) {
+ uptr end_down = RoundDownTo(storage_end, granularity);
+ // Ignore the last unaligned granule if the storage is followed by
+ // unpoisoned byte, because we can't poison the prefix anyway. Don't call
+ // AddressIsPoisoned at all if container changes does not affect the last
+ // granule at all.
+ if ((((old_end != new_end) && Max(old_end, new_end) > end_down) ||
+ ((old_beg != new_beg) && Max(old_beg, new_beg) > end_down)) &&
+ !AddressIsPoisoned(storage_end)) {
+ old_beg = Min(end_down, old_beg);
+ old_end = Min(end_down, old_end);
+ new_beg = Min(end_down, new_beg);
+ new_end = Min(end_down, new_end);
+ }
+ }
+
+ // Handle misaligned begin and cut it off.
+ if (UNLIKELY(!AddrIsAlignedByGranularity(storage_beg))) {
+ uptr beg_up = RoundUpTo(storage_beg, granularity);
+ // The first unaligned granule needs special handling only if we had bytes
+ // there before and will have none after.
+ if ((new_beg == new_end || new_beg >= beg_up) && old_beg != old_end &&
+ old_beg < beg_up) {
+ // Keep granule prefix outside of the storage unpoisoned.
+ uptr beg_down = RoundDownTo(storage_beg, granularity);
+ *(u8 *)MemToShadow(beg_down) = storage_beg - beg_down;
+ old_beg = Max(beg_up, old_beg);
+ old_end = Max(beg_up, old_end);
+ new_beg = Max(beg_up, new_beg);
+ new_end = Max(beg_up, new_end);
+ }
+ }
+}
+
+void __sanitizer_annotate_contiguous_container(const void *beg_p,
+ const void *end_p,
+ const void *old_mid_p,
+ const void *new_mid_p) {
+ if (!flags()->detect_container_overflow)
+ return;
+ VPrintf(2, "contiguous_container: %p %p %p %p\n", beg_p, end_p, old_mid_p,
+ new_mid_p);
+ uptr storage_beg = reinterpret_cast<uptr>(beg_p);
+ uptr storage_end = reinterpret_cast<uptr>(end_p);
+ uptr old_end = reinterpret_cast<uptr>(old_mid_p);
+ uptr new_end = reinterpret_cast<uptr>(new_mid_p);
+ uptr old_beg = storage_beg;
+ uptr new_beg = storage_beg;
+ uptr granularity = ASAN_SHADOW_GRANULARITY;
+ if (!(storage_beg <= old_end && storage_beg <= new_end &&
+ old_end <= storage_end && new_end <= storage_end)) {
+ GET_STACK_TRACE_FATAL_HERE;
+ ReportBadParamsToAnnotateContiguousContainer(storage_beg, storage_end,
+ old_end, new_end, &stack);
+ }
+ CHECK_LE(storage_end - storage_beg,
+ FIRST_32_SECOND_64(1UL << 30, 1ULL << 40)); // Sanity check.
+
+ if (old_end == new_end)
+ return; // Nothing to do here.
+
+ FixUnalignedStorage(storage_beg, storage_end, old_beg, old_end, new_beg,
+ new_end);
+
+ uptr a = RoundDownTo(Min(old_end, new_end), granularity);
+ uptr c = RoundUpTo(Max(old_end, new_end), granularity);
+ uptr d1 = RoundDownTo(old_end, granularity);
+ // uptr d2 = RoundUpTo(old_mid, granularity);
+ // Currently we should be in this state:
+ // [a, d1) is good, [d2, c) is bad, [d1, d2) is partially good.
+ // Make a quick sanity check that we are indeed in this state.
+ //
+ // FIXME: Two of these three checks are disabled until we fix
+ // https://github.com/google/sanitizers/issues/258.
+ // if (d1 != d2)
+ // CHECK_EQ(*(u8*)MemToShadow(d1), old_mid - d1);
+ if (a + granularity <= d1)
+ CHECK_EQ(*(u8 *)MemToShadow(a), 0);
+ // if (d2 + granularity <= c && c <= end)
+ // CHECK_EQ(*(u8 *)MemToShadow(c - granularity),
+ // kAsanContiguousContainerOOBMagic);
+
+ uptr b1 = RoundDownTo(new_end, granularity);
+ uptr b2 = RoundUpTo(new_end, granularity);
+ // New state:
+ // [a, b1) is good, [b2, c) is bad, [b1, b2) is partially good.
+ if (b1 > a)
+ PoisonShadow(a, b1 - a, 0);
+ else if (c > b2)
+ PoisonShadow(b2, c - b2, kAsanContiguousContainerOOBMagic);
+ if (b1 != b2) {
+ CHECK_EQ(b2 - b1, granularity);
+ *(u8 *)MemToShadow(b1) = static_cast<u8>(new_end - b1);
+ }
+}
+
+// Annotates a double ended contiguous memory area like std::deque's chunk.
+// It allows detecting buggy accesses to allocated but not used begining
+// or end items of such a container.
+void __sanitizer_annotate_double_ended_contiguous_container(
+ const void *storage_beg_p, const void *storage_end_p,
+ const void *old_container_beg_p, const void *old_container_end_p,
+ const void *new_container_beg_p, const void *new_container_end_p) {
+ if (!flags()->detect_container_overflow)
+ return;
+
+ VPrintf(2, "contiguous_container: %p %p %p %p %p %p\n", storage_beg_p,
+ storage_end_p, old_container_beg_p, old_container_end_p,
+ new_container_beg_p, new_container_end_p);
+
+ uptr storage_beg = reinterpret_cast<uptr>(storage_beg_p);
+ uptr storage_end = reinterpret_cast<uptr>(storage_end_p);
+ uptr old_beg = reinterpret_cast<uptr>(old_container_beg_p);
+ uptr old_end = reinterpret_cast<uptr>(old_container_end_p);
+ uptr new_beg = reinterpret_cast<uptr>(new_container_beg_p);
+ uptr new_end = reinterpret_cast<uptr>(new_container_end_p);
+
+ constexpr uptr granularity = ASAN_SHADOW_GRANULARITY;
+
+ if (!(old_beg <= old_end && new_beg <= new_end) ||
+ !(storage_beg <= new_beg && new_end <= storage_end) ||
+ !(storage_beg <= old_beg && old_end <= storage_end)) {
+ GET_STACK_TRACE_FATAL_HERE;
+ ReportBadParamsToAnnotateDoubleEndedContiguousContainer(
+ storage_beg, storage_end, old_beg, old_end, new_beg, new_end, &stack);
+ }
+ CHECK_LE(storage_end - storage_beg,
+ FIRST_32_SECOND_64(1UL << 30, 1ULL << 40)); // Sanity check.
+
+ if ((old_beg == old_end && new_beg == new_end) ||
+ (old_beg == new_beg && old_end == new_end))
+ return; // Nothing to do here.
+
+ FixUnalignedStorage(storage_beg, storage_end, old_beg, old_end, new_beg,
+ new_end);
+
+ // Handle non-intersecting new/old containers separately have simpler
+ // intersecting case.
+ if (old_beg == old_end || new_beg == new_end || new_end <= old_beg ||
+ old_end <= new_beg) {
+ if (old_beg != old_end) {
+ // Poisoning the old container.
+ uptr a = RoundDownTo(old_beg, granularity);
+ uptr b = RoundUpTo(old_end, granularity);
+ PoisonShadow(a, b - a, kAsanContiguousContainerOOBMagic);
+ }
+
+ if (new_beg != new_end) {
+ // Unpoisoning the new container.
+ uptr a = RoundDownTo(new_beg, granularity);
+ uptr b = RoundDownTo(new_end, granularity);
+ PoisonShadow(a, b - a, 0);
+ if (!AddrIsAlignedByGranularity(new_end))
+ *(u8 *)MemToShadow(b) = static_cast<u8>(new_end - b);
+ }
+
+ return;
+ }
+
+ // Intersection of old and new containers is not empty.
+ CHECK_LT(new_beg, old_end);
+ CHECK_GT(new_end, old_beg);
+
+ if (new_beg < old_beg) {
+ // Round down because we can't poison prefixes.
+ uptr a = RoundDownTo(new_beg, granularity);
+ // Round down and ignore the [c, old_beg) as its state defined by unchanged
+ // [old_beg, old_end).
+ uptr c = RoundDownTo(old_beg, granularity);
+ PoisonShadow(a, c - a, 0);
+ } else if (new_beg > old_beg) {
+ // Round down and poison [a, old_beg) because it was unpoisoned only as a
+ // prefix.
+ uptr a = RoundDownTo(old_beg, granularity);
+ // Round down and ignore the [c, new_beg) as its state defined by unchanged
+ // [new_beg, old_end).
+ uptr c = RoundDownTo(new_beg, granularity);
+
+ PoisonShadow(a, c - a, kAsanContiguousContainerOOBMagic);
+ }
+
+ if (new_end > old_end) {
+ // Round down to poison the prefix.
+ uptr a = RoundDownTo(old_end, granularity);
+ // Round down and handle remainder below.
+ uptr c = RoundDownTo(new_end, granularity);
+ PoisonShadow(a, c - a, 0);
+ if (!AddrIsAlignedByGranularity(new_end))
+ *(u8 *)MemToShadow(c) = static_cast<u8>(new_end - c);
+ } else if (new_end < old_end) {
+ // Round up and handle remained below.
+ uptr a2 = RoundUpTo(new_end, granularity);
+ // Round up to poison entire granule as we had nothing in [old_end, c2).
+ uptr c2 = RoundUpTo(old_end, granularity);
+ PoisonShadow(a2, c2 - a2, kAsanContiguousContainerOOBMagic);
+
+ if (!AddrIsAlignedByGranularity(new_end)) {
+ uptr a = RoundDownTo(new_end, granularity);
+ *(u8 *)MemToShadow(a) = static_cast<u8>(new_end - a);
+ }
+ }
+}
+
+static const void *FindBadAddress(uptr begin, uptr end, bool poisoned) {
+ CHECK_LE(begin, end);
+ constexpr uptr kMaxRangeToCheck = 32;
+ if (end - begin > kMaxRangeToCheck * 2) {
+ if (auto *bad = FindBadAddress(begin, begin + kMaxRangeToCheck, poisoned))
+ return bad;
+ if (auto *bad = FindBadAddress(end - kMaxRangeToCheck, end, poisoned))
+ return bad;
+ }
+
+ for (uptr i = begin; i < end; ++i)
+ if (AddressIsPoisoned(i) != poisoned)
+ return reinterpret_cast<const void *>(i);
+ return nullptr;
+}
+
+const void *__sanitizer_contiguous_container_find_bad_address(
+ const void *beg_p, const void *mid_p, const void *end_p) {
+ if (!flags()->detect_container_overflow)
+ return nullptr;
+ uptr granularity = ASAN_SHADOW_GRANULARITY;
+ uptr beg = reinterpret_cast<uptr>(beg_p);
+ uptr end = reinterpret_cast<uptr>(end_p);
+ uptr mid = reinterpret_cast<uptr>(mid_p);
+ CHECK_LE(beg, mid);
+ CHECK_LE(mid, end);
+ // If the byte after the storage is unpoisoned, everything in the granule
+ // before must stay unpoisoned.
+ uptr annotations_end =
+ (!AddrIsAlignedByGranularity(end) && !AddressIsPoisoned(end))
+ ? RoundDownTo(end, granularity)
+ : end;
+ beg = Min(beg, annotations_end);
+ mid = Min(mid, annotations_end);
+ if (auto *bad = FindBadAddress(beg, mid, false))
+ return bad;
+ if (auto *bad = FindBadAddress(mid, annotations_end, true))
+ return bad;
+ return FindBadAddress(annotations_end, end, false);
+}
+
+int __sanitizer_verify_contiguous_container(const void *beg_p,
+ const void *mid_p,
+ const void *end_p) {
+ return __sanitizer_contiguous_container_find_bad_address(beg_p, mid_p,
+ end_p) == nullptr;
+}
+
+const void *__sanitizer_double_ended_contiguous_container_find_bad_address(
+ const void *storage_beg_p, const void *container_beg_p,
+ const void *container_end_p, const void *storage_end_p) {
+ if (!flags()->detect_container_overflow)
+ return nullptr;
+ uptr granularity = ASAN_SHADOW_GRANULARITY;
+ uptr storage_beg = reinterpret_cast<uptr>(storage_beg_p);
+ uptr storage_end = reinterpret_cast<uptr>(storage_end_p);
+ uptr beg = reinterpret_cast<uptr>(container_beg_p);
+ uptr end = reinterpret_cast<uptr>(container_end_p);
+
+ // The prefix of the firs granule of the container is unpoisoned.
+ if (beg != end)
+ beg = Max(storage_beg, RoundDownTo(beg, granularity));
+
+ // If the byte after the storage is unpoisoned, the prefix of the last granule
+ // is unpoisoned.
+ uptr annotations_end = (!AddrIsAlignedByGranularity(storage_end) &&
+ !AddressIsPoisoned(storage_end))
+ ? RoundDownTo(storage_end, granularity)
+ : storage_end;
+ storage_beg = Min(storage_beg, annotations_end);
+ beg = Min(beg, annotations_end);
+ end = Min(end, annotations_end);
+
+ if (auto *bad = FindBadAddress(storage_beg, beg, true))
+ return bad;
+ if (auto *bad = FindBadAddress(beg, end, false))
+ return bad;
+ if (auto *bad = FindBadAddress(end, annotations_end, true))
+ return bad;
+ return FindBadAddress(annotations_end, storage_end, false);
+}
+
+int __sanitizer_verify_double_ended_contiguous_container(
+ const void *storage_beg_p, const void *container_beg_p,
+ const void *container_end_p, const void *storage_end_p) {
+ return __sanitizer_double_ended_contiguous_container_find_bad_address(
+ storage_beg_p, container_beg_p, container_end_p, storage_end_p) ==
+ nullptr;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __asan_poison_intra_object_redzone(uptr ptr, uptr size) {
+ AsanPoisonOrUnpoisonIntraObjectRedzone(ptr, size, true);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __asan_unpoison_intra_object_redzone(uptr ptr, uptr size) {
+ AsanPoisonOrUnpoisonIntraObjectRedzone(ptr, size, false);
+}
+
+// --- Implementation of LSan-specific functions --- {{{1
+namespace __lsan {
+bool WordIsPoisoned(uptr addr) {
+ return (__asan_region_is_poisoned(addr, sizeof(uptr)) != 0);
+}
+}
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_poisoning.h b/contrib/libs/clang16-rt/lib/asan/asan_poisoning.h
new file mode 100644
index 00000000000..600bd011f30
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_poisoning.h
@@ -0,0 +1,98 @@
+//===-- asan_poisoning.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Shadow memory poisoning by ASan RTL and by user application.
+//===----------------------------------------------------------------------===//
+
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_platform.h"
+
+namespace __asan {
+
+// Enable/disable memory poisoning.
+void SetCanPoisonMemory(bool value);
+bool CanPoisonMemory();
+
+// Poisons the shadow memory for "size" bytes starting from "addr".
+void PoisonShadow(uptr addr, uptr size, u8 value);
+
+// Poisons the shadow memory for "redzone_size" bytes starting from
+// "addr + size".
+void PoisonShadowPartialRightRedzone(uptr addr,
+ uptr size,
+ uptr redzone_size,
+ u8 value);
+
+// Fast versions of PoisonShadow and PoisonShadowPartialRightRedzone that
+// assume that memory addresses are properly aligned. Use in
+// performance-critical code with care.
+ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
+ u8 value) {
+ DCHECK(!value || CanPoisonMemory());
+#if SANITIZER_FUCHSIA
+ __sanitizer_fill_shadow(aligned_beg, aligned_size, value,
+ common_flags()->clear_shadow_mmap_threshold);
+#else
+ uptr shadow_beg = MEM_TO_SHADOW(aligned_beg);
+ uptr shadow_end =
+ MEM_TO_SHADOW(aligned_beg + aligned_size - ASAN_SHADOW_GRANULARITY) + 1;
+ // FIXME: Page states are different on Windows, so using the same interface
+ // for mapping shadow and zeroing out pages doesn't "just work", so we should
+ // probably provide higher-level interface for these operations.
+ // For now, just memset on Windows.
+ if (value || SANITIZER_WINDOWS == 1 ||
+ shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) {
+ REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
+ } else {
+ uptr page_size = GetPageSizeCached();
+ uptr page_beg = RoundUpTo(shadow_beg, page_size);
+ uptr page_end = RoundDownTo(shadow_end, page_size);
+
+ if (page_beg >= page_end) {
+ REAL(memset)((void *)shadow_beg, 0, shadow_end - shadow_beg);
+ } else {
+ if (page_beg != shadow_beg) {
+ REAL(memset)((void *)shadow_beg, 0, page_beg - shadow_beg);
+ }
+ if (page_end != shadow_end) {
+ REAL(memset)((void *)page_end, 0, shadow_end - page_end);
+ }
+ ReserveShadowMemoryRange(page_beg, page_end - 1, nullptr);
+ }
+ }
+#endif // SANITIZER_FUCHSIA
+}
+
+ALWAYS_INLINE void FastPoisonShadowPartialRightRedzone(
+ uptr aligned_addr, uptr size, uptr redzone_size, u8 value) {
+ DCHECK(CanPoisonMemory());
+ bool poison_partial = flags()->poison_partial;
+ u8 *shadow = (u8*)MEM_TO_SHADOW(aligned_addr);
+ for (uptr i = 0; i < redzone_size; i += ASAN_SHADOW_GRANULARITY, shadow++) {
+ if (i + ASAN_SHADOW_GRANULARITY <= size) {
+ *shadow = 0; // fully addressable
+ } else if (i >= size) {
+ *shadow =
+ (ASAN_SHADOW_GRANULARITY == 128) ? 0xff : value; // unaddressable
+ } else {
+ // first size-i bytes are addressable
+ *shadow = poison_partial ? static_cast<u8>(size - i) : 0;
+ }
+ }
+}
+
+// Calls __sanitizer::ReleaseMemoryPagesToOS() on
+// [MemToShadow(p), MemToShadow(p+size)].
+void FlushUnneededASanShadowMemory(uptr p, uptr size);
+
+} // namespace __asan
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_posix.cpp b/contrib/libs/clang16-rt/lib/asan/asan_posix.cpp
new file mode 100644
index 00000000000..765f4a26cd7
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_posix.cpp
@@ -0,0 +1,158 @@
+//===-- asan_posix.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Posix-specific details.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_POSIX
+
+# include <pthread.h>
+# include <signal.h>
+# include <stdlib.h>
+# include <sys/resource.h>
+# include <sys/time.h>
+# include <unistd.h>
+
+# include "asan_interceptors.h"
+# include "asan_internal.h"
+# include "asan_mapping.h"
+# include "asan_poisoning.h"
+# include "asan_report.h"
+# include "asan_stack.h"
+# include "lsan/lsan_common.h"
+# include "sanitizer_common/sanitizer_libc.h"
+# include "sanitizer_common/sanitizer_posix.h"
+# include "sanitizer_common/sanitizer_procmaps.h"
+
+namespace __asan {
+
+void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
+ StartReportDeadlySignal();
+ SignalContext sig(siginfo, context);
+ ReportDeadlySignal(sig);
+}
+
+bool PlatformUnpoisonStacks() {
+ stack_t signal_stack;
+ CHECK_EQ(0, sigaltstack(nullptr, &signal_stack));
+ uptr sigalt_bottom = (uptr)signal_stack.ss_sp;
+ uptr sigalt_top = (uptr)((char *)signal_stack.ss_sp + signal_stack.ss_size);
+ // If we're executing on the signal alternate stack AND the Linux flag
+ // SS_AUTODISARM was used, then we cannot get the signal alternate stack
+ // bounds from sigaltstack -- sigaltstack's output looks just as if no
+ // alternate stack has ever been set up.
+ // We're always unpoisoning the signal alternate stack to support jumping
+ // between the default stack and signal alternate stack.
+ if (signal_stack.ss_flags != SS_DISABLE)
+ UnpoisonStack(sigalt_bottom, sigalt_top, "sigalt");
+
+ if (signal_stack.ss_flags != SS_ONSTACK)
+ return false;
+
+ // Since we're on the signal alternate stack, we cannot find the DEFAULT
+ // stack bottom using a local variable.
+ uptr default_bottom, tls_addr, tls_size, stack_size;
+ GetThreadStackAndTls(/*main=*/false, &default_bottom, &stack_size, &tls_addr,
+ &tls_size);
+ UnpoisonStack(default_bottom, default_bottom + stack_size, "default");
+ return true;
+}
+
+// ---------------------- TSD ---------------- {{{1
+
+#if SANITIZER_NETBSD && !ASAN_DYNAMIC
+// Thread Static Data cannot be used in early static ASan init on NetBSD.
+// Reuse the Asan TSD API for compatibility with existing code
+// with an alternative implementation.
+
+static void (*tsd_destructor)(void *tsd) = nullptr;
+
+struct tsd_key {
+ tsd_key() : key(nullptr) {}
+ ~tsd_key() {
+ CHECK(tsd_destructor);
+ if (key)
+ (*tsd_destructor)(key);
+ }
+ void *key;
+};
+
+static thread_local struct tsd_key key;
+
+void AsanTSDInit(void (*destructor)(void *tsd)) {
+ CHECK(!tsd_destructor);
+ tsd_destructor = destructor;
+}
+
+void *AsanTSDGet() {
+ CHECK(tsd_destructor);
+ return key.key;
+}
+
+void AsanTSDSet(void *tsd) {
+ CHECK(tsd_destructor);
+ CHECK(tsd);
+ CHECK(!key.key);
+ key.key = tsd;
+}
+
+void PlatformTSDDtor(void *tsd) {
+ CHECK(tsd_destructor);
+ CHECK_EQ(key.key, tsd);
+ key.key = nullptr;
+ // Make sure that signal handler can not see a stale current thread pointer.
+ atomic_signal_fence(memory_order_seq_cst);
+ AsanThread::TSDDtor(tsd);
+}
+#else
+static pthread_key_t tsd_key;
+static bool tsd_key_inited = false;
+void AsanTSDInit(void (*destructor)(void *tsd)) {
+ CHECK(!tsd_key_inited);
+ tsd_key_inited = true;
+ CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
+}
+
+void *AsanTSDGet() {
+ CHECK(tsd_key_inited);
+ return pthread_getspecific(tsd_key);
+}
+
+void AsanTSDSet(void *tsd) {
+ CHECK(tsd_key_inited);
+ pthread_setspecific(tsd_key, tsd);
+}
+
+void PlatformTSDDtor(void *tsd) {
+ AsanThreadContext *context = (AsanThreadContext *)tsd;
+ if (context->destructor_iterations > 1) {
+ context->destructor_iterations--;
+ CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
+ return;
+ }
+ AsanThread::TSDDtor(tsd);
+}
+#endif
+
+void InstallAtExitCheckLeaks() {
+ if (CAN_SANITIZE_LEAKS) {
+ if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
+ if (flags()->halt_on_error)
+ Atexit(__lsan::DoLeakCheck);
+ else
+ Atexit(__lsan::DoRecoverableLeakCheckVoid);
+ }
+ }
+}
+
+} // namespace __asan
+
+#endif // SANITIZER_POSIX
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_preinit.cpp b/contrib/libs/clang16-rt/lib/asan/asan_preinit.cpp
new file mode 100644
index 00000000000..b07556ec96f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_preinit.cpp
@@ -0,0 +1,24 @@
+//===-- asan_preinit.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Call __asan_init at the very early stage of process startup.
+//===----------------------------------------------------------------------===//
+#include "asan_internal.h"
+
+using namespace __asan;
+
+#if SANITIZER_CAN_USE_PREINIT_ARRAY
+ // The symbol is called __local_asan_preinit, because it's not intended to be
+ // exported.
+ // This code linked into the main executable when -fsanitize=address is in
+ // the link flags. It can only use exported interface functions.
+ __attribute__((section(".preinit_array"), used))
+ void (*__local_asan_preinit)(void) = __asan_init;
+#endif
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_premap_shadow.cpp b/contrib/libs/clang16-rt/lib/asan/asan_premap_shadow.cpp
new file mode 100644
index 00000000000..bed2f62a225
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_premap_shadow.cpp
@@ -0,0 +1,64 @@
+//===-- asan_premap_shadow.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Reserve shadow memory with an ifunc resolver.
+//===----------------------------------------------------------------------===//
+
+#include "asan_mapping.h"
+
+#if ASAN_PREMAP_SHADOW
+
+#include "asan_premap_shadow.h"
+#include "sanitizer_common/sanitizer_posix.h"
+
+namespace __asan {
+
+// The code in this file needs to run in an unrelocated binary. It may not
+// access any external symbol, including its own non-hidden globals.
+
+// Conservative upper limit.
+uptr PremapShadowSize() {
+ uptr granularity = GetMmapGranularity();
+ return RoundUpTo(GetMaxVirtualAddress() >> ASAN_SHADOW_SCALE, granularity);
+}
+
+// Returns an address aligned to 8 pages, such that one page on the left and
+// PremapShadowSize() bytes on the right of it are mapped r/o.
+uptr PremapShadow() {
+ return MapDynamicShadow(PremapShadowSize(), /*mmap_alignment_scale*/ 3,
+ /*min_shadow_base_alignment*/ 0, kHighMemEnd);
+}
+
+bool PremapShadowFailed() {
+ uptr shadow = reinterpret_cast<uptr>(&__asan_shadow);
+ uptr resolver = reinterpret_cast<uptr>(&__asan_premap_shadow);
+ // shadow == resolver is how Android KitKat and older handles ifunc.
+ // shadow == 0 just in case.
+ if (shadow == 0 || shadow == resolver)
+ return true;
+ return false;
+}
+} // namespace __asan
+
+extern "C" {
+decltype(__asan_shadow)* __asan_premap_shadow() {
+ // The resolver may be called multiple times. Map the shadow just once.
+ static uptr premapped_shadow = 0;
+ if (!premapped_shadow) premapped_shadow = __asan::PremapShadow();
+ return reinterpret_cast<decltype(__asan_shadow)*>(premapped_shadow);
+}
+
+// __asan_shadow is a "function" that has the same address as the first byte of
+// the shadow mapping.
+INTERFACE_ATTRIBUTE __attribute__((ifunc("__asan_premap_shadow"))) void
+__asan_shadow();
+}
+
+#endif // ASAN_PREMAP_SHADOW
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_premap_shadow.h b/contrib/libs/clang16-rt/lib/asan/asan_premap_shadow.h
new file mode 100644
index 00000000000..c9c886e8dca
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_premap_shadow.h
@@ -0,0 +1,29 @@
+//===-- asan_mapping.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Premap shadow range with an ifunc resolver.
+//===----------------------------------------------------------------------===//
+
+
+#ifndef ASAN_PREMAP_SHADOW_H
+#define ASAN_PREMAP_SHADOW_H
+
+#if ASAN_PREMAP_SHADOW
+namespace __asan {
+// Conservative upper limit.
+uptr PremapShadowSize();
+bool PremapShadowFailed();
+}
+#endif
+
+extern "C" INTERFACE_ATTRIBUTE void __asan_shadow();
+extern "C" decltype(__asan_shadow)* __asan_premap_shadow();
+
+#endif // ASAN_PREMAP_SHADOW_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_report.cpp b/contrib/libs/clang16-rt/lib/asan/asan_report.cpp
new file mode 100644
index 00000000000..f2c04342e77
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_report.cpp
@@ -0,0 +1,585 @@
+//===-- asan_report.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// This file contains error reporting code.
+//===----------------------------------------------------------------------===//
+
+#include "asan_report.h"
+
+#include "asan_descriptions.h"
+#include "asan_errors.h"
+#include "asan_flags.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "asan_scariness_score.h"
+#include "asan_stack.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_interface_internal.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+
+namespace __asan {
+
+// -------------------- User-specified callbacks ----------------- {{{1
+static void (*error_report_callback)(const char*);
+static char *error_message_buffer = nullptr;
+static uptr error_message_buffer_pos = 0;
+static Mutex error_message_buf_mutex;
+static const unsigned kAsanBuggyPcPoolSize = 25;
+static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize];
+
+void AppendToErrorMessageBuffer(const char *buffer) {
+ Lock l(&error_message_buf_mutex);
+ if (!error_message_buffer) {
+ error_message_buffer =
+ (char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__);
+ error_message_buffer_pos = 0;
+ }
+ uptr length = internal_strlen(buffer);
+ RAW_CHECK(kErrorMessageBufferSize >= error_message_buffer_pos);
+ uptr remaining = kErrorMessageBufferSize - error_message_buffer_pos;
+ internal_strncpy(error_message_buffer + error_message_buffer_pos,
+ buffer, remaining);
+ error_message_buffer[kErrorMessageBufferSize - 1] = '\0';
+ // FIXME: reallocate the buffer instead of truncating the message.
+ error_message_buffer_pos += Min(remaining, length);
+}
+
+// ---------------------- Helper functions ----------------------- {{{1
+
+void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte,
+ bool in_shadow, const char *after) {
+ Decorator d;
+ str->append("%s%s%x%x%s%s", before,
+ in_shadow ? d.ShadowByte(byte) : d.MemoryByte(), byte >> 4,
+ byte & 15, d.Default(), after);
+}
+
+static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
+ const char *zone_name) {
+ if (zone_ptr) {
+ if (zone_name) {
+ Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n", (void *)ptr,
+ (void *)zone_ptr, zone_name);
+ } else {
+ Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
+ (void *)ptr, (void *)zone_ptr);
+ }
+ } else {
+ Printf("malloc_zone_from_ptr(%p) = 0\n", (void *)ptr);
+ }
+}
+
+// ---------------------- Address Descriptions ------------------- {{{1
+
+bool ParseFrameDescription(const char *frame_descr,
+ InternalMmapVector<StackVarDescr> *vars) {
+ CHECK(frame_descr);
+ const char *p;
+ // This string is created by the compiler and has the following form:
+ // "n alloc_1 alloc_2 ... alloc_n"
+ // where alloc_i looks like "offset size len ObjectName"
+ // or "offset size len ObjectName:line".
+ uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10);
+ if (n_objects == 0)
+ return false;
+
+ for (uptr i = 0; i < n_objects; i++) {
+ uptr beg = (uptr)internal_simple_strtoll(p, &p, 10);
+ uptr size = (uptr)internal_simple_strtoll(p, &p, 10);
+ uptr len = (uptr)internal_simple_strtoll(p, &p, 10);
+ if (beg == 0 || size == 0 || *p != ' ') {
+ return false;
+ }
+ p++;
+ char *colon_pos = internal_strchr(p, ':');
+ uptr line = 0;
+ uptr name_len = len;
+ if (colon_pos != nullptr && colon_pos < p + len) {
+ name_len = colon_pos - p;
+ line = (uptr)internal_simple_strtoll(colon_pos + 1, nullptr, 10);
+ }
+ StackVarDescr var = {beg, size, p, name_len, line};
+ vars->push_back(var);
+ p += len;
+ }
+
+ return true;
+}
+
+// -------------------- Different kinds of reports ----------------- {{{1
+
+// Use ScopedInErrorReport to run common actions just before and
+// immediately after printing error report.
+class ScopedInErrorReport {
+ public:
+ explicit ScopedInErrorReport(bool fatal = false)
+ : halt_on_error_(fatal || flags()->halt_on_error) {
+ // Make sure the registry and sanitizer report mutexes are locked while
+ // we're printing an error report.
+ // We can lock them only here to avoid self-deadlock in case of
+ // recursive reports.
+ asanThreadRegistry().Lock();
+ Printf(
+ "=================================================================\n");
+ }
+
+ ~ScopedInErrorReport() {
+ if (halt_on_error_ && !__sanitizer_acquire_crash_state()) {
+ asanThreadRegistry().Unlock();
+ return;
+ }
+ ASAN_ON_ERROR();
+ if (current_error_.IsValid()) current_error_.Print();
+
+ // Make sure the current thread is announced.
+ DescribeThread(GetCurrentThread());
+ // We may want to grab this lock again when printing stats.
+ asanThreadRegistry().Unlock();
+ // Print memory stats.
+ if (flags()->print_stats)
+ __asan_print_accumulated_stats();
+
+ if (common_flags()->print_cmdline)
+ PrintCmdline();
+
+ if (common_flags()->print_module_map == 2)
+ DumpProcessMap();
+
+ // Copy the message buffer so that we could start logging without holding a
+ // lock that gets acquired during printing.
+ InternalMmapVector<char> buffer_copy(kErrorMessageBufferSize);
+ {
+ Lock l(&error_message_buf_mutex);
+ internal_memcpy(buffer_copy.data(),
+ error_message_buffer, kErrorMessageBufferSize);
+ // Clear error_message_buffer so that if we find other errors
+ // we don't re-log this error.
+ error_message_buffer_pos = 0;
+ }
+
+ LogFullErrorReport(buffer_copy.data());
+
+ if (error_report_callback) {
+ error_report_callback(buffer_copy.data());
+ }
+
+ if (halt_on_error_ && common_flags()->abort_on_error) {
+ // On Android the message is truncated to 512 characters.
+ // FIXME: implement "compact" error format, possibly without, or with
+ // highly compressed stack traces?
+ // FIXME: or just use the summary line as abort message?
+ SetAbortMessage(buffer_copy.data());
+ }
+
+ // In halt_on_error = false mode, reset the current error object (before
+ // unlocking).
+ if (!halt_on_error_)
+ internal_memset(&current_error_, 0, sizeof(current_error_));
+
+ if (halt_on_error_) {
+ Report("ABORTING\n");
+ Die();
+ }
+ }
+
+ void ReportError(const ErrorDescription &description) {
+ // Can only report one error per ScopedInErrorReport.
+ CHECK_EQ(current_error_.kind, kErrorKindInvalid);
+ internal_memcpy(&current_error_, &description, sizeof(current_error_));
+ }
+
+ static ErrorDescription &CurrentError() {
+ return current_error_;
+ }
+
+ private:
+ ScopedErrorReportLock error_report_lock_;
+ // Error currently being reported. This enables the destructor to interact
+ // with the debugger and point it to an error description.
+ static ErrorDescription current_error_;
+ bool halt_on_error_;
+};
+
+ErrorDescription ScopedInErrorReport::current_error_(LINKER_INITIALIZED);
+
+void ReportDeadlySignal(const SignalContext &sig) {
+ ScopedInErrorReport in_report(/*fatal*/ true);
+ ErrorDeadlySignal error(GetCurrentTidOrInvalid(), sig);
+ in_report.ReportError(error);
+}
+
+void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) {
+ ScopedInErrorReport in_report;
+ ErrorDoubleFree error(GetCurrentTidOrInvalid(), free_stack, addr);
+ in_report.ReportError(error);
+}
+
+void ReportNewDeleteTypeMismatch(uptr addr, uptr delete_size,
+ uptr delete_alignment,
+ BufferedStackTrace *free_stack) {
+ ScopedInErrorReport in_report;
+ ErrorNewDeleteTypeMismatch error(GetCurrentTidOrInvalid(), free_stack, addr,
+ delete_size, delete_alignment);
+ in_report.ReportError(error);
+}
+
+void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack) {
+ ScopedInErrorReport in_report;
+ ErrorFreeNotMalloced error(GetCurrentTidOrInvalid(), free_stack, addr);
+ in_report.ReportError(error);
+}
+
+void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
+ AllocType alloc_type,
+ AllocType dealloc_type) {
+ ScopedInErrorReport in_report;
+ ErrorAllocTypeMismatch error(GetCurrentTidOrInvalid(), free_stack, addr,
+ alloc_type, dealloc_type);
+ in_report.ReportError(error);
+}
+
+void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report;
+ ErrorMallocUsableSizeNotOwned error(GetCurrentTidOrInvalid(), stack, addr);
+ in_report.ReportError(error);
+}
+
+void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
+ BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report;
+ ErrorSanitizerGetAllocatedSizeNotOwned error(GetCurrentTidOrInvalid(), stack,
+ addr);
+ in_report.ReportError(error);
+}
+
+void ReportCallocOverflow(uptr count, uptr size, BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report(/*fatal*/ true);
+ ErrorCallocOverflow error(GetCurrentTidOrInvalid(), stack, count, size);
+ in_report.ReportError(error);
+}
+
+void ReportReallocArrayOverflow(uptr count, uptr size,
+ BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report(/*fatal*/ true);
+ ErrorReallocArrayOverflow error(GetCurrentTidOrInvalid(), stack, count, size);
+ in_report.ReportError(error);
+}
+
+void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report(/*fatal*/ true);
+ ErrorPvallocOverflow error(GetCurrentTidOrInvalid(), stack, size);
+ in_report.ReportError(error);
+}
+
+void ReportInvalidAllocationAlignment(uptr alignment,
+ BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report(/*fatal*/ true);
+ ErrorInvalidAllocationAlignment error(GetCurrentTidOrInvalid(), stack,
+ alignment);
+ in_report.ReportError(error);
+}
+
+void ReportInvalidAlignedAllocAlignment(uptr size, uptr alignment,
+ BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report(/*fatal*/ true);
+ ErrorInvalidAlignedAllocAlignment error(GetCurrentTidOrInvalid(), stack,
+ size, alignment);
+ in_report.ReportError(error);
+}
+
+void ReportInvalidPosixMemalignAlignment(uptr alignment,
+ BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report(/*fatal*/ true);
+ ErrorInvalidPosixMemalignAlignment error(GetCurrentTidOrInvalid(), stack,
+ alignment);
+ in_report.ReportError(error);
+}
+
+void ReportAllocationSizeTooBig(uptr user_size, uptr total_size, uptr max_size,
+ BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report(/*fatal*/ true);
+ ErrorAllocationSizeTooBig error(GetCurrentTidOrInvalid(), stack, user_size,
+ total_size, max_size);
+ in_report.ReportError(error);
+}
+
+void ReportRssLimitExceeded(BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report(/*fatal*/ true);
+ ErrorRssLimitExceeded error(GetCurrentTidOrInvalid(), stack);
+ in_report.ReportError(error);
+}
+
+void ReportOutOfMemory(uptr requested_size, BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report(/*fatal*/ true);
+ ErrorOutOfMemory error(GetCurrentTidOrInvalid(), stack, requested_size);
+ in_report.ReportError(error);
+}
+
+void ReportStringFunctionMemoryRangesOverlap(const char *function,
+ const char *offset1, uptr length1,
+ const char *offset2, uptr length2,
+ BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report;
+ ErrorStringFunctionMemoryRangesOverlap error(
+ GetCurrentTidOrInvalid(), stack, (uptr)offset1, length1, (uptr)offset2,
+ length2, function);
+ in_report.ReportError(error);
+}
+
+void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
+ BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report;
+ ErrorStringFunctionSizeOverflow error(GetCurrentTidOrInvalid(), stack, offset,
+ size);
+ in_report.ReportError(error);
+}
+
+void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
+ uptr old_mid, uptr new_mid,
+ BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report;
+ ErrorBadParamsToAnnotateContiguousContainer error(
+ GetCurrentTidOrInvalid(), stack, beg, end, old_mid, new_mid);
+ in_report.ReportError(error);
+}
+
+void ReportBadParamsToAnnotateDoubleEndedContiguousContainer(
+ uptr storage_beg, uptr storage_end, uptr old_container_beg,
+ uptr old_container_end, uptr new_container_beg, uptr new_container_end,
+ BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report;
+ ErrorBadParamsToAnnotateDoubleEndedContiguousContainer error(
+ GetCurrentTidOrInvalid(), stack, storage_beg, storage_end,
+ old_container_beg, old_container_end, new_container_beg,
+ new_container_end);
+ in_report.ReportError(error);
+}
+
+void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
+ const __asan_global *g2, u32 stack_id2) {
+ ScopedInErrorReport in_report;
+ ErrorODRViolation error(GetCurrentTidOrInvalid(), g1, stack_id1, g2,
+ stack_id2);
+ in_report.ReportError(error);
+}
+
+// ----------------------- CheckForInvalidPointerPair ----------- {{{1
+static NOINLINE void ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp,
+ uptr a1, uptr a2) {
+ ScopedInErrorReport in_report;
+ ErrorInvalidPointerPair error(GetCurrentTidOrInvalid(), pc, bp, sp, a1, a2);
+ in_report.ReportError(error);
+}
+
+static bool IsInvalidPointerPair(uptr a1, uptr a2) {
+ if (a1 == a2)
+ return false;
+
+ // 256B in shadow memory can be iterated quite fast
+ static const uptr kMaxOffset = 2048;
+
+ uptr left = a1 < a2 ? a1 : a2;
+ uptr right = a1 < a2 ? a2 : a1;
+ uptr offset = right - left;
+ if (offset <= kMaxOffset)
+ return __asan_region_is_poisoned(left, offset);
+
+ AsanThread *t = GetCurrentThread();
+
+ // check whether left is a stack memory pointer
+ if (uptr shadow_offset1 = t->GetStackVariableShadowStart(left)) {
+ uptr shadow_offset2 = t->GetStackVariableShadowStart(right);
+ return shadow_offset2 == 0 || shadow_offset1 != shadow_offset2;
+ }
+
+ // check whether left is a heap memory address
+ HeapAddressDescription hdesc1, hdesc2;
+ if (GetHeapAddressInformation(left, 0, &hdesc1) &&
+ hdesc1.chunk_access.access_type == kAccessTypeInside)
+ return !GetHeapAddressInformation(right, 0, &hdesc2) ||
+ hdesc2.chunk_access.access_type != kAccessTypeInside ||
+ hdesc1.chunk_access.chunk_begin != hdesc2.chunk_access.chunk_begin;
+
+ // check whether left is an address of a global variable
+ GlobalAddressDescription gdesc1, gdesc2;
+ if (GetGlobalAddressInformation(left, 0, &gdesc1))
+ return !GetGlobalAddressInformation(right - 1, 0, &gdesc2) ||
+ !gdesc1.PointsInsideTheSameVariable(gdesc2);
+
+ if (t->GetStackVariableShadowStart(right) ||
+ GetHeapAddressInformation(right, 0, &hdesc2) ||
+ GetGlobalAddressInformation(right - 1, 0, &gdesc2))
+ return true;
+
+ // At this point we know nothing about both a1 and a2 addresses.
+ return false;
+}
+
+static inline void CheckForInvalidPointerPair(void *p1, void *p2) {
+ switch (flags()->detect_invalid_pointer_pairs) {
+ case 0:
+ return;
+ case 1:
+ if (p1 == nullptr || p2 == nullptr)
+ return;
+ break;
+ }
+
+ uptr a1 = reinterpret_cast<uptr>(p1);
+ uptr a2 = reinterpret_cast<uptr>(p2);
+
+ if (IsInvalidPointerPair(a1, a2)) {
+ GET_CALLER_PC_BP_SP;
+ ReportInvalidPointerPair(pc, bp, sp, a1, a2);
+ }
+}
+// ----------------------- Mac-specific reports ----------------- {{{1
+
+void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
+ BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report;
+ Printf(
+ "mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
+ "This is an unrecoverable problem, exiting now.\n",
+ (void *)addr);
+ PrintZoneForPointer(addr, zone_ptr, zone_name);
+ stack->Print();
+ DescribeAddressIfHeap(addr);
+}
+
+// -------------- SuppressErrorReport -------------- {{{1
+// Avoid error reports duplicating for ASan recover mode.
+static bool SuppressErrorReport(uptr pc) {
+ if (!common_flags()->suppress_equal_pcs) return false;
+ for (unsigned i = 0; i < kAsanBuggyPcPoolSize; i++) {
+ uptr cmp = atomic_load_relaxed(&AsanBuggyPcPool[i]);
+ if (cmp == 0 && atomic_compare_exchange_strong(&AsanBuggyPcPool[i], &cmp,
+ pc, memory_order_relaxed))
+ return false;
+ if (cmp == pc) return true;
+ }
+ Die();
+}
+
+void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
+ uptr access_size, u32 exp, bool fatal) {
+ if (__asan_test_only_reported_buggy_pointer) {
+ *__asan_test_only_reported_buggy_pointer = addr;
+ return;
+ }
+ if (!fatal && SuppressErrorReport(pc)) return;
+ ENABLE_FRAME_POINTER;
+
+ // Optimization experiments.
+ // The experiments can be used to evaluate potential optimizations that remove
+ // instrumentation (assess false negatives). Instead of completely removing
+ // some instrumentation, compiler can emit special calls into runtime
+ // (e.g. __asan_report_exp_load1 instead of __asan_report_load1) and pass
+ // mask of experiments (exp).
+ // The reaction to a non-zero value of exp is to be defined.
+ (void)exp;
+
+ ScopedInErrorReport in_report(fatal);
+ ErrorGeneric error(GetCurrentTidOrInvalid(), pc, bp, sp, addr, is_write,
+ access_size);
+ in_report.ReportError(error);
+}
+
+} // namespace __asan
+
+// --------------------------- Interface --------------------- {{{1
+using namespace __asan;
+
+void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
+ uptr access_size, u32 exp) {
+ ENABLE_FRAME_POINTER;
+ bool fatal = flags()->halt_on_error;
+ ReportGenericError(pc, bp, sp, addr, is_write, access_size, exp, fatal);
+}
+
+void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
+ Lock l(&error_message_buf_mutex);
+ error_report_callback = callback;
+}
+
+void __asan_describe_address(uptr addr) {
+ // Thread registry must be locked while we're describing an address.
+ asanThreadRegistry().Lock();
+ PrintAddressDescription(addr, 1, "");
+ asanThreadRegistry().Unlock();
+}
+
+int __asan_report_present() {
+ return ScopedInErrorReport::CurrentError().kind != kErrorKindInvalid;
+}
+
+uptr __asan_get_report_pc() {
+ if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
+ return ScopedInErrorReport::CurrentError().Generic.pc;
+ return 0;
+}
+
+uptr __asan_get_report_bp() {
+ if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
+ return ScopedInErrorReport::CurrentError().Generic.bp;
+ return 0;
+}
+
+uptr __asan_get_report_sp() {
+ if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
+ return ScopedInErrorReport::CurrentError().Generic.sp;
+ return 0;
+}
+
+uptr __asan_get_report_address() {
+ ErrorDescription &err = ScopedInErrorReport::CurrentError();
+ if (err.kind == kErrorKindGeneric)
+ return err.Generic.addr_description.Address();
+ else if (err.kind == kErrorKindDoubleFree)
+ return err.DoubleFree.addr_description.addr;
+ return 0;
+}
+
+int __asan_get_report_access_type() {
+ if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
+ return ScopedInErrorReport::CurrentError().Generic.is_write;
+ return 0;
+}
+
+uptr __asan_get_report_access_size() {
+ if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
+ return ScopedInErrorReport::CurrentError().Generic.access_size;
+ return 0;
+}
+
+const char *__asan_get_report_description() {
+ if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
+ return ScopedInErrorReport::CurrentError().Generic.bug_descr;
+ return ScopedInErrorReport::CurrentError().Base.scariness.GetDescription();
+}
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_ptr_sub(void *a, void *b) {
+ CheckForInvalidPointerPair(a, b);
+}
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_ptr_cmp(void *a, void *b) {
+ CheckForInvalidPointerPair(a, b);
+}
+} // extern "C"
+
+// Provide default implementation of __asan_on_error that does nothing
+// and may be overriden by user.
+SANITIZER_INTERFACE_WEAK_DEF(void, __asan_on_error, void) {}
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_report.h b/contrib/libs/clang16-rt/lib/asan/asan_report.h
new file mode 100644
index 00000000000..248e30dd42b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_report.h
@@ -0,0 +1,103 @@
+//===-- asan_report.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan-private header for error reporting functions.
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_REPORT_H
+#define ASAN_REPORT_H
+
+#include "asan_allocator.h"
+#include "asan_internal.h"
+#include "asan_thread.h"
+
+namespace __asan {
+
+struct StackVarDescr {
+ uptr beg;
+ uptr size;
+ const char *name_pos;
+ uptr name_len;
+ uptr line;
+};
+
+// Returns the number of globals close to the provided address and copies
+// them to "globals" array.
+int GetGlobalsForAddress(uptr addr, __asan_global *globals, u32 *reg_sites,
+ int max_globals);
+
+const char *MaybeDemangleGlobalName(const char *name);
+void PrintGlobalNameIfASCII(InternalScopedString *str, const __asan_global &g);
+void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g);
+
+void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte,
+ bool in_shadow, const char *after = "\n");
+
+// The following functions prints address description depending
+// on the memory type (shadow/heap/stack/global).
+bool ParseFrameDescription(const char *frame_descr,
+ InternalMmapVector<StackVarDescr> *vars);
+
+// Different kinds of error reports.
+void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
+ uptr access_size, u32 exp, bool fatal);
+void ReportDeadlySignal(const SignalContext &sig);
+void ReportNewDeleteTypeMismatch(uptr addr, uptr delete_size,
+ uptr delete_alignment,
+ BufferedStackTrace *free_stack);
+void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack);
+void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack);
+void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
+ AllocType alloc_type,
+ AllocType dealloc_type);
+void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack);
+void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
+ BufferedStackTrace *stack);
+void ReportCallocOverflow(uptr count, uptr size, BufferedStackTrace *stack);
+void ReportReallocArrayOverflow(uptr count, uptr size,
+ BufferedStackTrace *stack);
+void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack);
+void ReportInvalidAllocationAlignment(uptr alignment,
+ BufferedStackTrace *stack);
+void ReportInvalidAlignedAllocAlignment(uptr size, uptr alignment,
+ BufferedStackTrace *stack);
+void ReportInvalidPosixMemalignAlignment(uptr alignment,
+ BufferedStackTrace *stack);
+void ReportAllocationSizeTooBig(uptr user_size, uptr total_size, uptr max_size,
+ BufferedStackTrace *stack);
+void ReportRssLimitExceeded(BufferedStackTrace *stack);
+void ReportOutOfMemory(uptr requested_size, BufferedStackTrace *stack);
+void ReportStringFunctionMemoryRangesOverlap(const char *function,
+ const char *offset1, uptr length1,
+ const char *offset2, uptr length2,
+ BufferedStackTrace *stack);
+void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
+ BufferedStackTrace *stack);
+void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
+ uptr old_mid, uptr new_mid,
+ BufferedStackTrace *stack);
+void ReportBadParamsToAnnotateDoubleEndedContiguousContainer(
+ uptr storage_beg, uptr storage_end, uptr old_container_beg,
+ uptr old_container_end, uptr new_container_beg, uptr new_container_end,
+ BufferedStackTrace *stack);
+
+void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
+ const __asan_global *g2, u32 stack_id2);
+
+// Mac-specific errors and warnings.
+void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr,
+ const char *zone_name,
+ BufferedStackTrace *stack);
+void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr,
+ const char *zone_name,
+ BufferedStackTrace *stack);
+
+} // namespace __asan
+#endif // ASAN_REPORT_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_rtl.cpp b/contrib/libs/clang16-rt/lib/asan/asan_rtl.cpp
new file mode 100644
index 00000000000..853083182b4
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_rtl.cpp
@@ -0,0 +1,621 @@
+//===-- asan_rtl.cpp ------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Main file of the ASan run-time library.
+//===----------------------------------------------------------------------===//
+
+#include "asan_activation.h"
+#include "asan_allocator.h"
+#include "asan_fake_stack.h"
+#include "asan_interceptors.h"
+#include "asan_interface_internal.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+#include "asan_poisoning.h"
+#include "asan_report.h"
+#include "asan_stack.h"
+#include "asan_stats.h"
+#include "asan_suppressions.h"
+#include "asan_thread.h"
+#include "lsan/lsan_common.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_interface_internal.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+#include "ubsan/ubsan_init.h"
+#include "ubsan/ubsan_platform.h"
+
+uptr __asan_shadow_memory_dynamic_address; // Global interface symbol.
+int __asan_option_detect_stack_use_after_return; // Global interface symbol.
+uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan.
+
+namespace __asan {
+
+uptr AsanMappingProfile[kAsanMappingProfileSize];
+
+static void AsanDie() {
+ static atomic_uint32_t num_calls;
+ if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
+ // Don't die twice - run a busy loop.
+ while (1) {
+ internal_sched_yield();
+ }
+ }
+ if (common_flags()->print_module_map >= 1)
+ DumpProcessMap();
+
+ WaitForDebugger(flags()->sleep_before_dying, "before dying");
+
+ if (flags()->unmap_shadow_on_exit) {
+ if (kMidMemBeg) {
+ UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg);
+ UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd);
+ } else {
+ if (kHighShadowEnd)
+ UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
+ }
+ }
+}
+
+static void CheckUnwind() {
+ GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_check);
+ stack.Print();
+}
+
+// -------------------------- Globals --------------------- {{{1
+int asan_inited;
+bool asan_init_is_running;
+bool replace_intrin_cached;
+
+#if !ASAN_FIXED_MAPPING
+uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;
+#endif
+
+// -------------------------- Misc ---------------- {{{1
+void ShowStatsAndAbort() {
+ __asan_print_accumulated_stats();
+ Die();
+}
+
+NOINLINE
+static void ReportGenericErrorWrapper(uptr addr, bool is_write, int size,
+ int exp_arg, bool fatal) {
+ GET_CALLER_PC_BP_SP;
+ ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, fatal);
+}
+
+// --------------- LowLevelAllocateCallbac ---------- {{{1
+static void OnLowLevelAllocate(uptr ptr, uptr size) {
+ PoisonShadow(ptr, size, kAsanInternalHeapMagic);
+}
+
+// -------------------------- Run-time entry ------------------- {{{1
+// exported functions
+#define ASAN_REPORT_ERROR(type, is_write, size) \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+void __asan_report_ ## type ## size(uptr addr) { \
+ GET_CALLER_PC_BP_SP; \
+ ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \
+} \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+void __asan_report_exp_ ## type ## size(uptr addr, u32 exp) { \
+ GET_CALLER_PC_BP_SP; \
+ ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \
+} \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+void __asan_report_ ## type ## size ## _noabort(uptr addr) { \
+ GET_CALLER_PC_BP_SP; \
+ ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \
+} \
+
+ASAN_REPORT_ERROR(load, false, 1)
+ASAN_REPORT_ERROR(load, false, 2)
+ASAN_REPORT_ERROR(load, false, 4)
+ASAN_REPORT_ERROR(load, false, 8)
+ASAN_REPORT_ERROR(load, false, 16)
+ASAN_REPORT_ERROR(store, true, 1)
+ASAN_REPORT_ERROR(store, true, 2)
+ASAN_REPORT_ERROR(store, true, 4)
+ASAN_REPORT_ERROR(store, true, 8)
+ASAN_REPORT_ERROR(store, true, 16)
+
+#define ASAN_REPORT_ERROR_N(type, is_write) \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+void __asan_report_ ## type ## _n(uptr addr, uptr size) { \
+ GET_CALLER_PC_BP_SP; \
+ ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \
+} \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+void __asan_report_exp_ ## type ## _n(uptr addr, uptr size, u32 exp) { \
+ GET_CALLER_PC_BP_SP; \
+ ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \
+} \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+void __asan_report_ ## type ## _n_noabort(uptr addr, uptr size) { \
+ GET_CALLER_PC_BP_SP; \
+ ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \
+} \
+
+ASAN_REPORT_ERROR_N(load, false)
+ASAN_REPORT_ERROR_N(store, true)
+
+#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg, fatal) \
+ uptr sp = MEM_TO_SHADOW(addr); \
+ uptr s = size <= ASAN_SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \
+ : *reinterpret_cast<u16 *>(sp); \
+ if (UNLIKELY(s)) { \
+ if (UNLIKELY(size >= ASAN_SHADOW_GRANULARITY || \
+ ((s8)((addr & (ASAN_SHADOW_GRANULARITY - 1)) + size - 1)) >= \
+ (s8)s)) { \
+ ReportGenericErrorWrapper(addr, is_write, size, exp_arg, fatal); \
+ } \
+ }
+
+#define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \
+ extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+ void __asan_##type##size(uptr addr) { \
+ ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, true) \
+ } \
+ extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+ void __asan_exp_##type##size(uptr addr, u32 exp) { \
+ ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp, true) \
+ } \
+ extern "C" NOINLINE INTERFACE_ATTRIBUTE \
+ void __asan_##type##size ## _noabort(uptr addr) { \
+ ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, false) \
+ } \
+
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1)
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2)
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 4)
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 8)
+ASAN_MEMORY_ACCESS_CALLBACK(load, false, 16)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 1)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 2)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 4)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 8)
+ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16)
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_loadN(uptr addr, uptr size) {
+ if ((addr = __asan_region_is_poisoned(addr, size))) {
+ GET_CALLER_PC_BP_SP;
+ ReportGenericError(pc, bp, sp, addr, false, size, 0, true);
+ }
+}
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_exp_loadN(uptr addr, uptr size, u32 exp) {
+ if ((addr = __asan_region_is_poisoned(addr, size))) {
+ GET_CALLER_PC_BP_SP;
+ ReportGenericError(pc, bp, sp, addr, false, size, exp, true);
+ }
+}
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_loadN_noabort(uptr addr, uptr size) {
+ if ((addr = __asan_region_is_poisoned(addr, size))) {
+ GET_CALLER_PC_BP_SP;
+ ReportGenericError(pc, bp, sp, addr, false, size, 0, false);
+ }
+}
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_storeN(uptr addr, uptr size) {
+ if ((addr = __asan_region_is_poisoned(addr, size))) {
+ GET_CALLER_PC_BP_SP;
+ ReportGenericError(pc, bp, sp, addr, true, size, 0, true);
+ }
+}
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_exp_storeN(uptr addr, uptr size, u32 exp) {
+ if ((addr = __asan_region_is_poisoned(addr, size))) {
+ GET_CALLER_PC_BP_SP;
+ ReportGenericError(pc, bp, sp, addr, true, size, exp, true);
+ }
+}
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_storeN_noabort(uptr addr, uptr size) {
+ if ((addr = __asan_region_is_poisoned(addr, size))) {
+ GET_CALLER_PC_BP_SP;
+ ReportGenericError(pc, bp, sp, addr, true, size, 0, false);
+ }
+}
+
+// Force the linker to keep the symbols for various ASan interface functions.
+// We want to keep those in the executable in order to let the instrumented
+// dynamic libraries access the symbol even if it is not used by the executable
+// itself. This should help if the build system is removing dead code at link
+// time.
+static NOINLINE void force_interface_symbols() {
+ volatile int fake_condition = 0; // prevent dead condition elimination.
+ // __asan_report_* functions are noreturn, so we need a switch to prevent
+ // the compiler from removing any of them.
+ // clang-format off
+ switch (fake_condition) {
+ case 1: __asan_report_load1(0); break;
+ case 2: __asan_report_load2(0); break;
+ case 3: __asan_report_load4(0); break;
+ case 4: __asan_report_load8(0); break;
+ case 5: __asan_report_load16(0); break;
+ case 6: __asan_report_load_n(0, 0); break;
+ case 7: __asan_report_store1(0); break;
+ case 8: __asan_report_store2(0); break;
+ case 9: __asan_report_store4(0); break;
+ case 10: __asan_report_store8(0); break;
+ case 11: __asan_report_store16(0); break;
+ case 12: __asan_report_store_n(0, 0); break;
+ case 13: __asan_report_exp_load1(0, 0); break;
+ case 14: __asan_report_exp_load2(0, 0); break;
+ case 15: __asan_report_exp_load4(0, 0); break;
+ case 16: __asan_report_exp_load8(0, 0); break;
+ case 17: __asan_report_exp_load16(0, 0); break;
+ case 18: __asan_report_exp_load_n(0, 0, 0); break;
+ case 19: __asan_report_exp_store1(0, 0); break;
+ case 20: __asan_report_exp_store2(0, 0); break;
+ case 21: __asan_report_exp_store4(0, 0); break;
+ case 22: __asan_report_exp_store8(0, 0); break;
+ case 23: __asan_report_exp_store16(0, 0); break;
+ case 24: __asan_report_exp_store_n(0, 0, 0); break;
+ case 25: __asan_register_globals(nullptr, 0); break;
+ case 26: __asan_unregister_globals(nullptr, 0); break;
+ case 27: __asan_set_death_callback(nullptr); break;
+ case 28: __asan_set_error_report_callback(nullptr); break;
+ case 29: __asan_handle_no_return(); break;
+ case 30: __asan_address_is_poisoned(nullptr); break;
+ case 31: __asan_poison_memory_region(nullptr, 0); break;
+ case 32: __asan_unpoison_memory_region(nullptr, 0); break;
+ case 34: __asan_before_dynamic_init(nullptr); break;
+ case 35: __asan_after_dynamic_init(); break;
+ case 36: __asan_poison_stack_memory(0, 0); break;
+ case 37: __asan_unpoison_stack_memory(0, 0); break;
+ case 38: __asan_region_is_poisoned(0, 0); break;
+ case 39: __asan_describe_address(0); break;
+ case 40: __asan_set_shadow_00(0, 0); break;
+ case 41: __asan_set_shadow_01(0, 0); break;
+ case 42: __asan_set_shadow_02(0, 0); break;
+ case 43: __asan_set_shadow_03(0, 0); break;
+ case 44: __asan_set_shadow_04(0, 0); break;
+ case 45: __asan_set_shadow_05(0, 0); break;
+ case 46: __asan_set_shadow_06(0, 0); break;
+ case 47: __asan_set_shadow_07(0, 0); break;
+ case 48: __asan_set_shadow_f1(0, 0); break;
+ case 49: __asan_set_shadow_f2(0, 0); break;
+ case 50: __asan_set_shadow_f3(0, 0); break;
+ case 51: __asan_set_shadow_f5(0, 0); break;
+ case 52: __asan_set_shadow_f8(0, 0); break;
+ }
+ // clang-format on
+}
+
+static void asan_atexit() {
+ Printf("AddressSanitizer exit stats:\n");
+ __asan_print_accumulated_stats();
+ // Print AsanMappingProfile.
+ for (uptr i = 0; i < kAsanMappingProfileSize; i++) {
+ if (AsanMappingProfile[i] == 0) continue;
+ Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]);
+ }
+}
+
+static void InitializeHighMemEnd() {
+#if !ASAN_FIXED_MAPPING
+ kHighMemEnd = GetMaxUserVirtualAddress();
+ // Increase kHighMemEnd to make sure it's properly
+ // aligned together with kHighMemBeg:
+ kHighMemEnd |= (GetMmapGranularity() << ASAN_SHADOW_SCALE) - 1;
+#endif // !ASAN_FIXED_MAPPING
+ CHECK_EQ((kHighMemBeg % GetMmapGranularity()), 0);
+}
+
+void PrintAddressSpaceLayout() {
+ if (kHighMemBeg) {
+ Printf("|| `[%p, %p]` || HighMem ||\n",
+ (void*)kHighMemBeg, (void*)kHighMemEnd);
+ Printf("|| `[%p, %p]` || HighShadow ||\n",
+ (void*)kHighShadowBeg, (void*)kHighShadowEnd);
+ }
+ if (kMidMemBeg) {
+ Printf("|| `[%p, %p]` || ShadowGap3 ||\n",
+ (void*)kShadowGap3Beg, (void*)kShadowGap3End);
+ Printf("|| `[%p, %p]` || MidMem ||\n",
+ (void*)kMidMemBeg, (void*)kMidMemEnd);
+ Printf("|| `[%p, %p]` || ShadowGap2 ||\n",
+ (void*)kShadowGap2Beg, (void*)kShadowGap2End);
+ Printf("|| `[%p, %p]` || MidShadow ||\n",
+ (void*)kMidShadowBeg, (void*)kMidShadowEnd);
+ }
+ Printf("|| `[%p, %p]` || ShadowGap ||\n",
+ (void*)kShadowGapBeg, (void*)kShadowGapEnd);
+ if (kLowShadowBeg) {
+ Printf("|| `[%p, %p]` || LowShadow ||\n",
+ (void*)kLowShadowBeg, (void*)kLowShadowEnd);
+ Printf("|| `[%p, %p]` || LowMem ||\n",
+ (void*)kLowMemBeg, (void*)kLowMemEnd);
+ }
+ Printf("MemToShadow(shadow): %p %p",
+ (void*)MEM_TO_SHADOW(kLowShadowBeg),
+ (void*)MEM_TO_SHADOW(kLowShadowEnd));
+ if (kHighMemBeg) {
+ Printf(" %p %p",
+ (void*)MEM_TO_SHADOW(kHighShadowBeg),
+ (void*)MEM_TO_SHADOW(kHighShadowEnd));
+ }
+ if (kMidMemBeg) {
+ Printf(" %p %p",
+ (void*)MEM_TO_SHADOW(kMidShadowBeg),
+ (void*)MEM_TO_SHADOW(kMidShadowEnd));
+ }
+ Printf("\n");
+ Printf("redzone=%zu\n", (uptr)flags()->redzone);
+ Printf("max_redzone=%zu\n", (uptr)flags()->max_redzone);
+ Printf("quarantine_size_mb=%zuM\n", (uptr)flags()->quarantine_size_mb);
+ Printf("thread_local_quarantine_size_kb=%zuK\n",
+ (uptr)flags()->thread_local_quarantine_size_kb);
+ Printf("malloc_context_size=%zu\n",
+ (uptr)common_flags()->malloc_context_size);
+
+ Printf("SHADOW_SCALE: %d\n", (int)ASAN_SHADOW_SCALE);
+ Printf("SHADOW_GRANULARITY: %d\n", (int)ASAN_SHADOW_GRANULARITY);
+ Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)ASAN_SHADOW_OFFSET);
+ CHECK(ASAN_SHADOW_SCALE >= 3 && ASAN_SHADOW_SCALE <= 7);
+ if (kMidMemBeg)
+ CHECK(kMidShadowBeg > kLowShadowEnd &&
+ kMidMemBeg > kMidShadowEnd &&
+ kHighShadowBeg > kMidMemEnd);
+}
+
+static void AsanInitInternal() {
+ if (LIKELY(asan_inited)) return;
+ SanitizerToolName = "AddressSanitizer";
+ CHECK(!asan_init_is_running && "ASan init calls itself!");
+ asan_init_is_running = true;
+
+ CacheBinaryName();
+
+ // Initialize flags. This must be done early, because most of the
+ // initialization steps look at flags().
+ InitializeFlags();
+
+ WaitForDebugger(flags()->sleep_before_init, "before init");
+
+ // Stop performing init at this point if we are being loaded via
+ // dlopen() and the platform supports it.
+ if (SANITIZER_SUPPORTS_INIT_FOR_DLOPEN && UNLIKELY(HandleDlopenInit())) {
+ asan_init_is_running = false;
+ VReport(1, "AddressSanitizer init is being performed for dlopen().\n");
+ return;
+ }
+
+ AsanCheckIncompatibleRT();
+ AsanCheckDynamicRTPrereqs();
+ AvoidCVE_2016_2143();
+
+ SetCanPoisonMemory(flags()->poison_heap);
+ SetMallocContextSize(common_flags()->malloc_context_size);
+
+ InitializePlatformExceptionHandlers();
+
+ InitializeHighMemEnd();
+
+ // Make sure we are not statically linked.
+ AsanDoesNotSupportStaticLinkage();
+
+ // Install tool-specific callbacks in sanitizer_common.
+ AddDieCallback(AsanDie);
+ SetCheckUnwindCallback(CheckUnwind);
+ SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
+
+ __sanitizer_set_report_path(common_flags()->log_path);
+
+ __asan_option_detect_stack_use_after_return =
+ flags()->detect_stack_use_after_return;
+
+ __sanitizer::InitializePlatformEarly();
+
+ // Setup internal allocator callback.
+ SetLowLevelAllocateMinAlignment(ASAN_SHADOW_GRANULARITY);
+ SetLowLevelAllocateCallback(OnLowLevelAllocate);
+
+ InitializeAsanInterceptors();
+ CheckASLR();
+
+ // Enable system log ("adb logcat") on Android.
+ // Doing this before interceptors are initialized crashes in:
+ // AsanInitInternal -> android_log_write -> __interceptor_strcmp
+ AndroidLogInit();
+
+ ReplaceSystemMalloc();
+
+ DisableCoreDumperIfNecessary();
+
+ InitializeShadowMemory();
+
+ AsanTSDInit(PlatformTSDDtor);
+ InstallDeadlySignalHandlers(AsanOnDeadlySignal);
+
+ AllocatorOptions allocator_options;
+ allocator_options.SetFrom(flags(), common_flags());
+ InitializeAllocator(allocator_options);
+
+ if (SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL)
+ MaybeStartBackgroudThread();
+
+ // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
+ // should be set to 1 prior to initializing the threads.
+ replace_intrin_cached = flags()->replace_intrin;
+ asan_inited = 1;
+ asan_init_is_running = false;
+
+ if (flags()->atexit)
+ Atexit(asan_atexit);
+
+ InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
+
+ // Now that ASan runtime is (mostly) initialized, deactivate it if
+ // necessary, so that it can be re-activated when requested.
+ if (flags()->start_deactivated)
+ AsanDeactivate();
+
+ // interceptors
+ InitTlsSize();
+
+ // Create main thread.
+ AsanThread *main_thread = CreateMainThread();
+ CHECK_EQ(0, main_thread->tid());
+ force_interface_symbols(); // no-op.
+ SanitizerInitializeUnwinder();
+
+ if (CAN_SANITIZE_LEAKS) {
+ __lsan::InitCommonLsan();
+ InstallAtExitCheckLeaks();
+ }
+
+#if CAN_SANITIZE_UB
+ __ubsan::InitAsPlugin();
+#endif
+
+ InitializeSuppressions();
+
+ if (CAN_SANITIZE_LEAKS) {
+ // LateInitialize() calls dlsym, which can allocate an error string buffer
+ // in the TLS. Let's ignore the allocation to avoid reporting a leak.
+ __lsan::ScopedInterceptorDisabler disabler;
+ Symbolizer::LateInitialize();
+ } else {
+ Symbolizer::LateInitialize();
+ }
+
+ VReport(1, "AddressSanitizer Init done\n");
+
+ WaitForDebugger(flags()->sleep_after_init, "after init");
+}
+
+// Initialize as requested from some part of ASan runtime library (interceptors,
+// allocator, etc).
+void AsanInitFromRtl() {
+ AsanInitInternal();
+}
+
+#if ASAN_DYNAMIC
+// Initialize runtime in case it's LD_PRELOAD-ed into unsanitized executable
+// (and thus normal initializers from .preinit_array or modules haven't run).
+
+class AsanInitializer {
+ public:
+ AsanInitializer() {
+ AsanInitFromRtl();
+ }
+};
+
+static AsanInitializer asan_initializer;
+#endif // ASAN_DYNAMIC
+
+void UnpoisonStack(uptr bottom, uptr top, const char *type) {
+ static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M
+ if (top - bottom > kMaxExpectedCleanupSize) {
+ static bool reported_warning = false;
+ if (reported_warning)
+ return;
+ reported_warning = true;
+ Report(
+ "WARNING: ASan is ignoring requested __asan_handle_no_return: "
+ "stack type: %s top: %p; bottom %p; size: %p (%zd)\n"
+ "False positive error reports may follow\n"
+ "For details see "
+ "https://github.com/google/sanitizers/issues/189\n",
+ type, (void *)top, (void *)bottom, (void *)(top - bottom),
+ top - bottom);
+ return;
+ }
+ PoisonShadow(bottom, RoundUpTo(top - bottom, ASAN_SHADOW_GRANULARITY), 0);
+}
+
+static void UnpoisonDefaultStack() {
+ uptr bottom, top;
+
+ if (AsanThread *curr_thread = GetCurrentThread()) {
+ int local_stack;
+ const uptr page_size = GetPageSizeCached();
+ top = curr_thread->stack_top();
+ bottom = ((uptr)&local_stack - page_size) & ~(page_size - 1);
+ } else {
+ CHECK(!SANITIZER_FUCHSIA);
+ // If we haven't seen this thread, try asking the OS for stack bounds.
+ uptr tls_addr, tls_size, stack_size;
+ GetThreadStackAndTls(/*main=*/false, &bottom, &stack_size, &tls_addr,
+ &tls_size);
+ top = bottom + stack_size;
+ }
+
+ UnpoisonStack(bottom, top, "default");
+}
+
+static void UnpoisonFakeStack() {
+ AsanThread *curr_thread = GetCurrentThread();
+ if (!curr_thread)
+ return;
+ FakeStack *stack = curr_thread->get_fake_stack();
+ if (!stack)
+ return;
+ stack->HandleNoReturn();
+}
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan;
+
+void NOINLINE __asan_handle_no_return() {
+ if (asan_init_is_running)
+ return;
+
+ if (!PlatformUnpoisonStacks())
+ UnpoisonDefaultStack();
+
+ UnpoisonFakeStack();
+}
+
+extern "C" void *__asan_extra_spill_area() {
+ AsanThread *t = GetCurrentThread();
+ CHECK(t);
+ return t->extra_spill_area();
+}
+
+void __asan_handle_vfork(void *sp) {
+ AsanThread *t = GetCurrentThread();
+ CHECK(t);
+ uptr bottom = t->stack_bottom();
+ PoisonShadow(bottom, (uptr)sp - bottom, 0);
+}
+
+void NOINLINE __asan_set_death_callback(void (*callback)(void)) {
+ SetUserDieCallback(callback);
+}
+
+// Initialize as requested from instrumented application code.
+// We use this call as a trigger to wake up ASan from deactivated state.
+void __asan_init() {
+ AsanActivate();
+ AsanInitInternal();
+}
+
+void __asan_version_mismatch_check() {
+ // Do nothing.
+}
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_rtl_static.cpp b/contrib/libs/clang16-rt/lib/asan/asan_rtl_static.cpp
new file mode 100644
index 00000000000..a6f812bb891
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_rtl_static.cpp
@@ -0,0 +1,36 @@
+//===-- asan_static_rtl.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Main file of the ASan run-time library.
+//===----------------------------------------------------------------------===//
+
+// This file is empty for now. Main reason to have it is workaround for Windows
+// build, which complains because no files are part of the asan_static lib.
+
+#include "sanitizer_common/sanitizer_common.h"
+
+#define REPORT_FUNCTION(Name) \
+ extern "C" SANITIZER_WEAK_ATTRIBUTE void Name(__asan::uptr addr); \
+ extern "C" void Name##_asm(uptr addr) { Name(addr); }
+
+namespace __asan {
+
+REPORT_FUNCTION(__asan_report_load1)
+REPORT_FUNCTION(__asan_report_load2)
+REPORT_FUNCTION(__asan_report_load4)
+REPORT_FUNCTION(__asan_report_load8)
+REPORT_FUNCTION(__asan_report_load16)
+REPORT_FUNCTION(__asan_report_store1)
+REPORT_FUNCTION(__asan_report_store2)
+REPORT_FUNCTION(__asan_report_store4)
+REPORT_FUNCTION(__asan_report_store8)
+REPORT_FUNCTION(__asan_report_store16)
+
+} // namespace __asan
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_rtl_x86_64.S b/contrib/libs/clang16-rt/lib/asan/asan_rtl_x86_64.S
new file mode 100644
index 00000000000..d93b5ed2a7f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_rtl_x86_64.S
@@ -0,0 +1,146 @@
+#include "asan_mapping.h"
+#include "sanitizer_common/sanitizer_asm.h"
+
+#if defined(__x86_64__)
+#include "sanitizer_common/sanitizer_platform.h"
+
+.file "asan_rtl_x86_64.S"
+
+#define NAME(n, reg, op, s, i) n##_##op##_##i##_##s##_##reg
+
+#define FNAME(reg, op, s, i) NAME(__asan_check, reg, op, s, i)
+#define RLABEL(reg, op, s, i) NAME(.return, reg, op, s, i)
+#define CLABEL(reg, op, s, i) NAME(.check, reg, op, s, i)
+#define FLABEL(reg, op, s, i) NAME(.fail, reg, op, s, i)
+
+#define BEGINF(reg, op, s, i) \
+.section .text.FNAME(reg, op, s, i),"ax",@progbits ;\
+.globl FNAME(reg, op, s, i) ;\
+.hidden FNAME(reg, op, s, i) ;\
+ASM_TYPE_FUNCTION(FNAME(reg, op, s, i)) ;\
+.cfi_startproc ;\
+FNAME(reg, op, s, i): ;\
+
+#define ENDF .cfi_endproc ;\
+
+// Access check functions for 1,2 and 4 byte types, which require extra checks.
+#define ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, s) \
+ mov %##reg,%r10 ;\
+ shr $0x3,%r10 ;\
+ movsbl ASAN_SHADOW_OFFSET_CONST(%r10),%r10d ;\
+ test %r10d,%r10d ;\
+ jne CLABEL(reg, op, s, add) ;\
+RLABEL(reg, op, s, add): ;\
+ retq ;\
+
+#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, i) \
+CLABEL(reg, op, 1, i): ;\
+ push %rcx ;\
+ mov %##reg,%rcx ;\
+ and $0x7,%ecx ;\
+ cmp %r10d,%ecx ;\
+ pop %rcx ;\
+ jl RLABEL(reg, op, 1, i);\
+ mov %##reg,%rdi ;\
+ jmp __asan_report_##op##1_asm ;\
+
+#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, i) \
+CLABEL(reg, op, 2, i): ;\
+ push %rcx ;\
+ mov %##reg,%rcx ;\
+ and $0x7,%ecx ;\
+ add $0x1,%ecx ;\
+ cmp %r10d,%ecx ;\
+ pop %rcx ;\
+ jl RLABEL(reg, op, 2, i);\
+ mov %##reg,%rdi ;\
+ jmp __asan_report_##op##2_asm ;\
+
+#define ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, i) \
+CLABEL(reg, op, 4, i): ;\
+ push %rcx ;\
+ mov %##reg,%rcx ;\
+ and $0x7,%ecx ;\
+ add $0x3,%ecx ;\
+ cmp %r10d,%ecx ;\
+ pop %rcx ;\
+ jl RLABEL(reg, op, 4, i);\
+ mov %##reg,%rdi ;\
+ jmp __asan_report_##op##4_asm ;\
+
+#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, op) \
+BEGINF(reg, op, 1, add) ;\
+ ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 1) ;\
+ ASAN_MEMORY_ACCESS_EXTRA_CHECK_1(reg, op, add) ;\
+ENDF
+
+#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, op) \
+BEGINF(reg, op, 2, add) ;\
+ ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 2) ;\
+ ASAN_MEMORY_ACCESS_EXTRA_CHECK_2(reg, op, add) ;\
+ENDF
+
+#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, op) \
+BEGINF(reg, op, 4, add) ;\
+ ASAN_MEMORY_ACCESS_INITIAL_CHECK_ADD(reg, op, 4) ;\
+ ASAN_MEMORY_ACCESS_EXTRA_CHECK_4(reg, op, add) ;\
+ENDF
+
+// Access check functions for 8 and 16 byte types: no extra checks required.
+#define ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, s, c) \
+ mov %##reg,%r10 ;\
+ shr $0x3,%r10 ;\
+ ##c $0x0,ASAN_SHADOW_OFFSET_CONST(%r10) ;\
+ jne FLABEL(reg, op, s, add) ;\
+ retq ;\
+
+#define ASAN_MEMORY_ACCESS_FAIL(reg, op, s, i) \
+FLABEL(reg, op, s, i): ;\
+ mov %##reg,%rdi ;\
+ jmp __asan_report_##op##s##_asm;\
+
+#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, op) \
+BEGINF(reg, op, 8, add) ;\
+ ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 8, cmpb) ;\
+ ASAN_MEMORY_ACCESS_FAIL(reg, op, 8, add) ;\
+ENDF
+
+#define ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, op) \
+BEGINF(reg, op, 16, add) ;\
+ ASAN_MEMORY_ACCESS_CHECK_ADD(reg, op, 16, cmpw) ;\
+ ASAN_MEMORY_ACCESS_FAIL(reg, op, 16, add) ;\
+ENDF
+
+#define ASAN_MEMORY_ACCESS_CALLBACKS_ADD(reg) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, load) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_1(reg, store) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, load) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_2(reg, store) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, load) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_4(reg, store) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, load) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_8(reg, store) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, load) \
+ASAN_MEMORY_ACCESS_CALLBACK_ADD_16(reg, store) \
+
+
+// Instantiate all but R10 and R11 callbacks. We are using PLTSafe class with
+// the intrinsic, which guarantees that the code generation will never emit
+// R10 or R11 callback.
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RAX)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBX)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RCX)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDX)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RSI)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RDI)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(RBP)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R8)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R9)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R12)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R13)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R14)
+ASAN_MEMORY_ACCESS_CALLBACKS_ADD(R15)
+
+#endif
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_scariness_score.h b/contrib/libs/clang16-rt/lib/asan/asan_scariness_score.h
new file mode 100644
index 00000000000..3932973c225
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_scariness_score.h
@@ -0,0 +1,73 @@
+//===-- asan_scariness_score.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Compute the level of scariness of the error message.
+// Don't expect any deep science here, just a set of heuristics that suggest
+// that e.g. 1-byte-read-global-buffer-overflow is less scary than
+// 8-byte-write-stack-use-after-return.
+//
+// Every error report has one or more features, such as memory access size,
+// type (read or write), type of accessed memory (e.g. free-d heap, or a global
+// redzone), etc. Every such feature has an int score and a string description.
+// The overall score is the sum of all feature scores and the description
+// is a concatenation of feature descriptions.
+// Examples:
+// 17 (4-byte-read-heap-buffer-overflow)
+// 65 (multi-byte-write-stack-use-after-return)
+// 10 (null-deref)
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_SCARINESS_SCORE_H
+#define ASAN_SCARINESS_SCORE_H
+
+#include "asan_flags.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_libc.h"
+
+namespace __asan {
+struct ScarinessScoreBase {
+ void Clear() {
+ descr[0] = 0;
+ score = 0;
+ }
+ void Scare(int add_to_score, const char *reason) {
+ if (descr[0])
+ internal_strlcat(descr, "-", sizeof(descr));
+ internal_strlcat(descr, reason, sizeof(descr));
+ score += add_to_score;
+ }
+ int GetScore() const { return score; }
+ const char *GetDescription() const { return descr; }
+ void Print() const {
+ if (score && flags()->print_scariness)
+ Printf("SCARINESS: %d (%s)\n", score, descr);
+ }
+ static void PrintSimple(int score, const char *descr) {
+ ScarinessScoreBase SSB;
+ SSB.Clear();
+ SSB.Scare(score, descr);
+ SSB.Print();
+ }
+
+ private:
+ int score;
+ char descr[1024];
+};
+
+struct ScarinessScore : ScarinessScoreBase {
+ ScarinessScore() {
+ Clear();
+ }
+};
+
+} // namespace __asan
+
+#endif // ASAN_SCARINESS_SCORE_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_shadow_setup.cpp b/contrib/libs/clang16-rt/lib/asan/asan_shadow_setup.cpp
new file mode 100644
index 00000000000..fc6de39622b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_shadow_setup.cpp
@@ -0,0 +1,125 @@
+//===-- asan_shadow_setup.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Set up the shadow memory.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+
+// asan_fuchsia.cpp has their own InitializeShadowMemory implementation.
+#if !SANITIZER_FUCHSIA
+
+# include "asan_internal.h"
+# include "asan_mapping.h"
+
+namespace __asan {
+
+static void ProtectGap(uptr addr, uptr size) {
+ if (!flags()->protect_shadow_gap) {
+ // The shadow gap is unprotected, so there is a chance that someone
+ // is actually using this memory. Which means it needs a shadow...
+ uptr GapShadowBeg = RoundDownTo(MEM_TO_SHADOW(addr), GetPageSizeCached());
+ uptr GapShadowEnd =
+ RoundUpTo(MEM_TO_SHADOW(addr + size), GetPageSizeCached()) - 1;
+ if (Verbosity())
+ Printf(
+ "protect_shadow_gap=0:"
+ " not protecting shadow gap, allocating gap's shadow\n"
+ "|| `[%p, %p]` || ShadowGap's shadow ||\n",
+ (void*)GapShadowBeg, (void*)GapShadowEnd);
+ ReserveShadowMemoryRange(GapShadowBeg, GapShadowEnd,
+ "unprotected gap shadow");
+ return;
+ }
+ __sanitizer::ProtectGap(addr, size, kZeroBaseShadowStart,
+ kZeroBaseMaxShadowStart);
+}
+
+static void MaybeReportLinuxPIEBug() {
+#if SANITIZER_LINUX && \
+ (defined(__x86_64__) || defined(__aarch64__) || SANITIZER_RISCV64)
+ Report("This might be related to ELF_ET_DYN_BASE change in Linux 4.12.\n");
+ Report(
+ "See https://github.com/google/sanitizers/issues/856 for possible "
+ "workarounds.\n");
+#endif
+}
+
+void InitializeShadowMemory() {
+ // Set the shadow memory address to uninitialized.
+ __asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
+
+ uptr shadow_start = kLowShadowBeg;
+ // Detect if a dynamic shadow address must used and find a available location
+ // when necessary. When dynamic address is used, the macro |kLowShadowBeg|
+ // expands to |__asan_shadow_memory_dynamic_address| which is
+ // |kDefaultShadowSentinel|.
+ bool full_shadow_is_available = false;
+ if (shadow_start == kDefaultShadowSentinel) {
+ shadow_start = FindDynamicShadowStart();
+ if (SANITIZER_LINUX) full_shadow_is_available = true;
+ }
+ // Update the shadow memory address (potentially) used by instrumentation.
+ __asan_shadow_memory_dynamic_address = shadow_start;
+
+ if (kLowShadowBeg) shadow_start -= GetMmapGranularity();
+
+ if (!full_shadow_is_available)
+ full_shadow_is_available =
+ MemoryRangeIsAvailable(shadow_start, kHighShadowEnd);
+
+#if SANITIZER_LINUX && defined(__x86_64__) && defined(_LP64) && \
+ !ASAN_FIXED_MAPPING
+ if (!full_shadow_is_available) {
+ kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
+ kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
+ }
+#endif
+
+ if (Verbosity()) PrintAddressSpaceLayout();
+
+ if (full_shadow_is_available) {
+ // mmap the low shadow plus at least one page at the left.
+ if (kLowShadowBeg)
+ ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
+ // mmap the high shadow.
+ ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
+ // protect the gap.
+ ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
+ CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
+ } else if (kMidMemBeg &&
+ MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
+ MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
+ CHECK(kLowShadowBeg != kLowShadowEnd);
+ // mmap the low shadow plus at least one page at the left.
+ ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
+ // mmap the mid shadow.
+ ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow");
+ // mmap the high shadow.
+ ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
+ // protect the gaps.
+ ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
+ ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
+ ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);
+ } else {
+ Report(
+ "Shadow memory range interleaves with an existing memory mapping. "
+ "ASan cannot proceed correctly. ABORTING.\n");
+ Report("ASan shadow was supposed to be located in the [%p-%p] range.\n",
+ (void*)shadow_start, (void*)kHighShadowEnd);
+ MaybeReportLinuxPIEBug();
+ DumpProcessMap();
+ Die();
+ }
+}
+
+} // namespace __asan
+
+#endif // !SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_stack.cpp b/contrib/libs/clang16-rt/lib/asan/asan_stack.cpp
new file mode 100644
index 00000000000..048295d6928
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_stack.cpp
@@ -0,0 +1,89 @@
+//===-- asan_stack.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Code for ASan stack trace.
+//===----------------------------------------------------------------------===//
+#include "asan_internal.h"
+#include "asan_stack.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+
+namespace __asan {
+
+static atomic_uint32_t malloc_context_size;
+
+void SetMallocContextSize(u32 size) {
+ atomic_store(&malloc_context_size, size, memory_order_release);
+}
+
+u32 GetMallocContextSize() {
+ return atomic_load(&malloc_context_size, memory_order_acquire);
+}
+
+namespace {
+
+// ScopedUnwinding is a scope for stacktracing member of a context
+class ScopedUnwinding {
+ public:
+ explicit ScopedUnwinding(AsanThread *t) : thread(t) {
+ if (thread) {
+ can_unwind = !thread->isUnwinding();
+ thread->setUnwinding(true);
+ }
+ }
+ ~ScopedUnwinding() {
+ if (thread)
+ thread->setUnwinding(false);
+ }
+
+ bool CanUnwind() const { return can_unwind; }
+
+ private:
+ AsanThread *thread = nullptr;
+ bool can_unwind = true;
+};
+
+} // namespace
+
+} // namespace __asan
+
+void __sanitizer::BufferedStackTrace::UnwindImpl(
+ uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
+ using namespace __asan;
+ size = 0;
+ if (UNLIKELY(!asan_inited))
+ return;
+ request_fast = StackTrace::WillUseFastUnwind(request_fast);
+ AsanThread *t = GetCurrentThread();
+ ScopedUnwinding unwind_scope(t);
+ if (!unwind_scope.CanUnwind())
+ return;
+ if (request_fast) {
+ if (t) {
+ Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(),
+ true);
+ }
+ return;
+ }
+ if (SANITIZER_MIPS && t &&
+ !IsValidFrame(bp, t->stack_top(), t->stack_bottom()))
+ return;
+ Unwind(max_depth, pc, bp, context, t ? t->stack_top() : 0,
+ t ? t->stack_bottom() : 0, false);
+}
+
+// ------------------ Interface -------------- {{{1
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_print_stack_trace() {
+ using namespace __asan;
+ PRINT_CURRENT_STACK();
+}
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_stack.h b/contrib/libs/clang16-rt/lib/asan/asan_stack.h
new file mode 100644
index 00000000000..b9575d2f427
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_stack.h
@@ -0,0 +1,71 @@
+//===-- asan_stack.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan-private header for asan_stack.cpp.
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_STACK_H
+#define ASAN_STACK_H
+
+#include "asan_flags.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+
+namespace __asan {
+
+static const u32 kDefaultMallocContextSize = 30;
+
+void SetMallocContextSize(u32 size);
+u32 GetMallocContextSize();
+
+} // namespace __asan
+
+// NOTE: A Rule of thumb is to retrieve stack trace in the interceptors
+// as early as possible (in functions exposed to the user), as we generally
+// don't want stack trace to contain functions from ASan internals.
+
+#define GET_STACK_TRACE(max_size, fast) \
+ BufferedStackTrace stack; \
+ if (max_size <= 2) { \
+ stack.size = max_size; \
+ if (max_size > 0) { \
+ stack.top_frame_bp = GET_CURRENT_FRAME(); \
+ stack.trace_buffer[0] = StackTrace::GetCurrentPc(); \
+ if (max_size > 1) stack.trace_buffer[1] = GET_CALLER_PC(); \
+ } \
+ } else { \
+ stack.Unwind(StackTrace::GetCurrentPc(), \
+ GET_CURRENT_FRAME(), nullptr, fast, max_size); \
+ }
+
+#define GET_STACK_TRACE_FATAL(pc, bp) \
+ BufferedStackTrace stack; \
+ stack.Unwind(pc, bp, nullptr, \
+ common_flags()->fast_unwind_on_fatal)
+
+#define GET_STACK_TRACE_FATAL_HERE \
+ GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal)
+
+#define GET_STACK_TRACE_THREAD \
+ GET_STACK_TRACE(kStackTraceMax, true)
+
+#define GET_STACK_TRACE_MALLOC \
+ GET_STACK_TRACE(GetMallocContextSize(), common_flags()->fast_unwind_on_malloc)
+
+#define GET_STACK_TRACE_FREE GET_STACK_TRACE_MALLOC
+
+#define PRINT_CURRENT_STACK() \
+ { \
+ GET_STACK_TRACE_FATAL_HERE; \
+ stack.Print(); \
+ }
+
+#endif // ASAN_STACK_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_stats.cpp b/contrib/libs/clang16-rt/lib/asan/asan_stats.cpp
new file mode 100644
index 00000000000..9a715ea76fe
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_stats.cpp
@@ -0,0 +1,173 @@
+//===-- asan_stats.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Code related to statistics collected by AddressSanitizer.
+//===----------------------------------------------------------------------===//
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_stats.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+namespace __asan {
+
+AsanStats::AsanStats() {
+ Clear();
+}
+
+void AsanStats::Clear() {
+ CHECK(REAL(memset));
+ REAL(memset)(this, 0, sizeof(AsanStats));
+}
+
+static void PrintMallocStatsArray(const char *prefix,
+ uptr (&array)[kNumberOfSizeClasses]) {
+ Printf("%s", prefix);
+ for (uptr i = 0; i < kNumberOfSizeClasses; i++) {
+ if (!array[i]) continue;
+ Printf("%zu:%zu; ", i, array[i]);
+ }
+ Printf("\n");
+}
+
+void AsanStats::Print() {
+ Printf("Stats: %zuM malloced (%zuM for red zones) by %zu calls\n",
+ malloced>>20, malloced_redzones>>20, mallocs);
+ Printf("Stats: %zuM realloced by %zu calls\n", realloced>>20, reallocs);
+ Printf("Stats: %zuM freed by %zu calls\n", freed>>20, frees);
+ Printf("Stats: %zuM really freed by %zu calls\n",
+ really_freed>>20, real_frees);
+ Printf("Stats: %zuM (%zuM-%zuM) mmaped; %zu maps, %zu unmaps\n",
+ (mmaped-munmaped)>>20, mmaped>>20, munmaped>>20,
+ mmaps, munmaps);
+
+ PrintMallocStatsArray(" mallocs by size class: ", malloced_by_size);
+ Printf("Stats: malloc large: %zu\n", malloc_large);
+}
+
+void AsanStats::MergeFrom(const AsanStats *stats) {
+ uptr *dst_ptr = reinterpret_cast<uptr*>(this);
+ const uptr *src_ptr = reinterpret_cast<const uptr*>(stats);
+ uptr num_fields = sizeof(*this) / sizeof(uptr);
+ for (uptr i = 0; i < num_fields; i++)
+ dst_ptr[i] += src_ptr[i];
+}
+
+static Mutex print_lock;
+
+static AsanStats unknown_thread_stats(LINKER_INITIALIZED);
+static AsanStats dead_threads_stats(LINKER_INITIALIZED);
+static Mutex dead_threads_stats_lock;
+// Required for malloc_zone_statistics() on OS X. This can't be stored in
+// per-thread AsanStats.
+static uptr max_malloced_memory;
+
+static void MergeThreadStats(ThreadContextBase *tctx_base, void *arg) {
+ AsanStats *accumulated_stats = reinterpret_cast<AsanStats*>(arg);
+ AsanThreadContext *tctx = static_cast<AsanThreadContext*>(tctx_base);
+ if (AsanThread *t = tctx->thread)
+ accumulated_stats->MergeFrom(&t->stats());
+}
+
+static void GetAccumulatedStats(AsanStats *stats) {
+ stats->Clear();
+ {
+ ThreadRegistryLock l(&asanThreadRegistry());
+ asanThreadRegistry()
+ .RunCallbackForEachThreadLocked(MergeThreadStats, stats);
+ }
+ stats->MergeFrom(&unknown_thread_stats);
+ {
+ Lock lock(&dead_threads_stats_lock);
+ stats->MergeFrom(&dead_threads_stats);
+ }
+ // This is not very accurate: we may miss allocation peaks that happen
+ // between two updates of accumulated_stats_. For more accurate bookkeeping
+ // the maximum should be updated on every malloc(), which is unacceptable.
+ if (max_malloced_memory < stats->malloced) {
+ max_malloced_memory = stats->malloced;
+ }
+}
+
+void FlushToDeadThreadStats(AsanStats *stats) {
+ Lock lock(&dead_threads_stats_lock);
+ dead_threads_stats.MergeFrom(stats);
+ stats->Clear();
+}
+
+void FillMallocStatistics(AsanMallocStats *malloc_stats) {
+ AsanStats stats;
+ GetAccumulatedStats(&stats);
+ malloc_stats->blocks_in_use = stats.mallocs;
+ malloc_stats->size_in_use = stats.malloced;
+ malloc_stats->max_size_in_use = max_malloced_memory;
+ malloc_stats->size_allocated = stats.mmaped;
+}
+
+AsanStats &GetCurrentThreadStats() {
+ AsanThread *t = GetCurrentThread();
+ return (t) ? t->stats() : unknown_thread_stats;
+}
+
+static void PrintAccumulatedStats() {
+ AsanStats stats;
+ GetAccumulatedStats(&stats);
+ // Use lock to keep reports from mixing up.
+ Lock lock(&print_lock);
+ stats.Print();
+ StackDepotStats stack_depot_stats = StackDepotGetStats();
+ Printf("Stats: StackDepot: %zd ids; %zdM allocated\n",
+ stack_depot_stats.n_uniq_ids, stack_depot_stats.allocated >> 20);
+ PrintInternalAllocatorStats();
+}
+
+} // namespace __asan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan;
+
+uptr __sanitizer_get_current_allocated_bytes() {
+ AsanStats stats;
+ GetAccumulatedStats(&stats);
+ uptr malloced = stats.malloced;
+ uptr freed = stats.freed;
+ // Return sane value if malloced < freed due to racy
+ // way we update accumulated stats.
+ return (malloced > freed) ? malloced - freed : 1;
+}
+
+uptr __sanitizer_get_heap_size() {
+ AsanStats stats;
+ GetAccumulatedStats(&stats);
+ return stats.mmaped - stats.munmaped;
+}
+
+uptr __sanitizer_get_free_bytes() {
+ AsanStats stats;
+ GetAccumulatedStats(&stats);
+ uptr total_free = stats.mmaped
+ - stats.munmaped
+ + stats.really_freed;
+ uptr total_used = stats.malloced
+ + stats.malloced_redzones;
+ // Return sane value if total_free < total_used due to racy
+ // way we update accumulated stats.
+ return (total_free > total_used) ? total_free - total_used : 1;
+}
+
+uptr __sanitizer_get_unmapped_bytes() {
+ return 0;
+}
+
+void __asan_print_accumulated_stats() {
+ PrintAccumulatedStats();
+}
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_stats.h b/contrib/libs/clang16-rt/lib/asan/asan_stats.h
new file mode 100644
index 00000000000..d6da6534081
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_stats.h
@@ -0,0 +1,71 @@
+//===-- asan_stats.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan-private header for statistics.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_STATS_H
+#define ASAN_STATS_H
+
+#include "asan_allocator.h"
+#include "asan_internal.h"
+
+namespace __asan {
+
+// AsanStats struct is NOT thread-safe.
+// Each AsanThread has its own AsanStats, which are sometimes flushed
+// to the accumulated AsanStats.
+struct AsanStats {
+ // AsanStats must be a struct consisting of uptr fields only.
+ // When merging two AsanStats structs, we treat them as arrays of uptr.
+ uptr mallocs;
+ uptr malloced;
+ uptr malloced_redzones;
+ uptr frees;
+ uptr freed;
+ uptr real_frees;
+ uptr really_freed;
+ uptr reallocs;
+ uptr realloced;
+ uptr mmaps;
+ uptr mmaped;
+ uptr munmaps;
+ uptr munmaped;
+ uptr malloc_large;
+ uptr malloced_by_size[kNumberOfSizeClasses];
+
+ // Ctor for global AsanStats (accumulated stats for dead threads).
+ explicit AsanStats(LinkerInitialized) { }
+ // Creates empty stats.
+ AsanStats();
+
+ void Print(); // Prints formatted stats to stderr.
+ void Clear();
+ void MergeFrom(const AsanStats *stats);
+};
+
+// Returns stats for GetCurrentThread(), or stats for fake "unknown thread"
+// if GetCurrentThread() returns 0.
+AsanStats &GetCurrentThreadStats();
+// Flushes a given stats into accumulated stats of dead threads.
+void FlushToDeadThreadStats(AsanStats *stats);
+
+// A cross-platform equivalent of malloc_statistics_t on Mac OS.
+struct AsanMallocStats {
+ uptr blocks_in_use;
+ uptr size_in_use;
+ uptr max_size_in_use;
+ uptr size_allocated;
+};
+
+void FillMallocStatistics(AsanMallocStats *malloc_stats);
+
+} // namespace __asan
+
+#endif // ASAN_STATS_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_suppressions.cpp b/contrib/libs/clang16-rt/lib/asan/asan_suppressions.cpp
new file mode 100644
index 00000000000..8cb2c3e3b9b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_suppressions.cpp
@@ -0,0 +1,104 @@
+//===-- asan_suppressions.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Issue suppression and suppression-related functions.
+//===----------------------------------------------------------------------===//
+
+#include "asan_suppressions.h"
+
+#include "asan_stack.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+
+namespace __asan {
+
+ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
+static SuppressionContext *suppression_ctx = nullptr;
+static const char kInterceptorName[] = "interceptor_name";
+static const char kInterceptorViaFunction[] = "interceptor_via_fun";
+static const char kInterceptorViaLibrary[] = "interceptor_via_lib";
+static const char kODRViolation[] = "odr_violation";
+static const char *kSuppressionTypes[] = {
+ kInterceptorName, kInterceptorViaFunction, kInterceptorViaLibrary,
+ kODRViolation};
+
+SANITIZER_INTERFACE_WEAK_DEF(const char *, __asan_default_suppressions, void) {
+ return "";
+}
+
+void InitializeSuppressions() {
+ CHECK_EQ(nullptr, suppression_ctx);
+ suppression_ctx = new (suppression_placeholder)
+ SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
+ suppression_ctx->ParseFromFile(flags()->suppressions);
+ if (&__asan_default_suppressions)
+ suppression_ctx->Parse(__asan_default_suppressions());
+}
+
+bool IsInterceptorSuppressed(const char *interceptor_name) {
+ CHECK(suppression_ctx);
+ Suppression *s;
+ // Match "interceptor_name" suppressions.
+ return suppression_ctx->Match(interceptor_name, kInterceptorName, &s);
+}
+
+bool HaveStackTraceBasedSuppressions() {
+ CHECK(suppression_ctx);
+ return suppression_ctx->HasSuppressionType(kInterceptorViaFunction) ||
+ suppression_ctx->HasSuppressionType(kInterceptorViaLibrary);
+}
+
+bool IsODRViolationSuppressed(const char *global_var_name) {
+ CHECK(suppression_ctx);
+ Suppression *s;
+ // Match "odr_violation" suppressions.
+ return suppression_ctx->Match(global_var_name, kODRViolation, &s);
+}
+
+bool IsStackTraceSuppressed(const StackTrace *stack) {
+ if (!HaveStackTraceBasedSuppressions())
+ return false;
+
+ CHECK(suppression_ctx);
+ Symbolizer *symbolizer = Symbolizer::GetOrInit();
+ Suppression *s;
+ for (uptr i = 0; i < stack->size && stack->trace[i]; i++) {
+ uptr addr = stack->trace[i];
+
+ if (suppression_ctx->HasSuppressionType(kInterceptorViaLibrary)) {
+ // Match "interceptor_via_lib" suppressions.
+ if (const char *module_name = symbolizer->GetModuleNameForPc(addr))
+ if (suppression_ctx->Match(module_name, kInterceptorViaLibrary, &s))
+ return true;
+ }
+
+ if (suppression_ctx->HasSuppressionType(kInterceptorViaFunction)) {
+ SymbolizedStack *frames = symbolizer->SymbolizePC(addr);
+ CHECK(frames);
+ for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
+ const char *function_name = cur->info.function;
+ if (!function_name) {
+ continue;
+ }
+ // Match "interceptor_via_fun" suppressions.
+ if (suppression_ctx->Match(function_name, kInterceptorViaFunction,
+ &s)) {
+ frames->ClearAll();
+ return true;
+ }
+ }
+ frames->ClearAll();
+ }
+ }
+ return false;
+}
+
+} // namespace __asan
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_suppressions.h b/contrib/libs/clang16-rt/lib/asan/asan_suppressions.h
new file mode 100644
index 00000000000..121d4ddf187
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_suppressions.h
@@ -0,0 +1,29 @@
+//===-- asan_suppressions.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan-private header for asan_suppressions.cpp.
+//===----------------------------------------------------------------------===//
+#ifndef ASAN_SUPPRESSIONS_H
+#define ASAN_SUPPRESSIONS_H
+
+#include "asan_internal.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+
+namespace __asan {
+
+void InitializeSuppressions();
+bool IsInterceptorSuppressed(const char *interceptor_name);
+bool HaveStackTraceBasedSuppressions();
+bool IsStackTraceSuppressed(const StackTrace *stack);
+bool IsODRViolationSuppressed(const char *global_var_name);
+
+} // namespace __asan
+
+#endif // ASAN_SUPPRESSIONS_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_thread.cpp b/contrib/libs/clang16-rt/lib/asan/asan_thread.cpp
new file mode 100644
index 00000000000..003cd2b9eee
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_thread.cpp
@@ -0,0 +1,610 @@
+//===-- asan_thread.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Thread-related code.
+//===----------------------------------------------------------------------===//
+#include "asan_allocator.h"
+#include "asan_interceptors.h"
+#include "asan_poisoning.h"
+#include "asan_stack.h"
+#include "asan_thread.h"
+#include "asan_mapping.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+#include "lsan/lsan_common.h"
+
+namespace __asan {
+
+// AsanThreadContext implementation.
+
+void AsanThreadContext::OnCreated(void *arg) {
+ CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg);
+ if (args->stack)
+ stack_id = StackDepotPut(*args->stack);
+ thread = args->thread;
+ thread->set_context(this);
+}
+
+void AsanThreadContext::OnFinished() {
+ // Drop the link to the AsanThread object.
+ thread = nullptr;
+}
+
+// MIPS requires aligned address
+static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)];
+static ThreadRegistry *asan_thread_registry;
+
+static Mutex mu_for_thread_context;
+static LowLevelAllocator allocator_for_thread_context;
+
+static ThreadContextBase *GetAsanThreadContext(u32 tid) {
+ Lock lock(&mu_for_thread_context);
+ return new(allocator_for_thread_context) AsanThreadContext(tid);
+}
+
+ThreadRegistry &asanThreadRegistry() {
+ static bool initialized;
+ // Don't worry about thread_safety - this should be called when there is
+ // a single thread.
+ if (!initialized) {
+ // Never reuse ASan threads: we store pointer to AsanThreadContext
+ // in TSD and can't reliably tell when no more TSD destructors will
+ // be called. It would be wrong to reuse AsanThreadContext for another
+ // thread before all TSD destructors will be called for it.
+ asan_thread_registry =
+ new (thread_registry_placeholder) ThreadRegistry(GetAsanThreadContext);
+ initialized = true;
+ }
+ return *asan_thread_registry;
+}
+
+AsanThreadContext *GetThreadContextByTidLocked(u32 tid) {
+ return static_cast<AsanThreadContext *>(
+ asanThreadRegistry().GetThreadLocked(tid));
+}
+
+// AsanThread implementation.
+
+AsanThread *AsanThread::Create(thread_callback_t start_routine, void *arg,
+ u32 parent_tid, StackTrace *stack,
+ bool detached) {
+ uptr PageSize = GetPageSizeCached();
+ uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
+ AsanThread *thread = (AsanThread*)MmapOrDie(size, __func__);
+ thread->start_routine_ = start_routine;
+ thread->arg_ = arg;
+ AsanThreadContext::CreateThreadContextArgs args = {thread, stack};
+ asanThreadRegistry().CreateThread(0, detached, parent_tid, &args);
+
+ return thread;
+}
+
+void AsanThread::TSDDtor(void *tsd) {
+ AsanThreadContext *context = (AsanThreadContext*)tsd;
+ VReport(1, "T%d TSDDtor\n", context->tid);
+ if (context->thread)
+ context->thread->Destroy();
+}
+
+void AsanThread::Destroy() {
+ int tid = this->tid();
+ VReport(1, "T%d exited\n", tid);
+
+ bool was_running =
+ (asanThreadRegistry().FinishThread(tid) == ThreadStatusRunning);
+ if (was_running) {
+ if (AsanThread *thread = GetCurrentThread())
+ CHECK_EQ(this, thread);
+ malloc_storage().CommitBack();
+ if (common_flags()->use_sigaltstack)
+ UnsetAlternateSignalStack();
+ FlushToDeadThreadStats(&stats_);
+ // We also clear the shadow on thread destruction because
+ // some code may still be executing in later TSD destructors
+ // and we don't want it to have any poisoned stack.
+ ClearShadowForThreadStackAndTLS();
+ DeleteFakeStack(tid);
+ } else {
+ CHECK_NE(this, GetCurrentThread());
+ }
+ uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached());
+ UnmapOrDie(this, size);
+ if (was_running)
+ DTLS_Destroy();
+}
+
+void AsanThread::StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom,
+ uptr size) {
+ if (atomic_load(&stack_switching_, memory_order_relaxed)) {
+ Report("ERROR: starting fiber switch while in fiber switch\n");
+ Die();
+ }
+
+ next_stack_bottom_ = bottom;
+ next_stack_top_ = bottom + size;
+ atomic_store(&stack_switching_, 1, memory_order_release);
+
+ FakeStack *current_fake_stack = fake_stack_;
+ if (fake_stack_save)
+ *fake_stack_save = fake_stack_;
+ fake_stack_ = nullptr;
+ SetTLSFakeStack(nullptr);
+ // if fake_stack_save is null, the fiber will die, delete the fakestack
+ if (!fake_stack_save && current_fake_stack)
+ current_fake_stack->Destroy(this->tid());
+}
+
+void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save,
+ uptr *bottom_old,
+ uptr *size_old) {
+ if (!atomic_load(&stack_switching_, memory_order_relaxed)) {
+ Report("ERROR: finishing a fiber switch that has not started\n");
+ Die();
+ }
+
+ if (fake_stack_save) {
+ SetTLSFakeStack(fake_stack_save);
+ fake_stack_ = fake_stack_save;
+ }
+
+ if (bottom_old)
+ *bottom_old = stack_bottom_;
+ if (size_old)
+ *size_old = stack_top_ - stack_bottom_;
+ stack_bottom_ = next_stack_bottom_;
+ stack_top_ = next_stack_top_;
+ atomic_store(&stack_switching_, 0, memory_order_release);
+ next_stack_top_ = 0;
+ next_stack_bottom_ = 0;
+}
+
+inline AsanThread::StackBounds AsanThread::GetStackBounds() const {
+ if (!atomic_load(&stack_switching_, memory_order_acquire)) {
+ // Make sure the stack bounds are fully initialized.
+ if (stack_bottom_ >= stack_top_) return {0, 0};
+ return {stack_bottom_, stack_top_};
+ }
+ char local;
+ const uptr cur_stack = (uptr)&local;
+ // Note: need to check next stack first, because FinishSwitchFiber
+ // may be in process of overwriting stack_top_/bottom_. But in such case
+ // we are already on the next stack.
+ if (cur_stack >= next_stack_bottom_ && cur_stack < next_stack_top_)
+ return {next_stack_bottom_, next_stack_top_};
+ return {stack_bottom_, stack_top_};
+}
+
+uptr AsanThread::stack_top() {
+ return GetStackBounds().top;
+}
+
+uptr AsanThread::stack_bottom() {
+ return GetStackBounds().bottom;
+}
+
+uptr AsanThread::stack_size() {
+ const auto bounds = GetStackBounds();
+ return bounds.top - bounds.bottom;
+}
+
+// We want to create the FakeStack lazily on the first use, but not earlier
+// than the stack size is known and the procedure has to be async-signal safe.
+FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
+ uptr stack_size = this->stack_size();
+ if (stack_size == 0) // stack_size is not yet available, don't use FakeStack.
+ return nullptr;
+ uptr old_val = 0;
+ // fake_stack_ has 3 states:
+ // 0 -- not initialized
+ // 1 -- being initialized
+ // ptr -- initialized
+ // This CAS checks if the state was 0 and if so changes it to state 1,
+ // if that was successful, it initializes the pointer.
+ if (atomic_compare_exchange_strong(
+ reinterpret_cast<atomic_uintptr_t *>(&fake_stack_), &old_val, 1UL,
+ memory_order_relaxed)) {
+ uptr stack_size_log = Log2(RoundUpToPowerOfTwo(stack_size));
+ CHECK_LE(flags()->min_uar_stack_size_log, flags()->max_uar_stack_size_log);
+ stack_size_log =
+ Min(stack_size_log, static_cast<uptr>(flags()->max_uar_stack_size_log));
+ stack_size_log =
+ Max(stack_size_log, static_cast<uptr>(flags()->min_uar_stack_size_log));
+ fake_stack_ = FakeStack::Create(stack_size_log);
+ DCHECK_EQ(GetCurrentThread(), this);
+ SetTLSFakeStack(fake_stack_);
+ return fake_stack_;
+ }
+ return nullptr;
+}
+
+void AsanThread::Init(const InitOptions *options) {
+ DCHECK_NE(tid(), kInvalidTid);
+ next_stack_top_ = next_stack_bottom_ = 0;
+ atomic_store(&stack_switching_, false, memory_order_release);
+ CHECK_EQ(this->stack_size(), 0U);
+ SetThreadStackAndTls(options);
+ if (stack_top_ != stack_bottom_) {
+ CHECK_GT(this->stack_size(), 0U);
+ CHECK(AddrIsInMem(stack_bottom_));
+ CHECK(AddrIsInMem(stack_top_ - 1));
+ }
+ ClearShadowForThreadStackAndTLS();
+ fake_stack_ = nullptr;
+ if (__asan_option_detect_stack_use_after_return &&
+ tid() == GetCurrentTidOrInvalid()) {
+ // AsyncSignalSafeLazyInitFakeStack makes use of threadlocals and must be
+ // called from the context of the thread it is initializing, not its parent.
+ // Most platforms call AsanThread::Init on the newly-spawned thread, but
+ // Fuchsia calls this function from the parent thread. To support that
+ // approach, we avoid calling AsyncSignalSafeLazyInitFakeStack here; it will
+ // be called by the new thread when it first attempts to access the fake
+ // stack.
+ AsyncSignalSafeLazyInitFakeStack();
+ }
+ int local = 0;
+ VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(),
+ (void *)stack_bottom_, (void *)stack_top_, stack_top_ - stack_bottom_,
+ (void *)&local);
+}
+
+// Fuchsia doesn't use ThreadStart.
+// asan_fuchsia.c definies CreateMainThread and SetThreadStackAndTls.
+#if !SANITIZER_FUCHSIA
+
+thread_return_t AsanThread::ThreadStart(tid_t os_id) {
+ Init();
+ asanThreadRegistry().StartThread(tid(), os_id, ThreadType::Regular, nullptr);
+
+ if (common_flags()->use_sigaltstack) SetAlternateSignalStack();
+
+ if (!start_routine_) {
+ // start_routine_ == 0 if we're on the main thread or on one of the
+ // OS X libdispatch worker threads. But nobody is supposed to call
+ // ThreadStart() for the worker threads.
+ CHECK_EQ(tid(), 0);
+ return 0;
+ }
+
+ thread_return_t res = start_routine_(arg_);
+
+ // On POSIX systems we defer this to the TSD destructor. LSan will consider
+ // the thread's memory as non-live from the moment we call Destroy(), even
+ // though that memory might contain pointers to heap objects which will be
+ // cleaned up by a user-defined TSD destructor. Thus, calling Destroy() before
+ // the TSD destructors have run might cause false positives in LSan.
+ if (!SANITIZER_POSIX)
+ this->Destroy();
+
+ return res;
+}
+
+AsanThread *CreateMainThread() {
+ AsanThread *main_thread = AsanThread::Create(
+ /* start_routine */ nullptr, /* arg */ nullptr, /* parent_tid */ kMainTid,
+ /* stack */ nullptr, /* detached */ true);
+ SetCurrentThread(main_thread);
+ main_thread->ThreadStart(internal_getpid());
+ return main_thread;
+}
+
+// This implementation doesn't use the argument, which is just passed down
+// from the caller of Init (which see, above). It's only there to support
+// OS-specific implementations that need more information passed through.
+void AsanThread::SetThreadStackAndTls(const InitOptions *options) {
+ DCHECK_EQ(options, nullptr);
+ uptr tls_size = 0;
+ uptr stack_size = 0;
+ GetThreadStackAndTls(tid() == kMainTid, &stack_bottom_, &stack_size,
+ &tls_begin_, &tls_size);
+ stack_top_ = RoundDownTo(stack_bottom_ + stack_size, ASAN_SHADOW_GRANULARITY);
+ tls_end_ = tls_begin_ + tls_size;
+ dtls_ = DTLS_Get();
+
+ if (stack_top_ != stack_bottom_) {
+ int local;
+ CHECK(AddrIsInStack((uptr)&local));
+ }
+}
+
+#endif // !SANITIZER_FUCHSIA
+
+void AsanThread::ClearShadowForThreadStackAndTLS() {
+ if (stack_top_ != stack_bottom_)
+ PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
+ if (tls_begin_ != tls_end_) {
+ uptr tls_begin_aligned = RoundDownTo(tls_begin_, ASAN_SHADOW_GRANULARITY);
+ uptr tls_end_aligned = RoundUpTo(tls_end_, ASAN_SHADOW_GRANULARITY);
+ FastPoisonShadow(tls_begin_aligned, tls_end_aligned - tls_begin_aligned, 0);
+ }
+}
+
+bool AsanThread::GetStackFrameAccessByAddr(uptr addr,
+ StackFrameAccess *access) {
+ if (stack_top_ == stack_bottom_)
+ return false;
+
+ uptr bottom = 0;
+ if (AddrIsInStack(addr)) {
+ bottom = stack_bottom();
+ } else if (FakeStack *fake_stack = get_fake_stack()) {
+ bottom = fake_stack->AddrIsInFakeStack(addr);
+ CHECK(bottom);
+ access->offset = addr - bottom;
+ access->frame_pc = ((uptr*)bottom)[2];
+ access->frame_descr = (const char *)((uptr*)bottom)[1];
+ return true;
+ }
+ uptr aligned_addr = RoundDownTo(addr, SANITIZER_WORDSIZE / 8); // align addr.
+ uptr mem_ptr = RoundDownTo(aligned_addr, ASAN_SHADOW_GRANULARITY);
+ u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
+ u8 *shadow_bottom = (u8*)MemToShadow(bottom);
+
+ while (shadow_ptr >= shadow_bottom &&
+ *shadow_ptr != kAsanStackLeftRedzoneMagic) {
+ shadow_ptr--;
+ mem_ptr -= ASAN_SHADOW_GRANULARITY;
+ }
+
+ while (shadow_ptr >= shadow_bottom &&
+ *shadow_ptr == kAsanStackLeftRedzoneMagic) {
+ shadow_ptr--;
+ mem_ptr -= ASAN_SHADOW_GRANULARITY;
+ }
+
+ if (shadow_ptr < shadow_bottom) {
+ return false;
+ }
+
+ uptr *ptr = (uptr *)(mem_ptr + ASAN_SHADOW_GRANULARITY);
+ CHECK(ptr[0] == kCurrentStackFrameMagic);
+ access->offset = addr - (uptr)ptr;
+ access->frame_pc = ptr[2];
+ access->frame_descr = (const char*)ptr[1];
+ return true;
+}
+
+uptr AsanThread::GetStackVariableShadowStart(uptr addr) {
+ uptr bottom = 0;
+ if (AddrIsInStack(addr)) {
+ bottom = stack_bottom();
+ } else if (FakeStack *fake_stack = get_fake_stack()) {
+ bottom = fake_stack->AddrIsInFakeStack(addr);
+ if (bottom == 0) {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ uptr aligned_addr = RoundDownTo(addr, SANITIZER_WORDSIZE / 8); // align addr.
+ u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
+ u8 *shadow_bottom = (u8*)MemToShadow(bottom);
+
+ while (shadow_ptr >= shadow_bottom &&
+ (*shadow_ptr != kAsanStackLeftRedzoneMagic &&
+ *shadow_ptr != kAsanStackMidRedzoneMagic &&
+ *shadow_ptr != kAsanStackRightRedzoneMagic))
+ shadow_ptr--;
+
+ return (uptr)shadow_ptr + 1;
+}
+
+bool AsanThread::AddrIsInStack(uptr addr) {
+ const auto bounds = GetStackBounds();
+ return addr >= bounds.bottom && addr < bounds.top;
+}
+
+static bool ThreadStackContainsAddress(ThreadContextBase *tctx_base,
+ void *addr) {
+ AsanThreadContext *tctx = static_cast<AsanThreadContext *>(tctx_base);
+ AsanThread *t = tctx->thread;
+ if (!t)
+ return false;
+ if (t->AddrIsInStack((uptr)addr))
+ return true;
+ FakeStack *fake_stack = t->get_fake_stack();
+ if (!fake_stack)
+ return false;
+ return fake_stack->AddrIsInFakeStack((uptr)addr);
+}
+
+AsanThread *GetCurrentThread() {
+ AsanThreadContext *context =
+ reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
+ if (!context) {
+ if (SANITIZER_ANDROID) {
+ // On Android, libc constructor is called _after_ asan_init, and cleans up
+ // TSD. Try to figure out if this is still the main thread by the stack
+ // address. We are not entirely sure that we have correct main thread
+ // limits, so only do this magic on Android, and only if the found thread
+ // is the main thread.
+ AsanThreadContext *tctx = GetThreadContextByTidLocked(kMainTid);
+ if (tctx && ThreadStackContainsAddress(tctx, &context)) {
+ SetCurrentThread(tctx->thread);
+ return tctx->thread;
+ }
+ }
+ return nullptr;
+ }
+ return context->thread;
+}
+
+void SetCurrentThread(AsanThread *t) {
+ CHECK(t->context());
+ VReport(2, "SetCurrentThread: %p for thread %p\n", (void *)t->context(),
+ (void *)GetThreadSelf());
+ // Make sure we do not reset the current AsanThread.
+ CHECK_EQ(0, AsanTSDGet());
+ AsanTSDSet(t->context());
+ CHECK_EQ(t->context(), AsanTSDGet());
+}
+
+u32 GetCurrentTidOrInvalid() {
+ AsanThread *t = GetCurrentThread();
+ return t ? t->tid() : kInvalidTid;
+}
+
+AsanThread *FindThreadByStackAddress(uptr addr) {
+ asanThreadRegistry().CheckLocked();
+ AsanThreadContext *tctx = static_cast<AsanThreadContext *>(
+ asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress,
+ (void *)addr));
+ return tctx ? tctx->thread : nullptr;
+}
+
+void EnsureMainThreadIDIsCorrect() {
+ AsanThreadContext *context =
+ reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
+ if (context && (context->tid == kMainTid))
+ context->os_id = GetTid();
+}
+
+__asan::AsanThread *GetAsanThreadByOsIDLocked(tid_t os_id) {
+ __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>(
+ __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id));
+ if (!context) return nullptr;
+ return context->thread;
+}
+} // namespace __asan
+
+// --- Implementation of LSan-specific functions --- {{{1
+namespace __lsan {
+void LockThreadRegistry() { __asan::asanThreadRegistry().Lock(); }
+
+void UnlockThreadRegistry() { __asan::asanThreadRegistry().Unlock(); }
+
+static ThreadRegistry *GetAsanThreadRegistryLocked() {
+ __asan::asanThreadRegistry().CheckLocked();
+ return &__asan::asanThreadRegistry();
+}
+
+void EnsureMainThreadIDIsCorrect() { __asan::EnsureMainThreadIDIsCorrect(); }
+
+bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
+ uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
+ uptr *cache_end, DTLS **dtls) {
+ __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
+ if (!t) return false;
+ *stack_begin = t->stack_bottom();
+ *stack_end = t->stack_top();
+ *tls_begin = t->tls_begin();
+ *tls_end = t->tls_end();
+ // ASan doesn't keep allocator caches in TLS, so these are unused.
+ *cache_begin = 0;
+ *cache_end = 0;
+ *dtls = t->dtls();
+ return true;
+}
+
+void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {}
+
+void GetThreadExtraStackRangesLocked(tid_t os_id,
+ InternalMmapVector<Range> *ranges) {
+ __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
+ if (!t)
+ return;
+ __asan::FakeStack *fake_stack = t->get_fake_stack();
+ if (!fake_stack)
+ return;
+
+ fake_stack->ForEachFakeFrame(
+ [](uptr begin, uptr end, void *arg) {
+ reinterpret_cast<InternalMmapVector<Range> *>(arg)->push_back(
+ {begin, end});
+ },
+ ranges);
+}
+
+void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges) {
+ GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
+ [](ThreadContextBase *tctx, void *arg) {
+ GetThreadExtraStackRangesLocked(
+ tctx->os_id, reinterpret_cast<InternalMmapVector<Range> *>(arg));
+ },
+ ranges);
+}
+
+void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs) {
+ GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
+ [](ThreadContextBase *tctx, void *ptrs) {
+ // Look for the arg pointer of threads that have been created or are
+ // running. This is necessary to prevent false positive leaks due to the
+ // AsanThread holding the only live reference to a heap object. This
+ // can happen because the `pthread_create()` interceptor doesn't wait
+ // for the child thread to start before returning and thus loosing the
+ // the only live reference to the heap object on the stack.
+
+ __asan::AsanThreadContext *atctx =
+ static_cast<__asan::AsanThreadContext *>(tctx);
+
+ // Note ThreadStatusRunning is required because there is a small window
+ // where the thread status switches to `ThreadStatusRunning` but the
+ // `arg` pointer still isn't on the stack yet.
+ if (atctx->status != ThreadStatusCreated &&
+ atctx->status != ThreadStatusRunning)
+ return;
+
+ uptr thread_arg = reinterpret_cast<uptr>(atctx->thread->get_arg());
+ if (!thread_arg)
+ return;
+
+ auto ptrsVec = reinterpret_cast<InternalMmapVector<uptr> *>(ptrs);
+ ptrsVec->push_back(thread_arg);
+ },
+ ptrs);
+}
+
+void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads) {
+ GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
+ [](ThreadContextBase *tctx, void *threads) {
+ if (tctx->status == ThreadStatusRunning)
+ reinterpret_cast<InternalMmapVector<tid_t> *>(threads)->push_back(
+ tctx->os_id);
+ },
+ threads);
+}
+
+void FinishThreadLocked(u32 tid) {
+ GetAsanThreadRegistryLocked()->FinishThread(tid);
+}
+
+} // namespace __lsan
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __asan;
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_start_switch_fiber(void **fakestacksave, const void *bottom,
+ uptr size) {
+ AsanThread *t = GetCurrentThread();
+ if (!t) {
+ VReport(1, "__asan_start_switch_fiber called from unknown thread\n");
+ return;
+ }
+ t->StartSwitchFiber((FakeStack**)fakestacksave, (uptr)bottom, size);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_finish_switch_fiber(void* fakestack,
+ const void **bottom_old,
+ uptr *size_old) {
+ AsanThread *t = GetCurrentThread();
+ if (!t) {
+ VReport(1, "__asan_finish_switch_fiber called from unknown thread\n");
+ return;
+ }
+ t->FinishSwitchFiber((FakeStack*)fakestack,
+ (uptr*)bottom_old,
+ (uptr*)size_old);
+}
+}
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_thread.h b/contrib/libs/clang16-rt/lib/asan/asan_thread.h
new file mode 100644
index 00000000000..801a3960ec6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_thread.h
@@ -0,0 +1,188 @@
+//===-- asan_thread.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan-private header for asan_thread.cpp.
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_THREAD_H
+#define ASAN_THREAD_H
+
+#include "asan_allocator.h"
+#include "asan_internal.h"
+#include "asan_fake_stack.h"
+#include "asan_stats.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
+
+namespace __sanitizer {
+struct DTLS;
+} // namespace __sanitizer
+
+namespace __asan {
+
+class AsanThread;
+
+// These objects are created for every thread and are never deleted,
+// so we can find them by tid even if the thread is long dead.
+class AsanThreadContext final : public ThreadContextBase {
+ public:
+ explicit AsanThreadContext(int tid)
+ : ThreadContextBase(tid), announced(false),
+ destructor_iterations(GetPthreadDestructorIterations()), stack_id(0),
+ thread(nullptr) {}
+ bool announced;
+ u8 destructor_iterations;
+ u32 stack_id;
+ AsanThread *thread;
+
+ void OnCreated(void *arg) override;
+ void OnFinished() override;
+
+ struct CreateThreadContextArgs {
+ AsanThread *thread;
+ StackTrace *stack;
+ };
+};
+
+// AsanThreadContext objects are never freed, so we need many of them.
+COMPILER_CHECK(sizeof(AsanThreadContext) <= 256);
+
+// AsanThread are stored in TSD and destroyed when the thread dies.
+class AsanThread {
+ public:
+ static AsanThread *Create(thread_callback_t start_routine, void *arg,
+ u32 parent_tid, StackTrace *stack, bool detached);
+ static void TSDDtor(void *tsd);
+ void Destroy();
+
+ struct InitOptions;
+ void Init(const InitOptions *options = nullptr);
+
+ thread_return_t ThreadStart(tid_t os_id);
+
+ uptr stack_top();
+ uptr stack_bottom();
+ uptr stack_size();
+ uptr tls_begin() { return tls_begin_; }
+ uptr tls_end() { return tls_end_; }
+ DTLS *dtls() { return dtls_; }
+ u32 tid() { return context_->tid; }
+ AsanThreadContext *context() { return context_; }
+ void set_context(AsanThreadContext *context) { context_ = context; }
+
+ struct StackFrameAccess {
+ uptr offset;
+ uptr frame_pc;
+ const char *frame_descr;
+ };
+ bool GetStackFrameAccessByAddr(uptr addr, StackFrameAccess *access);
+
+ // Returns a pointer to the start of the stack variable's shadow memory.
+ uptr GetStackVariableShadowStart(uptr addr);
+
+ bool AddrIsInStack(uptr addr);
+
+ void DeleteFakeStack(int tid) {
+ if (!fake_stack_) return;
+ FakeStack *t = fake_stack_;
+ fake_stack_ = nullptr;
+ SetTLSFakeStack(nullptr);
+ t->Destroy(tid);
+ }
+
+ void StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom, uptr size);
+ void FinishSwitchFiber(FakeStack *fake_stack_save, uptr *bottom_old,
+ uptr *size_old);
+
+ FakeStack *get_fake_stack() {
+ if (atomic_load(&stack_switching_, memory_order_relaxed))
+ return nullptr;
+ if (reinterpret_cast<uptr>(fake_stack_) <= 1)
+ return nullptr;
+ return fake_stack_;
+ }
+
+ FakeStack *get_or_create_fake_stack() {
+ if (atomic_load(&stack_switching_, memory_order_relaxed))
+ return nullptr;
+ if (reinterpret_cast<uptr>(fake_stack_) <= 1)
+ return AsyncSignalSafeLazyInitFakeStack();
+ return fake_stack_;
+ }
+
+ // True is this thread is currently unwinding stack (i.e. collecting a stack
+ // trace). Used to prevent deadlocks on platforms where libc unwinder calls
+ // malloc internally. See PR17116 for more details.
+ bool isUnwinding() const { return unwinding_; }
+ void setUnwinding(bool b) { unwinding_ = b; }
+
+ AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
+ AsanStats &stats() { return stats_; }
+
+ void *extra_spill_area() { return &extra_spill_area_; }
+
+ void *get_arg() { return arg_; }
+
+ private:
+ // NOTE: There is no AsanThread constructor. It is allocated
+ // via mmap() and *must* be valid in zero-initialized state.
+
+ void SetThreadStackAndTls(const InitOptions *options);
+
+ void ClearShadowForThreadStackAndTLS();
+ FakeStack *AsyncSignalSafeLazyInitFakeStack();
+
+ struct StackBounds {
+ uptr bottom;
+ uptr top;
+ };
+ StackBounds GetStackBounds() const;
+
+ AsanThreadContext *context_;
+ thread_callback_t start_routine_;
+ void *arg_;
+
+ uptr stack_top_;
+ uptr stack_bottom_;
+ // these variables are used when the thread is about to switch stack
+ uptr next_stack_top_;
+ uptr next_stack_bottom_;
+ // true if switching is in progress
+ atomic_uint8_t stack_switching_;
+
+ uptr tls_begin_;
+ uptr tls_end_;
+ DTLS *dtls_;
+
+ FakeStack *fake_stack_;
+ AsanThreadLocalMallocStorage malloc_storage_;
+ AsanStats stats_;
+ bool unwinding_;
+ uptr extra_spill_area_;
+};
+
+// Returns a single instance of registry.
+ThreadRegistry &asanThreadRegistry();
+
+// Must be called under ThreadRegistryLock.
+AsanThreadContext *GetThreadContextByTidLocked(u32 tid);
+
+// Get the current thread. May return 0.
+AsanThread *GetCurrentThread();
+void SetCurrentThread(AsanThread *t);
+u32 GetCurrentTidOrInvalid();
+AsanThread *FindThreadByStackAddress(uptr addr);
+
+// Used to handle fork().
+void EnsureMainThreadIDIsCorrect();
+} // namespace __asan
+
+#endif // ASAN_THREAD_H
diff --git a/contrib/libs/clang16-rt/lib/asan/asan_win.cpp b/contrib/libs/clang16-rt/lib/asan/asan_win.cpp
new file mode 100644
index 00000000000..7dbd7ab98a1
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/asan_win.cpp
@@ -0,0 +1,400 @@
+//===-- asan_win.cpp
+//------------------------------------------------------===//>
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific details.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_WINDOWS
+# define WIN32_LEAN_AND_MEAN
+# include <stdlib.h>
+# include <windows.h>
+
+# include "asan_interceptors.h"
+# include "asan_internal.h"
+# include "asan_mapping.h"
+# include "asan_report.h"
+# include "asan_stack.h"
+# include "asan_thread.h"
+# include "sanitizer_common/sanitizer_libc.h"
+# include "sanitizer_common/sanitizer_mutex.h"
+# include "sanitizer_common/sanitizer_win.h"
+# include "sanitizer_common/sanitizer_win_defs.h"
+
+using namespace __asan;
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+int __asan_should_detect_stack_use_after_return() {
+ __asan_init();
+ return __asan_option_detect_stack_use_after_return;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __asan_get_shadow_memory_dynamic_address() {
+ __asan_init();
+ return __asan_shadow_memory_dynamic_address;
+}
+} // extern "C"
+
+// ---------------------- Windows-specific interceptors ---------------- {{{
+static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
+static LPTOP_LEVEL_EXCEPTION_FILTER user_seh_handler;
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE long __asan_unhandled_exception_filter(
+ EXCEPTION_POINTERS *info) {
+ EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
+ CONTEXT *context = info->ContextRecord;
+
+ // FIXME: Handle EXCEPTION_STACK_OVERFLOW here.
+
+ SignalContext sig(exception_record, context);
+ ReportDeadlySignal(sig);
+ UNREACHABLE("returned from reporting deadly signal");
+}
+
+// Wrapper SEH Handler. If the exception should be handled by asan, we call
+// __asan_unhandled_exception_filter, otherwise, we execute the user provided
+// exception handler or the default.
+static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
+ DWORD exception_code = info->ExceptionRecord->ExceptionCode;
+ if (__sanitizer::IsHandledDeadlyException(exception_code))
+ return __asan_unhandled_exception_filter(info);
+ if (user_seh_handler)
+ return user_seh_handler(info);
+ // Bubble out to the default exception filter.
+ if (default_seh_handler)
+ return default_seh_handler(info);
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+INTERCEPTOR_WINAPI(LPTOP_LEVEL_EXCEPTION_FILTER, SetUnhandledExceptionFilter,
+ LPTOP_LEVEL_EXCEPTION_FILTER ExceptionFilter) {
+ CHECK(REAL(SetUnhandledExceptionFilter));
+ if (ExceptionFilter == &SEHHandler)
+ return REAL(SetUnhandledExceptionFilter)(ExceptionFilter);
+ // We record the user provided exception handler to be called for all the
+ // exceptions unhandled by asan.
+ Swap(ExceptionFilter, user_seh_handler);
+ return ExceptionFilter;
+}
+
+INTERCEPTOR_WINAPI(void, RtlRaiseException, EXCEPTION_RECORD *ExceptionRecord) {
+ CHECK(REAL(RtlRaiseException));
+ // This is a noreturn function, unless it's one of the exceptions raised to
+ // communicate with the debugger, such as the one from OutputDebugString.
+ if (ExceptionRecord->ExceptionCode != DBG_PRINTEXCEPTION_C)
+ __asan_handle_no_return();
+ REAL(RtlRaiseException)(ExceptionRecord);
+}
+
+INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
+ CHECK(REAL(RaiseException));
+ __asan_handle_no_return();
+ REAL(RaiseException)(a, b, c, d);
+}
+
+#ifdef _WIN64
+
+INTERCEPTOR_WINAPI(EXCEPTION_DISPOSITION, __C_specific_handler,
+ _EXCEPTION_RECORD *a, void *b, _CONTEXT *c,
+ _DISPATCHER_CONTEXT *d) {
+ CHECK(REAL(__C_specific_handler));
+ __asan_handle_no_return();
+ return REAL(__C_specific_handler)(a, b, c, d);
+}
+
+#else
+
+INTERCEPTOR(int, _except_handler3, void *a, void *b, void *c, void *d) {
+ CHECK(REAL(_except_handler3));
+ __asan_handle_no_return();
+ return REAL(_except_handler3)(a, b, c, d);
+}
+
+#if ASAN_DYNAMIC
+// This handler is named differently in -MT and -MD CRTs.
+#define _except_handler4 _except_handler4_common
+#endif
+INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
+ CHECK(REAL(_except_handler4));
+ __asan_handle_no_return();
+ return REAL(_except_handler4)(a, b, c, d);
+}
+#endif
+
+static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
+ AsanThread *t = (AsanThread *)arg;
+ SetCurrentThread(t);
+ return t->ThreadStart(GetTid());
+}
+
+INTERCEPTOR_WINAPI(HANDLE, CreateThread, LPSECURITY_ATTRIBUTES security,
+ SIZE_T stack_size, LPTHREAD_START_ROUTINE start_routine,
+ void *arg, DWORD thr_flags, DWORD *tid) {
+ // Strict init-order checking is thread-hostile.
+ if (flags()->strict_init_order)
+ StopInitOrderChecking();
+ GET_STACK_TRACE_THREAD;
+ // FIXME: The CreateThread interceptor is not the same as a pthread_create
+ // one. This is a bandaid fix for PR22025.
+ bool detached = false; // FIXME: how can we determine it on Windows?
+ u32 current_tid = GetCurrentTidOrInvalid();
+ AsanThread *t =
+ AsanThread::Create(start_routine, arg, current_tid, &stack, detached);
+ return REAL(CreateThread)(security, stack_size, asan_thread_start, t,
+ thr_flags, tid);
+}
+
+// }}}
+
+namespace __asan {
+
+void InitializePlatformInterceptors() {
+ // The interceptors were not designed to be removable, so we have to keep this
+ // module alive for the life of the process.
+ HMODULE pinned;
+ CHECK(GetModuleHandleExW(
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN,
+ (LPCWSTR)&InitializePlatformInterceptors, &pinned));
+
+ ASAN_INTERCEPT_FUNC(CreateThread);
+ ASAN_INTERCEPT_FUNC(SetUnhandledExceptionFilter);
+
+#ifdef _WIN64
+ ASAN_INTERCEPT_FUNC(__C_specific_handler);
+#else
+ ASAN_INTERCEPT_FUNC(_except_handler3);
+ ASAN_INTERCEPT_FUNC(_except_handler4);
+#endif
+
+ // Try to intercept kernel32!RaiseException, and if that fails, intercept
+ // ntdll!RtlRaiseException instead.
+ if (!::__interception::OverrideFunction("RaiseException",
+ (uptr)WRAP(RaiseException),
+ (uptr *)&REAL(RaiseException))) {
+ CHECK(::__interception::OverrideFunction("RtlRaiseException",
+ (uptr)WRAP(RtlRaiseException),
+ (uptr *)&REAL(RtlRaiseException)));
+ }
+}
+
+void InstallAtExitCheckLeaks() {}
+
+void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
+ UNIMPLEMENTED();
+}
+
+void FlushUnneededASanShadowMemory(uptr p, uptr size) {
+ // Since asan's mapping is compacting, the shadow chunk may be
+ // not page-aligned, so we only flush the page-aligned portion.
+ ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
+}
+
+// ---------------------- TSD ---------------- {{{
+static bool tsd_key_inited = false;
+
+static __declspec(thread) void *fake_tsd = 0;
+
+// https://docs.microsoft.com/en-us/windows/desktop/api/winternl/ns-winternl-_teb
+// "[This structure may be altered in future versions of Windows. Applications
+// should use the alternate functions listed in this topic.]"
+typedef struct _TEB {
+ PVOID Reserved1[12];
+ // PVOID ThreadLocalStoragePointer; is here, at the last field in Reserved1.
+ PVOID ProcessEnvironmentBlock;
+ PVOID Reserved2[399];
+ BYTE Reserved3[1952];
+ PVOID TlsSlots[64];
+ BYTE Reserved4[8];
+ PVOID Reserved5[26];
+ PVOID ReservedForOle;
+ PVOID Reserved6[4];
+ PVOID TlsExpansionSlots;
+} TEB, *PTEB;
+
+constexpr size_t TEB_RESERVED_FIELDS_THREAD_LOCAL_STORAGE_OFFSET = 11;
+BOOL IsTlsInitialized() {
+ PTEB teb = (PTEB)NtCurrentTeb();
+ return teb->Reserved1[TEB_RESERVED_FIELDS_THREAD_LOCAL_STORAGE_OFFSET] !=
+ nullptr;
+}
+
+void AsanTSDInit(void (*destructor)(void *tsd)) {
+ // FIXME: we're ignoring the destructor for now.
+ tsd_key_inited = true;
+}
+
+void *AsanTSDGet() {
+ CHECK(tsd_key_inited);
+ return IsTlsInitialized() ? fake_tsd : nullptr;
+}
+
+void AsanTSDSet(void *tsd) {
+ CHECK(tsd_key_inited);
+ fake_tsd = tsd;
+}
+
+void PlatformTSDDtor(void *tsd) { AsanThread::TSDDtor(tsd); }
+// }}}
+
+// ---------------------- Various stuff ---------------- {{{
+void *AsanDoesNotSupportStaticLinkage() {
+#if defined(_DEBUG)
+#error Please build the runtime with a non-debug CRT: /MD or /MT
+#endif
+ return 0;
+}
+
+uptr FindDynamicShadowStart() {
+ return MapDynamicShadow(MemToShadowSize(kHighMemEnd), ASAN_SHADOW_SCALE,
+ /*min_shadow_base_alignment*/ 0, kHighMemEnd);
+}
+
+void AsanCheckDynamicRTPrereqs() {}
+
+void AsanCheckIncompatibleRT() {}
+
+void AsanOnDeadlySignal(int, void *siginfo, void *context) { UNIMPLEMENTED(); }
+
+bool PlatformUnpoisonStacks() { return false; }
+
+#if SANITIZER_WINDOWS64
+// Exception handler for dealing with shadow memory.
+static LONG CALLBACK
+ShadowExceptionHandler(PEXCEPTION_POINTERS exception_pointers) {
+ uptr page_size = GetPageSizeCached();
+ // Only handle access violations.
+ if (exception_pointers->ExceptionRecord->ExceptionCode !=
+ EXCEPTION_ACCESS_VIOLATION ||
+ exception_pointers->ExceptionRecord->NumberParameters < 2) {
+ __asan_handle_no_return();
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ // Only handle access violations that land within the shadow memory.
+ uptr addr =
+ (uptr)(exception_pointers->ExceptionRecord->ExceptionInformation[1]);
+
+ // Check valid shadow range.
+ if (!AddrIsInShadow(addr)) {
+ __asan_handle_no_return();
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ // This is an access violation while trying to read from the shadow. Commit
+ // the relevant page and let execution continue.
+
+ // Determine the address of the page that is being accessed.
+ uptr page = RoundDownTo(addr, page_size);
+
+ // Commit the page.
+ uptr result =
+ (uptr)::VirtualAlloc((LPVOID)page, page_size, MEM_COMMIT, PAGE_READWRITE);
+ if (result != page)
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ // The page mapping succeeded, so continue execution as usual.
+ return EXCEPTION_CONTINUE_EXECUTION;
+}
+
+#endif
+
+void InitializePlatformExceptionHandlers() {
+#if SANITIZER_WINDOWS64
+ // On Win64, we map memory on demand with access violation handler.
+ // Install our exception handler.
+ CHECK(AddVectoredExceptionHandler(TRUE, &ShadowExceptionHandler));
+#endif
+}
+
+bool IsSystemHeapAddress(uptr addr) {
+ return ::HeapValidate(GetProcessHeap(), 0, (void *)addr) != FALSE;
+}
+
+// We want to install our own exception handler (EH) to print helpful reports
+// on access violations and whatnot. Unfortunately, the CRT initializers assume
+// they are run before any user code and drop any previously-installed EHs on
+// the floor, so we can't install our handler inside __asan_init.
+// (See crt0dat.c in the CRT sources for the details)
+//
+// Things get even more complicated with the dynamic runtime, as it finishes its
+// initialization before the .exe module CRT begins to initialize.
+//
+// For the static runtime (-MT), it's enough to put a callback to
+// __asan_set_seh_filter in the last section for C initializers.
+//
+// For the dynamic runtime (-MD), we want link the same
+// asan_dynamic_runtime_thunk.lib to all the modules, thus __asan_set_seh_filter
+// will be called for each instrumented module. This ensures that at least one
+// __asan_set_seh_filter call happens after the .exe module CRT is initialized.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE int __asan_set_seh_filter() {
+ // We should only store the previous handler if it's not our own handler in
+ // order to avoid loops in the EH chain.
+ auto prev_seh_handler = SetUnhandledExceptionFilter(SEHHandler);
+ if (prev_seh_handler != &SEHHandler)
+ default_seh_handler = prev_seh_handler;
+ return 0;
+}
+
+bool HandleDlopenInit() {
+ // Not supported on this platform.
+ static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
+ "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
+ return false;
+}
+
+#if !ASAN_DYNAMIC
+// The CRT runs initializers in this order:
+// - C initializers, from XIA to XIZ
+// - C++ initializers, from XCA to XCZ
+// Prior to 2015, the CRT set the unhandled exception filter at priority XIY,
+// near the end of C initialization. Starting in 2015, it was moved to the
+// beginning of C++ initialization. We set our priority to XCAB to run
+// immediately after the CRT runs. This way, our exception filter is called
+// first and we can delegate to their filter if appropriate.
+#pragma section(".CRT$XCAB", long, read)
+__declspec(allocate(".CRT$XCAB")) int (*__intercept_seh)() =
+ __asan_set_seh_filter;
+
+// Piggyback on the TLS initialization callback directory to initialize asan as
+// early as possible. Initializers in .CRT$XL* are called directly by ntdll,
+// which run before the CRT. Users also add code to .CRT$XLC, so it's important
+// to run our initializers first.
+static void NTAPI asan_thread_init(void *module, DWORD reason, void *reserved) {
+ if (reason == DLL_PROCESS_ATTACH)
+ __asan_init();
+}
+
+#pragma section(".CRT$XLAB", long, read)
+__declspec(allocate(".CRT$XLAB")) void(NTAPI *__asan_tls_init)(
+ void *, unsigned long, void *) = asan_thread_init;
+#endif
+
+static void NTAPI asan_thread_exit(void *module, DWORD reason, void *reserved) {
+ if (reason == DLL_THREAD_DETACH) {
+ // Unpoison the thread's stack because the memory may be re-used.
+ NT_TIB *tib = (NT_TIB *)NtCurrentTeb();
+ uptr stackSize = (uptr)tib->StackBase - (uptr)tib->StackLimit;
+ __asan_unpoison_memory_region(tib->StackLimit, stackSize);
+ }
+}
+
+#pragma section(".CRT$XLY", long, read)
+__declspec(allocate(".CRT$XLY")) void(NTAPI *__asan_tls_exit)(
+ void *, unsigned long, void *) = asan_thread_exit;
+
+WIN_FORCE_LINK(__asan_dso_reg_hook)
+
+// }}}
+} // namespace __asan
+
+#endif // SANITIZER_WINDOWS
diff --git a/contrib/libs/clang16-rt/lib/asan/ya.make b/contrib/libs/clang16-rt/lib/asan/ya.make
new file mode 100644
index 00000000000..03799ec0ef8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan/ya.make
@@ -0,0 +1,159 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.asan${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHAVE_RPC_XDR_H=0
+ -DUBSAN_CAN_USE_CXXABI
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ asan/asan_activation.cpp
+ asan/asan_allocator.cpp
+ asan/asan_debugging.cpp
+ asan/asan_descriptions.cpp
+ asan/asan_errors.cpp
+ asan/asan_fake_stack.cpp
+ asan/asan_flags.cpp
+ asan/asan_fuchsia.cpp
+ asan/asan_globals.cpp
+ asan/asan_globals_win.cpp
+ asan/asan_interceptors.cpp
+ asan/asan_interceptors_memintrinsics.cpp
+ asan/asan_interceptors_vfork.S
+ asan/asan_linux.cpp
+ asan/asan_mac.cpp
+ asan/asan_malloc_linux.cpp
+ asan/asan_malloc_mac.cpp
+ asan/asan_malloc_win.cpp
+ asan/asan_memory_profile.cpp
+ asan/asan_poisoning.cpp
+ asan/asan_posix.cpp
+ asan/asan_preinit.cpp
+ asan/asan_premap_shadow.cpp
+ asan/asan_report.cpp
+ asan/asan_rtl.cpp
+ asan/asan_shadow_setup.cpp
+ asan/asan_stack.cpp
+ asan/asan_stats.cpp
+ asan/asan_suppressions.cpp
+ asan/asan_thread.cpp
+ asan/asan_win.cpp
+ interception/interception_linux.cpp
+ interception/interception_mac.cpp
+ interception/interception_type_test.cpp
+ interception/interception_win.cpp
+ lsan/lsan_common.cpp
+ lsan/lsan_common_fuchsia.cpp
+ lsan/lsan_common_linux.cpp
+ lsan/lsan_common_mac.cpp
+ sanitizer_common/sancov_flags.cpp
+ sanitizer_common/sanitizer_allocator.cpp
+ sanitizer_common/sanitizer_allocator_checks.cpp
+ sanitizer_common/sanitizer_allocator_report.cpp
+ sanitizer_common/sanitizer_chained_origin_depot.cpp
+ sanitizer_common/sanitizer_common.cpp
+ sanitizer_common/sanitizer_common_libcdep.cpp
+ sanitizer_common/sanitizer_coverage_fuchsia.cpp
+ sanitizer_common/sanitizer_coverage_libcdep_new.cpp
+ sanitizer_common/sanitizer_coverage_win_sections.cpp
+ sanitizer_common/sanitizer_deadlock_detector1.cpp
+ sanitizer_common/sanitizer_deadlock_detector2.cpp
+ sanitizer_common/sanitizer_errno.cpp
+ sanitizer_common/sanitizer_file.cpp
+ sanitizer_common/sanitizer_flag_parser.cpp
+ sanitizer_common/sanitizer_flags.cpp
+ sanitizer_common/sanitizer_fuchsia.cpp
+ sanitizer_common/sanitizer_libc.cpp
+ sanitizer_common/sanitizer_libignore.cpp
+ sanitizer_common/sanitizer_linux.cpp
+ sanitizer_common/sanitizer_linux_libcdep.cpp
+ sanitizer_common/sanitizer_linux_s390.cpp
+ sanitizer_common/sanitizer_mac.cpp
+ sanitizer_common/sanitizer_mac_libcdep.cpp
+ sanitizer_common/sanitizer_mutex.cpp
+ sanitizer_common/sanitizer_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+ sanitizer_common/sanitizer_platform_limits_linux.cpp
+ sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_posix.cpp
+ sanitizer_common/sanitizer_platform_limits_solaris.cpp
+ sanitizer_common/sanitizer_posix.cpp
+ sanitizer_common/sanitizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_printf.cpp
+ sanitizer_common/sanitizer_procmaps_bsd.cpp
+ sanitizer_common/sanitizer_procmaps_common.cpp
+ sanitizer_common/sanitizer_procmaps_fuchsia.cpp
+ sanitizer_common/sanitizer_procmaps_linux.cpp
+ sanitizer_common/sanitizer_procmaps_mac.cpp
+ sanitizer_common/sanitizer_procmaps_solaris.cpp
+ sanitizer_common/sanitizer_solaris.cpp
+ sanitizer_common/sanitizer_stack_store.cpp
+ sanitizer_common/sanitizer_stackdepot.cpp
+ sanitizer_common/sanitizer_stacktrace.cpp
+ sanitizer_common/sanitizer_stacktrace_libcdep.cpp
+ sanitizer_common/sanitizer_stacktrace_printer.cpp
+ sanitizer_common/sanitizer_stacktrace_sparc.cpp
+ sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
+ sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_mac.cpp
+ sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_win.cpp
+ sanitizer_common/sanitizer_suppressions.cpp
+ sanitizer_common/sanitizer_symbolizer.cpp
+ sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
+ sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_mac.cpp
+ sanitizer_common/sanitizer_symbolizer_markup.cpp
+ sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_report.cpp
+ sanitizer_common/sanitizer_symbolizer_win.cpp
+ sanitizer_common/sanitizer_termination.cpp
+ sanitizer_common/sanitizer_thread_registry.cpp
+ sanitizer_common/sanitizer_tls_get_addr.cpp
+ sanitizer_common/sanitizer_type_traits.cpp
+ sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
+ sanitizer_common/sanitizer_unwind_win.cpp
+ sanitizer_common/sanitizer_win.cpp
+ ubsan/ubsan_diag.cpp
+ ubsan/ubsan_flags.cpp
+ ubsan/ubsan_handlers.cpp
+ ubsan/ubsan_init.cpp
+ ubsan/ubsan_monitor.cpp
+ ubsan/ubsan_value.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/asan_cxx/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/asan_cxx/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan_cxx/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/asan_cxx/ya.make b/contrib/libs/clang16-rt/lib/asan_cxx/ya.make
new file mode 100644
index 00000000000..8e5343b8c17
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan_cxx/ya.make
@@ -0,0 +1,51 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.asan_cxx${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DUBSAN_CAN_USE_CXXABI
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -frtti
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ asan/asan_new_delete.cpp
+ ubsan/ubsan_handlers_cxx.cpp
+ ubsan/ubsan_type_hash.cpp
+ ubsan/ubsan_type_hash_itanium.cpp
+ ubsan/ubsan_type_hash_win.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/asan_static/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/asan_static/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan_static/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/asan_static/ya.make b/contrib/libs/clang16-rt/lib/asan_static/ya.make
new file mode 100644
index 00000000000..d837c5e8844
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/asan_static/ya.make
@@ -0,0 +1,51 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.asan_static${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib/asan)
+
+SRCS(
+ asan_rtl_static.cpp
+)
+
+IF (ARCH_X86_64 AND NOT OS_DARWIN)
+ SRCS(
+ asan_rtl_x86_64.S
+ )
+ENDIF()
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/builtins/README.txt b/contrib/libs/clang16-rt/lib/builtins/README.txt
new file mode 100644
index 00000000000..53d656d5086
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/builtins/README.txt
@@ -0,0 +1,353 @@
+Compiler-RT
+================================
+
+This directory and its subdirectories contain source code for the compiler
+support routines.
+
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+================================
+
+This is a replacement library for libgcc. Each function is contained
+in its own file. Each function has a corresponding unit test under
+test/Unit.
+
+A rudimentary script to test each file is in the file called
+test/Unit/test.
+
+Here is the specification for this library:
+
+http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html#Libgcc
+
+Please note that the libgcc specification explicitly mentions actual types of
+arguments and returned values being expressed with machine modes.
+In some cases particular types such as "int", "unsigned", "long long", etc.
+may be specified just as examples there.
+
+Here is a synopsis of the contents of this library:
+
+typedef int32_t si_int;
+typedef uint32_t su_int;
+
+typedef int64_t di_int;
+typedef uint64_t du_int;
+
+// Integral bit manipulation
+
+di_int __ashldi3(di_int a, si_int b); // a << b
+ti_int __ashlti3(ti_int a, si_int b); // a << b
+
+di_int __ashrdi3(di_int a, si_int b); // a >> b arithmetic (sign fill)
+ti_int __ashrti3(ti_int a, si_int b); // a >> b arithmetic (sign fill)
+di_int __lshrdi3(di_int a, si_int b); // a >> b logical (zero fill)
+ti_int __lshrti3(ti_int a, si_int b); // a >> b logical (zero fill)
+
+int __clzsi2(si_int a); // count leading zeros
+int __clzdi2(di_int a); // count leading zeros
+int __clzti2(ti_int a); // count leading zeros
+int __ctzsi2(si_int a); // count trailing zeros
+int __ctzdi2(di_int a); // count trailing zeros
+int __ctzti2(ti_int a); // count trailing zeros
+
+int __ffssi2(si_int a); // find least significant 1 bit
+int __ffsdi2(di_int a); // find least significant 1 bit
+int __ffsti2(ti_int a); // find least significant 1 bit
+
+int __paritysi2(si_int a); // bit parity
+int __paritydi2(di_int a); // bit parity
+int __parityti2(ti_int a); // bit parity
+
+int __popcountsi2(si_int a); // bit population
+int __popcountdi2(di_int a); // bit population
+int __popcountti2(ti_int a); // bit population
+
+uint32_t __bswapsi2(uint32_t a); // a byteswapped
+uint64_t __bswapdi2(uint64_t a); // a byteswapped
+
+// Integral arithmetic
+
+di_int __negdi2 (di_int a); // -a
+ti_int __negti2 (ti_int a); // -a
+di_int __muldi3 (di_int a, di_int b); // a * b
+ti_int __multi3 (ti_int a, ti_int b); // a * b
+si_int __divsi3 (si_int a, si_int b); // a / b signed
+di_int __divdi3 (di_int a, di_int b); // a / b signed
+ti_int __divti3 (ti_int a, ti_int b); // a / b signed
+su_int __udivsi3 (su_int n, su_int d); // a / b unsigned
+du_int __udivdi3 (du_int a, du_int b); // a / b unsigned
+tu_int __udivti3 (tu_int a, tu_int b); // a / b unsigned
+si_int __modsi3 (si_int a, si_int b); // a % b signed
+di_int __moddi3 (di_int a, di_int b); // a % b signed
+ti_int __modti3 (ti_int a, ti_int b); // a % b signed
+su_int __umodsi3 (su_int a, su_int b); // a % b unsigned
+du_int __umoddi3 (du_int a, du_int b); // a % b unsigned
+tu_int __umodti3 (tu_int a, tu_int b); // a % b unsigned
+du_int __udivmoddi4(du_int a, du_int b, du_int* rem); // a / b, *rem = a % b unsigned
+tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem); // a / b, *rem = a % b unsigned
+su_int __udivmodsi4(su_int a, su_int b, su_int* rem); // a / b, *rem = a % b unsigned
+si_int __divmodsi4(si_int a, si_int b, si_int* rem); // a / b, *rem = a % b signed
+di_int __divmoddi4(di_int a, di_int b, di_int* rem); // a / b, *rem = a % b signed
+ti_int __divmodti4(ti_int a, ti_int b, ti_int* rem); // a / b, *rem = a % b signed
+
+
+
+// Integral arithmetic with trapping overflow
+
+si_int __absvsi2(si_int a); // abs(a)
+di_int __absvdi2(di_int a); // abs(a)
+ti_int __absvti2(ti_int a); // abs(a)
+
+si_int __negvsi2(si_int a); // -a
+di_int __negvdi2(di_int a); // -a
+ti_int __negvti2(ti_int a); // -a
+
+si_int __addvsi3(si_int a, si_int b); // a + b
+di_int __addvdi3(di_int a, di_int b); // a + b
+ti_int __addvti3(ti_int a, ti_int b); // a + b
+
+si_int __subvsi3(si_int a, si_int b); // a - b
+di_int __subvdi3(di_int a, di_int b); // a - b
+ti_int __subvti3(ti_int a, ti_int b); // a - b
+
+si_int __mulvsi3(si_int a, si_int b); // a * b
+di_int __mulvdi3(di_int a, di_int b); // a * b
+ti_int __mulvti3(ti_int a, ti_int b); // a * b
+
+
+// Integral arithmetic which returns if overflow
+
+si_int __mulosi4(si_int a, si_int b, int* overflow); // a * b, overflow set to one if result not in signed range
+di_int __mulodi4(di_int a, di_int b, int* overflow); // a * b, overflow set to one if result not in signed range
+ti_int __muloti4(ti_int a, ti_int b, int* overflow); // a * b, overflow set to
+ one if result not in signed range
+
+
+// Integral comparison: a < b -> 0
+// a == b -> 1
+// a > b -> 2
+
+si_int __cmpdi2 (di_int a, di_int b);
+si_int __cmpti2 (ti_int a, ti_int b);
+si_int __ucmpdi2(du_int a, du_int b);
+si_int __ucmpti2(tu_int a, tu_int b);
+
+// Integral / floating point conversion
+
+di_int __fixsfdi( float a);
+di_int __fixdfdi( double a);
+di_int __fixxfdi(long double a);
+
+ti_int __fixsfti( float a);
+ti_int __fixdfti( double a);
+ti_int __fixxfti(long double a);
+uint64_t __fixtfdi(long double input); // ppc only, doesn't match documentation
+
+su_int __fixunssfsi( float a);
+su_int __fixunsdfsi( double a);
+su_int __fixunsxfsi(long double a);
+
+du_int __fixunssfdi( float a);
+du_int __fixunsdfdi( double a);
+du_int __fixunsxfdi(long double a);
+
+tu_int __fixunssfti( float a);
+tu_int __fixunsdfti( double a);
+tu_int __fixunsxfti(long double a);
+uint64_t __fixunstfdi(long double input); // ppc only
+
+float __floatdisf(di_int a);
+double __floatdidf(di_int a);
+long double __floatdixf(di_int a);
+long double __floatditf(int64_t a); // ppc only
+
+float __floattisf(ti_int a);
+double __floattidf(ti_int a);
+long double __floattixf(ti_int a);
+
+float __floatundisf(du_int a);
+double __floatundidf(du_int a);
+long double __floatundixf(du_int a);
+long double __floatunditf(uint64_t a); // ppc only
+
+float __floatuntisf(tu_int a);
+double __floatuntidf(tu_int a);
+long double __floatuntixf(tu_int a);
+
+// Floating point raised to integer power
+
+float __powisf2( float a, int b); // a ^ b
+double __powidf2( double a, int b); // a ^ b
+long double __powixf2(long double a, int b); // a ^ b
+long double __powitf2(long double a, int b); // ppc only, a ^ b
+
+// Complex arithmetic
+
+// (a + ib) * (c + id)
+
+ float _Complex __mulsc3( float a, float b, float c, float d);
+ double _Complex __muldc3(double a, double b, double c, double d);
+long double _Complex __mulxc3(long double a, long double b,
+ long double c, long double d);
+long double _Complex __multc3(long double a, long double b,
+ long double c, long double d); // ppc only
+
+// (a + ib) / (c + id)
+
+ float _Complex __divsc3( float a, float b, float c, float d);
+ double _Complex __divdc3(double a, double b, double c, double d);
+long double _Complex __divxc3(long double a, long double b,
+ long double c, long double d);
+long double _Complex __divtc3(long double a, long double b,
+ long double c, long double d); // ppc only
+
+
+// Runtime support
+
+// __clear_cache() is used to tell process that new instructions have been
+// written to an address range. Necessary on processors that do not have
+// a unified instruction and data cache.
+void __clear_cache(void* start, void* end);
+
+// __enable_execute_stack() is used with nested functions when a trampoline
+// function is written onto the stack and that page range needs to be made
+// executable.
+void __enable_execute_stack(void* addr);
+
+// __gcc_personality_v0() is normally only called by the system unwinder.
+// C code (as opposed to C++) normally does not need a personality function
+// because there are no catch clauses or destructors to be run. But there
+// is a C language extension __attribute__((cleanup(func))) which marks local
+// variables as needing the cleanup function "func" to be run when the
+// variable goes out of scope. That includes when an exception is thrown,
+// so a personality handler is needed.
+_Unwind_Reason_Code __gcc_personality_v0(int version, _Unwind_Action actions,
+ uint64_t exceptionClass, struct _Unwind_Exception* exceptionObject,
+ _Unwind_Context_t context);
+
+// for use with some implementations of assert() in <assert.h>
+void __eprintf(const char* format, const char* assertion_expression,
+ const char* line, const char* file);
+
+// for systems with emulated thread local storage
+void* __emutls_get_address(struct __emutls_control*);
+
+
+// Power PC specific functions
+
+// There is no C interface to the saveFP/restFP functions. They are helper
+// functions called by the prolog and epilog of functions that need to save
+// a number of non-volatile float point registers.
+saveFP
+restFP
+
+// PowerPC has a standard template for trampoline functions. This function
+// generates a custom trampoline function with the specific realFunc
+// and localsPtr values.
+void __trampoline_setup(uint32_t* trampOnStack, int trampSizeAllocated,
+ const void* realFunc, void* localsPtr);
+
+// adds two 128-bit double-double precision values ( x + y )
+long double __gcc_qadd(long double x, long double y);
+
+// subtracts two 128-bit double-double precision values ( x - y )
+long double __gcc_qsub(long double x, long double y);
+
+// multiples two 128-bit double-double precision values ( x * y )
+long double __gcc_qmul(long double x, long double y);
+
+// divides two 128-bit double-double precision values ( x / y )
+long double __gcc_qdiv(long double a, long double b);
+
+
+// ARM specific functions
+
+// There is no C interface to the switch* functions. These helper functions
+// are only needed by Thumb1 code for efficient switch table generation.
+switch16
+switch32
+switch8
+switchu8
+
+// There is no C interface to the *_vfp_d8_d15_regs functions. There are
+// called in the prolog and epilog of Thumb1 functions. When the C++ ABI use
+// SJLJ for exceptions, each function with a catch clause or destructors needs
+// to save and restore all registers in it prolog and epilog. But there is
+// no way to access vector and high float registers from thumb1 code, so the
+// compiler must add call outs to these helper functions in the prolog and
+// epilog.
+restore_vfp_d8_d15_regs
+save_vfp_d8_d15_regs
+
+
+// Note: long ago ARM processors did not have floating point hardware support.
+// Floating point was done in software and floating point parameters were
+// passed in integer registers. When hardware support was added for floating
+// point, new *vfp functions were added to do the same operations but with
+// floating point parameters in floating point registers.
+
+// Undocumented functions
+
+float __addsf3vfp(float a, float b); // Appears to return a + b
+double __adddf3vfp(double a, double b); // Appears to return a + b
+float __divsf3vfp(float a, float b); // Appears to return a / b
+double __divdf3vfp(double a, double b); // Appears to return a / b
+int __eqsf2vfp(float a, float b); // Appears to return one
+ // iff a == b and neither is NaN.
+int __eqdf2vfp(double a, double b); // Appears to return one
+ // iff a == b and neither is NaN.
+double __extendsfdf2vfp(float a); // Appears to convert from
+ // float to double.
+int __fixdfsivfp(double a); // Appears to convert from
+ // double to int.
+int __fixsfsivfp(float a); // Appears to convert from
+ // float to int.
+unsigned int __fixunssfsivfp(float a); // Appears to convert from
+ // float to unsigned int.
+unsigned int __fixunsdfsivfp(double a); // Appears to convert from
+ // double to unsigned int.
+double __floatsidfvfp(int a); // Appears to convert from
+ // int to double.
+float __floatsisfvfp(int a); // Appears to convert from
+ // int to float.
+double __floatunssidfvfp(unsigned int a); // Appears to convert from
+ // unsigned int to double.
+float __floatunssisfvfp(unsigned int a); // Appears to convert from
+ // unsigned int to float.
+int __gedf2vfp(double a, double b); // Appears to return __gedf2
+ // (a >= b)
+int __gesf2vfp(float a, float b); // Appears to return __gesf2
+ // (a >= b)
+int __gtdf2vfp(double a, double b); // Appears to return __gtdf2
+ // (a > b)
+int __gtsf2vfp(float a, float b); // Appears to return __gtsf2
+ // (a > b)
+int __ledf2vfp(double a, double b); // Appears to return __ledf2
+ // (a <= b)
+int __lesf2vfp(float a, float b); // Appears to return __lesf2
+ // (a <= b)
+int __ltdf2vfp(double a, double b); // Appears to return __ltdf2
+ // (a < b)
+int __ltsf2vfp(float a, float b); // Appears to return __ltsf2
+ // (a < b)
+double __muldf3vfp(double a, double b); // Appears to return a * b
+float __mulsf3vfp(float a, float b); // Appears to return a * b
+int __nedf2vfp(double a, double b); // Appears to return __nedf2
+ // (a != b)
+double __negdf2vfp(double a); // Appears to return -a
+float __negsf2vfp(float a); // Appears to return -a
+float __negsf2vfp(float a); // Appears to return -a
+double __subdf3vfp(double a, double b); // Appears to return a - b
+float __subsf3vfp(float a, float b); // Appears to return a - b
+float __truncdfsf2vfp(double a); // Appears to convert from
+ // double to float.
+int __unorddf2vfp(double a, double b); // Appears to return __unorddf2
+int __unordsf2vfp(float a, float b); // Appears to return __unordsf2
+
+
+Preconditions are listed for each function at the definition when there are any.
+Any preconditions reflect the specification at
+http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html#Libgcc.
+
+Assumptions are listed in "int_lib.h", and in individual files. Where possible
+assumptions are checked at compile time.
diff --git a/contrib/libs/clang16-rt/lib/builtins/assembly.h b/contrib/libs/clang16-rt/lib/builtins/assembly.h
new file mode 100644
index 00000000000..69a3d8620f9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/builtins/assembly.h
@@ -0,0 +1,292 @@
+//===-- assembly.h - compiler-rt assembler support macros -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines macros for use in compiler-rt assembler source.
+// This file is not part of the interface of this library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef COMPILERRT_ASSEMBLY_H
+#define COMPILERRT_ASSEMBLY_H
+
+#if defined(__linux__) && defined(__CET__)
+#if __has_include(<cet.h>)
+#include <cet.h>
+#endif
+#endif
+
+#if defined(__APPLE__) && defined(__aarch64__)
+#define SEPARATOR %%
+#else
+#define SEPARATOR ;
+#endif
+
+#if defined(__APPLE__)
+#define HIDDEN(name) .private_extern name
+#define LOCAL_LABEL(name) L_##name
+// tell linker it can break up file at label boundaries
+#define FILE_LEVEL_DIRECTIVE .subsections_via_symbols
+#define SYMBOL_IS_FUNC(name)
+#define CONST_SECTION .const
+
+#define NO_EXEC_STACK_DIRECTIVE
+
+#elif defined(__ELF__)
+
+#define HIDDEN(name) .hidden name
+#define LOCAL_LABEL(name) .L_##name
+#define FILE_LEVEL_DIRECTIVE
+#if defined(__arm__) || defined(__aarch64__)
+#define SYMBOL_IS_FUNC(name) .type name,%function
+#else
+#define SYMBOL_IS_FUNC(name) .type name,@function
+#endif
+#define CONST_SECTION .section .rodata
+
+#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
+ defined(__linux__)
+#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
+#else
+#define NO_EXEC_STACK_DIRECTIVE
+#endif
+
+#else // !__APPLE__ && !__ELF__
+
+#define HIDDEN(name)
+#define LOCAL_LABEL(name) .L ## name
+#define FILE_LEVEL_DIRECTIVE
+#define SYMBOL_IS_FUNC(name) \
+ .def name SEPARATOR \
+ .scl 2 SEPARATOR \
+ .type 32 SEPARATOR \
+ .endef
+#define CONST_SECTION .section .rdata,"rd"
+
+#define NO_EXEC_STACK_DIRECTIVE
+
+#endif
+
+#if defined(__arm__) || defined(__aarch64__)
+#define FUNC_ALIGN \
+ .text SEPARATOR \
+ .balign 16 SEPARATOR
+#else
+#define FUNC_ALIGN
+#endif
+
+// BTI and PAC gnu property note
+#define NT_GNU_PROPERTY_TYPE_0 5
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2
+
+#if defined(__ARM_FEATURE_BTI_DEFAULT)
+#define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI
+#else
+#define BTI_FLAG 0
+#endif
+
+#if __ARM_FEATURE_PAC_DEFAULT & 3
+#define PAC_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_PAC
+#else
+#define PAC_FLAG 0
+#endif
+
+#define GNU_PROPERTY(type, value) \
+ .pushsection .note.gnu.property, "a" SEPARATOR \
+ .p2align 3 SEPARATOR \
+ .word 4 SEPARATOR \
+ .word 16 SEPARATOR \
+ .word NT_GNU_PROPERTY_TYPE_0 SEPARATOR \
+ .asciz "GNU" SEPARATOR \
+ .word type SEPARATOR \
+ .word 4 SEPARATOR \
+ .word value SEPARATOR \
+ .word 0 SEPARATOR \
+ .popsection
+
+#if BTI_FLAG != 0
+#define BTI_C hint #34
+#define BTI_J hint #36
+#else
+#define BTI_C
+#define BTI_J
+#endif
+
+#if (BTI_FLAG | PAC_FLAG) != 0
+#define GNU_PROPERTY_BTI_PAC \
+ GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, BTI_FLAG | PAC_FLAG)
+#else
+#define GNU_PROPERTY_BTI_PAC
+#endif
+
+#if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM)
+#define CFI_START .cfi_startproc
+#define CFI_END .cfi_endproc
+#else
+#define CFI_START
+#define CFI_END
+#endif
+
+#if defined(__arm__)
+
+// Determine actual [ARM][THUMB[1][2]] ISA using compiler predefined macros:
+// - for '-mthumb -march=armv6' compiler defines '__thumb__'
+// - for '-mthumb -march=armv7' compiler defines '__thumb__' and '__thumb2__'
+#if defined(__thumb2__) || defined(__thumb__)
+#define DEFINE_CODE_STATE .thumb SEPARATOR
+#define DECLARE_FUNC_ENCODING .thumb_func SEPARATOR
+#if defined(__thumb2__)
+#define USE_THUMB_2
+#define IT(cond) it cond
+#define ITT(cond) itt cond
+#define ITE(cond) ite cond
+#else
+#define USE_THUMB_1
+#define IT(cond)
+#define ITT(cond)
+#define ITE(cond)
+#endif // defined(__thumb__2)
+#else // !defined(__thumb2__) && !defined(__thumb__)
+#define DEFINE_CODE_STATE .arm SEPARATOR
+#define DECLARE_FUNC_ENCODING
+#define IT(cond)
+#define ITT(cond)
+#define ITE(cond)
+#endif
+
+#if defined(USE_THUMB_1) && defined(USE_THUMB_2)
+#error "USE_THUMB_1 and USE_THUMB_2 can't be defined together."
+#endif
+
+#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
+#define ARM_HAS_BX
+#endif
+#if !defined(__ARM_FEATURE_CLZ) && !defined(USE_THUMB_1) && \
+ (__ARM_ARCH >= 6 || (__ARM_ARCH == 5 && !defined(__ARM_ARCH_5__)))
+#define __ARM_FEATURE_CLZ
+#endif
+
+#ifdef ARM_HAS_BX
+#define JMP(r) bx r
+#define JMPc(r, c) bx##c r
+#else
+#define JMP(r) mov pc, r
+#define JMPc(r, c) mov##c pc, r
+#endif
+
+// pop {pc} can't switch Thumb mode on ARMv4T
+#if __ARM_ARCH >= 5
+#define POP_PC() pop {pc}
+#else
+#define POP_PC() \
+ pop {ip}; \
+ JMP(ip)
+#endif
+
+#if defined(USE_THUMB_2)
+#define WIDE(op) op.w
+#else
+#define WIDE(op) op
+#endif
+#else // !defined(__arm)
+#define DECLARE_FUNC_ENCODING
+#define DEFINE_CODE_STATE
+#endif
+
+#define GLUE2_(a, b) a##b
+#define GLUE(a, b) GLUE2_(a, b)
+#define GLUE2(a, b) GLUE2_(a, b)
+#define GLUE3_(a, b, c) a##b##c
+#define GLUE3(a, b, c) GLUE3_(a, b, c)
+#define GLUE4_(a, b, c, d) a##b##c##d
+#define GLUE4(a, b, c, d) GLUE4_(a, b, c, d)
+
+#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
+
+#ifdef VISIBILITY_HIDDEN
+#define DECLARE_SYMBOL_VISIBILITY(name) \
+ HIDDEN(SYMBOL_NAME(name)) SEPARATOR
+#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) \
+ HIDDEN(name) SEPARATOR
+#else
+#define DECLARE_SYMBOL_VISIBILITY(name)
+#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name)
+#endif
+
+#define DEFINE_COMPILERRT_FUNCTION(name) \
+ DEFINE_CODE_STATE \
+ FILE_LEVEL_DIRECTIVE SEPARATOR \
+ .globl SYMBOL_NAME(name) SEPARATOR \
+ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
+ DECLARE_SYMBOL_VISIBILITY(name) \
+ DECLARE_FUNC_ENCODING \
+ SYMBOL_NAME(name):
+
+#define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \
+ DEFINE_CODE_STATE \
+ FILE_LEVEL_DIRECTIVE SEPARATOR \
+ .globl SYMBOL_NAME(name) SEPARATOR \
+ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
+ DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \
+ .thumb_func SEPARATOR \
+ SYMBOL_NAME(name):
+
+#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \
+ DEFINE_CODE_STATE \
+ FILE_LEVEL_DIRECTIVE SEPARATOR \
+ .globl SYMBOL_NAME(name) SEPARATOR \
+ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
+ HIDDEN(SYMBOL_NAME(name)) SEPARATOR \
+ DECLARE_FUNC_ENCODING \
+ SYMBOL_NAME(name):
+
+#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \
+ DEFINE_CODE_STATE \
+ .globl name SEPARATOR \
+ SYMBOL_IS_FUNC(name) SEPARATOR \
+ HIDDEN(name) SEPARATOR \
+ DECLARE_FUNC_ENCODING \
+ name:
+
+#define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name) \
+ DEFINE_CODE_STATE \
+ FUNC_ALIGN \
+ .globl name SEPARATOR \
+ SYMBOL_IS_FUNC(name) SEPARATOR \
+ DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) SEPARATOR \
+ CFI_START SEPARATOR \
+ DECLARE_FUNC_ENCODING \
+ name: SEPARATOR BTI_C
+
+#define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \
+ .globl SYMBOL_NAME(name) SEPARATOR \
+ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
+ DECLARE_SYMBOL_VISIBILITY(SYMBOL_NAME(name)) SEPARATOR \
+ .set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR
+
+#if defined(__ARM_EABI__)
+#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \
+ DEFINE_COMPILERRT_FUNCTION_ALIAS(aeabi_name, name)
+#else
+#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name)
+#endif
+
+#ifdef __ELF__
+#define END_COMPILERRT_FUNCTION(name) \
+ .size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
+#define END_COMPILERRT_OUTLINE_FUNCTION(name) \
+ CFI_END SEPARATOR \
+ .size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
+#else
+#define END_COMPILERRT_FUNCTION(name)
+#define END_COMPILERRT_OUTLINE_FUNCTION(name) \
+ CFI_END
+#endif
+
+#endif // COMPILERRT_ASSEMBLY_H
diff --git a/contrib/libs/clang16-rt/lib/cfi/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/cfi/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/cfi/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/cfi/cfi.cpp b/contrib/libs/clang16-rt/lib/cfi/cfi.cpp
new file mode 100644
index 00000000000..6df3906467e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/cfi/cfi.cpp
@@ -0,0 +1,476 @@
+//===-------- cfi.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the runtime support for the cross-DSO CFI.
+//
+//===----------------------------------------------------------------------===//
+
+#include <assert.h>
+#include <elf.h>
+
+#include "sanitizer_common/sanitizer_common.h"
+#if SANITIZER_FREEBSD
+#error #include <sys/link_elf.h>
+#endif
+#include <link.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+#if SANITIZER_LINUX
+typedef ElfW(Phdr) Elf_Phdr;
+typedef ElfW(Ehdr) Elf_Ehdr;
+typedef ElfW(Addr) Elf_Addr;
+typedef ElfW(Sym) Elf_Sym;
+typedef ElfW(Dyn) Elf_Dyn;
+#elif SANITIZER_FREEBSD
+#if SANITIZER_WORDSIZE == 64
+#define ElfW64_Dyn Elf_Dyn
+#define ElfW64_Sym Elf_Sym
+#else
+#define ElfW32_Dyn Elf_Dyn
+#define ElfW32_Sym Elf_Sym
+#endif
+#endif
+
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "ubsan/ubsan_init.h"
+#include "ubsan/ubsan_flags.h"
+
+#ifdef CFI_ENABLE_DIAG
+#include "ubsan/ubsan_handlers.h"
+#endif
+
+using namespace __sanitizer;
+
+namespace __cfi {
+
+#define kCfiShadowLimitsStorageSize 4096 // 1 page
+// Lets hope that the data segment is mapped with 4K pages.
+// The pointer to the cfi shadow region is stored at the start of this page.
+// The rest of the page is unused and re-mapped read-only.
+static union {
+ char space[kCfiShadowLimitsStorageSize];
+ struct {
+ uptr start;
+ uptr size;
+ } limits;
+} cfi_shadow_limits_storage
+ __attribute__((aligned(kCfiShadowLimitsStorageSize)));
+static constexpr uptr kShadowGranularity = 12;
+static constexpr uptr kShadowAlign = 1UL << kShadowGranularity; // 4096
+
+static constexpr uint16_t kInvalidShadow = 0;
+static constexpr uint16_t kUncheckedShadow = 0xFFFFU;
+
+// Get the start address of the CFI shadow region.
+uptr GetShadow() {
+ return cfi_shadow_limits_storage.limits.start;
+}
+
+uptr GetShadowSize() {
+ return cfi_shadow_limits_storage.limits.size;
+}
+
+// This will only work while the shadow is not allocated.
+void SetShadowSize(uptr size) {
+ cfi_shadow_limits_storage.limits.size = size;
+}
+
+uptr MemToShadowOffset(uptr x) {
+ return (x >> kShadowGranularity) << 1;
+}
+
+uint16_t *MemToShadow(uptr x, uptr shadow_base) {
+ return (uint16_t *)(shadow_base + MemToShadowOffset(x));
+}
+
+typedef int (*CFICheckFn)(u64, void *, void *);
+
+// This class reads and decodes the shadow contents.
+class ShadowValue {
+ uptr addr;
+ uint16_t v;
+ explicit ShadowValue(uptr addr, uint16_t v) : addr(addr), v(v) {}
+
+public:
+ bool is_invalid() const { return v == kInvalidShadow; }
+
+ bool is_unchecked() const { return v == kUncheckedShadow; }
+
+ CFICheckFn get_cfi_check() const {
+ assert(!is_invalid() && !is_unchecked());
+ uptr aligned_addr = addr & ~(kShadowAlign - 1);
+ uptr p = aligned_addr - (((uptr)v - 1) << kShadowGranularity);
+ return reinterpret_cast<CFICheckFn>(p);
+ }
+
+ // Load a shadow value for the given application memory address.
+ static const ShadowValue load(uptr addr) {
+ uptr shadow_base = GetShadow();
+ uptr shadow_offset = MemToShadowOffset(addr);
+ if (shadow_offset > GetShadowSize())
+ return ShadowValue(addr, kInvalidShadow);
+ else
+ return ShadowValue(
+ addr, *reinterpret_cast<uint16_t *>(shadow_base + shadow_offset));
+ }
+};
+
+class ShadowBuilder {
+ uptr shadow_;
+
+public:
+ // Allocate a new empty shadow (for the entire address space) on the side.
+ void Start();
+ // Mark the given address range as unchecked.
+ // This is used for uninstrumented libraries like libc.
+ // Any CFI check with a target in that range will pass.
+ void AddUnchecked(uptr begin, uptr end);
+ // Mark the given address range as belonging to a library with the given
+ // cfi_check function.
+ void Add(uptr begin, uptr end, uptr cfi_check);
+ // Finish shadow construction. Atomically switch the current active shadow
+ // region with the newly constructed one and deallocate the former.
+ void Install();
+};
+
+void ShadowBuilder::Start() {
+ shadow_ = (uptr)MmapNoReserveOrDie(GetShadowSize(), "CFI shadow");
+ VReport(1, "CFI: shadow at %zx .. %zx\n", shadow_, shadow_ + GetShadowSize());
+}
+
+void ShadowBuilder::AddUnchecked(uptr begin, uptr end) {
+ uint16_t *shadow_begin = MemToShadow(begin, shadow_);
+ uint16_t *shadow_end = MemToShadow(end - 1, shadow_) + 1;
+ // memset takes a byte, so our unchecked shadow value requires both bytes to
+ // be the same. Make sure we're ok during compilation.
+ static_assert((kUncheckedShadow & 0xff) == ((kUncheckedShadow >> 8) & 0xff),
+ "Both bytes of the 16-bit value must be the same!");
+ memset(shadow_begin, kUncheckedShadow & 0xff,
+ (shadow_end - shadow_begin) * sizeof(*shadow_begin));
+}
+
+void ShadowBuilder::Add(uptr begin, uptr end, uptr cfi_check) {
+ assert((cfi_check & (kShadowAlign - 1)) == 0);
+
+ // Don't fill anything below cfi_check. We can not represent those addresses
+ // in the shadow, and must make sure at codegen to place all valid call
+ // targets above cfi_check.
+ begin = Max(begin, cfi_check);
+ uint16_t *s = MemToShadow(begin, shadow_);
+ uint16_t *s_end = MemToShadow(end - 1, shadow_) + 1;
+ uint16_t sv = ((begin - cfi_check) >> kShadowGranularity) + 1;
+ for (; s < s_end; s++, sv++)
+ *s = sv;
+}
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD
+void ShadowBuilder::Install() {
+ MprotectReadOnly(shadow_, GetShadowSize());
+ uptr main_shadow = GetShadow();
+ if (main_shadow) {
+ // Update.
+#if SANITIZER_LINUX
+ void *res = mremap((void *)shadow_, GetShadowSize(), GetShadowSize(),
+ MREMAP_MAYMOVE | MREMAP_FIXED, (void *)main_shadow);
+ CHECK(res != MAP_FAILED);
+#elif SANITIZER_NETBSD
+ void *res = mremap((void *)shadow_, GetShadowSize(), (void *)main_shadow,
+ GetShadowSize(), MAP_FIXED);
+ CHECK(res != MAP_FAILED);
+#else
+ void *res = MmapFixedOrDie(shadow_, GetShadowSize(), "cfi shadow");
+ CHECK(res != MAP_FAILED);
+ ::memcpy(&shadow_, &main_shadow, GetShadowSize());
+#endif
+ } else {
+ // Initial setup.
+ CHECK_EQ(kCfiShadowLimitsStorageSize, GetPageSizeCached());
+ CHECK_EQ(0, GetShadow());
+ cfi_shadow_limits_storage.limits.start = shadow_;
+ MprotectReadOnly((uptr)&cfi_shadow_limits_storage,
+ sizeof(cfi_shadow_limits_storage));
+ CHECK_EQ(shadow_, GetShadow());
+ }
+}
+#else
+#error not implemented
+#endif
+
+// This is a workaround for a glibc bug:
+// https://sourceware.org/bugzilla/show_bug.cgi?id=15199
+// Other platforms can, hopefully, just do
+// dlopen(RTLD_NOLOAD | RTLD_LAZY)
+// dlsym("__cfi_check").
+uptr find_cfi_check_in_dso(dl_phdr_info *info) {
+ const Elf_Dyn *dynamic = nullptr;
+ for (int i = 0; i < info->dlpi_phnum; ++i) {
+ if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) {
+ dynamic =
+ (const Elf_Dyn *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
+ break;
+ }
+ }
+ if (!dynamic) return 0;
+ uptr strtab = 0, symtab = 0, strsz = 0;
+ for (const Elf_Dyn *p = dynamic; p->d_tag != PT_NULL; ++p) {
+ if (p->d_tag == DT_SYMTAB)
+ symtab = p->d_un.d_ptr;
+ else if (p->d_tag == DT_STRTAB)
+ strtab = p->d_un.d_ptr;
+ else if (p->d_tag == DT_STRSZ)
+ strsz = p->d_un.d_ptr;
+ }
+
+ if (symtab > strtab) {
+ VReport(1, "Can not handle: symtab > strtab (%zx > %zx)\n", symtab, strtab);
+ return 0;
+ }
+
+ // Verify that strtab and symtab are inside of the same LOAD segment.
+ // This excludes VDSO, which has (very high) bogus strtab and symtab pointers.
+ int phdr_idx;
+ for (phdr_idx = 0; phdr_idx < info->dlpi_phnum; phdr_idx++) {
+ const Elf_Phdr *phdr = &info->dlpi_phdr[phdr_idx];
+ if (phdr->p_type == PT_LOAD) {
+ uptr beg = info->dlpi_addr + phdr->p_vaddr;
+ uptr end = beg + phdr->p_memsz;
+ if (strtab >= beg && strtab + strsz < end && symtab >= beg &&
+ symtab < end)
+ break;
+ }
+ }
+ if (phdr_idx == info->dlpi_phnum) {
+ // Nope, either different segments or just bogus pointers.
+ // Can not handle this.
+ VReport(1, "Can not handle: symtab %zx, strtab %zx\n", symtab, strtab);
+ return 0;
+ }
+
+ for (const Elf_Sym *p = (const Elf_Sym *)symtab; (Elf_Addr)p < strtab;
+ ++p) {
+ // There is no reliable way to find the end of the symbol table. In
+ // lld-produces files, there are other sections between symtab and strtab.
+ // Stop looking when the symbol name is not inside strtab.
+ if (p->st_name >= strsz) break;
+ char *name = (char*)(strtab + p->st_name);
+ if (strcmp(name, "__cfi_check") == 0) {
+ assert(p->st_info == ELF32_ST_INFO(STB_GLOBAL, STT_FUNC) ||
+ p->st_info == ELF32_ST_INFO(STB_WEAK, STT_FUNC));
+ uptr addr = info->dlpi_addr + p->st_value;
+ return addr;
+ }
+ }
+ return 0;
+}
+
+int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *data) {
+ uptr cfi_check = find_cfi_check_in_dso(info);
+ if (cfi_check)
+ VReport(1, "Module '%s' __cfi_check %zx\n", info->dlpi_name, cfi_check);
+
+ ShadowBuilder *b = reinterpret_cast<ShadowBuilder *>(data);
+
+ for (int i = 0; i < info->dlpi_phnum; i++) {
+ const Elf_Phdr *phdr = &info->dlpi_phdr[i];
+ if (phdr->p_type == PT_LOAD) {
+ // Jump tables are in the executable segment.
+ // VTables are in the non-executable one.
+ // Need to fill shadow for both.
+ // FIXME: reject writable if vtables are in the r/o segment. Depend on
+ // PT_RELRO?
+ uptr cur_beg = info->dlpi_addr + phdr->p_vaddr;
+ uptr cur_end = cur_beg + phdr->p_memsz;
+ if (cfi_check) {
+ VReport(1, " %zx .. %zx\n", cur_beg, cur_end);
+ b->Add(cur_beg, cur_end, cfi_check);
+ } else {
+ b->AddUnchecked(cur_beg, cur_end);
+ }
+ }
+ }
+ return 0;
+}
+
+// Init or update shadow for the current set of loaded libraries.
+void UpdateShadow() {
+ ShadowBuilder b;
+ b.Start();
+ dl_iterate_phdr(dl_iterate_phdr_cb, &b);
+ b.Install();
+}
+
+void InitShadow() {
+ CHECK_EQ(0, GetShadow());
+ CHECK_EQ(0, GetShadowSize());
+
+ uptr vma = GetMaxUserVirtualAddress();
+ // Shadow is 2 -> 2**kShadowGranularity.
+ SetShadowSize((vma >> (kShadowGranularity - 1)) + 1);
+ VReport(1, "CFI: VMA size %zx, shadow size %zx\n", vma, GetShadowSize());
+
+ UpdateShadow();
+}
+
+THREADLOCAL int in_loader;
+Mutex shadow_update_lock;
+
+void EnterLoader() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ if (in_loader == 0) {
+ shadow_update_lock.Lock();
+ }
+ ++in_loader;
+}
+
+void ExitLoader() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ CHECK(in_loader > 0);
+ --in_loader;
+ UpdateShadow();
+ if (in_loader == 0) {
+ shadow_update_lock.Unlock();
+ }
+}
+
+ALWAYS_INLINE void CfiSlowPathCommon(u64 CallSiteTypeId, void *Ptr,
+ void *DiagData) {
+ uptr Addr = (uptr)Ptr;
+ VReport(3, "__cfi_slowpath: %llx, %p\n", CallSiteTypeId, Ptr);
+ ShadowValue sv = ShadowValue::load(Addr);
+ if (sv.is_invalid()) {
+ VReport(1, "CFI: invalid memory region for a check target: %p\n", Ptr);
+#ifdef CFI_ENABLE_DIAG
+ if (DiagData) {
+ __ubsan_handle_cfi_check_fail(
+ reinterpret_cast<__ubsan::CFICheckFailData *>(DiagData), Addr, false);
+ return;
+ }
+#endif
+ Trap();
+ }
+ if (sv.is_unchecked()) {
+ VReport(2, "CFI: unchecked call (shadow=FFFF): %p\n", Ptr);
+ return;
+ }
+ CFICheckFn cfi_check = sv.get_cfi_check();
+ VReport(2, "__cfi_check at %p\n", (void *)cfi_check);
+ cfi_check(CallSiteTypeId, Ptr, DiagData);
+}
+
+void InitializeFlags() {
+ SetCommonFlagsDefaults();
+#ifdef CFI_ENABLE_DIAG
+ __ubsan::Flags *uf = __ubsan::flags();
+ uf->SetDefaults();
+#endif
+
+ FlagParser cfi_parser;
+ RegisterCommonFlags(&cfi_parser);
+ cfi_parser.ParseStringFromEnv("CFI_OPTIONS");
+
+#ifdef CFI_ENABLE_DIAG
+ FlagParser ubsan_parser;
+ __ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
+ RegisterCommonFlags(&ubsan_parser);
+
+ const char *ubsan_default_options = __ubsan_default_options();
+ ubsan_parser.ParseString(ubsan_default_options);
+ ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
+#endif
+
+ InitializeCommonFlags();
+
+ if (Verbosity())
+ ReportUnrecognizedFlags();
+
+ if (common_flags()->help) {
+ cfi_parser.PrintFlagDescriptions();
+ }
+}
+
+} // namespace __cfi
+
+using namespace __cfi;
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__cfi_slowpath(u64 CallSiteTypeId, void *Ptr) {
+ CfiSlowPathCommon(CallSiteTypeId, Ptr, nullptr);
+}
+
+#ifdef CFI_ENABLE_DIAG
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__cfi_slowpath_diag(u64 CallSiteTypeId, void *Ptr, void *DiagData) {
+ CfiSlowPathCommon(CallSiteTypeId, Ptr, DiagData);
+}
+#endif
+
+static void EnsureInterceptorsInitialized();
+
+// Setup shadow for dlopen()ed libraries.
+// The actual shadow setup happens after dlopen() returns, which means that
+// a library can not be a target of any CFI checks while its constructors are
+// running. It's unclear how to fix this without some extra help from libc.
+// In glibc, mmap inside dlopen is not interceptable.
+// Maybe a seccomp-bpf filter?
+// We could insert a high-priority constructor into the library, but that would
+// not help with the uninstrumented libraries.
+INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
+ EnsureInterceptorsInitialized();
+ EnterLoader();
+ void *handle = REAL(dlopen)(filename, flag);
+ ExitLoader();
+ return handle;
+}
+
+INTERCEPTOR(int, dlclose, void *handle) {
+ EnsureInterceptorsInitialized();
+ EnterLoader();
+ int res = REAL(dlclose)(handle);
+ ExitLoader();
+ return res;
+}
+
+static Mutex interceptor_init_lock;
+static bool interceptors_inited = false;
+
+static void EnsureInterceptorsInitialized() {
+ Lock lock(&interceptor_init_lock);
+ if (interceptors_inited)
+ return;
+
+ INTERCEPT_FUNCTION(dlopen);
+ INTERCEPT_FUNCTION(dlclose);
+
+ interceptors_inited = true;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+#if !SANITIZER_CAN_USE_PREINIT_ARRAY
+// On ELF platforms, the constructor is invoked using .preinit_array (see below)
+__attribute__((constructor(0)))
+#endif
+void __cfi_init() {
+ SanitizerToolName = "CFI";
+ InitializeFlags();
+ InitShadow();
+
+#ifdef CFI_ENABLE_DIAG
+ __ubsan::InitAsPlugin();
+#endif
+}
+
+#if SANITIZER_CAN_USE_PREINIT_ARRAY
+// On ELF platforms, run cfi initialization before any other constructors.
+// On other platforms we use the constructor attribute to arrange to run our
+// initialization early.
+extern "C" {
+__attribute__((section(".preinit_array"),
+ used)) void (*__cfi_preinit)(void) = __cfi_init;
+}
+#endif
diff --git a/contrib/libs/clang16-rt/lib/cfi/ya.make b/contrib/libs/clang16-rt/lib/cfi/ya.make
new file mode 100644
index 00000000000..cb1b2035544
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/cfi/ya.make
@@ -0,0 +1,96 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.cfi${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHAVE_RPC_XDR_H=0
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ cfi/cfi.cpp
+ interception/interception_linux.cpp
+ interception/interception_mac.cpp
+ interception/interception_type_test.cpp
+ interception/interception_win.cpp
+ sanitizer_common/sanitizer_allocator.cpp
+ sanitizer_common/sanitizer_allocator_checks.cpp
+ sanitizer_common/sanitizer_common.cpp
+ sanitizer_common/sanitizer_common_libcdep.cpp
+ sanitizer_common/sanitizer_deadlock_detector1.cpp
+ sanitizer_common/sanitizer_deadlock_detector2.cpp
+ sanitizer_common/sanitizer_errno.cpp
+ sanitizer_common/sanitizer_file.cpp
+ sanitizer_common/sanitizer_flag_parser.cpp
+ sanitizer_common/sanitizer_flags.cpp
+ sanitizer_common/sanitizer_fuchsia.cpp
+ sanitizer_common/sanitizer_libc.cpp
+ sanitizer_common/sanitizer_libignore.cpp
+ sanitizer_common/sanitizer_linux.cpp
+ sanitizer_common/sanitizer_linux_libcdep.cpp
+ sanitizer_common/sanitizer_linux_s390.cpp
+ sanitizer_common/sanitizer_mac.cpp
+ sanitizer_common/sanitizer_mac_libcdep.cpp
+ sanitizer_common/sanitizer_mutex.cpp
+ sanitizer_common/sanitizer_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+ sanitizer_common/sanitizer_platform_limits_linux.cpp
+ sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_posix.cpp
+ sanitizer_common/sanitizer_platform_limits_solaris.cpp
+ sanitizer_common/sanitizer_posix.cpp
+ sanitizer_common/sanitizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_printf.cpp
+ sanitizer_common/sanitizer_procmaps_bsd.cpp
+ sanitizer_common/sanitizer_procmaps_common.cpp
+ sanitizer_common/sanitizer_procmaps_fuchsia.cpp
+ sanitizer_common/sanitizer_procmaps_linux.cpp
+ sanitizer_common/sanitizer_procmaps_mac.cpp
+ sanitizer_common/sanitizer_procmaps_solaris.cpp
+ sanitizer_common/sanitizer_solaris.cpp
+ sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
+ sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_mac.cpp
+ sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_win.cpp
+ sanitizer_common/sanitizer_suppressions.cpp
+ sanitizer_common/sanitizer_termination.cpp
+ sanitizer_common/sanitizer_thread_registry.cpp
+ sanitizer_common/sanitizer_tls_get_addr.cpp
+ sanitizer_common/sanitizer_type_traits.cpp
+ sanitizer_common/sanitizer_win.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/cfi_diag/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/cfi_diag/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/cfi_diag/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/cfi_diag/ya.make b/contrib/libs/clang16-rt/lib/cfi_diag/ya.make
new file mode 100644
index 00000000000..b54f8643bc1
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/cfi_diag/ya.make
@@ -0,0 +1,126 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.cfi_diag${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DCFI_ENABLE_DIAG=1
+ -DHAVE_RPC_XDR_H=0
+ -DUBSAN_CAN_USE_CXXABI
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ cfi/cfi.cpp
+ interception/interception_linux.cpp
+ interception/interception_mac.cpp
+ interception/interception_type_test.cpp
+ interception/interception_win.cpp
+ sanitizer_common/sancov_flags.cpp
+ sanitizer_common/sanitizer_allocator.cpp
+ sanitizer_common/sanitizer_allocator_checks.cpp
+ sanitizer_common/sanitizer_allocator_report.cpp
+ sanitizer_common/sanitizer_chained_origin_depot.cpp
+ sanitizer_common/sanitizer_common.cpp
+ sanitizer_common/sanitizer_common_libcdep.cpp
+ sanitizer_common/sanitizer_coverage_fuchsia.cpp
+ sanitizer_common/sanitizer_coverage_libcdep_new.cpp
+ sanitizer_common/sanitizer_coverage_win_sections.cpp
+ sanitizer_common/sanitizer_deadlock_detector1.cpp
+ sanitizer_common/sanitizer_deadlock_detector2.cpp
+ sanitizer_common/sanitizer_errno.cpp
+ sanitizer_common/sanitizer_file.cpp
+ sanitizer_common/sanitizer_flag_parser.cpp
+ sanitizer_common/sanitizer_flags.cpp
+ sanitizer_common/sanitizer_fuchsia.cpp
+ sanitizer_common/sanitizer_libc.cpp
+ sanitizer_common/sanitizer_libignore.cpp
+ sanitizer_common/sanitizer_linux.cpp
+ sanitizer_common/sanitizer_linux_libcdep.cpp
+ sanitizer_common/sanitizer_linux_s390.cpp
+ sanitizer_common/sanitizer_mac.cpp
+ sanitizer_common/sanitizer_mac_libcdep.cpp
+ sanitizer_common/sanitizer_mutex.cpp
+ sanitizer_common/sanitizer_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+ sanitizer_common/sanitizer_platform_limits_linux.cpp
+ sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_posix.cpp
+ sanitizer_common/sanitizer_platform_limits_solaris.cpp
+ sanitizer_common/sanitizer_posix.cpp
+ sanitizer_common/sanitizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_printf.cpp
+ sanitizer_common/sanitizer_procmaps_bsd.cpp
+ sanitizer_common/sanitizer_procmaps_common.cpp
+ sanitizer_common/sanitizer_procmaps_fuchsia.cpp
+ sanitizer_common/sanitizer_procmaps_linux.cpp
+ sanitizer_common/sanitizer_procmaps_mac.cpp
+ sanitizer_common/sanitizer_procmaps_solaris.cpp
+ sanitizer_common/sanitizer_solaris.cpp
+ sanitizer_common/sanitizer_stack_store.cpp
+ sanitizer_common/sanitizer_stackdepot.cpp
+ sanitizer_common/sanitizer_stacktrace.cpp
+ sanitizer_common/sanitizer_stacktrace_libcdep.cpp
+ sanitizer_common/sanitizer_stacktrace_printer.cpp
+ sanitizer_common/sanitizer_stacktrace_sparc.cpp
+ sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
+ sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_mac.cpp
+ sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_win.cpp
+ sanitizer_common/sanitizer_suppressions.cpp
+ sanitizer_common/sanitizer_symbolizer.cpp
+ sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
+ sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_mac.cpp
+ sanitizer_common/sanitizer_symbolizer_markup.cpp
+ sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_report.cpp
+ sanitizer_common/sanitizer_symbolizer_win.cpp
+ sanitizer_common/sanitizer_termination.cpp
+ sanitizer_common/sanitizer_thread_registry.cpp
+ sanitizer_common/sanitizer_tls_get_addr.cpp
+ sanitizer_common/sanitizer_type_traits.cpp
+ sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
+ sanitizer_common/sanitizer_unwind_win.cpp
+ sanitizer_common/sanitizer_win.cpp
+ ubsan/ubsan_diag.cpp
+ ubsan/ubsan_flags.cpp
+ ubsan/ubsan_handlers.cpp
+ ubsan/ubsan_init.cpp
+ ubsan/ubsan_monitor.cpp
+ ubsan/ubsan_value.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/dd/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/dd/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dd/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/dd/ya.make b/contrib/libs/clang16-rt/lib/dd/ya.make
new file mode 100644
index 00000000000..0bf12728983
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dd/ya.make
@@ -0,0 +1,97 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.dd${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHAVE_RPC_XDR_H=0
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ interception/interception_linux.cpp
+ interception/interception_mac.cpp
+ interception/interception_type_test.cpp
+ interception/interception_win.cpp
+ sanitizer_common/sanitizer_allocator.cpp
+ sanitizer_common/sanitizer_allocator_checks.cpp
+ sanitizer_common/sanitizer_common.cpp
+ sanitizer_common/sanitizer_common_libcdep.cpp
+ sanitizer_common/sanitizer_deadlock_detector1.cpp
+ sanitizer_common/sanitizer_deadlock_detector2.cpp
+ sanitizer_common/sanitizer_errno.cpp
+ sanitizer_common/sanitizer_file.cpp
+ sanitizer_common/sanitizer_flag_parser.cpp
+ sanitizer_common/sanitizer_flags.cpp
+ sanitizer_common/sanitizer_fuchsia.cpp
+ sanitizer_common/sanitizer_libc.cpp
+ sanitizer_common/sanitizer_libignore.cpp
+ sanitizer_common/sanitizer_linux.cpp
+ sanitizer_common/sanitizer_linux_libcdep.cpp
+ sanitizer_common/sanitizer_linux_s390.cpp
+ sanitizer_common/sanitizer_mac.cpp
+ sanitizer_common/sanitizer_mac_libcdep.cpp
+ sanitizer_common/sanitizer_mutex.cpp
+ sanitizer_common/sanitizer_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+ sanitizer_common/sanitizer_platform_limits_linux.cpp
+ sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_posix.cpp
+ sanitizer_common/sanitizer_platform_limits_solaris.cpp
+ sanitizer_common/sanitizer_posix.cpp
+ sanitizer_common/sanitizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_printf.cpp
+ sanitizer_common/sanitizer_procmaps_bsd.cpp
+ sanitizer_common/sanitizer_procmaps_common.cpp
+ sanitizer_common/sanitizer_procmaps_fuchsia.cpp
+ sanitizer_common/sanitizer_procmaps_linux.cpp
+ sanitizer_common/sanitizer_procmaps_mac.cpp
+ sanitizer_common/sanitizer_procmaps_solaris.cpp
+ sanitizer_common/sanitizer_solaris.cpp
+ sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
+ sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_mac.cpp
+ sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_win.cpp
+ sanitizer_common/sanitizer_suppressions.cpp
+ sanitizer_common/sanitizer_termination.cpp
+ sanitizer_common/sanitizer_thread_registry.cpp
+ sanitizer_common/sanitizer_tls_get_addr.cpp
+ sanitizer_common/sanitizer_type_traits.cpp
+ sanitizer_common/sanitizer_win.cpp
+ tsan/dd/dd_interceptors.cpp
+ tsan/dd/dd_rtl.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/dfsan/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/dfsan/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan.cpp b/contrib/libs/clang16-rt/lib/dfsan/dfsan.cpp
new file mode 100644
index 00000000000..faf5a6619c2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan.cpp
@@ -0,0 +1,1262 @@
+//===-- dfsan.cpp ---------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataFlowSanitizer.
+//
+// DataFlowSanitizer runtime. This file defines the public interface to
+// DataFlowSanitizer as well as the definition of certain runtime functions
+// called automatically by the compiler (specifically the instrumentation pass
+// in llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp).
+//
+// The public interface is defined in include/sanitizer/dfsan_interface.h whose
+// functions are prefixed dfsan_ while the compiler interface functions are
+// prefixed __dfsan_.
+//===----------------------------------------------------------------------===//
+
+#include "dfsan/dfsan.h"
+
+#include "dfsan/dfsan_chained_origin_depot.h"
+#include "dfsan/dfsan_flags.h"
+#include "dfsan/dfsan_origin.h"
+#include "dfsan/dfsan_thread.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_file.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+
+using namespace __dfsan;
+
+Flags __dfsan::flags_data;
+
+// The size of TLS variables. These constants must be kept in sync with the ones
+// in DataFlowSanitizer.cpp.
+static const int kDFsanArgTlsSize = 800;
+static const int kDFsanRetvalTlsSize = 800;
+static const int kDFsanArgOriginTlsSize = 800;
+
+SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u64
+ __dfsan_retval_tls[kDFsanRetvalTlsSize / sizeof(u64)];
+SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u32 __dfsan_retval_origin_tls;
+SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u64
+ __dfsan_arg_tls[kDFsanArgTlsSize / sizeof(u64)];
+SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u32
+ __dfsan_arg_origin_tls[kDFsanArgOriginTlsSize / sizeof(u32)];
+
+// Instrumented code may set this value in terms of -dfsan-track-origins.
+// * undefined or 0: do not track origins.
+// * 1: track origins at memory store operations.
+// * 2: track origins at memory load and store operations.
+// TODO: track callsites.
+extern "C" SANITIZER_WEAK_ATTRIBUTE const int __dfsan_track_origins;
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE int dfsan_get_track_origins() {
+ return &__dfsan_track_origins ? __dfsan_track_origins : 0;
+}
+
+// On Linux/x86_64, memory is laid out as follows:
+//
+// +--------------------+ 0x800000000000 (top of memory)
+// | application 3 |
+// +--------------------+ 0x700000000000
+// | invalid |
+// +--------------------+ 0x610000000000
+// | origin 1 |
+// +--------------------+ 0x600000000000
+// | application 2 |
+// +--------------------+ 0x510000000000
+// | shadow 1 |
+// +--------------------+ 0x500000000000
+// | invalid |
+// +--------------------+ 0x400000000000
+// | origin 3 |
+// +--------------------+ 0x300000000000
+// | shadow 3 |
+// +--------------------+ 0x200000000000
+// | origin 2 |
+// +--------------------+ 0x110000000000
+// | invalid |
+// +--------------------+ 0x100000000000
+// | shadow 2 |
+// +--------------------+ 0x010000000000
+// | application 1 |
+// +--------------------+ 0x000000000000
+//
+// MEM_TO_SHADOW(mem) = mem ^ 0x500000000000
+// SHADOW_TO_ORIGIN(shadow) = shadow + 0x100000000000
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+dfsan_label __dfsan_union_load(const dfsan_label *ls, uptr n) {
+ dfsan_label label = ls[0];
+ for (uptr i = 1; i != n; ++i)
+ label |= ls[i];
+ return label;
+}
+
+// Return the union of all the n labels from addr at the high 32 bit, and the
+// origin of the first taint byte at the low 32 bit.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE u64
+__dfsan_load_label_and_origin(const void *addr, uptr n) {
+ dfsan_label label = 0;
+ u64 ret = 0;
+ uptr p = (uptr)addr;
+ dfsan_label *s = shadow_for((void *)p);
+ for (uptr i = 0; i < n; ++i) {
+ dfsan_label l = s[i];
+ if (!l)
+ continue;
+ label |= l;
+ if (!ret)
+ ret = *(dfsan_origin *)origin_for((void *)(p + i));
+ }
+ return ret | (u64)label << 32;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __dfsan_unimplemented(char *fname) {
+ if (flags().warn_unimplemented)
+ Report("WARNING: DataFlowSanitizer: call to uninstrumented function %s\n",
+ fname);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_wrapper_extern_weak_null(
+ const void *addr, char *fname) {
+ if (!addr)
+ Report(
+ "ERROR: DataFlowSanitizer: dfsan generated wrapper calling null "
+ "extern_weak function %s\nIf this only happens with dfsan, the "
+ "dfsan instrumentation pass may be accidentally optimizing out a "
+ "null check\n",
+ fname);
+}
+
+// Use '-mllvm -dfsan-debug-nonzero-labels' and break on this function
+// to try to figure out where labels are being introduced in a nominally
+// label-free program.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_nonzero_label() {
+ if (flags().warn_nonzero_labels)
+ Report("WARNING: DataFlowSanitizer: saw nonzero label\n");
+}
+
+// Indirect call to an uninstrumented vararg function. We don't have a way of
+// handling these at the moment.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__dfsan_vararg_wrapper(const char *fname) {
+ Report("FATAL: DataFlowSanitizer: unsupported indirect call to vararg "
+ "function %s\n", fname);
+ Die();
+}
+
+// Resolves the union of two labels.
+SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
+dfsan_union(dfsan_label l1, dfsan_label l2) {
+ return l1 | l2;
+}
+
+static const uptr kOriginAlign = sizeof(dfsan_origin);
+static const uptr kOriginAlignMask = ~(kOriginAlign - 1UL);
+
+static uptr OriginAlignUp(uptr u) {
+ return (u + kOriginAlign - 1) & kOriginAlignMask;
+}
+
+static uptr OriginAlignDown(uptr u) { return u & kOriginAlignMask; }
+
+// Return the origin of the first taint byte in the size bytes from the address
+// addr.
+static dfsan_origin GetOriginIfTainted(uptr addr, uptr size) {
+ for (uptr i = 0; i < size; ++i, ++addr) {
+ dfsan_label *s = shadow_for((void *)addr);
+
+ if (*s) {
+ // Validate address region.
+ CHECK(MEM_IS_SHADOW(s));
+ return *(dfsan_origin *)origin_for((void *)addr);
+ }
+ }
+ return 0;
+}
+
+// For platforms which support slow unwinder only, we need to restrict the store
+// context size to 1, basically only storing the current pc, because the slow
+// unwinder which is based on libunwind is not async signal safe and causes
+// random freezes in forking applications as well as in signal handlers.
+// DFSan supports only Linux. So we do not restrict the store context size.
+#define GET_STORE_STACK_TRACE_PC_BP(pc, bp) \
+ BufferedStackTrace stack; \
+ stack.Unwind(pc, bp, nullptr, true, flags().store_context_size);
+
+#define PRINT_CALLER_STACK_TRACE \
+ { \
+ GET_CALLER_PC_BP_SP; \
+ (void)sp; \
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp) \
+ stack.Print(); \
+ }
+
+// Return a chain with the previous ID id and the current stack.
+// from_init = true if this is the first chain of an origin tracking path.
+static u32 ChainOrigin(u32 id, StackTrace *stack, bool from_init = false) {
+ // StackDepot is not async signal safe. Do not create new chains in a signal
+ // handler.
+ DFsanThread *t = GetCurrentThread();
+ if (t && t->InSignalHandler())
+ return id;
+
+ // As an optimization the origin of an application byte is updated only when
+ // its shadow is non-zero. Because we are only interested in the origins of
+ // taint labels, it does not matter what origin a zero label has. This reduces
+ // memory write cost. MSan does similar optimization. The following invariant
+ // may not hold because of some bugs. We check the invariant to help debug.
+ if (!from_init && id == 0 && flags().check_origin_invariant) {
+ Printf(" DFSan found invalid origin invariant\n");
+ PRINT_CALLER_STACK_TRACE
+ }
+
+ Origin o = Origin::FromRawId(id);
+ stack->tag = StackTrace::TAG_UNKNOWN;
+ Origin chained = Origin::CreateChainedOrigin(o, stack);
+ return chained.raw_id();
+}
+
+static void ChainAndWriteOriginIfTainted(uptr src, uptr size, uptr dst,
+ StackTrace *stack) {
+ dfsan_origin o = GetOriginIfTainted(src, size);
+ if (o) {
+ o = ChainOrigin(o, stack);
+ *(dfsan_origin *)origin_for((void *)dst) = o;
+ }
+}
+
+// Copy the origins of the size bytes from src to dst. The source and target
+// memory ranges cannot be overlapped. This is used by memcpy. stack records the
+// stack trace of the memcpy. When dst and src are not 4-byte aligned properly,
+// origins at the unaligned address boundaries may be overwritten because four
+// contiguous bytes share the same origin.
+static void CopyOrigin(const void *dst, const void *src, uptr size,
+ StackTrace *stack) {
+ uptr d = (uptr)dst;
+ uptr beg = OriginAlignDown(d);
+ // Copy left unaligned origin if that memory is tainted.
+ if (beg < d) {
+ ChainAndWriteOriginIfTainted((uptr)src, beg + kOriginAlign - d, beg, stack);
+ beg += kOriginAlign;
+ }
+
+ uptr end = OriginAlignDown(d + size);
+ // If both ends fall into the same 4-byte slot, we are done.
+ if (end < beg)
+ return;
+
+ // Copy right unaligned origin if that memory is tainted.
+ if (end < d + size)
+ ChainAndWriteOriginIfTainted((uptr)src + (end - d), (d + size) - end, end,
+ stack);
+
+ if (beg >= end)
+ return;
+
+ // Align src up.
+ uptr src_a = OriginAlignUp((uptr)src);
+ dfsan_origin *src_o = origin_for((void *)src_a);
+ u32 *src_s = (u32 *)shadow_for((void *)src_a);
+ dfsan_origin *src_end = origin_for((void *)(src_a + (end - beg)));
+ dfsan_origin *dst_o = origin_for((void *)beg);
+ dfsan_origin last_src_o = 0;
+ dfsan_origin last_dst_o = 0;
+ for (; src_o < src_end; ++src_o, ++src_s, ++dst_o) {
+ if (!*src_s)
+ continue;
+ if (*src_o != last_src_o) {
+ last_src_o = *src_o;
+ last_dst_o = ChainOrigin(last_src_o, stack);
+ }
+ *dst_o = last_dst_o;
+ }
+}
+
+// Copy the origins of the size bytes from src to dst. The source and target
+// memory ranges may be overlapped. So the copy is done in a reverse order.
+// This is used by memmove. stack records the stack trace of the memmove.
+static void ReverseCopyOrigin(const void *dst, const void *src, uptr size,
+ StackTrace *stack) {
+ uptr d = (uptr)dst;
+ uptr end = OriginAlignDown(d + size);
+
+ // Copy right unaligned origin if that memory is tainted.
+ if (end < d + size)
+ ChainAndWriteOriginIfTainted((uptr)src + (end - d), (d + size) - end, end,
+ stack);
+
+ uptr beg = OriginAlignDown(d);
+
+ if (beg + kOriginAlign < end) {
+ // Align src up.
+ uptr src_a = OriginAlignUp((uptr)src);
+ void *src_end = (void *)(src_a + end - beg - kOriginAlign);
+ dfsan_origin *src_end_o = origin_for(src_end);
+ u32 *src_end_s = (u32 *)shadow_for(src_end);
+ dfsan_origin *src_begin_o = origin_for((void *)src_a);
+ dfsan_origin *dst = origin_for((void *)(end - kOriginAlign));
+ dfsan_origin last_src_o = 0;
+ dfsan_origin last_dst_o = 0;
+ for (; src_end_o >= src_begin_o; --src_end_o, --src_end_s, --dst) {
+ if (!*src_end_s)
+ continue;
+ if (*src_end_o != last_src_o) {
+ last_src_o = *src_end_o;
+ last_dst_o = ChainOrigin(last_src_o, stack);
+ }
+ *dst = last_dst_o;
+ }
+ }
+
+ // Copy left unaligned origin if that memory is tainted.
+ if (beg < d)
+ ChainAndWriteOriginIfTainted((uptr)src, beg + kOriginAlign - d, beg, stack);
+}
+
+// Copy or move the origins of the len bytes from src to dst. The source and
+// target memory ranges may or may not be overlapped. This is used by memory
+// transfer operations. stack records the stack trace of the memory transfer
+// operation.
+static void MoveOrigin(const void *dst, const void *src, uptr size,
+ StackTrace *stack) {
+ // Validate address regions.
+ if (!MEM_IS_SHADOW(shadow_for(dst)) ||
+ !MEM_IS_SHADOW(shadow_for((void *)((uptr)dst + size))) ||
+ !MEM_IS_SHADOW(shadow_for(src)) ||
+ !MEM_IS_SHADOW(shadow_for((void *)((uptr)src + size)))) {
+ CHECK(false);
+ return;
+ }
+ // If destination origin range overlaps with source origin range, move
+ // origins by copying origins in a reverse order; otherwise, copy origins in
+ // a normal order. The orders of origin transfer are consistent with the
+ // orders of how memcpy and memmove transfer user data.
+ uptr src_aligned_beg = OriginAlignDown((uptr)src);
+ uptr src_aligned_end = OriginAlignDown((uptr)src + size);
+ uptr dst_aligned_beg = OriginAlignDown((uptr)dst);
+ if (dst_aligned_beg < src_aligned_end && dst_aligned_beg >= src_aligned_beg)
+ return ReverseCopyOrigin(dst, src, size, stack);
+ return CopyOrigin(dst, src, size, stack);
+}
+
+// Set the size bytes from the addres dst to be the origin value.
+static void SetOrigin(const void *dst, uptr size, u32 origin) {
+ if (size == 0)
+ return;
+
+ // Origin mapping is 4 bytes per 4 bytes of application memory.
+ // Here we extend the range such that its left and right bounds are both
+ // 4 byte aligned.
+ uptr x = unaligned_origin_for((uptr)dst);
+ uptr beg = OriginAlignDown(x);
+ uptr end = OriginAlignUp(x + size); // align up.
+ u64 origin64 = ((u64)origin << 32) | origin;
+ // This is like memset, but the value is 32-bit. We unroll by 2 to write
+ // 64 bits at once. May want to unroll further to get 128-bit stores.
+ if (beg & 7ULL) {
+ if (*(u32 *)beg != origin)
+ *(u32 *)beg = origin;
+ beg += 4;
+ }
+ for (uptr addr = beg; addr < (end & ~7UL); addr += 8) {
+ if (*(u64 *)addr == origin64)
+ continue;
+ *(u64 *)addr = origin64;
+ }
+ if (end & 7ULL)
+ if (*(u32 *)(end - kOriginAlign) != origin)
+ *(u32 *)(end - kOriginAlign) = origin;
+}
+
+#define RET_CHAIN_ORIGIN(id) \
+ GET_CALLER_PC_BP_SP; \
+ (void)sp; \
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp); \
+ return ChainOrigin(id, &stack);
+
+// Return a new origin chain with the previous ID id and the current stack
+// trace.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
+__dfsan_chain_origin(dfsan_origin id) {
+ RET_CHAIN_ORIGIN(id)
+}
+
+// Return a new origin chain with the previous ID id and the current stack
+// trace if the label is tainted.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
+__dfsan_chain_origin_if_tainted(dfsan_label label, dfsan_origin id) {
+ if (!label)
+ return id;
+ RET_CHAIN_ORIGIN(id)
+}
+
+// Copy or move the origins of the len bytes from src to dst.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_mem_origin_transfer(
+ const void *dst, const void *src, uptr len) {
+ if (src == dst)
+ return;
+ GET_CALLER_PC_BP;
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp);
+ MoveOrigin(dst, src, len, &stack);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_mem_origin_transfer(
+ const void *dst, const void *src, uptr len) {
+ __dfsan_mem_origin_transfer(dst, src, len);
+}
+
+static void CopyShadow(void *dst, const void *src, uptr len) {
+ internal_memcpy((void *)__dfsan::shadow_for(dst),
+ (const void *)__dfsan::shadow_for(src),
+ len * sizeof(dfsan_label));
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_mem_shadow_transfer(
+ void *dst, const void *src, uptr len) {
+ CopyShadow(dst, src, len);
+}
+
+// Copy shadow and origins of the len bytes from src to dst.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__dfsan_mem_shadow_origin_transfer(void *dst, const void *src, uptr size) {
+ if (src == dst)
+ return;
+ CopyShadow(dst, src, size);
+ if (dfsan_get_track_origins()) {
+ // Duplicating code instead of calling __dfsan_mem_origin_transfer
+ // so that the getting the caller stack frame works correctly.
+ GET_CALLER_PC_BP;
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp);
+ MoveOrigin(dst, src, size, &stack);
+ }
+}
+
+// Copy shadow and origins as per __atomic_compare_exchange.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__dfsan_mem_shadow_origin_conditional_exchange(u8 condition, void *target,
+ void *expected,
+ const void *desired, uptr size) {
+ void *dst;
+ const void *src;
+ // condition is result of native call to __atomic_compare_exchange
+ if (condition) {
+ // Copy desired into target
+ dst = target;
+ src = desired;
+ } else {
+ // Copy target into expected
+ dst = expected;
+ src = target;
+ }
+ if (src == dst)
+ return;
+ CopyShadow(dst, src, size);
+ if (dfsan_get_track_origins()) {
+ // Duplicating code instead of calling __dfsan_mem_origin_transfer
+ // so that the getting the caller stack frame works correctly.
+ GET_CALLER_PC_BP;
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp);
+ MoveOrigin(dst, src, size, &stack);
+ }
+}
+
+namespace __dfsan {
+
+bool dfsan_inited = false;
+bool dfsan_init_is_running = false;
+
+void dfsan_copy_memory(void *dst, const void *src, uptr size) {
+ internal_memcpy(dst, src, size);
+ dfsan_mem_shadow_transfer(dst, src, size);
+ if (dfsan_get_track_origins())
+ dfsan_mem_origin_transfer(dst, src, size);
+}
+
+// Releases the pages within the origin address range.
+static void ReleaseOrigins(void *addr, uptr size) {
+ const uptr beg_origin_addr = (uptr)__dfsan::origin_for(addr);
+ const void *end_addr = (void *)((uptr)addr + size);
+ const uptr end_origin_addr = (uptr)__dfsan::origin_for(end_addr);
+
+ if (end_origin_addr - beg_origin_addr <
+ common_flags()->clear_shadow_mmap_threshold)
+ return;
+
+ const uptr page_size = GetPageSizeCached();
+ const uptr beg_aligned = RoundUpTo(beg_origin_addr, page_size);
+ const uptr end_aligned = RoundDownTo(end_origin_addr, page_size);
+
+ if (!MmapFixedSuperNoReserve(beg_aligned, end_aligned - beg_aligned))
+ Die();
+}
+
+static void WriteZeroShadowInRange(uptr beg, uptr end) {
+ // Don't write the label if it is already the value we need it to be.
+ // In a program where most addresses are not labeled, it is common that
+ // a page of shadow memory is entirely zeroed. The Linux copy-on-write
+ // implementation will share all of the zeroed pages, making a copy of a
+ // page when any value is written. The un-sharing will happen even if
+ // the value written does not change the value in memory. Avoiding the
+ // write when both |label| and |*labelp| are zero dramatically reduces
+ // the amount of real memory used by large programs.
+ if (!mem_is_zero((const char *)beg, end - beg))
+ internal_memset((void *)beg, 0, end - beg);
+}
+
+// Releases the pages within the shadow address range, and sets
+// the shadow addresses not on the pages to be 0.
+static void ReleaseOrClearShadows(void *addr, uptr size) {
+ const uptr beg_shadow_addr = (uptr)__dfsan::shadow_for(addr);
+ const void *end_addr = (void *)((uptr)addr + size);
+ const uptr end_shadow_addr = (uptr)__dfsan::shadow_for(end_addr);
+
+ if (end_shadow_addr - beg_shadow_addr <
+ common_flags()->clear_shadow_mmap_threshold) {
+ WriteZeroShadowInRange(beg_shadow_addr, end_shadow_addr);
+ return;
+ }
+
+ const uptr page_size = GetPageSizeCached();
+ const uptr beg_aligned = RoundUpTo(beg_shadow_addr, page_size);
+ const uptr end_aligned = RoundDownTo(end_shadow_addr, page_size);
+
+ if (beg_aligned >= end_aligned) {
+ WriteZeroShadowInRange(beg_shadow_addr, end_shadow_addr);
+ } else {
+ if (beg_aligned != beg_shadow_addr)
+ WriteZeroShadowInRange(beg_shadow_addr, beg_aligned);
+ if (end_aligned != end_shadow_addr)
+ WriteZeroShadowInRange(end_aligned, end_shadow_addr);
+ if (!MmapFixedSuperNoReserve(beg_aligned, end_aligned - beg_aligned))
+ Die();
+ }
+}
+
+void SetShadow(dfsan_label label, void *addr, uptr size, dfsan_origin origin) {
+ if (0 != label) {
+ const uptr beg_shadow_addr = (uptr)__dfsan::shadow_for(addr);
+ internal_memset((void *)beg_shadow_addr, label, size);
+ if (dfsan_get_track_origins())
+ SetOrigin(addr, size, origin);
+ return;
+ }
+
+ if (dfsan_get_track_origins())
+ ReleaseOrigins(addr, size);
+
+ ReleaseOrClearShadows(addr, size);
+}
+
+} // namespace __dfsan
+
+// If the label s is tainted, set the size bytes from the address p to be a new
+// origin chain with the previous ID o and the current stack trace. This is
+// used by instrumentation to reduce code size when too much code is inserted.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_maybe_store_origin(
+ dfsan_label s, void *p, uptr size, dfsan_origin o) {
+ if (UNLIKELY(s)) {
+ GET_CALLER_PC_BP_SP;
+ (void)sp;
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp);
+ SetOrigin(p, size, ChainOrigin(o, &stack));
+ }
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_set_label(
+ dfsan_label label, dfsan_origin origin, void *addr, uptr size) {
+ __dfsan::SetShadow(label, addr, size, origin);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void dfsan_set_label(dfsan_label label, void *addr, uptr size) {
+ dfsan_origin init_origin = 0;
+ if (label && dfsan_get_track_origins()) {
+ GET_CALLER_PC_BP;
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp);
+ init_origin = ChainOrigin(0, &stack, true);
+ }
+ __dfsan::SetShadow(label, addr, size, init_origin);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void dfsan_add_label(dfsan_label label, void *addr, uptr size) {
+ if (0 == label)
+ return;
+
+ if (dfsan_get_track_origins()) {
+ GET_CALLER_PC_BP;
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp);
+ dfsan_origin init_origin = ChainOrigin(0, &stack, true);
+ SetOrigin(addr, size, init_origin);
+ }
+
+ for (dfsan_label *labelp = shadow_for(addr); size != 0; --size, ++labelp)
+ *labelp |= label;
+}
+
+// Unlike the other dfsan interface functions the behavior of this function
+// depends on the label of one of its arguments. Hence it is implemented as a
+// custom function.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
+__dfsw_dfsan_get_label(long data, dfsan_label data_label,
+ dfsan_label *ret_label) {
+ *ret_label = 0;
+ return data_label;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label __dfso_dfsan_get_label(
+ long data, dfsan_label data_label, dfsan_label *ret_label,
+ dfsan_origin data_origin, dfsan_origin *ret_origin) {
+ *ret_label = 0;
+ *ret_origin = 0;
+ return data_label;
+}
+
+// This function is used if dfsan_get_origin is called when origin tracking is
+// off.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin __dfsw_dfsan_get_origin(
+ long data, dfsan_label data_label, dfsan_label *ret_label) {
+ *ret_label = 0;
+ return 0;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin __dfso_dfsan_get_origin(
+ long data, dfsan_label data_label, dfsan_label *ret_label,
+ dfsan_origin data_origin, dfsan_origin *ret_origin) {
+ *ret_label = 0;
+ *ret_origin = 0;
+ return data_origin;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
+dfsan_read_label(const void *addr, uptr size) {
+ if (size == 0)
+ return 0;
+ return __dfsan_union_load(shadow_for(addr), size);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
+dfsan_read_origin_of_first_taint(const void *addr, uptr size) {
+ return GetOriginIfTainted((uptr)addr, size);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE void dfsan_set_label_origin(dfsan_label label,
+ dfsan_origin origin,
+ void *addr,
+ uptr size) {
+ __dfsan_set_label(label, origin, addr, size);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE int
+dfsan_has_label(dfsan_label label, dfsan_label elem) {
+ return (label & elem) == elem;
+}
+
+namespace __dfsan {
+
+typedef void (*dfsan_conditional_callback_t)(dfsan_label label,
+ dfsan_origin origin);
+static dfsan_conditional_callback_t conditional_callback = nullptr;
+static dfsan_label labels_in_signal_conditional = 0;
+
+static void ConditionalCallback(dfsan_label label, dfsan_origin origin) {
+ // Programs have many branches. For efficiency the conditional sink callback
+ // handler needs to ignore as many as possible as early as possible.
+ if (label == 0) {
+ return;
+ }
+ if (conditional_callback == nullptr) {
+ return;
+ }
+
+ // This initial ConditionalCallback handler needs to be in here in dfsan
+ // runtime (rather than being an entirely user implemented hook) so that it
+ // has access to dfsan thread information.
+ DFsanThread *t = GetCurrentThread();
+ // A callback operation which does useful work (like record the flow) will
+ // likely be too long executed in a signal handler.
+ if (t && t->InSignalHandler()) {
+ // Record set of labels used in signal handler for completeness.
+ labels_in_signal_conditional |= label;
+ return;
+ }
+
+ conditional_callback(label, origin);
+}
+
+} // namespace __dfsan
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__dfsan_conditional_callback_origin(dfsan_label label, dfsan_origin origin) {
+ __dfsan::ConditionalCallback(label, origin);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_conditional_callback(
+ dfsan_label label) {
+ __dfsan::ConditionalCallback(label, 0);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_set_conditional_callback(
+ __dfsan::dfsan_conditional_callback_t callback) {
+ __dfsan::conditional_callback = callback;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
+dfsan_get_labels_in_signal_conditional() {
+ return __dfsan::labels_in_signal_conditional;
+}
+
+namespace __dfsan {
+
+typedef void (*dfsan_reaches_function_callback_t)(dfsan_label label,
+ dfsan_origin origin,
+ const char *file,
+ unsigned int line,
+ const char *function);
+static dfsan_reaches_function_callback_t reaches_function_callback = nullptr;
+static dfsan_label labels_in_signal_reaches_function = 0;
+
+static void ReachesFunctionCallback(dfsan_label label, dfsan_origin origin,
+ const char *file, unsigned int line,
+ const char *function) {
+ if (label == 0) {
+ return;
+ }
+ if (reaches_function_callback == nullptr) {
+ return;
+ }
+
+ // This initial ReachesFunctionCallback handler needs to be in here in dfsan
+ // runtime (rather than being an entirely user implemented hook) so that it
+ // has access to dfsan thread information.
+ DFsanThread *t = GetCurrentThread();
+ // A callback operation which does useful work (like record the flow) will
+ // likely be too long executed in a signal handler.
+ if (t && t->InSignalHandler()) {
+ // Record set of labels used in signal handler for completeness.
+ labels_in_signal_reaches_function |= label;
+ return;
+ }
+
+ reaches_function_callback(label, origin, file, line, function);
+}
+
+} // namespace __dfsan
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__dfsan_reaches_function_callback_origin(dfsan_label label, dfsan_origin origin,
+ const char *file, unsigned int line,
+ const char *function) {
+ __dfsan::ReachesFunctionCallback(label, origin, file, line, function);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__dfsan_reaches_function_callback(dfsan_label label, const char *file,
+ unsigned int line, const char *function) {
+ __dfsan::ReachesFunctionCallback(label, 0, file, line, function);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+dfsan_set_reaches_function_callback(
+ __dfsan::dfsan_reaches_function_callback_t callback) {
+ __dfsan::reaches_function_callback = callback;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
+dfsan_get_labels_in_signal_reaches_function() {
+ return __dfsan::labels_in_signal_reaches_function;
+}
+
+class Decorator : public __sanitizer::SanitizerCommonDecorator {
+ public:
+ Decorator() : SanitizerCommonDecorator() {}
+ const char *Origin() const { return Magenta(); }
+};
+
+namespace {
+
+void PrintNoOriginTrackingWarning() {
+ Decorator d;
+ Printf(
+ " %sDFSan: origin tracking is not enabled. Did you specify the "
+ "-dfsan-track-origins=1 option?%s\n",
+ d.Warning(), d.Default());
+}
+
+void PrintNoTaintWarning(const void *address) {
+ Decorator d;
+ Printf(" %sDFSan: no tainted value at %x%s\n", d.Warning(), address,
+ d.Default());
+}
+
+void PrintInvalidOriginWarning(dfsan_label label, const void *address) {
+ Decorator d;
+ Printf(
+ " %sTaint value 0x%x (at %p) has invalid origin tracking. This can "
+ "be a DFSan bug.%s\n",
+ d.Warning(), label, address, d.Default());
+}
+
+void PrintInvalidOriginIdWarning(dfsan_origin origin) {
+ Decorator d;
+ Printf(
+ " %sOrigin Id %d has invalid origin tracking. This can "
+ "be a DFSan bug.%s\n",
+ d.Warning(), origin, d.Default());
+}
+
+bool PrintOriginTraceFramesToStr(Origin o, InternalScopedString *out) {
+ Decorator d;
+ bool found = false;
+
+ while (o.isChainedOrigin()) {
+ StackTrace stack;
+ dfsan_origin origin_id = o.raw_id();
+ o = o.getNextChainedOrigin(&stack);
+ if (o.isChainedOrigin())
+ out->append(
+ " %sOrigin value: 0x%x, Taint value was stored to memory at%s\n",
+ d.Origin(), origin_id, d.Default());
+ else
+ out->append(" %sOrigin value: 0x%x, Taint value was created at%s\n",
+ d.Origin(), origin_id, d.Default());
+
+ // Includes a trailing newline, so no need to add it again.
+ stack.PrintTo(out);
+ found = true;
+ }
+
+ return found;
+}
+
+bool PrintOriginTraceToStr(const void *addr, const char *description,
+ InternalScopedString *out) {
+ CHECK(out);
+ CHECK(dfsan_get_track_origins());
+ Decorator d;
+
+ const dfsan_label label = *__dfsan::shadow_for(addr);
+ CHECK(label);
+
+ const dfsan_origin origin = *__dfsan::origin_for(addr);
+
+ out->append(" %sTaint value 0x%x (at %p) origin tracking (%s)%s\n",
+ d.Origin(), label, addr, description ? description : "",
+ d.Default());
+
+ Origin o = Origin::FromRawId(origin);
+ return PrintOriginTraceFramesToStr(o, out);
+}
+
+} // namespace
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_print_origin_trace(
+ const void *addr, const char *description) {
+ if (!dfsan_get_track_origins()) {
+ PrintNoOriginTrackingWarning();
+ return;
+ }
+
+ const dfsan_label label = *__dfsan::shadow_for(addr);
+ if (!label) {
+ PrintNoTaintWarning(addr);
+ return;
+ }
+
+ InternalScopedString trace;
+ bool success = PrintOriginTraceToStr(addr, description, &trace);
+
+ if (trace.length())
+ Printf("%s", trace.data());
+
+ if (!success)
+ PrintInvalidOriginWarning(label, addr);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr
+dfsan_sprint_origin_trace(const void *addr, const char *description,
+ char *out_buf, uptr out_buf_size) {
+ CHECK(out_buf);
+
+ if (!dfsan_get_track_origins()) {
+ PrintNoOriginTrackingWarning();
+ return 0;
+ }
+
+ const dfsan_label label = *__dfsan::shadow_for(addr);
+ if (!label) {
+ PrintNoTaintWarning(addr);
+ return 0;
+ }
+
+ InternalScopedString trace;
+ bool success = PrintOriginTraceToStr(addr, description, &trace);
+
+ if (!success) {
+ PrintInvalidOriginWarning(label, addr);
+ return 0;
+ }
+
+ if (out_buf_size) {
+ internal_strncpy(out_buf, trace.data(), out_buf_size - 1);
+ out_buf[out_buf_size - 1] = '\0';
+ }
+
+ return trace.length();
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_print_origin_id_trace(
+ dfsan_origin origin) {
+ if (!dfsan_get_track_origins()) {
+ PrintNoOriginTrackingWarning();
+ return;
+ }
+ Origin o = Origin::FromRawId(origin);
+
+ InternalScopedString trace;
+ bool success = PrintOriginTraceFramesToStr(o, &trace);
+
+ if (trace.length())
+ Printf("%s", trace.data());
+
+ if (!success)
+ PrintInvalidOriginIdWarning(origin);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr dfsan_sprint_origin_id_trace(
+ dfsan_origin origin, char *out_buf, uptr out_buf_size) {
+ CHECK(out_buf);
+
+ if (!dfsan_get_track_origins()) {
+ PrintNoOriginTrackingWarning();
+ return 0;
+ }
+ Origin o = Origin::FromRawId(origin);
+
+ InternalScopedString trace;
+ bool success = PrintOriginTraceFramesToStr(o, &trace);
+
+ if (!success) {
+ PrintInvalidOriginIdWarning(origin);
+ return 0;
+ }
+
+ if (out_buf_size) {
+ internal_strncpy(out_buf, trace.data(), out_buf_size - 1);
+ out_buf[out_buf_size - 1] = '\0';
+ }
+
+ return trace.length();
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
+dfsan_get_init_origin(const void *addr) {
+ if (!dfsan_get_track_origins())
+ return 0;
+
+ const dfsan_label label = *__dfsan::shadow_for(addr);
+ if (!label)
+ return 0;
+
+ const dfsan_origin origin = *__dfsan::origin_for(addr);
+
+ Origin o = Origin::FromRawId(origin);
+ dfsan_origin origin_id = o.raw_id();
+ while (o.isChainedOrigin()) {
+ StackTrace stack;
+ origin_id = o.raw_id();
+ o = o.getNextChainedOrigin(&stack);
+ }
+ return origin_id;
+}
+
+void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
+ void *context,
+ bool request_fast,
+ u32 max_depth) {
+ using namespace __dfsan;
+ DFsanThread *t = GetCurrentThread();
+ if (!t || !StackTrace::WillUseFastUnwind(request_fast)) {
+ return Unwind(max_depth, pc, bp, context, 0, 0, false);
+ }
+ Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), true);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_print_stack_trace() {
+ GET_CALLER_PC_BP;
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp);
+ stack.Print();
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr
+dfsan_sprint_stack_trace(char *out_buf, uptr out_buf_size) {
+ CHECK(out_buf);
+ GET_CALLER_PC_BP;
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp);
+ return stack.PrintTo(out_buf, out_buf_size);
+}
+
+void Flags::SetDefaults() {
+#define DFSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "dfsan_flags.inc"
+#undef DFSAN_FLAG
+}
+
+static void RegisterDfsanFlags(FlagParser *parser, Flags *f) {
+#define DFSAN_FLAG(Type, Name, DefaultValue, Description) \
+ RegisterFlag(parser, #Name, Description, &f->Name);
+#include "dfsan_flags.inc"
+#undef DFSAN_FLAG
+}
+
+static void InitializeFlags() {
+ SetCommonFlagsDefaults();
+ {
+ CommonFlags cf;
+ cf.CopyFrom(*common_flags());
+ cf.intercept_tls_get_addr = true;
+ OverrideCommonFlags(cf);
+ }
+ flags().SetDefaults();
+
+ FlagParser parser;
+ RegisterCommonFlags(&parser);
+ RegisterDfsanFlags(&parser, &flags());
+ parser.ParseStringFromEnv("DFSAN_OPTIONS");
+ InitializeCommonFlags();
+ if (Verbosity()) ReportUnrecognizedFlags();
+ if (common_flags()->help) parser.PrintFlagDescriptions();
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void dfsan_clear_arg_tls(uptr offset, uptr size) {
+ internal_memset((void *)((uptr)__dfsan_arg_tls + offset), 0, size);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void dfsan_clear_thread_local_state() {
+ internal_memset(__dfsan_arg_tls, 0, sizeof(__dfsan_arg_tls));
+ internal_memset(__dfsan_retval_tls, 0, sizeof(__dfsan_retval_tls));
+
+ if (dfsan_get_track_origins()) {
+ internal_memset(__dfsan_arg_origin_tls, 0, sizeof(__dfsan_arg_origin_tls));
+ internal_memset(&__dfsan_retval_origin_tls, 0,
+ sizeof(__dfsan_retval_origin_tls));
+ }
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void dfsan_set_arg_tls(uptr offset, dfsan_label label) {
+ // 2x to match ShadowTLSAlignment.
+ // ShadowTLSAlignment should probably be changed.
+ // TODO: Consider reducing ShadowTLSAlignment to 1.
+ // Aligning to 2 bytes is probably a remnant of fast16 mode.
+ ((dfsan_label *)__dfsan_arg_tls)[offset * 2] = label;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void dfsan_set_arg_origin_tls(uptr offset, dfsan_origin o) {
+ __dfsan_arg_origin_tls[offset] = o;
+}
+
+extern "C" void dfsan_flush() {
+ const uptr maxVirtualAddress = GetMaxUserVirtualAddress();
+ for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
+ uptr start = kMemoryLayout[i].start;
+ uptr end = kMemoryLayout[i].end;
+ uptr size = end - start;
+ MappingDesc::Type type = kMemoryLayout[i].type;
+
+ if (type != MappingDesc::SHADOW && type != MappingDesc::ORIGIN)
+ continue;
+
+ // Check if the segment should be mapped based on platform constraints.
+ if (start >= maxVirtualAddress)
+ continue;
+
+ if (!MmapFixedSuperNoReserve(start, size, kMemoryLayout[i].name)) {
+ Printf("FATAL: DataFlowSanitizer: failed to clear memory region\n");
+ Die();
+ }
+ }
+ __dfsan::labels_in_signal_conditional = 0;
+ __dfsan::labels_in_signal_reaches_function = 0;
+}
+
+// TODO: CheckMemoryLayoutSanity is based on msan.
+// Consider refactoring these into a shared implementation.
+static void CheckMemoryLayoutSanity() {
+ uptr prev_end = 0;
+ for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
+ uptr start = kMemoryLayout[i].start;
+ uptr end = kMemoryLayout[i].end;
+ MappingDesc::Type type = kMemoryLayout[i].type;
+ CHECK_LT(start, end);
+ CHECK_EQ(prev_end, start);
+ CHECK(addr_is_type(start, type));
+ CHECK(addr_is_type((start + end) / 2, type));
+ CHECK(addr_is_type(end - 1, type));
+ if (type == MappingDesc::APP) {
+ uptr addr = start;
+ CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
+ CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
+ CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
+
+ addr = (start + end) / 2;
+ CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
+ CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
+ CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
+
+ addr = end - 1;
+ CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
+ CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
+ CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
+ }
+ prev_end = end;
+ }
+}
+
+// TODO: CheckMemoryRangeAvailability is based on msan.
+// Consider refactoring these into a shared implementation.
+static bool CheckMemoryRangeAvailability(uptr beg, uptr size) {
+ if (size > 0) {
+ uptr end = beg + size - 1;
+ if (!MemoryRangeIsAvailable(beg, end)) {
+ Printf("FATAL: Memory range %p - %p is not available.\n", beg, end);
+ return false;
+ }
+ }
+ return true;
+}
+
+// TODO: ProtectMemoryRange is based on msan.
+// Consider refactoring these into a shared implementation.
+static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) {
+ if (size > 0) {
+ void *addr = MmapFixedNoAccess(beg, size, name);
+ if (beg == 0 && addr) {
+ // Depending on the kernel configuration, we may not be able to protect
+ // the page at address zero.
+ uptr gap = 16 * GetPageSizeCached();
+ beg += gap;
+ size -= gap;
+ addr = MmapFixedNoAccess(beg, size, name);
+ }
+ if ((uptr)addr != beg) {
+ uptr end = beg + size - 1;
+ Printf("FATAL: Cannot protect memory range %p - %p (%s).\n", beg, end,
+ name);
+ return false;
+ }
+ }
+ return true;
+}
+
+// TODO: InitShadow is based on msan.
+// Consider refactoring these into a shared implementation.
+bool InitShadow(bool init_origins) {
+ // Let user know mapping parameters first.
+ VPrintf(1, "dfsan_init %p\n", (void *)&__dfsan::dfsan_init);
+ for (unsigned i = 0; i < kMemoryLayoutSize; ++i)
+ VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout[i].name, kMemoryLayout[i].start,
+ kMemoryLayout[i].end - 1);
+
+ CheckMemoryLayoutSanity();
+
+ if (!MEM_IS_APP(&__dfsan::dfsan_init)) {
+ Printf("FATAL: Code %p is out of application range. Non-PIE build?\n",
+ (uptr)&__dfsan::dfsan_init);
+ return false;
+ }
+
+ const uptr maxVirtualAddress = GetMaxUserVirtualAddress();
+
+ for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
+ uptr start = kMemoryLayout[i].start;
+ uptr end = kMemoryLayout[i].end;
+ uptr size = end - start;
+ MappingDesc::Type type = kMemoryLayout[i].type;
+
+ // Check if the segment should be mapped based on platform constraints.
+ if (start >= maxVirtualAddress)
+ continue;
+
+ bool map = type == MappingDesc::SHADOW ||
+ (init_origins && type == MappingDesc::ORIGIN);
+ bool protect = type == MappingDesc::INVALID ||
+ (!init_origins && type == MappingDesc::ORIGIN);
+ CHECK(!(map && protect));
+ if (!map && !protect)
+ CHECK(type == MappingDesc::APP);
+ if (map) {
+ if (!CheckMemoryRangeAvailability(start, size))
+ return false;
+ if (!MmapFixedSuperNoReserve(start, size, kMemoryLayout[i].name))
+ return false;
+ if (common_flags()->use_madv_dontdump)
+ DontDumpShadowMemory(start, size);
+ }
+ if (protect) {
+ if (!CheckMemoryRangeAvailability(start, size))
+ return false;
+ if (!ProtectMemoryRange(start, size, kMemoryLayout[i].name))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void DFsanInit(int argc, char **argv, char **envp) {
+ CHECK(!dfsan_init_is_running);
+ if (dfsan_inited)
+ return;
+ dfsan_init_is_running = true;
+ SanitizerToolName = "DataflowSanitizer";
+
+ AvoidCVE_2016_2143();
+
+ InitializeFlags();
+
+ CheckASLR();
+
+ InitShadow(dfsan_get_track_origins());
+
+ initialize_interceptors();
+
+ // Set up threads
+ DFsanTSDInit(DFsanTSDDtor);
+
+ dfsan_allocator_init();
+
+ DFsanThread *main_thread = DFsanThread::Create(nullptr, nullptr);
+ SetCurrentThread(main_thread);
+ main_thread->Init();
+
+ dfsan_init_is_running = false;
+ dfsan_inited = true;
+}
+
+namespace __dfsan {
+
+void dfsan_init() { DFsanInit(0, nullptr, nullptr); }
+
+} // namespace __dfsan
+
+#if SANITIZER_CAN_USE_PREINIT_ARRAY
+__attribute__((section(".preinit_array"),
+ used)) static void (*dfsan_init_ptr)(int, char **,
+ char **) = DFsanInit;
+#endif
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan.h b/contrib/libs/clang16-rt/lib/dfsan/dfsan.h
new file mode 100644
index 00000000000..29938a08de5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan.h
@@ -0,0 +1,112 @@
+//===-- dfsan.h -------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataFlowSanitizer.
+//
+// Private DFSan header.
+//===----------------------------------------------------------------------===//
+
+#ifndef DFSAN_H
+#define DFSAN_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+#include "dfsan_platform.h"
+
+using __sanitizer::u32;
+using __sanitizer::u8;
+using __sanitizer::uptr;
+
+// Copy declarations from public sanitizer/dfsan_interface.h header here.
+typedef u8 dfsan_label;
+typedef u32 dfsan_origin;
+
+extern "C" {
+void dfsan_add_label(dfsan_label label, void *addr, uptr size);
+void dfsan_set_label(dfsan_label label, void *addr, uptr size);
+dfsan_label dfsan_read_label(const void *addr, uptr size);
+dfsan_label dfsan_union(dfsan_label l1, dfsan_label l2);
+// Zero out [offset, offset+size) from __dfsan_arg_tls.
+void dfsan_clear_arg_tls(uptr offset, uptr size);
+// Zero out the TLS storage.
+void dfsan_clear_thread_local_state();
+
+// Set DFSan label and origin TLS of argument for a call.
+// Note that offset may not correspond with argument number.
+// Some arguments (aggregate/array) will use several offsets.
+void dfsan_set_arg_tls(uptr offset, dfsan_label label);
+void dfsan_set_arg_origin_tls(uptr offset, dfsan_origin o);
+
+// Return the origin associated with the first taint byte in the size bytes
+// from the address addr.
+dfsan_origin dfsan_read_origin_of_first_taint(const void *addr, uptr size);
+
+// Set the data within [addr, addr+size) with label and origin.
+void dfsan_set_label_origin(dfsan_label label, dfsan_origin origin, void *addr,
+ uptr size);
+
+// Copy or move the origins of the len bytes from src to dst.
+void dfsan_mem_origin_transfer(const void *dst, const void *src, uptr len);
+
+// Copy shadow bytes from src to dst.
+// Note this preserves distinct taint labels at specific offsets.
+void dfsan_mem_shadow_transfer(void *dst, const void *src, uptr len);
+} // extern "C"
+
+template <typename T>
+void dfsan_set_label(dfsan_label label, T &data) {
+ dfsan_set_label(label, (void *)&data, sizeof(T));
+}
+
+namespace __dfsan {
+
+extern bool dfsan_inited;
+extern bool dfsan_init_is_running;
+
+void initialize_interceptors();
+
+inline dfsan_label *shadow_for(void *ptr) {
+ return (dfsan_label *)MEM_TO_SHADOW(ptr);
+}
+
+inline const dfsan_label *shadow_for(const void *ptr) {
+ return shadow_for(const_cast<void *>(ptr));
+}
+
+inline uptr unaligned_origin_for(uptr ptr) { return MEM_TO_ORIGIN(ptr); }
+
+inline dfsan_origin *origin_for(void *ptr) {
+ auto aligned_addr = unaligned_origin_for(reinterpret_cast<uptr>(ptr)) &
+ ~(sizeof(dfsan_origin) - 1);
+ return reinterpret_cast<dfsan_origin *>(aligned_addr);
+}
+
+inline const dfsan_origin *origin_for(const void *ptr) {
+ return origin_for(const_cast<void *>(ptr));
+}
+
+void dfsan_copy_memory(void *dst, const void *src, uptr size);
+
+void dfsan_allocator_init();
+void dfsan_deallocate(void *ptr);
+
+void *dfsan_malloc(uptr size);
+void *dfsan_calloc(uptr nmemb, uptr size);
+void *dfsan_realloc(void *ptr, uptr size);
+void *dfsan_reallocarray(void *ptr, uptr nmemb, uptr size);
+void *dfsan_valloc(uptr size);
+void *dfsan_pvalloc(uptr size);
+void *dfsan_aligned_alloc(uptr alignment, uptr size);
+void *dfsan_memalign(uptr alignment, uptr size);
+int dfsan_posix_memalign(void **memptr, uptr alignment, uptr size);
+
+void dfsan_init();
+
+} // namespace __dfsan
+
+#endif // DFSAN_H
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan_allocator.cpp b/contrib/libs/clang16-rt/lib/dfsan/dfsan_allocator.cpp
new file mode 100644
index 00000000000..5fb8fef213b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan_allocator.cpp
@@ -0,0 +1,297 @@
+//===-- dfsan_allocator.cpp -------------------------- --------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataflowSanitizer.
+//
+// DataflowSanitizer allocator.
+//===----------------------------------------------------------------------===//
+
+#include "dfsan_allocator.h"
+
+#include "dfsan.h"
+#include "dfsan_flags.h"
+#include "dfsan_thread.h"
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_checks.h"
+#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
+#include "sanitizer_common/sanitizer_errno.h"
+
+namespace __dfsan {
+
+struct Metadata {
+ uptr requested_size;
+};
+
+struct DFsanMapUnmapCallback {
+ void OnMap(uptr p, uptr size) const { dfsan_set_label(0, (void *)p, size); }
+ void OnUnmap(uptr p, uptr size) const { dfsan_set_label(0, (void *)p, size); }
+};
+
+#if defined(__aarch64__)
+const uptr kAllocatorSpace = 0xE00000000000ULL;
+#else
+const uptr kAllocatorSpace = 0x700000000000ULL;
+#endif
+const uptr kMaxAllowedMallocSize = 8UL << 30;
+
+struct AP64 { // Allocator64 parameters. Deliberately using a short name.
+ static const uptr kSpaceBeg = kAllocatorSpace;
+ static const uptr kSpaceSize = 0x40000000000; // 4T.
+ static const uptr kMetadataSize = sizeof(Metadata);
+ typedef DefaultSizeClassMap SizeClassMap;
+ typedef DFsanMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+ using AddressSpaceView = LocalAddressSpaceView;
+};
+
+typedef SizeClassAllocator64<AP64> PrimaryAllocator;
+
+typedef CombinedAllocator<PrimaryAllocator> Allocator;
+typedef Allocator::AllocatorCache AllocatorCache;
+
+static Allocator allocator;
+static AllocatorCache fallback_allocator_cache;
+static StaticSpinMutex fallback_mutex;
+
+static uptr max_malloc_size;
+
+void dfsan_allocator_init() {
+ SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null);
+ allocator.Init(common_flags()->allocator_release_to_os_interval_ms);
+ if (common_flags()->max_allocation_size_mb)
+ max_malloc_size = Min(common_flags()->max_allocation_size_mb << 20,
+ kMaxAllowedMallocSize);
+ else
+ max_malloc_size = kMaxAllowedMallocSize;
+}
+
+AllocatorCache *GetAllocatorCache(DFsanThreadLocalMallocStorage *ms) {
+ CHECK(ms);
+ CHECK_LE(sizeof(AllocatorCache), sizeof(ms->allocator_cache));
+ return reinterpret_cast<AllocatorCache *>(ms->allocator_cache);
+}
+
+void DFsanThreadLocalMallocStorage::CommitBack() {
+ allocator.SwallowCache(GetAllocatorCache(this));
+}
+
+static void *DFsanAllocate(uptr size, uptr alignment, bool zeroise) {
+ if (size > max_malloc_size) {
+ if (AllocatorMayReturnNull()) {
+ Report("WARNING: DataflowSanitizer failed to allocate 0x%zx bytes\n",
+ size);
+ return nullptr;
+ }
+ BufferedStackTrace stack;
+ ReportAllocationSizeTooBig(size, max_malloc_size, &stack);
+ }
+ if (UNLIKELY(IsRssLimitExceeded())) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ BufferedStackTrace stack;
+ ReportRssLimitExceeded(&stack);
+ }
+ DFsanThread *t = GetCurrentThread();
+ void *allocated;
+ if (t) {
+ AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
+ allocated = allocator.Allocate(cache, size, alignment);
+ } else {
+ SpinMutexLock l(&fallback_mutex);
+ AllocatorCache *cache = &fallback_allocator_cache;
+ allocated = allocator.Allocate(cache, size, alignment);
+ }
+ if (UNLIKELY(!allocated)) {
+ SetAllocatorOutOfMemory();
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ BufferedStackTrace stack;
+ ReportOutOfMemory(size, &stack);
+ }
+ Metadata *meta =
+ reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated));
+ meta->requested_size = size;
+ if (zeroise) {
+ internal_memset(allocated, 0, size);
+ dfsan_set_label(0, allocated, size);
+ } else if (flags().zero_in_malloc) {
+ dfsan_set_label(0, allocated, size);
+ }
+ return allocated;
+}
+
+void dfsan_deallocate(void *p) {
+ CHECK(p);
+ Metadata *meta = reinterpret_cast<Metadata *>(allocator.GetMetaData(p));
+ uptr size = meta->requested_size;
+ meta->requested_size = 0;
+ if (flags().zero_in_free)
+ dfsan_set_label(0, p, size);
+ DFsanThread *t = GetCurrentThread();
+ if (t) {
+ AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
+ allocator.Deallocate(cache, p);
+ } else {
+ SpinMutexLock l(&fallback_mutex);
+ AllocatorCache *cache = &fallback_allocator_cache;
+ allocator.Deallocate(cache, p);
+ }
+}
+
+void *DFsanReallocate(void *old_p, uptr new_size, uptr alignment) {
+ Metadata *meta = reinterpret_cast<Metadata *>(allocator.GetMetaData(old_p));
+ uptr old_size = meta->requested_size;
+ uptr actually_allocated_size = allocator.GetActuallyAllocatedSize(old_p);
+ if (new_size <= actually_allocated_size) {
+ // We are not reallocating here.
+ meta->requested_size = new_size;
+ if (new_size > old_size && flags().zero_in_malloc)
+ dfsan_set_label(0, (char *)old_p + old_size, new_size - old_size);
+ return old_p;
+ }
+ uptr memcpy_size = Min(new_size, old_size);
+ void *new_p = DFsanAllocate(new_size, alignment, false /*zeroise*/);
+ if (new_p) {
+ dfsan_copy_memory(new_p, old_p, memcpy_size);
+ dfsan_deallocate(old_p);
+ }
+ return new_p;
+}
+
+void *DFsanCalloc(uptr nmemb, uptr size) {
+ if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ BufferedStackTrace stack;
+ ReportCallocOverflow(nmemb, size, &stack);
+ }
+ return DFsanAllocate(nmemb * size, sizeof(u64), true /*zeroise*/);
+}
+
+static uptr AllocationSize(const void *p) {
+ if (!p)
+ return 0;
+ const void *beg = allocator.GetBlockBegin(p);
+ if (beg != p)
+ return 0;
+ Metadata *b = (Metadata *)allocator.GetMetaData(p);
+ return b->requested_size;
+}
+
+void *dfsan_malloc(uptr size) {
+ return SetErrnoOnNull(DFsanAllocate(size, sizeof(u64), false /*zeroise*/));
+}
+
+void *dfsan_calloc(uptr nmemb, uptr size) {
+ return SetErrnoOnNull(DFsanCalloc(nmemb, size));
+}
+
+void *dfsan_realloc(void *ptr, uptr size) {
+ if (!ptr)
+ return SetErrnoOnNull(DFsanAllocate(size, sizeof(u64), false /*zeroise*/));
+ if (size == 0) {
+ dfsan_deallocate(ptr);
+ return nullptr;
+ }
+ return SetErrnoOnNull(DFsanReallocate(ptr, size, sizeof(u64)));
+}
+
+void *dfsan_reallocarray(void *ptr, uptr nmemb, uptr size) {
+ if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+ errno = errno_ENOMEM;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ BufferedStackTrace stack;
+ ReportReallocArrayOverflow(nmemb, size, &stack);
+ }
+ return dfsan_realloc(ptr, nmemb * size);
+}
+
+void *dfsan_valloc(uptr size) {
+ return SetErrnoOnNull(
+ DFsanAllocate(size, GetPageSizeCached(), false /*zeroise*/));
+}
+
+void *dfsan_pvalloc(uptr size) {
+ uptr PageSize = GetPageSizeCached();
+ if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) {
+ errno = errno_ENOMEM;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ BufferedStackTrace stack;
+ ReportPvallocOverflow(size, &stack);
+ }
+ // pvalloc(0) should allocate one page.
+ size = size ? RoundUpTo(size, PageSize) : PageSize;
+ return SetErrnoOnNull(DFsanAllocate(size, PageSize, false /*zeroise*/));
+}
+
+void *dfsan_aligned_alloc(uptr alignment, uptr size) {
+ if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ BufferedStackTrace stack;
+ ReportInvalidAlignedAllocAlignment(size, alignment, &stack);
+ }
+ return SetErrnoOnNull(DFsanAllocate(size, alignment, false /*zeroise*/));
+}
+
+void *dfsan_memalign(uptr alignment, uptr size) {
+ if (UNLIKELY(!IsPowerOfTwo(alignment))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ BufferedStackTrace stack;
+ ReportInvalidAllocationAlignment(alignment, &stack);
+ }
+ return SetErrnoOnNull(DFsanAllocate(size, alignment, false /*zeroise*/));
+}
+
+int dfsan_posix_memalign(void **memptr, uptr alignment, uptr size) {
+ if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
+ if (AllocatorMayReturnNull())
+ return errno_EINVAL;
+ BufferedStackTrace stack;
+ ReportInvalidPosixMemalignAlignment(alignment, &stack);
+ }
+ void *ptr = DFsanAllocate(size, alignment, false /*zeroise*/);
+ if (UNLIKELY(!ptr))
+ // OOM error is already taken care of by DFsanAllocate.
+ return errno_ENOMEM;
+ CHECK(IsAligned((uptr)ptr, alignment));
+ *memptr = ptr;
+ return 0;
+}
+
+} // namespace __dfsan
+
+using namespace __dfsan;
+
+uptr __sanitizer_get_current_allocated_bytes() {
+ uptr stats[AllocatorStatCount];
+ allocator.GetStats(stats);
+ return stats[AllocatorStatAllocated];
+}
+
+uptr __sanitizer_get_heap_size() {
+ uptr stats[AllocatorStatCount];
+ allocator.GetStats(stats);
+ return stats[AllocatorStatMapped];
+}
+
+uptr __sanitizer_get_free_bytes() { return 1; }
+
+uptr __sanitizer_get_unmapped_bytes() { return 1; }
+
+uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; }
+
+int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; }
+
+uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); }
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan_allocator.h b/contrib/libs/clang16-rt/lib/dfsan/dfsan_allocator.h
new file mode 100644
index 00000000000..3b4171b6314
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan_allocator.h
@@ -0,0 +1,30 @@
+//===-- dfsan_allocator.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataflowSanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DFSAN_ALLOCATOR_H
+#define DFSAN_ALLOCATOR_H
+
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace __dfsan {
+
+struct DFsanThreadLocalMallocStorage {
+ ALIGNED(8) uptr allocator_cache[96 * (512 * 8 + 16)]; // Opaque.
+ void CommitBack();
+
+ private:
+ // These objects are allocated via mmap() and are zero-initialized.
+ DFsanThreadLocalMallocStorage() {}
+};
+
+} // namespace __dfsan
+#endif // DFSAN_ALLOCATOR_H
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan_chained_origin_depot.cpp b/contrib/libs/clang16-rt/lib/dfsan/dfsan_chained_origin_depot.cpp
new file mode 100644
index 00000000000..9ec598bf2ce
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan_chained_origin_depot.cpp
@@ -0,0 +1,22 @@
+//===-- dfsan_chained_origin_depot.cpp ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataFlowSanitizer.
+//
+// A storage for chained origins.
+//===----------------------------------------------------------------------===//
+
+#include "dfsan_chained_origin_depot.h"
+
+namespace __dfsan {
+
+static ChainedOriginDepot chainedOriginDepot;
+
+ChainedOriginDepot* GetChainedOriginDepot() { return &chainedOriginDepot; }
+
+} // namespace __dfsan
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan_chained_origin_depot.h b/contrib/libs/clang16-rt/lib/dfsan/dfsan_chained_origin_depot.h
new file mode 100644
index 00000000000..d715ef707f4
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan_chained_origin_depot.h
@@ -0,0 +1,26 @@
+//===-- dfsan_chained_origin_depot.h ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataFlowSanitizer.
+//
+// A storage for chained origins.
+//===----------------------------------------------------------------------===//
+
+#ifndef DFSAN_CHAINED_ORIGIN_DEPOT_H
+#define DFSAN_CHAINED_ORIGIN_DEPOT_H
+
+#include "sanitizer_common/sanitizer_chained_origin_depot.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace __dfsan {
+
+ChainedOriginDepot* GetChainedOriginDepot();
+
+} // namespace __dfsan
+
+#endif // DFSAN_CHAINED_ORIGIN_DEPOT_H
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan_custom.cpp b/contrib/libs/clang16-rt/lib/dfsan/dfsan_custom.cpp
new file mode 100644
index 00000000000..6f41e225d9e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan_custom.cpp
@@ -0,0 +1,2488 @@
+//===-- dfsan_custom.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataFlowSanitizer.
+//
+// This file defines the custom functions listed in done_abilist.txt.
+//===----------------------------------------------------------------------===//
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <ctype.h>
+#include <dlfcn.h>
+#include <link.h>
+#include <poll.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/resource.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "dfsan/dfsan.h"
+#include "dfsan/dfsan_chained_origin_depot.h"
+#include "dfsan/dfsan_flags.h"
+#include "dfsan/dfsan_thread.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+using namespace __dfsan;
+
+#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) \
+ do { \
+ if (f) \
+ f(__VA_ARGS__); \
+ } while (false)
+#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);
+
+// Async-safe, non-reentrant spin lock.
+class SignalSpinLocker {
+ public:
+ SignalSpinLocker() {
+ sigset_t all_set;
+ sigfillset(&all_set);
+ pthread_sigmask(SIG_SETMASK, &all_set, &saved_thread_mask_);
+ sigactions_mu.Lock();
+ }
+ ~SignalSpinLocker() {
+ sigactions_mu.Unlock();
+ pthread_sigmask(SIG_SETMASK, &saved_thread_mask_, nullptr);
+ }
+
+ private:
+ static StaticSpinMutex sigactions_mu;
+ sigset_t saved_thread_mask_;
+
+ SignalSpinLocker(const SignalSpinLocker &) = delete;
+ SignalSpinLocker &operator=(const SignalSpinLocker &) = delete;
+};
+
+StaticSpinMutex SignalSpinLocker::sigactions_mu;
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE int
+__dfsw_stat(const char *path, struct stat *buf, dfsan_label path_label,
+ dfsan_label buf_label, dfsan_label *ret_label) {
+ int ret = stat(path, buf);
+ if (ret == 0)
+ dfsan_set_label(0, buf, sizeof(struct stat));
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_stat(
+ const char *path, struct stat *buf, dfsan_label path_label,
+ dfsan_label buf_label, dfsan_label *ret_label, dfsan_origin path_origin,
+ dfsan_origin buf_origin, dfsan_origin *ret_origin) {
+ int ret = __dfsw_stat(path, buf, path_label, buf_label, ret_label);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_fstat(int fd, struct stat *buf,
+ dfsan_label fd_label,
+ dfsan_label buf_label,
+ dfsan_label *ret_label) {
+ int ret = fstat(fd, buf);
+ if (ret == 0)
+ dfsan_set_label(0, buf, sizeof(struct stat));
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_fstat(
+ int fd, struct stat *buf, dfsan_label fd_label, dfsan_label buf_label,
+ dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
+ dfsan_origin *ret_origin) {
+ int ret = __dfsw_fstat(fd, buf, fd_label, buf_label, ret_label);
+ return ret;
+}
+
+static char *dfsan_strchr_with_label(const char *s, int c, size_t *bytes_read,
+ dfsan_label s_label, dfsan_label c_label,
+ dfsan_label *ret_label) {
+ char *match_pos = nullptr;
+ for (size_t i = 0;; ++i) {
+ if (s[i] == c || s[i] == 0) {
+ // If s[i] is the \0 at the end of the string, and \0 is not the
+ // character we are searching for, then return null.
+ *bytes_read = i + 1;
+ match_pos = s[i] == 0 && c != 0 ? nullptr : const_cast<char *>(s + i);
+ break;
+ }
+ }
+ if (flags().strict_data_dependencies)
+ *ret_label = s_label;
+ else
+ *ret_label = dfsan_union(dfsan_read_label(s, *bytes_read),
+ dfsan_union(s_label, c_label));
+ return match_pos;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strchr(const char *s, int c,
+ dfsan_label s_label,
+ dfsan_label c_label,
+ dfsan_label *ret_label) {
+ size_t bytes_read;
+ return dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label,
+ ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strchr(
+ const char *s, int c, dfsan_label s_label, dfsan_label c_label,
+ dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
+ dfsan_origin *ret_origin) {
+ size_t bytes_read;
+ char *r =
+ dfsan_strchr_with_label(s, c, &bytes_read, s_label, c_label, ret_label);
+ if (flags().strict_data_dependencies) {
+ *ret_origin = s_origin;
+ } else if (*ret_label) {
+ dfsan_origin o = dfsan_read_origin_of_first_taint(s, bytes_read);
+ *ret_origin = o ? o : (s_label ? s_origin : c_origin);
+ }
+ return r;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strpbrk(const char *s,
+ const char *accept,
+ dfsan_label s_label,
+ dfsan_label accept_label,
+ dfsan_label *ret_label) {
+ const char *ret = strpbrk(s, accept);
+ if (flags().strict_data_dependencies) {
+ *ret_label = ret ? s_label : 0;
+ } else {
+ size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
+ *ret_label =
+ dfsan_union(dfsan_read_label(s, s_bytes_read),
+ dfsan_union(dfsan_read_label(accept, strlen(accept) + 1),
+ dfsan_union(s_label, accept_label)));
+ }
+ return const_cast<char *>(ret);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strpbrk(
+ const char *s, const char *accept, dfsan_label s_label,
+ dfsan_label accept_label, dfsan_label *ret_label, dfsan_origin s_origin,
+ dfsan_origin accept_origin, dfsan_origin *ret_origin) {
+ const char *ret = __dfsw_strpbrk(s, accept, s_label, accept_label, ret_label);
+ if (flags().strict_data_dependencies) {
+ if (ret)
+ *ret_origin = s_origin;
+ } else {
+ if (*ret_label) {
+ size_t s_bytes_read = (ret ? ret - s : strlen(s)) + 1;
+ dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_bytes_read);
+ if (o) {
+ *ret_origin = o;
+ } else {
+ o = dfsan_read_origin_of_first_taint(accept, strlen(accept) + 1);
+ *ret_origin = o ? o : (s_label ? s_origin : accept_origin);
+ }
+ }
+ }
+ return const_cast<char *>(ret);
+}
+
+static int dfsan_memcmp_bcmp(const void *s1, const void *s2, size_t n,
+ size_t *bytes_read) {
+ const char *cs1 = (const char *) s1, *cs2 = (const char *) s2;
+ for (size_t i = 0; i != n; ++i) {
+ if (cs1[i] != cs2[i]) {
+ *bytes_read = i + 1;
+ return cs1[i] - cs2[i];
+ }
+ }
+ *bytes_read = n;
+ return 0;
+}
+
+static dfsan_label dfsan_get_memcmp_label(const void *s1, const void *s2,
+ size_t pos) {
+ if (flags().strict_data_dependencies)
+ return 0;
+ return dfsan_union(dfsan_read_label(s1, pos), dfsan_read_label(s2, pos));
+}
+
+static void dfsan_get_memcmp_origin(const void *s1, const void *s2, size_t pos,
+ dfsan_label *ret_label,
+ dfsan_origin *ret_origin) {
+ *ret_label = dfsan_get_memcmp_label(s1, s2, pos);
+ if (*ret_label == 0)
+ return;
+ dfsan_origin o = dfsan_read_origin_of_first_taint(s1, pos);
+ *ret_origin = o ? o : dfsan_read_origin_of_first_taint(s2, pos);
+}
+
+static int dfsan_memcmp_bcmp_label(const void *s1, const void *s2, size_t n,
+ dfsan_label *ret_label) {
+ size_t bytes_read;
+ int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
+ *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
+ return r;
+}
+
+static int dfsan_memcmp_bcmp_origin(const void *s1, const void *s2, size_t n,
+ dfsan_label *ret_label,
+ dfsan_origin *ret_origin) {
+ size_t bytes_read;
+ int r = dfsan_memcmp_bcmp(s1, s2, n, &bytes_read);
+ dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
+ return r;
+}
+
+DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, uptr caller_pc,
+ const void *s1, const void *s2, size_t n,
+ dfsan_label s1_label, dfsan_label s2_label,
+ dfsan_label n_label)
+
+DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, uptr caller_pc,
+ const void *s1, const void *s2, size_t n,
+ dfsan_label s1_label, dfsan_label s2_label,
+ dfsan_label n_label, dfsan_origin s1_origin,
+ dfsan_origin s2_origin, dfsan_origin n_origin)
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2,
+ size_t n, dfsan_label s1_label,
+ dfsan_label s2_label,
+ dfsan_label n_label,
+ dfsan_label *ret_label) {
+ CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, GET_CALLER_PC(), s1, s2, n,
+ s1_label, s2_label, n_label);
+ return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_memcmp(
+ const void *s1, const void *s2, size_t n, dfsan_label s1_label,
+ dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
+ dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
+ dfsan_origin *ret_origin) {
+ CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_memcmp, GET_CALLER_PC(), s1,
+ s2, n, s1_label, s2_label, n_label, s1_origin,
+ s2_origin, n_origin);
+ return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_bcmp(const void *s1, const void *s2,
+ size_t n, dfsan_label s1_label,
+ dfsan_label s2_label,
+ dfsan_label n_label,
+ dfsan_label *ret_label) {
+ return dfsan_memcmp_bcmp_label(s1, s2, n, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_bcmp(
+ const void *s1, const void *s2, size_t n, dfsan_label s1_label,
+ dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
+ dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
+ dfsan_origin *ret_origin) {
+ return dfsan_memcmp_bcmp_origin(s1, s2, n, ret_label, ret_origin);
+}
+
+// When n == 0, compare strings without byte limit.
+// When n > 0, compare the first (at most) n bytes of s1 and s2.
+static int dfsan_strncmp(const char *s1, const char *s2, size_t n,
+ size_t *bytes_read) {
+ for (size_t i = 0;; ++i) {
+ if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || (n > 0 && i == n - 1)) {
+ *bytes_read = i + 1;
+ return s1[i] - s2[i];
+ }
+ }
+}
+
+DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, uptr caller_pc,
+ const char *s1, const char *s2,
+ dfsan_label s1_label, dfsan_label s2_label)
+
+DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, uptr caller_pc,
+ const char *s1, const char *s2,
+ dfsan_label s1_label, dfsan_label s2_label,
+ dfsan_origin s1_origin, dfsan_origin s2_origin)
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2,
+ dfsan_label s1_label,
+ dfsan_label s2_label,
+ dfsan_label *ret_label) {
+ CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, GET_CALLER_PC(), s1, s2,
+ s1_label, s2_label);
+ size_t bytes_read;
+ int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
+ *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
+ return r;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcmp(
+ const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
+ dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
+ dfsan_origin *ret_origin) {
+ CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strcmp, GET_CALLER_PC(), s1,
+ s2, s1_label, s2_label, s1_origin, s2_origin);
+ size_t bytes_read;
+ int r = dfsan_strncmp(s1, s2, 0, &bytes_read);
+ dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
+ return r;
+}
+
+// When n == 0, compare strings without byte limit.
+// When n > 0, compare the first (at most) n bytes of s1 and s2.
+static int dfsan_strncasecmp(const char *s1, const char *s2, size_t n,
+ size_t *bytes_read) {
+ for (size_t i = 0;; ++i) {
+ char s1_lower = tolower(s1[i]);
+ char s2_lower = tolower(s2[i]);
+
+ if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0 ||
+ (n > 0 && i == n - 1)) {
+ *bytes_read = i + 1;
+ return s1_lower - s2_lower;
+ }
+ }
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcasecmp(const char *s1,
+ const char *s2,
+ dfsan_label s1_label,
+ dfsan_label s2_label,
+ dfsan_label *ret_label) {
+ size_t bytes_read;
+ int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
+ *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
+ return r;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strcasecmp(
+ const char *s1, const char *s2, dfsan_label s1_label, dfsan_label s2_label,
+ dfsan_label *ret_label, dfsan_origin s1_origin, dfsan_origin s2_origin,
+ dfsan_origin *ret_origin) {
+ size_t bytes_read;
+ int r = dfsan_strncasecmp(s1, s2, 0, &bytes_read);
+ dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
+ return r;
+}
+
+DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, uptr caller_pc,
+ const char *s1, const char *s2, size_t n,
+ dfsan_label s1_label, dfsan_label s2_label,
+ dfsan_label n_label)
+
+DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, uptr caller_pc,
+ const char *s1, const char *s2, size_t n,
+ dfsan_label s1_label, dfsan_label s2_label,
+ dfsan_label n_label, dfsan_origin s1_origin,
+ dfsan_origin s2_origin, dfsan_origin n_origin)
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2,
+ size_t n, dfsan_label s1_label,
+ dfsan_label s2_label,
+ dfsan_label n_label,
+ dfsan_label *ret_label) {
+ if (n == 0) {
+ *ret_label = 0;
+ return 0;
+ }
+
+ CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, GET_CALLER_PC(), s1, s2,
+ n, s1_label, s2_label, n_label);
+
+ size_t bytes_read;
+ int r = dfsan_strncmp(s1, s2, n, &bytes_read);
+ *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
+ return r;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncmp(
+ const char *s1, const char *s2, size_t n, dfsan_label s1_label,
+ dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
+ dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
+ dfsan_origin *ret_origin) {
+ if (n == 0) {
+ *ret_label = 0;
+ return 0;
+ }
+
+ CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_origin_strncmp, GET_CALLER_PC(),
+ s1, s2, n, s1_label, s2_label, n_label, s1_origin,
+ s2_origin, n_origin);
+
+ size_t bytes_read;
+ int r = dfsan_strncmp(s1, s2, n, &bytes_read);
+ dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
+ return r;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncasecmp(
+ const char *s1, const char *s2, size_t n, dfsan_label s1_label,
+ dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label) {
+ if (n == 0) {
+ *ret_label = 0;
+ return 0;
+ }
+
+ size_t bytes_read;
+ int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
+ *ret_label = dfsan_get_memcmp_label(s1, s2, bytes_read);
+ return r;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_strncasecmp(
+ const char *s1, const char *s2, size_t n, dfsan_label s1_label,
+ dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
+ dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
+ dfsan_origin *ret_origin) {
+ if (n == 0) {
+ *ret_label = 0;
+ return 0;
+ }
+
+ size_t bytes_read;
+ int r = dfsan_strncasecmp(s1, s2, n, &bytes_read);
+ dfsan_get_memcmp_origin(s1, s2, bytes_read, ret_label, ret_origin);
+ return r;
+}
+
+
+SANITIZER_INTERFACE_ATTRIBUTE size_t
+__dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
+ size_t ret = strlen(s);
+ if (flags().strict_data_dependencies) {
+ *ret_label = 0;
+ } else {
+ *ret_label = dfsan_read_label(s, ret + 1);
+ }
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strlen(const char *s,
+ dfsan_label s_label,
+ dfsan_label *ret_label,
+ dfsan_origin s_origin,
+ dfsan_origin *ret_origin) {
+ size_t ret = __dfsw_strlen(s, s_label, ret_label);
+ if (!flags().strict_data_dependencies)
+ *ret_origin = dfsan_read_origin_of_first_taint(s, ret + 1);
+ return ret;
+}
+
+static void *dfsan_memmove(void *dest, const void *src, size_t n) {
+ dfsan_label *sdest = shadow_for(dest);
+ const dfsan_label *ssrc = shadow_for(src);
+ internal_memmove((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label));
+ return internal_memmove(dest, src, n);
+}
+
+static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) {
+ dfsan_mem_origin_transfer(dest, src, n);
+ return dfsan_memmove(dest, src, n);
+}
+
+static void *dfsan_memcpy(void *dest, const void *src, size_t n) {
+ dfsan_mem_shadow_transfer(dest, src, n);
+ return internal_memcpy(dest, src, n);
+}
+
+static void *dfsan_memcpy_with_origin(void *dest, const void *src, size_t n) {
+ dfsan_mem_origin_transfer(dest, src, n);
+ return dfsan_memcpy(dest, src, n);
+}
+
+static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) {
+ internal_memset(s, c, n);
+ dfsan_set_label(c_label, s, n);
+}
+
+static void dfsan_memset_with_origin(void *s, int c, dfsan_label c_label,
+ dfsan_origin c_origin, size_t n) {
+ internal_memset(s, c, n);
+ dfsan_set_label_origin(c_label, c_origin, s, n);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__dfsw_memcpy(void *dest, const void *src, size_t n,
+ dfsan_label dest_label, dfsan_label src_label,
+ dfsan_label n_label, dfsan_label *ret_label) {
+ *ret_label = dest_label;
+ return dfsan_memcpy(dest, src, n);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__dfso_memcpy(void *dest, const void *src, size_t n,
+ dfsan_label dest_label, dfsan_label src_label,
+ dfsan_label n_label, dfsan_label *ret_label,
+ dfsan_origin dest_origin, dfsan_origin src_origin,
+ dfsan_origin n_origin, dfsan_origin *ret_origin) {
+ *ret_label = dest_label;
+ *ret_origin = dest_origin;
+ return dfsan_memcpy_with_origin(dest, src, n);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__dfsw_memmove(void *dest, const void *src, size_t n,
+ dfsan_label dest_label, dfsan_label src_label,
+ dfsan_label n_label, dfsan_label *ret_label) {
+ *ret_label = dest_label;
+ return dfsan_memmove(dest, src, n);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__dfso_memmove(void *dest, const void *src, size_t n,
+ dfsan_label dest_label, dfsan_label src_label,
+ dfsan_label n_label, dfsan_label *ret_label,
+ dfsan_origin dest_origin, dfsan_origin src_origin,
+ dfsan_origin n_origin, dfsan_origin *ret_origin) {
+ *ret_label = dest_label;
+ *ret_origin = dest_origin;
+ return dfsan_memmove_with_origin(dest, src, n);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__dfsw_memset(void *s, int c, size_t n,
+ dfsan_label s_label, dfsan_label c_label,
+ dfsan_label n_label, dfsan_label *ret_label) {
+ dfsan_memset(s, c, c_label, n);
+ *ret_label = s_label;
+ return s;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__dfso_memset(void *s, int c, size_t n, dfsan_label s_label,
+ dfsan_label c_label, dfsan_label n_label,
+ dfsan_label *ret_label, dfsan_origin s_origin,
+ dfsan_origin c_origin, dfsan_origin n_origin,
+ dfsan_origin *ret_origin) {
+ dfsan_memset_with_origin(s, c, c_label, c_origin, n);
+ *ret_label = s_label;
+ *ret_origin = s_origin;
+ return s;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src,
+ dfsan_label dest_label,
+ dfsan_label src_label,
+ dfsan_label *ret_label) {
+ size_t dest_len = strlen(dest);
+ char *ret = strcat(dest, src);
+ dfsan_mem_shadow_transfer(dest + dest_len, src, strlen(src));
+ *ret_label = dest_label;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat(
+ char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label,
+ dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin,
+ dfsan_origin *ret_origin) {
+ size_t dest_len = strlen(dest);
+ char *ret = strcat(dest, src);
+ size_t src_len = strlen(src);
+ dfsan_mem_origin_transfer(dest + dest_len, src, src_len);
+ dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);
+ *ret_label = dest_label;
+ *ret_origin = dest_origin;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *
+__dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
+ size_t len = strlen(s);
+ void *p = malloc(len+1);
+ dfsan_memcpy(p, s, len+1);
+ *ret_label = 0;
+ return static_cast<char *>(p);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strdup(const char *s,
+ dfsan_label s_label,
+ dfsan_label *ret_label,
+ dfsan_origin s_origin,
+ dfsan_origin *ret_origin) {
+ size_t len = strlen(s);
+ void *p = malloc(len + 1);
+ dfsan_memcpy_with_origin(p, s, len + 1);
+ *ret_label = 0;
+ return static_cast<char *>(p);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *
+__dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label,
+ dfsan_label s2_label, dfsan_label n_label,
+ dfsan_label *ret_label) {
+ size_t len = strlen(s2);
+ if (len < n) {
+ dfsan_memcpy(s1, s2, len+1);
+ dfsan_memset(s1+len+1, 0, 0, n-len-1);
+ } else {
+ dfsan_memcpy(s1, s2, n);
+ }
+
+ *ret_label = s1_label;
+ return s1;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncpy(
+ char *s1, const char *s2, size_t n, dfsan_label s1_label,
+ dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
+ dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
+ dfsan_origin *ret_origin) {
+ size_t len = strlen(s2);
+ if (len < n) {
+ dfsan_memcpy_with_origin(s1, s2, len + 1);
+ dfsan_memset_with_origin(s1 + len + 1, 0, 0, 0, n - len - 1);
+ } else {
+ dfsan_memcpy_with_origin(s1, s2, n);
+ }
+
+ *ret_label = s1_label;
+ *ret_origin = s1_origin;
+ return s1;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE ssize_t
+__dfsw_pread(int fd, void *buf, size_t count, off_t offset,
+ dfsan_label fd_label, dfsan_label buf_label,
+ dfsan_label count_label, dfsan_label offset_label,
+ dfsan_label *ret_label) {
+ ssize_t ret = pread(fd, buf, count, offset);
+ if (ret > 0)
+ dfsan_set_label(0, buf, ret);
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_pread(
+ int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label,
+ dfsan_label buf_label, dfsan_label count_label, dfsan_label offset_label,
+ dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
+ dfsan_origin count_origin, dfsan_label offset_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_pread(fd, buf, count, offset, fd_label, buf_label, count_label,
+ offset_label, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE ssize_t
+__dfsw_read(int fd, void *buf, size_t count,
+ dfsan_label fd_label, dfsan_label buf_label,
+ dfsan_label count_label,
+ dfsan_label *ret_label) {
+ ssize_t ret = read(fd, buf, count);
+ if (ret > 0)
+ dfsan_set_label(0, buf, ret);
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_read(
+ int fd, void *buf, size_t count, dfsan_label fd_label,
+ dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
+ dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_read(fd, buf, count, fd_label, buf_label, count_label,
+ ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id,
+ struct timespec *tp,
+ dfsan_label clk_id_label,
+ dfsan_label tp_label,
+ dfsan_label *ret_label) {
+ int ret = clock_gettime(clk_id, tp);
+ if (ret == 0)
+ dfsan_set_label(0, tp, sizeof(struct timespec));
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_clock_gettime(
+ clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label,
+ dfsan_label tp_label, dfsan_label *ret_label, dfsan_origin clk_id_origin,
+ dfsan_origin tp_origin, dfsan_origin *ret_origin) {
+ return __dfsw_clock_gettime(clk_id, tp, clk_id_label, tp_label, ret_label);
+}
+
+static void dfsan_set_zero_label(const void *ptr, uptr size) {
+ dfsan_set_label(0, const_cast<void *>(ptr), size);
+}
+
+// dlopen() ultimately calls mmap() down inside the loader, which generally
+// doesn't participate in dynamic symbol resolution. Therefore we won't
+// intercept its calls to mmap, and we have to hook it here.
+SANITIZER_INTERFACE_ATTRIBUTE void *
+__dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label,
+ dfsan_label flag_label, dfsan_label *ret_label) {
+ void *handle = dlopen(filename, flag);
+ link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle);
+ if (map)
+ ForEachMappedRegion(map, dfsan_set_zero_label);
+ *ret_label = 0;
+ return handle;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen(
+ const char *filename, int flag, dfsan_label filename_label,
+ dfsan_label flag_label, dfsan_label *ret_label,
+ dfsan_origin filename_origin, dfsan_origin flag_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_dlopen(filename, flag, filename_label, flag_label, ret_label);
+}
+
+static void *DFsanThreadStartFunc(void *arg) {
+ DFsanThread *t = (DFsanThread *)arg;
+ SetCurrentThread(t);
+ t->Init();
+ SetSigProcMask(&t->starting_sigset_, nullptr);
+ return t->ThreadStart();
+}
+
+static int dfsan_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
+ void *start_routine, void *arg,
+ dfsan_label *ret_label,
+ bool track_origins = false) {
+ pthread_attr_t myattr;
+ if (!attr) {
+ pthread_attr_init(&myattr);
+ attr = &myattr;
+ }
+
+ // Ensure that the thread stack is large enough to hold all TLS data.
+ AdjustStackSize((void *)(const_cast<pthread_attr_t *>(attr)));
+
+ DFsanThread *t =
+ DFsanThread::Create((thread_callback_t)start_routine, arg, track_origins);
+ ScopedBlockSignals block(&t->starting_sigset_);
+ int res = pthread_create(thread, attr, DFsanThreadStartFunc, t);
+
+ if (attr == &myattr)
+ pthread_attr_destroy(&myattr);
+ *ret_label = 0;
+ return res;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create(
+ pthread_t *thread, const pthread_attr_t *attr, void *start_routine,
+ void *arg, dfsan_label thread_label, dfsan_label attr_label,
+ dfsan_label start_routine_label, dfsan_label arg_label,
+ dfsan_label *ret_label) {
+ return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_create(
+ pthread_t *thread, const pthread_attr_t *attr, void *start_routine,
+ void *arg, dfsan_label thread_label, dfsan_label attr_label,
+ dfsan_label start_routine_label, dfsan_label arg_label,
+ dfsan_label *ret_label, dfsan_origin thread_origin,
+ dfsan_origin attr_origin, dfsan_origin start_routine_origin,
+ dfsan_origin arg_origin, dfsan_origin *ret_origin) {
+ return dfsan_pthread_create(thread, attr, start_routine, arg, ret_label,
+ true);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_join(pthread_t thread,
+ void **retval,
+ dfsan_label thread_label,
+ dfsan_label retval_label,
+ dfsan_label *ret_label) {
+ int ret = pthread_join(thread, retval);
+ if (ret == 0 && retval)
+ dfsan_set_label(0, retval, sizeof(*retval));
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_pthread_join(
+ pthread_t thread, void **retval, dfsan_label thread_label,
+ dfsan_label retval_label, dfsan_label *ret_label,
+ dfsan_origin thread_origin, dfsan_origin retval_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_pthread_join(thread, retval, thread_label, retval_label,
+ ret_label);
+}
+
+struct dl_iterate_phdr_info {
+ int (*callback)(struct dl_phdr_info *info, size_t size, void *data);
+ void *data;
+};
+
+int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) {
+ dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data;
+ dfsan_set_label(0, *info);
+ dfsan_set_label(0, const_cast<char *>(info->dlpi_name),
+ strlen(info->dlpi_name) + 1);
+ dfsan_set_label(
+ 0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),
+ sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
+
+ dfsan_clear_thread_local_state();
+ return dipi->callback(info, size, dipi->data);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(
+ int (*callback)(struct dl_phdr_info *info, size_t size, void *data),
+ void *data, dfsan_label callback_label, dfsan_label data_label,
+ dfsan_label *ret_label) {
+ dl_iterate_phdr_info dipi = {callback, data};
+ *ret_label = 0;
+ return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr(
+ int (*callback)(struct dl_phdr_info *info, size_t size, void *data),
+ void *data, dfsan_label callback_label, dfsan_label data_label,
+ dfsan_label *ret_label, dfsan_origin callback_origin,
+ dfsan_origin data_origin, dfsan_origin *ret_origin) {
+ dl_iterate_phdr_info dipi = {callback, data};
+ *ret_label = 0;
+ return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
+}
+
+// This function is only available for glibc 2.27 or newer. Mark it weak so
+// linking succeeds with older glibcs.
+SANITIZER_WEAK_ATTRIBUTE void _dl_get_tls_static_info(size_t *sizep,
+ size_t *alignp);
+
+SANITIZER_INTERFACE_ATTRIBUTE void __dfsw__dl_get_tls_static_info(
+ size_t *sizep, size_t *alignp, dfsan_label sizep_label,
+ dfsan_label alignp_label) {
+ assert(_dl_get_tls_static_info);
+ _dl_get_tls_static_info(sizep, alignp);
+ dfsan_set_label(0, sizep, sizeof(*sizep));
+ dfsan_set_label(0, alignp, sizeof(*alignp));
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE void __dfso__dl_get_tls_static_info(
+ size_t *sizep, size_t *alignp, dfsan_label sizep_label,
+ dfsan_label alignp_label, dfsan_origin sizep_origin,
+ dfsan_origin alignp_origin) {
+ __dfsw__dl_get_tls_static_info(sizep, alignp, sizep_label, alignp_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
+ dfsan_label buf_label, dfsan_label *ret_label) {
+ char *ret = ctime_r(timep, buf);
+ if (ret) {
+ dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), buf,
+ strlen(buf) + 1);
+ *ret_label = buf_label;
+ } else {
+ *ret_label = 0;
+ }
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+char *__dfso_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
+ dfsan_label buf_label, dfsan_label *ret_label,
+ dfsan_origin timep_origin, dfsan_origin buf_origin,
+ dfsan_origin *ret_origin) {
+ char *ret = ctime_r(timep, buf);
+ if (ret) {
+ dfsan_set_label_origin(
+ dfsan_read_label(timep, sizeof(time_t)),
+ dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), buf,
+ strlen(buf) + 1);
+ *ret_label = buf_label;
+ *ret_origin = buf_origin;
+ } else {
+ *ret_label = 0;
+ }
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+char *__dfsw_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
+ dfsan_label size_label, dfsan_label stream_label,
+ dfsan_label *ret_label) {
+ char *ret = fgets(s, size, stream);
+ if (ret) {
+ dfsan_set_label(0, ret, strlen(ret) + 1);
+ *ret_label = s_label;
+ } else {
+ *ret_label = 0;
+ }
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+char *__dfso_fgets(char *s, int size, FILE *stream, dfsan_label s_label,
+ dfsan_label size_label, dfsan_label stream_label,
+ dfsan_label *ret_label, dfsan_origin s_origin,
+ dfsan_origin size_origin, dfsan_origin stream_origin,
+ dfsan_origin *ret_origin) {
+ char *ret = __dfsw_fgets(s, size, stream, s_label, size_label, stream_label,
+ ret_label);
+ if (ret)
+ *ret_origin = s_origin;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+char *__dfsw_getcwd(char *buf, size_t size, dfsan_label buf_label,
+ dfsan_label size_label, dfsan_label *ret_label) {
+ char *ret = getcwd(buf, size);
+ if (ret) {
+ dfsan_set_label(0, ret, strlen(ret) + 1);
+ *ret_label = buf_label;
+ } else {
+ *ret_label = 0;
+ }
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+char *__dfso_getcwd(char *buf, size_t size, dfsan_label buf_label,
+ dfsan_label size_label, dfsan_label *ret_label,
+ dfsan_origin buf_origin, dfsan_origin size_origin,
+ dfsan_origin *ret_origin) {
+ char *ret = __dfsw_getcwd(buf, size, buf_label, size_label, ret_label);
+ if (ret)
+ *ret_origin = buf_origin;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+char *__dfsw_get_current_dir_name(dfsan_label *ret_label) {
+ char *ret = get_current_dir_name();
+ if (ret)
+ dfsan_set_label(0, ret, strlen(ret) + 1);
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+char *__dfso_get_current_dir_name(dfsan_label *ret_label,
+ dfsan_origin *ret_origin) {
+ return __dfsw_get_current_dir_name(ret_label);
+}
+
+// This function is only available for glibc 2.25 or newer. Mark it weak so
+// linking succeeds with older glibcs.
+SANITIZER_WEAK_ATTRIBUTE int getentropy(void *buffer, size_t length);
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getentropy(void *buffer, size_t length,
+ dfsan_label buffer_label,
+ dfsan_label length_label,
+ dfsan_label *ret_label) {
+ int ret = getentropy(buffer, length);
+ if (ret == 0) {
+ dfsan_set_label(0, buffer, length);
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getentropy(void *buffer, size_t length,
+ dfsan_label buffer_label,
+ dfsan_label length_label,
+ dfsan_label *ret_label,
+ dfsan_origin buffer_origin,
+ dfsan_origin length_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_getentropy(buffer, length, buffer_label, length_label,
+ ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label,
+ dfsan_label len_label, dfsan_label *ret_label) {
+ int ret = gethostname(name, len);
+ if (ret == 0) {
+ dfsan_set_label(0, name, strlen(name) + 1);
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_gethostname(char *name, size_t len, dfsan_label name_label,
+ dfsan_label len_label, dfsan_label *ret_label,
+ dfsan_origin name_origin, dfsan_origin len_origin,
+ dfsan_label *ret_origin) {
+ return __dfsw_gethostname(name, len, name_label, len_label, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_getrlimit(int resource, struct rlimit *rlim,
+ dfsan_label resource_label, dfsan_label rlim_label,
+ dfsan_label *ret_label) {
+ int ret = getrlimit(resource, rlim);
+ if (ret == 0) {
+ dfsan_set_label(0, rlim, sizeof(struct rlimit));
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_getrlimit(int resource, struct rlimit *rlim,
+ dfsan_label resource_label, dfsan_label rlim_label,
+ dfsan_label *ret_label, dfsan_origin resource_origin,
+ dfsan_origin rlim_origin, dfsan_origin *ret_origin) {
+ return __dfsw_getrlimit(resource, rlim, resource_label, rlim_label,
+ ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label,
+ dfsan_label usage_label, dfsan_label *ret_label) {
+ int ret = getrusage(who, usage);
+ if (ret == 0) {
+ dfsan_set_label(0, usage, sizeof(struct rusage));
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_getrusage(int who, struct rusage *usage, dfsan_label who_label,
+ dfsan_label usage_label, dfsan_label *ret_label,
+ dfsan_origin who_origin, dfsan_origin usage_origin,
+ dfsan_label *ret_origin) {
+ return __dfsw_getrusage(who, usage, who_label, usage_label, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label,
+ dfsan_label src_label, dfsan_label *ret_label) {
+ char *ret = strcpy(dest, src);
+ if (ret) {
+ dfsan_mem_shadow_transfer(dest, src, strlen(src) + 1);
+ }
+ *ret_label = dst_label;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label,
+ dfsan_label src_label, dfsan_label *ret_label,
+ dfsan_origin dst_origin, dfsan_origin src_origin,
+ dfsan_origin *ret_origin) {
+ char *ret = strcpy(dest, src);
+ if (ret) {
+ size_t str_len = strlen(src) + 1;
+ dfsan_mem_origin_transfer(dest, src, str_len);
+ dfsan_mem_shadow_transfer(dest, src, str_len);
+ }
+ *ret_label = dst_label;
+ *ret_origin = dst_origin;
+ return ret;
+}
+
+static long int dfsan_strtol(const char *nptr, char **endptr, int base,
+ char **tmp_endptr) {
+ assert(tmp_endptr);
+ long int ret = strtol(nptr, tmp_endptr, base);
+ if (endptr)
+ *endptr = *tmp_endptr;
+ return ret;
+}
+
+static void dfsan_strtolong_label(const char *nptr, const char *tmp_endptr,
+ dfsan_label base_label,
+ dfsan_label *ret_label) {
+ if (tmp_endptr > nptr) {
+ // If *tmp_endptr is '\0' include its label as well.
+ *ret_label = dfsan_union(
+ base_label,
+ dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
+ } else {
+ *ret_label = 0;
+ }
+}
+
+static void dfsan_strtolong_origin(const char *nptr, const char *tmp_endptr,
+ dfsan_label base_label,
+ dfsan_label *ret_label,
+ dfsan_origin base_origin,
+ dfsan_origin *ret_origin) {
+ if (tmp_endptr > nptr) {
+ // When multiple inputs are tainted, we propagate one of its origins.
+ // Because checking if base_label is tainted does not need additional
+ // computation, we prefer to propagating base_origin.
+ *ret_origin = base_label
+ ? base_origin
+ : dfsan_read_origin_of_first_taint(
+ nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
+ }
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+long int __dfsw_strtol(const char *nptr, char **endptr, int base,
+ dfsan_label nptr_label, dfsan_label endptr_label,
+ dfsan_label base_label, dfsan_label *ret_label) {
+ char *tmp_endptr;
+ long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+long int __dfso_strtol(const char *nptr, char **endptr, int base,
+ dfsan_label nptr_label, dfsan_label endptr_label,
+ dfsan_label base_label, dfsan_label *ret_label,
+ dfsan_origin nptr_origin, dfsan_origin endptr_origin,
+ dfsan_origin base_origin, dfsan_origin *ret_origin) {
+ char *tmp_endptr;
+ long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
+ ret_origin);
+ return ret;
+}
+
+static double dfsan_strtod(const char *nptr, char **endptr, char **tmp_endptr) {
+ assert(tmp_endptr);
+ double ret = strtod(nptr, tmp_endptr);
+ if (endptr)
+ *endptr = *tmp_endptr;
+ return ret;
+}
+
+static void dfsan_strtod_label(const char *nptr, const char *tmp_endptr,
+ dfsan_label *ret_label) {
+ if (tmp_endptr > nptr) {
+ // If *tmp_endptr is '\0' include its label as well.
+ *ret_label = dfsan_read_label(
+ nptr,
+ tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
+ } else {
+ *ret_label = 0;
+ }
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+double __dfsw_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
+ dfsan_label endptr_label, dfsan_label *ret_label) {
+ char *tmp_endptr;
+ double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
+ dfsan_strtod_label(nptr, tmp_endptr, ret_label);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+double __dfso_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
+ dfsan_label endptr_label, dfsan_label *ret_label,
+ dfsan_origin nptr_origin, dfsan_origin endptr_origin,
+ dfsan_origin *ret_origin) {
+ char *tmp_endptr;
+ double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
+ dfsan_strtod_label(nptr, tmp_endptr, ret_label);
+ if (tmp_endptr > nptr) {
+ // If *tmp_endptr is '\0' include its label as well.
+ *ret_origin = dfsan_read_origin_of_first_taint(
+ nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
+ } else {
+ *ret_origin = 0;
+ }
+ return ret;
+}
+
+static long long int dfsan_strtoll(const char *nptr, char **endptr, int base,
+ char **tmp_endptr) {
+ assert(tmp_endptr);
+ long long int ret = strtoll(nptr, tmp_endptr, base);
+ if (endptr)
+ *endptr = *tmp_endptr;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+long long int __dfsw_strtoll(const char *nptr, char **endptr, int base,
+ dfsan_label nptr_label, dfsan_label endptr_label,
+ dfsan_label base_label, dfsan_label *ret_label) {
+ char *tmp_endptr;
+ long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+long long int __dfso_strtoll(const char *nptr, char **endptr, int base,
+ dfsan_label nptr_label, dfsan_label endptr_label,
+ dfsan_label base_label, dfsan_label *ret_label,
+ dfsan_origin nptr_origin,
+ dfsan_origin endptr_origin,
+ dfsan_origin base_origin,
+ dfsan_origin *ret_origin) {
+ char *tmp_endptr;
+ long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
+ ret_origin);
+ return ret;
+}
+
+static unsigned long int dfsan_strtoul(const char *nptr, char **endptr,
+ int base, char **tmp_endptr) {
+ assert(tmp_endptr);
+ unsigned long int ret = strtoul(nptr, tmp_endptr, base);
+ if (endptr)
+ *endptr = *tmp_endptr;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+unsigned long int __dfsw_strtoul(const char *nptr, char **endptr, int base,
+ dfsan_label nptr_label, dfsan_label endptr_label,
+ dfsan_label base_label, dfsan_label *ret_label) {
+ char *tmp_endptr;
+ unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+unsigned long int __dfso_strtoul(
+ const char *nptr, char **endptr, int base, dfsan_label nptr_label,
+ dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label,
+ dfsan_origin nptr_origin, dfsan_origin endptr_origin,
+ dfsan_origin base_origin, dfsan_origin *ret_origin) {
+ char *tmp_endptr;
+ unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
+ ret_origin);
+ return ret;
+}
+
+static long long unsigned int dfsan_strtoull(const char *nptr, char **endptr,
+ int base, char **tmp_endptr) {
+ assert(tmp_endptr);
+ long long unsigned int ret = strtoull(nptr, tmp_endptr, base);
+ if (endptr)
+ *endptr = *tmp_endptr;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+long long unsigned int __dfsw_strtoull(const char *nptr, char **endptr,
+ int base, dfsan_label nptr_label,
+ dfsan_label endptr_label,
+ dfsan_label base_label,
+ dfsan_label *ret_label) {
+ char *tmp_endptr;
+ long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+long long unsigned int __dfso_strtoull(
+ const char *nptr, char **endptr, int base, dfsan_label nptr_label,
+ dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label,
+ dfsan_origin nptr_origin, dfsan_origin endptr_origin,
+ dfsan_origin base_origin, dfsan_origin *ret_origin) {
+ char *tmp_endptr;
+ long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
+ ret_origin);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+time_t __dfsw_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label) {
+ time_t ret = time(t);
+ if (ret != (time_t) -1 && t) {
+ dfsan_set_label(0, t, sizeof(time_t));
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+time_t __dfso_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label,
+ dfsan_origin t_origin, dfsan_origin *ret_origin) {
+ return __dfsw_time(t, t_label, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,
+ dfsan_label src_label, dfsan_label dst_label,
+ dfsan_label *ret_label) {
+ int ret = inet_pton(af, src, dst);
+ if (ret == 1) {
+ dfsan_set_label(dfsan_read_label(src, strlen(src) + 1), dst,
+ af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_inet_pton(int af, const char *src, void *dst, dfsan_label af_label,
+ dfsan_label src_label, dfsan_label dst_label,
+ dfsan_label *ret_label, dfsan_origin af_origin,
+ dfsan_origin src_origin, dfsan_origin dst_origin,
+ dfsan_origin *ret_origin) {
+ int ret = inet_pton(af, src, dst);
+ if (ret == 1) {
+ int src_len = strlen(src) + 1;
+ dfsan_set_label_origin(
+ dfsan_read_label(src, src_len),
+ dfsan_read_origin_of_first_taint(src, src_len), dst,
+ af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr));
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+struct tm *__dfsw_localtime_r(const time_t *timep, struct tm *result,
+ dfsan_label timep_label, dfsan_label result_label,
+ dfsan_label *ret_label) {
+ struct tm *ret = localtime_r(timep, result);
+ if (ret) {
+ dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), result,
+ sizeof(struct tm));
+ *ret_label = result_label;
+ } else {
+ *ret_label = 0;
+ }
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+struct tm *__dfso_localtime_r(const time_t *timep, struct tm *result,
+ dfsan_label timep_label, dfsan_label result_label,
+ dfsan_label *ret_label, dfsan_origin timep_origin,
+ dfsan_origin result_origin,
+ dfsan_origin *ret_origin) {
+ struct tm *ret = localtime_r(timep, result);
+ if (ret) {
+ dfsan_set_label_origin(
+ dfsan_read_label(timep, sizeof(time_t)),
+ dfsan_read_origin_of_first_taint(timep, sizeof(time_t)), result,
+ sizeof(struct tm));
+ *ret_label = result_label;
+ *ret_origin = result_origin;
+ } else {
+ *ret_label = 0;
+ }
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_getpwuid_r(id_t uid, struct passwd *pwd,
+ char *buf, size_t buflen, struct passwd **result,
+ dfsan_label uid_label, dfsan_label pwd_label,
+ dfsan_label buf_label, dfsan_label buflen_label,
+ dfsan_label result_label, dfsan_label *ret_label) {
+ // Store the data in pwd, the strings referenced from pwd in buf, and the
+ // address of pwd in *result. On failure, NULL is stored in *result.
+ int ret = getpwuid_r(uid, pwd, buf, buflen, result);
+ if (ret == 0) {
+ dfsan_set_label(0, pwd, sizeof(struct passwd));
+ dfsan_set_label(0, buf, strlen(buf) + 1);
+ }
+ *ret_label = 0;
+ dfsan_set_label(0, result, sizeof(struct passwd*));
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_getpwuid_r(id_t uid, struct passwd *pwd, char *buf, size_t buflen,
+ struct passwd **result, dfsan_label uid_label,
+ dfsan_label pwd_label, dfsan_label buf_label,
+ dfsan_label buflen_label, dfsan_label result_label,
+ dfsan_label *ret_label, dfsan_origin uid_origin,
+ dfsan_origin pwd_origin, dfsan_origin buf_origin,
+ dfsan_origin buflen_origin, dfsan_origin result_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_getpwuid_r(uid, pwd, buf, buflen, result, uid_label, pwd_label,
+ buf_label, buflen_label, result_label, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_epoll_wait(int epfd, struct epoll_event *events, int maxevents,
+ int timeout, dfsan_label epfd_label,
+ dfsan_label events_label, dfsan_label maxevents_label,
+ dfsan_label timeout_label, dfsan_label *ret_label) {
+ int ret = epoll_wait(epfd, events, maxevents, timeout);
+ if (ret > 0)
+ dfsan_set_label(0, events, ret * sizeof(*events));
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_epoll_wait(int epfd, struct epoll_event *events, int maxevents,
+ int timeout, dfsan_label epfd_label,
+ dfsan_label events_label, dfsan_label maxevents_label,
+ dfsan_label timeout_label, dfsan_label *ret_label,
+ dfsan_origin epfd_origin, dfsan_origin events_origin,
+ dfsan_origin maxevents_origin,
+ dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
+ return __dfsw_epoll_wait(epfd, events, maxevents, timeout, epfd_label,
+ events_label, maxevents_label, timeout_label,
+ ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_poll(struct pollfd *fds, nfds_t nfds, int timeout,
+ dfsan_label dfs_label, dfsan_label nfds_label,
+ dfsan_label timeout_label, dfsan_label *ret_label) {
+ int ret = poll(fds, nfds, timeout);
+ if (ret >= 0) {
+ for (; nfds > 0; --nfds) {
+ dfsan_set_label(0, &fds[nfds - 1].revents, sizeof(fds[nfds - 1].revents));
+ }
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_poll(struct pollfd *fds, nfds_t nfds, int timeout,
+ dfsan_label dfs_label, dfsan_label nfds_label,
+ dfsan_label timeout_label, dfsan_label *ret_label,
+ dfsan_origin dfs_origin, dfsan_origin nfds_origin,
+ dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
+ return __dfsw_poll(fds, nfds, timeout, dfs_label, nfds_label, timeout_label,
+ ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout,
+ dfsan_label nfds_label, dfsan_label readfds_label,
+ dfsan_label writefds_label, dfsan_label exceptfds_label,
+ dfsan_label timeout_label, dfsan_label *ret_label) {
+ int ret = select(nfds, readfds, writefds, exceptfds, timeout);
+ // Clear everything (also on error) since their content is either set or
+ // undefined.
+ if (readfds) {
+ dfsan_set_label(0, readfds, sizeof(fd_set));
+ }
+ if (writefds) {
+ dfsan_set_label(0, writefds, sizeof(fd_set));
+ }
+ if (exceptfds) {
+ dfsan_set_label(0, exceptfds, sizeof(fd_set));
+ }
+ dfsan_set_label(0, timeout, sizeof(struct timeval));
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout,
+ dfsan_label nfds_label, dfsan_label readfds_label,
+ dfsan_label writefds_label, dfsan_label exceptfds_label,
+ dfsan_label timeout_label, dfsan_label *ret_label,
+ dfsan_origin nfds_origin, dfsan_origin readfds_origin,
+ dfsan_origin writefds_origin, dfsan_origin exceptfds_origin,
+ dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
+ return __dfsw_select(nfds, readfds, writefds, exceptfds, timeout, nfds_label,
+ readfds_label, writefds_label, exceptfds_label,
+ timeout_label, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,
+ dfsan_label pid_label,
+ dfsan_label cpusetsize_label,
+ dfsan_label mask_label, dfsan_label *ret_label) {
+ int ret = sched_getaffinity(pid, cpusetsize, mask);
+ if (ret == 0) {
+ dfsan_set_label(0, mask, cpusetsize);
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask,
+ dfsan_label pid_label,
+ dfsan_label cpusetsize_label,
+ dfsan_label mask_label, dfsan_label *ret_label,
+ dfsan_origin pid_origin,
+ dfsan_origin cpusetsize_origin,
+ dfsan_origin mask_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_sched_getaffinity(pid, cpusetsize, mask, pid_label,
+ cpusetsize_label, mask_label, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_sigemptyset(sigset_t *set, dfsan_label set_label,
+ dfsan_label *ret_label) {
+ int ret = sigemptyset(set);
+ dfsan_set_label(0, set, sizeof(sigset_t));
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_sigemptyset(sigset_t *set, dfsan_label set_label,
+ dfsan_label *ret_label, dfsan_origin set_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_sigemptyset(set, set_label, ret_label);
+}
+
+class SignalHandlerScope {
+ public:
+ SignalHandlerScope() {
+ if (DFsanThread *t = GetCurrentThread())
+ t->EnterSignalHandler();
+ }
+ ~SignalHandlerScope() {
+ if (DFsanThread *t = GetCurrentThread())
+ t->LeaveSignalHandler();
+ }
+};
+
+// Clear DFSan runtime TLS state at the end of a scope.
+//
+// Implementation must be async-signal-safe and use small data size, because
+// instances of this class may live on the signal handler stack.
+//
+// DFSan uses TLS to pass metadata of arguments and return values. When an
+// instrumented function accesses the TLS, if a signal callback happens, and the
+// callback calls other instrumented functions with updating the same TLS, the
+// TLS is in an inconsistent state after the callback ends. This may cause
+// either under-tainting or over-tainting.
+//
+// The current implementation simply resets TLS at restore. This prevents from
+// over-tainting. Although under-tainting may still happen, a taint flow can be
+// found eventually if we run a DFSan-instrumented program multiple times. The
+// alternative option is saving the entire TLS. However the TLS storage takes
+// 2k bytes, and signal calls could be nested. So it does not seem worth.
+class ScopedClearThreadLocalState {
+ public:
+ ScopedClearThreadLocalState() {}
+ ~ScopedClearThreadLocalState() { dfsan_clear_thread_local_state(); }
+};
+
+// SignalSpinLocker::sigactions_mu guarantees atomicity of sigaction() calls.
+const int kMaxSignals = 1024;
+static atomic_uintptr_t sigactions[kMaxSignals];
+
+static void SignalHandler(int signo) {
+ SignalHandlerScope signal_handler_scope;
+ ScopedClearThreadLocalState scoped_clear_tls;
+
+ // Clear shadows for all inputs provided by system.
+ dfsan_clear_arg_tls(0, sizeof(dfsan_label));
+
+ typedef void (*signal_cb)(int x);
+ signal_cb cb =
+ (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
+ cb(signo);
+}
+
+static void SignalAction(int signo, siginfo_t *si, void *uc) {
+ SignalHandlerScope signal_handler_scope;
+ ScopedClearThreadLocalState scoped_clear_tls;
+
+ // Clear shadows for all inputs provided by system. Similar to SignalHandler.
+ dfsan_clear_arg_tls(0, 3 * sizeof(dfsan_label));
+ dfsan_set_label(0, si, sizeof(*si));
+ dfsan_set_label(0, uc, sizeof(ucontext_t));
+
+ typedef void (*sigaction_cb)(int, siginfo_t *, void *);
+ sigaction_cb cb =
+ (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
+ cb(signo, si, uc);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_sigaction(int signum, const struct sigaction *act,
+ struct sigaction *oldact, dfsan_label signum_label,
+ dfsan_label act_label, dfsan_label oldact_label,
+ dfsan_label *ret_label) {
+ CHECK_LT(signum, kMaxSignals);
+ SignalSpinLocker lock;
+ uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
+ struct sigaction new_act;
+ struct sigaction *pnew_act = act ? &new_act : nullptr;
+ if (act) {
+ internal_memcpy(pnew_act, act, sizeof(struct sigaction));
+ if (pnew_act->sa_flags & SA_SIGINFO) {
+ uptr cb = (uptr)(pnew_act->sa_sigaction);
+ if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
+ atomic_store(&sigactions[signum], cb, memory_order_relaxed);
+ pnew_act->sa_sigaction = SignalAction;
+ }
+ } else {
+ uptr cb = (uptr)(pnew_act->sa_handler);
+ if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) {
+ atomic_store(&sigactions[signum], cb, memory_order_relaxed);
+ pnew_act->sa_handler = SignalHandler;
+ }
+ }
+ }
+
+ int ret = sigaction(signum, pnew_act, oldact);
+
+ if (ret == 0 && oldact) {
+ if (oldact->sa_flags & SA_SIGINFO) {
+ if (oldact->sa_sigaction == SignalAction)
+ oldact->sa_sigaction = (decltype(oldact->sa_sigaction))old_cb;
+ } else {
+ if (oldact->sa_handler == SignalHandler)
+ oldact->sa_handler = (decltype(oldact->sa_handler))old_cb;
+ }
+ }
+
+ if (oldact) {
+ dfsan_set_label(0, oldact, sizeof(struct sigaction));
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_sigaction(int signum, const struct sigaction *act,
+ struct sigaction *oldact, dfsan_label signum_label,
+ dfsan_label act_label, dfsan_label oldact_label,
+ dfsan_label *ret_label, dfsan_origin signum_origin,
+ dfsan_origin act_origin, dfsan_origin oldact_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_sigaction(signum, act, oldact, signum_label, act_label,
+ oldact_label, ret_label);
+}
+
+static sighandler_t dfsan_signal(int signum, sighandler_t handler,
+ dfsan_label *ret_label) {
+ CHECK_LT(signum, kMaxSignals);
+ SignalSpinLocker lock;
+ uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed);
+ if (handler != SIG_IGN && handler != SIG_DFL) {
+ atomic_store(&sigactions[signum], (uptr)handler, memory_order_relaxed);
+ handler = &SignalHandler;
+ }
+
+ sighandler_t ret = signal(signum, handler);
+
+ if (ret == SignalHandler)
+ ret = (sighandler_t)old_cb;
+
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+sighandler_t __dfsw_signal(int signum, sighandler_t handler,
+ dfsan_label signum_label, dfsan_label handler_label,
+ dfsan_label *ret_label) {
+ return dfsan_signal(signum, handler, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+sighandler_t __dfso_signal(int signum, sighandler_t handler,
+ dfsan_label signum_label, dfsan_label handler_label,
+ dfsan_label *ret_label, dfsan_origin signum_origin,
+ dfsan_origin handler_origin,
+ dfsan_origin *ret_origin) {
+ return dfsan_signal(signum, handler, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
+ dfsan_label old_ss_label, dfsan_label *ret_label) {
+ int ret = sigaltstack(ss, old_ss);
+ if (ret != -1 && old_ss)
+ dfsan_set_label(0, old_ss, sizeof(*old_ss));
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label,
+ dfsan_label old_ss_label, dfsan_label *ret_label,
+ dfsan_origin ss_origin, dfsan_origin old_ss_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_sigaltstack(ss, old_ss, ss_label, old_ss_label, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_gettimeofday(struct timeval *tv, struct timezone *tz,
+ dfsan_label tv_label, dfsan_label tz_label,
+ dfsan_label *ret_label) {
+ int ret = gettimeofday(tv, tz);
+ if (tv) {
+ dfsan_set_label(0, tv, sizeof(struct timeval));
+ }
+ if (tz) {
+ dfsan_set_label(0, tz, sizeof(struct timezone));
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_gettimeofday(struct timeval *tv, struct timezone *tz,
+ dfsan_label tv_label, dfsan_label tz_label,
+ dfsan_label *ret_label, dfsan_origin tv_origin,
+ dfsan_origin tz_origin, dfsan_origin *ret_origin) {
+ return __dfsw_gettimeofday(tv, tz, tv_label, tz_label, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n,
+ dfsan_label s_label,
+ dfsan_label c_label,
+ dfsan_label n_label,
+ dfsan_label *ret_label) {
+ void *ret = memchr(s, c, n);
+ if (flags().strict_data_dependencies) {
+ *ret_label = ret ? s_label : 0;
+ } else {
+ size_t len =
+ ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
+ : n;
+ *ret_label =
+ dfsan_union(dfsan_read_label(s, len), dfsan_union(s_label, c_label));
+ }
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_memchr(
+ void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label,
+ dfsan_label n_label, dfsan_label *ret_label, dfsan_origin s_origin,
+ dfsan_origin c_origin, dfsan_origin n_origin, dfsan_origin *ret_origin) {
+ void *ret = __dfsw_memchr(s, c, n, s_label, c_label, n_label, ret_label);
+ if (flags().strict_data_dependencies) {
+ if (ret)
+ *ret_origin = s_origin;
+ } else {
+ size_t len =
+ ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
+ : n;
+ dfsan_origin o = dfsan_read_origin_of_first_taint(s, len);
+ *ret_origin = o ? o : (s_label ? s_origin : c_origin);
+ }
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c,
+ dfsan_label s_label,
+ dfsan_label c_label,
+ dfsan_label *ret_label) {
+ char *ret = strrchr(s, c);
+ if (flags().strict_data_dependencies) {
+ *ret_label = ret ? s_label : 0;
+ } else {
+ *ret_label =
+ dfsan_union(dfsan_read_label(s, strlen(s) + 1),
+ dfsan_union(s_label, c_label));
+ }
+
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strrchr(
+ char *s, int c, dfsan_label s_label, dfsan_label c_label,
+ dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
+ dfsan_origin *ret_origin) {
+ char *ret = __dfsw_strrchr(s, c, s_label, c_label, ret_label);
+ if (flags().strict_data_dependencies) {
+ if (ret)
+ *ret_origin = s_origin;
+ } else {
+ size_t s_len = strlen(s) + 1;
+ dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_len);
+ *ret_origin = o ? o : (s_label ? s_origin : c_origin);
+ }
+
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle,
+ dfsan_label haystack_label,
+ dfsan_label needle_label,
+ dfsan_label *ret_label) {
+ char *ret = strstr(haystack, needle);
+ if (flags().strict_data_dependencies) {
+ *ret_label = ret ? haystack_label : 0;
+ } else {
+ size_t len = ret ? ret + strlen(needle) - haystack : strlen(haystack) + 1;
+ *ret_label =
+ dfsan_union(dfsan_read_label(haystack, len),
+ dfsan_union(dfsan_read_label(needle, strlen(needle) + 1),
+ dfsan_union(haystack_label, needle_label)));
+ }
+
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strstr(char *haystack, char *needle,
+ dfsan_label haystack_label,
+ dfsan_label needle_label,
+ dfsan_label *ret_label,
+ dfsan_origin haystack_origin,
+ dfsan_origin needle_origin,
+ dfsan_origin *ret_origin) {
+ char *ret =
+ __dfsw_strstr(haystack, needle, haystack_label, needle_label, ret_label);
+ if (flags().strict_data_dependencies) {
+ if (ret)
+ *ret_origin = haystack_origin;
+ } else {
+ size_t needle_len = strlen(needle);
+ size_t len = ret ? ret + needle_len - haystack : strlen(haystack) + 1;
+ dfsan_origin o = dfsan_read_origin_of_first_taint(haystack, len);
+ if (o) {
+ *ret_origin = o;
+ } else {
+ o = dfsan_read_origin_of_first_taint(needle, needle_len + 1);
+ *ret_origin = o ? o : (haystack_label ? haystack_origin : needle_origin);
+ }
+ }
+
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req,
+ struct timespec *rem,
+ dfsan_label req_label,
+ dfsan_label rem_label,
+ dfsan_label *ret_label) {
+ int ret = nanosleep(req, rem);
+ *ret_label = 0;
+ if (ret == -1) {
+ // Interrupted by a signal, rem is filled with the remaining time.
+ dfsan_set_label(0, rem, sizeof(struct timespec));
+ }
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_nanosleep(
+ const struct timespec *req, struct timespec *rem, dfsan_label req_label,
+ dfsan_label rem_label, dfsan_label *ret_label, dfsan_origin req_origin,
+ dfsan_origin rem_origin, dfsan_origin *ret_origin) {
+ return __dfsw_nanosleep(req, rem, req_label, rem_label, ret_label);
+}
+
+static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg) {
+ dfsan_set_label(0, msg, sizeof(*msg));
+ dfsan_set_label(0, msg->msg_name, msg->msg_namelen);
+ dfsan_set_label(0, msg->msg_control, msg->msg_controllen);
+ for (size_t i = 0; bytes_written > 0; ++i) {
+ assert(i < msg->msg_iovlen);
+ struct iovec *iov = &msg->msg_iov[i];
+ size_t iov_written =
+ bytes_written < iov->iov_len ? bytes_written : iov->iov_len;
+ dfsan_set_label(0, iov->iov_base, iov_written);
+ bytes_written -= iov_written;
+ }
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_recvmmsg(
+ int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
+ struct timespec *timeout, dfsan_label sockfd_label,
+ dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
+ dfsan_label timeout_label, dfsan_label *ret_label) {
+ int ret = recvmmsg(sockfd, msgvec, vlen, flags, timeout);
+ for (int i = 0; i < ret; ++i) {
+ dfsan_set_label(0, &msgvec[i].msg_len, sizeof(msgvec[i].msg_len));
+ clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr);
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_recvmmsg(
+ int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
+ struct timespec *timeout, dfsan_label sockfd_label,
+ dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
+ dfsan_label timeout_label, dfsan_label *ret_label,
+ dfsan_origin sockfd_origin, dfsan_origin msgvec_origin,
+ dfsan_origin vlen_origin, dfsan_origin flags_origin,
+ dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
+ return __dfsw_recvmmsg(sockfd, msgvec, vlen, flags, timeout, sockfd_label,
+ msgvec_label, vlen_label, flags_label, timeout_label,
+ ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg(
+ int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
+ dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) {
+ ssize_t ret = recvmsg(sockfd, msg, flags);
+ if (ret >= 0)
+ clear_msghdr_labels(ret, msg);
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_recvmsg(
+ int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
+ dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label,
+ dfsan_origin sockfd_origin, dfsan_origin msg_origin,
+ dfsan_origin flags_origin, dfsan_origin *ret_origin) {
+ return __dfsw_recvmsg(sockfd, msg, flags, sockfd_label, msg_label,
+ flags_label, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int
+__dfsw_socketpair(int domain, int type, int protocol, int sv[2],
+ dfsan_label domain_label, dfsan_label type_label,
+ dfsan_label protocol_label, dfsan_label sv_label,
+ dfsan_label *ret_label) {
+ int ret = socketpair(domain, type, protocol, sv);
+ *ret_label = 0;
+ if (ret == 0) {
+ dfsan_set_label(0, sv, sizeof(*sv) * 2);
+ }
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_socketpair(
+ int domain, int type, int protocol, int sv[2], dfsan_label domain_label,
+ dfsan_label type_label, dfsan_label protocol_label, dfsan_label sv_label,
+ dfsan_label *ret_label, dfsan_origin domain_origin,
+ dfsan_origin type_origin, dfsan_origin protocol_origin,
+ dfsan_origin sv_origin, dfsan_origin *ret_origin) {
+ return __dfsw_socketpair(domain, type, protocol, sv, domain_label, type_label,
+ protocol_label, sv_label, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockopt(
+ int sockfd, int level, int optname, void *optval, socklen_t *optlen,
+ dfsan_label sockfd_label, dfsan_label level_label,
+ dfsan_label optname_label, dfsan_label optval_label,
+ dfsan_label optlen_label, dfsan_label *ret_label) {
+ int ret = getsockopt(sockfd, level, optname, optval, optlen);
+ if (ret != -1 && optval && optlen) {
+ dfsan_set_label(0, optlen, sizeof(*optlen));
+ dfsan_set_label(0, optval, *optlen);
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockopt(
+ int sockfd, int level, int optname, void *optval, socklen_t *optlen,
+ dfsan_label sockfd_label, dfsan_label level_label,
+ dfsan_label optname_label, dfsan_label optval_label,
+ dfsan_label optlen_label, dfsan_label *ret_label,
+ dfsan_origin sockfd_origin, dfsan_origin level_origin,
+ dfsan_origin optname_origin, dfsan_origin optval_origin,
+ dfsan_origin optlen_origin, dfsan_origin *ret_origin) {
+ return __dfsw_getsockopt(sockfd, level, optname, optval, optlen, sockfd_label,
+ level_label, optname_label, optval_label,
+ optlen_label, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockname(
+ int sockfd, struct sockaddr *addr, socklen_t *addrlen,
+ dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
+ dfsan_label *ret_label) {
+ socklen_t origlen = addrlen ? *addrlen : 0;
+ int ret = getsockname(sockfd, addr, addrlen);
+ if (ret != -1 && addr && addrlen) {
+ socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
+ dfsan_set_label(0, addrlen, sizeof(*addrlen));
+ dfsan_set_label(0, addr, written_bytes);
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockname(
+ int sockfd, struct sockaddr *addr, socklen_t *addrlen,
+ dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
+ dfsan_label *ret_label, dfsan_origin sockfd_origin,
+ dfsan_origin addr_origin, dfsan_origin addrlen_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_getsockname(sockfd, addr, addrlen, sockfd_label, addr_label,
+ addrlen_label, ret_label);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getpeername(
+ int sockfd, struct sockaddr *addr, socklen_t *addrlen,
+ dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
+ dfsan_label *ret_label) {
+ socklen_t origlen = addrlen ? *addrlen : 0;
+ int ret = getpeername(sockfd, addr, addrlen);
+ if (ret != -1 && addr && addrlen) {
+ socklen_t written_bytes = origlen < *addrlen ? origlen : *addrlen;
+ dfsan_set_label(0, addrlen, sizeof(*addrlen));
+ dfsan_set_label(0, addr, written_bytes);
+ }
+ *ret_label = 0;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername(
+ int sockfd, struct sockaddr *addr, socklen_t *addrlen,
+ dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
+ dfsan_label *ret_label, dfsan_origin sockfd_origin,
+ dfsan_origin addr_origin, dfsan_origin addrlen_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_getpeername(sockfd, addr, addrlen, sockfd_label, addr_label,
+ addrlen_label, ret_label);
+}
+
+// Type of the function passed to dfsan_set_write_callback.
+typedef void (*write_dfsan_callback_t)(int fd, const void *buf, ssize_t count);
+
+// Calls to dfsan_set_write_callback() set the values in this struct.
+// Calls to the custom version of write() read (and invoke) them.
+static struct {
+ write_dfsan_callback_t write_callback = nullptr;
+} write_callback_info;
+
+SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_dfsan_set_write_callback(
+ write_dfsan_callback_t write_callback, dfsan_label write_callback_label,
+ dfsan_label *ret_label) {
+ write_callback_info.write_callback = write_callback;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE void __dfso_dfsan_set_write_callback(
+ write_dfsan_callback_t write_callback, dfsan_label write_callback_label,
+ dfsan_label *ret_label, dfsan_origin write_callback_origin,
+ dfsan_origin *ret_origin) {
+ write_callback_info.write_callback = write_callback;
+}
+
+static inline void setup_tls_args_for_write_callback(
+ dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label,
+ bool origins, dfsan_origin fd_origin, dfsan_origin buf_origin,
+ dfsan_origin count_origin) {
+ // The callback code will expect argument shadow labels in the args TLS,
+ // and origin labels in the origin args TLS.
+ // Previously this was done by a trampoline, but we want to remove this:
+ // https://github.com/llvm/llvm-project/issues/54172
+ //
+ // Instead, this code is manually setting up the args TLS data.
+ //
+ // The offsets used need to correspond with the instrumentation code,
+ // see llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+ // DFSanFunction::getShadowForTLSArgument.
+ // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L1684
+ // https://github.com/llvm/llvm-project/blob/0acc9e4b5edd8b39ff3d4c6d0e17f02007671c4e/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp#L125
+ //
+ // Here the arguments are all primitives, but it can be more complex
+ // to compute offsets for array/aggregate type arguments.
+ //
+ // TODO(browneee): Consider a builtin to improve maintainabliity.
+ // With a builtin, we would provide the argument labels via builtin,
+ // and the builtin would reuse parts of the instrumentation code to ensure
+ // that this code and the instrumentation can never be out of sync.
+ // Note: Currently DFSan instrumentation does not run on this code, so
+ // the builtin may need to be handled outside DFSan instrumentation.
+ dfsan_set_arg_tls(0, fd_label);
+ dfsan_set_arg_tls(1, buf_label);
+ dfsan_set_arg_tls(2, count_label);
+ if (origins) {
+ dfsan_set_arg_origin_tls(0, fd_origin);
+ dfsan_set_arg_origin_tls(1, buf_origin);
+ dfsan_set_arg_origin_tls(2, count_origin);
+ }
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int
+__dfsw_write(int fd, const void *buf, size_t count,
+ dfsan_label fd_label, dfsan_label buf_label,
+ dfsan_label count_label, dfsan_label *ret_label) {
+ if (write_callback_info.write_callback) {
+ setup_tls_args_for_write_callback(fd_label, buf_label, count_label, false,
+ 0, 0, 0);
+ write_callback_info.write_callback(fd, buf, count);
+ }
+
+ *ret_label = 0;
+ return write(fd, buf, count);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write(
+ int fd, const void *buf, size_t count, dfsan_label fd_label,
+ dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
+ dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
+ dfsan_origin *ret_origin) {
+ if (write_callback_info.write_callback) {
+ setup_tls_args_for_write_callback(fd_label, buf_label, count_label, true,
+ fd_origin, buf_origin, count_origin);
+ write_callback_info.write_callback(fd, buf, count);
+ }
+
+ *ret_label = 0;
+ return write(fd, buf, count);
+}
+} // namespace __dfsan
+
+// Type used to extract a dfsan_label with va_arg()
+typedef int dfsan_label_va;
+
+// Formats a chunk either a constant string or a single format directive (e.g.,
+// '%.3f').
+struct Formatter {
+ Formatter(char *str_, const char *fmt_, size_t size_)
+ : str(str_), str_off(0), size(size_), fmt_start(fmt_), fmt_cur(fmt_),
+ width(-1) {}
+
+ int format() {
+ char *tmp_fmt = build_format_string();
+ int retval =
+ snprintf(str + str_off, str_off < size ? size - str_off : 0, tmp_fmt,
+ 0 /* used only to avoid warnings */);
+ free(tmp_fmt);
+ return retval;
+ }
+
+ template <typename T> int format(T arg) {
+ char *tmp_fmt = build_format_string();
+ int retval;
+ if (width >= 0) {
+ retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
+ tmp_fmt, width, arg);
+ } else {
+ retval = snprintf(str + str_off, str_off < size ? size - str_off : 0,
+ tmp_fmt, arg);
+ }
+ free(tmp_fmt);
+ return retval;
+ }
+
+ char *build_format_string() {
+ size_t fmt_size = fmt_cur - fmt_start + 1;
+ char *new_fmt = (char *)malloc(fmt_size + 1);
+ assert(new_fmt);
+ internal_memcpy(new_fmt, fmt_start, fmt_size);
+ new_fmt[fmt_size] = '\0';
+ return new_fmt;
+ }
+
+ char *str_cur() { return str + str_off; }
+
+ size_t num_written_bytes(int retval) {
+ if (retval < 0) {
+ return 0;
+ }
+
+ size_t num_avail = str_off < size ? size - str_off : 0;
+ if (num_avail == 0) {
+ return 0;
+ }
+
+ size_t num_written = retval;
+ // A return value of {v,}snprintf of size or more means that the output was
+ // truncated.
+ if (num_written >= num_avail) {
+ num_written -= num_avail;
+ }
+
+ return num_written;
+ }
+
+ char *str;
+ size_t str_off;
+ size_t size;
+ const char *fmt_start;
+ const char *fmt_cur;
+ int width;
+};
+
+// Formats the input and propagates the input labels to the output. The output
+// is stored in 'str'. 'size' bounds the number of output bytes. 'format' and
+// 'ap' are the format string and the list of arguments for formatting. Returns
+// the return value vsnprintf would return.
+//
+// The function tokenizes the format string in chunks representing either a
+// constant string or a single format directive (e.g., '%.3f') and formats each
+// chunk independently into the output string. This approach allows to figure
+// out which bytes of the output string depends on which argument and thus to
+// propagate labels more precisely.
+//
+// WARNING: This implementation does not support conversion specifiers with
+// positional arguments.
+static int format_buffer(char *str, size_t size, const char *fmt,
+ dfsan_label *va_labels, dfsan_label *ret_label,
+ dfsan_origin *va_origins, dfsan_origin *ret_origin,
+ va_list ap) {
+ Formatter formatter(str, fmt, size);
+
+ while (*formatter.fmt_cur) {
+ formatter.fmt_start = formatter.fmt_cur;
+ formatter.width = -1;
+ int retval = 0;
+
+ if (*formatter.fmt_cur != '%') {
+ // Ordinary character. Consume all the characters until a '%' or the end
+ // of the string.
+ for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%';
+ ++formatter.fmt_cur) {}
+ retval = formatter.format();
+ dfsan_set_label(0, formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ } else {
+ // Conversion directive. Consume all the characters until a conversion
+ // specifier or the end of the string.
+ bool end_fmt = false;
+ for (; *formatter.fmt_cur && !end_fmt; ) {
+ switch (*++formatter.fmt_cur) {
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ switch (*(formatter.fmt_cur - 1)) {
+ case 'h':
+ // Also covers the 'hh' case (since the size of the arg is still
+ // an int).
+ retval = formatter.format(va_arg(ap, int));
+ break;
+ case 'l':
+ if (formatter.fmt_cur - formatter.fmt_start >= 2 &&
+ *(formatter.fmt_cur - 2) == 'l') {
+ retval = formatter.format(va_arg(ap, long long int));
+ } else {
+ retval = formatter.format(va_arg(ap, long int));
+ }
+ break;
+ case 'q':
+ retval = formatter.format(va_arg(ap, long long int));
+ break;
+ case 'j':
+ retval = formatter.format(va_arg(ap, intmax_t));
+ break;
+ case 'z':
+ case 't':
+ retval = formatter.format(va_arg(ap, size_t));
+ break;
+ default:
+ retval = formatter.format(va_arg(ap, int));
+ }
+ if (va_origins == nullptr)
+ dfsan_set_label(*va_labels++, formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ else
+ dfsan_set_label_origin(*va_labels++, *va_origins++,
+ formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ end_fmt = true;
+ break;
+
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ if (*(formatter.fmt_cur - 1) == 'L') {
+ retval = formatter.format(va_arg(ap, long double));
+ } else {
+ retval = formatter.format(va_arg(ap, double));
+ }
+ if (va_origins == nullptr)
+ dfsan_set_label(*va_labels++, formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ else
+ dfsan_set_label_origin(*va_labels++, *va_origins++,
+ formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ end_fmt = true;
+ break;
+
+ case 'c':
+ retval = formatter.format(va_arg(ap, int));
+ if (va_origins == nullptr)
+ dfsan_set_label(*va_labels++, formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ else
+ dfsan_set_label_origin(*va_labels++, *va_origins++,
+ formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ end_fmt = true;
+ break;
+
+ case 's': {
+ char *arg = va_arg(ap, char *);
+ retval = formatter.format(arg);
+ if (va_origins) {
+ va_origins++;
+ dfsan_mem_origin_transfer(formatter.str_cur(), arg,
+ formatter.num_written_bytes(retval));
+ }
+ va_labels++;
+ dfsan_mem_shadow_transfer(formatter.str_cur(), arg,
+ formatter.num_written_bytes(retval));
+ end_fmt = true;
+ break;
+ }
+
+ case 'p':
+ retval = formatter.format(va_arg(ap, void *));
+ if (va_origins == nullptr)
+ dfsan_set_label(*va_labels++, formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ else
+ dfsan_set_label_origin(*va_labels++, *va_origins++,
+ formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ end_fmt = true;
+ break;
+
+ case 'n': {
+ int *ptr = va_arg(ap, int *);
+ *ptr = (int)formatter.str_off;
+ va_labels++;
+ if (va_origins)
+ va_origins++;
+ dfsan_set_label(0, ptr, sizeof(ptr));
+ end_fmt = true;
+ break;
+ }
+
+ case '%':
+ retval = formatter.format();
+ dfsan_set_label(0, formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ end_fmt = true;
+ break;
+
+ case '*':
+ formatter.width = va_arg(ap, int);
+ va_labels++;
+ if (va_origins)
+ va_origins++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (retval < 0) {
+ return retval;
+ }
+
+ formatter.fmt_cur++;
+ formatter.str_off += retval;
+ }
+
+ *ret_label = 0;
+ if (ret_origin)
+ *ret_origin = 0;
+
+ // Number of bytes written in total.
+ return formatter.str_off;
+}
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_sprintf(char *str, const char *format, dfsan_label str_label,
+ dfsan_label format_label, dfsan_label *va_labels,
+ dfsan_label *ret_label, ...) {
+ va_list ap;
+ va_start(ap, ret_label);
+ int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, nullptr,
+ nullptr, ap);
+ va_end(ap);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_sprintf(char *str, const char *format, dfsan_label str_label,
+ dfsan_label format_label, dfsan_label *va_labels,
+ dfsan_label *ret_label, dfsan_origin str_origin,
+ dfsan_origin format_origin, dfsan_origin *va_origins,
+ dfsan_origin *ret_origin, ...) {
+ va_list ap;
+ va_start(ap, ret_origin);
+ int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, va_origins,
+ ret_origin, ap);
+ va_end(ap);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_snprintf(char *str, size_t size, const char *format,
+ dfsan_label str_label, dfsan_label size_label,
+ dfsan_label format_label, dfsan_label *va_labels,
+ dfsan_label *ret_label, ...) {
+ va_list ap;
+ va_start(ap, ret_label);
+ int ret = format_buffer(str, size, format, va_labels, ret_label, nullptr,
+ nullptr, ap);
+ va_end(ap);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_snprintf(char *str, size_t size, const char *format,
+ dfsan_label str_label, dfsan_label size_label,
+ dfsan_label format_label, dfsan_label *va_labels,
+ dfsan_label *ret_label, dfsan_origin str_origin,
+ dfsan_origin size_origin, dfsan_origin format_origin,
+ dfsan_origin *va_origins, dfsan_origin *ret_origin, ...) {
+ va_list ap;
+ va_start(ap, ret_origin);
+ int ret = format_buffer(str, size, format, va_labels, ret_label, va_origins,
+ ret_origin, ap);
+ va_end(ap);
+ return ret;
+}
+
+static void BeforeFork() {
+ StackDepotLockAll();
+ GetChainedOriginDepot()->LockAll();
+}
+
+static void AfterFork() {
+ GetChainedOriginDepot()->UnlockAll();
+ StackDepotUnlockAll();
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+pid_t __dfsw_fork(dfsan_label *ret_label) {
+ pid_t pid = fork();
+ *ret_label = 0;
+ return pid;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+pid_t __dfso_fork(dfsan_label *ret_label, dfsan_origin *ret_origin) {
+ BeforeFork();
+ pid_t pid = __dfsw_fork(ret_label);
+ AfterFork();
+ return pid;
+}
+
+// Default empty implementations (weak). Users should redefine them.
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *,
+ u32 *) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr *beg,
+ const uptr *end) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {}
+
+SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp1, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp2, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp4, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp8, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp1,
+ void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp2,
+ void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp4,
+ void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp8,
+ void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_switch, void) {}
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan_flags.h b/contrib/libs/clang16-rt/lib/dfsan/dfsan_flags.h
new file mode 100644
index 00000000000..ec7edf6112a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan_flags.h
@@ -0,0 +1,32 @@
+//===-- dfsan_flags.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataFlowSanitizer.
+//
+// DFSan flags.
+//===----------------------------------------------------------------------===//
+
+#ifndef DFSAN_FLAGS_H
+#define DFSAN_FLAGS_H
+
+namespace __dfsan {
+
+struct Flags {
+#define DFSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "dfsan_flags.inc"
+#undef DFSAN_FLAG
+
+ void SetDefaults();
+};
+
+extern Flags flags_data;
+inline Flags &flags() { return flags_data; }
+
+} // namespace __dfsan
+
+#endif // DFSAN_FLAGS_H
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan_flags.inc b/contrib/libs/clang16-rt/lib/dfsan/dfsan_flags.inc
new file mode 100644
index 00000000000..67fda0eee49
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan_flags.inc
@@ -0,0 +1,43 @@
+//===-- dfsan_flags.inc -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// DFSan runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef DFSAN_FLAG
+# error "Define DFSAN_FLAG prior to including this file!"
+#endif
+
+// DFSAN_FLAG(Type, Name, DefaultValue, Description)
+// See COMMON_FLAG in sanitizer_flags.inc for more details.
+
+DFSAN_FLAG(bool, warn_unimplemented, false,
+ "Whether to warn on unimplemented functions.")
+DFSAN_FLAG(bool, warn_nonzero_labels, false,
+ "Whether to warn on unimplemented functions.")
+DFSAN_FLAG(
+ bool, strict_data_dependencies, true,
+ "Whether to propagate labels only when there is an obvious data dependency"
+ "(e.g., when comparing strings, ignore the fact that the output of the"
+ "comparison might be data-dependent on the content of the strings). This"
+ "applies only to the custom functions defined in 'custom.c'.")
+DFSAN_FLAG(
+ int, origin_history_size, Origin::kMaxDepth,
+ "The limit of origin chain length. Non-positive values mean unlimited.")
+DFSAN_FLAG(
+ int, origin_history_per_stack_limit, 20000,
+ "The limit of origin node's references count. "
+ "Non-positive values mean unlimited.")
+DFSAN_FLAG(int, store_context_size, 20,
+ "The depth limit of origin tracking stack traces.")
+DFSAN_FLAG(bool, check_origin_invariant, false,
+ "Whether to check if the origin invariant holds.")
+DFSAN_FLAG(bool, zero_in_malloc, true,
+ "Whether to zero shadow space of new allocated memory.")
+DFSAN_FLAG(bool, zero_in_free, true,
+ "Whether to zero shadow space of deallocated memory.")
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan_interceptors.cpp b/contrib/libs/clang16-rt/lib/dfsan/dfsan_interceptors.cpp
new file mode 100644
index 00000000000..d8fb9ea8661
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan_interceptors.cpp
@@ -0,0 +1,220 @@
+//===-- dfsan_interceptors.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataFlowSanitizer.
+//
+// Interceptors for standard library functions.
+//===----------------------------------------------------------------------===//
+
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include "dfsan/dfsan.h"
+#include "dfsan/dfsan_thread.h"
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_allocator_dlsym.h"
+#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_errno.h"
+#include "sanitizer_common/sanitizer_platform_limits_posix.h"
+#include "sanitizer_common/sanitizer_posix.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+
+using namespace __sanitizer;
+
+static bool interceptors_initialized;
+
+struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
+ static bool UseImpl() { return !__dfsan::dfsan_inited; }
+};
+
+INTERCEPTOR(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size) {
+ return __dfsan::dfsan_reallocarray(ptr, nmemb, size);
+}
+
+INTERCEPTOR(void *, __libc_memalign, SIZE_T alignment, SIZE_T size) {
+ void *ptr = __dfsan::dfsan_memalign(alignment, size);
+ if (ptr)
+ DTLS_on_libc_memalign(ptr, size);
+ return ptr;
+}
+
+INTERCEPTOR(void *, aligned_alloc, SIZE_T alignment, SIZE_T size) {
+ return __dfsan::dfsan_aligned_alloc(alignment, size);
+}
+
+INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Callocate(nmemb, size);
+ return __dfsan::dfsan_calloc(nmemb, size);
+}
+
+INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
+ if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Realloc(ptr, size);
+ return __dfsan::dfsan_realloc(ptr, size);
+}
+
+INTERCEPTOR(void *, malloc, SIZE_T size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Allocate(size);
+ return __dfsan::dfsan_malloc(size);
+}
+
+INTERCEPTOR(void, free, void *ptr) {
+ if (!ptr)
+ return;
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+ return __dfsan::dfsan_deallocate(ptr);
+}
+
+INTERCEPTOR(void, cfree, void *ptr) {
+ if (!ptr)
+ return;
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+ return __dfsan::dfsan_deallocate(ptr);
+}
+
+INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) {
+ CHECK_NE(memptr, 0);
+ int res = __dfsan::dfsan_posix_memalign(memptr, alignment, size);
+ if (!res)
+ dfsan_set_label(0, memptr, sizeof(*memptr));
+ return res;
+}
+
+INTERCEPTOR(void *, memalign, SIZE_T alignment, SIZE_T size) {
+ return __dfsan::dfsan_memalign(alignment, size);
+}
+
+INTERCEPTOR(void *, valloc, SIZE_T size) { return __dfsan::dfsan_valloc(size); }
+
+INTERCEPTOR(void *, pvalloc, SIZE_T size) {
+ return __dfsan::dfsan_pvalloc(size);
+}
+
+INTERCEPTOR(void, mallinfo, __sanitizer_struct_mallinfo *sret) {
+ internal_memset(sret, 0, sizeof(*sret));
+ dfsan_set_label(0, sret, sizeof(*sret));
+}
+
+INTERCEPTOR(int, mallopt, int cmd, int value) { return 0; }
+
+INTERCEPTOR(void, malloc_stats, void) {
+ // FIXME: implement, but don't call REAL(malloc_stats)!
+}
+
+INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
+ return __sanitizer_get_allocated_size(ptr);
+}
+
+#define ENSURE_DFSAN_INITED() \
+ do { \
+ CHECK(!__dfsan::dfsan_init_is_running); \
+ if (!__dfsan::dfsan_inited) { \
+ __dfsan::dfsan_init(); \
+ } \
+ } while (0)
+
+#define COMMON_INTERCEPTOR_ENTER(func, ...) \
+ if (__dfsan::dfsan_init_is_running) \
+ return REAL(func)(__VA_ARGS__); \
+ ENSURE_DFSAN_INITED(); \
+ dfsan_set_label(0, __errno_location(), sizeof(int));
+
+INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
+ int fd, OFF_T offset) {
+ if (common_flags()->detect_write_exec)
+ ReportMmapWriteExec(prot, flags);
+ if (!__dfsan::dfsan_inited)
+ return (void *)internal_mmap(addr, length, prot, flags, fd, offset);
+ COMMON_INTERCEPTOR_ENTER(mmap, addr, length, prot, flags, fd, offset);
+ void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);
+ if (res != (void *)-1) {
+ dfsan_set_label(0, res, RoundUpTo(length, GetPageSizeCached()));
+ }
+ return res;
+}
+
+INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,
+ int fd, OFF64_T offset) {
+ if (common_flags()->detect_write_exec)
+ ReportMmapWriteExec(prot, flags);
+ if (!__dfsan::dfsan_inited)
+ return (void *)internal_mmap(addr, length, prot, flags, fd, offset);
+ COMMON_INTERCEPTOR_ENTER(mmap64, addr, length, prot, flags, fd, offset);
+ void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
+ if (res != (void *)-1) {
+ dfsan_set_label(0, res, RoundUpTo(length, GetPageSizeCached()));
+ }
+ return res;
+}
+
+INTERCEPTOR(int, munmap, void *addr, SIZE_T length) {
+ if (!__dfsan::dfsan_inited)
+ return internal_munmap(addr, length);
+ COMMON_INTERCEPTOR_ENTER(munmap, addr, length);
+ int res = REAL(munmap)(addr, length);
+ if (res != -1)
+ dfsan_set_label(0, addr, RoundUpTo(length, GetPageSizeCached()));
+ return res;
+}
+
+#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
+ if (__dfsan::DFsanThread *t = __dfsan::GetCurrentThread()) { \
+ *begin = t->tls_begin(); \
+ *end = t->tls_end(); \
+ } else { \
+ *begin = *end = 0; \
+ }
+#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
+ dfsan_set_label(0, ptr, size)
+
+INTERCEPTOR(void *, __tls_get_addr, void *arg) {
+ COMMON_INTERCEPTOR_ENTER(__tls_get_addr, arg);
+ void *res = REAL(__tls_get_addr)(arg);
+ uptr tls_begin, tls_end;
+ COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
+ DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, tls_begin, tls_end);
+ if (dtv) {
+ // New DTLS block has been allocated.
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
+ }
+ return res;
+}
+
+namespace __dfsan {
+void initialize_interceptors() {
+ CHECK(!interceptors_initialized);
+
+ INTERCEPT_FUNCTION(aligned_alloc);
+ INTERCEPT_FUNCTION(calloc);
+ INTERCEPT_FUNCTION(cfree);
+ INTERCEPT_FUNCTION(free);
+ INTERCEPT_FUNCTION(mallinfo);
+ INTERCEPT_FUNCTION(malloc);
+ INTERCEPT_FUNCTION(malloc_stats);
+ INTERCEPT_FUNCTION(malloc_usable_size);
+ INTERCEPT_FUNCTION(mallopt);
+ INTERCEPT_FUNCTION(memalign);
+ INTERCEPT_FUNCTION(mmap);
+ INTERCEPT_FUNCTION(mmap64);
+ INTERCEPT_FUNCTION(munmap);
+ INTERCEPT_FUNCTION(posix_memalign);
+ INTERCEPT_FUNCTION(pvalloc);
+ INTERCEPT_FUNCTION(realloc);
+ INTERCEPT_FUNCTION(reallocarray);
+ INTERCEPT_FUNCTION(valloc);
+ INTERCEPT_FUNCTION(__tls_get_addr);
+ INTERCEPT_FUNCTION(__libc_memalign);
+
+ interceptors_initialized = true;
+}
+} // namespace __dfsan
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan_new_delete.cpp b/contrib/libs/clang16-rt/lib/dfsan/dfsan_new_delete.cpp
new file mode 100644
index 00000000000..7ac906e8107
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan_new_delete.cpp
@@ -0,0 +1,124 @@
+//===-- dfsan_new_delete.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataflowSanitizer.
+//
+// Interceptors for operators new and delete.
+//===----------------------------------------------------------------------===//
+
+#include <stddef.h>
+
+#include "dfsan.h"
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
+
+using namespace __dfsan;
+
+// Fake std::nothrow_t and std::align_val_t to avoid including <new>.
+namespace std {
+struct nothrow_t {};
+enum class align_val_t : size_t {};
+} // namespace std
+
+// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
+#define OPERATOR_NEW_BODY(nothrow) \
+ void *res = dfsan_malloc(size); \
+ if (!nothrow && UNLIKELY(!res)) { \
+ BufferedStackTrace stack; \
+ ReportOutOfMemory(size, &stack); \
+ } \
+ return res
+#define OPERATOR_NEW_BODY_ALIGN(nothrow) \
+ void *res = dfsan_memalign((uptr)align, size); \
+ if (!nothrow && UNLIKELY(!res)) { \
+ BufferedStackTrace stack; \
+ ReportOutOfMemory(size, &stack); \
+ } \
+ return res;
+
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::nothrow_t const &) {
+ OPERATOR_NEW_BODY(true /*nothrow*/);
+}
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::nothrow_t const &) {
+ OPERATOR_NEW_BODY(true /*nothrow*/);
+}
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::align_val_t align) {
+ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/);
+}
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::align_val_t align) {
+ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/);
+}
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::align_val_t align,
+ std::nothrow_t const &) {
+ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/);
+}
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::align_val_t align,
+ std::nothrow_t const &) {
+ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/);
+}
+
+#define OPERATOR_DELETE_BODY \
+ if (ptr) \
+ dfsan_deallocate(ptr)
+
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr)NOEXCEPT { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::nothrow_t const &) {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::nothrow_t const &) {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, size_t size)NOEXCEPT { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, size_t size) NOEXCEPT {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align)NOEXCEPT {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align,
+ std::nothrow_t const &) {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align,
+ std::nothrow_t const &) {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, size_t size, std::align_val_t align)NOEXCEPT {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, size_t size,
+ std::align_val_t align) NOEXCEPT {
+ OPERATOR_DELETE_BODY;
+}
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan_origin.h b/contrib/libs/clang16-rt/lib/dfsan/dfsan_origin.h
new file mode 100644
index 00000000000..89fd7f99599
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan_origin.h
@@ -0,0 +1,127 @@
+//===-- dfsan_origin.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataFlowSanitizer.
+//
+// Origin id utils.
+//===----------------------------------------------------------------------===//
+
+#ifndef DFSAN_ORIGIN_H
+#define DFSAN_ORIGIN_H
+
+#include "dfsan_chained_origin_depot.h"
+#include "dfsan_flags.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+namespace __dfsan {
+
+// Origin handling.
+//
+// Origin is a 32-bit identifier that is attached to any taint value in the
+// program and describes how this memory came to be tainted.
+//
+// Chained origin id is like:
+// zzzz xxxx xxxx xxxx
+//
+// Chained origin id describes an event of storing a taint value to
+// memory. The xxx part is a value of ChainedOriginDepot, which is a mapping of
+// (stack_id, prev_id) -> id, where
+// * stack_id describes the event.
+// StackDepot keeps a mapping between those and corresponding stack traces.
+// * prev_id is another origin id that describes the earlier part of the
+// taint value history. 0 prev_id indicates the start of a chain.
+// Following a chain of prev_id provides the full recorded history of a taint
+// value.
+//
+// This, effectively, defines a forest where nodes are points in value history
+// marked with origin ids, and edges are events that are marked with stack_id.
+//
+// The "zzzz" bits of chained origin id are used to store the length of the
+// origin chain.
+
+class Origin {
+ public:
+ static bool isValidId(u32 id) { return id != 0; }
+
+ u32 raw_id() const { return raw_id_; }
+
+ bool isChainedOrigin() const { return Origin::isValidId(raw_id_); }
+
+ u32 getChainedId() const {
+ CHECK(Origin::isValidId(raw_id_));
+ return raw_id_ & kChainedIdMask;
+ }
+
+ // Returns the next origin in the chain and the current stack trace.
+ //
+ // It scans a partition of StackDepot linearly, and is used only by origin
+ // tracking report.
+ Origin getNextChainedOrigin(StackTrace *stack) const {
+ CHECK(Origin::isValidId(raw_id_));
+ u32 prev_id;
+ u32 stack_id = GetChainedOriginDepot()->Get(getChainedId(), &prev_id);
+ if (stack)
+ *stack = StackDepotGet(stack_id);
+ return Origin(prev_id);
+ }
+
+ static Origin CreateChainedOrigin(Origin prev, StackTrace *stack) {
+ int depth = prev.isChainedOrigin() ? prev.depth() : -1;
+ // depth is the length of the chain minus 1.
+ // origin_history_size of 0 means unlimited depth.
+ if (flags().origin_history_size > 0) {
+ ++depth;
+ if (depth >= flags().origin_history_size || depth > kMaxDepth)
+ return prev;
+ }
+
+ StackDepotHandle h = StackDepotPut_WithHandle(*stack);
+ if (!h.valid())
+ return prev;
+
+ if (flags().origin_history_per_stack_limit > 0) {
+ int use_count = h.use_count();
+ if (use_count > flags().origin_history_per_stack_limit)
+ return prev;
+ }
+
+ u32 chained_id;
+ bool inserted =
+ GetChainedOriginDepot()->Put(h.id(), prev.raw_id(), &chained_id);
+ CHECK((chained_id & kChainedIdMask) == chained_id);
+
+ if (inserted && flags().origin_history_per_stack_limit > 0)
+ h.inc_use_count_unsafe();
+
+ return Origin((depth << kDepthShift) | chained_id);
+ }
+
+ static Origin FromRawId(u32 id) { return Origin(id); }
+
+ private:
+ static const int kDepthBits = 4;
+ static const int kDepthShift = 32 - kDepthBits;
+
+ static const u32 kChainedIdMask = ((u32)-1) >> kDepthBits;
+
+ u32 raw_id_;
+
+ explicit Origin(u32 raw_id) : raw_id_(raw_id) {}
+
+ int depth() const {
+ CHECK(isChainedOrigin());
+ return (raw_id_ >> kDepthShift) & ((1 << kDepthBits) - 1);
+ }
+
+ public:
+ static const int kMaxDepth = (1 << kDepthBits) - 1;
+};
+
+} // namespace __dfsan
+
+#endif // DFSAN_ORIGIN_H
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan_platform.h b/contrib/libs/clang16-rt/lib/dfsan/dfsan_platform.h
new file mode 100644
index 00000000000..b849b4b528a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan_platform.h
@@ -0,0 +1,115 @@
+//===-- dfsan_platform.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataFlowSanitizer.
+//
+// Platform specific information for DFSan.
+//===----------------------------------------------------------------------===//
+
+#ifndef DFSAN_PLATFORM_H
+#define DFSAN_PLATFORM_H
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_platform.h"
+
+namespace __dfsan {
+
+using __sanitizer::uptr;
+
+// TODO: The memory mapping code to setup a 1:1 shadow is based on msan.
+// Consider refactoring these into a shared implementation.
+
+struct MappingDesc {
+ uptr start;
+ uptr end;
+ enum Type { INVALID, APP, SHADOW, ORIGIN } type;
+ const char *name;
+};
+
+#if SANITIZER_LINUX && SANITIZER_WORDSIZE == 64
+
+# if defined(__aarch64__)
+// The mapping assumes 48-bit VMA. AArch64 maps:
+// - 0x0000000000000-0x0100000000000: 39/42/48-bits program own segments
+// - 0x0a00000000000-0x0b00000000000: 48-bits PIE program segments
+// Ideally, this would extend to 0x0c00000000000 (2^45 bytes - the
+// maximum ASLR region for 48-bit VMA) but it is too hard to fit in
+// the larger app/shadow/origin regions.
+// - 0x0e00000000000-0x1000000000000: 48-bits libraries segments
+const MappingDesc kMemoryLayout[] = {
+ {0X0000000000000, 0X0100000000000, MappingDesc::APP, "app-10-13"},
+ {0X0100000000000, 0X0200000000000, MappingDesc::SHADOW, "shadow-14"},
+ {0X0200000000000, 0X0300000000000, MappingDesc::INVALID, "invalid"},
+ {0X0300000000000, 0X0400000000000, MappingDesc::ORIGIN, "origin-14"},
+ {0X0400000000000, 0X0600000000000, MappingDesc::SHADOW, "shadow-15"},
+ {0X0600000000000, 0X0800000000000, MappingDesc::ORIGIN, "origin-15"},
+ {0X0800000000000, 0X0A00000000000, MappingDesc::INVALID, "invalid"},
+ {0X0A00000000000, 0X0B00000000000, MappingDesc::APP, "app-14"},
+ {0X0B00000000000, 0X0C00000000000, MappingDesc::SHADOW, "shadow-10-13"},
+ {0X0C00000000000, 0X0D00000000000, MappingDesc::INVALID, "invalid"},
+ {0X0D00000000000, 0X0E00000000000, MappingDesc::ORIGIN, "origin-10-13"},
+ {0X0E00000000000, 0X1000000000000, MappingDesc::APP, "app-15"},
+};
+# define MEM_TO_SHADOW(mem) ((uptr)mem ^ 0xB00000000000ULL)
+# define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x200000000000ULL)
+
+# else
+// All of the following configurations are supported.
+// ASLR disabled: main executable and DSOs at 0x555550000000
+// PIE and ASLR: main executable and DSOs at 0x7f0000000000
+// non-PIE: main executable below 0x100000000, DSOs at 0x7f0000000000
+// Heap at 0x700000000000.
+const MappingDesc kMemoryLayout[] = {
+ {0x000000000000ULL, 0x010000000000ULL, MappingDesc::APP, "app-1"},
+ {0x010000000000ULL, 0x100000000000ULL, MappingDesc::SHADOW, "shadow-2"},
+ {0x100000000000ULL, 0x110000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x110000000000ULL, 0x200000000000ULL, MappingDesc::ORIGIN, "origin-2"},
+ {0x200000000000ULL, 0x300000000000ULL, MappingDesc::SHADOW, "shadow-3"},
+ {0x300000000000ULL, 0x400000000000ULL, MappingDesc::ORIGIN, "origin-3"},
+ {0x400000000000ULL, 0x500000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x500000000000ULL, 0x510000000000ULL, MappingDesc::SHADOW, "shadow-1"},
+ {0x510000000000ULL, 0x600000000000ULL, MappingDesc::APP, "app-2"},
+ {0x600000000000ULL, 0x610000000000ULL, MappingDesc::ORIGIN, "origin-1"},
+ {0x610000000000ULL, 0x700000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x700000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}};
+# define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL)
+# define SHADOW_TO_ORIGIN(mem) (((uptr)(mem)) + 0x100000000000ULL)
+# endif
+
+#else
+# error "Unsupported platform"
+#endif
+
+const uptr kMemoryLayoutSize = sizeof(kMemoryLayout) / sizeof(kMemoryLayout[0]);
+
+#define MEM_TO_ORIGIN(mem) (SHADOW_TO_ORIGIN(MEM_TO_SHADOW((mem))))
+
+#ifndef __clang__
+__attribute__((optimize("unroll-loops")))
+#endif
+inline bool
+addr_is_type(uptr addr, MappingDesc::Type mapping_type) {
+// It is critical for performance that this loop is unrolled (because then it is
+// simplified into just a few constant comparisons).
+#ifdef __clang__
+# pragma unroll
+#endif
+ for (unsigned i = 0; i < kMemoryLayoutSize; ++i)
+ if (kMemoryLayout[i].type == mapping_type &&
+ addr >= kMemoryLayout[i].start && addr < kMemoryLayout[i].end)
+ return true;
+ return false;
+}
+
+#define MEM_IS_APP(mem) addr_is_type((uptr)(mem), MappingDesc::APP)
+#define MEM_IS_SHADOW(mem) addr_is_type((uptr)(mem), MappingDesc::SHADOW)
+#define MEM_IS_ORIGIN(mem) addr_is_type((uptr)(mem), MappingDesc::ORIGIN)
+
+} // namespace __dfsan
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan_thread.cpp b/contrib/libs/clang16-rt/lib/dfsan/dfsan_thread.cpp
new file mode 100644
index 00000000000..e64f0f818fb
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan_thread.cpp
@@ -0,0 +1,134 @@
+#include "dfsan_thread.h"
+
+#include <pthread.h>
+
+#include "dfsan.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+
+namespace __dfsan {
+
+DFsanThread *DFsanThread::Create(thread_callback_t start_routine, void *arg,
+ bool track_origins) {
+ uptr PageSize = GetPageSizeCached();
+ uptr size = RoundUpTo(sizeof(DFsanThread), PageSize);
+ DFsanThread *thread = (DFsanThread *)MmapOrDie(size, __func__);
+ thread->start_routine_ = start_routine;
+ thread->arg_ = arg;
+ thread->track_origins_ = track_origins;
+ thread->destructor_iterations_ = GetPthreadDestructorIterations();
+
+ return thread;
+}
+
+void DFsanThread::SetThreadStackAndTls() {
+ uptr tls_size = 0;
+ uptr stack_size = 0;
+ GetThreadStackAndTls(IsMainThread(), &stack_.bottom, &stack_size, &tls_begin_,
+ &tls_size);
+ stack_.top = stack_.bottom + stack_size;
+ tls_end_ = tls_begin_ + tls_size;
+
+ int local;
+ CHECK(AddrIsInStack((uptr)&local));
+}
+
+void DFsanThread::ClearShadowForThreadStackAndTLS() {
+ dfsan_set_label(0, (void *)stack_.bottom, stack_.top - stack_.bottom);
+ if (tls_begin_ != tls_end_)
+ dfsan_set_label(0, (void *)tls_begin_, tls_end_ - tls_begin_);
+ DTLS *dtls = DTLS_Get();
+ CHECK_NE(dtls, 0);
+ ForEachDVT(dtls, [](const DTLS::DTV &dtv, int id) {
+ dfsan_set_label(0, (void *)(dtv.beg), dtv.size);
+ });
+}
+
+void DFsanThread::Init() {
+ SetThreadStackAndTls();
+ ClearShadowForThreadStackAndTLS();
+}
+
+void DFsanThread::TSDDtor(void *tsd) {
+ DFsanThread *t = (DFsanThread *)tsd;
+ t->Destroy();
+}
+
+void DFsanThread::Destroy() {
+ malloc_storage().CommitBack();
+ // We also clear the shadow on thread destruction because
+ // some code may still be executing in later TSD destructors
+ // and we don't want it to have any poisoned stack.
+ ClearShadowForThreadStackAndTLS();
+ uptr size = RoundUpTo(sizeof(DFsanThread), GetPageSizeCached());
+ UnmapOrDie(this, size);
+ DTLS_Destroy();
+}
+
+thread_return_t DFsanThread::ThreadStart() {
+ if (!start_routine_) {
+ // start_routine_ == 0 if we're on the main thread or on one of the
+ // OS X libdispatch worker threads. But nobody is supposed to call
+ // ThreadStart() for the worker threads.
+ return 0;
+ }
+
+ // The only argument is void* arg.
+ //
+ // We have never supported propagating the pointer arg as tainted,
+ // __dfsw_pthread_create/__dfso_pthread_create ignore the taint label.
+ // Note that the bytes pointed-to (probably the much more common case)
+ // can still have taint labels attached to them.
+ dfsan_clear_thread_local_state();
+
+ return start_routine_(arg_);
+}
+
+DFsanThread::StackBounds DFsanThread::GetStackBounds() const {
+ return {stack_.bottom, stack_.top};
+}
+
+uptr DFsanThread::stack_top() { return GetStackBounds().top; }
+
+uptr DFsanThread::stack_bottom() { return GetStackBounds().bottom; }
+
+bool DFsanThread::AddrIsInStack(uptr addr) {
+ const auto bounds = GetStackBounds();
+ return addr >= bounds.bottom && addr < bounds.top;
+}
+
+static pthread_key_t tsd_key;
+static bool tsd_key_inited = false;
+
+void DFsanTSDInit(void (*destructor)(void *tsd)) {
+ CHECK(!tsd_key_inited);
+ tsd_key_inited = true;
+ CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
+}
+
+static THREADLOCAL DFsanThread *dfsan_current_thread;
+
+DFsanThread *GetCurrentThread() { return dfsan_current_thread; }
+
+void SetCurrentThread(DFsanThread *t) {
+ // Make sure we do not reset the current DFsanThread.
+ CHECK_EQ(0, dfsan_current_thread);
+ dfsan_current_thread = t;
+ // Make sure that DFsanTSDDtor gets called at the end.
+ CHECK(tsd_key_inited);
+ pthread_setspecific(tsd_key, t);
+}
+
+void DFsanTSDDtor(void *tsd) {
+ DFsanThread *t = (DFsanThread *)tsd;
+ if (t->destructor_iterations_ > 1) {
+ t->destructor_iterations_--;
+ CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
+ return;
+ }
+ dfsan_current_thread = nullptr;
+ // Make sure that signal handler can not see a stale current thread pointer.
+ atomic_signal_fence(memory_order_seq_cst);
+ DFsanThread::TSDDtor(tsd);
+}
+
+} // namespace __dfsan
diff --git a/contrib/libs/clang16-rt/lib/dfsan/dfsan_thread.h b/contrib/libs/clang16-rt/lib/dfsan/dfsan_thread.h
new file mode 100644
index 00000000000..ebc25499e26
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/dfsan_thread.h
@@ -0,0 +1,82 @@
+//===-- dfsan_thread.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataFlowSanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DFSAN_THREAD_H
+#define DFSAN_THREAD_H
+
+#include "dfsan_allocator.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_posix.h"
+
+namespace __dfsan {
+
+class DFsanThread {
+ public:
+ // NOTE: There is no DFsanThread constructor. It is allocated
+ // via mmap() and *must* be valid in zero-initialized state.
+
+ static DFsanThread *Create(thread_callback_t start_routine, void *arg,
+ bool track_origins = false);
+ static void TSDDtor(void *tsd);
+ void Destroy();
+
+ void Init(); // Should be called from the thread itself.
+ thread_return_t ThreadStart();
+
+ uptr stack_top();
+ uptr stack_bottom();
+ uptr tls_begin() { return tls_begin_; }
+ uptr tls_end() { return tls_end_; }
+ bool IsMainThread() { return start_routine_ == nullptr; }
+
+ bool InSignalHandler() { return in_signal_handler_; }
+ void EnterSignalHandler() { in_signal_handler_++; }
+ void LeaveSignalHandler() { in_signal_handler_--; }
+
+ DFsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
+
+ int destructor_iterations_;
+ __sanitizer_sigset_t starting_sigset_;
+
+ private:
+ void SetThreadStackAndTls();
+ void ClearShadowForThreadStackAndTLS();
+ struct StackBounds {
+ uptr bottom;
+ uptr top;
+ };
+ StackBounds GetStackBounds() const;
+
+ bool AddrIsInStack(uptr addr);
+
+ thread_callback_t start_routine_;
+ void *arg_;
+ bool track_origins_;
+
+ StackBounds stack_;
+
+ uptr tls_begin_;
+ uptr tls_end_;
+
+ unsigned in_signal_handler_;
+
+ DFsanThreadLocalMallocStorage malloc_storage_;
+};
+
+DFsanThread *GetCurrentThread();
+void SetCurrentThread(DFsanThread *t);
+void DFsanTSDInit(void (*destructor)(void *tsd));
+void DFsanTSDDtor(void *tsd);
+
+} // namespace __dfsan
+
+#endif // DFSAN_THREAD_H
diff --git a/contrib/libs/clang16-rt/lib/dfsan/ya.make b/contrib/libs/clang16-rt/lib/dfsan/ya.make
new file mode 100644
index 00000000000..44e68592b60
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/dfsan/ya.make
@@ -0,0 +1,122 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.dfsan${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHAVE_RPC_XDR_H=0
+ -fPIE
+ -ffreestanding
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ dfsan/dfsan.cpp
+ dfsan/dfsan_allocator.cpp
+ dfsan/dfsan_chained_origin_depot.cpp
+ dfsan/dfsan_custom.cpp
+ dfsan/dfsan_interceptors.cpp
+ dfsan/dfsan_new_delete.cpp
+ dfsan/dfsan_thread.cpp
+ interception/interception_linux.cpp
+ interception/interception_mac.cpp
+ interception/interception_type_test.cpp
+ interception/interception_win.cpp
+ sanitizer_common/sanitizer_allocator.cpp
+ sanitizer_common/sanitizer_allocator_checks.cpp
+ sanitizer_common/sanitizer_allocator_report.cpp
+ sanitizer_common/sanitizer_chained_origin_depot.cpp
+ sanitizer_common/sanitizer_common.cpp
+ sanitizer_common/sanitizer_common_libcdep.cpp
+ sanitizer_common/sanitizer_deadlock_detector1.cpp
+ sanitizer_common/sanitizer_deadlock_detector2.cpp
+ sanitizer_common/sanitizer_errno.cpp
+ sanitizer_common/sanitizer_file.cpp
+ sanitizer_common/sanitizer_flag_parser.cpp
+ sanitizer_common/sanitizer_flags.cpp
+ sanitizer_common/sanitizer_fuchsia.cpp
+ sanitizer_common/sanitizer_libc.cpp
+ sanitizer_common/sanitizer_libignore.cpp
+ sanitizer_common/sanitizer_linux.cpp
+ sanitizer_common/sanitizer_linux_libcdep.cpp
+ sanitizer_common/sanitizer_linux_s390.cpp
+ sanitizer_common/sanitizer_mac.cpp
+ sanitizer_common/sanitizer_mac_libcdep.cpp
+ sanitizer_common/sanitizer_mutex.cpp
+ sanitizer_common/sanitizer_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+ sanitizer_common/sanitizer_platform_limits_linux.cpp
+ sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_posix.cpp
+ sanitizer_common/sanitizer_platform_limits_solaris.cpp
+ sanitizer_common/sanitizer_posix.cpp
+ sanitizer_common/sanitizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_printf.cpp
+ sanitizer_common/sanitizer_procmaps_bsd.cpp
+ sanitizer_common/sanitizer_procmaps_common.cpp
+ sanitizer_common/sanitizer_procmaps_fuchsia.cpp
+ sanitizer_common/sanitizer_procmaps_linux.cpp
+ sanitizer_common/sanitizer_procmaps_mac.cpp
+ sanitizer_common/sanitizer_procmaps_solaris.cpp
+ sanitizer_common/sanitizer_solaris.cpp
+ sanitizer_common/sanitizer_stack_store.cpp
+ sanitizer_common/sanitizer_stackdepot.cpp
+ sanitizer_common/sanitizer_stacktrace.cpp
+ sanitizer_common/sanitizer_stacktrace_libcdep.cpp
+ sanitizer_common/sanitizer_stacktrace_printer.cpp
+ sanitizer_common/sanitizer_stacktrace_sparc.cpp
+ sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
+ sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_mac.cpp
+ sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_win.cpp
+ sanitizer_common/sanitizer_suppressions.cpp
+ sanitizer_common/sanitizer_symbolizer.cpp
+ sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
+ sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_mac.cpp
+ sanitizer_common/sanitizer_symbolizer_markup.cpp
+ sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_report.cpp
+ sanitizer_common/sanitizer_symbolizer_win.cpp
+ sanitizer_common/sanitizer_termination.cpp
+ sanitizer_common/sanitizer_thread_registry.cpp
+ sanitizer_common/sanitizer_tls_get_addr.cpp
+ sanitizer_common/sanitizer_type_traits.cpp
+ sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
+ sanitizer_common/sanitizer_unwind_win.cpp
+ sanitizer_common/sanitizer_win.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/gwp_asan/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/common.cpp b/contrib/libs/clang16-rt/lib/gwp_asan/common.cpp
new file mode 100644
index 00000000000..790a331aa66
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/common.cpp
@@ -0,0 +1,112 @@
+//===-- common.cpp ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "gwp_asan/common.h"
+#include "gwp_asan/stack_trace_compressor.h"
+
+#include <assert.h>
+
+using AllocationMetadata = gwp_asan::AllocationMetadata;
+using Error = gwp_asan::Error;
+
+namespace gwp_asan {
+
+const char *ErrorToString(const Error &E) {
+ switch (E) {
+ case Error::UNKNOWN:
+ return "Unknown";
+ case Error::USE_AFTER_FREE:
+ return "Use After Free";
+ case Error::DOUBLE_FREE:
+ return "Double Free";
+ case Error::INVALID_FREE:
+ return "Invalid (Wild) Free";
+ case Error::BUFFER_OVERFLOW:
+ return "Buffer Overflow";
+ case Error::BUFFER_UNDERFLOW:
+ return "Buffer Underflow";
+ }
+ __builtin_trap();
+}
+
+constexpr size_t AllocationMetadata::kStackFrameStorageBytes;
+constexpr size_t AllocationMetadata::kMaxTraceLengthToCollect;
+
+void AllocationMetadata::RecordAllocation(uintptr_t AllocAddr,
+ size_t AllocSize) {
+ Addr = AllocAddr;
+ RequestedSize = AllocSize;
+ IsDeallocated = false;
+
+ AllocationTrace.ThreadID = getThreadID();
+ DeallocationTrace.TraceSize = 0;
+ DeallocationTrace.ThreadID = kInvalidThreadID;
+}
+
+void AllocationMetadata::RecordDeallocation() {
+ IsDeallocated = true;
+ DeallocationTrace.ThreadID = getThreadID();
+}
+
+void AllocationMetadata::CallSiteInfo::RecordBacktrace(
+ options::Backtrace_t Backtrace) {
+ TraceSize = 0;
+ if (!Backtrace)
+ return;
+
+ uintptr_t UncompressedBuffer[kMaxTraceLengthToCollect];
+ size_t BacktraceLength =
+ Backtrace(UncompressedBuffer, kMaxTraceLengthToCollect);
+ // Backtrace() returns the number of available frames, which may be greater
+ // than the number of frames in the buffer. In this case, we need to only pack
+ // the number of frames that are in the buffer.
+ if (BacktraceLength > kMaxTraceLengthToCollect)
+ BacktraceLength = kMaxTraceLengthToCollect;
+ TraceSize =
+ compression::pack(UncompressedBuffer, BacktraceLength, CompressedTrace,
+ AllocationMetadata::kStackFrameStorageBytes);
+}
+
+size_t AllocatorState::maximumAllocationSize() const { return PageSize; }
+
+uintptr_t AllocatorState::slotToAddr(size_t N) const {
+ return GuardedPagePool + (PageSize * (1 + N)) + (maximumAllocationSize() * N);
+}
+
+bool AllocatorState::isGuardPage(uintptr_t Ptr) const {
+ assert(pointerIsMine(reinterpret_cast<void *>(Ptr)));
+ size_t PageOffsetFromPoolStart = (Ptr - GuardedPagePool) / PageSize;
+ size_t PagesPerSlot = maximumAllocationSize() / PageSize;
+ return (PageOffsetFromPoolStart % (PagesPerSlot + 1)) == 0;
+}
+
+static size_t addrToSlot(const AllocatorState *State, uintptr_t Ptr) {
+ size_t ByteOffsetFromPoolStart = Ptr - State->GuardedPagePool;
+ return ByteOffsetFromPoolStart /
+ (State->maximumAllocationSize() + State->PageSize);
+}
+
+size_t AllocatorState::getNearestSlot(uintptr_t Ptr) const {
+ if (Ptr <= GuardedPagePool + PageSize)
+ return 0;
+ if (Ptr > GuardedPagePoolEnd - PageSize)
+ return MaxSimultaneousAllocations - 1;
+
+ if (!isGuardPage(Ptr))
+ return addrToSlot(this, Ptr);
+
+ if (Ptr % PageSize <= PageSize / 2)
+ return addrToSlot(this, Ptr - PageSize); // Round down.
+ return addrToSlot(this, Ptr + PageSize); // Round up.
+}
+
+uintptr_t AllocatorState::internallyDetectedErrorFaultAddress() const {
+ return GuardedPagePoolEnd - 0x10;
+}
+
+} // namespace gwp_asan
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/common.h b/contrib/libs/clang16-rt/lib/gwp_asan/common.h
new file mode 100644
index 00000000000..df451021d34
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/common.h
@@ -0,0 +1,193 @@
+//===-- common.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// This file contains code that is common between the crash handler and the
+// GuardedPoolAllocator.
+
+#ifndef GWP_ASAN_COMMON_H_
+#define GWP_ASAN_COMMON_H_
+
+#include "gwp_asan/definitions.h"
+#include "gwp_asan/options.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace gwp_asan {
+
+// Magic header that resides in the AllocatorState so that GWP-ASan bugreports
+// can be understood by tools at different versions. Out-of-process crash
+// handlers, like crashpad on Fuchsia, take the raw contents of the
+// AllocationMetatada array and the AllocatorState, and shove them into the
+// minidump. Online unpacking of these structs needs to know from which version
+// of GWP-ASan it's extracting the information, as the structures are not
+// stable.
+struct AllocatorVersionMagic {
+ // The values are copied into the structure at runtime, during
+ // `GuardedPoolAllocator::init()` so that GWP-ASan remains completely in the
+ // `.bss` segment.
+ static constexpr uint8_t kAllocatorVersionMagic[4] = {'A', 'S', 'A', 'N'};
+ uint8_t Magic[4] = {};
+ // Update the version number when the AllocatorState or AllocationMetadata
+ // change.
+ static constexpr uint16_t kAllocatorVersion = 2;
+ uint16_t Version = 0;
+ uint16_t Reserved = 0;
+};
+
+enum class Error : uint8_t {
+ UNKNOWN,
+ USE_AFTER_FREE,
+ DOUBLE_FREE,
+ INVALID_FREE,
+ BUFFER_OVERFLOW,
+ BUFFER_UNDERFLOW
+};
+
+const char *ErrorToString(const Error &E);
+
+static constexpr uint64_t kInvalidThreadID = UINT64_MAX;
+// Get the current thread ID, or kInvalidThreadID if failure. Note: This
+// implementation is platform-specific.
+uint64_t getThreadID();
+
+// This struct contains all the metadata recorded about a single allocation made
+// by GWP-ASan. If `AllocationMetadata.Addr` is zero, the metadata is non-valid.
+struct AllocationMetadata {
+ // The number of bytes used to store a compressed stack frame. On 64-bit
+ // platforms, assuming a compression ratio of 50%, this should allow us to
+ // store ~64 frames per trace.
+ static constexpr size_t kStackFrameStorageBytes = 256;
+
+ // Maximum number of stack frames to collect on allocation/deallocation. The
+ // actual number of collected frames may be less than this as the stack
+ // frames are compressed into a fixed memory range.
+ static constexpr size_t kMaxTraceLengthToCollect = 128;
+
+ // Records the given allocation metadata into this struct.
+ void RecordAllocation(uintptr_t Addr, size_t RequestedSize);
+ // Record that this allocation is now deallocated.
+ void RecordDeallocation();
+
+ struct CallSiteInfo {
+ // Record the current backtrace to this callsite.
+ void RecordBacktrace(options::Backtrace_t Backtrace);
+
+ // The compressed backtrace to the allocation/deallocation.
+ uint8_t CompressedTrace[kStackFrameStorageBytes];
+ // The thread ID for this trace, or kInvalidThreadID if not available.
+ uint64_t ThreadID = kInvalidThreadID;
+ // The size of the compressed trace (in bytes). Zero indicates that no
+ // trace was collected.
+ size_t TraceSize = 0;
+ };
+
+ // The address of this allocation. If zero, the rest of this struct isn't
+ // valid, as the allocation has never occurred.
+ uintptr_t Addr = 0;
+ // Represents the actual size of the allocation.
+ size_t RequestedSize = 0;
+
+ CallSiteInfo AllocationTrace;
+ CallSiteInfo DeallocationTrace;
+
+ // Whether this allocation has been deallocated yet.
+ bool IsDeallocated = false;
+
+ // In recoverable mode, whether this allocation has had a crash associated
+ // with it. This has certain side effects, like meaning this allocation will
+ // permanently occupy a slot, and won't ever have another crash reported from
+ // it.
+ bool HasCrashed = false;
+};
+
+// This holds the state that's shared between the GWP-ASan allocator and the
+// crash handler. This, in conjunction with the Metadata array, forms the entire
+// set of information required for understanding a GWP-ASan crash.
+struct AllocatorState {
+ constexpr AllocatorState() {}
+ AllocatorVersionMagic VersionMagic{};
+
+ // Returns whether the provided pointer is a current sampled allocation that
+ // is owned by this pool.
+ GWP_ASAN_ALWAYS_INLINE bool pointerIsMine(const void *Ptr) const {
+ uintptr_t P = reinterpret_cast<uintptr_t>(Ptr);
+ return P < GuardedPagePoolEnd && GuardedPagePool <= P;
+ }
+
+ // Returns the address of the N-th guarded slot.
+ uintptr_t slotToAddr(size_t N) const;
+
+ // Returns the largest allocation that is supported by this pool.
+ size_t maximumAllocationSize() const;
+
+ // Gets the nearest slot to the provided address.
+ size_t getNearestSlot(uintptr_t Ptr) const;
+
+ // Returns whether the provided pointer is a guard page or not. The pointer
+ // must be within memory owned by this pool, else the result is undefined.
+ bool isGuardPage(uintptr_t Ptr) const;
+
+ // Returns the address that's used by __gwp_asan_get_internal_crash_address()
+ // and GPA::raiseInternallyDetectedError() to communicate that the SEGV in
+ // question comes from an internally-detected error.
+ uintptr_t internallyDetectedErrorFaultAddress() const;
+
+ // The number of guarded slots that this pool holds.
+ size_t MaxSimultaneousAllocations = 0;
+
+ // Pointer to the pool of guarded slots. Note that this points to the start of
+ // the pool (which is a guard page), not a pointer to the first guarded page.
+ uintptr_t GuardedPagePool = 0;
+ uintptr_t GuardedPagePoolEnd = 0;
+
+ // Cached page size for this system in bytes.
+ size_t PageSize = 0;
+
+ // The type and address of an internally-detected failure. For INVALID_FREE
+ // and DOUBLE_FREE, these errors are detected in GWP-ASan, which will set
+ // these values and terminate the process.
+ Error FailureType = Error::UNKNOWN;
+ uintptr_t FailureAddress = 0;
+};
+
+// Below are various compile-time checks that the layout of the internal
+// GWP-ASan structures are undisturbed. If they are disturbed, the version magic
+// number needs to be increased by one, and the asserts need to be updated.
+// Out-of-process crash handlers, like breakpad/crashpad, may copy the internal
+// GWP-ASan structures into a minidump for offline reconstruction of the crash.
+// In order to accomplish this, the offline reconstructor needs to know the
+// version of GWP-ASan internal structures that it's unpacking (along with the
+// architecture-specific layout info, which is left as an exercise to the crash
+// handler).
+static_assert(offsetof(AllocatorState, VersionMagic) == 0, "");
+static_assert(sizeof(AllocatorVersionMagic) == 8, "");
+#if defined(__x86_64__)
+static_assert(sizeof(AllocatorState) == 56, "");
+static_assert(offsetof(AllocatorState, FailureAddress) == 48, "");
+static_assert(sizeof(AllocationMetadata) == 568, "");
+static_assert(offsetof(AllocationMetadata, IsDeallocated) == 560, "");
+#elif defined(__aarch64__)
+static_assert(sizeof(AllocatorState) == 56, "");
+static_assert(offsetof(AllocatorState, FailureAddress) == 48, "");
+static_assert(sizeof(AllocationMetadata) == 568, "");
+static_assert(offsetof(AllocationMetadata, IsDeallocated) == 560, "");
+#elif defined(__i386__)
+static_assert(sizeof(AllocatorState) == 32, "");
+static_assert(offsetof(AllocatorState, FailureAddress) == 28, "");
+static_assert(sizeof(AllocationMetadata) == 548, "");
+static_assert(offsetof(AllocationMetadata, IsDeallocated) == 544, "");
+#elif defined(__arm__)
+static_assert(sizeof(AllocatorState) == 32, "");
+static_assert(offsetof(AllocatorState, FailureAddress) == 28, "");
+static_assert(sizeof(AllocationMetadata) == 560, "");
+static_assert(offsetof(AllocationMetadata, IsDeallocated) == 552, "");
+#endif // defined($ARCHITECTURE)
+
+} // namespace gwp_asan
+#endif // GWP_ASAN_COMMON_H_
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/crash_handler.cpp b/contrib/libs/clang16-rt/lib/gwp_asan/crash_handler.cpp
new file mode 100644
index 00000000000..555365c6e6f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/crash_handler.cpp
@@ -0,0 +1,162 @@
+//===-- crash_handler.cpp ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "gwp_asan/common.h"
+#include "gwp_asan/stack_trace_compressor.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+using AllocationMetadata = gwp_asan::AllocationMetadata;
+using Error = gwp_asan::Error;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool __gwp_asan_error_is_mine(const gwp_asan::AllocatorState *State,
+ uintptr_t ErrorPtr) {
+ assert(State && "State should not be nullptr.");
+ if (State->FailureType != Error::UNKNOWN && State->FailureAddress != 0)
+ return true;
+
+ return ErrorPtr < State->GuardedPagePoolEnd &&
+ State->GuardedPagePool <= ErrorPtr;
+}
+
+uintptr_t
+__gwp_asan_get_internal_crash_address(const gwp_asan::AllocatorState *State,
+ uintptr_t ErrorPtr) {
+ // There can be a race between internally- and externally-raised faults. The
+ // fault address from the signal handler is used to discriminate whether it's
+ // internally- or externally-raised, and the pool maintains a special page at
+ // the end of the GuardedPagePool specifically for the internally-raised
+ // faults.
+ if (ErrorPtr != State->internallyDetectedErrorFaultAddress())
+ return 0u;
+ return State->FailureAddress;
+}
+
+static const AllocationMetadata *
+addrToMetadata(const gwp_asan::AllocatorState *State,
+ const AllocationMetadata *Metadata, uintptr_t Ptr) {
+ // Note - Similar implementation in guarded_pool_allocator.cpp.
+ return &Metadata[State->getNearestSlot(Ptr)];
+}
+
+gwp_asan::Error
+__gwp_asan_diagnose_error(const gwp_asan::AllocatorState *State,
+ const gwp_asan::AllocationMetadata *Metadata,
+ uintptr_t ErrorPtr) {
+ if (!__gwp_asan_error_is_mine(State, ErrorPtr))
+ return Error::UNKNOWN;
+
+ if (State->FailureType != Error::UNKNOWN)
+ return State->FailureType;
+
+ // Check for use-after-free.
+ if (addrToMetadata(State, Metadata, ErrorPtr)->IsDeallocated)
+ return Error::USE_AFTER_FREE;
+
+ // Check for buffer-overflow. Because of allocation alignment or left/right
+ // page placement, we can have buffer-overflows that don't touch a guarded
+ // page, but these are not possible to detect unless it's also a
+ // use-after-free, which is handled above.
+ if (State->isGuardPage(ErrorPtr)) {
+ size_t Slot = State->getNearestSlot(ErrorPtr);
+ const AllocationMetadata *SlotMeta =
+ addrToMetadata(State, Metadata, State->slotToAddr(Slot));
+
+ // Ensure that this slot was allocated once upon a time.
+ if (!SlotMeta->Addr)
+ return Error::UNKNOWN;
+
+ if (SlotMeta->Addr < ErrorPtr)
+ return Error::BUFFER_OVERFLOW;
+ return Error::BUFFER_UNDERFLOW;
+ }
+
+ // If we have reached here, the error is still unknown.
+ return Error::UNKNOWN;
+}
+
+const gwp_asan::AllocationMetadata *
+__gwp_asan_get_metadata(const gwp_asan::AllocatorState *State,
+ const gwp_asan::AllocationMetadata *Metadata,
+ uintptr_t ErrorPtr) {
+ if (!__gwp_asan_error_is_mine(State, ErrorPtr))
+ return nullptr;
+
+ if (ErrorPtr >= State->GuardedPagePoolEnd ||
+ State->GuardedPagePool > ErrorPtr)
+ return nullptr;
+
+ const AllocationMetadata *Meta = addrToMetadata(State, Metadata, ErrorPtr);
+ if (Meta->Addr == 0)
+ return nullptr;
+
+ return Meta;
+}
+
+uintptr_t __gwp_asan_get_allocation_address(
+ const gwp_asan::AllocationMetadata *AllocationMeta) {
+ return AllocationMeta->Addr;
+}
+
+size_t __gwp_asan_get_allocation_size(
+ const gwp_asan::AllocationMetadata *AllocationMeta) {
+ return AllocationMeta->RequestedSize;
+}
+
+uint64_t __gwp_asan_get_allocation_thread_id(
+ const gwp_asan::AllocationMetadata *AllocationMeta) {
+ return AllocationMeta->AllocationTrace.ThreadID;
+}
+
+size_t __gwp_asan_get_allocation_trace(
+ const gwp_asan::AllocationMetadata *AllocationMeta, uintptr_t *Buffer,
+ size_t BufferLen) {
+ uintptr_t UncompressedBuffer[AllocationMetadata::kMaxTraceLengthToCollect];
+ size_t UnpackedLength = gwp_asan::compression::unpack(
+ AllocationMeta->AllocationTrace.CompressedTrace,
+ AllocationMeta->AllocationTrace.TraceSize, UncompressedBuffer,
+ AllocationMetadata::kMaxTraceLengthToCollect);
+ if (UnpackedLength < BufferLen)
+ BufferLen = UnpackedLength;
+ memcpy(Buffer, UncompressedBuffer, BufferLen * sizeof(*Buffer));
+ return UnpackedLength;
+}
+
+bool __gwp_asan_is_deallocated(
+ const gwp_asan::AllocationMetadata *AllocationMeta) {
+ return AllocationMeta->IsDeallocated;
+}
+
+uint64_t __gwp_asan_get_deallocation_thread_id(
+ const gwp_asan::AllocationMetadata *AllocationMeta) {
+ return AllocationMeta->DeallocationTrace.ThreadID;
+}
+
+size_t __gwp_asan_get_deallocation_trace(
+ const gwp_asan::AllocationMetadata *AllocationMeta, uintptr_t *Buffer,
+ size_t BufferLen) {
+ uintptr_t UncompressedBuffer[AllocationMetadata::kMaxTraceLengthToCollect];
+ size_t UnpackedLength = gwp_asan::compression::unpack(
+ AllocationMeta->DeallocationTrace.CompressedTrace,
+ AllocationMeta->DeallocationTrace.TraceSize, UncompressedBuffer,
+ AllocationMetadata::kMaxTraceLengthToCollect);
+ if (UnpackedLength < BufferLen)
+ BufferLen = UnpackedLength;
+ memcpy(Buffer, UncompressedBuffer, BufferLen * sizeof(*Buffer));
+ return UnpackedLength;
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/crash_handler.h b/contrib/libs/clang16-rt/lib/gwp_asan/crash_handler.h
new file mode 100644
index 00000000000..1ff60edea47
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/crash_handler.h
@@ -0,0 +1,131 @@
+//===-- crash_handler.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// This file contains interface functions that can be called by an in-process or
+// out-of-process crash handler after the process has terminated. Functions in
+// this interface are never thread safe. For an in-process crash handler, the
+// handler should call GuardedPoolAllocator::disable() to stop any other threads
+// from retrieving new GWP-ASan allocations, which may corrupt the metadata.
+#ifndef GWP_ASAN_INTERFACE_H_
+#define GWP_ASAN_INTERFACE_H_
+
+#include "gwp_asan/common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// When a process crashes, there are three possible outcomes:
+// 1. The crash is unrelated to GWP-ASan - in which case this function returns
+// false.
+// 2. The crash is internally detected within GWP-ASan itself (e.g. a
+// double-free bug is caught in GuardedPoolAllocator::deallocate(), and
+// GWP-ASan will terminate the process). In this case - this function
+// returns true.
+// 3. The crash is caused by a memory error at `AccessPtr` that's caught by the
+// system, but GWP-ASan is responsible for the allocation. In this case -
+// the function also returns true.
+// This function takes an optional `AccessPtr` parameter. If the pointer that
+// was attempted to be accessed is available, you should provide it here. In the
+// case of some internally-detected errors, the crash may manifest as an abort
+// or trap may or may not have an associated pointer. In these cases, the
+// pointer can be obtained by a call to __gwp_asan_get_internal_crash_address.
+bool __gwp_asan_error_is_mine(const gwp_asan::AllocatorState *State,
+ uintptr_t ErrorPtr = 0u);
+
+// Diagnose and return the type of error that occurred at `ErrorPtr`. If
+// `ErrorPtr` is unrelated to GWP-ASan, or if the error type cannot be deduced,
+// this function returns Error::UNKNOWN.
+gwp_asan::Error
+__gwp_asan_diagnose_error(const gwp_asan::AllocatorState *State,
+ const gwp_asan::AllocationMetadata *Metadata,
+ uintptr_t ErrorPtr);
+
+// This function, provided the fault address from the signal handler, returns
+// the following values:
+// 1. If the crash was caused by an internally-detected error (invalid free,
+// double free), this function returns the pointer that was used for the
+// internally-detected bad operation (i.e. the pointer given to free()).
+// 2. For externally-detected crashes (use-after-free, buffer-overflow), this
+// function returns zero.
+// 3. If GWP-ASan wasn't responsible for the crash at all, this function also
+// returns zero.
+uintptr_t
+__gwp_asan_get_internal_crash_address(const gwp_asan::AllocatorState *State,
+ uintptr_t ErrorPtr);
+
+// Returns a pointer to the metadata for the allocation that's responsible for
+// the crash. This metadata should not be dereferenced directly due to API
+// compatibility issues, but should be instead passed to functions below for
+// information retrieval. Returns nullptr if there is no metadata available for
+// this crash.
+const gwp_asan::AllocationMetadata *
+__gwp_asan_get_metadata(const gwp_asan::AllocatorState *State,
+ const gwp_asan::AllocationMetadata *Metadata,
+ uintptr_t ErrorPtr);
+
+// +---------------------------------------------------------------------------+
+// | Error Information Functions |
+// +---------------------------------------------------------------------------+
+// Functions below return information about the type of error that was caught by
+// GWP-ASan, or information about the allocation that caused the error. These
+// functions generally take an `AllocationMeta` argument, which should be
+// retrieved via. __gwp_asan_get_metadata.
+
+// Returns the start of the allocation whose metadata is in `AllocationMeta`.
+uintptr_t __gwp_asan_get_allocation_address(
+ const gwp_asan::AllocationMetadata *AllocationMeta);
+
+// Returns the size of the allocation whose metadata is in `AllocationMeta`
+size_t __gwp_asan_get_allocation_size(
+ const gwp_asan::AllocationMetadata *AllocationMeta);
+
+// Returns the Thread ID that allocated the memory that caused the error at
+// `ErrorPtr`. This function may not be called if __gwp_asan_has_metadata()
+// returns false.
+uint64_t __gwp_asan_get_allocation_thread_id(
+ const gwp_asan::AllocationMetadata *AllocationMeta);
+
+// Retrieve the allocation trace for the allocation whose metadata is in
+// `AllocationMeta`, and place it into the provided `Buffer` that has at least
+// `BufferLen` elements. This function returns the number of frames that would
+// have been written into `Buffer` if the space was available (i.e. however many
+// frames were stored by GWP-ASan). A return value greater than `BufferLen`
+// indicates that the trace was truncated when storing to `Buffer`.
+size_t __gwp_asan_get_allocation_trace(
+ const gwp_asan::AllocationMetadata *AllocationMeta, uintptr_t *Buffer,
+ size_t BufferLen);
+
+// Returns whether the allocation whose metadata is in `AllocationMeta` has been
+// deallocated. This function may not be called if __gwp_asan_has_metadata()
+// returns false.
+bool __gwp_asan_is_deallocated(
+ const gwp_asan::AllocationMetadata *AllocationMeta);
+
+// Returns the Thread ID that deallocated the memory whose metadata is in
+// `AllocationMeta`. This function may not be called if
+// __gwp_asan_is_deallocated() returns false.
+uint64_t __gwp_asan_get_deallocation_thread_id(
+ const gwp_asan::AllocationMetadata *AllocationMeta);
+
+// Retrieve the deallocation trace for the allocation whose metadata is in
+// `AllocationMeta`, and place it into the provided `Buffer` that has at least
+// `BufferLen` elements. This function returns the number of frames that would
+// have been written into `Buffer` if the space was available (i.e. however many
+// frames were stored by GWP-ASan). A return value greater than `BufferLen`
+// indicates that the trace was truncated when storing to `Buffer`. This
+// function may not be called if __gwp_asan_is_deallocated() returns false.
+size_t __gwp_asan_get_deallocation_trace(
+ const gwp_asan::AllocationMetadata *AllocationMeta, uintptr_t *Buffer,
+ size_t BufferLen);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // GWP_ASAN_INTERFACE_H_
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/definitions.h b/contrib/libs/clang16-rt/lib/gwp_asan/definitions.h
new file mode 100644
index 00000000000..bec02903893
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/definitions.h
@@ -0,0 +1,20 @@
+//===-- definitions.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_DEFINITIONS_H_
+#define GWP_ASAN_DEFINITIONS_H_
+
+#define GWP_ASAN_TLS_INITIAL_EXEC \
+ __thread __attribute__((tls_model("initial-exec")))
+
+#define GWP_ASAN_UNLIKELY(X) __builtin_expect(!!(X), 0)
+#define GWP_ASAN_ALWAYS_INLINE inline __attribute__((always_inline))
+
+#define GWP_ASAN_WEAK __attribute__((weak))
+
+#endif // GWP_ASAN_DEFINITIONS_H_
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/guarded_pool_allocator.cpp b/contrib/libs/clang16-rt/lib/gwp_asan/guarded_pool_allocator.cpp
new file mode 100644
index 00000000000..9017ab7cf7a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/guarded_pool_allocator.cpp
@@ -0,0 +1,469 @@
+//===-- guarded_pool_allocator.cpp ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "gwp_asan/guarded_pool_allocator.h"
+
+#include "gwp_asan/crash_handler.h"
+#include "gwp_asan/options.h"
+#include "gwp_asan/utilities.h"
+
+#include <assert.h>
+#include <stddef.h>
+
+using AllocationMetadata = gwp_asan::AllocationMetadata;
+using Error = gwp_asan::Error;
+
+namespace gwp_asan {
+namespace {
+// Forward declare the pointer to the singleton version of this class.
+// Instantiated during initialisation, this allows the signal handler
+// to find this class in order to deduce the root cause of failures. Must not be
+// referenced by users outside this translation unit, in order to avoid
+// init-order-fiasco.
+GuardedPoolAllocator *SingletonPtr = nullptr;
+
+size_t roundUpTo(size_t Size, size_t Boundary) {
+ return (Size + Boundary - 1) & ~(Boundary - 1);
+}
+
+uintptr_t getPageAddr(uintptr_t Ptr, uintptr_t PageSize) {
+ return Ptr & ~(PageSize - 1);
+}
+
+bool isPowerOfTwo(uintptr_t X) { return (X & (X - 1)) == 0; }
+} // anonymous namespace
+
+// Gets the singleton implementation of this class. Thread-compatible until
+// init() is called, thread-safe afterwards.
+GuardedPoolAllocator *GuardedPoolAllocator::getSingleton() {
+ return SingletonPtr;
+}
+
+void GuardedPoolAllocator::init(const options::Options &Opts) {
+ // Note: We return from the constructor here if GWP-ASan is not available.
+ // This will stop heap-allocation of class members, as well as mmap() of the
+ // guarded slots.
+ if (!Opts.Enabled || Opts.SampleRate == 0 ||
+ Opts.MaxSimultaneousAllocations == 0)
+ return;
+
+ Check(Opts.SampleRate >= 0, "GWP-ASan Error: SampleRate is < 0.");
+ Check(Opts.SampleRate < (1 << 30), "GWP-ASan Error: SampleRate is >= 2^30.");
+ Check(Opts.MaxSimultaneousAllocations >= 0,
+ "GWP-ASan Error: MaxSimultaneousAllocations is < 0.");
+
+ SingletonPtr = this;
+ Backtrace = Opts.Backtrace;
+
+ State.VersionMagic = {{AllocatorVersionMagic::kAllocatorVersionMagic[0],
+ AllocatorVersionMagic::kAllocatorVersionMagic[1],
+ AllocatorVersionMagic::kAllocatorVersionMagic[2],
+ AllocatorVersionMagic::kAllocatorVersionMagic[3]},
+ AllocatorVersionMagic::kAllocatorVersion,
+ 0};
+
+ State.MaxSimultaneousAllocations = Opts.MaxSimultaneousAllocations;
+
+ const size_t PageSize = getPlatformPageSize();
+ // getPageAddr() and roundUpTo() assume the page size to be a power of 2.
+ assert((PageSize & (PageSize - 1)) == 0);
+ State.PageSize = PageSize;
+
+ // Number of pages required =
+ // + MaxSimultaneousAllocations * maximumAllocationSize (N pages per slot)
+ // + MaxSimultaneousAllocations (one guard on the left side of each slot)
+ // + 1 (an extra guard page at the end of the pool, on the right side)
+ // + 1 (an extra page that's used for reporting internally-detected crashes,
+ // like double free and invalid free, to the signal handler; see
+ // raiseInternallyDetectedError() for more info)
+ size_t PoolBytesRequired =
+ PageSize * (2 + State.MaxSimultaneousAllocations) +
+ State.MaxSimultaneousAllocations * State.maximumAllocationSize();
+ assert(PoolBytesRequired % PageSize == 0);
+ void *GuardedPoolMemory = reserveGuardedPool(PoolBytesRequired);
+
+ size_t BytesRequired =
+ roundUpTo(State.MaxSimultaneousAllocations * sizeof(*Metadata), PageSize);
+ Metadata = reinterpret_cast<AllocationMetadata *>(
+ map(BytesRequired, kGwpAsanMetadataName));
+
+ // Allocate memory and set up the free pages queue.
+ BytesRequired = roundUpTo(
+ State.MaxSimultaneousAllocations * sizeof(*FreeSlots), PageSize);
+ FreeSlots =
+ reinterpret_cast<size_t *>(map(BytesRequired, kGwpAsanFreeSlotsName));
+
+ // Multiply the sample rate by 2 to give a good, fast approximation for (1 /
+ // SampleRate) chance of sampling.
+ if (Opts.SampleRate != 1)
+ AdjustedSampleRatePlusOne = static_cast<uint32_t>(Opts.SampleRate) * 2 + 1;
+ else
+ AdjustedSampleRatePlusOne = 2;
+
+ initPRNG();
+ getThreadLocals()->NextSampleCounter =
+ ((getRandomUnsigned32() % (AdjustedSampleRatePlusOne - 1)) + 1) &
+ ThreadLocalPackedVariables::NextSampleCounterMask;
+
+ State.GuardedPagePool = reinterpret_cast<uintptr_t>(GuardedPoolMemory);
+ State.GuardedPagePoolEnd =
+ reinterpret_cast<uintptr_t>(GuardedPoolMemory) + PoolBytesRequired;
+
+ if (Opts.InstallForkHandlers)
+ installAtFork();
+}
+
+void GuardedPoolAllocator::disable() {
+ PoolMutex.lock();
+ BacktraceMutex.lock();
+}
+
+void GuardedPoolAllocator::enable() {
+ PoolMutex.unlock();
+ BacktraceMutex.unlock();
+}
+
+void GuardedPoolAllocator::iterate(void *Base, size_t Size, iterate_callback Cb,
+ void *Arg) {
+ uintptr_t Start = reinterpret_cast<uintptr_t>(Base);
+ for (size_t i = 0; i < State.MaxSimultaneousAllocations; ++i) {
+ const AllocationMetadata &Meta = Metadata[i];
+ if (Meta.Addr && !Meta.IsDeallocated && Meta.Addr >= Start &&
+ Meta.Addr < Start + Size)
+ Cb(Meta.Addr, Meta.RequestedSize, Arg);
+ }
+}
+
+void GuardedPoolAllocator::uninitTestOnly() {
+ if (State.GuardedPagePool) {
+ unreserveGuardedPool();
+ State.GuardedPagePool = 0;
+ State.GuardedPagePoolEnd = 0;
+ }
+ if (Metadata) {
+ unmap(Metadata,
+ roundUpTo(State.MaxSimultaneousAllocations * sizeof(*Metadata),
+ State.PageSize));
+ Metadata = nullptr;
+ }
+ if (FreeSlots) {
+ unmap(FreeSlots,
+ roundUpTo(State.MaxSimultaneousAllocations * sizeof(*FreeSlots),
+ State.PageSize));
+ FreeSlots = nullptr;
+ }
+ *getThreadLocals() = ThreadLocalPackedVariables();
+}
+
+// Note, minimum backing allocation size in GWP-ASan is always one page, and
+// each slot could potentially be multiple pages (but always in
+// page-increments). Thus, for anything that requires less than page size
+// alignment, we don't need to allocate extra padding to ensure the alignment
+// can be met.
+size_t GuardedPoolAllocator::getRequiredBackingSize(size_t Size,
+ size_t Alignment,
+ size_t PageSize) {
+ assert(isPowerOfTwo(Alignment) && "Alignment must be a power of two!");
+ assert(Alignment != 0 && "Alignment should be non-zero");
+ assert(Size != 0 && "Size should be non-zero");
+
+ if (Alignment <= PageSize)
+ return Size;
+
+ return Size + Alignment - PageSize;
+}
+
+uintptr_t GuardedPoolAllocator::alignUp(uintptr_t Ptr, size_t Alignment) {
+ assert(isPowerOfTwo(Alignment) && "Alignment must be a power of two!");
+ assert(Alignment != 0 && "Alignment should be non-zero");
+ if ((Ptr & (Alignment - 1)) == 0)
+ return Ptr;
+
+ Ptr += Alignment - (Ptr & (Alignment - 1));
+ return Ptr;
+}
+
+uintptr_t GuardedPoolAllocator::alignDown(uintptr_t Ptr, size_t Alignment) {
+ assert(isPowerOfTwo(Alignment) && "Alignment must be a power of two!");
+ assert(Alignment != 0 && "Alignment should be non-zero");
+ if ((Ptr & (Alignment - 1)) == 0)
+ return Ptr;
+
+ Ptr -= Ptr & (Alignment - 1);
+ return Ptr;
+}
+
+void *GuardedPoolAllocator::allocate(size_t Size, size_t Alignment) {
+ // GuardedPagePoolEnd == 0 when GWP-ASan is disabled. If we are disabled, fall
+ // back to the supporting allocator.
+ if (State.GuardedPagePoolEnd == 0) {
+ getThreadLocals()->NextSampleCounter =
+ (AdjustedSampleRatePlusOne - 1) &
+ ThreadLocalPackedVariables::NextSampleCounterMask;
+ return nullptr;
+ }
+
+ if (Size == 0)
+ Size = 1;
+ if (Alignment == 0)
+ Alignment = alignof(max_align_t);
+
+ if (!isPowerOfTwo(Alignment) || Alignment > State.maximumAllocationSize() ||
+ Size > State.maximumAllocationSize())
+ return nullptr;
+
+ size_t BackingSize = getRequiredBackingSize(Size, Alignment, State.PageSize);
+ if (BackingSize > State.maximumAllocationSize())
+ return nullptr;
+
+ // Protect against recursivity.
+ if (getThreadLocals()->RecursiveGuard)
+ return nullptr;
+ ScopedRecursiveGuard SRG;
+
+ size_t Index;
+ {
+ ScopedLock L(PoolMutex);
+ Index = reserveSlot();
+ }
+
+ if (Index == kInvalidSlotID)
+ return nullptr;
+
+ uintptr_t SlotStart = State.slotToAddr(Index);
+ AllocationMetadata *Meta = addrToMetadata(SlotStart);
+ uintptr_t SlotEnd = State.slotToAddr(Index) + State.maximumAllocationSize();
+ uintptr_t UserPtr;
+ // Randomly choose whether to left-align or right-align the allocation, and
+ // then apply the necessary adjustments to get an aligned pointer.
+ if (getRandomUnsigned32() % 2 == 0)
+ UserPtr = alignUp(SlotStart, Alignment);
+ else
+ UserPtr = alignDown(SlotEnd - Size, Alignment);
+
+ assert(UserPtr >= SlotStart);
+ assert(UserPtr + Size <= SlotEnd);
+
+ // If a slot is multiple pages in size, and the allocation takes up a single
+ // page, we can improve overflow detection by leaving the unused pages as
+ // unmapped.
+ const size_t PageSize = State.PageSize;
+ allocateInGuardedPool(
+ reinterpret_cast<void *>(getPageAddr(UserPtr, PageSize)),
+ roundUpTo(Size, PageSize));
+
+ Meta->RecordAllocation(UserPtr, Size);
+ {
+ ScopedLock UL(BacktraceMutex);
+ Meta->AllocationTrace.RecordBacktrace(Backtrace);
+ }
+
+ return reinterpret_cast<void *>(UserPtr);
+}
+
+void GuardedPoolAllocator::raiseInternallyDetectedError(uintptr_t Address,
+ Error E) {
+ // Disable the allocator before setting the internal failure state. In
+ // non-recoverable mode, the allocator will be permanently disabled, and so
+ // things will be accessed without locks.
+ disable();
+
+ // Races between internally- and externally-raised faults can happen. Right
+ // now, in this thread we've locked the allocator in order to raise an
+ // internally-detected fault, and another thread could SIGSEGV to raise an
+ // externally-detected fault. What will happen is that the other thread will
+ // wait in the signal handler, as we hold the allocator's locks from the
+ // disable() above. We'll trigger the signal handler by touching the
+ // internal-signal-raising address below, and the signal handler from our
+ // thread will get to run first as we will continue to hold the allocator
+ // locks until the enable() at the end of this function. Be careful though, if
+ // this thread receives another SIGSEGV after the disable() above, but before
+ // touching the internal-signal-raising address below, then this thread will
+ // get an "externally-raised" SIGSEGV while *also* holding the allocator
+ // locks, which means this thread's signal handler will deadlock. This could
+ // be resolved with a re-entrant lock, but asking platforms to implement this
+ // seems unnecessary given the only way to get a SIGSEGV in this critical
+ // section is either a memory safety bug in the couple lines of code below (be
+ // careful!), or someone outside uses `kill(this_thread, SIGSEGV)`, which
+ // really shouldn't happen.
+
+ State.FailureType = E;
+ State.FailureAddress = Address;
+
+ // Raise a SEGV by touching a specific address that identifies to the crash
+ // handler that this is an internally-raised fault. Changing this address?
+ // Don't forget to update __gwp_asan_get_internal_crash_address.
+ volatile char *p =
+ reinterpret_cast<char *>(State.internallyDetectedErrorFaultAddress());
+ *p = 0;
+
+ // This should never be reached in non-recoverable mode. Ensure that the
+ // signal handler called handleRecoverablePostCrashReport(), which was
+ // responsible for re-setting these fields.
+ assert(State.FailureType == Error::UNKNOWN);
+ assert(State.FailureAddress == 0u);
+
+ // In recoverable mode, the signal handler (after dumping the crash) marked
+ // the page containing the InternalFaultSegvAddress as read/writeable, to
+ // allow the second touch to succeed after returning from the signal handler.
+ // Now, we need to mark the page as non-read/write-able again, so future
+ // internal faults can be raised.
+ deallocateInGuardedPool(
+ reinterpret_cast<void *>(getPageAddr(
+ State.internallyDetectedErrorFaultAddress(), State.PageSize)),
+ State.PageSize);
+
+ // And now we're done with patching ourselves back up, enable the allocator.
+ enable();
+}
+
+void GuardedPoolAllocator::deallocate(void *Ptr) {
+ assert(pointerIsMine(Ptr) && "Pointer is not mine!");
+ uintptr_t UPtr = reinterpret_cast<uintptr_t>(Ptr);
+ size_t Slot = State.getNearestSlot(UPtr);
+ uintptr_t SlotStart = State.slotToAddr(Slot);
+ AllocationMetadata *Meta = addrToMetadata(UPtr);
+
+ // If this allocation is responsible for crash, never recycle it. Turn the
+ // deallocate() call into a no-op.
+ if (Meta->HasCrashed)
+ return;
+
+ if (Meta->Addr != UPtr) {
+ raiseInternallyDetectedError(UPtr, Error::INVALID_FREE);
+ return;
+ }
+ if (Meta->IsDeallocated) {
+ raiseInternallyDetectedError(UPtr, Error::DOUBLE_FREE);
+ return;
+ }
+
+ // Intentionally scope the mutex here, so that other threads can access the
+ // pool during the expensive markInaccessible() call.
+ {
+ ScopedLock L(PoolMutex);
+
+ // Ensure that the deallocation is recorded before marking the page as
+ // inaccessible. Otherwise, a racy use-after-free will have inconsistent
+ // metadata.
+ Meta->RecordDeallocation();
+
+ // Ensure that the unwinder is not called if the recursive flag is set,
+ // otherwise non-reentrant unwinders may deadlock.
+ if (!getThreadLocals()->RecursiveGuard) {
+ ScopedRecursiveGuard SRG;
+ ScopedLock UL(BacktraceMutex);
+ Meta->DeallocationTrace.RecordBacktrace(Backtrace);
+ }
+ }
+
+ deallocateInGuardedPool(reinterpret_cast<void *>(SlotStart),
+ State.maximumAllocationSize());
+
+ // And finally, lock again to release the slot back into the pool.
+ ScopedLock L(PoolMutex);
+ freeSlot(Slot);
+}
+
+// Thread-compatible, protected by PoolMutex.
+static bool PreviousRecursiveGuard;
+
+void GuardedPoolAllocator::preCrashReport(void *Ptr) {
+ assert(pointerIsMine(Ptr) && "Pointer is not mine!");
+ uintptr_t InternalCrashAddr = __gwp_asan_get_internal_crash_address(
+ &State, reinterpret_cast<uintptr_t>(Ptr));
+ if (!InternalCrashAddr)
+ disable();
+
+ // If something in the signal handler calls malloc() while dumping the
+ // GWP-ASan report (e.g. backtrace_symbols()), make sure that GWP-ASan doesn't
+ // service that allocation. `PreviousRecursiveGuard` is protected by the
+ // allocator locks taken in disable(), either explicitly above for
+ // externally-raised errors, or implicitly in raiseInternallyDetectedError()
+ // for internally-detected errors.
+ PreviousRecursiveGuard = getThreadLocals()->RecursiveGuard;
+ getThreadLocals()->RecursiveGuard = true;
+}
+
+void GuardedPoolAllocator::postCrashReportRecoverableOnly(void *SignalPtr) {
+ uintptr_t SignalUPtr = reinterpret_cast<uintptr_t>(SignalPtr);
+ uintptr_t InternalCrashAddr =
+ __gwp_asan_get_internal_crash_address(&State, SignalUPtr);
+ uintptr_t ErrorUptr = InternalCrashAddr ?: SignalUPtr;
+
+ AllocationMetadata *Metadata = addrToMetadata(ErrorUptr);
+ Metadata->HasCrashed = true;
+
+ allocateInGuardedPool(
+ reinterpret_cast<void *>(getPageAddr(SignalUPtr, State.PageSize)),
+ State.PageSize);
+
+ // Clear the internal state in order to not confuse the crash handler if a
+ // use-after-free or buffer-overflow comes from a different allocation in the
+ // future.
+ if (InternalCrashAddr) {
+ State.FailureType = Error::UNKNOWN;
+ State.FailureAddress = 0;
+ }
+
+ size_t Slot = State.getNearestSlot(ErrorUptr);
+ // If the slot is available, remove it permanently.
+ for (size_t i = 0; i < FreeSlotsLength; ++i) {
+ if (FreeSlots[i] == Slot) {
+ FreeSlots[i] = FreeSlots[FreeSlotsLength - 1];
+ FreeSlotsLength -= 1;
+ break;
+ }
+ }
+
+ getThreadLocals()->RecursiveGuard = PreviousRecursiveGuard;
+ if (!InternalCrashAddr)
+ enable();
+}
+
+size_t GuardedPoolAllocator::getSize(const void *Ptr) {
+ assert(pointerIsMine(Ptr));
+ ScopedLock L(PoolMutex);
+ AllocationMetadata *Meta = addrToMetadata(reinterpret_cast<uintptr_t>(Ptr));
+ assert(Meta->Addr == reinterpret_cast<uintptr_t>(Ptr));
+ return Meta->RequestedSize;
+}
+
+AllocationMetadata *GuardedPoolAllocator::addrToMetadata(uintptr_t Ptr) const {
+ return &Metadata[State.getNearestSlot(Ptr)];
+}
+
+size_t GuardedPoolAllocator::reserveSlot() {
+ // Avoid potential reuse of a slot before we have made at least a single
+ // allocation in each slot. Helps with our use-after-free detection.
+ if (NumSampledAllocations < State.MaxSimultaneousAllocations)
+ return NumSampledAllocations++;
+
+ if (FreeSlotsLength == 0)
+ return kInvalidSlotID;
+
+ size_t ReservedIndex = getRandomUnsigned32() % FreeSlotsLength;
+ size_t SlotIndex = FreeSlots[ReservedIndex];
+ FreeSlots[ReservedIndex] = FreeSlots[--FreeSlotsLength];
+ return SlotIndex;
+}
+
+void GuardedPoolAllocator::freeSlot(size_t SlotIndex) {
+ assert(FreeSlotsLength < State.MaxSimultaneousAllocations);
+ FreeSlots[FreeSlotsLength++] = SlotIndex;
+}
+
+uint32_t GuardedPoolAllocator::getRandomUnsigned32() {
+ uint32_t RandomState = getThreadLocals()->RandomState;
+ RandomState ^= RandomState << 13;
+ RandomState ^= RandomState >> 17;
+ RandomState ^= RandomState << 5;
+ getThreadLocals()->RandomState = RandomState;
+ return RandomState;
+}
+} // namespace gwp_asan
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/guarded_pool_allocator.h b/contrib/libs/clang16-rt/lib/gwp_asan/guarded_pool_allocator.h
new file mode 100644
index 00000000000..de07b6798c1
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/guarded_pool_allocator.h
@@ -0,0 +1,250 @@
+//===-- guarded_pool_allocator.h --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_GUARDED_POOL_ALLOCATOR_H_
+#define GWP_ASAN_GUARDED_POOL_ALLOCATOR_H_
+
+#include "gwp_asan/common.h"
+#include "gwp_asan/definitions.h"
+#include "gwp_asan/mutex.h"
+#include "gwp_asan/options.h"
+#include "gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.h" // IWYU pragma: keep
+#include "gwp_asan/platform_specific/guarded_pool_allocator_posix.h" // IWYU pragma: keep
+#include "gwp_asan/platform_specific/guarded_pool_allocator_tls.h"
+
+#include <stddef.h>
+#include <stdint.h>
+// IWYU pragma: no_include <__stddef_max_align_t.h>
+
+namespace gwp_asan {
+// This class is the primary implementation of the allocator portion of GWP-
+// ASan. It is the sole owner of the pool of sequentially allocated guarded
+// slots. It should always be treated as a singleton.
+
+// Functions in the public interface of this class are thread-compatible until
+// init() is called, at which point they become thread-safe (unless specified
+// otherwise).
+class GuardedPoolAllocator {
+public:
+ // Name of the GWP-ASan mapping that for `Metadata`.
+ static constexpr const char *kGwpAsanMetadataName = "GWP-ASan Metadata";
+
+ // During program startup, we must ensure that memory allocations do not land
+ // in this allocation pool if the allocator decides to runtime-disable
+ // GWP-ASan. The constructor value-initialises the class such that if no
+ // further initialisation takes place, calls to shouldSample() and
+ // pointerIsMine() will return false.
+ constexpr GuardedPoolAllocator() {}
+ GuardedPoolAllocator(const GuardedPoolAllocator &) = delete;
+ GuardedPoolAllocator &operator=(const GuardedPoolAllocator &) = delete;
+
+ // Note: This class is expected to be a singleton for the lifetime of the
+ // program. If this object is initialised, it will leak the guarded page pool
+ // and metadata allocations during destruction. We can't clean up these areas
+ // as this may cause a use-after-free on shutdown.
+ ~GuardedPoolAllocator() = default;
+
+ // Initialise the rest of the members of this class. Create the allocation
+ // pool using the provided options. See options.inc for runtime configuration
+ // options.
+ void init(const options::Options &Opts);
+ void uninitTestOnly();
+
+ // Functions exported for libmemunreachable's use on Android. disable()
+ // installs a lock in the allocator that prevents any thread from being able
+ // to allocate memory, until enable() is called.
+ void disable();
+ void enable();
+
+ typedef void (*iterate_callback)(uintptr_t base, size_t size, void *arg);
+ // Execute the callback Cb for every allocation the lies in [Base, Base +
+ // Size). Must be called while the allocator is disabled. The callback can not
+ // allocate.
+ void iterate(void *Base, size_t Size, iterate_callback Cb, void *Arg);
+
+ // Return whether the allocation should be randomly chosen for sampling.
+ GWP_ASAN_ALWAYS_INLINE bool shouldSample() {
+ // NextSampleCounter == 0 means we "should regenerate the counter".
+ // == 1 means we "should sample this allocation".
+ // AdjustedSampleRatePlusOne is designed to intentionally underflow. This
+ // class must be valid when zero-initialised, and we wish to sample as
+ // infrequently as possible when this is the case, hence we underflow to
+ // UINT32_MAX.
+ if (GWP_ASAN_UNLIKELY(getThreadLocals()->NextSampleCounter == 0))
+ getThreadLocals()->NextSampleCounter =
+ ((getRandomUnsigned32() % (AdjustedSampleRatePlusOne - 1)) + 1) &
+ ThreadLocalPackedVariables::NextSampleCounterMask;
+
+ return GWP_ASAN_UNLIKELY(--getThreadLocals()->NextSampleCounter == 0);
+ }
+
+ // Returns whether the provided pointer is a current sampled allocation that
+ // is owned by this pool.
+ GWP_ASAN_ALWAYS_INLINE bool pointerIsMine(const void *Ptr) const {
+ return State.pointerIsMine(Ptr);
+ }
+
+ // Allocate memory in a guarded slot, with the specified `Alignment`. Returns
+ // nullptr if the pool is empty, if the alignnment is not a power of two, or
+ // if the size/alignment makes the allocation too large for this pool to
+ // handle. By default, uses strong alignment (i.e. `max_align_t`), see
+ // http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2293.htm for discussion of
+ // alignment issues in the standard.
+ void *allocate(size_t Size, size_t Alignment = alignof(max_align_t));
+
+ // Deallocate memory in a guarded slot. The provided pointer must have been
+ // allocated using this pool. This will set the guarded slot as inaccessible.
+ void deallocate(void *Ptr);
+
+ // Returns the size of the allocation at Ptr.
+ size_t getSize(const void *Ptr);
+
+ // Returns a pointer to the Metadata region, or nullptr if it doesn't exist.
+ const AllocationMetadata *getMetadataRegion() const { return Metadata; }
+
+ // Returns a pointer to the AllocatorState region.
+ const AllocatorState *getAllocatorState() const { return &State; }
+
+ // Functions that the signal handler is responsible for calling, while
+ // providing the SEGV pointer, prior to dumping the crash, and after dumping
+ // the crash (in recoverable mode only).
+ void preCrashReport(void *Ptr);
+ void postCrashReportRecoverableOnly(void *Ptr);
+
+ // Exposed as protected for testing.
+protected:
+ // Returns the actual allocation size required to service an allocation with
+ // the provided Size and Alignment.
+ static size_t getRequiredBackingSize(size_t Size, size_t Alignment,
+ size_t PageSize);
+
+ // Returns the provided pointer that meets the specified alignment, depending
+ // on whether it's left or right aligned.
+ static uintptr_t alignUp(uintptr_t Ptr, size_t Alignment);
+ static uintptr_t alignDown(uintptr_t Ptr, size_t Alignment);
+
+private:
+ // Name of actively-occupied slot mappings.
+ static constexpr const char *kGwpAsanAliveSlotName = "GWP-ASan Alive Slot";
+ // Name of the guard pages. This includes all slots that are not actively in
+ // use (i.e. were never used, or have been free()'d).)
+ static constexpr const char *kGwpAsanGuardPageName = "GWP-ASan Guard Page";
+ // Name of the mapping for `FreeSlots`.
+ static constexpr const char *kGwpAsanFreeSlotsName = "GWP-ASan Metadata";
+
+ static constexpr size_t kInvalidSlotID = SIZE_MAX;
+
+ // These functions anonymously map memory or change the permissions of mapped
+ // memory into this process in a platform-specific way. Pointer and size
+ // arguments are expected to be page-aligned. These functions will never
+ // return on error, instead electing to kill the calling process on failure.
+ // The pool memory is initially reserved and inaccessible, and RW mappings are
+ // subsequently created and destroyed via allocateInGuardedPool() and
+ // deallocateInGuardedPool(). Each mapping is named on platforms that support
+ // it, primarily Android. This name must be a statically allocated string, as
+ // the Android kernel uses the string pointer directly.
+ void *map(size_t Size, const char *Name) const;
+ void unmap(void *Ptr, size_t Size) const;
+
+ // The pool is managed separately, as some platforms (particularly Fuchsia)
+ // manage virtual memory regions as a chunk where individual pages can still
+ // have separate permissions. These platforms maintain metadata about the
+ // region in order to perform operations. The pool is unique as it's the only
+ // thing in GWP-ASan that treats pages in a single VM region on an individual
+ // basis for page protection.
+ // The pointer returned by reserveGuardedPool() is the reserved address range
+ // of (at least) Size bytes.
+ void *reserveGuardedPool(size_t Size);
+ // allocateInGuardedPool() Ptr and Size must be a subrange of the previously
+ // reserved pool range.
+ void allocateInGuardedPool(void *Ptr, size_t Size) const;
+ // deallocateInGuardedPool() Ptr and Size must be an exact pair previously
+ // passed to allocateInGuardedPool().
+ void deallocateInGuardedPool(void *Ptr, size_t Size) const;
+ void unreserveGuardedPool();
+
+ // Get the page size from the platform-specific implementation. Only needs to
+ // be called once, and the result should be cached in PageSize in this class.
+ static size_t getPlatformPageSize();
+
+ // Returns a pointer to the metadata for the owned pointer. If the pointer is
+ // not owned by this pool, the result is undefined.
+ AllocationMetadata *addrToMetadata(uintptr_t Ptr) const;
+
+ // Reserve a slot for a new guarded allocation. Returns kInvalidSlotID if no
+ // slot is available to be reserved.
+ size_t reserveSlot();
+
+ // Unreserve the guarded slot.
+ void freeSlot(size_t SlotIndex);
+
+ // Raise a SEGV and set the corresponding fields in the Allocator's State in
+ // order to tell the crash handler what happened. Used when errors are
+ // detected internally (Double Free, Invalid Free).
+ void raiseInternallyDetectedError(uintptr_t Address, Error E);
+
+ static GuardedPoolAllocator *getSingleton();
+
+ // Install a pthread_atfork handler.
+ void installAtFork();
+
+ gwp_asan::AllocatorState State;
+
+ // A mutex to protect the guarded slot and metadata pool for this class.
+ Mutex PoolMutex;
+ // Some unwinders can grab the libdl lock. In order to provide atfork
+ // protection, we need to ensure that we allow an unwinding thread to release
+ // the libdl lock before forking.
+ Mutex BacktraceMutex;
+ // Record the number allocations that we've sampled. We store this amount so
+ // that we don't randomly choose to recycle a slot that previously had an
+ // allocation before all the slots have been utilised.
+ size_t NumSampledAllocations = 0;
+ // Pointer to the allocation metadata (allocation/deallocation stack traces),
+ // if any.
+ AllocationMetadata *Metadata = nullptr;
+
+ // Pointer to an array of free slot indexes.
+ size_t *FreeSlots = nullptr;
+ // The current length of the list of free slots.
+ size_t FreeSlotsLength = 0;
+
+ // See options.{h, inc} for more information.
+ bool PerfectlyRightAlign = false;
+
+ // Backtrace function provided by the supporting allocator. See `options.h`
+ // for more information.
+ options::Backtrace_t Backtrace = nullptr;
+
+ // The adjusted sample rate for allocation sampling. Default *must* be
+ // nonzero, as dynamic initialisation may call malloc (e.g. from libstdc++)
+ // before GPA::init() is called. This would cause an error in shouldSample(),
+ // where we would calculate modulo zero. This value is set UINT32_MAX, as when
+ // GWP-ASan is disabled, we wish to never spend wasted cycles recalculating
+ // the sample rate.
+ uint32_t AdjustedSampleRatePlusOne = 0;
+
+ // Additional platform specific data structure for the guarded pool mapping.
+ PlatformSpecificMapData GuardedPagePoolPlatformData = {};
+
+ class ScopedRecursiveGuard {
+ public:
+ ScopedRecursiveGuard() { getThreadLocals()->RecursiveGuard = true; }
+ ~ScopedRecursiveGuard() { getThreadLocals()->RecursiveGuard = false; }
+ };
+
+ // Initialise the PRNG, platform-specific.
+ void initPRNG();
+
+ // xorshift (32-bit output), extremely fast PRNG that uses arithmetic
+ // operations only. Seeded using platform-specific mechanisms by initPRNG().
+ uint32_t getRandomUnsigned32();
+};
+} // namespace gwp_asan
+
+#endif // GWP_ASAN_GUARDED_POOL_ALLOCATOR_H_
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/mutex.h b/contrib/libs/clang16-rt/lib/gwp_asan/mutex.h
new file mode 100644
index 00000000000..34b91a2880d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/mutex.h
@@ -0,0 +1,42 @@
+//===-- mutex.h -------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_MUTEX_H_
+#define GWP_ASAN_MUTEX_H_
+
+#include "gwp_asan/platform_specific/mutex_fuchsia.h" // IWYU pragma: keep
+#include "gwp_asan/platform_specific/mutex_posix.h" // IWYU pragma: keep
+
+namespace gwp_asan {
+class Mutex final : PlatformMutex {
+public:
+ constexpr Mutex() = default;
+ ~Mutex() = default;
+ Mutex(const Mutex &) = delete;
+ Mutex &operator=(const Mutex &) = delete;
+ // Lock the mutex.
+ void lock();
+ // Nonblocking trylock of the mutex. Returns true if the lock was acquired.
+ bool tryLock();
+ // Unlock the mutex.
+ void unlock();
+};
+
+class ScopedLock {
+public:
+ explicit ScopedLock(Mutex &Mx) : Mu(Mx) { Mu.lock(); }
+ ~ScopedLock() { Mu.unlock(); }
+ ScopedLock(const ScopedLock &) = delete;
+ ScopedLock &operator=(const ScopedLock &) = delete;
+
+private:
+ Mutex &Mu;
+};
+} // namespace gwp_asan
+
+#endif // GWP_ASAN_MUTEX_H_
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/optional/backtrace.h b/contrib/libs/clang16-rt/lib/gwp_asan/optional/backtrace.h
new file mode 100644
index 00000000000..9bb12af206a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/optional/backtrace.h
@@ -0,0 +1,53 @@
+//===-- backtrace.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_OPTIONAL_BACKTRACE_H_
+#define GWP_ASAN_OPTIONAL_BACKTRACE_H_
+
+#include "gwp_asan/optional/printf.h"
+#include "gwp_asan/options.h"
+
+namespace gwp_asan {
+namespace backtrace {
+// ================================ Description ================================
+// This function shall take the backtrace provided in `TraceBuffer`, and print
+// it in a human-readable format using `Print`. Generally, this function shall
+// resolve raw pointers to section offsets and print them with the following
+// sanitizer-common format:
+// " #{frame_number} {pointer} in {function name} ({binary name}+{offset}"
+// e.g. " #5 0x420459 in _start (/tmp/uaf+0x420459)"
+// This format allows the backtrace to be symbolized offline successfully using
+// llvm-symbolizer.
+// =================================== Notes ===================================
+// This function may directly or indirectly call malloc(), as the
+// GuardedPoolAllocator contains a reentrancy barrier to prevent infinite
+// recursion. Any allocation made inside this function will be served by the
+// supporting allocator, and will not have GWP-ASan protections.
+typedef void (*PrintBacktrace_t)(uintptr_t *TraceBuffer, size_t TraceLength,
+ Printf_t Print);
+
+// Returns a function pointer to a backtrace function that's suitable for
+// unwinding through a signal handler. This is important primarily for frame-
+// pointer based unwinders, DWARF or other unwinders can simply provide the
+// normal backtrace function as the implementation here. On POSIX, SignalContext
+// should be the `ucontext_t` from the signal handler.
+typedef size_t (*SegvBacktrace_t)(uintptr_t *TraceBuffer, size_t Size,
+ void *SignalContext);
+
+// Returns platform-specific provided implementations of Backtrace_t for use
+// inside the GWP-ASan core allocator.
+options::Backtrace_t getBacktraceFunction();
+
+// Returns platform-specific provided implementations of PrintBacktrace_t and
+// SegvBacktrace_t for use in the optional SEGV handler.
+PrintBacktrace_t getPrintBacktraceFunction();
+SegvBacktrace_t getSegvBacktraceFunction();
+} // namespace backtrace
+} // namespace gwp_asan
+
+#endif // GWP_ASAN_OPTIONAL_BACKTRACE_H_
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp b/contrib/libs/clang16-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp
new file mode 100644
index 00000000000..ea8e72be287
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp
@@ -0,0 +1,67 @@
+//===-- backtrace_linux_libc.cpp --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <assert.h>
+#include <execinfo.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gwp_asan/definitions.h"
+#include "gwp_asan/optional/backtrace.h"
+#include "gwp_asan/optional/printf.h"
+#include "gwp_asan/options.h"
+
+namespace {
+size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) {
+ static_assert(sizeof(uintptr_t) == sizeof(void *), "uintptr_t is not void*");
+
+ return backtrace(reinterpret_cast<void **>(TraceBuffer), Size);
+}
+
+// We don't need any custom handling for the Segv backtrace - the libc unwinder
+// has no problems with unwinding through a signal handler. Force inlining here
+// to avoid the additional frame.
+GWP_ASAN_ALWAYS_INLINE size_t SegvBacktrace(uintptr_t *TraceBuffer, size_t Size,
+ void * /*Context*/) {
+ return Backtrace(TraceBuffer, Size);
+}
+
+static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
+ gwp_asan::Printf_t Printf) {
+ if (TraceLength == 0) {
+ Printf(" <not found (does your allocator support backtracing?)>\n\n");
+ return;
+ }
+
+ char **BacktraceSymbols =
+ backtrace_symbols(reinterpret_cast<void **>(Trace), TraceLength);
+
+ for (size_t i = 0; i < TraceLength; ++i) {
+ if (!BacktraceSymbols)
+ Printf(" #%zu %p\n", i, Trace[i]);
+ else
+ Printf(" #%zu %s\n", i, BacktraceSymbols[i]);
+ }
+
+ Printf("\n");
+ if (BacktraceSymbols)
+ free(BacktraceSymbols);
+}
+} // anonymous namespace
+
+namespace gwp_asan {
+namespace backtrace {
+
+options::Backtrace_t getBacktraceFunction() { return Backtrace; }
+PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; }
+SegvBacktrace_t getSegvBacktraceFunction() { return SegvBacktrace; }
+
+} // namespace backtrace
+} // namespace gwp_asan
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/optional/options_parser.cpp b/contrib/libs/clang16-rt/lib/gwp_asan/optional/options_parser.cpp
new file mode 100644
index 00000000000..60234124e8e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/optional/options_parser.cpp
@@ -0,0 +1,258 @@
+//===-- options_parser.cpp --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "gwp_asan/optional/options_parser.h"
+#include "gwp_asan/optional/printf.h"
+#include "gwp_asan/utilities.h"
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+namespace {
+enum class OptionType : uint8_t {
+ OT_bool,
+ OT_int,
+};
+
+#define InvokeIfNonNull(Printf, ...) \
+ do { \
+ if (Printf) \
+ Printf(__VA_ARGS__); \
+ } while (0);
+
+class OptionParser {
+public:
+ explicit OptionParser(gwp_asan::Printf_t PrintfForWarnings)
+ : Printf(PrintfForWarnings) {}
+ void registerOption(const char *Name, const char *Desc, OptionType Type,
+ void *Var);
+ void parseString(const char *S);
+ void printOptionDescriptions();
+
+private:
+ // Calculate at compile-time how many options are available.
+#define GWP_ASAN_OPTION(...) +1
+ static constexpr size_t MaxOptions = 0
+#include "gwp_asan/options.inc"
+ ;
+#undef GWP_ASAN_OPTION
+
+ struct Option {
+ const char *Name;
+ const char *Desc;
+ OptionType Type;
+ void *Var;
+ } Options[MaxOptions];
+
+ size_t NumberOfOptions = 0;
+ const char *Buffer = nullptr;
+ uintptr_t Pos = 0;
+ gwp_asan::Printf_t Printf = nullptr;
+
+ void skipWhitespace();
+ void parseOptions();
+ bool parseOption();
+ bool setOptionToValue(const char *Name, const char *Value);
+};
+
+void OptionParser::printOptionDescriptions() {
+ InvokeIfNonNull(Printf, "GWP-ASan: Available options:\n");
+ for (size_t I = 0; I < NumberOfOptions; ++I)
+ InvokeIfNonNull(Printf, "\t%s\n\t\t- %s\n", Options[I].Name,
+ Options[I].Desc);
+}
+
+bool isSeparator(char C) {
+ return C == ' ' || C == ',' || C == ':' || C == '\n' || C == '\t' ||
+ C == '\r';
+}
+
+bool isSeparatorOrNull(char C) { return !C || isSeparator(C); }
+
+void OptionParser::skipWhitespace() {
+ while (isSeparator(Buffer[Pos]))
+ ++Pos;
+}
+
+bool OptionParser::parseOption() {
+ const uintptr_t NameStart = Pos;
+ while (Buffer[Pos] != '=' && !isSeparatorOrNull(Buffer[Pos]))
+ ++Pos;
+
+ const char *Name = Buffer + NameStart;
+ if (Buffer[Pos] != '=') {
+ InvokeIfNonNull(Printf, "GWP-ASan: Expected '=' when parsing option '%s'.",
+ Name);
+ return false;
+ }
+ const uintptr_t ValueStart = ++Pos;
+ const char *Value;
+ if (Buffer[Pos] == '\'' || Buffer[Pos] == '"') {
+ const char Quote = Buffer[Pos++];
+ while (Buffer[Pos] != 0 && Buffer[Pos] != Quote)
+ ++Pos;
+ if (Buffer[Pos] == 0) {
+ InvokeIfNonNull(Printf, "GWP-ASan: Unterminated string in option '%s'.",
+ Name);
+ return false;
+ }
+ Value = Buffer + ValueStart + 1;
+ ++Pos; // consume the closing quote
+ } else {
+ while (!isSeparatorOrNull(Buffer[Pos]))
+ ++Pos;
+ Value = Buffer + ValueStart;
+ }
+
+ return setOptionToValue(Name, Value);
+}
+
+void OptionParser::parseOptions() {
+ while (true) {
+ skipWhitespace();
+ if (Buffer[Pos] == 0)
+ break;
+ if (!parseOption()) {
+ InvokeIfNonNull(Printf, "GWP-ASan: Options parsing failed.\n");
+ return;
+ }
+ }
+}
+
+void OptionParser::parseString(const char *S) {
+ if (!S)
+ return;
+ Buffer = S;
+ Pos = 0;
+ parseOptions();
+}
+
+bool parseBool(const char *Value, bool *b) {
+ if (strncmp(Value, "0", 1) == 0 || strncmp(Value, "no", 2) == 0 ||
+ strncmp(Value, "false", 5) == 0) {
+ *b = false;
+ return true;
+ }
+ if (strncmp(Value, "1", 1) == 0 || strncmp(Value, "yes", 3) == 0 ||
+ strncmp(Value, "true", 4) == 0) {
+ *b = true;
+ return true;
+ }
+ return false;
+}
+
+bool OptionParser::setOptionToValue(const char *Name, const char *Value) {
+ for (size_t I = 0; I < NumberOfOptions; ++I) {
+ const uintptr_t Len = strlen(Options[I].Name);
+ if (strncmp(Name, Options[I].Name, Len) != 0 || Name[Len] != '=')
+ continue;
+ bool Ok = false;
+ switch (Options[I].Type) {
+ case OptionType::OT_bool:
+ Ok = parseBool(Value, reinterpret_cast<bool *>(Options[I].Var));
+ if (!Ok)
+ InvokeIfNonNull(
+ Printf, "GWP-ASan: Invalid boolean value '%s' for option '%s'.\n",
+ Value, Options[I].Name);
+ break;
+ case OptionType::OT_int:
+ char *ValueEnd;
+ *reinterpret_cast<int *>(Options[I].Var) =
+ static_cast<int>(strtol(Value, &ValueEnd, 10));
+ Ok =
+ *ValueEnd == '"' || *ValueEnd == '\'' || isSeparatorOrNull(*ValueEnd);
+ if (!Ok)
+ InvokeIfNonNull(
+ Printf, "GWP-ASan: Invalid integer value '%s' for option '%s'.\n",
+ Value, Options[I].Name);
+ break;
+ }
+ return Ok;
+ }
+
+ InvokeIfNonNull(Printf, "GWP-ASan: Unknown option '%s'.", Name);
+ return true;
+}
+
+void OptionParser::registerOption(const char *Name, const char *Desc,
+ OptionType Type, void *Var) {
+ assert(NumberOfOptions < MaxOptions &&
+ "GWP-ASan Error: Ran out of space for options.\n");
+ Options[NumberOfOptions].Name = Name;
+ Options[NumberOfOptions].Desc = Desc;
+ Options[NumberOfOptions].Type = Type;
+ Options[NumberOfOptions].Var = Var;
+ ++NumberOfOptions;
+}
+
+void registerGwpAsanOptions(OptionParser *parser,
+ gwp_asan::options::Options *o) {
+#define GWP_ASAN_OPTION(Type, Name, DefaultValue, Description) \
+ parser->registerOption(#Name, Description, OptionType::OT_##Type, &o->Name);
+#include "gwp_asan/options.inc"
+#undef GWP_ASAN_OPTION
+}
+
+const char *getGwpAsanDefaultOptions() {
+ return (__gwp_asan_default_options) ? __gwp_asan_default_options() : "";
+}
+
+gwp_asan::options::Options *getOptionsInternal() {
+ static gwp_asan::options::Options GwpAsanOptions;
+ return &GwpAsanOptions;
+}
+} // anonymous namespace
+
+namespace gwp_asan {
+namespace options {
+
+void initOptions(const char *OptionsStr, Printf_t PrintfForWarnings) {
+ Options *o = getOptionsInternal();
+ o->setDefaults();
+
+ OptionParser Parser(PrintfForWarnings);
+ registerGwpAsanOptions(&Parser, o);
+
+ // Override from the weak function definition in this executable.
+ Parser.parseString(getGwpAsanDefaultOptions());
+
+ // Override from the provided options string.
+ Parser.parseString(OptionsStr);
+
+ if (o->help)
+ Parser.printOptionDescriptions();
+
+ if (!o->Enabled)
+ return;
+
+ if (o->MaxSimultaneousAllocations <= 0) {
+ InvokeIfNonNull(
+ PrintfForWarnings,
+ "GWP-ASan ERROR: MaxSimultaneousAllocations must be > 0 when GWP-ASan "
+ "is enabled.\n");
+ o->Enabled = false;
+ }
+ if (o->SampleRate <= 0) {
+ InvokeIfNonNull(
+ PrintfForWarnings,
+ "GWP-ASan ERROR: SampleRate must be > 0 when GWP-ASan is enabled.\n");
+ o->Enabled = false;
+ }
+}
+
+void initOptions(Printf_t PrintfForWarnings) {
+ initOptions(getenv("GWP_ASAN_OPTIONS"), PrintfForWarnings);
+}
+
+Options &getOptions() { return *getOptionsInternal(); }
+
+} // namespace options
+} // namespace gwp_asan
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/optional/options_parser.h b/contrib/libs/clang16-rt/lib/gwp_asan/optional/options_parser.h
new file mode 100644
index 00000000000..a5a062801f8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/optional/options_parser.h
@@ -0,0 +1,31 @@
+//===-- options_parser.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_OPTIONAL_OPTIONS_PARSER_H_
+#define GWP_ASAN_OPTIONAL_OPTIONS_PARSER_H_
+
+#include "gwp_asan/optional/printf.h"
+#include "gwp_asan/options.h"
+
+namespace gwp_asan {
+namespace options {
+// Parse the options from the GWP_ASAN_OPTIONS environment variable.
+void initOptions(Printf_t PrintfForWarnings = nullptr);
+// Parse the options from the provided string.
+void initOptions(const char *OptionsStr, Printf_t PrintfForWarnings = nullptr);
+// Returns the initialised options. Call initOptions() prior to calling this
+// function.
+Options &getOptions();
+} // namespace options
+} // namespace gwp_asan
+
+extern "C" {
+__attribute__((weak)) const char *__gwp_asan_default_options();
+}
+
+#endif // GWP_ASAN_OPTIONAL_OPTIONS_PARSER_H_
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/optional/printf.h b/contrib/libs/clang16-rt/lib/gwp_asan/optional/printf.h
new file mode 100644
index 00000000000..1004a2c2498
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/optional/printf.h
@@ -0,0 +1,33 @@
+//===-- printf.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_OPTIONAL_PRINTF_H_
+#define GWP_ASAN_OPTIONAL_PRINTF_H_
+
+namespace gwp_asan {
+
+// ================================ Requirements ===============================
+// This function is required to be provided by the supporting allocator iff the
+// allocator wants to use any of the optional components.
+// ================================ Description ================================
+// This function shall produce output according to a strict subset of the C
+// standard library's printf() family. This function must support printing the
+// following formats:
+// 1. integers: "%([0-9]*)?(z|ll)?{d,u,x,X}"
+// 2. pointers: "%p"
+// 3. strings: "%[-]([0-9]*)?(\\.\\*)?s"
+// 4. chars: "%c"
+// This function must be implemented in a signal-safe manner, and thus must not
+// malloc().
+// =================================== Notes ===================================
+// This function has a slightly different signature than the C standard
+// library's printf(). Notably, it returns 'void' rather than 'int'.
+typedef void (*Printf_t)(const char *Format, ...);
+
+} // namespace gwp_asan
+#endif // GWP_ASAN_OPTIONAL_PRINTF_H_
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/optional/segv_handler.h b/contrib/libs/clang16-rt/lib/gwp_asan/optional/segv_handler.h
new file mode 100644
index 00000000000..72105ded7d5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/optional/segv_handler.h
@@ -0,0 +1,34 @@
+//===-- segv_handler.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_OPTIONAL_SEGV_HANDLER_H_
+#define GWP_ASAN_OPTIONAL_SEGV_HANDLER_H_
+
+#include "gwp_asan/guarded_pool_allocator.h"
+#include "gwp_asan/optional/backtrace.h"
+#include "gwp_asan/optional/printf.h"
+
+namespace gwp_asan {
+namespace segv_handler {
+// Install the SIGSEGV crash handler for printing use-after-free and heap-
+// buffer-{under|over}flow exceptions if the user asked for it. This is platform
+// specific as even though POSIX and Windows both support registering handlers
+// through signal(), we have to use platform-specific signal handlers to obtain
+// the address that caused the SIGSEGV exception. GPA->init() must be called
+// before this function.
+void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf,
+ gwp_asan::backtrace::PrintBacktrace_t PrintBacktrace,
+ gwp_asan::backtrace::SegvBacktrace_t SegvBacktrace,
+ bool Recoverable = false);
+
+// Uninistall the signal handlers, test-only.
+void uninstallSignalHandlers();
+} // namespace segv_handler
+} // namespace gwp_asan
+
+#endif // GWP_ASAN_OPTIONAL_SEGV_HANDLER_H_
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/optional/segv_handler_posix.cpp b/contrib/libs/clang16-rt/lib/gwp_asan/optional/segv_handler_posix.cpp
new file mode 100644
index 00000000000..e012963bffd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/optional/segv_handler_posix.cpp
@@ -0,0 +1,259 @@
+//===-- segv_handler_posix.cpp ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "gwp_asan/common.h"
+#include "gwp_asan/crash_handler.h"
+#include "gwp_asan/guarded_pool_allocator.h"
+#include "gwp_asan/optional/segv_handler.h"
+#include "gwp_asan/options.h"
+
+// RHEL creates the PRIu64 format macro (for printing uint64_t's) only when this
+// macro is defined before including <inttypes.h>.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS 1
+#endif
+
+#include <assert.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <stdio.h>
+
+using gwp_asan::AllocationMetadata;
+using gwp_asan::Error;
+using gwp_asan::GuardedPoolAllocator;
+using gwp_asan::Printf_t;
+using gwp_asan::backtrace::PrintBacktrace_t;
+using gwp_asan::backtrace::SegvBacktrace_t;
+
+namespace {
+
+struct ScopedEndOfReportDecorator {
+ ScopedEndOfReportDecorator(gwp_asan::Printf_t Printf) : Printf(Printf) {}
+ ~ScopedEndOfReportDecorator() { Printf("*** End GWP-ASan report ***\n"); }
+ gwp_asan::Printf_t Printf;
+};
+
+// Prints the provided error and metadata information.
+void printHeader(Error E, uintptr_t AccessPtr,
+ const gwp_asan::AllocationMetadata *Metadata,
+ Printf_t Printf) {
+ // Print using intermediate strings. Platforms like Android don't like when
+ // you print multiple times to the same line, as there may be a newline
+ // appended to a log file automatically per Printf() call.
+ constexpr size_t kDescriptionBufferLen = 128;
+ char DescriptionBuffer[kDescriptionBufferLen] = "";
+
+ bool AccessWasInBounds = false;
+ if (E != Error::UNKNOWN && Metadata != nullptr) {
+ uintptr_t Address = __gwp_asan_get_allocation_address(Metadata);
+ size_t Size = __gwp_asan_get_allocation_size(Metadata);
+ if (AccessPtr < Address) {
+ snprintf(DescriptionBuffer, kDescriptionBufferLen,
+ "(%zu byte%s to the left of a %zu-byte allocation at 0x%zx) ",
+ Address - AccessPtr, (Address - AccessPtr == 1) ? "" : "s", Size,
+ Address);
+ } else if (AccessPtr > Address) {
+ snprintf(DescriptionBuffer, kDescriptionBufferLen,
+ "(%zu byte%s to the right of a %zu-byte allocation at 0x%zx) ",
+ AccessPtr - Address, (AccessPtr - Address == 1) ? "" : "s", Size,
+ Address);
+ } else if (E == Error::DOUBLE_FREE) {
+ snprintf(DescriptionBuffer, kDescriptionBufferLen,
+ "(a %zu-byte allocation) ", Size);
+ } else {
+ AccessWasInBounds = true;
+ snprintf(DescriptionBuffer, kDescriptionBufferLen,
+ "(%zu byte%s into a %zu-byte allocation at 0x%zx) ",
+ AccessPtr - Address, (AccessPtr - Address == 1) ? "" : "s", Size,
+ Address);
+ }
+ }
+
+ // Possible number of digits of a 64-bit number: ceil(log10(2^64)) == 20. Add
+ // a null terminator, and round to the nearest 8-byte boundary.
+ uint64_t ThreadID = gwp_asan::getThreadID();
+ constexpr size_t kThreadBufferLen = 24;
+ char ThreadBuffer[kThreadBufferLen];
+ if (ThreadID == gwp_asan::kInvalidThreadID)
+ snprintf(ThreadBuffer, kThreadBufferLen, "<unknown>");
+ else
+ snprintf(ThreadBuffer, kThreadBufferLen, "%" PRIu64, ThreadID);
+
+ const char *OutOfBoundsAndUseAfterFreeWarning = "";
+ if (E == Error::USE_AFTER_FREE && !AccessWasInBounds) {
+ OutOfBoundsAndUseAfterFreeWarning =
+ " (warning: buffer overflow/underflow detected on a free()'d "
+ "allocation. This either means you have a buffer-overflow and a "
+ "use-after-free at the same time, or you have a long-lived "
+ "use-after-free bug where the allocation/deallocation metadata below "
+ "has already been overwritten and is likely bogus)";
+ }
+
+ Printf("%s%s at 0x%zx %sby thread %s here:\n", gwp_asan::ErrorToString(E),
+ OutOfBoundsAndUseAfterFreeWarning, AccessPtr, DescriptionBuffer,
+ ThreadBuffer);
+}
+
+void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
+ const gwp_asan::AllocationMetadata *Metadata,
+ SegvBacktrace_t SegvBacktrace, Printf_t Printf,
+ PrintBacktrace_t PrintBacktrace, void *Context) {
+ assert(State && "dumpReport missing Allocator State.");
+ assert(Metadata && "dumpReport missing Metadata.");
+ assert(Printf && "dumpReport missing Printf.");
+ assert(__gwp_asan_error_is_mine(State, ErrorPtr) &&
+ "dumpReport() called on a non-GWP-ASan error.");
+
+ uintptr_t InternalErrorPtr =
+ __gwp_asan_get_internal_crash_address(State, ErrorPtr);
+ if (InternalErrorPtr)
+ ErrorPtr = InternalErrorPtr;
+
+ const gwp_asan::AllocationMetadata *AllocMeta =
+ __gwp_asan_get_metadata(State, Metadata, ErrorPtr);
+
+ // It's unusual for a signal handler to be invoked multiple times for the same
+ // allocation, but it's possible in various scenarios, like:
+ // 1. A double-free or invalid-free was invoked in one thread at the same
+ // time as a buffer-overflow or use-after-free in another thread, or
+ // 2. Two threads do a use-after-free or buffer-overflow at the same time.
+ // In these instances, we've already dumped a report for this allocation, so
+ // skip dumping this issue as well.
+ if (AllocMeta->HasCrashed)
+ return;
+
+ Printf("*** GWP-ASan detected a memory error ***\n");
+ ScopedEndOfReportDecorator Decorator(Printf);
+
+ Error E = __gwp_asan_diagnose_error(State, Metadata, ErrorPtr);
+ if (E == Error::UNKNOWN) {
+ Printf("GWP-ASan cannot provide any more information about this error. "
+ "This may occur due to a wild memory access into the GWP-ASan pool, "
+ "or an overflow/underflow that is > 512B in length.\n");
+ return;
+ }
+
+ // Print the error header.
+ printHeader(E, ErrorPtr, AllocMeta, Printf);
+
+ // Print the fault backtrace.
+ static constexpr unsigned kMaximumStackFramesForCrashTrace = 512;
+ uintptr_t Trace[kMaximumStackFramesForCrashTrace];
+ size_t TraceLength =
+ SegvBacktrace(Trace, kMaximumStackFramesForCrashTrace, Context);
+
+ PrintBacktrace(Trace, TraceLength, Printf);
+
+ if (AllocMeta == nullptr)
+ return;
+
+ // Maybe print the deallocation trace.
+ if (__gwp_asan_is_deallocated(AllocMeta)) {
+ uint64_t ThreadID = __gwp_asan_get_deallocation_thread_id(AllocMeta);
+ if (ThreadID == gwp_asan::kInvalidThreadID)
+ Printf("0x%zx was deallocated by thread <unknown> here:\n", ErrorPtr);
+ else
+ Printf("0x%zx was deallocated by thread %zu here:\n", ErrorPtr, ThreadID);
+ TraceLength = __gwp_asan_get_deallocation_trace(
+ AllocMeta, Trace, kMaximumStackFramesForCrashTrace);
+ PrintBacktrace(Trace, TraceLength, Printf);
+ }
+
+ // Print the allocation trace.
+ uint64_t ThreadID = __gwp_asan_get_allocation_thread_id(AllocMeta);
+ if (ThreadID == gwp_asan::kInvalidThreadID)
+ Printf("0x%zx was allocated by thread <unknown> here:\n", ErrorPtr);
+ else
+ Printf("0x%zx was allocated by thread %zu here:\n", ErrorPtr, ThreadID);
+ TraceLength = __gwp_asan_get_allocation_trace(
+ AllocMeta, Trace, kMaximumStackFramesForCrashTrace);
+ PrintBacktrace(Trace, TraceLength, Printf);
+}
+
+struct sigaction PreviousHandler;
+bool SignalHandlerInstalled;
+bool RecoverableSignal;
+gwp_asan::GuardedPoolAllocator *GPAForSignalHandler;
+Printf_t PrintfForSignalHandler;
+PrintBacktrace_t PrintBacktraceForSignalHandler;
+SegvBacktrace_t BacktraceForSignalHandler;
+
+static void sigSegvHandler(int sig, siginfo_t *info, void *ucontext) {
+ const gwp_asan::AllocatorState *State =
+ GPAForSignalHandler->getAllocatorState();
+ void *FaultAddr = info->si_addr;
+ uintptr_t FaultAddrUPtr = reinterpret_cast<uintptr_t>(FaultAddr);
+
+ if (__gwp_asan_error_is_mine(State, FaultAddrUPtr)) {
+ GPAForSignalHandler->preCrashReport(FaultAddr);
+
+ dumpReport(FaultAddrUPtr, State, GPAForSignalHandler->getMetadataRegion(),
+ BacktraceForSignalHandler, PrintfForSignalHandler,
+ PrintBacktraceForSignalHandler, ucontext);
+
+ if (RecoverableSignal) {
+ GPAForSignalHandler->postCrashReportRecoverableOnly(FaultAddr);
+ return;
+ }
+ }
+
+ // Process any previous handlers as long as the crash wasn't a GWP-ASan crash
+ // in recoverable mode.
+ if (PreviousHandler.sa_flags & SA_SIGINFO) {
+ PreviousHandler.sa_sigaction(sig, info, ucontext);
+ } else if (PreviousHandler.sa_handler == SIG_DFL) {
+ // If the previous handler was the default handler, cause a core dump.
+ signal(SIGSEGV, SIG_DFL);
+ raise(SIGSEGV);
+ } else if (PreviousHandler.sa_handler == SIG_IGN) {
+ // If the previous segv handler was SIGIGN, crash iff we were responsible
+ // for the crash.
+ if (__gwp_asan_error_is_mine(GPAForSignalHandler->getAllocatorState(),
+ reinterpret_cast<uintptr_t>(info->si_addr))) {
+ signal(SIGSEGV, SIG_DFL);
+ raise(SIGSEGV);
+ }
+ } else {
+ PreviousHandler.sa_handler(sig);
+ }
+}
+} // anonymous namespace
+
+namespace gwp_asan {
+namespace segv_handler {
+
+void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf,
+ PrintBacktrace_t PrintBacktrace,
+ SegvBacktrace_t SegvBacktrace, bool Recoverable) {
+ assert(GPA && "GPA wasn't provided to installSignalHandlers.");
+ assert(Printf && "Printf wasn't provided to installSignalHandlers.");
+ assert(PrintBacktrace &&
+ "PrintBacktrace wasn't provided to installSignalHandlers.");
+ assert(SegvBacktrace &&
+ "SegvBacktrace wasn't provided to installSignalHandlers.");
+ GPAForSignalHandler = GPA;
+ PrintfForSignalHandler = Printf;
+ PrintBacktraceForSignalHandler = PrintBacktrace;
+ BacktraceForSignalHandler = SegvBacktrace;
+ RecoverableSignal = Recoverable;
+
+ struct sigaction Action = {};
+ Action.sa_sigaction = sigSegvHandler;
+ Action.sa_flags = SA_SIGINFO;
+ sigaction(SIGSEGV, &Action, &PreviousHandler);
+ SignalHandlerInstalled = true;
+}
+
+void uninstallSignalHandlers() {
+ if (SignalHandlerInstalled) {
+ sigaction(SIGSEGV, &PreviousHandler, nullptr);
+ SignalHandlerInstalled = false;
+ }
+}
+} // namespace segv_handler
+} // namespace gwp_asan
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/options.h b/contrib/libs/clang16-rt/lib/gwp_asan/options.h
new file mode 100644
index 00000000000..6fb43108b5d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/options.h
@@ -0,0 +1,57 @@
+//===-- options.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_OPTIONS_H_
+#define GWP_ASAN_OPTIONS_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace gwp_asan {
+namespace options {
+// ================================ Requirements ===============================
+// This function is required to be either implemented by the supporting
+// allocator, or one of the two provided implementations may be used
+// (RTGwpAsanBacktraceLibc or RTGwpAsanBacktraceSanitizerCommon).
+// ================================ Description ================================
+// This function shall collect the backtrace for the calling thread and place
+// the result in `TraceBuffer`. This function should elide itself and all frames
+// below itself from `TraceBuffer`, i.e. the caller's frame should be in
+// TraceBuffer[0], and subsequent frames 1..n into TraceBuffer[1..n], where a
+// maximum of `Size` frames are stored. Returns the number of frames stored into
+// `TraceBuffer`, and zero on failure. If the return value of this function is
+// equal to `Size`, it may indicate that the backtrace is truncated.
+// =================================== Notes ===================================
+// This function may directly or indirectly call malloc(), as the
+// GuardedPoolAllocator contains a reentrancy barrier to prevent infinite
+// recursion. Any allocation made inside this function will be served by the
+// supporting allocator, and will not have GWP-ASan protections.
+typedef size_t (*Backtrace_t)(uintptr_t *TraceBuffer, size_t Size);
+
+struct Options {
+ Backtrace_t Backtrace = nullptr;
+
+ // Read the options from the included definitions file.
+#define GWP_ASAN_OPTION(Type, Name, DefaultValue, Description) \
+ Type Name = DefaultValue;
+#include "gwp_asan/options.inc"
+#undef GWP_ASAN_OPTION
+
+ void setDefaults() {
+#define GWP_ASAN_OPTION(Type, Name, DefaultValue, Description) \
+ Name = DefaultValue;
+#include "gwp_asan/options.inc"
+#undef GWP_ASAN_OPTION
+
+ Backtrace = nullptr;
+ }
+};
+} // namespace options
+} // namespace gwp_asan
+
+#endif // GWP_ASAN_OPTIONS_H_
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/options.inc b/contrib/libs/clang16-rt/lib/gwp_asan/options.inc
new file mode 100644
index 00000000000..3a593216e8d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/options.inc
@@ -0,0 +1,79 @@
+//===-- options.inc ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_OPTION
+#error "Define GWP_ASAN_OPTION prior to including this file!"
+#endif
+
+#ifndef GWP_ASAN_DEFAULT_ENABLED
+#define GWP_ASAN_DEFAULT_ENABLED true
+#endif
+
+#ifndef GWP_ASAN_STRINGIFY
+#define GWP_ASAN_STRINGIFY(S) GWP_ASAN_STRINGIFY_(S)
+#define GWP_ASAN_STRINGIFY_(S) #S
+#endif
+
+GWP_ASAN_OPTION(bool, Enabled, GWP_ASAN_DEFAULT_ENABLED,
+ "Is GWP-ASan enabled? Defaults to " GWP_ASAN_STRINGIFY(
+ GWP_ASAN_DEFAULT_ENABLED) ".")
+
+GWP_ASAN_OPTION(int, MaxSimultaneousAllocations, 16,
+ "Number of simultaneously-guarded allocations available in the "
+ "pool. Defaults to 16.")
+
+GWP_ASAN_OPTION(int, SampleRate, 5000,
+ "The probability (1 / SampleRate) that an allocation is "
+ "selected for GWP-ASan sampling. Default is 5000. Sample rates "
+ "up to (2^30 - 1) are supported.")
+
+// Developer note - This option is not actually processed by GWP-ASan itself. It
+// is included here so that a user can specify whether they want signal handlers
+// or not. The supporting allocator should inspect this value to see whether
+// signal handlers need to be installed, and then use
+// crash_handler::installSignalHandlers() in order to install the handlers. Note
+// that in order to support signal handlers, you will need to link against the
+// optional crash_handler component.
+GWP_ASAN_OPTION(
+ bool, InstallSignalHandlers, true,
+ "Install GWP-ASan signal handlers for SIGSEGV during dynamic loading. This "
+ "allows better error reports by providing stack traces for allocation and "
+ "deallocation when reporting a memory error. GWP-ASan's signal handler "
+ "will forward the signal to any previously-installed handler, and user "
+ "programs that install further signal handlers should make sure they do "
+ "the same. Note, if the previously installed SIGSEGV handler is SIG_IGN, "
+ "we terminate the process after dumping the error report.")
+
+GWP_ASAN_OPTION(
+ bool, Recoverable, false,
+ "Install GWP-ASan's signal handler in recoverable mode. This means that "
+ "upon GWP-ASan detecting an error, it'll print the error report, but *not* "
+ "crash. Only one crash per sampled allocation will ever be recorded, and "
+ "if a sampled allocation does actually cause a crash, it'll permanently "
+ "occupy a slot in the pool. The recoverable mode also means that "
+ "previously-installed signal handlers will only be triggered for "
+ "non-GWP-ASan errors, as all GWP-ASan errors won't be forwarded.")
+
+GWP_ASAN_OPTION(bool, InstallForkHandlers, true,
+ "Install GWP-ASan atfork handlers to acquire internal locks "
+ "before fork and release them after.")
+
+GWP_ASAN_OPTION(bool, help, false, "Print a summary of the available options.")
+
+// =============================================================================
+// ==== WARNING
+// =============================================================================
+// If you are adding flags to GWP-ASan, please note that GWP-ASan flag strings
+// may be parsed by trusted system components (on Android, GWP-ASan flag strings
+// are parsed by libc during the dynamic loader). This means that GWP-ASan
+// should never feature flags like log paths on disk, because this can lead to
+// arbitrary file write and thus privilege escalation. For an example, see the
+// setuid ASan log_path exploits: https://www.exploit-db.com/exploits/46241.
+//
+// Please place all new flags above this warning, so that the warning always
+// stays at the bottom.
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/common_posix.cpp b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/common_posix.cpp
new file mode 100644
index 00000000000..0637fc2a424
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/common_posix.cpp
@@ -0,0 +1,26 @@
+//===-- common_posix.cpp ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "gwp_asan/common.h"
+
+#include <stdint.h>
+#include <sys/syscall.h> // IWYU pragma: keep
+// IWYU pragma: no_include <syscall.h>
+#include <unistd.h>
+
+namespace gwp_asan {
+
+uint64_t getThreadID() {
+#ifdef SYS_gettid
+ return syscall(SYS_gettid);
+#else
+ return kInvalidThreadID;
+#endif
+}
+
+} // namespace gwp_asan
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.h b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.h
new file mode 100644
index 00000000000..0295f6f7134
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.h
@@ -0,0 +1,22 @@
+//===-- guarded_pool_allocator_fuchsia.h ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__Fuchsia__)
+#ifndef GWP_ASAN_GUARDED_POOL_ALLOCATOR_FUCHSIA_H_
+#define GWP_ASAN_GUARDED_POOL_ALLOCATOR_FUCHSIA_H_
+
+#error #include <zircon/types.h>
+
+namespace gwp_asan {
+struct PlatformSpecificMapData {
+ zx_handle_t Vmar;
+};
+} // namespace gwp_asan
+
+#endif // GWP_ASAN_GUARDED_POOL_ALLOCATOR_FUCHSIA_H_
+#endif // defined(__Fuchsia__)
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp
new file mode 100644
index 00000000000..c036ebe3efc
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp
@@ -0,0 +1,115 @@
+//===-- guarded_pool_allocator_posix.cpp ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "gwp_asan/common.h"
+#include "gwp_asan/guarded_pool_allocator.h"
+#include "gwp_asan/platform_specific/guarded_pool_allocator_tls.h"
+#include "gwp_asan/utilities.h"
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <time.h>
+#include <unistd.h>
+
+#ifdef ANDROID
+#include <sys/prctl.h>
+#define PR_SET_VMA 0x53564d41
+#define PR_SET_VMA_ANON_NAME 0
+#endif // ANDROID
+
+namespace {
+void MaybeSetMappingName(void *Mapping, size_t Size, const char *Name) {
+#ifdef ANDROID
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, Mapping, Size, Name);
+#endif // ANDROID
+ // Anonymous mapping names are only supported on Android.
+ return;
+}
+} // anonymous namespace
+
+namespace gwp_asan {
+
+void GuardedPoolAllocator::initPRNG() {
+ getThreadLocals()->RandomState =
+ static_cast<uint32_t>(time(nullptr) + getThreadID());
+}
+
+void *GuardedPoolAllocator::map(size_t Size, const char *Name) const {
+ assert((Size % State.PageSize) == 0);
+ void *Ptr = mmap(nullptr, Size, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ Check(Ptr != MAP_FAILED, "Failed to map guarded pool allocator memory");
+ MaybeSetMappingName(Ptr, Size, Name);
+ return Ptr;
+}
+
+void GuardedPoolAllocator::unmap(void *Ptr, size_t Size) const {
+ assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0);
+ assert((Size % State.PageSize) == 0);
+ Check(munmap(Ptr, Size) == 0,
+ "Failed to unmap guarded pool allocator memory.");
+}
+
+void *GuardedPoolAllocator::reserveGuardedPool(size_t Size) {
+ assert((Size % State.PageSize) == 0);
+ void *Ptr =
+ mmap(nullptr, Size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ Check(Ptr != MAP_FAILED, "Failed to reserve guarded pool allocator memory");
+ MaybeSetMappingName(Ptr, Size, kGwpAsanGuardPageName);
+ return Ptr;
+}
+
+void GuardedPoolAllocator::unreserveGuardedPool() {
+ unmap(reinterpret_cast<void *>(State.GuardedPagePool),
+ State.GuardedPagePoolEnd - State.GuardedPagePool);
+}
+
+void GuardedPoolAllocator::allocateInGuardedPool(void *Ptr, size_t Size) const {
+ assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0);
+ assert((Size % State.PageSize) == 0);
+ Check(mprotect(Ptr, Size, PROT_READ | PROT_WRITE) == 0,
+ "Failed to allocate in guarded pool allocator memory");
+ MaybeSetMappingName(Ptr, Size, kGwpAsanAliveSlotName);
+}
+
+void GuardedPoolAllocator::deallocateInGuardedPool(void *Ptr,
+ size_t Size) const {
+ assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0);
+ assert((Size % State.PageSize) == 0);
+ // mmap() a PROT_NONE page over the address to release it to the system, if
+ // we used mprotect() here the system would count pages in the quarantine
+ // against the RSS.
+ Check(mmap(Ptr, Size, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1,
+ 0) != MAP_FAILED,
+ "Failed to deallocate in guarded pool allocator memory");
+ MaybeSetMappingName(Ptr, Size, kGwpAsanGuardPageName);
+}
+
+size_t GuardedPoolAllocator::getPlatformPageSize() {
+ return sysconf(_SC_PAGESIZE);
+}
+
+void GuardedPoolAllocator::installAtFork() {
+ static bool AtForkInstalled = false;
+ if (AtForkInstalled)
+ return;
+ AtForkInstalled = true;
+ auto Disable = []() {
+ if (auto *S = getSingleton())
+ S->disable();
+ };
+ auto Enable = []() {
+ if (auto *S = getSingleton())
+ S->enable();
+ };
+ pthread_atfork(Disable, Enable, Enable);
+}
+} // namespace gwp_asan
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.h b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.h
new file mode 100644
index 00000000000..7f4ba0d8ccd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.h
@@ -0,0 +1,18 @@
+//===-- guarded_pool_allocator_posix.h --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__unix__)
+#ifndef GWP_ASAN_GUARDED_POOL_ALLOCATOR_POSIX_H_
+#define GWP_ASAN_GUARDED_POOL_ALLOCATOR_POSIX_H_
+
+namespace gwp_asan {
+struct PlatformSpecificMapData {};
+} // namespace gwp_asan
+
+#endif // GWP_ASAN_GUARDED_POOL_ALLOCATOR_POSIX_H_
+#endif // defined(__unix__)
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_tls.h b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_tls.h
new file mode 100644
index 00000000000..7421ba16fbd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_tls.h
@@ -0,0 +1,55 @@
+//===-- guarded_pool_allocator_tls.h ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_GUARDED_POOL_ALLOCATOR_TLS_H_
+#define GWP_ASAN_GUARDED_POOL_ALLOCATOR_TLS_H_
+
+#include "gwp_asan/definitions.h"
+
+#include <stdint.h>
+
+namespace gwp_asan {
+// Pack the thread local variables into a struct to ensure that they're in
+// the same cache line for performance reasons. These are the most touched
+// variables in GWP-ASan.
+struct ThreadLocalPackedVariables {
+ constexpr ThreadLocalPackedVariables()
+ : RandomState(0xacd979ce), NextSampleCounter(0), RecursiveGuard(false) {}
+ // Initialised to a magic constant so that an uninitialised GWP-ASan won't
+ // regenerate its sample counter for as long as possible. The xorshift32()
+ // algorithm used below results in getRandomUnsigned32(0xacd979ce) ==
+ // 0xfffffffe.
+ uint32_t RandomState;
+ // Thread-local decrementing counter that indicates that a given allocation
+ // should be sampled when it reaches zero.
+ uint32_t NextSampleCounter : 31;
+ // The mask is needed to silence conversion errors.
+ static const uint32_t NextSampleCounterMask = (1U << 31) - 1;
+ // Guard against recursivity. Unwinders often contain complex behaviour that
+ // may not be safe for the allocator (i.e. the unwinder calls dlopen(),
+ // which calls malloc()). When recursive behaviour is detected, we will
+ // automatically fall back to the supporting allocator to supply the
+ // allocation.
+ bool RecursiveGuard : 1;
+};
+static_assert(sizeof(ThreadLocalPackedVariables) == sizeof(uint64_t),
+ "thread local data does not fit in a uint64_t");
+} // namespace gwp_asan
+
+#ifdef GWP_ASAN_PLATFORM_TLS_HEADER
+#error #include GWP_ASAN_PLATFORM_TLS_HEADER
+#else
+namespace gwp_asan {
+inline ThreadLocalPackedVariables *getThreadLocals() {
+ alignas(8) static GWP_ASAN_TLS_INITIAL_EXEC ThreadLocalPackedVariables Locals;
+ return &Locals;
+}
+} // namespace gwp_asan
+#endif // GWP_ASAN_PLATFORM_TLS_HEADER
+
+#endif // GWP_ASAN_GUARDED_POOL_ALLOCATOR_TLS_H_
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/mutex_fuchsia.h b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/mutex_fuchsia.h
new file mode 100644
index 00000000000..db53b47dcd8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/mutex_fuchsia.h
@@ -0,0 +1,23 @@
+//===-- mutex_fuchsia.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__Fuchsia__)
+#ifndef GWP_ASAN_MUTEX_FUCHSIA_H_
+#define GWP_ASAN_MUTEX_FUCHSIA_H_
+
+#error #include <lib/sync/mutex.h>
+
+namespace gwp_asan {
+class PlatformMutex {
+protected:
+ sync_mutex_t Mu = {};
+};
+} // namespace gwp_asan
+
+#endif // GWP_ASAN_MUTEX_FUCHSIA_H_
+#endif // defined(__Fuchsia__)
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/mutex_posix.cpp b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/mutex_posix.cpp
new file mode 100644
index 00000000000..8bd405e1074
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/mutex_posix.cpp
@@ -0,0 +1,30 @@
+//===-- mutex_posix.cpp -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "gwp_asan/mutex.h"
+
+#include <assert.h>
+#include <pthread.h>
+
+namespace gwp_asan {
+void Mutex::lock() {
+ int Status = pthread_mutex_lock(&Mu);
+ assert(Status == 0);
+ // Remove warning for non-debug builds.
+ (void)Status;
+}
+
+bool Mutex::tryLock() { return pthread_mutex_trylock(&Mu) == 0; }
+
+void Mutex::unlock() {
+ int Status = pthread_mutex_unlock(&Mu);
+ assert(Status == 0);
+ // Remove warning for non-debug builds.
+ (void)Status;
+}
+} // namespace gwp_asan
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/mutex_posix.h b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/mutex_posix.h
new file mode 100644
index 00000000000..7f0239198f5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/mutex_posix.h
@@ -0,0 +1,23 @@
+//===-- mutex_posix.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__unix__)
+#ifndef GWP_ASAN_MUTEX_POSIX_H_
+#define GWP_ASAN_MUTEX_POSIX_H_
+
+#include <pthread.h>
+
+namespace gwp_asan {
+class PlatformMutex {
+protected:
+ pthread_mutex_t Mu = PTHREAD_MUTEX_INITIALIZER;
+};
+} // namespace gwp_asan
+
+#endif // GWP_ASAN_MUTEX_POSIX_H_
+#endif // defined(__unix__)
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/utilities_posix.cpp b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/utilities_posix.cpp
new file mode 100644
index 00000000000..73579630550
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/platform_specific/utilities_posix.cpp
@@ -0,0 +1,30 @@
+//===-- utilities_posix.cpp -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <features.h> // IWYU pragma: keep (for __BIONIC__ macro)
+
+#ifdef __BIONIC__
+#include "gwp_asan/definitions.h"
+#include <stdlib.h>
+extern "C" GWP_ASAN_WEAK void android_set_abort_message(const char *);
+#else // __BIONIC__
+#include <stdio.h>
+#endif
+
+namespace gwp_asan {
+void die(const char *Message) {
+#ifdef __BIONIC__
+ if (&android_set_abort_message != nullptr)
+ android_set_abort_message(Message);
+ abort();
+#else // __BIONIC__
+ fprintf(stderr, "%s", Message);
+ __builtin_trap();
+#endif // __BIONIC__
+}
+} // namespace gwp_asan
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/stack_trace_compressor.cpp b/contrib/libs/clang16-rt/lib/gwp_asan/stack_trace_compressor.cpp
new file mode 100644
index 00000000000..ca3167fb83a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/stack_trace_compressor.cpp
@@ -0,0 +1,111 @@
+//===-- stack_trace_compressor.cpp ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "gwp_asan/stack_trace_compressor.h"
+
+namespace gwp_asan {
+namespace compression {
+namespace {
+// Encodes `Value` as a variable-length integer to `Out`. Returns zero if there
+// was not enough space in the output buffer to write the complete varInt.
+// Otherwise returns the length of the encoded integer.
+size_t varIntEncode(uintptr_t Value, uint8_t *Out, size_t OutLen) {
+ for (size_t i = 0; i < OutLen; ++i) {
+ Out[i] = Value & 0x7f;
+ Value >>= 7;
+ if (!Value)
+ return i + 1;
+
+ Out[i] |= 0x80;
+ }
+
+ return 0;
+}
+
+// Decodes a variable-length integer to `Out`. Returns zero if the integer was
+// too large to be represented in a uintptr_t, or if the input buffer finished
+// before the integer was decoded (either case meaning that the `In` does not
+// point to a valid varInt buffer). Otherwise, returns the number of bytes that
+// were used to store the decoded integer.
+size_t varIntDecode(const uint8_t *In, size_t InLen, uintptr_t *Out) {
+ *Out = 0;
+ uint8_t Shift = 0;
+
+ for (size_t i = 0; i < InLen; ++i) {
+ *Out |= (static_cast<uintptr_t>(In[i]) & 0x7f) << Shift;
+
+ if (In[i] < 0x80)
+ return i + 1;
+
+ Shift += 7;
+
+ // Disallow overflowing the range of the output integer.
+ if (Shift >= sizeof(uintptr_t) * 8)
+ return 0;
+ }
+ return 0;
+}
+
+uintptr_t zigzagEncode(uintptr_t Value) {
+ uintptr_t Encoded = Value << 1;
+ if (static_cast<intptr_t>(Value) >= 0)
+ return Encoded;
+ return ~Encoded;
+}
+
+uintptr_t zigzagDecode(uintptr_t Value) {
+ uintptr_t Decoded = Value >> 1;
+ if (!(Value & 1))
+ return Decoded;
+ return ~Decoded;
+}
+} // anonymous namespace
+
+size_t pack(const uintptr_t *Unpacked, size_t UnpackedSize, uint8_t *Packed,
+ size_t PackedMaxSize) {
+ size_t Index = 0;
+ for (size_t CurrentDepth = 0; CurrentDepth < UnpackedSize; CurrentDepth++) {
+ uintptr_t Diff = Unpacked[CurrentDepth];
+ if (CurrentDepth > 0)
+ Diff -= Unpacked[CurrentDepth - 1];
+ size_t EncodedLength =
+ varIntEncode(zigzagEncode(Diff), Packed + Index, PackedMaxSize - Index);
+ if (!EncodedLength)
+ break;
+
+ Index += EncodedLength;
+ }
+
+ return Index;
+}
+
+size_t unpack(const uint8_t *Packed, size_t PackedSize, uintptr_t *Unpacked,
+ size_t UnpackedMaxSize) {
+ size_t CurrentDepth;
+ size_t Index = 0;
+ for (CurrentDepth = 0; CurrentDepth < UnpackedMaxSize; CurrentDepth++) {
+ uintptr_t EncodedDiff;
+ size_t DecodedLength =
+ varIntDecode(Packed + Index, PackedSize - Index, &EncodedDiff);
+ if (!DecodedLength)
+ break;
+ Index += DecodedLength;
+
+ Unpacked[CurrentDepth] = zigzagDecode(EncodedDiff);
+ if (CurrentDepth > 0)
+ Unpacked[CurrentDepth] += Unpacked[CurrentDepth - 1];
+ }
+
+ if (Index != PackedSize && CurrentDepth != UnpackedMaxSize)
+ return 0;
+
+ return CurrentDepth;
+}
+
+} // namespace compression
+} // namespace gwp_asan
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/stack_trace_compressor.h b/contrib/libs/clang16-rt/lib/gwp_asan/stack_trace_compressor.h
new file mode 100644
index 00000000000..dcbd9a3c1f0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/stack_trace_compressor.h
@@ -0,0 +1,38 @@
+//===-- stack_trace_compressor.h --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_STACK_TRACE_COMPRESSOR_
+#define GWP_ASAN_STACK_TRACE_COMPRESSOR_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// These functions implement stack frame compression and decompression. We store
+// the zig-zag encoded pointer difference between frame[i] and frame[i - 1] as
+// a variable-length integer. This can reduce the memory overhead of stack
+// traces by 50%.
+
+namespace gwp_asan {
+namespace compression {
+
+// For the stack trace in `Unpacked` with length `UnpackedSize`, pack it into
+// the buffer `Packed` maximum length `PackedMaxSize`. The return value is the
+// number of bytes that were written to the output buffer.
+size_t pack(const uintptr_t *Unpacked, size_t UnpackedSize, uint8_t *Packed,
+ size_t PackedMaxSize);
+
+// From the packed stack trace in `Packed` of length `PackedSize`, write the
+// unpacked stack trace of maximum length `UnpackedMaxSize` into `Unpacked`.
+// Returns the number of full entries unpacked, or zero on error.
+size_t unpack(const uint8_t *Packed, size_t PackedSize, uintptr_t *Unpacked,
+ size_t UnpackedMaxSize);
+
+} // namespace compression
+} // namespace gwp_asan
+
+#endif // GWP_ASAN_STACK_TRACE_COMPRESSOR_
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/utilities.h b/contrib/libs/clang16-rt/lib/gwp_asan/utilities.h
new file mode 100644
index 00000000000..d8bc0e491a3
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/utilities.h
@@ -0,0 +1,28 @@
+//===-- utilities.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_UTILITIES_H_
+#define GWP_ASAN_UTILITIES_H_
+
+#include "gwp_asan/definitions.h"
+
+#include <stddef.h>
+
+namespace gwp_asan {
+// Terminates in a platform-specific way with `Message`.
+void die(const char *Message);
+
+// Checks that `Condition` is true, otherwise dies with `Message`.
+GWP_ASAN_ALWAYS_INLINE void Check(bool Condition, const char *Message) {
+ if (Condition)
+ return;
+ die(Message);
+}
+} // namespace gwp_asan
+
+#endif // GWP_ASAN_UTILITIES_H_
diff --git a/contrib/libs/clang16-rt/lib/gwp_asan/ya.make b/contrib/libs/clang16-rt/lib/gwp_asan/ya.make
new file mode 100644
index 00000000000..24f49509db7
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/gwp_asan/ya.make
@@ -0,0 +1,51 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.gwp_asan${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-omit-frame-pointer
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCS(
+ common.cpp
+ crash_handler.cpp
+ guarded_pool_allocator.cpp
+ platform_specific/common_posix.cpp
+ platform_specific/guarded_pool_allocator_posix.cpp
+ platform_specific/mutex_posix.cpp
+ platform_specific/utilities_posix.cpp
+ stack_trace_compressor.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/hwasan/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/hwasan/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan.cpp
new file mode 100644
index 00000000000..cdf231c2547
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan.cpp
@@ -0,0 +1,644 @@
+//===-- hwasan.cpp --------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// HWAddressSanitizer runtime.
+//===----------------------------------------------------------------------===//
+
+#include "hwasan.h"
+
+#include "hwasan_checks.h"
+#include "hwasan_dynamic_shadow.h"
+#include "hwasan_globals.h"
+#include "hwasan_mapping.h"
+#include "hwasan_poisoning.h"
+#include "hwasan_report.h"
+#include "hwasan_thread.h"
+#include "hwasan_thread_list.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_interface_internal.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+#include "ubsan/ubsan_flags.h"
+#include "ubsan/ubsan_init.h"
+
+// ACHTUNG! No system header includes in this file.
+
+using namespace __sanitizer;
+
+namespace __hwasan {
+
+static Flags hwasan_flags;
+
+Flags *flags() {
+ return &hwasan_flags;
+}
+
+int hwasan_inited = 0;
+int hwasan_instrumentation_inited = 0;
+bool hwasan_init_is_running;
+
+int hwasan_report_count = 0;
+
+uptr kLowShadowStart;
+uptr kLowShadowEnd;
+uptr kHighShadowStart;
+uptr kHighShadowEnd;
+
+void Flags::SetDefaults() {
+#define HWASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "hwasan_flags.inc"
+#undef HWASAN_FLAG
+}
+
+static void RegisterHwasanFlags(FlagParser *parser, Flags *f) {
+#define HWASAN_FLAG(Type, Name, DefaultValue, Description) \
+ RegisterFlag(parser, #Name, Description, &f->Name);
+#include "hwasan_flags.inc"
+#undef HWASAN_FLAG
+}
+
+static void InitializeFlags() {
+ SetCommonFlagsDefaults();
+ {
+ CommonFlags cf;
+ cf.CopyFrom(*common_flags());
+ cf.external_symbolizer_path = GetEnv("HWASAN_SYMBOLIZER_PATH");
+ cf.malloc_context_size = 20;
+ cf.handle_ioctl = true;
+ // FIXME: test and enable.
+ cf.check_printf = false;
+ cf.intercept_tls_get_addr = true;
+ cf.exitcode = 99;
+ // 8 shadow pages ~512kB, small enough to cover common stack sizes.
+ cf.clear_shadow_mmap_threshold = 4096 * (SANITIZER_ANDROID ? 2 : 8);
+ // Sigtrap is used in error reporting.
+ cf.handle_sigtrap = kHandleSignalExclusive;
+ // FIXME: enable once all false positives have been fixed.
+ cf.detect_leaks = false;
+
+#if SANITIZER_ANDROID
+ // Let platform handle other signals. It is better at reporting them then we
+ // are.
+ cf.handle_segv = kHandleSignalNo;
+ cf.handle_sigbus = kHandleSignalNo;
+ cf.handle_abort = kHandleSignalNo;
+ cf.handle_sigill = kHandleSignalNo;
+ cf.handle_sigfpe = kHandleSignalNo;
+#endif
+ OverrideCommonFlags(cf);
+ }
+
+ Flags *f = flags();
+ f->SetDefaults();
+
+ FlagParser parser;
+ RegisterHwasanFlags(&parser, f);
+ RegisterCommonFlags(&parser);
+
+#if CAN_SANITIZE_LEAKS
+ __lsan::Flags *lf = __lsan::flags();
+ lf->SetDefaults();
+
+ FlagParser lsan_parser;
+ __lsan::RegisterLsanFlags(&lsan_parser, lf);
+ RegisterCommonFlags(&lsan_parser);
+#endif
+
+#if HWASAN_CONTAINS_UBSAN
+ __ubsan::Flags *uf = __ubsan::flags();
+ uf->SetDefaults();
+
+ FlagParser ubsan_parser;
+ __ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
+ RegisterCommonFlags(&ubsan_parser);
+#endif
+
+ // Override from user-specified string.
+ if (__hwasan_default_options)
+ parser.ParseString(__hwasan_default_options());
+#if HWASAN_CONTAINS_UBSAN
+ const char *ubsan_default_options = __ubsan_default_options();
+ ubsan_parser.ParseString(ubsan_default_options);
+#endif
+
+ parser.ParseStringFromEnv("HWASAN_OPTIONS");
+#if CAN_SANITIZE_LEAKS
+ lsan_parser.ParseStringFromEnv("LSAN_OPTIONS");
+#endif
+#if HWASAN_CONTAINS_UBSAN
+ ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
+#endif
+
+ InitializeCommonFlags();
+
+ if (Verbosity()) ReportUnrecognizedFlags();
+
+ if (common_flags()->help) parser.PrintFlagDescriptions();
+ // Flag validation:
+ if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) {
+ Report("%s: detect_leaks is not supported on this platform.\n",
+ SanitizerToolName);
+ Die();
+ }
+}
+
+static void CheckUnwind() {
+ GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME());
+ stack.Print();
+}
+
+static void HwasanFormatMemoryUsage(InternalScopedString &s) {
+ HwasanThreadList &thread_list = hwasanThreadList();
+ auto thread_stats = thread_list.GetThreadStats();
+ auto sds = StackDepotGetStats();
+ AllocatorStatCounters asc;
+ GetAllocatorStats(asc);
+ s.append(
+ "HWASAN pid: %d rss: %zd threads: %zd stacks: %zd"
+ " thr_aux: %zd stack_depot: %zd uniq_stacks: %zd"
+ " heap: %zd",
+ internal_getpid(), GetRSS(), thread_stats.n_live_threads,
+ thread_stats.total_stack_size,
+ thread_stats.n_live_threads * thread_list.MemoryUsedPerThread(),
+ sds.allocated, sds.n_uniq_ids, asc[AllocatorStatMapped]);
+}
+
+#if SANITIZER_ANDROID
+static constexpr uptr kMemoryUsageBufferSize = 4096;
+
+static char *memory_usage_buffer = nullptr;
+
+static void InitMemoryUsage() {
+ memory_usage_buffer =
+ (char *)MmapOrDie(kMemoryUsageBufferSize, "memory usage string");
+ CHECK(memory_usage_buffer);
+ memory_usage_buffer[0] = '\0';
+ DecorateMapping((uptr)memory_usage_buffer, kMemoryUsageBufferSize,
+ memory_usage_buffer);
+}
+
+void UpdateMemoryUsage() {
+ if (!flags()->export_memory_stats)
+ return;
+ if (!memory_usage_buffer)
+ InitMemoryUsage();
+ InternalScopedString s;
+ HwasanFormatMemoryUsage(s);
+ internal_strncpy(memory_usage_buffer, s.data(), kMemoryUsageBufferSize - 1);
+ memory_usage_buffer[kMemoryUsageBufferSize - 1] = '\0';
+}
+#else
+void UpdateMemoryUsage() {}
+#endif
+
+void HwasanAtExit() {
+ if (common_flags()->print_module_map)
+ DumpProcessMap();
+ if (flags()->print_stats && (flags()->atexit || hwasan_report_count > 0))
+ ReportStats();
+ if (hwasan_report_count > 0) {
+ // ReportAtExitStatistics();
+ if (common_flags()->exitcode)
+ internal__exit(common_flags()->exitcode);
+ }
+}
+
+void HandleTagMismatch(AccessInfo ai, uptr pc, uptr frame, void *uc,
+ uptr *registers_frame) {
+ InternalMmapVector<BufferedStackTrace> stack_buffer(1);
+ BufferedStackTrace *stack = stack_buffer.data();
+ stack->Reset();
+ stack->Unwind(pc, frame, uc, common_flags()->fast_unwind_on_fatal);
+
+ // The second stack frame contains the failure __hwasan_check function, as
+ // we have a stack frame for the registers saved in __hwasan_tag_mismatch that
+ // we wish to ignore. This (currently) only occurs on AArch64, as x64
+ // implementations use SIGTRAP to implement the failure, and thus do not go
+ // through the stack saver.
+ if (registers_frame && stack->trace && stack->size > 0) {
+ stack->trace++;
+ stack->size--;
+ }
+
+ bool fatal = flags()->halt_on_error || !ai.recover;
+ ReportTagMismatch(stack, ai.addr, ai.size, ai.is_store, fatal,
+ registers_frame);
+}
+
+void HwasanTagMismatch(uptr addr, uptr pc, uptr frame, uptr access_info,
+ uptr *registers_frame, size_t outsize) {
+ __hwasan::AccessInfo ai;
+ ai.is_store = access_info & 0x10;
+ ai.is_load = !ai.is_store;
+ ai.recover = access_info & 0x20;
+ ai.addr = addr;
+ if ((access_info & 0xf) == 0xf)
+ ai.size = outsize;
+ else
+ ai.size = 1 << (access_info & 0xf);
+
+ HandleTagMismatch(ai, pc, frame, nullptr, registers_frame);
+}
+
+Thread *GetCurrentThread() {
+ uptr *ThreadLongPtr = GetCurrentThreadLongPtr();
+ if (UNLIKELY(*ThreadLongPtr == 0))
+ return nullptr;
+ auto *R = (StackAllocationsRingBuffer *)ThreadLongPtr;
+ return hwasanThreadList().GetThreadByBufferAddress((uptr)R->Next());
+}
+
+} // namespace __hwasan
+
+using namespace __hwasan;
+
+void __sanitizer::BufferedStackTrace::UnwindImpl(
+ uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
+ Thread *t = GetCurrentThread();
+ if (!t) {
+ // The thread is still being created, or has already been destroyed.
+ size = 0;
+ return;
+ }
+ Unwind(max_depth, pc, bp, context, t->stack_top(), t->stack_bottom(),
+ request_fast);
+}
+
+static bool InitializeSingleGlobal(const hwasan_global &global) {
+ uptr full_granule_size = RoundDownTo(global.size(), 16);
+ TagMemoryAligned(global.addr(), full_granule_size, global.tag());
+ if (global.size() % 16)
+ TagMemoryAligned(global.addr() + full_granule_size, 16, global.size() % 16);
+ return false;
+}
+
+static void InitLoadedGlobals() {
+ dl_iterate_phdr(
+ [](dl_phdr_info *info, size_t /* size */, void * /* data */) -> int {
+ for (const hwasan_global &global : HwasanGlobalsFor(
+ info->dlpi_addr, info->dlpi_phdr, info->dlpi_phnum))
+ InitializeSingleGlobal(global);
+ return 0;
+ },
+ nullptr);
+}
+
+// Prepare to run instrumented code on the main thread.
+static void InitInstrumentation() {
+ if (hwasan_instrumentation_inited) return;
+
+ InitializeOsSupport();
+
+ if (!InitShadow()) {
+ Printf("FATAL: HWAddressSanitizer cannot mmap the shadow memory.\n");
+ DumpProcessMap();
+ Die();
+ }
+
+ InitThreads();
+
+ hwasan_instrumentation_inited = 1;
+}
+
+// Interface.
+
+uptr __hwasan_shadow_memory_dynamic_address; // Global interface symbol.
+
+// This function was used by the old frame descriptor mechanism. We keep it
+// around to avoid breaking ABI.
+void __hwasan_init_frames(uptr beg, uptr end) {}
+
+void __hwasan_init_static() {
+ InitShadowGOT();
+ InitInstrumentation();
+
+ // In the non-static code path we call dl_iterate_phdr here. But at this point
+ // libc might not have been initialized enough for dl_iterate_phdr to work.
+ // Fortunately, since this is a statically linked executable we can use the
+ // linker-defined symbol __ehdr_start to find the only relevant set of phdrs.
+ extern ElfW(Ehdr) __ehdr_start;
+ for (const hwasan_global &global : HwasanGlobalsFor(
+ /* base */ 0,
+ reinterpret_cast<const ElfW(Phdr) *>(
+ reinterpret_cast<const char *>(&__ehdr_start) +
+ __ehdr_start.e_phoff),
+ __ehdr_start.e_phnum))
+ InitializeSingleGlobal(global);
+}
+
+__attribute__((constructor(0))) void __hwasan_init() {
+ CHECK(!hwasan_init_is_running);
+ if (hwasan_inited) return;
+ hwasan_init_is_running = 1;
+ SanitizerToolName = "HWAddressSanitizer";
+
+ InitTlsSize();
+
+ CacheBinaryName();
+ InitializeFlags();
+
+ // Install tool-specific callbacks in sanitizer_common.
+ SetCheckUnwindCallback(CheckUnwind);
+
+ __sanitizer_set_report_path(common_flags()->log_path);
+
+ AndroidTestTlsSlot();
+
+ DisableCoreDumperIfNecessary();
+
+ InitInstrumentation();
+ if constexpr (!SANITIZER_FUCHSIA) {
+ // Fuchsia's libc provides a hook (__sanitizer_module_loaded) that runs on
+ // the startup path which calls into __hwasan_library_loaded on all
+ // initially loaded modules, so explicitly registering the globals here
+ // isn't needed.
+ InitLoadedGlobals();
+ }
+
+ // Needs to be called here because flags()->random_tags might not have been
+ // initialized when InitInstrumentation() was called.
+ GetCurrentThread()->EnsureRandomStateInited();
+
+ SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
+ // This may call libc -> needs initialized shadow.
+ AndroidLogInit();
+
+ InitializeInterceptors();
+ InstallDeadlySignalHandlers(HwasanOnDeadlySignal);
+ InstallAtExitHandler(); // Needs __cxa_atexit interceptor.
+
+ InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
+
+ HwasanTSDInit();
+ HwasanTSDThreadInit();
+
+ HwasanAllocatorInit();
+ HwasanInstallAtForkHandler();
+
+ if (CAN_SANITIZE_LEAKS) {
+ __lsan::InitCommonLsan();
+ InstallAtExitCheckLeaks();
+ }
+
+#if HWASAN_CONTAINS_UBSAN
+ __ubsan::InitAsPlugin();
+#endif
+
+ if (CAN_SANITIZE_LEAKS) {
+ __lsan::ScopedInterceptorDisabler disabler;
+ Symbolizer::LateInitialize();
+ } else {
+ Symbolizer::LateInitialize();
+ }
+
+ VPrintf(1, "HWAddressSanitizer init done\n");
+
+ hwasan_init_is_running = 0;
+ hwasan_inited = 1;
+}
+
+void __hwasan_library_loaded(ElfW(Addr) base, const ElfW(Phdr) * phdr,
+ ElfW(Half) phnum) {
+ for (const hwasan_global &global : HwasanGlobalsFor(base, phdr, phnum))
+ InitializeSingleGlobal(global);
+}
+
+void __hwasan_library_unloaded(ElfW(Addr) base, const ElfW(Phdr) * phdr,
+ ElfW(Half) phnum) {
+ for (; phnum != 0; ++phdr, --phnum)
+ if (phdr->p_type == PT_LOAD)
+ TagMemory(base + phdr->p_vaddr, phdr->p_memsz, 0);
+}
+
+void __hwasan_print_shadow(const void *p, uptr sz) {
+ uptr ptr_raw = UntagAddr(reinterpret_cast<uptr>(p));
+ uptr shadow_first = MemToShadow(ptr_raw);
+ uptr shadow_last = MemToShadow(ptr_raw + sz - 1);
+ Printf("HWASan shadow map for %zx .. %zx (pointer tag %x)\n", ptr_raw,
+ ptr_raw + sz, GetTagFromPointer((uptr)p));
+ for (uptr s = shadow_first; s <= shadow_last; ++s) {
+ tag_t mem_tag = *reinterpret_cast<tag_t *>(s);
+ uptr granule_addr = ShadowToMem(s);
+ if (mem_tag && mem_tag < kShadowAlignment)
+ Printf(" %zx: %02x(%02x)\n", granule_addr, mem_tag,
+ *reinterpret_cast<tag_t *>(granule_addr + kShadowAlignment - 1));
+ else
+ Printf(" %zx: %02x\n", granule_addr, mem_tag);
+ }
+}
+
+sptr __hwasan_test_shadow(const void *p, uptr sz) {
+ if (sz == 0)
+ return -1;
+ tag_t ptr_tag = GetTagFromPointer((uptr)p);
+ uptr ptr_raw = UntagAddr(reinterpret_cast<uptr>(p));
+ uptr shadow_first = MemToShadow(ptr_raw);
+ uptr shadow_last = MemToShadow(ptr_raw + sz - 1);
+ for (uptr s = shadow_first; s <= shadow_last; ++s)
+ if (*(tag_t *)s != ptr_tag) {
+ sptr offset = ShadowToMem(s) - ptr_raw;
+ return offset < 0 ? 0 : offset;
+ }
+ return -1;
+}
+
+u16 __sanitizer_unaligned_load16(const uu16 *p) {
+ return *p;
+}
+u32 __sanitizer_unaligned_load32(const uu32 *p) {
+ return *p;
+}
+u64 __sanitizer_unaligned_load64(const uu64 *p) {
+ return *p;
+}
+void __sanitizer_unaligned_store16(uu16 *p, u16 x) {
+ *p = x;
+}
+void __sanitizer_unaligned_store32(uu32 *p, u32 x) {
+ *p = x;
+}
+void __sanitizer_unaligned_store64(uu64 *p, u64 x) {
+ *p = x;
+}
+
+void __hwasan_loadN(uptr p, uptr sz) {
+ CheckAddressSized<ErrorAction::Abort, AccessType::Load>(p, sz);
+}
+void __hwasan_load1(uptr p) {
+ CheckAddress<ErrorAction::Abort, AccessType::Load, 0>(p);
+}
+void __hwasan_load2(uptr p) {
+ CheckAddress<ErrorAction::Abort, AccessType::Load, 1>(p);
+}
+void __hwasan_load4(uptr p) {
+ CheckAddress<ErrorAction::Abort, AccessType::Load, 2>(p);
+}
+void __hwasan_load8(uptr p) {
+ CheckAddress<ErrorAction::Abort, AccessType::Load, 3>(p);
+}
+void __hwasan_load16(uptr p) {
+ CheckAddress<ErrorAction::Abort, AccessType::Load, 4>(p);
+}
+
+void __hwasan_loadN_noabort(uptr p, uptr sz) {
+ CheckAddressSized<ErrorAction::Recover, AccessType::Load>(p, sz);
+}
+void __hwasan_load1_noabort(uptr p) {
+ CheckAddress<ErrorAction::Recover, AccessType::Load, 0>(p);
+}
+void __hwasan_load2_noabort(uptr p) {
+ CheckAddress<ErrorAction::Recover, AccessType::Load, 1>(p);
+}
+void __hwasan_load4_noabort(uptr p) {
+ CheckAddress<ErrorAction::Recover, AccessType::Load, 2>(p);
+}
+void __hwasan_load8_noabort(uptr p) {
+ CheckAddress<ErrorAction::Recover, AccessType::Load, 3>(p);
+}
+void __hwasan_load16_noabort(uptr p) {
+ CheckAddress<ErrorAction::Recover, AccessType::Load, 4>(p);
+}
+
+void __hwasan_storeN(uptr p, uptr sz) {
+ CheckAddressSized<ErrorAction::Abort, AccessType::Store>(p, sz);
+}
+void __hwasan_store1(uptr p) {
+ CheckAddress<ErrorAction::Abort, AccessType::Store, 0>(p);
+}
+void __hwasan_store2(uptr p) {
+ CheckAddress<ErrorAction::Abort, AccessType::Store, 1>(p);
+}
+void __hwasan_store4(uptr p) {
+ CheckAddress<ErrorAction::Abort, AccessType::Store, 2>(p);
+}
+void __hwasan_store8(uptr p) {
+ CheckAddress<ErrorAction::Abort, AccessType::Store, 3>(p);
+}
+void __hwasan_store16(uptr p) {
+ CheckAddress<ErrorAction::Abort, AccessType::Store, 4>(p);
+}
+
+void __hwasan_storeN_noabort(uptr p, uptr sz) {
+ CheckAddressSized<ErrorAction::Recover, AccessType::Store>(p, sz);
+}
+void __hwasan_store1_noabort(uptr p) {
+ CheckAddress<ErrorAction::Recover, AccessType::Store, 0>(p);
+}
+void __hwasan_store2_noabort(uptr p) {
+ CheckAddress<ErrorAction::Recover, AccessType::Store, 1>(p);
+}
+void __hwasan_store4_noabort(uptr p) {
+ CheckAddress<ErrorAction::Recover, AccessType::Store, 2>(p);
+}
+void __hwasan_store8_noabort(uptr p) {
+ CheckAddress<ErrorAction::Recover, AccessType::Store, 3>(p);
+}
+void __hwasan_store16_noabort(uptr p) {
+ CheckAddress<ErrorAction::Recover, AccessType::Store, 4>(p);
+}
+
+void __hwasan_tag_memory(uptr p, u8 tag, uptr sz) {
+ TagMemoryAligned(p, sz, tag);
+}
+
+uptr __hwasan_tag_pointer(uptr p, u8 tag) {
+ return AddTagToPointer(p, tag);
+}
+
+void __hwasan_handle_longjmp(const void *sp_dst) {
+ uptr dst = (uptr)sp_dst;
+ // HWASan does not support tagged SP.
+ CHECK(GetTagFromPointer(dst) == 0);
+
+ uptr sp = (uptr)__builtin_frame_address(0);
+ static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M
+ if (dst < sp || dst - sp > kMaxExpectedCleanupSize) {
+ Report(
+ "WARNING: HWASan is ignoring requested __hwasan_handle_longjmp: "
+ "stack top: %p; target %p; distance: %p (%zd)\n"
+ "False positive error reports may follow\n",
+ (void *)sp, (void *)dst, dst - sp);
+ return;
+ }
+ TagMemory(sp, dst - sp, 0);
+}
+
+void __hwasan_handle_vfork(const void *sp_dst) {
+ uptr sp = (uptr)sp_dst;
+ Thread *t = GetCurrentThread();
+ CHECK(t);
+ uptr top = t->stack_top();
+ uptr bottom = t->stack_bottom();
+ if (top == 0 || bottom == 0 || sp < bottom || sp >= top) {
+ Report(
+ "WARNING: HWASan is ignoring requested __hwasan_handle_vfork: "
+ "stack top: %zx; current %zx; bottom: %zx \n"
+ "False positive error reports may follow\n",
+ top, sp, bottom);
+ return;
+ }
+ TagMemory(bottom, sp - bottom, 0);
+}
+
+extern "C" void *__hwasan_extra_spill_area() {
+ Thread *t = GetCurrentThread();
+ return &t->vfork_spill();
+}
+
+void __hwasan_print_memory_usage() {
+ InternalScopedString s;
+ HwasanFormatMemoryUsage(s);
+ Printf("%s\n", s.data());
+}
+
+static const u8 kFallbackTag = 0xBB & kTagMask;
+
+u8 __hwasan_generate_tag() {
+ Thread *t = GetCurrentThread();
+ if (!t) return kFallbackTag;
+ return t->GenerateRandomTag();
+}
+
+void __hwasan_add_frame_record(u64 frame_record_info) {
+ Thread *t = GetCurrentThread();
+ if (t)
+ t->stack_allocations()->push(frame_record_info);
+}
+
+#if !SANITIZER_SUPPORTS_WEAK_HOOKS
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+const char* __hwasan_default_options() { return ""; }
+} // extern "C"
+#endif
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_print_stack_trace() {
+ GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME());
+ stack.Print();
+}
+
+// Entry point for interoperability between __hwasan_tag_mismatch (ASM) and the
+// rest of the mismatch handling code (C++).
+void __hwasan_tag_mismatch4(uptr addr, uptr access_info, uptr *registers_frame,
+ size_t outsize) {
+ __hwasan::HwasanTagMismatch(addr, (uptr)__builtin_return_address(0),
+ (uptr)__builtin_frame_address(0), access_info,
+ registers_frame, outsize);
+}
+
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan.h b/contrib/libs/clang16-rt/lib/hwasan/hwasan.h
new file mode 100644
index 00000000000..c3d71a28142
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan.h
@@ -0,0 +1,221 @@
+//===-- hwasan.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// Private Hwasan header.
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_H
+#define HWASAN_H
+
+#include "hwasan_flags.h"
+#include "hwasan_interface_internal.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "ubsan/ubsan_platform.h"
+
+#ifndef HWASAN_CONTAINS_UBSAN
+# define HWASAN_CONTAINS_UBSAN CAN_SANITIZE_UB
+#endif
+
+#ifndef HWASAN_WITH_INTERCEPTORS
+#define HWASAN_WITH_INTERCEPTORS 0
+#endif
+
+#ifndef HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE
+#define HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE HWASAN_WITH_INTERCEPTORS
+#endif
+
+typedef u8 tag_t;
+
+#if defined(HWASAN_ALIASING_MODE)
+# if !defined(__x86_64__)
+# error Aliasing mode is only supported on x86_64
+# endif
+// Tags are done in middle bits using userspace aliasing.
+constexpr unsigned kAddressTagShift = 39;
+constexpr unsigned kTagBits = 3;
+
+// The alias region is placed next to the shadow so the upper bits of all
+// taggable addresses matches the upper bits of the shadow base. This shift
+// value determines which upper bits must match. It has a floor of 44 since the
+// shadow is always 8TB.
+// TODO(morehouse): In alias mode we can shrink the shadow and use a
+// simpler/faster shadow calculation.
+constexpr unsigned kTaggableRegionCheckShift =
+ __sanitizer::Max(kAddressTagShift + kTagBits + 1U, 44U);
+#elif defined(__x86_64__)
+// Tags are done in upper bits using Intel LAM.
+constexpr unsigned kAddressTagShift = 57;
+constexpr unsigned kTagBits = 6;
+#else
+// TBI (Top Byte Ignore) feature of AArch64: bits [63:56] are ignored in address
+// translation and can be used to store a tag.
+constexpr unsigned kAddressTagShift = 56;
+constexpr unsigned kTagBits = 8;
+#endif // defined(HWASAN_ALIASING_MODE)
+
+// Mask for extracting tag bits from the lower 8 bits.
+constexpr uptr kTagMask = (1UL << kTagBits) - 1;
+
+// Mask for extracting tag bits from full pointers.
+constexpr uptr kAddressTagMask = kTagMask << kAddressTagShift;
+
+// Minimal alignment of the shadow base address. Determines the space available
+// for threads and stack histories. This is an ABI constant.
+const unsigned kShadowBaseAlignment = 32;
+
+const unsigned kRecordAddrBaseTagShift = 3;
+const unsigned kRecordFPShift = 48;
+const unsigned kRecordFPLShift = 4;
+const unsigned kRecordFPModulus = 1 << (64 - kRecordFPShift + kRecordFPLShift);
+
+static inline tag_t GetTagFromPointer(uptr p) {
+ return (p >> kAddressTagShift) & kTagMask;
+}
+
+static inline uptr UntagAddr(uptr tagged_addr) {
+ return tagged_addr & ~kAddressTagMask;
+}
+
+static inline void *UntagPtr(const void *tagged_ptr) {
+ return reinterpret_cast<void *>(
+ UntagAddr(reinterpret_cast<uptr>(tagged_ptr)));
+}
+
+static inline uptr AddTagToPointer(uptr p, tag_t tag) {
+ return (p & ~kAddressTagMask) | ((uptr)tag << kAddressTagShift);
+}
+
+namespace __hwasan {
+
+extern int hwasan_inited;
+extern bool hwasan_init_is_running;
+extern int hwasan_report_count;
+
+bool InitShadow();
+void InitializeOsSupport();
+void InitThreads();
+void InitializeInterceptors();
+
+void HwasanAllocatorInit();
+void HwasanAllocatorLock();
+void HwasanAllocatorUnlock();
+
+void *hwasan_malloc(uptr size, StackTrace *stack);
+void *hwasan_calloc(uptr nmemb, uptr size, StackTrace *stack);
+void *hwasan_realloc(void *ptr, uptr size, StackTrace *stack);
+void *hwasan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack);
+void *hwasan_valloc(uptr size, StackTrace *stack);
+void *hwasan_pvalloc(uptr size, StackTrace *stack);
+void *hwasan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack);
+void *hwasan_memalign(uptr alignment, uptr size, StackTrace *stack);
+int hwasan_posix_memalign(void **memptr, uptr alignment, uptr size,
+ StackTrace *stack);
+void hwasan_free(void *ptr, StackTrace *stack);
+
+void InstallAtExitHandler();
+
+#define GET_MALLOC_STACK_TRACE \
+ BufferedStackTrace stack; \
+ if (hwasan_inited) \
+ stack.Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), \
+ nullptr, common_flags()->fast_unwind_on_malloc, \
+ common_flags()->malloc_context_size)
+
+#define GET_FATAL_STACK_TRACE_PC_BP(pc, bp) \
+ BufferedStackTrace stack; \
+ if (hwasan_inited) \
+ stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal)
+
+void HwasanTSDInit();
+void HwasanTSDThreadInit();
+void HwasanAtExit();
+
+void HwasanOnDeadlySignal(int signo, void *info, void *context);
+
+void HwasanInstallAtForkHandler();
+
+void InstallAtExitCheckLeaks();
+
+void UpdateMemoryUsage();
+
+void AppendToErrorMessageBuffer(const char *buffer);
+
+void AndroidTestTlsSlot();
+
+// This is a compiler-generated struct that can be shared between hwasan
+// implementations.
+struct AccessInfo {
+ uptr addr;
+ uptr size;
+ bool is_store;
+ bool is_load;
+ bool recover;
+};
+
+// Given access info and frame information, unwind the stack and report the tag
+// mismatch.
+void HandleTagMismatch(AccessInfo ai, uptr pc, uptr frame, void *uc,
+ uptr *registers_frame = nullptr);
+
+// This dispatches to HandleTagMismatch but sets up the AccessInfo, program
+// counter, and frame pointer.
+void HwasanTagMismatch(uptr addr, uptr pc, uptr frame, uptr access_info,
+ uptr *registers_frame, size_t outsize);
+
+} // namespace __hwasan
+
+#if HWASAN_WITH_INTERCEPTORS
+// For both bionic and glibc __sigset_t is an unsigned long.
+typedef unsigned long __hw_sigset_t;
+// Setjmp and longjmp implementations are platform specific, and hence the
+// interception code is platform specific too.
+# if defined(__aarch64__)
+constexpr size_t kHwRegisterBufSize = 22;
+# elif defined(__x86_64__)
+constexpr size_t kHwRegisterBufSize = 8;
+# elif SANITIZER_RISCV64
+// saving PC, 12 int regs, sp, 12 fp regs
+# ifndef __riscv_float_abi_soft
+constexpr size_t kHwRegisterBufSize = 1 + 12 + 1 + 12;
+# else
+constexpr size_t kHwRegisterBufSize = 1 + 12 + 1;
+# endif
+# endif
+typedef unsigned long long __hw_register_buf[kHwRegisterBufSize];
+struct __hw_jmp_buf_struct {
+ // NOTE: The machine-dependent definition of `__sigsetjmp'
+ // assume that a `__hw_jmp_buf' begins with a `__hw_register_buf' and that
+ // `__mask_was_saved' follows it. Do not move these members or add others
+ // before it.
+ //
+ // We add a __magic field to our struct to catch cases where libc's setjmp
+ // populated the jmp_buf instead of our interceptor.
+ __hw_register_buf __jmpbuf; // Calling environment.
+ unsigned __mask_was_saved : 1; // Saved the signal mask?
+ unsigned __magic : 31; // Used to distinguish __hw_jmp_buf from jmp_buf.
+ __hw_sigset_t __saved_mask; // Saved signal mask.
+};
+typedef struct __hw_jmp_buf_struct __hw_jmp_buf[1];
+typedef struct __hw_jmp_buf_struct __hw_sigjmp_buf[1];
+constexpr unsigned kHwJmpBufMagic = 0x248ACE77;
+#endif // HWASAN_WITH_INTERCEPTORS
+
+#define ENSURE_HWASAN_INITED() \
+ do { \
+ CHECK(!hwasan_init_is_running); \
+ if (!hwasan_inited) { \
+ __hwasan_init(); \
+ } \
+ } while (0)
+
+#endif // HWASAN_H
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_allocation_functions.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_allocation_functions.cpp
new file mode 100644
index 00000000000..9cd82dbabd1
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_allocation_functions.cpp
@@ -0,0 +1,175 @@
+//===-- hwasan_allocation_functions.cpp -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// Definitions for __sanitizer allocation functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "hwasan.h"
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_allocator_dlsym.h"
+#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+
+#if !SANITIZER_FUCHSIA
+
+using namespace __hwasan;
+
+struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
+ static bool UseImpl() { return !hwasan_inited; }
+};
+
+extern "C" {
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __sanitizer_posix_memalign(void **memptr, uptr alignment, uptr size) {
+ GET_MALLOC_STACK_TRACE;
+ CHECK_NE(memptr, 0);
+ int res = hwasan_posix_memalign(memptr, alignment, size, &stack);
+ return res;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer_memalign(uptr alignment, uptr size) {
+ GET_MALLOC_STACK_TRACE;
+ return hwasan_memalign(alignment, size, &stack);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer_aligned_alloc(uptr alignment, uptr size) {
+ GET_MALLOC_STACK_TRACE;
+ return hwasan_aligned_alloc(alignment, size, &stack);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer___libc_memalign(uptr alignment, uptr size) {
+ GET_MALLOC_STACK_TRACE;
+ void *ptr = hwasan_memalign(alignment, size, &stack);
+ if (ptr)
+ DTLS_on_libc_memalign(ptr, size);
+ return ptr;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer_valloc(uptr size) {
+ GET_MALLOC_STACK_TRACE;
+ return hwasan_valloc(size, &stack);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer_pvalloc(uptr size) {
+ GET_MALLOC_STACK_TRACE;
+ return hwasan_pvalloc(size, &stack);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_free(void *ptr) {
+ if (!ptr)
+ return;
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+ GET_MALLOC_STACK_TRACE;
+ hwasan_free(ptr, &stack);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_cfree(void *ptr) {
+ if (!ptr)
+ return;
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+ GET_MALLOC_STACK_TRACE;
+ hwasan_free(ptr, &stack);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __sanitizer_malloc_usable_size(const void *ptr) {
+ return __sanitizer_get_allocated_size(ptr);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+struct __sanitizer_struct_mallinfo __sanitizer_mallinfo() {
+ __sanitizer_struct_mallinfo sret;
+ internal_memset(&sret, 0, sizeof(sret));
+ return sret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __sanitizer_mallopt(int cmd, int value) { return 0; }
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_malloc_stats(void) {
+ // FIXME: implement, but don't call REAL(malloc_stats)!
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer_calloc(uptr nmemb, uptr size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Callocate(nmemb, size);
+ GET_MALLOC_STACK_TRACE;
+ return hwasan_calloc(nmemb, size, &stack);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer_realloc(void *ptr, uptr size) {
+ if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Realloc(ptr, size);
+ GET_MALLOC_STACK_TRACE;
+ return hwasan_realloc(ptr, size, &stack);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer_reallocarray(void *ptr, uptr nmemb, uptr size) {
+ GET_MALLOC_STACK_TRACE;
+ return hwasan_reallocarray(ptr, nmemb, size, &stack);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer_malloc(uptr size) {
+ if (UNLIKELY(!hwasan_init_is_running))
+ ENSURE_HWASAN_INITED();
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Allocate(size);
+ GET_MALLOC_STACK_TRACE;
+ return hwasan_malloc(size, &stack);
+}
+
+} // extern "C"
+
+#if HWASAN_WITH_INTERCEPTORS
+# define INTERCEPTOR_ALIAS(RET, FN, ARGS...) \
+ extern "C" SANITIZER_INTERFACE_ATTRIBUTE RET WRAP(FN)(ARGS) \
+ ALIAS("__sanitizer_" #FN); \
+ extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE RET FN( \
+ ARGS) ALIAS("__sanitizer_" #FN)
+
+INTERCEPTOR_ALIAS(int, posix_memalign, void **memptr, SIZE_T alignment,
+ SIZE_T size);
+INTERCEPTOR_ALIAS(void *, aligned_alloc, SIZE_T alignment, SIZE_T size);
+INTERCEPTOR_ALIAS(void *, __libc_memalign, SIZE_T alignment, SIZE_T size);
+INTERCEPTOR_ALIAS(void *, valloc, SIZE_T size);
+INTERCEPTOR_ALIAS(void, free, void *ptr);
+INTERCEPTOR_ALIAS(uptr, malloc_usable_size, const void *ptr);
+INTERCEPTOR_ALIAS(void *, calloc, SIZE_T nmemb, SIZE_T size);
+INTERCEPTOR_ALIAS(void *, realloc, void *ptr, SIZE_T size);
+INTERCEPTOR_ALIAS(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size);
+INTERCEPTOR_ALIAS(void *, malloc, SIZE_T size);
+
+# if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR_ALIAS(void *, memalign, SIZE_T alignment, SIZE_T size);
+INTERCEPTOR_ALIAS(void *, pvalloc, SIZE_T size);
+INTERCEPTOR_ALIAS(void, cfree, void *ptr);
+INTERCEPTOR_ALIAS(__sanitizer_struct_mallinfo, mallinfo);
+INTERCEPTOR_ALIAS(int, mallopt, int cmd, int value);
+INTERCEPTOR_ALIAS(void, malloc_stats, void);
+# endif
+#endif // #if HWASAN_WITH_INTERCEPTORS
+
+#endif // SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_allocator.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_allocator.cpp
new file mode 100644
index 00000000000..325675ce122
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_allocator.cpp
@@ -0,0 +1,628 @@
+//===-- hwasan_allocator.cpp ------------------------ ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// HWAddressSanitizer allocator.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_errno.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "hwasan.h"
+#include "hwasan_allocator.h"
+#include "hwasan_checks.h"
+#include "hwasan_mapping.h"
+#include "hwasan_malloc_bisect.h"
+#include "hwasan_thread.h"
+#include "hwasan_report.h"
+#include "lsan/lsan_common.h"
+
+namespace __hwasan {
+
+static Allocator allocator;
+static AllocatorCache fallback_allocator_cache;
+static SpinMutex fallback_mutex;
+static atomic_uint8_t hwasan_allocator_tagging_enabled;
+
+static constexpr tag_t kFallbackAllocTag = 0xBB & kTagMask;
+static constexpr tag_t kFallbackFreeTag = 0xBC;
+
+enum {
+ // Either just allocated by underlying allocator, but AsanChunk is not yet
+ // ready, or almost returned to undelying allocator and AsanChunk is already
+ // meaningless.
+ CHUNK_INVALID = 0,
+ // The chunk is allocated and not yet freed.
+ CHUNK_ALLOCATED = 1,
+};
+
+
+// Initialized in HwasanAllocatorInit, an never changed.
+static ALIGNED(16) u8 tail_magic[kShadowAlignment - 1];
+
+bool HwasanChunkView::IsAllocated() const {
+ return metadata_ && metadata_->IsAllocated();
+}
+
+uptr HwasanChunkView::Beg() const {
+ return block_;
+}
+uptr HwasanChunkView::End() const {
+ return Beg() + UsedSize();
+}
+uptr HwasanChunkView::UsedSize() const {
+ return metadata_->GetRequestedSize();
+}
+u32 HwasanChunkView::GetAllocStackId() const {
+ return metadata_->GetAllocStackId();
+}
+
+uptr HwasanChunkView::ActualSize() const {
+ return allocator.GetActuallyAllocatedSize(reinterpret_cast<void *>(block_));
+}
+
+bool HwasanChunkView::FromSmallHeap() const {
+ return allocator.FromPrimary(reinterpret_cast<void *>(block_));
+}
+
+bool HwasanChunkView::AddrIsInside(uptr addr) const {
+ return (addr >= Beg()) && (addr < Beg() + UsedSize());
+}
+
+inline void Metadata::SetAllocated(u32 stack, u64 size) {
+ Thread *t = GetCurrentThread();
+ u64 context = t ? t->unique_id() : kMainTid;
+ context <<= 32;
+ context += stack;
+ requested_size_low = size & ((1ul << 32) - 1);
+ requested_size_high = size >> 32;
+ atomic_store(&alloc_context_id, context, memory_order_relaxed);
+ atomic_store(&chunk_state, CHUNK_ALLOCATED, memory_order_release);
+}
+
+inline void Metadata::SetUnallocated() {
+ atomic_store(&chunk_state, CHUNK_INVALID, memory_order_release);
+ requested_size_low = 0;
+ requested_size_high = 0;
+ atomic_store(&alloc_context_id, 0, memory_order_relaxed);
+}
+
+inline bool Metadata::IsAllocated() const {
+ return atomic_load(&chunk_state, memory_order_relaxed) == CHUNK_ALLOCATED &&
+ GetRequestedSize();
+}
+
+inline u64 Metadata::GetRequestedSize() const {
+ return (static_cast<u64>(requested_size_high) << 32) + requested_size_low;
+}
+
+inline u32 Metadata::GetAllocStackId() const {
+ return atomic_load(&alloc_context_id, memory_order_relaxed);
+}
+
+void GetAllocatorStats(AllocatorStatCounters s) {
+ allocator.GetStats(s);
+}
+
+inline void Metadata::SetLsanTag(__lsan::ChunkTag tag) {
+ lsan_tag = tag;
+}
+
+inline __lsan::ChunkTag Metadata::GetLsanTag() const {
+ return static_cast<__lsan::ChunkTag>(lsan_tag);
+}
+
+uptr GetAliasRegionStart() {
+#if defined(HWASAN_ALIASING_MODE)
+ constexpr uptr kAliasRegionOffset = 1ULL << (kTaggableRegionCheckShift - 1);
+ uptr AliasRegionStart =
+ __hwasan_shadow_memory_dynamic_address + kAliasRegionOffset;
+
+ CHECK_EQ(AliasRegionStart >> kTaggableRegionCheckShift,
+ __hwasan_shadow_memory_dynamic_address >> kTaggableRegionCheckShift);
+ CHECK_EQ(
+ (AliasRegionStart + kAliasRegionOffset - 1) >> kTaggableRegionCheckShift,
+ __hwasan_shadow_memory_dynamic_address >> kTaggableRegionCheckShift);
+ return AliasRegionStart;
+#else
+ return 0;
+#endif
+}
+
+void HwasanAllocatorInit() {
+ atomic_store_relaxed(&hwasan_allocator_tagging_enabled,
+ !flags()->disable_allocator_tagging);
+ SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null);
+ allocator.Init(common_flags()->allocator_release_to_os_interval_ms,
+ GetAliasRegionStart());
+ for (uptr i = 0; i < sizeof(tail_magic); i++)
+ tail_magic[i] = GetCurrentThread()->GenerateRandomTag();
+}
+
+void HwasanAllocatorLock() { allocator.ForceLock(); }
+
+void HwasanAllocatorUnlock() { allocator.ForceUnlock(); }
+
+void AllocatorSwallowThreadLocalCache(AllocatorCache *cache) {
+ allocator.SwallowCache(cache);
+}
+
+static uptr TaggedSize(uptr size) {
+ if (!size) size = 1;
+ uptr new_size = RoundUpTo(size, kShadowAlignment);
+ CHECK_GE(new_size, size);
+ return new_size;
+}
+
+static void *HwasanAllocate(StackTrace *stack, uptr orig_size, uptr alignment,
+ bool zeroise) {
+ if (orig_size > kMaxAllowedMallocSize) {
+ if (AllocatorMayReturnNull()) {
+ Report("WARNING: HWAddressSanitizer failed to allocate 0x%zx bytes\n",
+ orig_size);
+ return nullptr;
+ }
+ ReportAllocationSizeTooBig(orig_size, kMaxAllowedMallocSize, stack);
+ }
+ if (UNLIKELY(IsRssLimitExceeded())) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportRssLimitExceeded(stack);
+ }
+
+ alignment = Max(alignment, kShadowAlignment);
+ uptr size = TaggedSize(orig_size);
+ Thread *t = GetCurrentThread();
+ void *allocated;
+ if (t) {
+ allocated = allocator.Allocate(t->allocator_cache(), size, alignment);
+ } else {
+ SpinMutexLock l(&fallback_mutex);
+ AllocatorCache *cache = &fallback_allocator_cache;
+ allocated = allocator.Allocate(cache, size, alignment);
+ }
+ if (UNLIKELY(!allocated)) {
+ SetAllocatorOutOfMemory();
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportOutOfMemory(size, stack);
+ }
+ if (zeroise) {
+ internal_memset(allocated, 0, size);
+ } else if (flags()->max_malloc_fill_size > 0) {
+ uptr fill_size = Min(size, (uptr)flags()->max_malloc_fill_size);
+ internal_memset(allocated, flags()->malloc_fill_byte, fill_size);
+ }
+ if (size != orig_size) {
+ u8 *tail = reinterpret_cast<u8 *>(allocated) + orig_size;
+ uptr tail_length = size - orig_size;
+ internal_memcpy(tail, tail_magic, tail_length - 1);
+ // Short granule is excluded from magic tail, so we explicitly untag.
+ tail[tail_length - 1] = 0;
+ }
+
+ void *user_ptr = allocated;
+ // Tagging can only be skipped when both tag_in_malloc and tag_in_free are
+ // false. When tag_in_malloc = false and tag_in_free = true malloc needs to
+ // retag to 0.
+ if (InTaggableRegion(reinterpret_cast<uptr>(user_ptr)) &&
+ (flags()->tag_in_malloc || flags()->tag_in_free) &&
+ atomic_load_relaxed(&hwasan_allocator_tagging_enabled)) {
+ if (flags()->tag_in_malloc && malloc_bisect(stack, orig_size)) {
+ tag_t tag = t ? t->GenerateRandomTag() : kFallbackAllocTag;
+ uptr tag_size = orig_size ? orig_size : 1;
+ uptr full_granule_size = RoundDownTo(tag_size, kShadowAlignment);
+ user_ptr =
+ (void *)TagMemoryAligned((uptr)user_ptr, full_granule_size, tag);
+ if (full_granule_size != tag_size) {
+ u8 *short_granule =
+ reinterpret_cast<u8 *>(allocated) + full_granule_size;
+ TagMemoryAligned((uptr)short_granule, kShadowAlignment,
+ tag_size % kShadowAlignment);
+ short_granule[kShadowAlignment - 1] = tag;
+ }
+ } else {
+ user_ptr = (void *)TagMemoryAligned((uptr)user_ptr, size, 0);
+ }
+ }
+
+ Metadata *meta =
+ reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated));
+#if CAN_SANITIZE_LEAKS
+ meta->SetLsanTag(__lsan::DisabledInThisThread() ? __lsan::kIgnored
+ : __lsan::kDirectlyLeaked);
+#endif
+ meta->SetAllocated(StackDepotPut(*stack), orig_size);
+ RunMallocHooks(user_ptr, size);
+ return user_ptr;
+}
+
+static bool PointerAndMemoryTagsMatch(void *tagged_ptr) {
+ CHECK(tagged_ptr);
+ uptr tagged_uptr = reinterpret_cast<uptr>(tagged_ptr);
+ if (!InTaggableRegion(tagged_uptr))
+ return true;
+ tag_t mem_tag = *reinterpret_cast<tag_t *>(
+ MemToShadow(reinterpret_cast<uptr>(UntagPtr(tagged_ptr))));
+ return PossiblyShortTagMatches(mem_tag, tagged_uptr, 1);
+}
+
+static bool CheckInvalidFree(StackTrace *stack, void *untagged_ptr,
+ void *tagged_ptr) {
+ // This function can return true if halt_on_error is false.
+ if (!MemIsApp(reinterpret_cast<uptr>(untagged_ptr)) ||
+ !PointerAndMemoryTagsMatch(tagged_ptr)) {
+ ReportInvalidFree(stack, reinterpret_cast<uptr>(tagged_ptr));
+ return true;
+ }
+ return false;
+}
+
+static void HwasanDeallocate(StackTrace *stack, void *tagged_ptr) {
+ CHECK(tagged_ptr);
+ RunFreeHooks(tagged_ptr);
+
+ bool in_taggable_region =
+ InTaggableRegion(reinterpret_cast<uptr>(tagged_ptr));
+ void *untagged_ptr = in_taggable_region ? UntagPtr(tagged_ptr) : tagged_ptr;
+
+ if (CheckInvalidFree(stack, untagged_ptr, tagged_ptr))
+ return;
+
+ void *aligned_ptr = reinterpret_cast<void *>(
+ RoundDownTo(reinterpret_cast<uptr>(untagged_ptr), kShadowAlignment));
+ tag_t pointer_tag = GetTagFromPointer(reinterpret_cast<uptr>(tagged_ptr));
+ Metadata *meta =
+ reinterpret_cast<Metadata *>(allocator.GetMetaData(aligned_ptr));
+ if (!meta) {
+ ReportInvalidFree(stack, reinterpret_cast<uptr>(tagged_ptr));
+ return;
+ }
+ uptr orig_size = meta->GetRequestedSize();
+ u32 free_context_id = StackDepotPut(*stack);
+ u32 alloc_context_id = meta->GetAllocStackId();
+
+ // Check tail magic.
+ uptr tagged_size = TaggedSize(orig_size);
+ if (flags()->free_checks_tail_magic && orig_size &&
+ tagged_size != orig_size) {
+ uptr tail_size = tagged_size - orig_size - 1;
+ CHECK_LT(tail_size, kShadowAlignment);
+ void *tail_beg = reinterpret_cast<void *>(
+ reinterpret_cast<uptr>(aligned_ptr) + orig_size);
+ tag_t short_granule_memtag = *(reinterpret_cast<tag_t *>(
+ reinterpret_cast<uptr>(tail_beg) + tail_size));
+ if (tail_size &&
+ (internal_memcmp(tail_beg, tail_magic, tail_size) ||
+ (in_taggable_region && pointer_tag != short_granule_memtag)))
+ ReportTailOverwritten(stack, reinterpret_cast<uptr>(tagged_ptr),
+ orig_size, tail_magic);
+ }
+
+ // TODO(kstoimenov): consider meta->SetUnallocated(free_context_id).
+ meta->SetUnallocated();
+ // This memory will not be reused by anyone else, so we are free to keep it
+ // poisoned.
+ Thread *t = GetCurrentThread();
+ if (flags()->max_free_fill_size > 0) {
+ uptr fill_size =
+ Min(TaggedSize(orig_size), (uptr)flags()->max_free_fill_size);
+ internal_memset(aligned_ptr, flags()->free_fill_byte, fill_size);
+ }
+ if (in_taggable_region && flags()->tag_in_free && malloc_bisect(stack, 0) &&
+ atomic_load_relaxed(&hwasan_allocator_tagging_enabled)) {
+ // Always store full 8-bit tags on free to maximize UAF detection.
+ tag_t tag;
+ if (t) {
+ // Make sure we are not using a short granule tag as a poison tag. This
+ // would make us attempt to read the memory on a UaF.
+ // The tag can be zero if tagging is disabled on this thread.
+ do {
+ tag = t->GenerateRandomTag(/*num_bits=*/8);
+ } while (
+ UNLIKELY((tag < kShadowAlignment || tag == pointer_tag) && tag != 0));
+ } else {
+ static_assert(kFallbackFreeTag >= kShadowAlignment,
+ "fallback tag must not be a short granule tag.");
+ tag = kFallbackFreeTag;
+ }
+ TagMemoryAligned(reinterpret_cast<uptr>(aligned_ptr), TaggedSize(orig_size),
+ tag);
+ }
+ if (t) {
+ allocator.Deallocate(t->allocator_cache(), aligned_ptr);
+ if (auto *ha = t->heap_allocations())
+ ha->push({reinterpret_cast<uptr>(tagged_ptr), alloc_context_id,
+ free_context_id, static_cast<u32>(orig_size)});
+ } else {
+ SpinMutexLock l(&fallback_mutex);
+ AllocatorCache *cache = &fallback_allocator_cache;
+ allocator.Deallocate(cache, aligned_ptr);
+ }
+}
+
+static void *HwasanReallocate(StackTrace *stack, void *tagged_ptr_old,
+ uptr new_size, uptr alignment) {
+ void *untagged_ptr_old =
+ InTaggableRegion(reinterpret_cast<uptr>(tagged_ptr_old))
+ ? UntagPtr(tagged_ptr_old)
+ : tagged_ptr_old;
+ if (CheckInvalidFree(stack, untagged_ptr_old, tagged_ptr_old))
+ return nullptr;
+ void *tagged_ptr_new =
+ HwasanAllocate(stack, new_size, alignment, false /*zeroise*/);
+ if (tagged_ptr_old && tagged_ptr_new) {
+ Metadata *meta =
+ reinterpret_cast<Metadata *>(allocator.GetMetaData(untagged_ptr_old));
+ internal_memcpy(
+ UntagPtr(tagged_ptr_new), untagged_ptr_old,
+ Min(new_size, static_cast<uptr>(meta->GetRequestedSize())));
+ HwasanDeallocate(stack, tagged_ptr_old);
+ }
+ return tagged_ptr_new;
+}
+
+static void *HwasanCalloc(StackTrace *stack, uptr nmemb, uptr size) {
+ if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportCallocOverflow(nmemb, size, stack);
+ }
+ return HwasanAllocate(stack, nmemb * size, sizeof(u64), true);
+}
+
+HwasanChunkView FindHeapChunkByAddress(uptr address) {
+ if (!allocator.PointerIsMine(reinterpret_cast<void *>(address)))
+ return HwasanChunkView();
+ void *block = allocator.GetBlockBegin(reinterpret_cast<void*>(address));
+ if (!block)
+ return HwasanChunkView();
+ Metadata *metadata =
+ reinterpret_cast<Metadata*>(allocator.GetMetaData(block));
+ return HwasanChunkView(reinterpret_cast<uptr>(block), metadata);
+}
+
+static uptr AllocationSize(const void *tagged_ptr) {
+ const void *untagged_ptr = UntagPtr(tagged_ptr);
+ if (!untagged_ptr) return 0;
+ const void *beg = allocator.GetBlockBegin(untagged_ptr);
+ Metadata *b = (Metadata *)allocator.GetMetaData(untagged_ptr);
+ if (beg != untagged_ptr) return 0;
+ return b->GetRequestedSize();
+}
+
+void *hwasan_malloc(uptr size, StackTrace *stack) {
+ return SetErrnoOnNull(HwasanAllocate(stack, size, sizeof(u64), false));
+}
+
+void *hwasan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
+ return SetErrnoOnNull(HwasanCalloc(stack, nmemb, size));
+}
+
+void *hwasan_realloc(void *ptr, uptr size, StackTrace *stack) {
+ if (!ptr)
+ return SetErrnoOnNull(HwasanAllocate(stack, size, sizeof(u64), false));
+ if (size == 0) {
+ HwasanDeallocate(stack, ptr);
+ return nullptr;
+ }
+ return SetErrnoOnNull(HwasanReallocate(stack, ptr, size, sizeof(u64)));
+}
+
+void *hwasan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack) {
+ if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+ errno = errno_ENOMEM;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportReallocArrayOverflow(nmemb, size, stack);
+ }
+ return hwasan_realloc(ptr, nmemb * size, stack);
+}
+
+void *hwasan_valloc(uptr size, StackTrace *stack) {
+ return SetErrnoOnNull(
+ HwasanAllocate(stack, size, GetPageSizeCached(), false));
+}
+
+void *hwasan_pvalloc(uptr size, StackTrace *stack) {
+ uptr PageSize = GetPageSizeCached();
+ if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) {
+ errno = errno_ENOMEM;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportPvallocOverflow(size, stack);
+ }
+ // pvalloc(0) should allocate one page.
+ size = size ? RoundUpTo(size, PageSize) : PageSize;
+ return SetErrnoOnNull(HwasanAllocate(stack, size, PageSize, false));
+}
+
+void *hwasan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack) {
+ if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAlignedAllocAlignment(size, alignment, stack);
+ }
+ return SetErrnoOnNull(HwasanAllocate(stack, size, alignment, false));
+}
+
+void *hwasan_memalign(uptr alignment, uptr size, StackTrace *stack) {
+ if (UNLIKELY(!IsPowerOfTwo(alignment))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAllocationAlignment(alignment, stack);
+ }
+ return SetErrnoOnNull(HwasanAllocate(stack, size, alignment, false));
+}
+
+int hwasan_posix_memalign(void **memptr, uptr alignment, uptr size,
+ StackTrace *stack) {
+ if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
+ if (AllocatorMayReturnNull())
+ return errno_EINVAL;
+ ReportInvalidPosixMemalignAlignment(alignment, stack);
+ }
+ void *ptr = HwasanAllocate(stack, size, alignment, false);
+ if (UNLIKELY(!ptr))
+ // OOM error is already taken care of by HwasanAllocate.
+ return errno_ENOMEM;
+ CHECK(IsAligned((uptr)ptr, alignment));
+ *memptr = ptr;
+ return 0;
+}
+
+void hwasan_free(void *ptr, StackTrace *stack) {
+ return HwasanDeallocate(stack, ptr);
+}
+
+} // namespace __hwasan
+
+// --- Implementation of LSan-specific functions --- {{{1
+namespace __lsan {
+
+void LockAllocator() {
+ __hwasan::HwasanAllocatorLock();
+}
+
+void UnlockAllocator() {
+ __hwasan::HwasanAllocatorUnlock();
+}
+
+void GetAllocatorGlobalRange(uptr *begin, uptr *end) {
+ *begin = (uptr)&__hwasan::allocator;
+ *end = *begin + sizeof(__hwasan::allocator);
+}
+
+uptr PointsIntoChunk(void *p) {
+ p = __hwasan::InTaggableRegion(reinterpret_cast<uptr>(p)) ? UntagPtr(p) : p;
+ uptr addr = reinterpret_cast<uptr>(p);
+ uptr chunk =
+ reinterpret_cast<uptr>(__hwasan::allocator.GetBlockBeginFastLocked(p));
+ if (!chunk)
+ return 0;
+ __hwasan::Metadata *metadata = reinterpret_cast<__hwasan::Metadata *>(
+ __hwasan::allocator.GetMetaData(reinterpret_cast<void *>(chunk)));
+ if (!metadata || !metadata->IsAllocated())
+ return 0;
+ if (addr < chunk + metadata->GetRequestedSize())
+ return chunk;
+ if (IsSpecialCaseOfOperatorNew0(chunk, metadata->GetRequestedSize(), addr))
+ return chunk;
+ return 0;
+}
+
+uptr GetUserBegin(uptr chunk) {
+ if (__hwasan::InTaggableRegion(chunk))
+ CHECK_EQ(UntagAddr(chunk), chunk);
+ void *block = __hwasan::allocator.GetBlockBeginFastLocked(
+ reinterpret_cast<void *>(chunk));
+ if (!block)
+ return 0;
+ __hwasan::Metadata *metadata = reinterpret_cast<__hwasan::Metadata *>(
+ __hwasan::allocator.GetMetaData(block));
+ if (!metadata || !metadata->IsAllocated())
+ return 0;
+
+ return reinterpret_cast<uptr>(block);
+}
+
+LsanMetadata::LsanMetadata(uptr chunk) {
+ if (__hwasan::InTaggableRegion(chunk))
+ CHECK_EQ(UntagAddr(chunk), chunk);
+ metadata_ =
+ chunk ? __hwasan::allocator.GetMetaData(reinterpret_cast<void *>(chunk))
+ : nullptr;
+}
+
+bool LsanMetadata::allocated() const {
+ if (!metadata_)
+ return false;
+ __hwasan::Metadata *m = reinterpret_cast<__hwasan::Metadata *>(metadata_);
+ return m->IsAllocated();
+}
+
+ChunkTag LsanMetadata::tag() const {
+ __hwasan::Metadata *m = reinterpret_cast<__hwasan::Metadata *>(metadata_);
+ return m->GetLsanTag();
+}
+
+void LsanMetadata::set_tag(ChunkTag value) {
+ __hwasan::Metadata *m = reinterpret_cast<__hwasan::Metadata *>(metadata_);
+ m->SetLsanTag(value);
+}
+
+uptr LsanMetadata::requested_size() const {
+ __hwasan::Metadata *m = reinterpret_cast<__hwasan::Metadata *>(metadata_);
+ return m->GetRequestedSize();
+}
+
+u32 LsanMetadata::stack_trace_id() const {
+ __hwasan::Metadata *m = reinterpret_cast<__hwasan::Metadata *>(metadata_);
+ return m->GetAllocStackId();
+}
+
+void ForEachChunk(ForEachChunkCallback callback, void *arg) {
+ __hwasan::allocator.ForEachChunk(callback, arg);
+}
+
+IgnoreObjectResult IgnoreObjectLocked(const void *p) {
+ p = __hwasan::InTaggableRegion(reinterpret_cast<uptr>(p)) ? UntagPtr(p) : p;
+ uptr addr = reinterpret_cast<uptr>(p);
+ uptr chunk =
+ reinterpret_cast<uptr>(__hwasan::allocator.GetBlockBeginFastLocked(p));
+ if (!chunk)
+ return kIgnoreObjectInvalid;
+ __hwasan::Metadata *metadata = reinterpret_cast<__hwasan::Metadata *>(
+ __hwasan::allocator.GetMetaData(reinterpret_cast<void *>(chunk)));
+ if (!metadata || !metadata->IsAllocated())
+ return kIgnoreObjectInvalid;
+ if (addr >= chunk + metadata->GetRequestedSize())
+ return kIgnoreObjectInvalid;
+ if (metadata->GetLsanTag() == kIgnored)
+ return kIgnoreObjectAlreadyIgnored;
+
+ metadata->SetLsanTag(kIgnored);
+ return kIgnoreObjectSuccess;
+}
+
+} // namespace __lsan
+
+using namespace __hwasan;
+
+void __hwasan_enable_allocator_tagging() {
+ atomic_store_relaxed(&hwasan_allocator_tagging_enabled, 1);
+}
+
+void __hwasan_disable_allocator_tagging() {
+ atomic_store_relaxed(&hwasan_allocator_tagging_enabled, 0);
+}
+
+uptr __sanitizer_get_current_allocated_bytes() {
+ uptr stats[AllocatorStatCount];
+ allocator.GetStats(stats);
+ return stats[AllocatorStatAllocated];
+}
+
+uptr __sanitizer_get_heap_size() {
+ uptr stats[AllocatorStatCount];
+ allocator.GetStats(stats);
+ return stats[AllocatorStatMapped];
+}
+
+uptr __sanitizer_get_free_bytes() { return 1; }
+
+uptr __sanitizer_get_unmapped_bytes() { return 1; }
+
+uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; }
+
+int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; }
+
+uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); }
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_allocator.h b/contrib/libs/clang16-rt/lib/hwasan/hwasan_allocator.h
new file mode 100644
index 00000000000..67982cad254
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_allocator.h
@@ -0,0 +1,135 @@
+//===-- hwasan_allocator.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_ALLOCATOR_H
+#define HWASAN_ALLOCATOR_H
+
+#include "hwasan.h"
+#include "hwasan_interface_internal.h"
+#include "hwasan_mapping.h"
+#include "hwasan_poisoning.h"
+#include "lsan/lsan_common.h"
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_checks.h"
+#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_ring_buffer.h"
+
+#if !defined(__aarch64__) && !defined(__x86_64__) && !(SANITIZER_RISCV64)
+# error Unsupported platform
+#endif
+
+namespace __hwasan {
+
+struct Metadata {
+ private:
+ atomic_uint64_t alloc_context_id;
+ u32 requested_size_low;
+ u16 requested_size_high;
+ atomic_uint8_t chunk_state;
+ u8 lsan_tag;
+
+ public:
+ inline void SetAllocated(u32 stack, u64 size);
+ inline void SetUnallocated();
+
+ inline bool IsAllocated() const;
+ inline u64 GetRequestedSize() const;
+ inline u32 GetAllocStackId() const;
+ inline void SetLsanTag(__lsan::ChunkTag tag);
+ inline __lsan::ChunkTag GetLsanTag() const;
+};
+static_assert(sizeof(Metadata) == 16);
+
+struct HwasanMapUnmapCallback {
+ void OnMap(uptr p, uptr size) const { UpdateMemoryUsage(); }
+ void OnUnmap(uptr p, uptr size) const {
+ // We are about to unmap a chunk of user memory.
+ // It can return as user-requested mmap() or another thread stack.
+ // Make it accessible with zero-tagged pointer.
+ TagMemory(p, size, 0);
+ }
+};
+
+static const uptr kMaxAllowedMallocSize = 1UL << 40; // 1T
+
+struct AP64 {
+ static const uptr kSpaceBeg = ~0ULL;
+
+#if defined(HWASAN_ALIASING_MODE)
+ static const uptr kSpaceSize = 1ULL << kAddressTagShift;
+#else
+ static const uptr kSpaceSize = 0x2000000000ULL;
+#endif
+ static const uptr kMetadataSize = sizeof(Metadata);
+ typedef __sanitizer::VeryDenseSizeClassMap SizeClassMap;
+ using AddressSpaceView = LocalAddressSpaceView;
+ typedef HwasanMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+};
+typedef SizeClassAllocator64<AP64> PrimaryAllocator;
+typedef CombinedAllocator<PrimaryAllocator> Allocator;
+typedef Allocator::AllocatorCache AllocatorCache;
+
+void AllocatorSwallowThreadLocalCache(AllocatorCache *cache);
+
+class HwasanChunkView {
+ public:
+ HwasanChunkView() : block_(0), metadata_(nullptr) {}
+ HwasanChunkView(uptr block, Metadata *metadata)
+ : block_(block), metadata_(metadata) {}
+ bool IsAllocated() const; // Checks if the memory is currently allocated
+ uptr Beg() const; // First byte of user memory
+ uptr End() const; // Last byte of user memory
+ uptr UsedSize() const; // Size requested by the user
+ uptr ActualSize() const; // Size allocated by the allocator.
+ u32 GetAllocStackId() const;
+ bool FromSmallHeap() const;
+ bool AddrIsInside(uptr addr) const;
+
+ private:
+ friend class __lsan::LsanMetadata;
+ uptr block_;
+ Metadata *const metadata_;
+};
+
+HwasanChunkView FindHeapChunkByAddress(uptr address);
+
+// Information about one (de)allocation that happened in the past.
+// These are recorded in a thread-local ring buffer.
+// TODO: this is currently 24 bytes (20 bytes + alignment).
+// Compress it to 16 bytes or extend it to be more useful.
+struct HeapAllocationRecord {
+ uptr tagged_addr;
+ u32 alloc_context_id;
+ u32 free_context_id;
+ u32 requested_size;
+};
+
+typedef RingBuffer<HeapAllocationRecord> HeapAllocationsRingBuffer;
+
+void GetAllocatorStats(AllocatorStatCounters s);
+
+inline bool InTaggableRegion(uptr addr) {
+#if defined(HWASAN_ALIASING_MODE)
+ // Aliases are mapped next to shadow so that the upper bits match the shadow
+ // base.
+ return (addr >> kTaggableRegionCheckShift) ==
+ (GetShadowOffset() >> kTaggableRegionCheckShift);
+#endif
+ return true;
+}
+
+} // namespace __hwasan
+
+#endif // HWASAN_ALLOCATOR_H
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_checks.h b/contrib/libs/clang16-rt/lib/hwasan/hwasan_checks.h
new file mode 100644
index 00000000000..b0b37d7a2e2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_checks.h
@@ -0,0 +1,144 @@
+//===-- hwasan_checks.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_CHECKS_H
+#define HWASAN_CHECKS_H
+
+#include "hwasan_allocator.h"
+#include "hwasan_mapping.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace __hwasan {
+template <unsigned X>
+__attribute__((always_inline)) static void SigTrap(uptr p) {
+#if defined(__aarch64__)
+ (void)p;
+ // 0x900 is added to do not interfere with the kernel use of lower values of
+ // brk immediate.
+ register uptr x0 asm("x0") = p;
+ asm("brk %1\n\t" ::"r"(x0), "n"(0x900 + X));
+#elif defined(__x86_64__)
+ // INT3 + NOP DWORD ptr [EAX + X] to pass X to our signal handler, 5 bytes
+ // total. The pointer is passed via rdi.
+ // 0x40 is added as a safeguard, to help distinguish our trap from others and
+ // to avoid 0 offsets in the command (otherwise it'll be reduced to a
+ // different nop command, the three bytes one).
+ asm volatile(
+ "int3\n"
+ "nopl %c0(%%rax)\n" ::"n"(0x40 + X),
+ "D"(p));
+#elif SANITIZER_RISCV64
+ // Put pointer into x10
+ // addiw contains immediate of 0x40 + X, where 0x40 is magic number and X
+ // encodes access size
+ register uptr x10 asm("x10") = p;
+ asm volatile(
+ "ebreak\n"
+ "addiw x0, x0, %1\n" ::"r"(x10),
+ "I"(0x40 + X));
+#else
+ // FIXME: not always sigill.
+ __builtin_trap();
+#endif
+ // __builtin_unreachable();
+}
+
+// Version with access size which is not power of 2
+template <unsigned X>
+__attribute__((always_inline)) static void SigTrap(uptr p, uptr size) {
+#if defined(__aarch64__)
+ register uptr x0 asm("x0") = p;
+ register uptr x1 asm("x1") = size;
+ asm("brk %2\n\t" ::"r"(x0), "r"(x1), "n"(0x900 + X));
+#elif defined(__x86_64__)
+ // Size is stored in rsi.
+ asm volatile(
+ "int3\n"
+ "nopl %c0(%%rax)\n" ::"n"(0x40 + X),
+ "D"(p), "S"(size));
+#elif SANITIZER_RISCV64
+ // Put access size into x11
+ register uptr x10 asm("x10") = p;
+ register uptr x11 asm("x11") = size;
+ asm volatile(
+ "ebreak\n"
+ "addiw x0, x0, %2\n" ::"r"(x10),
+ "r"(x11), "I"(0x40 + X));
+#else
+ __builtin_trap();
+#endif
+ // __builtin_unreachable();
+}
+
+__attribute__((always_inline, nodebug)) static bool PossiblyShortTagMatches(
+ tag_t mem_tag, uptr ptr, uptr sz) {
+ tag_t ptr_tag = GetTagFromPointer(ptr);
+ if (ptr_tag == mem_tag)
+ return true;
+ if (mem_tag >= kShadowAlignment)
+ return false;
+ if ((ptr & (kShadowAlignment - 1)) + sz > mem_tag)
+ return false;
+#if !defined(__aarch64__) && !(SANITIZER_RISCV64)
+ ptr = UntagAddr(ptr);
+#endif
+ return *(u8 *)(ptr | (kShadowAlignment - 1)) == ptr_tag;
+}
+
+enum class ErrorAction { Abort, Recover };
+enum class AccessType { Load, Store };
+
+template <ErrorAction EA, AccessType AT, unsigned LogSize>
+__attribute__((always_inline, nodebug)) static void CheckAddress(uptr p) {
+ if (!InTaggableRegion(p))
+ return;
+ uptr ptr_raw = p & ~kAddressTagMask;
+ tag_t mem_tag = *(tag_t *)MemToShadow(ptr_raw);
+ if (UNLIKELY(!PossiblyShortTagMatches(mem_tag, p, 1 << LogSize))) {
+ SigTrap<0x20 * (EA == ErrorAction::Recover) +
+ 0x10 * (AT == AccessType::Store) + LogSize>(p);
+ if (EA == ErrorAction::Abort)
+ __builtin_unreachable();
+ }
+}
+
+template <ErrorAction EA, AccessType AT>
+__attribute__((always_inline, nodebug)) static void CheckAddressSized(uptr p,
+ uptr sz) {
+ if (sz == 0 || !InTaggableRegion(p))
+ return;
+ tag_t ptr_tag = GetTagFromPointer(p);
+ uptr ptr_raw = p & ~kAddressTagMask;
+ tag_t *shadow_first = (tag_t *)MemToShadow(ptr_raw);
+ tag_t *shadow_last = (tag_t *)MemToShadow(ptr_raw + sz);
+ for (tag_t *t = shadow_first; t < shadow_last; ++t)
+ if (UNLIKELY(ptr_tag != *t)) {
+ SigTrap<0x20 * (EA == ErrorAction::Recover) +
+ 0x10 * (AT == AccessType::Store) + 0xf>(p, sz);
+ if (EA == ErrorAction::Abort)
+ __builtin_unreachable();
+ }
+ uptr end = p + sz;
+ uptr tail_sz = end & 0xf;
+ if (UNLIKELY(tail_sz != 0 &&
+ !PossiblyShortTagMatches(
+ *shadow_last, end & ~(kShadowAlignment - 1), tail_sz))) {
+ SigTrap<0x20 * (EA == ErrorAction::Recover) +
+ 0x10 * (AT == AccessType::Store) + 0xf>(p, sz);
+ if (EA == ErrorAction::Abort)
+ __builtin_unreachable();
+ }
+}
+
+} // end namespace __hwasan
+
+#endif // HWASAN_CHECKS_H
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_dynamic_shadow.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_dynamic_shadow.cpp
new file mode 100644
index 00000000000..7642ba6c0bf
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_dynamic_shadow.cpp
@@ -0,0 +1,143 @@
+//===-- hwasan_dynamic_shadow.cpp -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is a part of HWAddressSanitizer. It reserves dynamic shadow memory
+/// region and handles ifunc resolver case, when necessary.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hwasan_dynamic_shadow.h"
+
+#include <elf.h>
+#include <link.h>
+
+#include "hwasan.h"
+#include "hwasan_mapping.h"
+#include "hwasan_thread_list.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_posix.h"
+
+// The code in this file needs to run in an unrelocated binary. It should not
+// access any external symbol, including its own non-hidden globals.
+
+#if SANITIZER_ANDROID
+extern "C" {
+
+INTERFACE_ATTRIBUTE void __hwasan_shadow();
+decltype(__hwasan_shadow)* __hwasan_premap_shadow();
+
+} // extern "C"
+
+namespace __hwasan {
+
+// Conservative upper limit.
+static uptr PremapShadowSize() {
+ return RoundUpTo(GetMaxVirtualAddress() >> kShadowScale,
+ GetMmapGranularity());
+}
+
+static uptr PremapShadow() {
+ return MapDynamicShadow(PremapShadowSize(), kShadowScale,
+ kShadowBaseAlignment, kHighMemEnd);
+}
+
+static bool IsPremapShadowAvailable() {
+ const uptr shadow = reinterpret_cast<uptr>(&__hwasan_shadow);
+ const uptr resolver = reinterpret_cast<uptr>(&__hwasan_premap_shadow);
+ // shadow == resolver is how Android KitKat and older handles ifunc.
+ // shadow == 0 just in case.
+ return shadow != 0 && shadow != resolver;
+}
+
+static uptr FindPremappedShadowStart(uptr shadow_size_bytes) {
+ const uptr granularity = GetMmapGranularity();
+ const uptr shadow_start = reinterpret_cast<uptr>(&__hwasan_shadow);
+ const uptr premap_shadow_size = PremapShadowSize();
+ const uptr shadow_size = RoundUpTo(shadow_size_bytes, granularity);
+
+ // We may have mapped too much. Release extra memory.
+ UnmapFromTo(shadow_start + shadow_size, shadow_start + premap_shadow_size);
+ return shadow_start;
+}
+
+} // namespace __hwasan
+
+extern "C" {
+
+decltype(__hwasan_shadow)* __hwasan_premap_shadow() {
+ // The resolver might be called multiple times. Map the shadow just once.
+ static __sanitizer::uptr shadow = 0;
+ if (!shadow)
+ shadow = __hwasan::PremapShadow();
+ return reinterpret_cast<decltype(__hwasan_shadow)*>(shadow);
+}
+
+// __hwasan_shadow is a "function" that has the same address as the first byte
+// of the shadow mapping.
+INTERFACE_ATTRIBUTE __attribute__((ifunc("__hwasan_premap_shadow")))
+void __hwasan_shadow();
+
+extern __attribute((weak, visibility("hidden"))) ElfW(Rela) __rela_iplt_start[],
+ __rela_iplt_end[];
+
+} // extern "C"
+
+namespace __hwasan {
+
+void InitShadowGOT() {
+ // Call the ifunc resolver for __hwasan_shadow and fill in its GOT entry. This
+ // needs to be done before other ifunc resolvers (which are handled by libc)
+ // because a resolver might read __hwasan_shadow.
+ typedef ElfW(Addr) (*ifunc_resolver_t)(void);
+ for (ElfW(Rela) *r = __rela_iplt_start; r != __rela_iplt_end; ++r) {
+ ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset);
+ ElfW(Addr) resolver = r->r_addend;
+ if (resolver == reinterpret_cast<ElfW(Addr)>(&__hwasan_premap_shadow)) {
+ *offset = reinterpret_cast<ifunc_resolver_t>(resolver)();
+ break;
+ }
+ }
+}
+
+uptr FindDynamicShadowStart(uptr shadow_size_bytes) {
+ if (IsPremapShadowAvailable())
+ return FindPremappedShadowStart(shadow_size_bytes);
+ return MapDynamicShadow(shadow_size_bytes, kShadowScale, kShadowBaseAlignment,
+ kHighMemEnd);
+}
+
+} // namespace __hwasan
+
+#elif SANITIZER_FUCHSIA
+
+namespace __hwasan {
+
+void InitShadowGOT() {}
+
+} // namespace __hwasan
+
+#else
+namespace __hwasan {
+
+void InitShadowGOT() {}
+
+uptr FindDynamicShadowStart(uptr shadow_size_bytes) {
+# if defined(HWASAN_ALIASING_MODE)
+ constexpr uptr kAliasSize = 1ULL << kAddressTagShift;
+ constexpr uptr kNumAliases = 1ULL << kTagBits;
+ return MapDynamicShadowAndAliases(shadow_size_bytes, kAliasSize, kNumAliases,
+ RingBufferSize());
+# endif
+ return MapDynamicShadow(shadow_size_bytes, kShadowScale, kShadowBaseAlignment,
+ kHighMemEnd);
+}
+
+} // namespace __hwasan
+
+#endif // SANITIZER_ANDROID
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_dynamic_shadow.h b/contrib/libs/clang16-rt/lib/hwasan/hwasan_dynamic_shadow.h
new file mode 100644
index 00000000000..3c2e7c716a3
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_dynamic_shadow.h
@@ -0,0 +1,27 @@
+//===-- hwasan_dynamic_shadow.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is a part of HWAddressSanitizer. It reserves dynamic shadow memory
+/// region.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_PREMAP_SHADOW_H
+#define HWASAN_PREMAP_SHADOW_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __hwasan {
+
+uptr FindDynamicShadowStart(uptr shadow_size_bytes);
+void InitShadowGOT();
+
+} // namespace __hwasan
+
+#endif // HWASAN_PREMAP_SHADOW_H
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_exceptions.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_exceptions.cpp
new file mode 100644
index 00000000000..c9968a5e360
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_exceptions.cpp
@@ -0,0 +1,69 @@
+//===-- hwasan_exceptions.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// HWAddressSanitizer runtime.
+//===----------------------------------------------------------------------===//
+
+#include "hwasan_poisoning.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+#include <unwind.h>
+
+using namespace __hwasan;
+using namespace __sanitizer;
+
+typedef _Unwind_Reason_Code PersonalityFn(int version, _Unwind_Action actions,
+ uint64_t exception_class,
+ _Unwind_Exception* unwind_exception,
+ _Unwind_Context* context);
+
+// Pointers to the _Unwind_GetGR and _Unwind_GetCFA functions are passed in
+// instead of being called directly. This is to handle cases where the unwinder
+// is statically linked and the sanitizer runtime and the program are linked
+// against different unwinders. The _Unwind_Context data structure is opaque so
+// it may be incompatible between unwinders.
+typedef uintptr_t GetGRFn(_Unwind_Context* context, int index);
+typedef uintptr_t GetCFAFn(_Unwind_Context* context);
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE _Unwind_Reason_Code
+__hwasan_personality_wrapper(int version, _Unwind_Action actions,
+ uint64_t exception_class,
+ _Unwind_Exception* unwind_exception,
+ _Unwind_Context* context,
+ PersonalityFn* real_personality, GetGRFn* get_gr,
+ GetCFAFn* get_cfa) {
+ _Unwind_Reason_Code rc;
+ if (real_personality)
+ rc = real_personality(version, actions, exception_class, unwind_exception,
+ context);
+ else
+ rc = _URC_CONTINUE_UNWIND;
+
+ // We only untag frames without a landing pad because landing pads are
+ // responsible for untagging the stack themselves if they resume.
+ //
+ // Here we assume that the frame record appears after any locals. This is not
+ // required by AAPCS but is a requirement for HWASAN instrumented functions.
+ if ((actions & _UA_CLEANUP_PHASE) && rc == _URC_CONTINUE_UNWIND) {
+#if defined(__x86_64__)
+ uptr fp = get_gr(context, 6); // rbp
+#elif defined(__aarch64__)
+ uptr fp = get_gr(context, 29); // x29
+#elif SANITIZER_RISCV64
+ uptr fp = get_gr(context, 8); // x8
+#else
+#error Unsupported architecture
+#endif
+ uptr sp = get_cfa(context);
+ TagMemory(sp, fp - sp, 0);
+ }
+
+ return rc;
+}
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_flags.h b/contrib/libs/clang16-rt/lib/hwasan/hwasan_flags.h
new file mode 100644
index 00000000000..b17750158d0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_flags.h
@@ -0,0 +1,31 @@
+//===-- hwasan_flags.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+//===----------------------------------------------------------------------===//
+#ifndef HWASAN_FLAGS_H
+#define HWASAN_FLAGS_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __hwasan {
+
+struct Flags {
+#define HWASAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "hwasan_flags.inc"
+#undef HWASAN_FLAG
+
+ void SetDefaults();
+};
+
+Flags *flags();
+
+} // namespace __hwasan
+
+#endif // HWASAN_FLAGS_H
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_flags.inc b/contrib/libs/clang16-rt/lib/hwasan/hwasan_flags.inc
new file mode 100644
index 00000000000..4a226ee2ab8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_flags.inc
@@ -0,0 +1,83 @@
+//===-- hwasan_flags.inc ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Hwasan runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef HWASAN_FLAG
+# error "Define HWASAN_FLAG prior to including this file!"
+#endif
+
+// HWASAN_FLAG(Type, Name, DefaultValue, Description)
+// See COMMON_FLAG in sanitizer_flags.inc for more details.
+
+HWASAN_FLAG(bool, verbose_threads, false,
+ "inform on thread creation/destruction")
+HWASAN_FLAG(bool, tag_in_malloc, true, "")
+HWASAN_FLAG(bool, tag_in_free, true, "")
+HWASAN_FLAG(bool, print_stats, false, "")
+HWASAN_FLAG(bool, halt_on_error, true, "")
+HWASAN_FLAG(bool, atexit, false, "")
+
+// Test only flag to disable malloc/realloc/free memory tagging on startup.
+// Tagging can be reenabled with __hwasan_enable_allocator_tagging().
+HWASAN_FLAG(bool, disable_allocator_tagging, false, "")
+
+// If false, use simple increment of a thread local counter to generate new
+// tags.
+HWASAN_FLAG(bool, random_tags, true, "")
+
+HWASAN_FLAG(
+ int, max_malloc_fill_size, 0,
+ "HWASan allocator flag. max_malloc_fill_size is the maximal amount of "
+ "bytes that will be filled with malloc_fill_byte on malloc.")
+
+HWASAN_FLAG(bool, free_checks_tail_magic, 1,
+ "If set, free() will check the magic values "
+ "after the allocated object "
+ "if the allocation size is not a divident of the granule size")
+HWASAN_FLAG(
+ int, max_free_fill_size, 0,
+ "HWASan allocator flag. max_free_fill_size is the maximal amount of "
+ "bytes that will be filled with free_fill_byte during free.")
+HWASAN_FLAG(int, malloc_fill_byte, 0xbe,
+ "Value used to fill the newly allocated memory.")
+HWASAN_FLAG(int, free_fill_byte, 0x55,
+ "Value used to fill deallocated memory.")
+HWASAN_FLAG(int, heap_history_size, 1023,
+ "The number of heap (de)allocations remembered per thread. "
+ "Affects the quality of heap-related reports, but not the ability "
+ "to find bugs.")
+HWASAN_FLAG(bool, export_memory_stats, true,
+ "Export up-to-date memory stats through /proc")
+HWASAN_FLAG(int, stack_history_size, 1024,
+ "The number of stack frames remembered per thread. "
+ "Affects the quality of stack-related reports, but not the ability "
+ "to find bugs.")
+
+// Malloc / free bisection. Only tag malloc and free calls when a hash of
+// allocation size and stack trace is between malloc_bisect_left and
+// malloc_bisect_right (both inclusive). [0, 0] range is special and disables
+// bisection (i.e. everything is tagged). Once the range is narrowed down
+// enough, use malloc_bisect_dump to see interesting allocations.
+HWASAN_FLAG(uptr, malloc_bisect_left, 0,
+ "Left bound of malloc bisection, inclusive.")
+HWASAN_FLAG(uptr, malloc_bisect_right, 0,
+ "Right bound of malloc bisection, inclusive.")
+HWASAN_FLAG(bool, malloc_bisect_dump, false,
+ "Print all allocations within [malloc_bisect_left, "
+ "malloc_bisect_right] range ")
+
+
+// Exit if we fail to enable the AArch64 kernel ABI relaxation which allows
+// tagged pointers in syscalls. This is the default, but being able to disable
+// that behaviour is useful for running the testsuite on more platforms (the
+// testsuite can run since we manually ensure any pointer arguments to syscalls
+// are untagged before the call.
+HWASAN_FLAG(bool, fail_without_syscall_abi, true,
+ "Exit if fail to request relaxed syscall ABI.")
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_fuchsia.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_fuchsia.cpp
new file mode 100644
index 00000000000..cc0e4554815
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_fuchsia.cpp
@@ -0,0 +1,241 @@
+//===-- hwasan_fuchsia.cpp --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is a part of HWAddressSanitizer and contains Fuchsia-specific
+/// code.
+///
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_fuchsia.h"
+#if SANITIZER_FUCHSIA
+
+#error #include <zircon/features.h>
+#error #include <zircon/syscalls.h>
+
+#include "hwasan.h"
+#include "hwasan_interface_internal.h"
+#include "hwasan_report.h"
+#include "hwasan_thread.h"
+#include "hwasan_thread_list.h"
+
+// This TLS variable contains the location of the stack ring buffer and can be
+// used to always find the hwasan thread object associated with the current
+// running thread.
+[[gnu::tls_model("initial-exec")]]
+SANITIZER_INTERFACE_ATTRIBUTE
+THREADLOCAL uptr __hwasan_tls;
+
+namespace __hwasan {
+
+bool InitShadow() {
+ __sanitizer::InitShadowBounds();
+ CHECK_NE(__sanitizer::ShadowBounds.shadow_limit, 0);
+
+ // These variables are used by MemIsShadow for asserting we have a correct
+ // shadow address. On Fuchsia, we only have one region of shadow, so the
+ // bounds of Low shadow can be zero while High shadow represents the true
+ // bounds. Note that these are inclusive ranges.
+ kLowShadowStart = 0;
+ kLowShadowEnd = 0;
+ kHighShadowStart = __sanitizer::ShadowBounds.shadow_base;
+ kHighShadowEnd = __sanitizer::ShadowBounds.shadow_limit - 1;
+
+ return true;
+}
+
+bool MemIsApp(uptr p) {
+ CHECK(GetTagFromPointer(p) == 0);
+ return __sanitizer::ShadowBounds.shadow_limit <= p &&
+ p <= (__sanitizer::ShadowBounds.memory_limit - 1);
+}
+
+// These are known parameters passed to the hwasan runtime on thread creation.
+struct Thread::InitState {
+ uptr stack_bottom, stack_top;
+};
+
+static void FinishThreadInitialization(Thread *thread);
+
+void InitThreads() {
+ // This is the minimal alignment needed for the storage where hwasan threads
+ // and their stack ring buffers are placed. This alignment is necessary so the
+ // stack ring buffer can perform a simple calculation to get the next element
+ // in the RB. The instructions for this calculation are emitted by the
+ // compiler. (Full explanation in hwasan_thread_list.h.)
+ uptr alloc_size = UINT64_C(1) << kShadowBaseAlignment;
+ uptr thread_start = reinterpret_cast<uptr>(
+ MmapAlignedOrDieOnFatalError(alloc_size, alloc_size, __func__));
+
+ InitThreadList(thread_start, alloc_size);
+
+ // Create the hwasan thread object for the current (main) thread. Stack info
+ // for this thread is known from information passed via
+ // __sanitizer_startup_hook.
+ const Thread::InitState state = {
+ .stack_bottom = __sanitizer::MainThreadStackBase,
+ .stack_top =
+ __sanitizer::MainThreadStackBase + __sanitizer::MainThreadStackSize,
+ };
+ FinishThreadInitialization(hwasanThreadList().CreateCurrentThread(&state));
+}
+
+uptr *GetCurrentThreadLongPtr() { return &__hwasan_tls; }
+
+// This is called from the parent thread before the new thread is created. Here
+// we can propagate known info like the stack bounds to Thread::Init before
+// jumping into the thread. We cannot initialize the stack ring buffer yet since
+// we have not entered the new thread.
+static void *BeforeThreadCreateHook(uptr user_id, bool detached,
+ const char *name, uptr stack_bottom,
+ uptr stack_size) {
+ const Thread::InitState state = {
+ .stack_bottom = stack_bottom,
+ .stack_top = stack_bottom + stack_size,
+ };
+ return hwasanThreadList().CreateCurrentThread(&state);
+}
+
+// This sets the stack top and bottom according to the InitState passed to
+// CreateCurrentThread above.
+void Thread::InitStackAndTls(const InitState *state) {
+ CHECK_NE(state->stack_bottom, 0);
+ CHECK_NE(state->stack_top, 0);
+ stack_bottom_ = state->stack_bottom;
+ stack_top_ = state->stack_top;
+ tls_end_ = tls_begin_ = 0;
+}
+
+// This is called after creating a new thread with the pointer returned by
+// BeforeThreadCreateHook. We are still in the creating thread and should check
+// if it was actually created correctly.
+static void ThreadCreateHook(void *hook, bool aborted) {
+ Thread *thread = static_cast<Thread *>(hook);
+ if (!aborted) {
+ // The thread was created successfully.
+ // ThreadStartHook can already be running in the new thread.
+ } else {
+ // The thread wasn't created after all.
+ // Clean up everything we set up in BeforeThreadCreateHook.
+ atomic_signal_fence(memory_order_seq_cst);
+ hwasanThreadList().ReleaseThread(thread);
+ }
+}
+
+// This is called in the newly-created thread before it runs anything else,
+// with the pointer returned by BeforeThreadCreateHook (above). Here we can
+// setup the stack ring buffer.
+static void ThreadStartHook(void *hook, thrd_t self) {
+ Thread *thread = static_cast<Thread *>(hook);
+ FinishThreadInitialization(thread);
+ thread->EnsureRandomStateInited();
+}
+
+// This is the function that sets up the stack ring buffer and enables us to use
+// GetCurrentThread. This function should only be called while IN the thread
+// that we want to create the hwasan thread object for so __hwasan_tls can be
+// properly referenced.
+static void FinishThreadInitialization(Thread *thread) {
+ CHECK_NE(thread, nullptr);
+
+ // The ring buffer is located immediately before the thread object.
+ uptr stack_buffer_size = hwasanThreadList().GetRingBufferSize();
+ uptr stack_buffer_start = reinterpret_cast<uptr>(thread) - stack_buffer_size;
+ thread->InitStackRingBuffer(stack_buffer_start, stack_buffer_size);
+}
+
+static void ThreadExitHook(void *hook, thrd_t self) {
+ Thread *thread = static_cast<Thread *>(hook);
+ atomic_signal_fence(memory_order_seq_cst);
+ hwasanThreadList().ReleaseThread(thread);
+}
+
+uptr TagMemoryAligned(uptr p, uptr size, tag_t tag) {
+ CHECK(IsAligned(p, kShadowAlignment));
+ CHECK(IsAligned(size, kShadowAlignment));
+ __sanitizer_fill_shadow(p, size, tag,
+ common_flags()->clear_shadow_mmap_threshold);
+ return AddTagToPointer(p, tag);
+}
+
+// Not implemented because Fuchsia does not use signal handlers.
+void HwasanOnDeadlySignal(int signo, void *info, void *context) {}
+
+// Not implemented because Fuchsia does not use interceptors.
+void InitializeInterceptors() {}
+
+// Not implemented because this is only relevant for Android.
+void AndroidTestTlsSlot() {}
+
+// TSD was normally used on linux as a means of calling the hwasan thread exit
+// handler passed to pthread_key_create. This is not needed on Fuchsia because
+// we will be using __sanitizer_thread_exit_hook.
+void HwasanTSDInit() {}
+void HwasanTSDThreadInit() {}
+
+// On linux, this just would call `atexit(HwasanAtExit)`. The functions in
+// HwasanAtExit are unimplemented for Fuchsia and effectively no-ops, so this
+// function is unneeded.
+void InstallAtExitHandler() {}
+
+void HwasanInstallAtForkHandler() {}
+
+void InstallAtExitCheckLeaks() {}
+
+void InitializeOsSupport() {
+#ifdef __aarch64__
+ uint32_t features = 0;
+ CHECK_EQ(zx_system_get_features(ZX_FEATURE_KIND_ADDRESS_TAGGING, &features),
+ ZX_OK);
+ if (!(features & ZX_ARM64_FEATURE_ADDRESS_TAGGING_TBI) &&
+ flags()->fail_without_syscall_abi) {
+ Printf(
+ "FATAL: HWAddressSanitizer requires "
+ "ZX_ARM64_FEATURE_ADDRESS_TAGGING_TBI.\n");
+ Die();
+ }
+#endif
+}
+
+} // namespace __hwasan
+
+namespace __lsan {
+
+bool UseExitcodeOnLeak() { return __hwasan::flags()->halt_on_error; }
+
+} // namespace __lsan
+
+extern "C" {
+
+void *__sanitizer_before_thread_create_hook(thrd_t thread, bool detached,
+ const char *name, void *stack_base,
+ size_t stack_size) {
+ return __hwasan::BeforeThreadCreateHook(
+ reinterpret_cast<uptr>(thread), detached, name,
+ reinterpret_cast<uptr>(stack_base), stack_size);
+}
+
+void __sanitizer_thread_create_hook(void *hook, thrd_t thread, int error) {
+ __hwasan::ThreadCreateHook(hook, error != thrd_success);
+}
+
+void __sanitizer_thread_start_hook(void *hook, thrd_t self) {
+ __hwasan::ThreadStartHook(hook, reinterpret_cast<uptr>(self));
+}
+
+void __sanitizer_thread_exit_hook(void *hook, thrd_t self) {
+ __hwasan::ThreadExitHook(hook, self);
+}
+
+void __sanitizer_module_loaded(const struct dl_phdr_info *info, size_t) {
+ __hwasan_library_loaded(info->dlpi_addr, info->dlpi_phdr, info->dlpi_phnum);
+}
+
+} // extern "C"
+
+#endif // SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_globals.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_globals.cpp
new file mode 100644
index 00000000000..d71bcd792e1
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_globals.cpp
@@ -0,0 +1,91 @@
+//===-- hwasan_globals.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// HWAddressSanitizer globals-specific runtime.
+//===----------------------------------------------------------------------===//
+
+#include "hwasan_globals.h"
+
+namespace __hwasan {
+
+enum { NT_LLVM_HWASAN_GLOBALS = 3 };
+struct hwasan_global_note {
+ s32 begin_relptr;
+ s32 end_relptr;
+};
+
+// Check that the given library meets the code model requirements for tagged
+// globals. These properties are not checked at link time so they need to be
+// checked at runtime.
+static void CheckCodeModel(ElfW(Addr) base, const ElfW(Phdr) * phdr,
+ ElfW(Half) phnum) {
+ ElfW(Addr) min_addr = -1ull, max_addr = 0;
+ for (unsigned i = 0; i != phnum; ++i) {
+ if (phdr[i].p_type != PT_LOAD)
+ continue;
+ ElfW(Addr) lo = base + phdr[i].p_vaddr, hi = lo + phdr[i].p_memsz;
+ if (min_addr > lo)
+ min_addr = lo;
+ if (max_addr < hi)
+ max_addr = hi;
+ }
+
+ if (max_addr - min_addr > 1ull << 32) {
+ Report("FATAL: HWAddressSanitizer: library size exceeds 2^32\n");
+ Die();
+ }
+ if (max_addr > 1ull << 48) {
+ Report("FATAL: HWAddressSanitizer: library loaded above address 2^48\n");
+ Die();
+ }
+}
+
+ArrayRef<const hwasan_global> HwasanGlobalsFor(ElfW(Addr) base,
+ const ElfW(Phdr) * phdr,
+ ElfW(Half) phnum) {
+ // Read the phdrs from this DSO.
+ for (unsigned i = 0; i != phnum; ++i) {
+ if (phdr[i].p_type != PT_NOTE)
+ continue;
+
+ const char *note = reinterpret_cast<const char *>(base + phdr[i].p_vaddr);
+ const char *nend = note + phdr[i].p_memsz;
+
+ // Traverse all the notes until we find a HWASan note.
+ while (note < nend) {
+ auto *nhdr = reinterpret_cast<const ElfW(Nhdr) *>(note);
+ const char *name = note + sizeof(ElfW(Nhdr));
+ const char *desc = name + RoundUpTo(nhdr->n_namesz, 4);
+
+ // Discard non-HWASan-Globals notes.
+ if (nhdr->n_type != NT_LLVM_HWASAN_GLOBALS ||
+ internal_strcmp(name, "LLVM") != 0) {
+ note = desc + RoundUpTo(nhdr->n_descsz, 4);
+ continue;
+ }
+
+ // Only libraries with instrumented globals need to be checked against the
+ // code model since they use relocations that aren't checked at link time.
+ CheckCodeModel(base, phdr, phnum);
+
+ auto *global_note = reinterpret_cast<const hwasan_global_note *>(desc);
+ auto *globals_begin = reinterpret_cast<const hwasan_global *>(
+ note + global_note->begin_relptr);
+ auto *globals_end = reinterpret_cast<const hwasan_global *>(
+ note + global_note->end_relptr);
+
+ return {globals_begin, globals_end};
+ }
+ }
+
+ return {};
+}
+
+} // namespace __hwasan
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_globals.h b/contrib/libs/clang16-rt/lib/hwasan/hwasan_globals.h
new file mode 100644
index 00000000000..fd7adf7a058
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_globals.h
@@ -0,0 +1,49 @@
+//===-- hwasan_globals.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// Private Hwasan header.
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_GLOBALS_H
+#define HWASAN_GLOBALS_H
+
+#include <link.h>
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __hwasan {
+// This object should only ever be casted over the global (i.e. not constructed)
+// in the ELF PT_NOTE in order for `addr()` to work correctly.
+struct hwasan_global {
+ // The size of this global variable. Note that the size in the descriptor is
+ // max 1 << 24. Larger globals have multiple descriptors.
+ uptr size() const { return info & 0xffffff; }
+ // The fully-relocated address of this global.
+ uptr addr() const { return reinterpret_cast<uintptr_t>(this) + gv_relptr; }
+ // The static tag of this global.
+ u8 tag() const { return info >> 24; };
+
+ // The relative address between the start of the descriptor for the HWASan
+ // global (in the PT_NOTE), and the fully relocated address of the global.
+ s32 gv_relptr;
+ u32 info;
+};
+
+// Walk through the specific DSO (as specified by the base, phdr, and phnum),
+// and return the range of the [beginning, end) of the HWASan globals descriptor
+// array.
+ArrayRef<const hwasan_global> HwasanGlobalsFor(ElfW(Addr) base,
+ const ElfW(Phdr) * phdr,
+ ElfW(Half) phnum);
+
+} // namespace __hwasan
+
+#endif // HWASAN_GLOBALS_H
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_interceptors.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_interceptors.cpp
new file mode 100644
index 00000000000..05bf3f29eca
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_interceptors.cpp
@@ -0,0 +1,254 @@
+//===-- hwasan_interceptors.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// Interceptors for standard library functions.
+//
+// FIXME: move as many interceptors as possible into
+// sanitizer_common/sanitizer_common_interceptors.h
+//===----------------------------------------------------------------------===//
+
+#include "interception/interception.h"
+#include "hwasan.h"
+#include "hwasan_thread.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+#if !SANITIZER_FUCHSIA
+
+using namespace __hwasan;
+
+#if HWASAN_WITH_INTERCEPTORS
+
+struct ThreadStartArg {
+ thread_callback_t callback;
+ void *param;
+};
+
+static void *HwasanThreadStartFunc(void *arg) {
+ __hwasan_thread_enter();
+ ThreadStartArg A = *reinterpret_cast<ThreadStartArg*>(arg);
+ UnmapOrDie(arg, GetPageSizeCached());
+ return A.callback(A.param);
+}
+
+INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
+ void * param) {
+ ScopedTaggingDisabler disabler;
+ ThreadStartArg *A = reinterpret_cast<ThreadStartArg *> (MmapOrDie(
+ GetPageSizeCached(), "pthread_create"));
+ *A = {callback, param};
+ int res = REAL(pthread_create)(th, attr, &HwasanThreadStartFunc, A);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_join, void *t, void **arg) {
+ return REAL(pthread_join)(t, arg);
+}
+
+DEFINE_REAL_PTHREAD_FUNCTIONS
+
+DEFINE_REAL(int, vfork)
+DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
+
+// Get and/or change the set of blocked signals.
+extern "C" int sigprocmask(int __how, const __hw_sigset_t *__restrict __set,
+ __hw_sigset_t *__restrict __oset);
+#define SIG_BLOCK 0
+#define SIG_SETMASK 2
+extern "C" int __sigjmp_save(__hw_sigjmp_buf env, int savemask) {
+ env[0].__magic = kHwJmpBufMagic;
+ env[0].__mask_was_saved =
+ (savemask && sigprocmask(SIG_BLOCK, (__hw_sigset_t *)0,
+ &env[0].__saved_mask) == 0);
+ return 0;
+}
+
+static void __attribute__((always_inline))
+InternalLongjmp(__hw_register_buf env, int retval) {
+# if defined(__aarch64__)
+ constexpr size_t kSpIndex = 13;
+# elif defined(__x86_64__)
+ constexpr size_t kSpIndex = 6;
+# elif SANITIZER_RISCV64
+ constexpr size_t kSpIndex = 13;
+# endif
+
+ // Clear all memory tags on the stack between here and where we're going.
+ unsigned long long stack_pointer = env[kSpIndex];
+ // The stack pointer should never be tagged, so we don't need to clear the
+ // tag for this function call.
+ __hwasan_handle_longjmp((void *)stack_pointer);
+
+ // Run code for handling a longjmp.
+ // Need to use a register that isn't going to be loaded from the environment
+ // buffer -- hence why we need to specify the register to use.
+ // Must implement this ourselves, since we don't know the order of registers
+ // in different libc implementations and many implementations mangle the
+ // stack pointer so we can't use it without knowing the demangling scheme.
+# if defined(__aarch64__)
+ register long int retval_tmp asm("x1") = retval;
+ register void *env_address asm("x0") = &env[0];
+ asm volatile("ldp x19, x20, [%0, #0<<3];"
+ "ldp x21, x22, [%0, #2<<3];"
+ "ldp x23, x24, [%0, #4<<3];"
+ "ldp x25, x26, [%0, #6<<3];"
+ "ldp x27, x28, [%0, #8<<3];"
+ "ldp x29, x30, [%0, #10<<3];"
+ "ldp d8, d9, [%0, #14<<3];"
+ "ldp d10, d11, [%0, #16<<3];"
+ "ldp d12, d13, [%0, #18<<3];"
+ "ldp d14, d15, [%0, #20<<3];"
+ "ldr x5, [%0, #13<<3];"
+ "mov sp, x5;"
+ // Return the value requested to return through arguments.
+ // This should be in x1 given what we requested above.
+ "cmp %1, #0;"
+ "mov x0, #1;"
+ "csel x0, %1, x0, ne;"
+ "br x30;"
+ : "+r"(env_address)
+ : "r"(retval_tmp));
+# elif defined(__x86_64__)
+ register long int retval_tmp asm("%rsi") = retval;
+ register void *env_address asm("%rdi") = &env[0];
+ asm volatile(
+ // Restore registers.
+ "mov (0*8)(%0),%%rbx;"
+ "mov (1*8)(%0),%%rbp;"
+ "mov (2*8)(%0),%%r12;"
+ "mov (3*8)(%0),%%r13;"
+ "mov (4*8)(%0),%%r14;"
+ "mov (5*8)(%0),%%r15;"
+ "mov (6*8)(%0),%%rsp;"
+ "mov (7*8)(%0),%%rdx;"
+ // Return 1 if retval is 0.
+ "mov $1,%%rax;"
+ "test %1,%1;"
+ "cmovnz %1,%%rax;"
+ "jmp *%%rdx;" ::"r"(env_address),
+ "r"(retval_tmp));
+# elif SANITIZER_RISCV64
+ register long int retval_tmp asm("x11") = retval;
+ register void *env_address asm("x10") = &env[0];
+ asm volatile(
+ "ld ra, 0<<3(%0);"
+ "ld s0, 1<<3(%0);"
+ "ld s1, 2<<3(%0);"
+ "ld s2, 3<<3(%0);"
+ "ld s3, 4<<3(%0);"
+ "ld s4, 5<<3(%0);"
+ "ld s5, 6<<3(%0);"
+ "ld s6, 7<<3(%0);"
+ "ld s7, 8<<3(%0);"
+ "ld s8, 9<<3(%0);"
+ "ld s9, 10<<3(%0);"
+ "ld s10, 11<<3(%0);"
+ "ld s11, 12<<3(%0);"
+# if __riscv_float_abi_double
+ "fld fs0, 14<<3(%0);"
+ "fld fs1, 15<<3(%0);"
+ "fld fs2, 16<<3(%0);"
+ "fld fs3, 17<<3(%0);"
+ "fld fs4, 18<<3(%0);"
+ "fld fs5, 19<<3(%0);"
+ "fld fs6, 20<<3(%0);"
+ "fld fs7, 21<<3(%0);"
+ "fld fs8, 22<<3(%0);"
+ "fld fs9, 23<<3(%0);"
+ "fld fs10, 24<<3(%0);"
+ "fld fs11, 25<<3(%0);"
+# elif __riscv_float_abi_soft
+# else
+# error "Unsupported case"
+# endif
+ "ld a4, 13<<3(%0);"
+ "mv sp, a4;"
+ // Return the value requested to return through arguments.
+ // This should be in x11 given what we requested above.
+ "seqz a0, %1;"
+ "add a0, a0, %1;"
+ "ret;"
+ : "+r"(env_address)
+ : "r"(retval_tmp));
+# endif
+}
+
+INTERCEPTOR(void, siglongjmp, __hw_sigjmp_buf env, int val) {
+ if (env[0].__magic != kHwJmpBufMagic) {
+ Printf(
+ "WARNING: Unexpected bad jmp_buf. Either setjmp was not called or "
+ "there is a bug in HWASan.\n");
+ return REAL(siglongjmp)(env, val);
+ }
+
+ if (env[0].__mask_was_saved)
+ // Restore the saved signal mask.
+ (void)sigprocmask(SIG_SETMASK, &env[0].__saved_mask,
+ (__hw_sigset_t *)0);
+ InternalLongjmp(env[0].__jmpbuf, val);
+}
+
+// Required since glibc libpthread calls __libc_longjmp on pthread_exit, and
+// _setjmp on start_thread. Hence we have to intercept the longjmp on
+// pthread_exit so the __hw_jmp_buf order matches.
+INTERCEPTOR(void, __libc_longjmp, __hw_jmp_buf env, int val) {
+ if (env[0].__magic != kHwJmpBufMagic)
+ return REAL(__libc_longjmp)(env, val);
+ InternalLongjmp(env[0].__jmpbuf, val);
+}
+
+INTERCEPTOR(void, longjmp, __hw_jmp_buf env, int val) {
+ if (env[0].__magic != kHwJmpBufMagic) {
+ Printf(
+ "WARNING: Unexpected bad jmp_buf. Either setjmp was not called or "
+ "there is a bug in HWASan.\n");
+ return REAL(longjmp)(env, val);
+ }
+ InternalLongjmp(env[0].__jmpbuf, val);
+}
+#undef SIG_BLOCK
+#undef SIG_SETMASK
+
+# endif // HWASAN_WITH_INTERCEPTORS
+
+namespace __hwasan {
+
+int OnExit() {
+ if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks &&
+ __lsan::HasReportedLeaks()) {
+ return common_flags()->exitcode;
+ }
+ // FIXME: ask frontend whether we need to return failure.
+ return 0;
+}
+
+} // namespace __hwasan
+
+namespace __hwasan {
+
+void InitializeInterceptors() {
+ static int inited = 0;
+ CHECK_EQ(inited, 0);
+
+#if HWASAN_WITH_INTERCEPTORS
+#if defined(__linux__)
+ INTERCEPT_FUNCTION(__libc_longjmp);
+ INTERCEPT_FUNCTION(longjmp);
+ INTERCEPT_FUNCTION(siglongjmp);
+ INTERCEPT_FUNCTION(vfork);
+#endif // __linux__
+ INTERCEPT_FUNCTION(pthread_create);
+ INTERCEPT_FUNCTION(pthread_join);
+# endif
+
+ inited = 1;
+}
+} // namespace __hwasan
+
+#endif // #if !SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_interceptors_vfork.S b/contrib/libs/clang16-rt/lib/hwasan/hwasan_interceptors_vfork.S
new file mode 100644
index 00000000000..fd20825e3da
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_interceptors_vfork.S
@@ -0,0 +1,14 @@
+#include "sanitizer_common/sanitizer_asm.h"
+#include "builtins/assembly.h"
+
+#if defined(__linux__) && HWASAN_WITH_INTERCEPTORS
+#define COMMON_INTERCEPTOR_SPILL_AREA __hwasan_extra_spill_area
+#define COMMON_INTERCEPTOR_HANDLE_VFORK __hwasan_handle_vfork
+#include "sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S"
+#include "sanitizer_common/sanitizer_common_interceptors_vfork_riscv64.inc.S"
+#include "sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S"
+#endif
+
+NO_EXEC_STACK_DIRECTIVE
+
+GNU_PROPERTY_BTI_PAC
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_interface_internal.h b/contrib/libs/clang16-rt/lib/hwasan/hwasan_interface_internal.h
new file mode 100644
index 00000000000..d1ecbb592a2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_interface_internal.h
@@ -0,0 +1,190 @@
+//===-- hwasan_interface_internal.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// Private Hwasan interface header.
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_INTERFACE_INTERNAL_H
+#define HWASAN_INTERFACE_INTERNAL_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_platform_limits_posix.h"
+#include <link.h>
+
+extern "C" {
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_init_static();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_init();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_library_loaded(ElfW(Addr) base, const ElfW(Phdr) * phdr,
+ ElfW(Half) phnum);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_library_unloaded(ElfW(Addr) base, const ElfW(Phdr) * phdr,
+ ElfW(Half) phnum);
+
+using __sanitizer::uptr;
+using __sanitizer::sptr;
+using __sanitizer::uu64;
+using __sanitizer::uu32;
+using __sanitizer::uu16;
+using __sanitizer::u64;
+using __sanitizer::u32;
+using __sanitizer::u16;
+using __sanitizer::u8;
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_init_frames(uptr, uptr);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+extern uptr __hwasan_shadow_memory_dynamic_address;
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_loadN(uptr, uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load1(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load2(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load4(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load8(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load16(uptr);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_loadN_noabort(uptr, uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load1_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load2_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load4_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load8_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_load16_noabort(uptr);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_storeN(uptr, uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store1(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store2(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store4(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store8(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store16(uptr);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_storeN_noabort(uptr, uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store1_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store2_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store4_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store8_noabort(uptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_store16_noabort(uptr);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_tag_memory(uptr p, u8 tag, uptr sz);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __hwasan_tag_pointer(uptr p, u8 tag);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_tag_mismatch(uptr addr, u8 ts);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_tag_mismatch4(uptr addr, uptr access_info, uptr *registers_frame,
+ size_t outsize);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+u8 __hwasan_generate_tag();
+
+// Returns the offset of the first tag mismatch or -1 if the whole range is
+// good.
+SANITIZER_INTERFACE_ATTRIBUTE
+sptr __hwasan_test_shadow(const void *x, uptr size);
+
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+/* OPTIONAL */ const char* __hwasan_default_options();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_print_shadow(const void *x, uptr size);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_handle_longjmp(const void *sp_dst);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_handle_vfork(const void *sp_dst);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+u16 __sanitizer_unaligned_load16(const uu16 *p);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+u32 __sanitizer_unaligned_load32(const uu32 *p);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+u64 __sanitizer_unaligned_load64(const uu64 *p);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store16(uu16 *p, u16 x);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store32(uu32 *p, u32 x);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store64(uu64 *p, u64 x);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_enable_allocator_tagging();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_disable_allocator_tagging();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_thread_enter();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_thread_exit();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_print_memory_usage();
+
+// The compiler will generate this when
+// `-hwasan-record-stack-history-with-calls` is added as a flag, which will add
+// frame record information to the stack ring buffer. This is an alternative to
+// the compiler emitting instructions in the prologue for doing the same thing
+// by accessing the ring buffer directly.
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_add_frame_record(u64 frame_record_info);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__hwasan_memcpy(void *dst, const void *src, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__hwasan_memset(void *s, int c, uptr n);
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__hwasan_memmove(void *dest, const void *src, uptr n);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_set_error_report_callback(void (*callback)(const char *));
+} // extern "C"
+
+#endif // HWASAN_INTERFACE_INTERNAL_H
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_linux.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_linux.cpp
new file mode 100644
index 00000000000..d3e4b5390e8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_linux.cpp
@@ -0,0 +1,557 @@
+//===-- hwasan_linux.cpp ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is a part of HWAddressSanitizer and contains Linux-, NetBSD- and
+/// FreeBSD-specific code.
+///
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
+
+# include <dlfcn.h>
+# include <elf.h>
+# include <errno.h>
+# include <link.h>
+# include <pthread.h>
+# include <signal.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <sys/prctl.h>
+# include <sys/resource.h>
+# include <sys/time.h>
+# include <unistd.h>
+# include <unwind.h>
+
+# include "hwasan.h"
+# include "hwasan_dynamic_shadow.h"
+# include "hwasan_interface_internal.h"
+# include "hwasan_mapping.h"
+# include "hwasan_report.h"
+# include "hwasan_thread.h"
+# include "hwasan_thread_list.h"
+# include "sanitizer_common/sanitizer_common.h"
+# include "sanitizer_common/sanitizer_procmaps.h"
+# include "sanitizer_common/sanitizer_stackdepot.h"
+
+// Configurations of HWASAN_WITH_INTERCEPTORS and SANITIZER_ANDROID.
+//
+// HWASAN_WITH_INTERCEPTORS=OFF, SANITIZER_ANDROID=OFF
+// Not currently tested.
+// HWASAN_WITH_INTERCEPTORS=OFF, SANITIZER_ANDROID=ON
+// Integration tests downstream exist.
+// HWASAN_WITH_INTERCEPTORS=ON, SANITIZER_ANDROID=OFF
+// Tested with check-hwasan on x86_64-linux.
+// HWASAN_WITH_INTERCEPTORS=ON, SANITIZER_ANDROID=ON
+// Tested with check-hwasan on aarch64-linux-android.
+# if !SANITIZER_ANDROID
+SANITIZER_INTERFACE_ATTRIBUTE
+THREADLOCAL uptr __hwasan_tls;
+# endif
+
+namespace __hwasan {
+
+// With the zero shadow base we can not actually map pages starting from 0.
+// This constant is somewhat arbitrary.
+constexpr uptr kZeroBaseShadowStart = 0;
+constexpr uptr kZeroBaseMaxShadowStart = 1 << 18;
+
+static void ProtectGap(uptr addr, uptr size) {
+ __sanitizer::ProtectGap(addr, size, kZeroBaseShadowStart,
+ kZeroBaseMaxShadowStart);
+}
+
+uptr kLowMemStart;
+uptr kLowMemEnd;
+uptr kHighMemStart;
+uptr kHighMemEnd;
+
+static void PrintRange(uptr start, uptr end, const char *name) {
+ Printf("|| [%p, %p] || %.*s ||\n", (void *)start, (void *)end, 10, name);
+}
+
+static void PrintAddressSpaceLayout() {
+ PrintRange(kHighMemStart, kHighMemEnd, "HighMem");
+ if (kHighShadowEnd + 1 < kHighMemStart)
+ PrintRange(kHighShadowEnd + 1, kHighMemStart - 1, "ShadowGap");
+ else
+ CHECK_EQ(kHighShadowEnd + 1, kHighMemStart);
+ PrintRange(kHighShadowStart, kHighShadowEnd, "HighShadow");
+ if (kLowShadowEnd + 1 < kHighShadowStart)
+ PrintRange(kLowShadowEnd + 1, kHighShadowStart - 1, "ShadowGap");
+ else
+ CHECK_EQ(kLowMemEnd + 1, kHighShadowStart);
+ PrintRange(kLowShadowStart, kLowShadowEnd, "LowShadow");
+ if (kLowMemEnd + 1 < kLowShadowStart)
+ PrintRange(kLowMemEnd + 1, kLowShadowStart - 1, "ShadowGap");
+ else
+ CHECK_EQ(kLowMemEnd + 1, kLowShadowStart);
+ PrintRange(kLowMemStart, kLowMemEnd, "LowMem");
+ CHECK_EQ(0, kLowMemStart);
+}
+
+static uptr GetHighMemEnd() {
+ // HighMem covers the upper part of the address space.
+ uptr max_address = GetMaxUserVirtualAddress();
+ // Adjust max address to make sure that kHighMemEnd and kHighMemStart are
+ // properly aligned:
+ max_address |= (GetMmapGranularity() << kShadowScale) - 1;
+ return max_address;
+}
+
+static void InitializeShadowBaseAddress(uptr shadow_size_bytes) {
+ __hwasan_shadow_memory_dynamic_address =
+ FindDynamicShadowStart(shadow_size_bytes);
+}
+
+static void MaybeDieIfNoTaggingAbi(const char *message) {
+ if (!flags()->fail_without_syscall_abi)
+ return;
+ Printf("FATAL: %s\n", message);
+ Die();
+}
+
+# define PR_SET_TAGGED_ADDR_CTRL 55
+# define PR_GET_TAGGED_ADDR_CTRL 56
+# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
+# define ARCH_GET_UNTAG_MASK 0x4001
+# define ARCH_ENABLE_TAGGED_ADDR 0x4002
+# define ARCH_GET_MAX_TAG_BITS 0x4003
+
+static bool CanUseTaggingAbi() {
+# if defined(__x86_64__)
+ unsigned long num_bits = 0;
+ // Check for x86 LAM support. This API is based on a currently unsubmitted
+ // patch to the Linux kernel (as of August 2022) and is thus subject to
+ // change. The patch is here:
+ // https://lore.kernel.org/all/20220815041803.17954-1-kirill.shutemov@linux.intel.com/
+ //
+ // arch_prctl(ARCH_GET_MAX_TAG_BITS, &bits) returns the maximum number of tag
+ // bits the user can request, or zero if LAM is not supported by the hardware.
+ if (internal_iserror(internal_arch_prctl(ARCH_GET_MAX_TAG_BITS,
+ reinterpret_cast<uptr>(&num_bits))))
+ return false;
+ // The platform must provide enough bits for HWASan tags.
+ if (num_bits < kTagBits)
+ return false;
+ return true;
+# else
+ // Check for ARM TBI support.
+ return !internal_iserror(internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0));
+# endif // __x86_64__
+}
+
+static bool EnableTaggingAbi() {
+# if defined(__x86_64__)
+ // Enable x86 LAM tagging for the process.
+ //
+ // arch_prctl(ARCH_ENABLE_TAGGED_ADDR, bits) enables tagging if the number of
+ // tag bits requested by the user does not exceed that provided by the system.
+ // arch_prctl(ARCH_GET_UNTAG_MASK, &mask) returns the mask of significant
+ // address bits. It is ~0ULL if either LAM is disabled for the process or LAM
+ // is not supported by the hardware.
+ if (internal_iserror(internal_arch_prctl(ARCH_ENABLE_TAGGED_ADDR, kTagBits)))
+ return false;
+ unsigned long mask = 0;
+ // Make sure the tag bits are where we expect them to be.
+ if (internal_iserror(internal_arch_prctl(ARCH_GET_UNTAG_MASK,
+ reinterpret_cast<uptr>(&mask))))
+ return false;
+ // @mask has ones for non-tag bits, whereas @kAddressTagMask has ones for tag
+ // bits. Therefore these masks must not overlap.
+ if (mask & kAddressTagMask)
+ return false;
+ return true;
+# else
+ // Enable ARM TBI tagging for the process. If for some reason tagging is not
+ // supported, prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE) returns
+ // -EINVAL.
+ if (internal_iserror(internal_prctl(PR_SET_TAGGED_ADDR_CTRL,
+ PR_TAGGED_ADDR_ENABLE, 0, 0, 0)))
+ return false;
+ // Ensure that TBI is enabled.
+ if (internal_prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0) !=
+ PR_TAGGED_ADDR_ENABLE)
+ return false;
+ return true;
+# endif // __x86_64__
+}
+
+void InitializeOsSupport() {
+ // Check we're running on a kernel that can use the tagged address ABI.
+ bool has_abi = CanUseTaggingAbi();
+
+ if (!has_abi) {
+# if SANITIZER_ANDROID || defined(HWASAN_ALIASING_MODE)
+ // Some older Android kernels have the tagged pointer ABI on
+ // unconditionally, and hence don't have the tagged-addr prctl while still
+ // allow the ABI.
+ // If targeting Android and the prctl is not around we assume this is the
+ // case.
+ return;
+# else
+ MaybeDieIfNoTaggingAbi(
+ "HWAddressSanitizer requires a kernel with tagged address ABI.");
+# endif
+ }
+
+ if (EnableTaggingAbi())
+ return;
+
+# if SANITIZER_ANDROID
+ MaybeDieIfNoTaggingAbi(
+ "HWAddressSanitizer failed to enable tagged address syscall ABI.\n"
+ "Check the `sysctl abi.tagged_addr_disabled` configuration.");
+# else
+ MaybeDieIfNoTaggingAbi(
+ "HWAddressSanitizer failed to enable tagged address syscall ABI.\n");
+# endif
+}
+
+bool InitShadow() {
+ // Define the entire memory range.
+ kHighMemEnd = GetHighMemEnd();
+
+ // Determine shadow memory base offset.
+ InitializeShadowBaseAddress(MemToShadowSize(kHighMemEnd));
+
+ // Place the low memory first.
+ kLowMemEnd = __hwasan_shadow_memory_dynamic_address - 1;
+ kLowMemStart = 0;
+
+ // Define the low shadow based on the already placed low memory.
+ kLowShadowEnd = MemToShadow(kLowMemEnd);
+ kLowShadowStart = __hwasan_shadow_memory_dynamic_address;
+
+ // High shadow takes whatever memory is left up there (making sure it is not
+ // interfering with low memory in the fixed case).
+ kHighShadowEnd = MemToShadow(kHighMemEnd);
+ kHighShadowStart = Max(kLowMemEnd, MemToShadow(kHighShadowEnd)) + 1;
+
+ // High memory starts where allocated shadow allows.
+ kHighMemStart = ShadowToMem(kHighShadowStart);
+
+ // Check the sanity of the defined memory ranges (there might be gaps).
+ CHECK_EQ(kHighMemStart % GetMmapGranularity(), 0);
+ CHECK_GT(kHighMemStart, kHighShadowEnd);
+ CHECK_GT(kHighShadowEnd, kHighShadowStart);
+ CHECK_GT(kHighShadowStart, kLowMemEnd);
+ CHECK_GT(kLowMemEnd, kLowMemStart);
+ CHECK_GT(kLowShadowEnd, kLowShadowStart);
+ CHECK_GT(kLowShadowStart, kLowMemEnd);
+
+ if (Verbosity())
+ PrintAddressSpaceLayout();
+
+ // Reserve shadow memory.
+ ReserveShadowMemoryRange(kLowShadowStart, kLowShadowEnd, "low shadow");
+ ReserveShadowMemoryRange(kHighShadowStart, kHighShadowEnd, "high shadow");
+
+ // Protect all the gaps.
+ ProtectGap(0, Min(kLowMemStart, kLowShadowStart));
+ if (kLowMemEnd + 1 < kLowShadowStart)
+ ProtectGap(kLowMemEnd + 1, kLowShadowStart - kLowMemEnd - 1);
+ if (kLowShadowEnd + 1 < kHighShadowStart)
+ ProtectGap(kLowShadowEnd + 1, kHighShadowStart - kLowShadowEnd - 1);
+ if (kHighShadowEnd + 1 < kHighMemStart)
+ ProtectGap(kHighShadowEnd + 1, kHighMemStart - kHighShadowEnd - 1);
+
+ return true;
+}
+
+void InitThreads() {
+ CHECK(__hwasan_shadow_memory_dynamic_address);
+ uptr guard_page_size = GetMmapGranularity();
+ uptr thread_space_start =
+ __hwasan_shadow_memory_dynamic_address - (1ULL << kShadowBaseAlignment);
+ uptr thread_space_end =
+ __hwasan_shadow_memory_dynamic_address - guard_page_size;
+ ReserveShadowMemoryRange(thread_space_start, thread_space_end - 1,
+ "hwasan threads", /*madvise_shadow*/ false);
+ ProtectGap(thread_space_end,
+ __hwasan_shadow_memory_dynamic_address - thread_space_end);
+ InitThreadList(thread_space_start, thread_space_end - thread_space_start);
+ hwasanThreadList().CreateCurrentThread();
+}
+
+bool MemIsApp(uptr p) {
+// Memory outside the alias range has non-zero tags.
+# if !defined(HWASAN_ALIASING_MODE)
+ CHECK(GetTagFromPointer(p) == 0);
+# endif
+
+ return (p >= kHighMemStart && p <= kHighMemEnd) ||
+ (p >= kLowMemStart && p <= kLowMemEnd);
+}
+
+void InstallAtExitHandler() { atexit(HwasanAtExit); }
+
+// ---------------------- TSD ---------------- {{{1
+
+extern "C" void __hwasan_thread_enter() {
+ hwasanThreadList().CreateCurrentThread()->EnsureRandomStateInited();
+}
+
+extern "C" void __hwasan_thread_exit() {
+ Thread *t = GetCurrentThread();
+ // Make sure that signal handler can not see a stale current thread pointer.
+ atomic_signal_fence(memory_order_seq_cst);
+ if (t)
+ hwasanThreadList().ReleaseThread(t);
+}
+
+# if HWASAN_WITH_INTERCEPTORS
+static pthread_key_t tsd_key;
+static bool tsd_key_inited = false;
+
+void HwasanTSDThreadInit() {
+ if (tsd_key_inited)
+ CHECK_EQ(0, pthread_setspecific(tsd_key,
+ (void *)GetPthreadDestructorIterations()));
+}
+
+void HwasanTSDDtor(void *tsd) {
+ uptr iterations = (uptr)tsd;
+ if (iterations > 1) {
+ CHECK_EQ(0, pthread_setspecific(tsd_key, (void *)(iterations - 1)));
+ return;
+ }
+ __hwasan_thread_exit();
+}
+
+void HwasanTSDInit() {
+ CHECK(!tsd_key_inited);
+ tsd_key_inited = true;
+ CHECK_EQ(0, pthread_key_create(&tsd_key, HwasanTSDDtor));
+}
+# else
+void HwasanTSDInit() {}
+void HwasanTSDThreadInit() {}
+# endif
+
+# if SANITIZER_ANDROID
+uptr *GetCurrentThreadLongPtr() { return (uptr *)get_android_tls_ptr(); }
+# else
+uptr *GetCurrentThreadLongPtr() { return &__hwasan_tls; }
+# endif
+
+# if SANITIZER_ANDROID
+void AndroidTestTlsSlot() {
+ uptr kMagicValue = 0x010203040A0B0C0D;
+ uptr *tls_ptr = GetCurrentThreadLongPtr();
+ uptr old_value = *tls_ptr;
+ *tls_ptr = kMagicValue;
+ dlerror();
+ if (*(uptr *)get_android_tls_ptr() != kMagicValue) {
+ Printf(
+ "ERROR: Incompatible version of Android: TLS_SLOT_SANITIZER(6) is used "
+ "for dlerror().\n");
+ Die();
+ }
+ *tls_ptr = old_value;
+}
+# else
+void AndroidTestTlsSlot() {}
+# endif
+
+static AccessInfo GetAccessInfo(siginfo_t *info, ucontext_t *uc) {
+ // Access type is passed in a platform dependent way (see below) and encoded
+ // as 0xXY, where X&1 is 1 for store, 0 for load, and X&2 is 1 if the error is
+ // recoverable. Valid values of Y are 0 to 4, which are interpreted as
+ // log2(access_size), and 0xF, which means that access size is passed via
+ // platform dependent register (see below).
+# if defined(__aarch64__)
+ // Access type is encoded in BRK immediate as 0x900 + 0xXY. For Y == 0xF,
+ // access size is stored in X1 register. Access address is always in X0
+ // register.
+ uptr pc = (uptr)info->si_addr;
+ const unsigned code = ((*(u32 *)pc) >> 5) & 0xffff;
+ if ((code & 0xff00) != 0x900)
+ return AccessInfo{}; // Not ours.
+
+ const bool is_store = code & 0x10;
+ const bool recover = code & 0x20;
+ const uptr addr = uc->uc_mcontext.regs[0];
+ const unsigned size_log = code & 0xf;
+ if (size_log > 4 && size_log != 0xf)
+ return AccessInfo{}; // Not ours.
+ const uptr size = size_log == 0xf ? uc->uc_mcontext.regs[1] : 1U << size_log;
+
+# elif defined(__x86_64__)
+ // Access type is encoded in the instruction following INT3 as
+ // NOP DWORD ptr [EAX + 0x40 + 0xXY]. For Y == 0xF, access size is stored in
+ // RSI register. Access address is always in RDI register.
+ uptr pc = (uptr)uc->uc_mcontext.gregs[REG_RIP];
+ uint8_t *nop = (uint8_t *)pc;
+ if (*nop != 0x0f || *(nop + 1) != 0x1f || *(nop + 2) != 0x40 ||
+ *(nop + 3) < 0x40)
+ return AccessInfo{}; // Not ours.
+ const unsigned code = *(nop + 3);
+
+ const bool is_store = code & 0x10;
+ const bool recover = code & 0x20;
+ const uptr addr = uc->uc_mcontext.gregs[REG_RDI];
+ const unsigned size_log = code & 0xf;
+ if (size_log > 4 && size_log != 0xf)
+ return AccessInfo{}; // Not ours.
+ const uptr size =
+ size_log == 0xf ? uc->uc_mcontext.gregs[REG_RSI] : 1U << size_log;
+
+# elif SANITIZER_RISCV64
+ // Access type is encoded in the instruction following EBREAK as
+ // ADDI x0, x0, [0x40 + 0xXY]. For Y == 0xF, access size is stored in
+ // X11 register. Access address is always in X10 register.
+ uptr pc = (uptr)uc->uc_mcontext.__gregs[REG_PC];
+ uint8_t byte1 = *((u8 *)(pc + 0));
+ uint8_t byte2 = *((u8 *)(pc + 1));
+ uint8_t byte3 = *((u8 *)(pc + 2));
+ uint8_t byte4 = *((u8 *)(pc + 3));
+ uint32_t ebreak = (byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24));
+ bool isFaultShort = false;
+ bool isEbreak = (ebreak == 0x100073);
+ bool isShortEbreak = false;
+# if defined(__riscv_compressed)
+ isFaultShort = ((ebreak & 0x3) != 0x3);
+ isShortEbreak = ((ebreak & 0xffff) == 0x9002);
+# endif
+ // faulted insn is not ebreak, not our case
+ if (!(isEbreak || isShortEbreak))
+ return AccessInfo{};
+ // advance pc to point after ebreak and reconstruct addi instruction
+ pc += isFaultShort ? 2 : 4;
+ byte1 = *((u8 *)(pc + 0));
+ byte2 = *((u8 *)(pc + 1));
+ byte3 = *((u8 *)(pc + 2));
+ byte4 = *((u8 *)(pc + 3));
+ // reconstruct instruction
+ uint32_t instr = (byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24));
+ // check if this is really 32 bit instruction
+ // code is encoded in top 12 bits, since instruction is supposed to be with
+ // imm
+ const unsigned code = (instr >> 20) & 0xffff;
+ const uptr addr = uc->uc_mcontext.__gregs[10];
+ const bool is_store = code & 0x10;
+ const bool recover = code & 0x20;
+ const unsigned size_log = code & 0xf;
+ if (size_log > 4 && size_log != 0xf)
+ return AccessInfo{}; // Not our case
+ const uptr size =
+ size_log == 0xf ? uc->uc_mcontext.__gregs[11] : 1U << size_log;
+
+# else
+# error Unsupported architecture
+# endif
+
+ return AccessInfo{addr, size, is_store, !is_store, recover};
+}
+
+static bool HwasanOnSIGTRAP(int signo, siginfo_t *info, ucontext_t *uc) {
+ AccessInfo ai = GetAccessInfo(info, uc);
+ if (!ai.is_store && !ai.is_load)
+ return false;
+
+ SignalContext sig{info, uc};
+ HandleTagMismatch(ai, StackTrace::GetNextInstructionPc(sig.pc), sig.bp, uc);
+
+# if defined(__aarch64__)
+ uc->uc_mcontext.pc += 4;
+# elif defined(__x86_64__)
+# elif SANITIZER_RISCV64
+ // pc points to EBREAK which is 2 bytes long
+ uint8_t *exception_source = (uint8_t *)(uc->uc_mcontext.__gregs[REG_PC]);
+ uint8_t byte1 = (uint8_t)(*(exception_source + 0));
+ uint8_t byte2 = (uint8_t)(*(exception_source + 1));
+ uint8_t byte3 = (uint8_t)(*(exception_source + 2));
+ uint8_t byte4 = (uint8_t)(*(exception_source + 3));
+ uint32_t faulted = (byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24));
+ bool isFaultShort = false;
+# if defined(__riscv_compressed)
+ isFaultShort = ((faulted & 0x3) != 0x3);
+# endif
+ uc->uc_mcontext.__gregs[REG_PC] += isFaultShort ? 2 : 4;
+# else
+# error Unsupported architecture
+# endif
+ return true;
+}
+
+static void OnStackUnwind(const SignalContext &sig, const void *,
+ BufferedStackTrace *stack) {
+ stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
+ common_flags()->fast_unwind_on_fatal);
+}
+
+void HwasanOnDeadlySignal(int signo, void *info, void *context) {
+ // Probably a tag mismatch.
+ if (signo == SIGTRAP)
+ if (HwasanOnSIGTRAP(signo, (siginfo_t *)info, (ucontext_t *)context))
+ return;
+
+ HandleDeadlySignal(info, context, GetTid(), &OnStackUnwind, nullptr);
+}
+
+void Thread::InitStackAndTls(const InitState *) {
+ uptr tls_size;
+ uptr stack_size;
+ GetThreadStackAndTls(IsMainThread(), &stack_bottom_, &stack_size, &tls_begin_,
+ &tls_size);
+ stack_top_ = stack_bottom_ + stack_size;
+ tls_end_ = tls_begin_ + tls_size;
+}
+
+uptr TagMemoryAligned(uptr p, uptr size, tag_t tag) {
+ CHECK(IsAligned(p, kShadowAlignment));
+ CHECK(IsAligned(size, kShadowAlignment));
+ uptr shadow_start = MemToShadow(p);
+ uptr shadow_size = MemToShadowSize(size);
+
+ uptr page_size = GetPageSizeCached();
+ uptr page_start = RoundUpTo(shadow_start, page_size);
+ uptr page_end = RoundDownTo(shadow_start + shadow_size, page_size);
+ uptr threshold = common_flags()->clear_shadow_mmap_threshold;
+ if (SANITIZER_LINUX &&
+ UNLIKELY(page_end >= page_start + threshold && tag == 0)) {
+ internal_memset((void *)shadow_start, tag, page_start - shadow_start);
+ internal_memset((void *)page_end, tag,
+ shadow_start + shadow_size - page_end);
+ // For an anonymous private mapping MADV_DONTNEED will return a zero page on
+ // Linux.
+ ReleaseMemoryPagesToOSAndZeroFill(page_start, page_end);
+ } else {
+ internal_memset((void *)shadow_start, tag, shadow_size);
+ }
+ return AddTagToPointer(p, tag);
+}
+
+void HwasanInstallAtForkHandler() {
+ auto before = []() {
+ HwasanAllocatorLock();
+ StackDepotLockAll();
+ };
+ auto after = []() {
+ StackDepotUnlockAll();
+ HwasanAllocatorUnlock();
+ };
+ pthread_atfork(before, after, after);
+}
+
+void InstallAtExitCheckLeaks() {
+ if (CAN_SANITIZE_LEAKS) {
+ if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
+ if (flags()->halt_on_error)
+ Atexit(__lsan::DoLeakCheck);
+ else
+ Atexit(__lsan::DoRecoverableLeakCheckVoid);
+ }
+ }
+}
+
+} // namespace __hwasan
+
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_malloc_bisect.h b/contrib/libs/clang16-rt/lib/hwasan/hwasan_malloc_bisect.h
new file mode 100644
index 00000000000..7d134e8c4b7
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_malloc_bisect.h
@@ -0,0 +1,50 @@
+//===-- hwasan_malloc_bisect.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_hash.h"
+#include "hwasan.h"
+
+namespace __hwasan {
+
+static u32 malloc_hash(StackTrace *stack, uptr orig_size) {
+ uptr len = Min(stack->size, (unsigned)7);
+ MurMur2HashBuilder H(len);
+ H.add(orig_size);
+ // Start with frame #1 to skip __sanitizer_malloc frame, which is
+ // (a) almost always the same (well, could be operator new or new[])
+ // (b) can change hashes when compiler-rt is rebuilt, invalidating previous
+ // bisection results.
+ // Because of ASLR, use only offset inside the page.
+ for (uptr i = 1; i < len; ++i) H.add(((u32)stack->trace[i]) & 0xFFF);
+ return H.get();
+}
+
+static inline bool malloc_bisect(StackTrace *stack, uptr orig_size) {
+ uptr left = flags()->malloc_bisect_left;
+ uptr right = flags()->malloc_bisect_right;
+ if (LIKELY(left == 0 && right == 0))
+ return true;
+ if (!stack)
+ return true;
+ // Allow malloc_bisect_right > (u32)(-1) to avoid spelling the latter in
+ // decimal.
+ uptr h = (uptr)malloc_hash(stack, orig_size);
+ if (h < left || h > right)
+ return false;
+ if (flags()->malloc_bisect_dump) {
+ Printf("[alloc] %u %zu\n", h, orig_size);
+ stack->Print();
+ }
+ return true;
+}
+
+} // namespace __hwasan
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_mapping.h b/contrib/libs/clang16-rt/lib/hwasan/hwasan_mapping.h
new file mode 100644
index 00000000000..79a143632f6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_mapping.h
@@ -0,0 +1,75 @@
+//===-- hwasan_mapping.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is a part of HWAddressSanitizer and defines memory mapping.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_MAPPING_H
+#define HWASAN_MAPPING_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "hwasan_interface_internal.h"
+
+// Typical mapping on Linux/x86_64:
+// with dynamic shadow mapped at [0x770d59f40000, 0x7f0d59f40000]:
+// || [0x7f0d59f40000, 0x7fffffffffff] || HighMem ||
+// || [0x7efe2f934000, 0x7f0d59f3ffff] || HighShadow ||
+// || [0x7e7e2f934000, 0x7efe2f933fff] || ShadowGap ||
+// || [0x770d59f40000, 0x7e7e2f933fff] || LowShadow ||
+// || [0x000000000000, 0x770d59f3ffff] || LowMem ||
+
+// Typical mapping on Android/AArch64
+// with dynamic shadow mapped: [0x007477480000, 0x007c77480000]:
+// || [0x007c77480000, 0x007fffffffff] || HighMem ||
+// || [0x007c3ebc8000, 0x007c7747ffff] || HighShadow ||
+// || [0x007bbebc8000, 0x007c3ebc7fff] || ShadowGap ||
+// || [0x007477480000, 0x007bbebc7fff] || LowShadow ||
+// || [0x000000000000, 0x00747747ffff] || LowMem ||
+
+// Reasonable values are 4 (for 1/16th shadow) and 6 (for 1/64th).
+constexpr uptr kShadowScale = 4;
+constexpr uptr kShadowAlignment = 1ULL << kShadowScale;
+
+namespace __hwasan {
+
+extern uptr kLowMemStart;
+extern uptr kLowMemEnd;
+extern uptr kLowShadowEnd;
+extern uptr kLowShadowStart;
+extern uptr kHighShadowStart;
+extern uptr kHighShadowEnd;
+extern uptr kHighMemStart;
+extern uptr kHighMemEnd;
+
+inline uptr GetShadowOffset() {
+ return SANITIZER_FUCHSIA ? 0 : __hwasan_shadow_memory_dynamic_address;
+}
+inline uptr MemToShadow(uptr untagged_addr) {
+ return (untagged_addr >> kShadowScale) + GetShadowOffset();
+}
+inline uptr ShadowToMem(uptr shadow_addr) {
+ return (shadow_addr - GetShadowOffset()) << kShadowScale;
+}
+inline uptr MemToShadowSize(uptr size) {
+ return size >> kShadowScale;
+}
+
+bool MemIsApp(uptr p);
+
+inline bool MemIsShadow(uptr p) {
+ return (kLowShadowStart <= p && p <= kLowShadowEnd) ||
+ (kHighShadowStart <= p && p <= kHighShadowEnd);
+}
+
+uptr GetAliasRegionStart();
+
+} // namespace __hwasan
+
+#endif // HWASAN_MAPPING_H
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_memintrinsics.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_memintrinsics.cpp
new file mode 100644
index 00000000000..ea7f5ce40b0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_memintrinsics.cpp
@@ -0,0 +1,44 @@
+//===-- hwasan_memintrinsics.cpp --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is a part of HWAddressSanitizer and contains HWASAN versions of
+/// memset, memcpy and memmove
+///
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+#include "hwasan.h"
+#include "hwasan_checks.h"
+#include "hwasan_flags.h"
+#include "hwasan_interface_internal.h"
+#include "sanitizer_common/sanitizer_libc.h"
+
+using namespace __hwasan;
+
+void *__hwasan_memset(void *block, int c, uptr size) {
+ CheckAddressSized<ErrorAction::Recover, AccessType::Store>(
+ reinterpret_cast<uptr>(block), size);
+ return memset(block, c, size);
+}
+
+void *__hwasan_memcpy(void *to, const void *from, uptr size) {
+ CheckAddressSized<ErrorAction::Recover, AccessType::Store>(
+ reinterpret_cast<uptr>(to), size);
+ CheckAddressSized<ErrorAction::Recover, AccessType::Load>(
+ reinterpret_cast<uptr>(from), size);
+ return memcpy(to, from, size);
+}
+
+void *__hwasan_memmove(void *to, const void *from, uptr size) {
+ CheckAddressSized<ErrorAction::Recover, AccessType::Store>(
+ reinterpret_cast<uptr>(to), size);
+ CheckAddressSized<ErrorAction::Recover, AccessType::Load>(
+ reinterpret_cast<uptr>(from), size);
+ return memmove(to, from, size);
+}
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_new_delete.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_new_delete.cpp
new file mode 100644
index 00000000000..495046a754f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_new_delete.cpp
@@ -0,0 +1,138 @@
+//===-- hwasan_new_delete.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// Interceptors for operators new and delete.
+//===----------------------------------------------------------------------===//
+
+#include "hwasan.h"
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#if HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE
+
+// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
+# define OPERATOR_NEW_BODY(nothrow) \
+ GET_MALLOC_STACK_TRACE; \
+ void *res = hwasan_malloc(size, &stack); \
+ if (!nothrow && UNLIKELY(!res)) \
+ ReportOutOfMemory(size, &stack); \
+ return res
+# define OPERATOR_NEW_ALIGN_BODY(nothrow) \
+ GET_MALLOC_STACK_TRACE; \
+ void *res = hwasan_memalign(static_cast<uptr>(align), size, &stack); \
+ if (!nothrow && UNLIKELY(!res)) \
+ ReportOutOfMemory(size, &stack); \
+ return res
+
+# define OPERATOR_DELETE_BODY \
+ GET_MALLOC_STACK_TRACE; \
+ if (ptr) \
+ hwasan_free(ptr, &stack)
+
+#elif defined(__ANDROID__)
+
+// We don't actually want to intercept operator new and delete on Android, but
+// since we previously released a runtime that intercepted these functions,
+// removing the interceptors would break ABI. Therefore we simply forward to
+// malloc and free.
+# define OPERATOR_NEW_BODY(nothrow) return malloc(size)
+# define OPERATOR_DELETE_BODY free(ptr)
+
+#endif
+
+#ifdef OPERATOR_NEW_BODY
+
+using namespace __hwasan;
+
+// Fake std::nothrow_t to avoid including <new>.
+namespace std {
+struct nothrow_t {};
+} // namespace std
+
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(size_t size) {
+ OPERATOR_NEW_BODY(false /*nothrow*/);
+}
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
+ size_t size) {
+ OPERATOR_NEW_BODY(false /*nothrow*/);
+}
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
+ size_t size, std::nothrow_t const &) {
+ OPERATOR_NEW_BODY(true /*nothrow*/);
+}
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
+ size_t size, std::nothrow_t const &) {
+ OPERATOR_NEW_BODY(true /*nothrow*/);
+}
+
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
+ void *ptr) NOEXCEPT {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
+ void *ptr) NOEXCEPT {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
+ void *ptr, std::nothrow_t const &) {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
+ void *ptr, std::nothrow_t const &) {
+ OPERATOR_DELETE_BODY;
+}
+
+#endif // OPERATOR_NEW_BODY
+
+#ifdef OPERATOR_NEW_ALIGN_BODY
+
+namespace std {
+enum class align_val_t : size_t {};
+} // namespace std
+
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
+ size_t size, std::align_val_t align) {
+ OPERATOR_NEW_ALIGN_BODY(false /*nothrow*/);
+}
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
+ size_t size, std::align_val_t align) {
+ OPERATOR_NEW_ALIGN_BODY(false /*nothrow*/);
+}
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(
+ size_t size, std::align_val_t align, std::nothrow_t const &) {
+ OPERATOR_NEW_ALIGN_BODY(true /*nothrow*/);
+}
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[](
+ size_t size, std::align_val_t align, std::nothrow_t const &) {
+ OPERATOR_NEW_ALIGN_BODY(true /*nothrow*/);
+}
+
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
+ void *ptr, std::align_val_t align) NOEXCEPT {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
+ void *ptr, std::align_val_t) NOEXCEPT {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete(
+ void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[](
+ void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT {
+ OPERATOR_DELETE_BODY;
+}
+
+#endif // OPERATOR_NEW_ALIGN_BODY
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_poisoning.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_poisoning.cpp
new file mode 100644
index 00000000000..a4e5935754a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_poisoning.cpp
@@ -0,0 +1,36 @@
+//===-- hwasan_poisoning.cpp ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "hwasan_poisoning.h"
+
+#include "hwasan_mapping.h"
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_linux.h"
+
+namespace __hwasan {
+
+uptr TagMemory(uptr p, uptr size, tag_t tag) {
+ uptr start = RoundDownTo(p, kShadowAlignment);
+ uptr end = RoundUpTo(p + size, kShadowAlignment);
+ return TagMemoryAligned(start, end - start, tag);
+}
+
+} // namespace __hwasan
+
+// --- Implementation of LSan-specific functions --- {{{1
+namespace __lsan {
+bool WordIsPoisoned(uptr addr) {
+ // Fixme: implement actual tag checking.
+ return false;
+}
+} // namespace __lsan
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_poisoning.h b/contrib/libs/clang16-rt/lib/hwasan/hwasan_poisoning.h
new file mode 100644
index 00000000000..61751f7d252
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_poisoning.h
@@ -0,0 +1,24 @@
+//===-- hwasan_poisoning.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_POISONING_H
+#define HWASAN_POISONING_H
+
+#include "hwasan.h"
+
+namespace __hwasan {
+uptr TagMemory(uptr p, uptr size, tag_t tag);
+uptr TagMemoryAligned(uptr p, uptr size, tag_t tag);
+
+} // namespace __hwasan
+
+#endif // HWASAN_POISONING_H
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_preinit.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_preinit.cpp
new file mode 100644
index 00000000000..8c9c95f413b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_preinit.cpp
@@ -0,0 +1,23 @@
+//===-- hwasan_preinit.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer, an address sanity checker.
+//
+// Call __hwasan_init at the very early stage of process startup.
+//===----------------------------------------------------------------------===//
+#include "hwasan_interface_internal.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+#if SANITIZER_CAN_USE_PREINIT_ARRAY
+// The symbol is called __local_hwasan_preinit, because it's not intended to
+// be exported.
+// This code linked into the main executable when -fsanitize=hwaddress is in
+// the link flags. It can only use exported interface functions.
+__attribute__((section(".preinit_array"), used)) static void (
+ *__local_hwasan_preinit)(void) = __hwasan_init;
+#endif
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_report.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_report.cpp
new file mode 100644
index 00000000000..31e190a8ebb
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_report.cpp
@@ -0,0 +1,804 @@
+//===-- hwasan_report.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// Error reporting.
+//===----------------------------------------------------------------------===//
+
+#include "hwasan_report.h"
+
+#include <dlfcn.h>
+
+#include "hwasan.h"
+#include "hwasan_allocator.h"
+#include "hwasan_globals.h"
+#include "hwasan_mapping.h"
+#include "hwasan_thread.h"
+#include "hwasan_thread_list.h"
+#include "sanitizer_common/sanitizer_allocator_internal.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_stacktrace_printer.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+
+using namespace __sanitizer;
+
+namespace __hwasan {
+
+class ScopedReport {
+ public:
+ ScopedReport(bool fatal = false) : error_message_(1), fatal(fatal) {
+ Lock lock(&error_message_lock_);
+ error_message_ptr_ = fatal ? &error_message_ : nullptr;
+ ++hwasan_report_count;
+ }
+
+ ~ScopedReport() {
+ void (*report_cb)(const char *);
+ {
+ Lock lock(&error_message_lock_);
+ report_cb = error_report_callback_;
+ error_message_ptr_ = nullptr;
+ }
+ if (report_cb)
+ report_cb(error_message_.data());
+ if (fatal)
+ SetAbortMessage(error_message_.data());
+ if (common_flags()->print_module_map >= 2 ||
+ (fatal && common_flags()->print_module_map))
+ DumpProcessMap();
+ if (fatal)
+ Die();
+ }
+
+ static void MaybeAppendToErrorMessage(const char *msg) {
+ Lock lock(&error_message_lock_);
+ if (!error_message_ptr_)
+ return;
+ uptr len = internal_strlen(msg);
+ uptr old_size = error_message_ptr_->size();
+ error_message_ptr_->resize(old_size + len);
+ // overwrite old trailing '\0', keep new trailing '\0' untouched.
+ internal_memcpy(&(*error_message_ptr_)[old_size - 1], msg, len);
+ }
+
+ static void SetErrorReportCallback(void (*callback)(const char *)) {
+ Lock lock(&error_message_lock_);
+ error_report_callback_ = callback;
+ }
+
+ private:
+ ScopedErrorReportLock error_report_lock_;
+ InternalMmapVector<char> error_message_;
+ bool fatal;
+
+ static InternalMmapVector<char> *error_message_ptr_;
+ static Mutex error_message_lock_;
+ static void (*error_report_callback_)(const char *);
+};
+
+InternalMmapVector<char> *ScopedReport::error_message_ptr_;
+Mutex ScopedReport::error_message_lock_;
+void (*ScopedReport::error_report_callback_)(const char *);
+
+// If there is an active ScopedReport, append to its error message.
+void AppendToErrorMessageBuffer(const char *buffer) {
+ ScopedReport::MaybeAppendToErrorMessage(buffer);
+}
+
+static StackTrace GetStackTraceFromId(u32 id) {
+ CHECK(id);
+ StackTrace res = StackDepotGet(id);
+ CHECK(res.trace);
+ return res;
+}
+
+static void MaybePrintAndroidHelpUrl() {
+#if SANITIZER_ANDROID
+ Printf(
+ "Learn more about HWASan reports: "
+ "https://source.android.com/docs/security/test/memory-safety/"
+ "hwasan-reports\n");
+#endif
+}
+
+// A RAII object that holds a copy of the current thread stack ring buffer.
+// The actual stack buffer may change while we are iterating over it (for
+// example, Printf may call syslog() which can itself be built with hwasan).
+class SavedStackAllocations {
+ public:
+ SavedStackAllocations(StackAllocationsRingBuffer *rb) {
+ uptr size = rb->size() * sizeof(uptr);
+ void *storage =
+ MmapAlignedOrDieOnFatalError(size, size * 2, "saved stack allocations");
+ new (&rb_) StackAllocationsRingBuffer(*rb, storage);
+ }
+
+ ~SavedStackAllocations() {
+ StackAllocationsRingBuffer *rb = get();
+ UnmapOrDie(rb->StartOfStorage(), rb->size() * sizeof(uptr));
+ }
+
+ StackAllocationsRingBuffer *get() {
+ return (StackAllocationsRingBuffer *)&rb_;
+ }
+
+ private:
+ uptr rb_;
+};
+
+class Decorator: public __sanitizer::SanitizerCommonDecorator {
+ public:
+ Decorator() : SanitizerCommonDecorator() { }
+ const char *Access() { return Blue(); }
+ const char *Allocation() const { return Magenta(); }
+ const char *Origin() const { return Magenta(); }
+ const char *Name() const { return Green(); }
+ const char *Location() { return Green(); }
+ const char *Thread() { return Green(); }
+};
+
+static bool FindHeapAllocation(HeapAllocationsRingBuffer *rb, uptr tagged_addr,
+ HeapAllocationRecord *har, uptr *ring_index,
+ uptr *num_matching_addrs,
+ uptr *num_matching_addrs_4b) {
+ if (!rb) return false;
+
+ *num_matching_addrs = 0;
+ *num_matching_addrs_4b = 0;
+ for (uptr i = 0, size = rb->size(); i < size; i++) {
+ auto h = (*rb)[i];
+ if (h.tagged_addr <= tagged_addr &&
+ h.tagged_addr + h.requested_size > tagged_addr) {
+ *har = h;
+ *ring_index = i;
+ return true;
+ }
+
+ // Measure the number of heap ring buffer entries that would have matched
+ // if we had only one entry per address (e.g. if the ring buffer data was
+ // stored at the address itself). This will help us tune the allocator
+ // implementation for MTE.
+ if (UntagAddr(h.tagged_addr) <= UntagAddr(tagged_addr) &&
+ UntagAddr(h.tagged_addr) + h.requested_size > UntagAddr(tagged_addr)) {
+ ++*num_matching_addrs;
+ }
+
+ // Measure the number of heap ring buffer entries that would have matched
+ // if we only had 4 tag bits, which is the case for MTE.
+ auto untag_4b = [](uptr p) {
+ return p & ((1ULL << 60) - 1);
+ };
+ if (untag_4b(h.tagged_addr) <= untag_4b(tagged_addr) &&
+ untag_4b(h.tagged_addr) + h.requested_size > untag_4b(tagged_addr)) {
+ ++*num_matching_addrs_4b;
+ }
+ }
+ return false;
+}
+
+static void PrintStackAllocations(StackAllocationsRingBuffer *sa,
+ tag_t addr_tag, uptr untagged_addr) {
+ uptr frames = Min((uptr)flags()->stack_history_size, sa->size());
+ bool found_local = false;
+ for (uptr i = 0; i < frames; i++) {
+ const uptr *record_addr = &(*sa)[i];
+ uptr record = *record_addr;
+ if (!record)
+ break;
+ tag_t base_tag =
+ reinterpret_cast<uptr>(record_addr) >> kRecordAddrBaseTagShift;
+ uptr fp = (record >> kRecordFPShift) << kRecordFPLShift;
+ uptr pc_mask = (1ULL << kRecordFPShift) - 1;
+ uptr pc = record & pc_mask;
+ FrameInfo frame;
+ if (Symbolizer::GetOrInit()->SymbolizeFrame(pc, &frame)) {
+ for (LocalInfo &local : frame.locals) {
+ if (!local.has_frame_offset || !local.has_size || !local.has_tag_offset)
+ continue;
+ tag_t obj_tag = base_tag ^ local.tag_offset;
+ if (obj_tag != addr_tag)
+ continue;
+ // Calculate the offset from the object address to the faulting
+ // address. Because we only store bits 4-19 of FP (bits 0-3 are
+ // guaranteed to be zero), the calculation is performed mod 2^20 and may
+ // harmlessly underflow if the address mod 2^20 is below the object
+ // address.
+ uptr obj_offset =
+ (untagged_addr - fp - local.frame_offset) & (kRecordFPModulus - 1);
+ if (obj_offset >= local.size)
+ continue;
+ if (!found_local) {
+ Printf("Potentially referenced stack objects:\n");
+ found_local = true;
+ }
+ Printf(" %s in %s %s:%d\n", local.name, local.function_name,
+ local.decl_file, local.decl_line);
+ }
+ frame.Clear();
+ }
+ }
+
+ if (found_local)
+ return;
+
+ // We didn't find any locals. Most likely we don't have symbols, so dump
+ // the information that we have for offline analysis.
+ InternalScopedString frame_desc;
+ Printf("Previously allocated frames:\n");
+ for (uptr i = 0; i < frames; i++) {
+ const uptr *record_addr = &(*sa)[i];
+ uptr record = *record_addr;
+ if (!record)
+ break;
+ uptr pc_mask = (1ULL << 48) - 1;
+ uptr pc = record & pc_mask;
+ frame_desc.append(" record_addr:0x%zx record:0x%zx",
+ reinterpret_cast<uptr>(record_addr), record);
+ if (SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc)) {
+ RenderFrame(&frame_desc, " %F %L", 0, frame->info.address, &frame->info,
+ common_flags()->symbolize_vs_style,
+ common_flags()->strip_path_prefix);
+ frame->ClearAll();
+ }
+ Printf("%s\n", frame_desc.data());
+ frame_desc.clear();
+ }
+}
+
+// Returns true if tag == *tag_ptr, reading tags from short granules if
+// necessary. This may return a false positive if tags 1-15 are used as a
+// regular tag rather than a short granule marker.
+static bool TagsEqual(tag_t tag, tag_t *tag_ptr) {
+ if (tag == *tag_ptr)
+ return true;
+ if (*tag_ptr == 0 || *tag_ptr > kShadowAlignment - 1)
+ return false;
+ uptr mem = ShadowToMem(reinterpret_cast<uptr>(tag_ptr));
+ tag_t inline_tag = *reinterpret_cast<tag_t *>(mem + kShadowAlignment - 1);
+ return tag == inline_tag;
+}
+
+// HWASan globals store the size of the global in the descriptor. In cases where
+// we don't have a binary with symbols, we can't grab the size of the global
+// from the debug info - but we might be able to retrieve it from the
+// descriptor. Returns zero if the lookup failed.
+static uptr GetGlobalSizeFromDescriptor(uptr ptr) {
+ // Find the ELF object that this global resides in.
+ Dl_info info;
+ if (dladdr(reinterpret_cast<void *>(ptr), &info) == 0)
+ return 0;
+ auto *ehdr = reinterpret_cast<const ElfW(Ehdr) *>(info.dli_fbase);
+ auto *phdr_begin = reinterpret_cast<const ElfW(Phdr) *>(
+ reinterpret_cast<const u8 *>(ehdr) + ehdr->e_phoff);
+
+ // Get the load bias. This is normally the same as the dli_fbase address on
+ // position-independent code, but can be different on non-PIE executables,
+ // binaries using LLD's partitioning feature, or binaries compiled with a
+ // linker script.
+ ElfW(Addr) load_bias = 0;
+ for (const auto &phdr :
+ ArrayRef<const ElfW(Phdr)>(phdr_begin, phdr_begin + ehdr->e_phnum)) {
+ if (phdr.p_type != PT_LOAD || phdr.p_offset != 0)
+ continue;
+ load_bias = reinterpret_cast<ElfW(Addr)>(ehdr) - phdr.p_vaddr;
+ break;
+ }
+
+ // Walk all globals in this ELF object, looking for the one we're interested
+ // in. Once we find it, we can stop iterating and return the size of the
+ // global we're interested in.
+ for (const hwasan_global &global :
+ HwasanGlobalsFor(load_bias, phdr_begin, ehdr->e_phnum))
+ if (global.addr() <= ptr && ptr < global.addr() + global.size())
+ return global.size();
+
+ return 0;
+}
+
+static void ShowHeapOrGlobalCandidate(uptr untagged_addr, tag_t *candidate,
+ tag_t *left, tag_t *right) {
+ Decorator d;
+ uptr mem = ShadowToMem(reinterpret_cast<uptr>(candidate));
+ HwasanChunkView chunk = FindHeapChunkByAddress(mem);
+ if (chunk.IsAllocated()) {
+ uptr offset;
+ const char *whence;
+ if (untagged_addr < chunk.End() && untagged_addr >= chunk.Beg()) {
+ offset = untagged_addr - chunk.Beg();
+ whence = "inside";
+ } else if (candidate == left) {
+ offset = untagged_addr - chunk.End();
+ whence = "after";
+ } else {
+ offset = chunk.Beg() - untagged_addr;
+ whence = "before";
+ }
+ Printf("%s", d.Error());
+ Printf("\nCause: heap-buffer-overflow\n");
+ Printf("%s", d.Default());
+ Printf("%s", d.Location());
+ Printf("%p is located %zd bytes %s a %zd-byte region [%p,%p)\n",
+ untagged_addr, offset, whence, chunk.UsedSize(), chunk.Beg(),
+ chunk.End());
+ Printf("%s", d.Allocation());
+ Printf("allocated here:\n");
+ Printf("%s", d.Default());
+ GetStackTraceFromId(chunk.GetAllocStackId()).Print();
+ return;
+ }
+ // Check whether the address points into a loaded library. If so, this is
+ // most likely a global variable.
+ const char *module_name;
+ uptr module_address;
+ Symbolizer *sym = Symbolizer::GetOrInit();
+ if (sym->GetModuleNameAndOffsetForPC(mem, &module_name, &module_address)) {
+ Printf("%s", d.Error());
+ Printf("\nCause: global-overflow\n");
+ Printf("%s", d.Default());
+ DataInfo info;
+ Printf("%s", d.Location());
+ if (sym->SymbolizeData(mem, &info) && info.start) {
+ Printf(
+ "%p is located %zd bytes %s a %zd-byte global variable "
+ "%s [%p,%p) in %s\n",
+ untagged_addr,
+ candidate == left ? untagged_addr - (info.start + info.size)
+ : info.start - untagged_addr,
+ candidate == left ? "after" : "before", info.size, info.name,
+ info.start, info.start + info.size, module_name);
+ } else {
+ uptr size = GetGlobalSizeFromDescriptor(mem);
+ if (size == 0)
+ // We couldn't find the size of the global from the descriptors.
+ Printf(
+ "%p is located %s a global variable in "
+ "\n #0 0x%x (%s+0x%x)\n",
+ untagged_addr, candidate == left ? "after" : "before", mem,
+ module_name, module_address);
+ else
+ Printf(
+ "%p is located %s a %zd-byte global variable in "
+ "\n #0 0x%x (%s+0x%x)\n",
+ untagged_addr, candidate == left ? "after" : "before", size, mem,
+ module_name, module_address);
+ }
+ Printf("%s", d.Default());
+ }
+}
+
+void PrintAddressDescription(
+ uptr tagged_addr, uptr access_size,
+ StackAllocationsRingBuffer *current_stack_allocations) {
+ Decorator d;
+ int num_descriptions_printed = 0;
+ uptr untagged_addr = UntagAddr(tagged_addr);
+
+ if (MemIsShadow(untagged_addr)) {
+ Printf("%s%p is HWAsan shadow memory.\n%s", d.Location(), untagged_addr,
+ d.Default());
+ return;
+ }
+
+ // Print some very basic information about the address, if it's a heap.
+ HwasanChunkView chunk = FindHeapChunkByAddress(untagged_addr);
+ if (uptr beg = chunk.Beg()) {
+ uptr size = chunk.ActualSize();
+ Printf("%s[%p,%p) is a %s %s heap chunk; "
+ "size: %zd offset: %zd\n%s",
+ d.Location(),
+ beg, beg + size,
+ chunk.FromSmallHeap() ? "small" : "large",
+ chunk.IsAllocated() ? "allocated" : "unallocated",
+ size, untagged_addr - beg,
+ d.Default());
+ }
+
+ tag_t addr_tag = GetTagFromPointer(tagged_addr);
+
+ bool on_stack = false;
+ // Check stack first. If the address is on the stack of a live thread, we
+ // know it cannot be a heap / global overflow.
+ hwasanThreadList().VisitAllLiveThreads([&](Thread *t) {
+ if (t->AddrIsInStack(untagged_addr)) {
+ on_stack = true;
+ // TODO(fmayer): figure out how to distinguish use-after-return and
+ // stack-buffer-overflow.
+ Printf("%s", d.Error());
+ Printf("\nCause: stack tag-mismatch\n");
+ Printf("%s", d.Location());
+ Printf("Address %p is located in stack of thread T%zd\n", untagged_addr,
+ t->unique_id());
+ Printf("%s", d.Default());
+ t->Announce();
+
+ auto *sa = (t == GetCurrentThread() && current_stack_allocations)
+ ? current_stack_allocations
+ : t->stack_allocations();
+ PrintStackAllocations(sa, addr_tag, untagged_addr);
+ num_descriptions_printed++;
+ }
+ });
+
+ // Check if this looks like a heap buffer overflow by scanning
+ // the shadow left and right and looking for the first adjacent
+ // object with a different memory tag. If that tag matches addr_tag,
+ // check the allocator if it has a live chunk there.
+ tag_t *tag_ptr = reinterpret_cast<tag_t*>(MemToShadow(untagged_addr));
+ tag_t *candidate = nullptr, *left = tag_ptr, *right = tag_ptr;
+ uptr candidate_distance = 0;
+ for (; candidate_distance < 1000; candidate_distance++) {
+ if (MemIsShadow(reinterpret_cast<uptr>(left)) &&
+ TagsEqual(addr_tag, left)) {
+ candidate = left;
+ break;
+ }
+ --left;
+ if (MemIsShadow(reinterpret_cast<uptr>(right)) &&
+ TagsEqual(addr_tag, right)) {
+ candidate = right;
+ break;
+ }
+ ++right;
+ }
+
+ constexpr auto kCloseCandidateDistance = 1;
+
+ if (!on_stack && candidate && candidate_distance <= kCloseCandidateDistance) {
+ ShowHeapOrGlobalCandidate(untagged_addr, candidate, left, right);
+ num_descriptions_printed++;
+ }
+
+ hwasanThreadList().VisitAllLiveThreads([&](Thread *t) {
+ // Scan all threads' ring buffers to find if it's a heap-use-after-free.
+ HeapAllocationRecord har;
+ uptr ring_index, num_matching_addrs, num_matching_addrs_4b;
+ if (FindHeapAllocation(t->heap_allocations(), tagged_addr, &har,
+ &ring_index, &num_matching_addrs,
+ &num_matching_addrs_4b)) {
+ Printf("%s", d.Error());
+ Printf("\nCause: use-after-free\n");
+ Printf("%s", d.Location());
+ Printf("%p is located %zd bytes inside a %zd-byte region [%p,%p)\n",
+ untagged_addr, untagged_addr - UntagAddr(har.tagged_addr),
+ har.requested_size, UntagAddr(har.tagged_addr),
+ UntagAddr(har.tagged_addr) + har.requested_size);
+ Printf("%s", d.Allocation());
+ Printf("freed by thread T%zd here:\n", t->unique_id());
+ Printf("%s", d.Default());
+ GetStackTraceFromId(har.free_context_id).Print();
+
+ Printf("%s", d.Allocation());
+ Printf("previously allocated here:\n", t);
+ Printf("%s", d.Default());
+ GetStackTraceFromId(har.alloc_context_id).Print();
+
+ // Print a developer note: the index of this heap object
+ // in the thread's deallocation ring buffer.
+ Printf("hwasan_dev_note_heap_rb_distance: %zd %zd\n", ring_index + 1,
+ flags()->heap_history_size);
+ Printf("hwasan_dev_note_num_matching_addrs: %zd\n", num_matching_addrs);
+ Printf("hwasan_dev_note_num_matching_addrs_4b: %zd\n",
+ num_matching_addrs_4b);
+
+ t->Announce();
+ num_descriptions_printed++;
+ }
+ });
+
+ if (candidate && num_descriptions_printed == 0) {
+ ShowHeapOrGlobalCandidate(untagged_addr, candidate, left, right);
+ num_descriptions_printed++;
+ }
+
+ // Print the remaining threads, as an extra information, 1 line per thread.
+ hwasanThreadList().VisitAllLiveThreads([&](Thread *t) { t->Announce(); });
+
+ if (!num_descriptions_printed)
+ // We exhausted our possibilities. Bail out.
+ Printf("HWAddressSanitizer can not describe address in more detail.\n");
+ if (num_descriptions_printed > 1) {
+ Printf(
+ "There are %d potential causes, printed above in order "
+ "of likeliness.\n",
+ num_descriptions_printed);
+ }
+}
+
+void ReportStats() {}
+
+static void PrintTagInfoAroundAddr(tag_t *tag_ptr, uptr num_rows,
+ void (*print_tag)(InternalScopedString &s,
+ tag_t *tag)) {
+ const uptr row_len = 16; // better be power of two.
+ tag_t *center_row_beg = reinterpret_cast<tag_t *>(
+ RoundDownTo(reinterpret_cast<uptr>(tag_ptr), row_len));
+ tag_t *beg_row = center_row_beg - row_len * (num_rows / 2);
+ tag_t *end_row = center_row_beg + row_len * ((num_rows + 1) / 2);
+ InternalScopedString s;
+ for (tag_t *row = beg_row; row < end_row; row += row_len) {
+ s.append("%s", row == center_row_beg ? "=>" : " ");
+ s.append("%p:", (void *)ShadowToMem(reinterpret_cast<uptr>(row)));
+ for (uptr i = 0; i < row_len; i++) {
+ s.append("%s", row + i == tag_ptr ? "[" : " ");
+ print_tag(s, &row[i]);
+ s.append("%s", row + i == tag_ptr ? "]" : " ");
+ }
+ s.append("\n");
+ }
+ Printf("%s", s.data());
+}
+
+static void PrintTagsAroundAddr(tag_t *tag_ptr) {
+ Printf(
+ "Memory tags around the buggy address (one tag corresponds to %zd "
+ "bytes):\n", kShadowAlignment);
+ PrintTagInfoAroundAddr(tag_ptr, 17, [](InternalScopedString &s, tag_t *tag) {
+ s.append("%02x", *tag);
+ });
+
+ Printf(
+ "Tags for short granules around the buggy address (one tag corresponds "
+ "to %zd bytes):\n",
+ kShadowAlignment);
+ PrintTagInfoAroundAddr(tag_ptr, 3, [](InternalScopedString &s, tag_t *tag) {
+ if (*tag >= 1 && *tag <= kShadowAlignment) {
+ uptr granule_addr = ShadowToMem(reinterpret_cast<uptr>(tag));
+ s.append("%02x",
+ *reinterpret_cast<u8 *>(granule_addr + kShadowAlignment - 1));
+ } else {
+ s.append("..");
+ }
+ });
+ Printf(
+ "See "
+ "https://clang.llvm.org/docs/"
+ "HardwareAssistedAddressSanitizerDesign.html#short-granules for a "
+ "description of short granule tags\n");
+}
+
+uptr GetTopPc(StackTrace *stack) {
+ return stack->size ? StackTrace::GetPreviousInstructionPc(stack->trace[0])
+ : 0;
+}
+
+void ReportInvalidFree(StackTrace *stack, uptr tagged_addr) {
+ ScopedReport R(flags()->halt_on_error);
+
+ uptr untagged_addr = UntagAddr(tagged_addr);
+ tag_t ptr_tag = GetTagFromPointer(tagged_addr);
+ tag_t *tag_ptr = nullptr;
+ tag_t mem_tag = 0;
+ if (MemIsApp(untagged_addr)) {
+ tag_ptr = reinterpret_cast<tag_t *>(MemToShadow(untagged_addr));
+ if (MemIsShadow(reinterpret_cast<uptr>(tag_ptr)))
+ mem_tag = *tag_ptr;
+ else
+ tag_ptr = nullptr;
+ }
+ Decorator d;
+ Printf("%s", d.Error());
+ uptr pc = GetTopPc(stack);
+ const char *bug_type = "invalid-free";
+ const Thread *thread = GetCurrentThread();
+ if (thread) {
+ Report("ERROR: %s: %s on address %p at pc %p on thread T%zd\n",
+ SanitizerToolName, bug_type, untagged_addr, pc, thread->unique_id());
+ } else {
+ Report("ERROR: %s: %s on address %p at pc %p on unknown thread\n",
+ SanitizerToolName, bug_type, untagged_addr, pc);
+ }
+ Printf("%s", d.Access());
+ if (tag_ptr)
+ Printf("tags: %02x/%02x (ptr/mem)\n", ptr_tag, mem_tag);
+ Printf("%s", d.Default());
+
+ stack->Print();
+
+ PrintAddressDescription(tagged_addr, 0, nullptr);
+
+ if (tag_ptr)
+ PrintTagsAroundAddr(tag_ptr);
+
+ MaybePrintAndroidHelpUrl();
+ ReportErrorSummary(bug_type, stack);
+}
+
+void ReportTailOverwritten(StackTrace *stack, uptr tagged_addr, uptr orig_size,
+ const u8 *expected) {
+ uptr tail_size = kShadowAlignment - (orig_size % kShadowAlignment);
+ u8 actual_expected[kShadowAlignment];
+ internal_memcpy(actual_expected, expected, tail_size);
+ tag_t ptr_tag = GetTagFromPointer(tagged_addr);
+ // Short granule is stashed in the last byte of the magic string. To avoid
+ // confusion, make the expected magic string contain the short granule tag.
+ if (orig_size % kShadowAlignment != 0) {
+ actual_expected[tail_size - 1] = ptr_tag;
+ }
+
+ ScopedReport R(flags()->halt_on_error);
+ Decorator d;
+ uptr untagged_addr = UntagAddr(tagged_addr);
+ Printf("%s", d.Error());
+ const char *bug_type = "allocation-tail-overwritten";
+ Report("ERROR: %s: %s; heap object [%p,%p) of size %zd\n", SanitizerToolName,
+ bug_type, untagged_addr, untagged_addr + orig_size, orig_size);
+ Printf("\n%s", d.Default());
+ Printf(
+ "Stack of invalid access unknown. Issue detected at deallocation "
+ "time.\n");
+ Printf("%s", d.Allocation());
+ Printf("deallocated here:\n");
+ Printf("%s", d.Default());
+ stack->Print();
+ HwasanChunkView chunk = FindHeapChunkByAddress(untagged_addr);
+ if (chunk.Beg()) {
+ Printf("%s", d.Allocation());
+ Printf("allocated here:\n");
+ Printf("%s", d.Default());
+ GetStackTraceFromId(chunk.GetAllocStackId()).Print();
+ }
+
+ InternalScopedString s;
+ CHECK_GT(tail_size, 0U);
+ CHECK_LT(tail_size, kShadowAlignment);
+ u8 *tail = reinterpret_cast<u8*>(untagged_addr + orig_size);
+ s.append("Tail contains: ");
+ for (uptr i = 0; i < kShadowAlignment - tail_size; i++)
+ s.append(".. ");
+ for (uptr i = 0; i < tail_size; i++)
+ s.append("%02x ", tail[i]);
+ s.append("\n");
+ s.append("Expected: ");
+ for (uptr i = 0; i < kShadowAlignment - tail_size; i++)
+ s.append(".. ");
+ for (uptr i = 0; i < tail_size; i++) s.append("%02x ", actual_expected[i]);
+ s.append("\n");
+ s.append(" ");
+ for (uptr i = 0; i < kShadowAlignment - tail_size; i++)
+ s.append(" ");
+ for (uptr i = 0; i < tail_size; i++)
+ s.append("%s ", actual_expected[i] != tail[i] ? "^^" : " ");
+
+ s.append("\nThis error occurs when a buffer overflow overwrites memory\n"
+ "after a heap object, but within the %zd-byte granule, e.g.\n"
+ " char *x = new char[20];\n"
+ " x[25] = 42;\n"
+ "%s does not detect such bugs in uninstrumented code at the time of write,"
+ "\nbut can detect them at the time of free/delete.\n"
+ "To disable this feature set HWASAN_OPTIONS=free_checks_tail_magic=0\n",
+ kShadowAlignment, SanitizerToolName);
+ Printf("%s", s.data());
+ GetCurrentThread()->Announce();
+
+ tag_t *tag_ptr = reinterpret_cast<tag_t*>(MemToShadow(untagged_addr));
+ PrintTagsAroundAddr(tag_ptr);
+
+ MaybePrintAndroidHelpUrl();
+ ReportErrorSummary(bug_type, stack);
+}
+
+void ReportTagMismatch(StackTrace *stack, uptr tagged_addr, uptr access_size,
+ bool is_store, bool fatal, uptr *registers_frame) {
+ ScopedReport R(fatal);
+ SavedStackAllocations current_stack_allocations(
+ GetCurrentThread()->stack_allocations());
+
+ Decorator d;
+ uptr untagged_addr = UntagAddr(tagged_addr);
+ // TODO: when possible, try to print heap-use-after-free, etc.
+ const char *bug_type = "tag-mismatch";
+ uptr pc = GetTopPc(stack);
+ Printf("%s", d.Error());
+ Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type,
+ untagged_addr, pc);
+
+ Thread *t = GetCurrentThread();
+
+ sptr offset =
+ __hwasan_test_shadow(reinterpret_cast<void *>(tagged_addr), access_size);
+ CHECK(offset >= 0 && offset < static_cast<sptr>(access_size));
+ tag_t ptr_tag = GetTagFromPointer(tagged_addr);
+ tag_t *tag_ptr =
+ reinterpret_cast<tag_t *>(MemToShadow(untagged_addr + offset));
+ tag_t mem_tag = *tag_ptr;
+
+ Printf("%s", d.Access());
+ if (mem_tag && mem_tag < kShadowAlignment) {
+ tag_t *granule_ptr = reinterpret_cast<tag_t *>((untagged_addr + offset) &
+ ~(kShadowAlignment - 1));
+ // If offset is 0, (untagged_addr + offset) is not aligned to granules.
+ // This is the offset of the leftmost accessed byte within the bad granule.
+ u8 in_granule_offset = (untagged_addr + offset) & (kShadowAlignment - 1);
+ tag_t short_tag = granule_ptr[kShadowAlignment - 1];
+ // The first mismatch was a short granule that matched the ptr_tag.
+ if (short_tag == ptr_tag) {
+ // If the access starts after the end of the short granule, then the first
+ // bad byte is the first byte of the access; otherwise it is the first
+ // byte past the end of the short granule
+ if (mem_tag > in_granule_offset) {
+ offset += mem_tag - in_granule_offset;
+ }
+ }
+ Printf(
+ "%s of size %zu at %p tags: %02x/%02x(%02x) (ptr/mem) in thread T%zd\n",
+ is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag,
+ mem_tag, short_tag, t->unique_id());
+ } else {
+ Printf("%s of size %zu at %p tags: %02x/%02x (ptr/mem) in thread T%zd\n",
+ is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag,
+ mem_tag, t->unique_id());
+ }
+ if (offset != 0)
+ Printf("Invalid access starting at offset %zu\n", offset);
+ Printf("%s", d.Default());
+
+ stack->Print();
+
+ PrintAddressDescription(tagged_addr, access_size,
+ current_stack_allocations.get());
+ t->Announce();
+
+ PrintTagsAroundAddr(tag_ptr);
+
+ if (registers_frame)
+ ReportRegisters(registers_frame, pc);
+
+ MaybePrintAndroidHelpUrl();
+ ReportErrorSummary(bug_type, stack);
+}
+
+// See the frame breakdown defined in __hwasan_tag_mismatch (from
+// hwasan_tag_mismatch_{aarch64,riscv64}.S).
+void ReportRegisters(uptr *frame, uptr pc) {
+ Printf("Registers where the failure occurred (pc %p):\n", pc);
+
+ // We explicitly print a single line (4 registers/line) each iteration to
+ // reduce the amount of logcat error messages printed. Each Printf() will
+ // result in a new logcat line, irrespective of whether a newline is present,
+ // and so we wish to reduce the number of Printf() calls we have to make.
+#if defined(__aarch64__)
+ Printf(" x0 %016llx x1 %016llx x2 %016llx x3 %016llx\n",
+ frame[0], frame[1], frame[2], frame[3]);
+#elif SANITIZER_RISCV64
+ Printf(" sp %016llx x1 %016llx x2 %016llx x3 %016llx\n",
+ reinterpret_cast<u8 *>(frame) + 256, frame[1], frame[2], frame[3]);
+#endif
+ Printf(" x4 %016llx x5 %016llx x6 %016llx x7 %016llx\n",
+ frame[4], frame[5], frame[6], frame[7]);
+ Printf(" x8 %016llx x9 %016llx x10 %016llx x11 %016llx\n",
+ frame[8], frame[9], frame[10], frame[11]);
+ Printf(" x12 %016llx x13 %016llx x14 %016llx x15 %016llx\n",
+ frame[12], frame[13], frame[14], frame[15]);
+ Printf(" x16 %016llx x17 %016llx x18 %016llx x19 %016llx\n",
+ frame[16], frame[17], frame[18], frame[19]);
+ Printf(" x20 %016llx x21 %016llx x22 %016llx x23 %016llx\n",
+ frame[20], frame[21], frame[22], frame[23]);
+ Printf(" x24 %016llx x25 %016llx x26 %016llx x27 %016llx\n",
+ frame[24], frame[25], frame[26], frame[27]);
+ // hwasan_check* reduces the stack pointer by 256, then __hwasan_tag_mismatch
+ // passes it to this function.
+#if defined(__aarch64__)
+ Printf(" x28 %016llx x29 %016llx x30 %016llx sp %016llx\n", frame[28],
+ frame[29], frame[30], reinterpret_cast<u8 *>(frame) + 256);
+#elif SANITIZER_RISCV64
+ Printf(" x28 %016llx x29 %016llx x30 %016llx x31 %016llx\n", frame[28],
+ frame[29], frame[30], frame[31]);
+#else
+#endif
+}
+
+} // namespace __hwasan
+
+void __hwasan_set_error_report_callback(void (*callback)(const char *)) {
+ __hwasan::ScopedReport::SetErrorReportCallback(callback);
+}
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_report.h b/contrib/libs/clang16-rt/lib/hwasan/hwasan_report.h
new file mode 100644
index 00000000000..de86c38fc01
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_report.h
@@ -0,0 +1,35 @@
+//===-- hwasan_report.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is a part of HWAddressSanitizer. HWASan-private header for error
+/// reporting functions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_REPORT_H
+#define HWASAN_REPORT_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+
+namespace __hwasan {
+
+void ReportStats();
+void ReportTagMismatch(StackTrace *stack, uptr addr, uptr access_size,
+ bool is_store, bool fatal, uptr *registers_frame);
+void ReportInvalidFree(StackTrace *stack, uptr addr);
+void ReportTailOverwritten(StackTrace *stack, uptr addr, uptr orig_size,
+ const u8 *expected);
+void ReportRegisters(uptr *registers_frame, uptr pc);
+void ReportAtExitStatistics();
+
+
+} // namespace __hwasan
+
+#endif // HWASAN_REPORT_H
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_setjmp_aarch64.S b/contrib/libs/clang16-rt/lib/hwasan/hwasan_setjmp_aarch64.S
new file mode 100644
index 00000000000..744748a5101
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_setjmp_aarch64.S
@@ -0,0 +1,101 @@
+//===-- hwasan_setjmp_aarch64.S -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// HWAddressSanitizer runtime.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_asm.h"
+#include "builtins/assembly.h"
+
+#if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__)
+#include "sanitizer_common/sanitizer_platform.h"
+
+// We want to save the context of the calling function.
+// That requires
+// 1) No modification of the link register by this function.
+// 2) No modification of the stack pointer by this function.
+// 3) (no modification of any other saved register, but that's not really going
+// to occur, and hence isn't as much of a worry).
+//
+// There's essentially no way to ensure that the compiler will not modify the
+// stack pointer when compiling a C function.
+// Hence we have to write this function in assembly.
+
+.section .text
+.file "hwasan_setjmp_aarch64.S"
+
+.global __interceptor_setjmp
+ASM_TYPE_FUNCTION(__interceptor_setjmp)
+__interceptor_setjmp:
+ CFI_STARTPROC
+ BTI_C
+ mov x1, #0
+ b __interceptor_sigsetjmp
+ CFI_ENDPROC
+ASM_SIZE(__interceptor_setjmp)
+
+#if SANITIZER_ANDROID
+// Bionic also defines a function `setjmp` that calls `sigsetjmp` saving the
+// current signal.
+.global __interceptor_setjmp_bionic
+ASM_TYPE_FUNCTION(__interceptor_setjmp_bionic)
+__interceptor_setjmp_bionic:
+ CFI_STARTPROC
+ BTI_C
+ mov x1, #1
+ b __interceptor_sigsetjmp
+ CFI_ENDPROC
+ASM_SIZE(__interceptor_setjmp_bionic)
+#endif
+
+.global __interceptor_sigsetjmp
+ASM_TYPE_FUNCTION(__interceptor_sigsetjmp)
+__interceptor_sigsetjmp:
+ CFI_STARTPROC
+ BTI_C
+ stp x19, x20, [x0, #0<<3]
+ stp x21, x22, [x0, #2<<3]
+ stp x23, x24, [x0, #4<<3]
+ stp x25, x26, [x0, #6<<3]
+ stp x27, x28, [x0, #8<<3]
+ stp x29, x30, [x0, #10<<3]
+ stp d8, d9, [x0, #14<<3]
+ stp d10, d11, [x0, #16<<3]
+ stp d12, d13, [x0, #18<<3]
+ stp d14, d15, [x0, #20<<3]
+ mov x2, sp
+ str x2, [x0, #13<<3]
+ // We always have the second argument to __sigjmp_save (savemask) set, since
+ // the _setjmp function above has set it for us as `false`.
+ // This function is defined in hwasan_interceptors.cc
+ b __sigjmp_save
+ CFI_ENDPROC
+ASM_SIZE(__interceptor_sigsetjmp)
+
+
+.macro WEAK_ALIAS first second
+ .weak \second
+ .equ \second\(), \first
+.endm
+
+#if SANITIZER_ANDROID
+WEAK_ALIAS __interceptor_sigsetjmp, sigsetjmp
+WEAK_ALIAS __interceptor_setjmp_bionic, setjmp
+#else
+WEAK_ALIAS __interceptor_sigsetjmp, __sigsetjmp
+#endif
+
+WEAK_ALIAS __interceptor_setjmp, _setjmp
+#endif
+
+// We do not need executable stack.
+NO_EXEC_STACK_DIRECTIVE
+
+GNU_PROPERTY_BTI_PAC
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_setjmp_riscv64.S b/contrib/libs/clang16-rt/lib/hwasan/hwasan_setjmp_riscv64.S
new file mode 100644
index 00000000000..43f9c3c26b4
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_setjmp_riscv64.S
@@ -0,0 +1,97 @@
+//===-- hwasan_setjmp_riscv64.S -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+// setjmp interceptor for risc-v.
+// HWAddressSanitizer runtime.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_asm.h"
+#include "builtins/assembly.h"
+
+#if HWASAN_WITH_INTERCEPTORS && defined(__riscv) && (__riscv_xlen == 64)
+#include "sanitizer_common/sanitizer_platform.h"
+
+// We want to save the context of the calling function.
+// That requires
+// 1) No modification of the link register by this function.
+// 2) No modification of the stack pointer by this function.
+// 3) (no modification of any other saved register, but that's not really going
+// to occur, and hence isn't as much of a worry).
+//
+// There's essentially no way to ensure that the compiler will not modify the
+// stack pointer when compiling a C function.
+// Hence we have to write this function in assembly.
+
+.section .text
+.file "hwasan_setjmp_riscv64.S"
+
+.global __interceptor_setjmp
+ASM_TYPE_FUNCTION(__interceptor_setjmp)
+__interceptor_setjmp:
+ CFI_STARTPROC
+ addi x11, x0, 0
+ tail __interceptor_sigsetjmp
+ CFI_ENDPROC
+ASM_SIZE(__interceptor_setjmp)
+
+.global __interceptor_sigsetjmp
+ASM_TYPE_FUNCTION(__interceptor_sigsetjmp)
+__interceptor_sigsetjmp:
+ CFI_STARTPROC
+ sd ra, 0<<3(x10)
+ sd s0, 1<<3(x10)
+ sd s1, 2<<3(x10)
+ sd s2, 3<<3(x10)
+ sd s3, 4<<3(x10)
+ sd s4, 5<<3(x10)
+ sd s5, 6<<3(x10)
+ sd s6, 7<<3(x10)
+ sd s7, 8<<3(x10)
+ sd s8, 9<<3(x10)
+ sd s9, 10<<3(x10)
+ sd s10, 11<<3(x10)
+ sd s11, 12<<3(x10)
+ sd sp, 13<<3(x10)
+#if __riscv_float_abi_double
+ fsd fs0, 14<<3(x10)
+ fsd fs1, 15<<3(x10)
+ fsd fs2, 16<<3(x10)
+ fsd fs3, 17<<3(x10)
+ fsd fs4, 18<<3(x10)
+ fsd fs5, 19<<3(x10)
+ fsd fs6, 20<<3(x10)
+ fsd fs7, 21<<3(x10)
+ fsd fs8, 22<<3(x10)
+ fsd fs9, 23<<3(x10)
+ fsd fs10, 24<<3(x10)
+ fsd fs11, 25<<3(x10)
+#elif __riscv_float_abi_soft
+#else
+# error "Unsupported case"
+#endif
+ // We always have the second argument to __sigjmp_save (savemask) set, since
+ // the _setjmp function above has set it for us as `false`.
+ // This function is defined in hwasan_interceptors.cc
+ tail __sigjmp_save
+ CFI_ENDPROC
+ASM_SIZE(__interceptor_sigsetjmp)
+
+
+.macro WEAK_ALIAS first second
+ .weak \second
+ .equ \second\(), \first
+.endm
+
+WEAK_ALIAS __interceptor_sigsetjmp, __sigsetjmp
+
+WEAK_ALIAS __interceptor_setjmp, _setjmp
+#endif
+
+// We do not need executable stack.
+NO_EXEC_STACK_DIRECTIVE
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_setjmp_x86_64.S b/contrib/libs/clang16-rt/lib/hwasan/hwasan_setjmp_x86_64.S
new file mode 100644
index 00000000000..7566c1ea0a5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_setjmp_x86_64.S
@@ -0,0 +1,82 @@
+//===-- hwasan_setjmp_x86_64.S --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// setjmp interceptor for x86_64.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_asm.h"
+
+#if HWASAN_WITH_INTERCEPTORS && defined(__x86_64__)
+#include "sanitizer_common/sanitizer_platform.h"
+
+// We want to save the context of the calling function.
+// That requires
+// 1) No modification of the return address by this function.
+// 2) No modification of the stack pointer by this function.
+// 3) (no modification of any other saved register, but that's not really going
+// to occur, and hence isn't as much of a worry).
+//
+// There's essentially no way to ensure that the compiler will not modify the
+// stack pointer when compiling a C function.
+// Hence we have to write this function in assembly.
+//
+// TODO: Handle Intel CET.
+
+.section .text
+.file "hwasan_setjmp_x86_64.S"
+
+.global __interceptor_setjmp
+ASM_TYPE_FUNCTION(__interceptor_setjmp)
+__interceptor_setjmp:
+ CFI_STARTPROC
+ _CET_ENDBR
+ xorl %esi, %esi
+ jmp __interceptor_sigsetjmp
+ CFI_ENDPROC
+ASM_SIZE(__interceptor_setjmp)
+
+.global __interceptor_sigsetjmp
+ASM_TYPE_FUNCTION(__interceptor_sigsetjmp)
+__interceptor_sigsetjmp:
+ CFI_STARTPROC
+ _CET_ENDBR
+
+ // Save callee save registers.
+ mov %rbx, (0*8)(%rdi)
+ mov %rbp, (1*8)(%rdi)
+ mov %r12, (2*8)(%rdi)
+ mov %r13, (3*8)(%rdi)
+ mov %r14, (4*8)(%rdi)
+ mov %r15, (5*8)(%rdi)
+
+ // Save SP as it was in caller's frame.
+ lea 8(%rsp), %rdx
+ mov %rdx, (6*8)(%rdi)
+
+ // Save return address.
+ mov (%rsp), %rax
+ mov %rax, (7*8)(%rdi)
+
+ jmp __sigjmp_save
+
+ CFI_ENDPROC
+ASM_SIZE(__interceptor_sigsetjmp)
+
+
+.macro WEAK_ALIAS first second
+ .weak \second
+ .equ \second\(), \first
+.endm
+
+WEAK_ALIAS __interceptor_sigsetjmp, __sigsetjmp
+WEAK_ALIAS __interceptor_setjmp, _setjmp
+#endif
+
+// We do not need executable stack.
+NO_EXEC_STACK_DIRECTIVE
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S b/contrib/libs/clang16-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S
new file mode 100644
index 00000000000..bcb0df42019
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S
@@ -0,0 +1,158 @@
+#include "sanitizer_common/sanitizer_asm.h"
+#include "builtins/assembly.h"
+
+// The content of this file is AArch64-only:
+#if defined(__aarch64__)
+
+// The responsibility of the HWASan entry point in compiler-rt is to primarily
+// readjust the stack from the callee and save the current register values to
+// the stack.
+// This entry point function should be called from a __hwasan_check_* symbol.
+// These are generated during a lowering pass in the backend, and are found in
+// AArch64AsmPrinter::EmitHwasanMemaccessSymbols(). Please look there for
+// further information.
+// The __hwasan_check_* caller of this function should have expanded the stack
+// and saved the previous values of x0, x1, x29, and x30. This function will
+// "consume" these saved values and treats it as part of its own stack frame.
+// In this sense, the __hwasan_check_* callee and this function "share" a stack
+// frame. This allows us to omit having unwinding information (.cfi_*) present
+// in every __hwasan_check_* function, therefore reducing binary size. This is
+// particularly important as hwasan_check_* instances are duplicated in every
+// translation unit where HWASan is enabled.
+// This function calls HwasanTagMismatch to step back into the C++ code that
+// completes the stack unwinding and error printing. This function is is not
+// permitted to return.
+
+
+// Frame from __hwasan_check_:
+// | ... |
+// | ... |
+// | Previous stack frames... |
+// +=================================+
+// | Unused 8-bytes for maintaining |
+// | 16-byte SP alignment. |
+// +---------------------------------+
+// | Return address (x30) for caller |
+// | of __hwasan_check_*. |
+// +---------------------------------+
+// | Frame address (x29) for caller |
+// | of __hwasan_check_* |
+// +---------------------------------+ <-- [SP + 232]
+// | ... |
+// | |
+// | Stack frame space for x2 - x28. |
+// | |
+// | ... |
+// +---------------------------------+ <-- [SP + 16]
+// | |
+// | Saved x1, as __hwasan_check_* |
+// | clobbers it. |
+// +---------------------------------+
+// | Saved x0, likewise above. |
+// +---------------------------------+ <-- [x30 / SP]
+
+// This function takes two arguments:
+// * x0: The data address.
+// * x1: The encoded access info for the failing access.
+
+// This function has two entry points. The first, __hwasan_tag_mismatch, is used
+// by clients that were compiled without short tag checks (i.e. binaries built
+// by older compilers and binaries targeting older runtimes). In this case the
+// outlined tag check will be missing the code handling short tags (which won't
+// be used in the binary's own stack variables but may be used on the heap
+// or stack variables in other binaries), so the check needs to be done here.
+//
+// The second, __hwasan_tag_mismatch_v2, is used by binaries targeting newer
+// runtimes. This entry point bypasses the short tag check since it will have
+// already been done as part of the outlined tag check. Since tag mismatches are
+// uncommon, there isn't a significant performance benefit to being able to
+// bypass the check; the main benefits are that we can sometimes avoid
+// clobbering the x17 register in error reports, and that the program will have
+// a runtime dependency on the __hwasan_tag_mismatch_v2 symbol therefore it will
+// fail to start up given an older (i.e. incompatible) runtime.
+.section .text
+.file "hwasan_tag_mismatch_aarch64.S"
+.global __hwasan_tag_mismatch
+.type __hwasan_tag_mismatch, %function
+__hwasan_tag_mismatch:
+ BTI_J
+
+ // Compute the granule position one past the end of the access.
+ mov x16, #1
+ and x17, x1, #0xf
+ lsl x16, x16, x17
+ and x17, x0, #0xf
+ add x17, x16, x17
+
+ // Load the shadow byte again and check whether it is a short tag within the
+ // range of the granule position computed above.
+ ubfx x16, x0, #4, #52
+ ldrb w16, [x9, x16]
+ cmp w16, #0xf
+ b.hi __hwasan_tag_mismatch_v2
+ cmp w16, w17
+ b.lo __hwasan_tag_mismatch_v2
+
+ // Load the real tag from the last byte of the granule and compare against
+ // the pointer tag.
+ orr x16, x0, #0xf
+ ldrb w16, [x16]
+ cmp x16, x0, lsr #56
+ b.ne __hwasan_tag_mismatch_v2
+
+ // Restore x0, x1 and sp to their values from before the __hwasan_tag_mismatch
+ // call and resume execution.
+ ldp x0, x1, [sp], #256
+ ret
+
+.global __hwasan_tag_mismatch_v2
+.type __hwasan_tag_mismatch_v2, %function
+__hwasan_tag_mismatch_v2:
+ CFI_STARTPROC
+ BTI_J
+
+ // Set the CFA to be the return address for caller of __hwasan_check_*. Note
+ // that we do not emit CFI predicates to describe the contents of this stack
+ // frame, as this proxy entry point should never be debugged. The contents
+ // are static and are handled by the unwinder after calling
+ // __hwasan_tag_mismatch. The frame pointer is already correctly setup
+ // by __hwasan_check_*.
+ add x29, sp, #232
+ CFI_DEF_CFA(w29, 24)
+ CFI_OFFSET(w30, -16)
+ CFI_OFFSET(w29, -24)
+
+ // Save the rest of the registers into the preallocated space left by
+ // __hwasan_check.
+ str x28, [sp, #224]
+ stp x26, x27, [sp, #208]
+ stp x24, x25, [sp, #192]
+ stp x22, x23, [sp, #176]
+ stp x20, x21, [sp, #160]
+ stp x18, x19, [sp, #144]
+ stp x16, x17, [sp, #128]
+ stp x14, x15, [sp, #112]
+ stp x12, x13, [sp, #96]
+ stp x10, x11, [sp, #80]
+ stp x8, x9, [sp, #64]
+ stp x6, x7, [sp, #48]
+ stp x4, x5, [sp, #32]
+ stp x2, x3, [sp, #16]
+
+ // Pass the address of the frame to __hwasan_tag_mismatch4, so that it can
+ // extract the saved registers from this frame without having to worry about
+ // finding this frame.
+ mov x2, sp
+
+ bl __hwasan_tag_mismatch4
+ CFI_ENDPROC
+
+.Lfunc_end0:
+ .size __hwasan_tag_mismatch, .Lfunc_end0-__hwasan_tag_mismatch
+
+#endif // defined(__aarch64__)
+
+// We do not need executable stack.
+NO_EXEC_STACK_DIRECTIVE
+
+GNU_PROPERTY_BTI_PAC
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_tag_mismatch_riscv64.S b/contrib/libs/clang16-rt/lib/hwasan/hwasan_tag_mismatch_riscv64.S
new file mode 100644
index 00000000000..487a042405b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_tag_mismatch_riscv64.S
@@ -0,0 +1,132 @@
+#include "sanitizer_common/sanitizer_asm.h"
+
+// The content of this file is RISCV64-only:
+#if defined(__riscv) && (__riscv_xlen == 64)
+
+// The responsibility of the HWASan entry point in compiler-rt is to primarily
+// readjust the stack from the callee and save the current register values to
+// the stack.
+// This entry point function should be called from a __hwasan_check_* symbol.
+// These are generated during a lowering pass in the backend, and are found in
+// RISCVAsmPrinter::EmitHwasanMemaccessSymbols(). Please look there for
+// further information.
+// The __hwasan_check_* caller of this function should have expanded the stack
+// and saved the previous values of x10(arg0), x11(arg1), x1(ra), and x8(fp).
+// This function will "consume" these saved values and treats it as part of its
+// own stack frame. In this sense, the __hwasan_check_* callee and this function
+// "share" a stack frame. This allows us to omit having unwinding information
+// (.cfi_*) present in every __hwasan_check_* function, therefore reducing binary size.
+// This is particularly important as hwasan_check_* instances are duplicated in every
+// translation unit where HWASan is enabled.
+// This function calls HwasanTagMismatch to step back into the C++ code that
+// completes the stack unwinding and error printing. This function is is not
+// permitted to return.
+
+
+// | ... |
+// | ... |
+// | Previous stack frames... |
+// +=================================+
+// | ... |
+// | |
+// | Stack frame space for x12 - x31.|
+// | |
+// | ... |
+// +---------------------------------+ <-- [SP + 96]
+// | Saved x11(arg1), as |
+// | __hwasan_check_* clobbers it. |
+// +---------------------------------+ <-- [SP + 88]
+// | Saved x10(arg0), as |
+// | __hwasan_check_* clobbers it. |
+// +---------------------------------+ <-- [SP + 80]
+// | |
+// | Stack frame space for x9. |
+// +---------------------------------+ <-- [SP + 72]
+// | |
+// | Saved x8(fp), as |
+// | __hwasan_check_* clobbers it. |
+// +---------------------------------+ <-- [SP + 64]
+// | ... |
+// | |
+// | Stack frame space for x2 - x7. |
+// | |
+// | ... |
+// +---------------------------------+ <-- [SP + 16]
+// | Return address (x1) for caller |
+// | of __hwasan_check_*. |
+// +---------------------------------+ <-- [SP + 8]
+// | Reserved place for x0, possibly |
+// | junk, since we don't save it. |
+// +---------------------------------+ <-- [x2 / SP]
+
+// This function takes two arguments:
+// * x10/a0: The data address.
+// * x11/a1: The encoded access info for the failing access.
+
+.section .text
+.file "hwasan_tag_mismatch_riscv64.S"
+
+.global __hwasan_tag_mismatch_v2
+ASM_TYPE_FUNCTION(__hwasan_tag_mismatch_v2)
+__hwasan_tag_mismatch_v2:
+ CFI_STARTPROC
+
+ // Set the CFA to be the return address for caller of __hwasan_check_*. Note
+ // that we do not emit CFI predicates to describe the contents of this stack
+ // frame, as this proxy entry point should never be debugged. The contents
+ // are static and are handled by the unwinder after calling
+ // __hwasan_tag_mismatch. The frame pointer is already correctly setup
+ // by __hwasan_check_*.
+ addi fp, sp, 256
+ CFI_DEF_CFA(fp, 0)
+ CFI_OFFSET(ra, -248)
+ CFI_OFFSET(fp, -192)
+
+ // Save the rest of the registers into the preallocated space left by
+ // __hwasan_check.
+ sd x31, 248(sp)
+ sd x30, 240(sp)
+ sd x29, 232(sp)
+ sd x28, 224(sp)
+ sd x27, 216(sp)
+ sd x26, 208(sp)
+ sd x25, 200(sp)
+ sd x24, 192(sp)
+ sd x23, 184(sp)
+ sd x22, 176(sp)
+ sd x21, 168(sp)
+ sd x20, 160(sp)
+ sd x19, 152(sp)
+ sd x18, 144(sp)
+ sd x17, 136(sp)
+ sd x16, 128(sp)
+ sd x15, 120(sp)
+ sd x14, 112(sp)
+ sd x13, 104(sp)
+ sd x12, 96(sp)
+ // sd x11, 88(sp) ; already saved
+ // sd x10, 80(sp) ; already saved
+ sd x9, 72(sp)
+ // sd x8, 64(sp) ; already saved
+ sd x7, 56(sp)
+ sd x6, 48(sp)
+ sd x5, 40(sp)
+ sd x4, 32(sp)
+ sd x3, 24(sp)
+ sd x2, 16(sp)
+ // sd x1, 8(sp) ; already saved
+ // sd x0, 0(sp) ; don't store zero register
+
+ // Pass the address of the frame to __hwasan_tag_mismatch4, so that it can
+ // extract the saved registers from this frame without having to worry about
+ // finding this frame.
+ mv x12, sp
+
+ call __hwasan_tag_mismatch4
+ CFI_ENDPROC
+ASM_SIZE(__hwasan_tag_mismatch_v2)
+
+#endif // defined(__riscv) && (__riscv_xlen == 64)
+
+// We do not need executable stack.
+NO_EXEC_STACK_DIRECTIVE
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_thread.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_thread.cpp
new file mode 100644
index 00000000000..4a78f606290
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_thread.cpp
@@ -0,0 +1,204 @@
+
+#include "hwasan_thread.h"
+
+#include "hwasan.h"
+#include "hwasan_interface_internal.h"
+#include "hwasan_mapping.h"
+#include "hwasan_poisoning.h"
+#include "hwasan_thread_list.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_file.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+
+namespace __hwasan {
+
+static u32 RandomSeed() {
+ u32 seed;
+ do {
+ if (UNLIKELY(!GetRandom(reinterpret_cast<void *>(&seed), sizeof(seed),
+ /*blocking=*/false))) {
+ seed = static_cast<u32>(
+ (NanoTime() >> 12) ^
+ (reinterpret_cast<uptr>(__builtin_frame_address(0)) >> 4));
+ }
+ } while (!seed);
+ return seed;
+}
+
+void Thread::InitRandomState() {
+ random_state_ = flags()->random_tags ? RandomSeed() : unique_id_;
+ random_state_inited_ = true;
+
+ // Push a random number of zeros onto the ring buffer so that the first stack
+ // tag base will be random.
+ for (tag_t i = 0, e = GenerateRandomTag(); i != e; ++i)
+ stack_allocations_->push(0);
+}
+
+void Thread::Init(uptr stack_buffer_start, uptr stack_buffer_size,
+ const InitState *state) {
+ CHECK_EQ(0, unique_id_); // try to catch bad stack reuse
+ CHECK_EQ(0, stack_top_);
+ CHECK_EQ(0, stack_bottom_);
+
+ static atomic_uint64_t unique_id;
+ unique_id_ = atomic_fetch_add(&unique_id, 1, memory_order_relaxed);
+
+ if (auto sz = flags()->heap_history_size)
+ heap_allocations_ = HeapAllocationsRingBuffer::New(sz);
+
+#if !SANITIZER_FUCHSIA
+ // Do not initialize the stack ring buffer just yet on Fuchsia. Threads will
+ // be initialized before we enter the thread itself, so we will instead call
+ // this later.
+ InitStackRingBuffer(stack_buffer_start, stack_buffer_size);
+#endif
+ InitStackAndTls(state);
+ dtls_ = DTLS_Get();
+}
+
+void Thread::InitStackRingBuffer(uptr stack_buffer_start,
+ uptr stack_buffer_size) {
+ HwasanTSDThreadInit(); // Only needed with interceptors.
+ uptr *ThreadLong = GetCurrentThreadLongPtr();
+ // The following implicitly sets (this) as the current thread.
+ stack_allocations_ = new (ThreadLong)
+ StackAllocationsRingBuffer((void *)stack_buffer_start, stack_buffer_size);
+ // Check that it worked.
+ CHECK_EQ(GetCurrentThread(), this);
+
+ // ScopedTaggingDisable needs GetCurrentThread to be set up.
+ ScopedTaggingDisabler disabler;
+
+ if (stack_bottom_) {
+ int local;
+ CHECK(AddrIsInStack((uptr)&local));
+ CHECK(MemIsApp(stack_bottom_));
+ CHECK(MemIsApp(stack_top_ - 1));
+ }
+
+ if (flags()->verbose_threads) {
+ if (IsMainThread()) {
+ Printf("sizeof(Thread): %zd sizeof(HeapRB): %zd sizeof(StackRB): %zd\n",
+ sizeof(Thread), heap_allocations_->SizeInBytes(),
+ stack_allocations_->size() * sizeof(uptr));
+ }
+ Print("Creating : ");
+ }
+}
+
+void Thread::ClearShadowForThreadStackAndTLS() {
+ if (stack_top_ != stack_bottom_)
+ TagMemory(stack_bottom_, stack_top_ - stack_bottom_, 0);
+ if (tls_begin_ != tls_end_)
+ TagMemory(tls_begin_, tls_end_ - tls_begin_, 0);
+}
+
+void Thread::Destroy() {
+ if (flags()->verbose_threads)
+ Print("Destroying: ");
+ AllocatorSwallowThreadLocalCache(allocator_cache());
+ ClearShadowForThreadStackAndTLS();
+ if (heap_allocations_)
+ heap_allocations_->Delete();
+ DTLS_Destroy();
+ // Unregister this as the current thread.
+ // Instrumented code can not run on this thread from this point onwards, but
+ // malloc/free can still be served. Glibc may call free() very late, after all
+ // TSD destructors are done.
+ CHECK_EQ(GetCurrentThread(), this);
+ *GetCurrentThreadLongPtr() = 0;
+}
+
+void Thread::Print(const char *Prefix) {
+ Printf("%sT%zd %p stack: [%p,%p) sz: %zd tls: [%p,%p)\n", Prefix, unique_id_,
+ (void *)this, stack_bottom(), stack_top(),
+ stack_top() - stack_bottom(), tls_begin(), tls_end());
+}
+
+static u32 xorshift(u32 state) {
+ state ^= state << 13;
+ state ^= state >> 17;
+ state ^= state << 5;
+ return state;
+}
+
+// Generate a (pseudo-)random non-zero tag.
+tag_t Thread::GenerateRandomTag(uptr num_bits) {
+ DCHECK_GT(num_bits, 0);
+ if (tagging_disabled_)
+ return 0;
+ tag_t tag;
+ const uptr tag_mask = (1ULL << num_bits) - 1;
+ do {
+ if (flags()->random_tags) {
+ if (!random_buffer_) {
+ EnsureRandomStateInited();
+ random_buffer_ = random_state_ = xorshift(random_state_);
+ }
+ CHECK(random_buffer_);
+ tag = random_buffer_ & tag_mask;
+ random_buffer_ >>= num_bits;
+ } else {
+ EnsureRandomStateInited();
+ random_state_ += 1;
+ tag = random_state_ & tag_mask;
+ }
+ } while (!tag);
+ return tag;
+}
+
+} // namespace __hwasan
+
+// --- Implementation of LSan-specific functions --- {{{1
+namespace __lsan {
+
+static __hwasan::HwasanThreadList *GetHwasanThreadListLocked() {
+ auto &tl = __hwasan::hwasanThreadList();
+ tl.CheckLocked();
+ return &tl;
+}
+
+static __hwasan::Thread *GetThreadByOsIDLocked(tid_t os_id) {
+ return GetHwasanThreadListLocked()->FindThreadLocked(
+ [os_id](__hwasan::Thread *t) { return t->os_id() == os_id; });
+}
+
+void LockThreadRegistry() { __hwasan::hwasanThreadList().Lock(); }
+
+void UnlockThreadRegistry() { __hwasan::hwasanThreadList().Unlock(); }
+
+void EnsureMainThreadIDIsCorrect() {
+ auto *t = __hwasan::GetCurrentThread();
+ if (t && (t->IsMainThread()))
+ t->set_os_id(GetTid());
+}
+
+bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
+ uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
+ uptr *cache_end, DTLS **dtls) {
+ auto *t = GetThreadByOsIDLocked(os_id);
+ if (!t)
+ return false;
+ *stack_begin = t->stack_bottom();
+ *stack_end = t->stack_top();
+ *tls_begin = t->tls_begin();
+ *tls_end = t->tls_end();
+ // Fixme: is this correct for HWASan.
+ *cache_begin = 0;
+ *cache_end = 0;
+ *dtls = t->dtls();
+ return true;
+}
+
+void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {}
+
+void GetThreadExtraStackRangesLocked(tid_t os_id,
+ InternalMmapVector<Range> *ranges) {}
+void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges) {}
+
+void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs) {}
+void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads) {}
+
+} // namespace __lsan
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_thread.h b/contrib/libs/clang16-rt/lib/hwasan/hwasan_thread.h
new file mode 100644
index 00000000000..9727585ef75
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_thread.h
@@ -0,0 +1,120 @@
+//===-- hwasan_thread.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_THREAD_H
+#define HWASAN_THREAD_H
+
+#include "hwasan_allocator.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_ring_buffer.h"
+
+namespace __hwasan {
+
+typedef __sanitizer::CompactRingBuffer<uptr> StackAllocationsRingBuffer;
+
+class Thread {
+ public:
+ // These are optional parameters that can be passed to Init.
+ struct InitState;
+
+ void Init(uptr stack_buffer_start, uptr stack_buffer_size,
+ const InitState *state = nullptr);
+
+ void InitStackAndTls(const InitState *state = nullptr);
+
+ // Must be called from the thread itself.
+ void InitStackRingBuffer(uptr stack_buffer_start, uptr stack_buffer_size);
+
+ inline void EnsureRandomStateInited() {
+ if (UNLIKELY(!random_state_inited_))
+ InitRandomState();
+ }
+
+ void Destroy();
+
+ uptr stack_top() { return stack_top_; }
+ uptr stack_bottom() { return stack_bottom_; }
+ uptr stack_size() { return stack_top() - stack_bottom(); }
+ uptr tls_begin() { return tls_begin_; }
+ uptr tls_end() { return tls_end_; }
+ DTLS *dtls() { return dtls_; }
+ bool IsMainThread() { return unique_id_ == 0; }
+
+ bool AddrIsInStack(uptr addr) {
+ return addr >= stack_bottom_ && addr < stack_top_;
+ }
+
+ AllocatorCache *allocator_cache() { return &allocator_cache_; }
+ HeapAllocationsRingBuffer *heap_allocations() { return heap_allocations_; }
+ StackAllocationsRingBuffer *stack_allocations() { return stack_allocations_; }
+
+ tag_t GenerateRandomTag(uptr num_bits = kTagBits);
+
+ void DisableTagging() { tagging_disabled_++; }
+ void EnableTagging() { tagging_disabled_--; }
+
+ u32 unique_id() const { return unique_id_; }
+ void Announce() {
+ if (announced_) return;
+ announced_ = true;
+ Print("Thread: ");
+ }
+
+ tid_t os_id() const { return os_id_; }
+ void set_os_id(tid_t os_id) { os_id_ = os_id; }
+
+ uptr &vfork_spill() { return vfork_spill_; }
+
+ private:
+ // NOTE: There is no Thread constructor. It is allocated
+ // via mmap() and *must* be valid in zero-initialized state.
+ void ClearShadowForThreadStackAndTLS();
+ void Print(const char *prefix);
+ void InitRandomState();
+ uptr vfork_spill_;
+ uptr stack_top_;
+ uptr stack_bottom_;
+ uptr tls_begin_;
+ uptr tls_end_;
+ DTLS *dtls_;
+
+ u32 random_state_;
+ u32 random_buffer_;
+
+ AllocatorCache allocator_cache_;
+ HeapAllocationsRingBuffer *heap_allocations_;
+ StackAllocationsRingBuffer *stack_allocations_;
+
+ u32 unique_id_; // counting from zero.
+
+ tid_t os_id_;
+
+ u32 tagging_disabled_; // if non-zero, malloc uses zero tag in this thread.
+
+ bool announced_;
+
+ bool random_state_inited_; // Whether InitRandomState() has been called.
+
+ friend struct ThreadListHead;
+};
+
+Thread *GetCurrentThread();
+uptr *GetCurrentThreadLongPtr();
+
+struct ScopedTaggingDisabler {
+ ScopedTaggingDisabler() { GetCurrentThread()->DisableTagging(); }
+ ~ScopedTaggingDisabler() { GetCurrentThread()->EnableTagging(); }
+};
+
+} // namespace __hwasan
+
+#endif // HWASAN_THREAD_H
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_thread_list.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_thread_list.cpp
new file mode 100644
index 00000000000..fa46e658b69
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_thread_list.cpp
@@ -0,0 +1,15 @@
+#include "hwasan_thread_list.h"
+
+namespace __hwasan {
+static ALIGNED(16) char thread_list_placeholder[sizeof(HwasanThreadList)];
+static HwasanThreadList *hwasan_thread_list;
+
+HwasanThreadList &hwasanThreadList() { return *hwasan_thread_list; }
+
+void InitThreadList(uptr storage, uptr size) {
+ CHECK(hwasan_thread_list == nullptr);
+ hwasan_thread_list =
+ new (thread_list_placeholder) HwasanThreadList(storage, size);
+}
+
+} // namespace __hwasan
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_thread_list.h b/contrib/libs/clang16-rt/lib/hwasan/hwasan_thread_list.h
new file mode 100644
index 00000000000..97485b195b6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_thread_list.h
@@ -0,0 +1,226 @@
+//===-- hwasan_thread_list.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+// HwasanThreadList is a registry for live threads, as well as an allocator for
+// HwasanThread objects and their stack history ring buffers. There are
+// constraints on memory layout of the shadow region and CompactRingBuffer that
+// are part of the ABI contract between compiler-rt and llvm.
+//
+// * Start of the shadow memory region is aligned to 2**kShadowBaseAlignment.
+// * All stack ring buffers are located within (2**kShadowBaseAlignment)
+// sized region below and adjacent to the shadow region.
+// * Each ring buffer has a size of (2**N)*4096 where N is in [0, 8), and is
+// aligned to twice its size. The value of N can be different for each buffer.
+//
+// These constrains guarantee that, given an address A of any element of the
+// ring buffer,
+// A_next = (A + sizeof(uptr)) & ~((1 << (N + 13)) - 1)
+// is the address of the next element of that ring buffer (with wrap-around).
+// And, with K = kShadowBaseAlignment,
+// S = (A | ((1 << K) - 1)) + 1
+// (align up to kShadowBaseAlignment) is the start of the shadow region.
+//
+// These calculations are used in compiler instrumentation to update the ring
+// buffer and obtain the base address of shadow using only two inputs: address
+// of the current element of the ring buffer, and N (i.e. size of the ring
+// buffer). Since the value of N is very limited, we pack both inputs into a
+// single thread-local word as
+// (1 << (N + 56)) | A
+// See the implementation of class CompactRingBuffer, which is what is stored in
+// said thread-local word.
+//
+// Note the unusual way of aligning up the address of the shadow:
+// (A | ((1 << K) - 1)) + 1
+// It is only correct if A is not already equal to the shadow base address, but
+// it saves 2 instructions on AArch64.
+
+#include "hwasan.h"
+#include "hwasan_allocator.h"
+#include "hwasan_flags.h"
+#include "hwasan_thread.h"
+
+#include "sanitizer_common/sanitizer_placement_new.h"
+
+namespace __hwasan {
+
+static uptr RingBufferSize() {
+ uptr desired_bytes = flags()->stack_history_size * sizeof(uptr);
+ // FIXME: increase the limit to 8 once this bug is fixed:
+ // https://bugs.llvm.org/show_bug.cgi?id=39030
+ for (int shift = 1; shift < 7; ++shift) {
+ uptr size = 4096 * (1ULL << shift);
+ if (size >= desired_bytes)
+ return size;
+ }
+ Printf("stack history size too large: %d\n", flags()->stack_history_size);
+ CHECK(0);
+ return 0;
+}
+
+struct ThreadStats {
+ uptr n_live_threads;
+ uptr total_stack_size;
+};
+
+class SANITIZER_MUTEX HwasanThreadList {
+ public:
+ HwasanThreadList(uptr storage, uptr size)
+ : free_space_(storage), free_space_end_(storage + size) {
+ // [storage, storage + size) is used as a vector of
+ // thread_alloc_size_-sized, ring_buffer_size_*2-aligned elements.
+ // Each element contains
+ // * a ring buffer at offset 0,
+ // * a Thread object at offset ring_buffer_size_.
+ ring_buffer_size_ = RingBufferSize();
+ thread_alloc_size_ =
+ RoundUpTo(ring_buffer_size_ + sizeof(Thread), ring_buffer_size_ * 2);
+ }
+
+ Thread *CreateCurrentThread(const Thread::InitState *state = nullptr)
+ SANITIZER_EXCLUDES(free_list_mutex_, live_list_mutex_) {
+ Thread *t = nullptr;
+ {
+ SpinMutexLock l(&free_list_mutex_);
+ if (!free_list_.empty()) {
+ t = free_list_.back();
+ free_list_.pop_back();
+ }
+ }
+ if (t) {
+ uptr start = (uptr)t - ring_buffer_size_;
+ internal_memset((void *)start, 0, ring_buffer_size_ + sizeof(Thread));
+ } else {
+ t = AllocThread();
+ }
+ {
+ SpinMutexLock l(&live_list_mutex_);
+ live_list_.push_back(t);
+ }
+ t->Init((uptr)t - ring_buffer_size_, ring_buffer_size_, state);
+ AddThreadStats(t);
+ return t;
+ }
+
+ void DontNeedThread(Thread *t) {
+ uptr start = (uptr)t - ring_buffer_size_;
+ ReleaseMemoryPagesToOS(start, start + thread_alloc_size_);
+ }
+
+ void RemoveThreadFromLiveList(Thread *t)
+ SANITIZER_EXCLUDES(live_list_mutex_) {
+ SpinMutexLock l(&live_list_mutex_);
+ for (Thread *&t2 : live_list_)
+ if (t2 == t) {
+ // To remove t2, copy the last element of the list in t2's position, and
+ // pop_back(). This works even if t2 is itself the last element.
+ t2 = live_list_.back();
+ live_list_.pop_back();
+ return;
+ }
+ CHECK(0 && "thread not found in live list");
+ }
+
+ void ReleaseThread(Thread *t) SANITIZER_EXCLUDES(free_list_mutex_) {
+ RemoveThreadStats(t);
+ t->Destroy();
+ DontNeedThread(t);
+ RemoveThreadFromLiveList(t);
+ SpinMutexLock l(&free_list_mutex_);
+ free_list_.push_back(t);
+ }
+
+ Thread *GetThreadByBufferAddress(uptr p) {
+ return (Thread *)(RoundDownTo(p, ring_buffer_size_ * 2) +
+ ring_buffer_size_);
+ }
+
+ uptr MemoryUsedPerThread() {
+ uptr res = sizeof(Thread) + ring_buffer_size_;
+ if (auto sz = flags()->heap_history_size)
+ res += HeapAllocationsRingBuffer::SizeInBytes(sz);
+ return res;
+ }
+
+ template <class CB>
+ void VisitAllLiveThreads(CB cb) SANITIZER_EXCLUDES(live_list_mutex_) {
+ SpinMutexLock l(&live_list_mutex_);
+ for (Thread *t : live_list_) cb(t);
+ }
+
+ template <class CB>
+ Thread *FindThreadLocked(CB cb) SANITIZER_CHECK_LOCKED(stats_mutex_) {
+ CheckLocked();
+ for (Thread *t : live_list_)
+ if (cb(t))
+ return t;
+ return nullptr;
+ }
+
+ void AddThreadStats(Thread *t) SANITIZER_EXCLUDES(stats_mutex_) {
+ SpinMutexLock l(&stats_mutex_);
+ stats_.n_live_threads++;
+ stats_.total_stack_size += t->stack_size();
+ }
+
+ void RemoveThreadStats(Thread *t) SANITIZER_EXCLUDES(stats_mutex_) {
+ SpinMutexLock l(&stats_mutex_);
+ stats_.n_live_threads--;
+ stats_.total_stack_size -= t->stack_size();
+ }
+
+ ThreadStats GetThreadStats() SANITIZER_EXCLUDES(stats_mutex_) {
+ SpinMutexLock l(&stats_mutex_);
+ return stats_;
+ }
+
+ uptr GetRingBufferSize() const { return ring_buffer_size_; }
+
+ void Lock() SANITIZER_ACQUIRE(live_list_mutex_) { live_list_mutex_.Lock(); }
+ void CheckLocked() const SANITIZER_CHECK_LOCKED(live_list_mutex_) {
+ live_list_mutex_.CheckLocked();
+ }
+ void Unlock() SANITIZER_RELEASE(live_list_mutex_) {
+ live_list_mutex_.Unlock();
+ }
+
+ private:
+ Thread *AllocThread() {
+ SpinMutexLock l(&free_space_mutex_);
+ uptr align = ring_buffer_size_ * 2;
+ CHECK(IsAligned(free_space_, align));
+ Thread *t = (Thread *)(free_space_ + ring_buffer_size_);
+ free_space_ += thread_alloc_size_;
+ CHECK(free_space_ <= free_space_end_ && "out of thread memory");
+ return t;
+ }
+
+ SpinMutex free_space_mutex_;
+ uptr free_space_;
+ uptr free_space_end_;
+ uptr ring_buffer_size_;
+ uptr thread_alloc_size_;
+
+ SpinMutex free_list_mutex_;
+ InternalMmapVector<Thread *> free_list_
+ SANITIZER_GUARDED_BY(free_list_mutex_);
+ SpinMutex live_list_mutex_;
+ InternalMmapVector<Thread *> live_list_
+ SANITIZER_GUARDED_BY(live_list_mutex_);
+
+ SpinMutex stats_mutex_;
+ ThreadStats stats_ SANITIZER_GUARDED_BY(stats_mutex_);
+};
+
+void InitThreadList(uptr storage, uptr size);
+HwasanThreadList &hwasanThreadList();
+
+} // namespace __hwasan
diff --git a/contrib/libs/clang16-rt/lib/hwasan/hwasan_type_test.cpp b/contrib/libs/clang16-rt/lib/hwasan/hwasan_type_test.cpp
new file mode 100644
index 00000000000..5307073fb40
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/hwasan_type_test.cpp
@@ -0,0 +1,25 @@
+//===-- hwasan_type_test.cpp ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// Compile-time tests of the internal type definitions.
+//===----------------------------------------------------------------------===//
+
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_platform_limits_posix.h"
+#include "hwasan.h"
+#include <setjmp.h>
+
+#define CHECK_TYPE_SIZE_FITS(TYPE) \
+ COMPILER_CHECK(sizeof(__hw_##TYPE) <= sizeof(TYPE))
+
+#if HWASAN_WITH_INTERCEPTORS
+CHECK_TYPE_SIZE_FITS(jmp_buf);
+CHECK_TYPE_SIZE_FITS(sigjmp_buf);
+#endif
diff --git a/contrib/libs/clang16-rt/lib/hwasan/ya.make b/contrib/libs/clang16-rt/lib/hwasan/ya.make
new file mode 100644
index 00000000000..da9b1d285a8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan/ya.make
@@ -0,0 +1,152 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.hwasan${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHAVE_RPC_XDR_H=0
+ -DHWASAN_WITH_INTERCEPTORS=1
+ -DUBSAN_CAN_USE_CXXABI
+ -ffreestanding
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ hwasan/hwasan.cpp
+ hwasan/hwasan_allocation_functions.cpp
+ hwasan/hwasan_allocator.cpp
+ hwasan/hwasan_dynamic_shadow.cpp
+ hwasan/hwasan_exceptions.cpp
+ hwasan/hwasan_fuchsia.cpp
+ hwasan/hwasan_globals.cpp
+ hwasan/hwasan_interceptors.cpp
+ hwasan/hwasan_interceptors_vfork.S
+ hwasan/hwasan_linux.cpp
+ hwasan/hwasan_memintrinsics.cpp
+ hwasan/hwasan_poisoning.cpp
+ hwasan/hwasan_preinit.cpp
+ hwasan/hwasan_report.cpp
+ hwasan/hwasan_setjmp_aarch64.S
+ hwasan/hwasan_setjmp_riscv64.S
+ hwasan/hwasan_setjmp_x86_64.S
+ hwasan/hwasan_tag_mismatch_aarch64.S
+ hwasan/hwasan_tag_mismatch_riscv64.S
+ hwasan/hwasan_thread.cpp
+ hwasan/hwasan_thread_list.cpp
+ hwasan/hwasan_type_test.cpp
+ interception/interception_linux.cpp
+ interception/interception_mac.cpp
+ interception/interception_type_test.cpp
+ interception/interception_win.cpp
+ lsan/lsan_common.cpp
+ lsan/lsan_common_fuchsia.cpp
+ lsan/lsan_common_linux.cpp
+ lsan/lsan_common_mac.cpp
+ sanitizer_common/sancov_flags.cpp
+ sanitizer_common/sanitizer_allocator.cpp
+ sanitizer_common/sanitizer_allocator_checks.cpp
+ sanitizer_common/sanitizer_allocator_report.cpp
+ sanitizer_common/sanitizer_chained_origin_depot.cpp
+ sanitizer_common/sanitizer_common.cpp
+ sanitizer_common/sanitizer_common_libcdep.cpp
+ sanitizer_common/sanitizer_coverage_fuchsia.cpp
+ sanitizer_common/sanitizer_coverage_libcdep_new.cpp
+ sanitizer_common/sanitizer_coverage_win_sections.cpp
+ sanitizer_common/sanitizer_deadlock_detector1.cpp
+ sanitizer_common/sanitizer_deadlock_detector2.cpp
+ sanitizer_common/sanitizer_errno.cpp
+ sanitizer_common/sanitizer_file.cpp
+ sanitizer_common/sanitizer_flag_parser.cpp
+ sanitizer_common/sanitizer_flags.cpp
+ sanitizer_common/sanitizer_fuchsia.cpp
+ sanitizer_common/sanitizer_libc.cpp
+ sanitizer_common/sanitizer_libignore.cpp
+ sanitizer_common/sanitizer_linux.cpp
+ sanitizer_common/sanitizer_linux_libcdep.cpp
+ sanitizer_common/sanitizer_linux_s390.cpp
+ sanitizer_common/sanitizer_mac.cpp
+ sanitizer_common/sanitizer_mac_libcdep.cpp
+ sanitizer_common/sanitizer_mutex.cpp
+ sanitizer_common/sanitizer_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+ sanitizer_common/sanitizer_platform_limits_linux.cpp
+ sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_posix.cpp
+ sanitizer_common/sanitizer_platform_limits_solaris.cpp
+ sanitizer_common/sanitizer_posix.cpp
+ sanitizer_common/sanitizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_printf.cpp
+ sanitizer_common/sanitizer_procmaps_bsd.cpp
+ sanitizer_common/sanitizer_procmaps_common.cpp
+ sanitizer_common/sanitizer_procmaps_fuchsia.cpp
+ sanitizer_common/sanitizer_procmaps_linux.cpp
+ sanitizer_common/sanitizer_procmaps_mac.cpp
+ sanitizer_common/sanitizer_procmaps_solaris.cpp
+ sanitizer_common/sanitizer_solaris.cpp
+ sanitizer_common/sanitizer_stack_store.cpp
+ sanitizer_common/sanitizer_stackdepot.cpp
+ sanitizer_common/sanitizer_stacktrace.cpp
+ sanitizer_common/sanitizer_stacktrace_libcdep.cpp
+ sanitizer_common/sanitizer_stacktrace_printer.cpp
+ sanitizer_common/sanitizer_stacktrace_sparc.cpp
+ sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
+ sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_mac.cpp
+ sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_win.cpp
+ sanitizer_common/sanitizer_suppressions.cpp
+ sanitizer_common/sanitizer_symbolizer.cpp
+ sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
+ sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_mac.cpp
+ sanitizer_common/sanitizer_symbolizer_markup.cpp
+ sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_report.cpp
+ sanitizer_common/sanitizer_symbolizer_win.cpp
+ sanitizer_common/sanitizer_termination.cpp
+ sanitizer_common/sanitizer_thread_registry.cpp
+ sanitizer_common/sanitizer_tls_get_addr.cpp
+ sanitizer_common/sanitizer_type_traits.cpp
+ sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
+ sanitizer_common/sanitizer_unwind_win.cpp
+ sanitizer_common/sanitizer_win.cpp
+ ubsan/ubsan_diag.cpp
+ ubsan/ubsan_flags.cpp
+ ubsan/ubsan_handlers.cpp
+ ubsan/ubsan_init.cpp
+ ubsan/ubsan_monitor.cpp
+ ubsan/ubsan_value.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/hwasan_aliases/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/hwasan_aliases/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan_aliases/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/hwasan_aliases/ya.make b/contrib/libs/clang16-rt/lib/hwasan_aliases/ya.make
new file mode 100644
index 00000000000..fa8e16ee84e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan_aliases/ya.make
@@ -0,0 +1,153 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.hwasan_aliases${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHAVE_RPC_XDR_H=0
+ -DHWASAN_ALIASING_MODE
+ -DHWASAN_WITH_INTERCEPTORS=1
+ -DUBSAN_CAN_USE_CXXABI
+ -ffreestanding
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ hwasan/hwasan.cpp
+ hwasan/hwasan_allocation_functions.cpp
+ hwasan/hwasan_allocator.cpp
+ hwasan/hwasan_dynamic_shadow.cpp
+ hwasan/hwasan_exceptions.cpp
+ hwasan/hwasan_fuchsia.cpp
+ hwasan/hwasan_globals.cpp
+ hwasan/hwasan_interceptors.cpp
+ hwasan/hwasan_interceptors_vfork.S
+ hwasan/hwasan_linux.cpp
+ hwasan/hwasan_memintrinsics.cpp
+ hwasan/hwasan_poisoning.cpp
+ hwasan/hwasan_preinit.cpp
+ hwasan/hwasan_report.cpp
+ hwasan/hwasan_setjmp_aarch64.S
+ hwasan/hwasan_setjmp_riscv64.S
+ hwasan/hwasan_setjmp_x86_64.S
+ hwasan/hwasan_tag_mismatch_aarch64.S
+ hwasan/hwasan_tag_mismatch_riscv64.S
+ hwasan/hwasan_thread.cpp
+ hwasan/hwasan_thread_list.cpp
+ hwasan/hwasan_type_test.cpp
+ interception/interception_linux.cpp
+ interception/interception_mac.cpp
+ interception/interception_type_test.cpp
+ interception/interception_win.cpp
+ lsan/lsan_common.cpp
+ lsan/lsan_common_fuchsia.cpp
+ lsan/lsan_common_linux.cpp
+ lsan/lsan_common_mac.cpp
+ sanitizer_common/sancov_flags.cpp
+ sanitizer_common/sanitizer_allocator.cpp
+ sanitizer_common/sanitizer_allocator_checks.cpp
+ sanitizer_common/sanitizer_allocator_report.cpp
+ sanitizer_common/sanitizer_chained_origin_depot.cpp
+ sanitizer_common/sanitizer_common.cpp
+ sanitizer_common/sanitizer_common_libcdep.cpp
+ sanitizer_common/sanitizer_coverage_fuchsia.cpp
+ sanitizer_common/sanitizer_coverage_libcdep_new.cpp
+ sanitizer_common/sanitizer_coverage_win_sections.cpp
+ sanitizer_common/sanitizer_deadlock_detector1.cpp
+ sanitizer_common/sanitizer_deadlock_detector2.cpp
+ sanitizer_common/sanitizer_errno.cpp
+ sanitizer_common/sanitizer_file.cpp
+ sanitizer_common/sanitizer_flag_parser.cpp
+ sanitizer_common/sanitizer_flags.cpp
+ sanitizer_common/sanitizer_fuchsia.cpp
+ sanitizer_common/sanitizer_libc.cpp
+ sanitizer_common/sanitizer_libignore.cpp
+ sanitizer_common/sanitizer_linux.cpp
+ sanitizer_common/sanitizer_linux_libcdep.cpp
+ sanitizer_common/sanitizer_linux_s390.cpp
+ sanitizer_common/sanitizer_mac.cpp
+ sanitizer_common/sanitizer_mac_libcdep.cpp
+ sanitizer_common/sanitizer_mutex.cpp
+ sanitizer_common/sanitizer_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+ sanitizer_common/sanitizer_platform_limits_linux.cpp
+ sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_posix.cpp
+ sanitizer_common/sanitizer_platform_limits_solaris.cpp
+ sanitizer_common/sanitizer_posix.cpp
+ sanitizer_common/sanitizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_printf.cpp
+ sanitizer_common/sanitizer_procmaps_bsd.cpp
+ sanitizer_common/sanitizer_procmaps_common.cpp
+ sanitizer_common/sanitizer_procmaps_fuchsia.cpp
+ sanitizer_common/sanitizer_procmaps_linux.cpp
+ sanitizer_common/sanitizer_procmaps_mac.cpp
+ sanitizer_common/sanitizer_procmaps_solaris.cpp
+ sanitizer_common/sanitizer_solaris.cpp
+ sanitizer_common/sanitizer_stack_store.cpp
+ sanitizer_common/sanitizer_stackdepot.cpp
+ sanitizer_common/sanitizer_stacktrace.cpp
+ sanitizer_common/sanitizer_stacktrace_libcdep.cpp
+ sanitizer_common/sanitizer_stacktrace_printer.cpp
+ sanitizer_common/sanitizer_stacktrace_sparc.cpp
+ sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
+ sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_mac.cpp
+ sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_win.cpp
+ sanitizer_common/sanitizer_suppressions.cpp
+ sanitizer_common/sanitizer_symbolizer.cpp
+ sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
+ sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_mac.cpp
+ sanitizer_common/sanitizer_symbolizer_markup.cpp
+ sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_report.cpp
+ sanitizer_common/sanitizer_symbolizer_win.cpp
+ sanitizer_common/sanitizer_termination.cpp
+ sanitizer_common/sanitizer_thread_registry.cpp
+ sanitizer_common/sanitizer_tls_get_addr.cpp
+ sanitizer_common/sanitizer_type_traits.cpp
+ sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
+ sanitizer_common/sanitizer_unwind_win.cpp
+ sanitizer_common/sanitizer_win.cpp
+ ubsan/ubsan_diag.cpp
+ ubsan/ubsan_flags.cpp
+ ubsan/ubsan_handlers.cpp
+ ubsan/ubsan_init.cpp
+ ubsan/ubsan_monitor.cpp
+ ubsan/ubsan_value.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/hwasan_aliases_cxx/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/hwasan_aliases_cxx/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan_aliases_cxx/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/hwasan_aliases_cxx/ya.make b/contrib/libs/clang16-rt/lib/hwasan_aliases_cxx/ya.make
new file mode 100644
index 00000000000..b9ab7ef41b9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan_aliases_cxx/ya.make
@@ -0,0 +1,53 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.hwasan_aliases_cxx${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHWASAN_WITH_INTERCEPTORS=1
+ -DUBSAN_CAN_USE_CXXABI
+ -ffreestanding
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -frtti
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ hwasan/hwasan_new_delete.cpp
+ ubsan/ubsan_handlers_cxx.cpp
+ ubsan/ubsan_type_hash.cpp
+ ubsan/ubsan_type_hash_itanium.cpp
+ ubsan/ubsan_type_hash_win.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/hwasan_cxx/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/hwasan_cxx/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan_cxx/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/hwasan_cxx/ya.make b/contrib/libs/clang16-rt/lib/hwasan_cxx/ya.make
new file mode 100644
index 00000000000..f23203d31cc
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/hwasan_cxx/ya.make
@@ -0,0 +1,53 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.hwasan_cxx${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHWASAN_WITH_INTERCEPTORS=1
+ -DUBSAN_CAN_USE_CXXABI
+ -ffreestanding
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -frtti
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ hwasan/hwasan_new_delete.cpp
+ ubsan/ubsan_handlers_cxx.cpp
+ ubsan/ubsan_type_hash.cpp
+ ubsan/ubsan_type_hash_itanium.cpp
+ ubsan/ubsan_type_hash_win.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/interception/interception.h b/contrib/libs/clang16-rt/lib/interception/interception.h
new file mode 100644
index 00000000000..85dd7231c71
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/interception/interception.h
@@ -0,0 +1,295 @@
+//===-- interception.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Machinery for providing replacements/wrappers for system functions.
+//===----------------------------------------------------------------------===//
+
+#ifndef INTERCEPTION_H
+#define INTERCEPTION_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+#if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_APPLE && \
+ !SANITIZER_NETBSD && !SANITIZER_WINDOWS && !SANITIZER_FUCHSIA && \
+ !SANITIZER_SOLARIS
+# error "Interception doesn't work on this operating system."
+#endif
+
+// These typedefs should be used only in the interceptor definitions to replace
+// the standard system types (e.g. SSIZE_T instead of ssize_t)
+typedef __sanitizer::uptr SIZE_T;
+typedef __sanitizer::sptr SSIZE_T;
+typedef __sanitizer::sptr PTRDIFF_T;
+typedef __sanitizer::s64 INTMAX_T;
+typedef __sanitizer::u64 UINTMAX_T;
+typedef __sanitizer::OFF_T OFF_T;
+typedef __sanitizer::OFF64_T OFF64_T;
+
+// How to add an interceptor:
+// Suppose you need to wrap/replace system function (generally, from libc):
+// int foo(const char *bar, double baz);
+// You'll need to:
+// 1) define INTERCEPTOR(int, foo, const char *bar, double baz) { ... } in
+// your source file. See the notes below for cases when
+// INTERCEPTOR_WITH_SUFFIX(...) should be used instead.
+// 2) Call "INTERCEPT_FUNCTION(foo)" prior to the first call of "foo".
+// INTERCEPT_FUNCTION(foo) evaluates to "true" iff the function was
+// intercepted successfully.
+// You can access original function by calling REAL(foo)(bar, baz).
+// By default, REAL(foo) will be visible only inside your interceptor, and if
+// you want to use it in other parts of RTL, you'll need to:
+// 3a) add DECLARE_REAL(int, foo, const char*, double) to a
+// header file.
+// However, if the call "INTERCEPT_FUNCTION(foo)" and definition for
+// INTERCEPTOR(..., foo, ...) are in different files, you'll instead need to:
+// 3b) add DECLARE_REAL_AND_INTERCEPTOR(int, foo, const char*, double)
+// to a header file.
+
+// Notes: 1. Things may not work properly if macro INTERCEPTOR(...) {...} or
+// DECLARE_REAL(...) are located inside namespaces.
+// 2. On Mac you can also use: "OVERRIDE_FUNCTION(foo, zoo)" to
+// effectively redirect calls from "foo" to "zoo". In this case
+// you aren't required to implement
+// INTERCEPTOR(int, foo, const char *bar, double baz) {...}
+// but instead you'll have to add
+// DECLARE_REAL(int, foo, const char *bar, double baz) in your
+// source file (to define a pointer to overriden function).
+// 3. Some Mac functions have symbol variants discriminated by
+// additional suffixes, e.g. _$UNIX2003 (see
+// https://developer.apple.com/library/mac/#releasenotes/Darwin/SymbolVariantsRelNotes/index.html
+// for more details). To intercept such functions you need to use the
+// INTERCEPTOR_WITH_SUFFIX(...) macro.
+
+// How it works:
+// To replace system functions on Linux we just need to declare functions
+// with same names in our library and then obtain the real function pointers
+// using dlsym().
+// There is one complication. A user may also intercept some of the functions
+// we intercept. To resolve this we declare our interceptors with __interceptor_
+// prefix, and then make actual interceptors weak aliases to __interceptor_
+// functions.
+//
+// This is not so on Mac OS, where the two-level namespace makes
+// our replacement functions invisible to other libraries. This may be overcomed
+// using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared
+// libraries in Chromium were noticed when doing so.
+// Instead we create a dylib containing a __DATA,__interpose section that
+// associates library functions with their wrappers. When this dylib is
+// preloaded before an executable using DYLD_INSERT_LIBRARIES, it routes all
+// the calls to interposed functions done through stubs to the wrapper
+// functions.
+// As it's decided at compile time which functions are to be intercepted on Mac,
+// INTERCEPT_FUNCTION() is effectively a no-op on this system.
+
+#if SANITIZER_APPLE
+#include <sys/cdefs.h> // For __DARWIN_ALIAS_C().
+
+// Just a pair of pointers.
+struct interpose_substitution {
+ const __sanitizer::uptr replacement;
+ const __sanitizer::uptr original;
+};
+
+// For a function foo() create a global pair of pointers { wrap_foo, foo } in
+// the __DATA,__interpose section.
+// As a result all the calls to foo() will be routed to wrap_foo() at runtime.
+#define INTERPOSER(func_name) __attribute__((used)) \
+const interpose_substitution substitution_##func_name[] \
+ __attribute__((section("__DATA, __interpose"))) = { \
+ { reinterpret_cast<const uptr>(WRAP(func_name)), \
+ reinterpret_cast<const uptr>(func_name) } \
+}
+
+// For a function foo() and a wrapper function bar() create a global pair
+// of pointers { bar, foo } in the __DATA,__interpose section.
+// As a result all the calls to foo() will be routed to bar() at runtime.
+#define INTERPOSER_2(func_name, wrapper_name) __attribute__((used)) \
+const interpose_substitution substitution_##func_name[] \
+ __attribute__((section("__DATA, __interpose"))) = { \
+ { reinterpret_cast<const uptr>(wrapper_name), \
+ reinterpret_cast<const uptr>(func_name) } \
+}
+
+# define WRAP(x) wrap_##x
+# define WRAPPER_NAME(x) "wrap_"#x
+# define INTERCEPTOR_ATTRIBUTE
+# define DECLARE_WRAPPER(ret_type, func, ...)
+
+#elif SANITIZER_WINDOWS
+# define WRAP(x) __asan_wrap_##x
+# define WRAPPER_NAME(x) "__asan_wrap_"#x
+# define INTERCEPTOR_ATTRIBUTE __declspec(dllexport)
+# define DECLARE_WRAPPER(ret_type, func, ...) \
+ extern "C" ret_type func(__VA_ARGS__);
+# define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \
+ extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__);
+#elif SANITIZER_FREEBSD || SANITIZER_NETBSD
+# define WRAP(x) __interceptor_ ## x
+# define WRAPPER_NAME(x) "__interceptor_" #x
+# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
+// FreeBSD's dynamic linker (incompliantly) gives non-weak symbols higher
+// priority than weak ones so weak aliases won't work for indirect calls
+// in position-independent (-fPIC / -fPIE) mode.
+# define DECLARE_WRAPPER(ret_type, func, ...) \
+ extern "C" ret_type func(__VA_ARGS__) \
+ __attribute__((alias("__interceptor_" #func), visibility("default")));
+#elif !SANITIZER_FUCHSIA
+# define WRAP(x) __interceptor_ ## x
+# define WRAPPER_NAME(x) "__interceptor_" #x
+# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
+# define DECLARE_WRAPPER(ret_type, func, ...) \
+ extern "C" ret_type func(__VA_ARGS__) \
+ __attribute__((weak, alias("__interceptor_" #func), visibility("default")));
+#endif
+
+#if SANITIZER_FUCHSIA
+// There is no general interception at all on Fuchsia.
+// Sanitizer runtimes just define functions directly to preempt them,
+// and have bespoke ways to access the underlying libc functions.
+# error #include <zircon/sanitizer.h>
+# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
+# define REAL(x) __unsanitized_##x
+# define DECLARE_REAL(ret_type, func, ...)
+#elif !SANITIZER_APPLE
+# define PTR_TO_REAL(x) real_##x
+# define REAL(x) __interception::PTR_TO_REAL(x)
+# define FUNC_TYPE(x) x##_type
+
+# define DECLARE_REAL(ret_type, func, ...) \
+ typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
+ namespace __interception { \
+ extern FUNC_TYPE(func) PTR_TO_REAL(func); \
+ }
+# define ASSIGN_REAL(dst, src) REAL(dst) = REAL(src)
+#else // SANITIZER_APPLE
+# define REAL(x) x
+# define DECLARE_REAL(ret_type, func, ...) \
+ extern "C" ret_type func(__VA_ARGS__);
+# define ASSIGN_REAL(x, y)
+#endif // SANITIZER_APPLE
+
+#if !SANITIZER_FUCHSIA
+# define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \
+ DECLARE_REAL(ret_type, func, __VA_ARGS__) \
+ extern "C" ret_type WRAP(func)(__VA_ARGS__);
+// Declare an interceptor and its wrapper defined in a different translation
+// unit (ex. asm).
+# define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...) \
+ extern "C" ret_type WRAP(func)(__VA_ARGS__); \
+ extern "C" ret_type func(__VA_ARGS__);
+#else
+# define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...)
+# define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...)
+#endif
+
+// Generally, you don't need to use DEFINE_REAL by itself, as INTERCEPTOR
+// macros does its job. In exceptional cases you may need to call REAL(foo)
+// without defining INTERCEPTOR(..., foo, ...). For example, if you override
+// foo with an interceptor for other function.
+#if !SANITIZER_APPLE && !SANITIZER_FUCHSIA
+# define DEFINE_REAL(ret_type, func, ...) \
+ typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
+ namespace __interception { \
+ FUNC_TYPE(func) PTR_TO_REAL(func); \
+ }
+#else
+# define DEFINE_REAL(ret_type, func, ...)
+#endif
+
+#if SANITIZER_FUCHSIA
+
+// We need to define the __interceptor_func name just to get
+// sanitizer_common/scripts/gen_dynamic_list.py to export func.
+// But we don't need to export __interceptor_func to get that.
+#define INTERCEPTOR(ret_type, func, ...) \
+ extern "C"[[ gnu::alias(#func), gnu::visibility("hidden") ]] ret_type \
+ __interceptor_##func(__VA_ARGS__); \
+ extern "C" INTERCEPTOR_ATTRIBUTE ret_type func(__VA_ARGS__)
+
+#elif !SANITIZER_APPLE
+
+#define INTERCEPTOR(ret_type, func, ...) \
+ DEFINE_REAL(ret_type, func, __VA_ARGS__) \
+ DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \
+ extern "C" \
+ INTERCEPTOR_ATTRIBUTE \
+ ret_type WRAP(func)(__VA_ARGS__)
+
+// We don't need INTERCEPTOR_WITH_SUFFIX on non-Darwin for now.
+#define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \
+ INTERCEPTOR(ret_type, func, __VA_ARGS__)
+
+#else // SANITIZER_APPLE
+
+#define INTERCEPTOR_ZZZ(suffix, ret_type, func, ...) \
+ extern "C" ret_type func(__VA_ARGS__) suffix; \
+ extern "C" ret_type WRAP(func)(__VA_ARGS__); \
+ INTERPOSER(func); \
+ extern "C" INTERCEPTOR_ATTRIBUTE ret_type WRAP(func)(__VA_ARGS__)
+
+#define INTERCEPTOR(ret_type, func, ...) \
+ INTERCEPTOR_ZZZ(/*no symbol variants*/, ret_type, func, __VA_ARGS__)
+
+#define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \
+ INTERCEPTOR_ZZZ(__DARWIN_ALIAS_C(func), ret_type, func, __VA_ARGS__)
+
+// Override |overridee| with |overrider|.
+#define OVERRIDE_FUNCTION(overridee, overrider) \
+ INTERPOSER_2(overridee, WRAP(overrider))
+#endif
+
+#if SANITIZER_WINDOWS
+# define INTERCEPTOR_WINAPI(ret_type, func, ...) \
+ typedef ret_type (__stdcall *FUNC_TYPE(func))(__VA_ARGS__); \
+ namespace __interception { \
+ FUNC_TYPE(func) PTR_TO_REAL(func); \
+ } \
+ extern "C" \
+ INTERCEPTOR_ATTRIBUTE \
+ ret_type __stdcall WRAP(func)(__VA_ARGS__)
+#endif
+
+// ISO C++ forbids casting between pointer-to-function and pointer-to-object,
+// so we use casting via an integral type __interception::uptr,
+// assuming that system is POSIX-compliant. Using other hacks seem
+// challenging, as we don't even pass function type to
+// INTERCEPT_FUNCTION macro, only its name.
+namespace __interception {
+#if defined(_WIN64)
+typedef unsigned long long uptr;
+#else
+typedef unsigned long uptr;
+#endif // _WIN64
+} // namespace __interception
+
+#define INCLUDED_FROM_INTERCEPTION_LIB
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
+ SANITIZER_SOLARIS
+
+# include "interception_linux.h"
+# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
+# define INTERCEPT_FUNCTION_VER(func, symver) \
+ INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver)
+#elif SANITIZER_APPLE
+# include "interception_mac.h"
+# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func)
+# define INTERCEPT_FUNCTION_VER(func, symver) \
+ INTERCEPT_FUNCTION_VER_MAC(func, symver)
+#elif SANITIZER_WINDOWS
+# include "interception_win.h"
+# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_WIN(func)
+# define INTERCEPT_FUNCTION_VER(func, symver) \
+ INTERCEPT_FUNCTION_VER_WIN(func, symver)
+#endif
+
+#undef INCLUDED_FROM_INTERCEPTION_LIB
+
+#endif // INTERCEPTION_H
diff --git a/contrib/libs/clang16-rt/lib/interception/interception_linux.cpp b/contrib/libs/clang16-rt/lib/interception/interception_linux.cpp
new file mode 100644
index 00000000000..5111a87f0a6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/interception/interception_linux.cpp
@@ -0,0 +1,83 @@
+//===-- interception_linux.cpp ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Linux-specific interception methods.
+//===----------------------------------------------------------------------===//
+
+#include "interception.h"
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
+ SANITIZER_SOLARIS
+
+#include <dlfcn.h> // for dlsym() and dlvsym()
+
+namespace __interception {
+
+#if SANITIZER_NETBSD
+static int StrCmp(const char *s1, const char *s2) {
+ while (true) {
+ if (*s1 != *s2)
+ return false;
+ if (*s1 == 0)
+ return true;
+ s1++;
+ s2++;
+ }
+}
+#endif
+
+static void *GetFuncAddr(const char *name, uptr wrapper_addr) {
+#if SANITIZER_NETBSD
+ // FIXME: Find a better way to handle renames
+ if (StrCmp(name, "sigaction"))
+ name = "__sigaction14";
+#endif
+ void *addr = dlsym(RTLD_NEXT, name);
+ if (!addr) {
+ // If the lookup using RTLD_NEXT failed, the sanitizer runtime library is
+ // later in the library search order than the DSO that we are trying to
+ // intercept, which means that we cannot intercept this function. We still
+ // want the address of the real definition, though, so look it up using
+ // RTLD_DEFAULT.
+ addr = dlsym(RTLD_DEFAULT, name);
+
+ // In case `name' is not loaded, dlsym ends up finding the actual wrapper.
+ // We don't want to intercept the wrapper and have it point to itself.
+ if ((uptr)addr == wrapper_addr)
+ addr = nullptr;
+ }
+ return addr;
+}
+
+bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,
+ uptr wrapper) {
+ void *addr = GetFuncAddr(name, wrapper);
+ *ptr_to_real = (uptr)addr;
+ return addr && (func == wrapper);
+}
+
+// dlvsym is a GNU extension supported by some other platforms.
+#if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD
+static void *GetFuncAddr(const char *name, const char *ver) {
+ return dlvsym(RTLD_NEXT, name, ver);
+}
+
+bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
+ uptr func, uptr wrapper) {
+ void *addr = GetFuncAddr(name, ver);
+ *ptr_to_real = (uptr)addr;
+ return addr && (func == wrapper);
+}
+#endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD
+
+} // namespace __interception
+
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
+ // SANITIZER_SOLARIS
diff --git a/contrib/libs/clang16-rt/lib/interception/interception_linux.h b/contrib/libs/clang16-rt/lib/interception/interception_linux.h
new file mode 100644
index 00000000000..a08f8cb98c4
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/interception/interception_linux.h
@@ -0,0 +1,53 @@
+//===-- interception_linux.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Linux-specific interception methods.
+//===----------------------------------------------------------------------===//
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
+ SANITIZER_SOLARIS
+
+#if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
+# error "interception_linux.h should be included from interception library only"
+#endif
+
+#ifndef INTERCEPTION_LINUX_H
+#define INTERCEPTION_LINUX_H
+
+namespace __interception {
+bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,
+ uptr wrapper);
+bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
+ uptr func, uptr wrapper);
+} // namespace __interception
+
+#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \
+ ::__interception::InterceptFunction( \
+ #func, \
+ (::__interception::uptr *) & REAL(func), \
+ (::__interception::uptr) & (func), \
+ (::__interception::uptr) & WRAP(func))
+
+// dlvsym is a GNU extension supported by some other platforms.
+#if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD
+#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
+ ::__interception::InterceptFunction( \
+ #func, symver, \
+ (::__interception::uptr *) & REAL(func), \
+ (::__interception::uptr) & (func), \
+ (::__interception::uptr) & WRAP(func))
+#else
+#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
+ INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
+#endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD
+
+#endif // INTERCEPTION_LINUX_H
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
+ // SANITIZER_SOLARIS
diff --git a/contrib/libs/clang16-rt/lib/interception/interception_mac.cpp b/contrib/libs/clang16-rt/lib/interception/interception_mac.cpp
new file mode 100644
index 00000000000..03eae0fdca0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/interception/interception_mac.cpp
@@ -0,0 +1,18 @@
+//===-- interception_mac.cpp ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Mac-specific interception methods.
+//===----------------------------------------------------------------------===//
+
+#include "interception.h"
+
+#if SANITIZER_APPLE
+
+#endif // SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/interception/interception_mac.h b/contrib/libs/clang16-rt/lib/interception/interception_mac.h
new file mode 100644
index 00000000000..26079518c64
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/interception/interception_mac.h
@@ -0,0 +1,27 @@
+//===-- interception_mac.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Mac-specific interception methods.
+//===----------------------------------------------------------------------===//
+
+#if SANITIZER_APPLE
+
+#if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
+# error "interception_mac.h should be included from interception.h only"
+#endif
+
+#ifndef INTERCEPTION_MAC_H
+#define INTERCEPTION_MAC_H
+
+#define INTERCEPT_FUNCTION_MAC(func)
+#define INTERCEPT_FUNCTION_VER_MAC(func, symver)
+
+#endif // INTERCEPTION_MAC_H
+#endif // SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/interception/interception_type_test.cpp b/contrib/libs/clang16-rt/lib/interception/interception_type_test.cpp
new file mode 100644
index 00000000000..7c3de82a1e8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/interception/interception_type_test.cpp
@@ -0,0 +1,39 @@
+//===-- interception_type_test.cpp ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Compile-time tests of the internal type definitions.
+//===----------------------------------------------------------------------===//
+
+#include "interception.h"
+
+#if SANITIZER_LINUX || SANITIZER_APPLE
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdint.h>
+
+COMPILER_CHECK(sizeof(::SIZE_T) == sizeof(size_t));
+COMPILER_CHECK(sizeof(::SSIZE_T) == sizeof(ssize_t));
+COMPILER_CHECK(sizeof(::PTRDIFF_T) == sizeof(ptrdiff_t));
+COMPILER_CHECK(sizeof(::INTMAX_T) == sizeof(intmax_t));
+
+# if SANITIZER_GLIBC || SANITIZER_ANDROID
+COMPILER_CHECK(sizeof(::OFF64_T) == sizeof(off64_t));
+# endif
+
+// The following are the cases when pread (and friends) is used instead of
+// pread64. In those cases we need OFF_T to match off_t. We don't care about the
+// rest (they depend on _FILE_OFFSET_BITS setting when building an application).
+# if SANITIZER_ANDROID || !defined _FILE_OFFSET_BITS || \
+ _FILE_OFFSET_BITS != 64
+COMPILER_CHECK(sizeof(::OFF_T) == sizeof(off_t));
+# endif
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/interception/interception_win.cpp b/contrib/libs/clang16-rt/lib/interception/interception_win.cpp
new file mode 100644
index 00000000000..faaa8ee1538
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/interception/interception_win.cpp
@@ -0,0 +1,1071 @@
+//===-- interception_linux.cpp ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific interception methods.
+//
+// This file is implementing several hooking techniques to intercept calls
+// to functions. The hooks are dynamically installed by modifying the assembly
+// code.
+//
+// The hooking techniques are making assumptions on the way the code is
+// generated and are safe under these assumptions.
+//
+// On 64-bit architecture, there is no direct 64-bit jump instruction. To allow
+// arbitrary branching on the whole memory space, the notion of trampoline
+// region is used. A trampoline region is a memory space withing 2G boundary
+// where it is safe to add custom assembly code to build 64-bit jumps.
+//
+// Hooking techniques
+// ==================
+//
+// 1) Detour
+//
+// The Detour hooking technique is assuming the presence of an header with
+// padding and an overridable 2-bytes nop instruction (mov edi, edi). The
+// nop instruction can safely be replaced by a 2-bytes jump without any need
+// to save the instruction. A jump to the target is encoded in the function
+// header and the nop instruction is replaced by a short jump to the header.
+//
+// head: 5 x nop head: jmp <hook>
+// func: mov edi, edi --> func: jmp short <head>
+// [...] real: [...]
+//
+// This technique is only implemented on 32-bit architecture.
+// Most of the time, Windows API are hookable with the detour technique.
+//
+// 2) Redirect Jump
+//
+// The redirect jump is applicable when the first instruction is a direct
+// jump. The instruction is replaced by jump to the hook.
+//
+// func: jmp <label> --> func: jmp <hook>
+//
+// On an 64-bit architecture, a trampoline is inserted.
+//
+// func: jmp <label> --> func: jmp <tramp>
+// [...]
+//
+// [trampoline]
+// tramp: jmp QWORD [addr]
+// addr: .bytes <hook>
+//
+// Note: <real> is equivalent to <label>.
+//
+// 3) HotPatch
+//
+// The HotPatch hooking is assuming the presence of an header with padding
+// and a first instruction with at least 2-bytes.
+//
+// The reason to enforce the 2-bytes limitation is to provide the minimal
+// space to encode a short jump. HotPatch technique is only rewriting one
+// instruction to avoid breaking a sequence of instructions containing a
+// branching target.
+//
+// Assumptions are enforced by MSVC compiler by using the /HOTPATCH flag.
+// see: https://msdn.microsoft.com/en-us/library/ms173507.aspx
+// Default padding length is 5 bytes in 32-bits and 6 bytes in 64-bits.
+//
+// head: 5 x nop head: jmp <hook>
+// func: <instr> --> func: jmp short <head>
+// [...] body: [...]
+//
+// [trampoline]
+// real: <instr>
+// jmp <body>
+//
+// On an 64-bit architecture:
+//
+// head: 6 x nop head: jmp QWORD [addr1]
+// func: <instr> --> func: jmp short <head>
+// [...] body: [...]
+//
+// [trampoline]
+// addr1: .bytes <hook>
+// real: <instr>
+// jmp QWORD [addr2]
+// addr2: .bytes <body>
+//
+// 4) Trampoline
+//
+// The Trampoline hooking technique is the most aggressive one. It is
+// assuming that there is a sequence of instructions that can be safely
+// replaced by a jump (enough room and no incoming branches).
+//
+// Unfortunately, these assumptions can't be safely presumed and code may
+// be broken after hooking.
+//
+// func: <instr> --> func: jmp <hook>
+// <instr>
+// [...] body: [...]
+//
+// [trampoline]
+// real: <instr>
+// <instr>
+// jmp <body>
+//
+// On an 64-bit architecture:
+//
+// func: <instr> --> func: jmp QWORD [addr1]
+// <instr>
+// [...] body: [...]
+//
+// [trampoline]
+// addr1: .bytes <hook>
+// real: <instr>
+// <instr>
+// jmp QWORD [addr2]
+// addr2: .bytes <body>
+//===----------------------------------------------------------------------===//
+
+#include "interception.h"
+
+#if SANITIZER_WINDOWS
+#include "sanitizer_common/sanitizer_platform.h"
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace __interception {
+
+static const int kAddressLength = FIRST_32_SECOND_64(4, 8);
+static const int kJumpInstructionLength = 5;
+static const int kShortJumpInstructionLength = 2;
+UNUSED static const int kIndirectJumpInstructionLength = 6;
+static const int kBranchLength =
+ FIRST_32_SECOND_64(kJumpInstructionLength, kIndirectJumpInstructionLength);
+static const int kDirectBranchLength = kBranchLength + kAddressLength;
+
+static void InterceptionFailed() {
+ // Do we have a good way to abort with an error message here?
+ __debugbreak();
+}
+
+static bool DistanceIsWithin2Gig(uptr from, uptr target) {
+#if SANITIZER_WINDOWS64
+ if (from < target)
+ return target - from <= (uptr)0x7FFFFFFFU;
+ else
+ return from - target <= (uptr)0x80000000U;
+#else
+ // In a 32-bit address space, the address calculation will wrap, so this check
+ // is unnecessary.
+ return true;
+#endif
+}
+
+static uptr GetMmapGranularity() {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return si.dwAllocationGranularity;
+}
+
+UNUSED static uptr RoundUpTo(uptr size, uptr boundary) {
+ return (size + boundary - 1) & ~(boundary - 1);
+}
+
+// FIXME: internal_str* and internal_mem* functions should be moved from the
+// ASan sources into interception/.
+
+static size_t _strlen(const char *str) {
+ const char* p = str;
+ while (*p != '\0') ++p;
+ return p - str;
+}
+
+static char* _strchr(char* str, char c) {
+ while (*str) {
+ if (*str == c)
+ return str;
+ ++str;
+ }
+ return nullptr;
+}
+
+static void _memset(void *p, int value, size_t sz) {
+ for (size_t i = 0; i < sz; ++i)
+ ((char*)p)[i] = (char)value;
+}
+
+static void _memcpy(void *dst, void *src, size_t sz) {
+ char *dst_c = (char*)dst,
+ *src_c = (char*)src;
+ for (size_t i = 0; i < sz; ++i)
+ dst_c[i] = src_c[i];
+}
+
+static bool ChangeMemoryProtection(
+ uptr address, uptr size, DWORD *old_protection) {
+ return ::VirtualProtect((void*)address, size,
+ PAGE_EXECUTE_READWRITE,
+ old_protection) != FALSE;
+}
+
+static bool RestoreMemoryProtection(
+ uptr address, uptr size, DWORD old_protection) {
+ DWORD unused;
+ return ::VirtualProtect((void*)address, size,
+ old_protection,
+ &unused) != FALSE;
+}
+
+static bool IsMemoryPadding(uptr address, uptr size) {
+ u8* function = (u8*)address;
+ for (size_t i = 0; i < size; ++i)
+ if (function[i] != 0x90 && function[i] != 0xCC)
+ return false;
+ return true;
+}
+
+static const u8 kHintNop8Bytes[] = {
+ 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+template<class T>
+static bool FunctionHasPrefix(uptr address, const T &pattern) {
+ u8* function = (u8*)address - sizeof(pattern);
+ for (size_t i = 0; i < sizeof(pattern); ++i)
+ if (function[i] != pattern[i])
+ return false;
+ return true;
+}
+
+static bool FunctionHasPadding(uptr address, uptr size) {
+ if (IsMemoryPadding(address - size, size))
+ return true;
+ if (size <= sizeof(kHintNop8Bytes) &&
+ FunctionHasPrefix(address, kHintNop8Bytes))
+ return true;
+ return false;
+}
+
+static void WritePadding(uptr from, uptr size) {
+ _memset((void*)from, 0xCC, (size_t)size);
+}
+
+static void WriteJumpInstruction(uptr from, uptr target) {
+ if (!DistanceIsWithin2Gig(from + kJumpInstructionLength, target))
+ InterceptionFailed();
+ ptrdiff_t offset = target - from - kJumpInstructionLength;
+ *(u8*)from = 0xE9;
+ *(u32*)(from + 1) = offset;
+}
+
+static void WriteShortJumpInstruction(uptr from, uptr target) {
+ sptr offset = target - from - kShortJumpInstructionLength;
+ if (offset < -128 || offset > 127)
+ InterceptionFailed();
+ *(u8*)from = 0xEB;
+ *(u8*)(from + 1) = (u8)offset;
+}
+
+#if SANITIZER_WINDOWS64
+static void WriteIndirectJumpInstruction(uptr from, uptr indirect_target) {
+ // jmp [rip + <offset>] = FF 25 <offset> where <offset> is a relative
+ // offset.
+ // The offset is the distance from then end of the jump instruction to the
+ // memory location containing the targeted address. The displacement is still
+ // 32-bit in x64, so indirect_target must be located within +/- 2GB range.
+ int offset = indirect_target - from - kIndirectJumpInstructionLength;
+ if (!DistanceIsWithin2Gig(from + kIndirectJumpInstructionLength,
+ indirect_target)) {
+ InterceptionFailed();
+ }
+ *(u16*)from = 0x25FF;
+ *(u32*)(from + 2) = offset;
+}
+#endif
+
+static void WriteBranch(
+ uptr from, uptr indirect_target, uptr target) {
+#if SANITIZER_WINDOWS64
+ WriteIndirectJumpInstruction(from, indirect_target);
+ *(u64*)indirect_target = target;
+#else
+ (void)indirect_target;
+ WriteJumpInstruction(from, target);
+#endif
+}
+
+static void WriteDirectBranch(uptr from, uptr target) {
+#if SANITIZER_WINDOWS64
+ // Emit an indirect jump through immediately following bytes:
+ // jmp [rip + kBranchLength]
+ // .quad <target>
+ WriteBranch(from, from + kBranchLength, target);
+#else
+ WriteJumpInstruction(from, target);
+#endif
+}
+
+struct TrampolineMemoryRegion {
+ uptr content;
+ uptr allocated_size;
+ uptr max_size;
+};
+
+UNUSED static const uptr kTrampolineScanLimitRange = 1 << 31; // 2 gig
+static const int kMaxTrampolineRegion = 1024;
+static TrampolineMemoryRegion TrampolineRegions[kMaxTrampolineRegion];
+
+static void *AllocateTrampolineRegion(uptr image_address, size_t granularity) {
+#if SANITIZER_WINDOWS64
+ uptr address = image_address;
+ uptr scanned = 0;
+ while (scanned < kTrampolineScanLimitRange) {
+ MEMORY_BASIC_INFORMATION info;
+ if (!::VirtualQuery((void*)address, &info, sizeof(info)))
+ return nullptr;
+
+ // Check whether a region can be allocated at |address|.
+ if (info.State == MEM_FREE && info.RegionSize >= granularity) {
+ void *page = ::VirtualAlloc((void*)RoundUpTo(address, granularity),
+ granularity,
+ MEM_RESERVE | MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE);
+ return page;
+ }
+
+ // Move to the next region.
+ address = (uptr)info.BaseAddress + info.RegionSize;
+ scanned += info.RegionSize;
+ }
+ return nullptr;
+#else
+ return ::VirtualAlloc(nullptr,
+ granularity,
+ MEM_RESERVE | MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE);
+#endif
+}
+
+// Used by unittests to release mapped memory space.
+void TestOnlyReleaseTrampolineRegions() {
+ for (size_t bucket = 0; bucket < kMaxTrampolineRegion; ++bucket) {
+ TrampolineMemoryRegion *current = &TrampolineRegions[bucket];
+ if (current->content == 0)
+ return;
+ ::VirtualFree((void*)current->content, 0, MEM_RELEASE);
+ current->content = 0;
+ }
+}
+
+static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) {
+ // Find a region within 2G with enough space to allocate |size| bytes.
+ TrampolineMemoryRegion *region = nullptr;
+ for (size_t bucket = 0; bucket < kMaxTrampolineRegion; ++bucket) {
+ TrampolineMemoryRegion* current = &TrampolineRegions[bucket];
+ if (current->content == 0) {
+ // No valid region found, allocate a new region.
+ size_t bucket_size = GetMmapGranularity();
+ void *content = AllocateTrampolineRegion(image_address, bucket_size);
+ if (content == nullptr)
+ return 0U;
+
+ current->content = (uptr)content;
+ current->allocated_size = 0;
+ current->max_size = bucket_size;
+ region = current;
+ break;
+ } else if (current->max_size - current->allocated_size > size) {
+#if SANITIZER_WINDOWS64
+ // In 64-bits, the memory space must be allocated within 2G boundary.
+ uptr next_address = current->content + current->allocated_size;
+ if (next_address < image_address ||
+ next_address - image_address >= 0x7FFF0000)
+ continue;
+#endif
+ // The space can be allocated in the current region.
+ region = current;
+ break;
+ }
+ }
+
+ // Failed to find a region.
+ if (region == nullptr)
+ return 0U;
+
+ // Allocate the space in the current region.
+ uptr allocated_space = region->content + region->allocated_size;
+ region->allocated_size += size;
+ WritePadding(allocated_space, size);
+
+ return allocated_space;
+}
+
+// The following prologues cannot be patched because of the short jump
+// jumping to the patching region.
+
+#if SANITIZER_WINDOWS64
+// ntdll!wcslen in Win11
+// 488bc1 mov rax,rcx
+// 0fb710 movzx edx,word ptr [rax]
+// 4883c002 add rax,2
+// 6685d2 test dx,dx
+// 75f4 jne -12
+static const u8 kPrologueWithShortJump1[] = {
+ 0x48, 0x8b, 0xc1, 0x0f, 0xb7, 0x10, 0x48, 0x83,
+ 0xc0, 0x02, 0x66, 0x85, 0xd2, 0x75, 0xf4,
+};
+
+// ntdll!strrchr in Win11
+// 4c8bc1 mov r8,rcx
+// 8a01 mov al,byte ptr [rcx]
+// 48ffc1 inc rcx
+// 84c0 test al,al
+// 75f7 jne -9
+static const u8 kPrologueWithShortJump2[] = {
+ 0x4c, 0x8b, 0xc1, 0x8a, 0x01, 0x48, 0xff, 0xc1,
+ 0x84, 0xc0, 0x75, 0xf7,
+};
+#endif
+
+// Returns 0 on error.
+static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
+#if SANITIZER_WINDOWS64
+ if (memcmp((u8*)address, kPrologueWithShortJump1,
+ sizeof(kPrologueWithShortJump1)) == 0 ||
+ memcmp((u8*)address, kPrologueWithShortJump2,
+ sizeof(kPrologueWithShortJump2)) == 0) {
+ return 0;
+ }
+#endif
+
+ switch (*(u64*)address) {
+ case 0x90909090909006EB: // stub: jmp over 6 x nop.
+ return 8;
+ }
+
+ switch (*(u8*)address) {
+ case 0x90: // 90 : nop
+ return 1;
+
+ case 0x50: // push eax / rax
+ case 0x51: // push ecx / rcx
+ case 0x52: // push edx / rdx
+ case 0x53: // push ebx / rbx
+ case 0x54: // push esp / rsp
+ case 0x55: // push ebp / rbp
+ case 0x56: // push esi / rsi
+ case 0x57: // push edi / rdi
+ case 0x5D: // pop ebp / rbp
+ return 1;
+
+ case 0x6A: // 6A XX = push XX
+ return 2;
+
+ case 0xb8: // b8 XX XX XX XX : mov eax, XX XX XX XX
+ case 0xB9: // b9 XX XX XX XX : mov ecx, XX XX XX XX
+ return 5;
+
+ // Cannot overwrite control-instruction. Return 0 to indicate failure.
+ case 0xE9: // E9 XX XX XX XX : jmp <label>
+ case 0xE8: // E8 XX XX XX XX : call <func>
+ case 0xC3: // C3 : ret
+ case 0xEB: // EB XX : jmp XX (short jump)
+ case 0x70: // 7Y YY : jy XX (short conditional jump)
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77:
+ case 0x78:
+ case 0x79:
+ case 0x7A:
+ case 0x7B:
+ case 0x7C:
+ case 0x7D:
+ case 0x7E:
+ case 0x7F:
+ return 0;
+ }
+
+ switch (*(u16*)(address)) {
+ case 0x018A: // 8A 01 : mov al, byte ptr [ecx]
+ case 0xFF8B: // 8B FF : mov edi, edi
+ case 0xEC8B: // 8B EC : mov ebp, esp
+ case 0xc889: // 89 C8 : mov eax, ecx
+ case 0xC18B: // 8B C1 : mov eax, ecx
+ case 0xC033: // 33 C0 : xor eax, eax
+ case 0xC933: // 33 C9 : xor ecx, ecx
+ case 0xD233: // 33 D2 : xor edx, edx
+ return 2;
+
+ // Cannot overwrite control-instruction. Return 0 to indicate failure.
+ case 0x25FF: // FF 25 XX XX XX XX : jmp [XXXXXXXX]
+ return 0;
+ }
+
+ switch (0x00FFFFFF & *(u32*)address) {
+ case 0x24A48D: // 8D A4 24 XX XX XX XX : lea esp, [esp + XX XX XX XX]
+ return 7;
+ }
+
+#if SANITIZER_WINDOWS64
+ switch (*(u8*)address) {
+ case 0xA1: // A1 XX XX XX XX XX XX XX XX :
+ // movabs eax, dword ptr ds:[XXXXXXXX]
+ return 9;
+
+ case 0x83:
+ const u8 next_byte = *(u8*)(address + 1);
+ const u8 mod = next_byte >> 6;
+ const u8 rm = next_byte & 7;
+ if (mod == 1 && rm == 4)
+ return 5; // 83 ModR/M SIB Disp8 Imm8
+ // add|or|adc|sbb|and|sub|xor|cmp [r+disp8], imm8
+ }
+
+ switch (*(u16*)address) {
+ case 0x5040: // push rax
+ case 0x5140: // push rcx
+ case 0x5240: // push rdx
+ case 0x5340: // push rbx
+ case 0x5440: // push rsp
+ case 0x5540: // push rbp
+ case 0x5640: // push rsi
+ case 0x5740: // push rdi
+ case 0x5441: // push r12
+ case 0x5541: // push r13
+ case 0x5641: // push r14
+ case 0x5741: // push r15
+ case 0x9066: // Two-byte NOP
+ case 0xc084: // test al, al
+ case 0x018a: // mov al, byte ptr [rcx]
+ return 2;
+
+ case 0x058B: // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX]
+ if (rel_offset)
+ *rel_offset = 2;
+ return 6;
+ }
+
+ switch (0x00FFFFFF & *(u32*)address) {
+ case 0xe58948: // 48 8b c4 : mov rbp, rsp
+ case 0xc18b48: // 48 8b c1 : mov rax, rcx
+ case 0xc48b48: // 48 8b c4 : mov rax, rsp
+ case 0xd9f748: // 48 f7 d9 : neg rcx
+ case 0xd12b48: // 48 2b d1 : sub rdx, rcx
+ case 0x07c1f6: // f6 c1 07 : test cl, 0x7
+ case 0xc98548: // 48 85 C9 : test rcx, rcx
+ case 0xd28548: // 48 85 d2 : test rdx, rdx
+ case 0xc0854d: // 4d 85 c0 : test r8, r8
+ case 0xc2b60f: // 0f b6 c2 : movzx eax, dl
+ case 0xc03345: // 45 33 c0 : xor r8d, r8d
+ case 0xc93345: // 45 33 c9 : xor r9d, r9d
+ case 0xdb3345: // 45 33 DB : xor r11d, r11d
+ case 0xd98b4c: // 4c 8b d9 : mov r11, rcx
+ case 0xd28b4c: // 4c 8b d2 : mov r10, rdx
+ case 0xc98b4c: // 4C 8B C9 : mov r9, rcx
+ case 0xc18b4c: // 4C 8B C1 : mov r8, rcx
+ case 0xd2b60f: // 0f b6 d2 : movzx edx, dl
+ case 0xca2b48: // 48 2b ca : sub rcx, rdx
+ case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]
+ case 0xc00b4d: // 3d 0b c0 : or r8, r8
+ case 0xc08b41: // 41 8b c0 : mov eax, r8d
+ case 0xd18b48: // 48 8b d1 : mov rdx, rcx
+ case 0xdc8b4c: // 4c 8b dc : mov r11, rsp
+ case 0xd18b4c: // 4c 8b d1 : mov r10, rcx
+ case 0xE0E483: // 83 E4 E0 : and esp, 0xFFFFFFE0
+ return 3;
+
+ case 0xec8348: // 48 83 ec XX : sub rsp, XX
+ case 0xf88349: // 49 83 f8 XX : cmp r8, XX
+ case 0x588948: // 48 89 58 XX : mov QWORD PTR[rax + XX], rbx
+ return 4;
+
+ case 0xec8148: // 48 81 EC XX XX XX XX : sub rsp, XXXXXXXX
+ return 7;
+
+ case 0x058b48: // 48 8b 05 XX XX XX XX :
+ // mov rax, QWORD PTR [rip + XXXXXXXX]
+ case 0x25ff48: // 48 ff 25 XX XX XX XX :
+ // rex.W jmp QWORD PTR [rip + XXXXXXXX]
+
+ // Instructions having offset relative to 'rip' need offset adjustment.
+ if (rel_offset)
+ *rel_offset = 3;
+ return 7;
+
+ case 0x2444c7: // C7 44 24 XX YY YY YY YY
+ // mov dword ptr [rsp + XX], YYYYYYYY
+ return 8;
+ }
+
+ switch (*(u32*)(address)) {
+ case 0x24448b48: // 48 8b 44 24 XX : mov rax, QWORD ptr [rsp + XX]
+ case 0x246c8948: // 48 89 6C 24 XX : mov QWORD ptr [rsp + XX], rbp
+ case 0x245c8948: // 48 89 5c 24 XX : mov QWORD PTR [rsp + XX], rbx
+ case 0x24748948: // 48 89 74 24 XX : mov QWORD PTR [rsp + XX], rsi
+ case 0x247c8948: // 48 89 7c 24 XX : mov QWORD PTR [rsp + XX], rdi
+ case 0x244C8948: // 48 89 4C 24 XX : mov QWORD PTR [rsp + XX], rcx
+ case 0x24548948: // 48 89 54 24 XX : mov QWORD PTR [rsp + XX], rdx
+ case 0x244c894c: // 4c 89 4c 24 XX : mov QWORD PTR [rsp + XX], r9
+ case 0x2444894c: // 4c 89 44 24 XX : mov QWORD PTR [rsp + XX], r8
+ return 5;
+ case 0x24648348: // 48 83 64 24 XX : and QWORD PTR [rsp + XX], YY
+ return 6;
+ }
+
+#else
+
+ switch (*(u8*)address) {
+ case 0xA1: // A1 XX XX XX XX : mov eax, dword ptr ds:[XXXXXXXX]
+ return 5;
+ }
+ switch (*(u16*)address) {
+ case 0x458B: // 8B 45 XX : mov eax, dword ptr [ebp + XX]
+ case 0x5D8B: // 8B 5D XX : mov ebx, dword ptr [ebp + XX]
+ case 0x7D8B: // 8B 7D XX : mov edi, dword ptr [ebp + XX]
+ case 0xEC83: // 83 EC XX : sub esp, XX
+ case 0x75FF: // FF 75 XX : push dword ptr [ebp + XX]
+ return 3;
+ case 0xC1F7: // F7 C1 XX YY ZZ WW : test ecx, WWZZYYXX
+ case 0x25FF: // FF 25 XX YY ZZ WW : jmp dword ptr ds:[WWZZYYXX]
+ return 6;
+ case 0x3D83: // 83 3D XX YY ZZ WW TT : cmp TT, WWZZYYXX
+ return 7;
+ case 0x7D83: // 83 7D XX YY : cmp dword ptr [ebp + XX], YY
+ return 4;
+ }
+
+ switch (0x00FFFFFF & *(u32*)address) {
+ case 0x24448A: // 8A 44 24 XX : mov eal, dword ptr [esp + XX]
+ case 0x24448B: // 8B 44 24 XX : mov eax, dword ptr [esp + XX]
+ case 0x244C8B: // 8B 4C 24 XX : mov ecx, dword ptr [esp + XX]
+ case 0x24548B: // 8B 54 24 XX : mov edx, dword ptr [esp + XX]
+ case 0x24748B: // 8B 74 24 XX : mov esi, dword ptr [esp + XX]
+ case 0x247C8B: // 8B 7C 24 XX : mov edi, dword ptr [esp + XX]
+ return 4;
+ }
+
+ switch (*(u32*)address) {
+ case 0x2444B60F: // 0F B6 44 24 XX : movzx eax, byte ptr [esp + XX]
+ return 5;
+ }
+#endif
+
+ // Unknown instruction!
+ // FIXME: Unknown instruction failures might happen when we add a new
+ // interceptor or a new compiler version. In either case, they should result
+ // in visible and readable error messages. However, merely calling abort()
+ // leads to an infinite recursion in CheckFailed.
+ InterceptionFailed();
+ return 0;
+}
+
+// Returns 0 on error.
+static size_t RoundUpToInstrBoundary(size_t size, uptr address) {
+ size_t cursor = 0;
+ while (cursor < size) {
+ size_t instruction_size = GetInstructionSize(address + cursor);
+ if (!instruction_size)
+ return 0;
+ cursor += instruction_size;
+ }
+ return cursor;
+}
+
+static bool CopyInstructions(uptr to, uptr from, size_t size) {
+ size_t cursor = 0;
+ while (cursor != size) {
+ size_t rel_offset = 0;
+ size_t instruction_size = GetInstructionSize(from + cursor, &rel_offset);
+ _memcpy((void*)(to + cursor), (void*)(from + cursor),
+ (size_t)instruction_size);
+ if (rel_offset) {
+ uptr delta = to - from;
+ uptr relocated_offset = *(u32*)(to + cursor + rel_offset) - delta;
+#if SANITIZER_WINDOWS64
+ if (relocated_offset + 0x80000000U >= 0xFFFFFFFFU)
+ return false;
+#endif
+ *(u32*)(to + cursor + rel_offset) = relocated_offset;
+ }
+ cursor += instruction_size;
+ }
+ return true;
+}
+
+
+#if !SANITIZER_WINDOWS64
+bool OverrideFunctionWithDetour(
+ uptr old_func, uptr new_func, uptr *orig_old_func) {
+ const int kDetourHeaderLen = 5;
+ const u16 kDetourInstruction = 0xFF8B;
+
+ uptr header = (uptr)old_func - kDetourHeaderLen;
+ uptr patch_length = kDetourHeaderLen + kShortJumpInstructionLength;
+
+ // Validate that the function is hookable.
+ if (*(u16*)old_func != kDetourInstruction ||
+ !IsMemoryPadding(header, kDetourHeaderLen))
+ return false;
+
+ // Change memory protection to writable.
+ DWORD protection = 0;
+ if (!ChangeMemoryProtection(header, patch_length, &protection))
+ return false;
+
+ // Write a relative jump to the redirected function.
+ WriteJumpInstruction(header, new_func);
+
+ // Write the short jump to the function prefix.
+ WriteShortJumpInstruction(old_func, header);
+
+ // Restore previous memory protection.
+ if (!RestoreMemoryProtection(header, patch_length, protection))
+ return false;
+
+ if (orig_old_func)
+ *orig_old_func = old_func + kShortJumpInstructionLength;
+
+ return true;
+}
+#endif
+
+bool OverrideFunctionWithRedirectJump(
+ uptr old_func, uptr new_func, uptr *orig_old_func) {
+ // Check whether the first instruction is a relative jump.
+ if (*(u8*)old_func != 0xE9)
+ return false;
+
+ if (orig_old_func) {
+ sptr relative_offset = *(s32 *)(old_func + 1);
+ uptr absolute_target = old_func + relative_offset + kJumpInstructionLength;
+ *orig_old_func = absolute_target;
+ }
+
+#if SANITIZER_WINDOWS64
+ // If needed, get memory space for a trampoline jump.
+ uptr trampoline = AllocateMemoryForTrampoline(old_func, kDirectBranchLength);
+ if (!trampoline)
+ return false;
+ WriteDirectBranch(trampoline, new_func);
+#endif
+
+ // Change memory protection to writable.
+ DWORD protection = 0;
+ if (!ChangeMemoryProtection(old_func, kJumpInstructionLength, &protection))
+ return false;
+
+ // Write a relative jump to the redirected function.
+ WriteJumpInstruction(old_func, FIRST_32_SECOND_64(new_func, trampoline));
+
+ // Restore previous memory protection.
+ if (!RestoreMemoryProtection(old_func, kJumpInstructionLength, protection))
+ return false;
+
+ return true;
+}
+
+bool OverrideFunctionWithHotPatch(
+ uptr old_func, uptr new_func, uptr *orig_old_func) {
+ const int kHotPatchHeaderLen = kBranchLength;
+
+ uptr header = (uptr)old_func - kHotPatchHeaderLen;
+ uptr patch_length = kHotPatchHeaderLen + kShortJumpInstructionLength;
+
+ // Validate that the function is hot patchable.
+ size_t instruction_size = GetInstructionSize(old_func);
+ if (instruction_size < kShortJumpInstructionLength ||
+ !FunctionHasPadding(old_func, kHotPatchHeaderLen))
+ return false;
+
+ if (orig_old_func) {
+ // Put the needed instructions into the trampoline bytes.
+ uptr trampoline_length = instruction_size + kDirectBranchLength;
+ uptr trampoline = AllocateMemoryForTrampoline(old_func, trampoline_length);
+ if (!trampoline)
+ return false;
+ if (!CopyInstructions(trampoline, old_func, instruction_size))
+ return false;
+ WriteDirectBranch(trampoline + instruction_size,
+ old_func + instruction_size);
+ *orig_old_func = trampoline;
+ }
+
+ // If needed, get memory space for indirect address.
+ uptr indirect_address = 0;
+#if SANITIZER_WINDOWS64
+ indirect_address = AllocateMemoryForTrampoline(old_func, kAddressLength);
+ if (!indirect_address)
+ return false;
+#endif
+
+ // Change memory protection to writable.
+ DWORD protection = 0;
+ if (!ChangeMemoryProtection(header, patch_length, &protection))
+ return false;
+
+ // Write jumps to the redirected function.
+ WriteBranch(header, indirect_address, new_func);
+ WriteShortJumpInstruction(old_func, header);
+
+ // Restore previous memory protection.
+ if (!RestoreMemoryProtection(header, patch_length, protection))
+ return false;
+
+ return true;
+}
+
+bool OverrideFunctionWithTrampoline(
+ uptr old_func, uptr new_func, uptr *orig_old_func) {
+
+ size_t instructions_length = kBranchLength;
+ size_t padding_length = 0;
+ uptr indirect_address = 0;
+
+ if (orig_old_func) {
+ // Find out the number of bytes of the instructions we need to copy
+ // to the trampoline.
+ instructions_length = RoundUpToInstrBoundary(kBranchLength, old_func);
+ if (!instructions_length)
+ return false;
+
+ // Put the needed instructions into the trampoline bytes.
+ uptr trampoline_length = instructions_length + kDirectBranchLength;
+ uptr trampoline = AllocateMemoryForTrampoline(old_func, trampoline_length);
+ if (!trampoline)
+ return false;
+ if (!CopyInstructions(trampoline, old_func, instructions_length))
+ return false;
+ WriteDirectBranch(trampoline + instructions_length,
+ old_func + instructions_length);
+ *orig_old_func = trampoline;
+ }
+
+#if SANITIZER_WINDOWS64
+ // Check if the targeted address can be encoded in the function padding.
+ // Otherwise, allocate it in the trampoline region.
+ if (IsMemoryPadding(old_func - kAddressLength, kAddressLength)) {
+ indirect_address = old_func - kAddressLength;
+ padding_length = kAddressLength;
+ } else {
+ indirect_address = AllocateMemoryForTrampoline(old_func, kAddressLength);
+ if (!indirect_address)
+ return false;
+ }
+#endif
+
+ // Change memory protection to writable.
+ uptr patch_address = old_func - padding_length;
+ uptr patch_length = instructions_length + padding_length;
+ DWORD protection = 0;
+ if (!ChangeMemoryProtection(patch_address, patch_length, &protection))
+ return false;
+
+ // Patch the original function.
+ WriteBranch(old_func, indirect_address, new_func);
+
+ // Restore previous memory protection.
+ if (!RestoreMemoryProtection(patch_address, patch_length, protection))
+ return false;
+
+ return true;
+}
+
+bool OverrideFunction(
+ uptr old_func, uptr new_func, uptr *orig_old_func) {
+#if !SANITIZER_WINDOWS64
+ if (OverrideFunctionWithDetour(old_func, new_func, orig_old_func))
+ return true;
+#endif
+ if (OverrideFunctionWithRedirectJump(old_func, new_func, orig_old_func))
+ return true;
+ if (OverrideFunctionWithHotPatch(old_func, new_func, orig_old_func))
+ return true;
+ if (OverrideFunctionWithTrampoline(old_func, new_func, orig_old_func))
+ return true;
+ return false;
+}
+
+static void **InterestingDLLsAvailable() {
+ static const char *InterestingDLLs[] = {
+ "kernel32.dll",
+ "msvcr100.dll", // VS2010
+ "msvcr110.dll", // VS2012
+ "msvcr120.dll", // VS2013
+ "vcruntime140.dll", // VS2015
+ "ucrtbase.dll", // Universal CRT
+ // NTDLL should go last as it exports some functions that we should
+ // override in the CRT [presumably only used internally].
+ "ntdll.dll", NULL};
+ static void *result[ARRAY_SIZE(InterestingDLLs)] = { 0 };
+ if (!result[0]) {
+ for (size_t i = 0, j = 0; InterestingDLLs[i]; ++i) {
+ if (HMODULE h = GetModuleHandleA(InterestingDLLs[i]))
+ result[j++] = (void *)h;
+ }
+ }
+ return &result[0];
+}
+
+namespace {
+// Utility for reading loaded PE images.
+template <typename T> class RVAPtr {
+ public:
+ RVAPtr(void *module, uptr rva)
+ : ptr_(reinterpret_cast<T *>(reinterpret_cast<char *>(module) + rva)) {}
+ operator T *() { return ptr_; }
+ T *operator->() { return ptr_; }
+ T *operator++() { return ++ptr_; }
+
+ private:
+ T *ptr_;
+};
+} // namespace
+
+// Internal implementation of GetProcAddress. At least since Windows 8,
+// GetProcAddress appears to initialize DLLs before returning function pointers
+// into them. This is problematic for the sanitizers, because they typically
+// want to intercept malloc *before* MSVCRT initializes. Our internal
+// implementation walks the export list manually without doing initialization.
+uptr InternalGetProcAddress(void *module, const char *func_name) {
+ // Check that the module header is full and present.
+ RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0);
+ RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew);
+ if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
+ headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0"
+ headers->FileHeader.SizeOfOptionalHeader <
+ sizeof(IMAGE_OPTIONAL_HEADER)) {
+ return 0;
+ }
+
+ IMAGE_DATA_DIRECTORY *export_directory =
+ &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
+ if (export_directory->Size == 0)
+ return 0;
+ RVAPtr<IMAGE_EXPORT_DIRECTORY> exports(module,
+ export_directory->VirtualAddress);
+ RVAPtr<DWORD> functions(module, exports->AddressOfFunctions);
+ RVAPtr<DWORD> names(module, exports->AddressOfNames);
+ RVAPtr<WORD> ordinals(module, exports->AddressOfNameOrdinals);
+
+ for (DWORD i = 0; i < exports->NumberOfNames; i++) {
+ RVAPtr<char> name(module, names[i]);
+ if (!strcmp(func_name, name)) {
+ DWORD index = ordinals[i];
+ RVAPtr<char> func(module, functions[index]);
+
+ // Handle forwarded functions.
+ DWORD offset = functions[index];
+ if (offset >= export_directory->VirtualAddress &&
+ offset < export_directory->VirtualAddress + export_directory->Size) {
+ // An entry for a forwarded function is a string with the following
+ // format: "<module> . <function_name>" that is stored into the
+ // exported directory.
+ char function_name[256];
+ size_t funtion_name_length = _strlen(func);
+ if (funtion_name_length >= sizeof(function_name) - 1)
+ InterceptionFailed();
+
+ _memcpy(function_name, func, funtion_name_length);
+ function_name[funtion_name_length] = '\0';
+ char* separator = _strchr(function_name, '.');
+ if (!separator)
+ InterceptionFailed();
+ *separator = '\0';
+
+ void* redirected_module = GetModuleHandleA(function_name);
+ if (!redirected_module)
+ InterceptionFailed();
+ return InternalGetProcAddress(redirected_module, separator + 1);
+ }
+
+ return (uptr)(char *)func;
+ }
+ }
+
+ return 0;
+}
+
+bool OverrideFunction(
+ const char *func_name, uptr new_func, uptr *orig_old_func) {
+ bool hooked = false;
+ void **DLLs = InterestingDLLsAvailable();
+ for (size_t i = 0; DLLs[i]; ++i) {
+ uptr func_addr = InternalGetProcAddress(DLLs[i], func_name);
+ if (func_addr &&
+ OverrideFunction(func_addr, new_func, orig_old_func)) {
+ hooked = true;
+ }
+ }
+ return hooked;
+}
+
+bool OverrideImportedFunction(const char *module_to_patch,
+ const char *imported_module,
+ const char *function_name, uptr new_function,
+ uptr *orig_old_func) {
+ HMODULE module = GetModuleHandleA(module_to_patch);
+ if (!module)
+ return false;
+
+ // Check that the module header is full and present.
+ RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0);
+ RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew);
+ if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
+ headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0"
+ headers->FileHeader.SizeOfOptionalHeader <
+ sizeof(IMAGE_OPTIONAL_HEADER)) {
+ return false;
+ }
+
+ IMAGE_DATA_DIRECTORY *import_directory =
+ &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+
+ // Iterate the list of imported DLLs. FirstThunk will be null for the last
+ // entry.
+ RVAPtr<IMAGE_IMPORT_DESCRIPTOR> imports(module,
+ import_directory->VirtualAddress);
+ for (; imports->FirstThunk != 0; ++imports) {
+ RVAPtr<const char> modname(module, imports->Name);
+ if (_stricmp(&*modname, imported_module) == 0)
+ break;
+ }
+ if (imports->FirstThunk == 0)
+ return false;
+
+ // We have two parallel arrays: the import address table (IAT) and the table
+ // of names. They start out containing the same data, but the loader rewrites
+ // the IAT to hold imported addresses and leaves the name table in
+ // OriginalFirstThunk alone.
+ RVAPtr<IMAGE_THUNK_DATA> name_table(module, imports->OriginalFirstThunk);
+ RVAPtr<IMAGE_THUNK_DATA> iat(module, imports->FirstThunk);
+ for (; name_table->u1.Ordinal != 0; ++name_table, ++iat) {
+ if (!IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
+ RVAPtr<IMAGE_IMPORT_BY_NAME> import_by_name(
+ module, name_table->u1.ForwarderString);
+ const char *funcname = &import_by_name->Name[0];
+ if (strcmp(funcname, function_name) == 0)
+ break;
+ }
+ }
+ if (name_table->u1.Ordinal == 0)
+ return false;
+
+ // Now we have the correct IAT entry. Do the swap. We have to make the page
+ // read/write first.
+ if (orig_old_func)
+ *orig_old_func = iat->u1.AddressOfData;
+ DWORD old_prot, unused_prot;
+ if (!VirtualProtect(&iat->u1.AddressOfData, 4, PAGE_EXECUTE_READWRITE,
+ &old_prot))
+ return false;
+ iat->u1.AddressOfData = new_function;
+ if (!VirtualProtect(&iat->u1.AddressOfData, 4, old_prot, &unused_prot))
+ return false; // Not clear if this failure bothers us.
+ return true;
+}
+
+} // namespace __interception
+
+#endif // SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/interception/interception_win.h b/contrib/libs/clang16-rt/lib/interception/interception_win.h
new file mode 100644
index 00000000000..4590013019e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/interception/interception_win.h
@@ -0,0 +1,83 @@
+//===-- interception_linux.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Windows-specific interception methods.
+//===----------------------------------------------------------------------===//
+
+#if SANITIZER_WINDOWS
+
+#if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
+# error "interception_win.h should be included from interception library only"
+#endif
+
+#ifndef INTERCEPTION_WIN_H
+#define INTERCEPTION_WIN_H
+
+namespace __interception {
+// All the functions in the OverrideFunction() family return true on success,
+// false on failure (including "couldn't find the function").
+
+// Overrides a function by its address.
+bool OverrideFunction(uptr old_func, uptr new_func, uptr *orig_old_func = 0);
+
+// Overrides a function in a system DLL or DLL CRT by its exported name.
+bool OverrideFunction(const char *name, uptr new_func, uptr *orig_old_func = 0);
+
+// Windows-only replacement for GetProcAddress. Useful for some sanitizers.
+uptr InternalGetProcAddress(void *module, const char *func_name);
+
+// Overrides a function only when it is called from a specific DLL. For example,
+// this is used to override calls to HeapAlloc/HeapFree from ucrtbase without
+// affecting other third party libraries.
+bool OverrideImportedFunction(const char *module_to_patch,
+ const char *imported_module,
+ const char *function_name, uptr new_function,
+ uptr *orig_old_func);
+
+#if !SANITIZER_WINDOWS64
+// Exposed for unittests
+bool OverrideFunctionWithDetour(
+ uptr old_func, uptr new_func, uptr *orig_old_func);
+#endif
+
+// Exposed for unittests
+bool OverrideFunctionWithRedirectJump(
+ uptr old_func, uptr new_func, uptr *orig_old_func);
+bool OverrideFunctionWithHotPatch(
+ uptr old_func, uptr new_func, uptr *orig_old_func);
+bool OverrideFunctionWithTrampoline(
+ uptr old_func, uptr new_func, uptr *orig_old_func);
+
+// Exposed for unittests
+void TestOnlyReleaseTrampolineRegions();
+
+} // namespace __interception
+
+#if defined(INTERCEPTION_DYNAMIC_CRT)
+#define INTERCEPT_FUNCTION_WIN(func) \
+ ::__interception::OverrideFunction(#func, \
+ (::__interception::uptr)WRAP(func), \
+ (::__interception::uptr *)&REAL(func))
+#else
+#define INTERCEPT_FUNCTION_WIN(func) \
+ ::__interception::OverrideFunction((::__interception::uptr)func, \
+ (::__interception::uptr)WRAP(func), \
+ (::__interception::uptr *)&REAL(func))
+#endif
+
+#define INTERCEPT_FUNCTION_VER_WIN(func, symver) INTERCEPT_FUNCTION_WIN(func)
+
+#define INTERCEPT_FUNCTION_DLLIMPORT(user_dll, provider_dll, func) \
+ ::__interception::OverrideImportedFunction( \
+ user_dll, provider_dll, #func, (::__interception::uptr)WRAP(func), \
+ (::__interception::uptr *)&REAL(func))
+
+#endif // INTERCEPTION_WIN_H
+#endif // SANITIZER_WINDOWS
diff --git a/contrib/libs/clang16-rt/lib/lsan/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/lsan/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan.cpp
new file mode 100644
index 00000000000..489c5ca01fe
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan.cpp
@@ -0,0 +1,115 @@
+//=-- lsan.cpp ------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Standalone LSan RTL.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lsan.h"
+
+#include "lsan_allocator.h"
+#include "lsan_common.h"
+#include "lsan_thread.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_interface_internal.h"
+
+bool lsan_inited;
+bool lsan_init_is_running;
+
+namespace __lsan {
+
+///// Interface to the common LSan module. /////
+bool WordIsPoisoned(uptr addr) {
+ return false;
+}
+
+} // namespace __lsan
+
+void __sanitizer::BufferedStackTrace::UnwindImpl(
+ uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
+ using namespace __lsan;
+ uptr stack_top = 0, stack_bottom = 0;
+ if (ThreadContext *t = CurrentThreadContext()) {
+ stack_top = t->stack_end();
+ stack_bottom = t->stack_begin();
+ }
+ if (SANITIZER_MIPS && !IsValidFrame(bp, stack_top, stack_bottom))
+ return;
+ bool fast = StackTrace::WillUseFastUnwind(request_fast);
+ Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, fast);
+}
+
+using namespace __lsan;
+
+static void InitializeFlags() {
+ // Set all the default values.
+ SetCommonFlagsDefaults();
+ {
+ CommonFlags cf;
+ cf.CopyFrom(*common_flags());
+ cf.external_symbolizer_path = GetEnv("LSAN_SYMBOLIZER_PATH");
+ cf.malloc_context_size = 30;
+ cf.intercept_tls_get_addr = true;
+ cf.detect_leaks = true;
+ cf.exitcode = 23;
+ OverrideCommonFlags(cf);
+ }
+
+ Flags *f = flags();
+ f->SetDefaults();
+
+ FlagParser parser;
+ RegisterLsanFlags(&parser, f);
+ RegisterCommonFlags(&parser);
+
+ // Override from user-specified string.
+ const char *lsan_default_options = __lsan_default_options();
+ parser.ParseString(lsan_default_options);
+ parser.ParseStringFromEnv("LSAN_OPTIONS");
+
+ InitializeCommonFlags();
+
+ if (Verbosity()) ReportUnrecognizedFlags();
+
+ if (common_flags()->help) parser.PrintFlagDescriptions();
+
+ __sanitizer_set_report_path(common_flags()->log_path);
+}
+
+extern "C" void __lsan_init() {
+ CHECK(!lsan_init_is_running);
+ if (lsan_inited)
+ return;
+ lsan_init_is_running = true;
+ SanitizerToolName = "LeakSanitizer";
+ CacheBinaryName();
+ AvoidCVE_2016_2143();
+ InitializeFlags();
+ InitCommonLsan();
+ InitializeAllocator();
+ ReplaceSystemMalloc();
+ InitTlsSize();
+ InitializeInterceptors();
+ InitializeThreadRegistry();
+ InstallDeadlySignalHandlers(LsanOnDeadlySignal);
+ InitializeMainThread();
+ InstallAtExitCheckLeaks();
+
+ InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
+
+ lsan_inited = true;
+ lsan_init_is_running = false;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_print_stack_trace() {
+ GET_STACK_TRACE_FATAL;
+ stack.Print();
+}
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan.h b/contrib/libs/clang16-rt/lib/lsan/lsan.h
new file mode 100644
index 00000000000..757edec8e10
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan.h
@@ -0,0 +1,56 @@
+//=-- lsan.h --------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Private header for standalone LSan RTL.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lsan_thread.h"
+#if SANITIZER_POSIX
+# include "lsan_posix.h"
+#elif SANITIZER_FUCHSIA
+# include "lsan_fuchsia.h"
+#endif
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+
+#define GET_STACK_TRACE(max_size, fast) \
+ __sanitizer::BufferedStackTrace stack; \
+ stack.Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), nullptr, fast, \
+ max_size);
+
+#define GET_STACK_TRACE_FATAL \
+ GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal)
+
+#define GET_STACK_TRACE_MALLOC \
+ GET_STACK_TRACE(__sanitizer::common_flags()->malloc_context_size, \
+ common_flags()->fast_unwind_on_malloc)
+
+#define GET_STACK_TRACE_THREAD GET_STACK_TRACE(kStackTraceMax, true)
+
+namespace __lsan {
+
+void InitializeInterceptors();
+void ReplaceSystemMalloc();
+void LsanOnDeadlySignal(int signo, void *siginfo, void *context);
+void InstallAtExitCheckLeaks();
+
+#define ENSURE_LSAN_INITED \
+ do { \
+ CHECK(!lsan_init_is_running); \
+ if (!lsan_inited) \
+ __lsan_init(); \
+ } while (0)
+
+} // namespace __lsan
+
+extern bool lsan_inited;
+extern bool lsan_init_is_running;
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __lsan_init();
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_allocator.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan_allocator.cpp
new file mode 100644
index 00000000000..b18d829a1a2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_allocator.cpp
@@ -0,0 +1,367 @@
+//=-- lsan_allocator.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// See lsan_allocator.h for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lsan_allocator.h"
+
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_checks.h"
+#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
+#include "sanitizer_common/sanitizer_errno.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "lsan_common.h"
+
+extern "C" void *memset(void *ptr, int value, uptr num);
+
+namespace __lsan {
+#if defined(__i386__) || defined(__arm__)
+static const uptr kMaxAllowedMallocSize = 1ULL << 30;
+#elif defined(__mips64) || defined(__aarch64__)
+static const uptr kMaxAllowedMallocSize = 4ULL << 30;
+#else
+static const uptr kMaxAllowedMallocSize = 8ULL << 30;
+#endif
+
+static Allocator allocator;
+
+static uptr max_malloc_size;
+
+void InitializeAllocator() {
+ SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null);
+ allocator.InitLinkerInitialized(
+ common_flags()->allocator_release_to_os_interval_ms);
+ if (common_flags()->max_allocation_size_mb)
+ max_malloc_size = Min(common_flags()->max_allocation_size_mb << 20,
+ kMaxAllowedMallocSize);
+ else
+ max_malloc_size = kMaxAllowedMallocSize;
+}
+
+void AllocatorThreadFinish() {
+ allocator.SwallowCache(GetAllocatorCache());
+}
+
+static ChunkMetadata *Metadata(const void *p) {
+ return reinterpret_cast<ChunkMetadata *>(allocator.GetMetaData(p));
+}
+
+static void RegisterAllocation(const StackTrace &stack, void *p, uptr size) {
+ if (!p) return;
+ ChunkMetadata *m = Metadata(p);
+ CHECK(m);
+ m->tag = DisabledInThisThread() ? kIgnored : kDirectlyLeaked;
+ m->stack_trace_id = StackDepotPut(stack);
+ m->requested_size = size;
+ atomic_store(reinterpret_cast<atomic_uint8_t *>(m), 1, memory_order_relaxed);
+}
+
+static void RegisterDeallocation(void *p) {
+ if (!p) return;
+ ChunkMetadata *m = Metadata(p);
+ CHECK(m);
+ atomic_store(reinterpret_cast<atomic_uint8_t *>(m), 0, memory_order_relaxed);
+}
+
+static void *ReportAllocationSizeTooBig(uptr size, const StackTrace &stack) {
+ if (AllocatorMayReturnNull()) {
+ Report("WARNING: LeakSanitizer failed to allocate 0x%zx bytes\n", size);
+ return nullptr;
+ }
+ ReportAllocationSizeTooBig(size, max_malloc_size, &stack);
+}
+
+void *Allocate(const StackTrace &stack, uptr size, uptr alignment,
+ bool cleared) {
+ if (size == 0)
+ size = 1;
+ if (size > max_malloc_size)
+ return ReportAllocationSizeTooBig(size, stack);
+ if (UNLIKELY(IsRssLimitExceeded())) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportRssLimitExceeded(&stack);
+ }
+ void *p = allocator.Allocate(GetAllocatorCache(), size, alignment);
+ if (UNLIKELY(!p)) {
+ SetAllocatorOutOfMemory();
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportOutOfMemory(size, &stack);
+ }
+ // Do not rely on the allocator to clear the memory (it's slow).
+ if (cleared && allocator.FromPrimary(p))
+ memset(p, 0, size);
+ RegisterAllocation(stack, p, size);
+ RunMallocHooks(p, size);
+ return p;
+}
+
+static void *Calloc(uptr nmemb, uptr size, const StackTrace &stack) {
+ if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportCallocOverflow(nmemb, size, &stack);
+ }
+ size *= nmemb;
+ return Allocate(stack, size, 1, true);
+}
+
+void Deallocate(void *p) {
+ RunFreeHooks(p);
+ RegisterDeallocation(p);
+ allocator.Deallocate(GetAllocatorCache(), p);
+}
+
+void *Reallocate(const StackTrace &stack, void *p, uptr new_size,
+ uptr alignment) {
+ if (new_size > max_malloc_size) {
+ ReportAllocationSizeTooBig(new_size, stack);
+ return nullptr;
+ }
+ RegisterDeallocation(p);
+ void *new_p =
+ allocator.Reallocate(GetAllocatorCache(), p, new_size, alignment);
+ if (new_p)
+ RegisterAllocation(stack, new_p, new_size);
+ else if (new_size != 0)
+ RegisterAllocation(stack, p, new_size);
+ return new_p;
+}
+
+void GetAllocatorCacheRange(uptr *begin, uptr *end) {
+ *begin = (uptr)GetAllocatorCache();
+ *end = *begin + sizeof(AllocatorCache);
+}
+
+uptr GetMallocUsableSize(const void *p) {
+ if (!p)
+ return 0;
+ ChunkMetadata *m = Metadata(p);
+ if (!m) return 0;
+ return m->requested_size;
+}
+
+int lsan_posix_memalign(void **memptr, uptr alignment, uptr size,
+ const StackTrace &stack) {
+ if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
+ if (AllocatorMayReturnNull())
+ return errno_EINVAL;
+ ReportInvalidPosixMemalignAlignment(alignment, &stack);
+ }
+ void *ptr = Allocate(stack, size, alignment, kAlwaysClearMemory);
+ if (UNLIKELY(!ptr))
+ // OOM error is already taken care of by Allocate.
+ return errno_ENOMEM;
+ CHECK(IsAligned((uptr)ptr, alignment));
+ *memptr = ptr;
+ return 0;
+}
+
+void *lsan_aligned_alloc(uptr alignment, uptr size, const StackTrace &stack) {
+ if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAlignedAllocAlignment(size, alignment, &stack);
+ }
+ return SetErrnoOnNull(Allocate(stack, size, alignment, kAlwaysClearMemory));
+}
+
+void *lsan_memalign(uptr alignment, uptr size, const StackTrace &stack) {
+ if (UNLIKELY(!IsPowerOfTwo(alignment))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAllocationAlignment(alignment, &stack);
+ }
+ return SetErrnoOnNull(Allocate(stack, size, alignment, kAlwaysClearMemory));
+}
+
+void *lsan_malloc(uptr size, const StackTrace &stack) {
+ return SetErrnoOnNull(Allocate(stack, size, 1, kAlwaysClearMemory));
+}
+
+void lsan_free(void *p) {
+ Deallocate(p);
+}
+
+void *lsan_realloc(void *p, uptr size, const StackTrace &stack) {
+ return SetErrnoOnNull(Reallocate(stack, p, size, 1));
+}
+
+void *lsan_reallocarray(void *ptr, uptr nmemb, uptr size,
+ const StackTrace &stack) {
+ if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+ errno = errno_ENOMEM;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportReallocArrayOverflow(nmemb, size, &stack);
+ }
+ return lsan_realloc(ptr, nmemb * size, stack);
+}
+
+void *lsan_calloc(uptr nmemb, uptr size, const StackTrace &stack) {
+ return SetErrnoOnNull(Calloc(nmemb, size, stack));
+}
+
+void *lsan_valloc(uptr size, const StackTrace &stack) {
+ return SetErrnoOnNull(
+ Allocate(stack, size, GetPageSizeCached(), kAlwaysClearMemory));
+}
+
+void *lsan_pvalloc(uptr size, const StackTrace &stack) {
+ uptr PageSize = GetPageSizeCached();
+ if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) {
+ errno = errno_ENOMEM;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportPvallocOverflow(size, &stack);
+ }
+ // pvalloc(0) should allocate one page.
+ size = size ? RoundUpTo(size, PageSize) : PageSize;
+ return SetErrnoOnNull(Allocate(stack, size, PageSize, kAlwaysClearMemory));
+}
+
+uptr lsan_mz_size(const void *p) {
+ return GetMallocUsableSize(p);
+}
+
+///// Interface to the common LSan module. /////
+
+void LockAllocator() {
+ allocator.ForceLock();
+}
+
+void UnlockAllocator() {
+ allocator.ForceUnlock();
+}
+
+void GetAllocatorGlobalRange(uptr *begin, uptr *end) {
+ *begin = (uptr)&allocator;
+ *end = *begin + sizeof(allocator);
+}
+
+uptr PointsIntoChunk(void* p) {
+ uptr addr = reinterpret_cast<uptr>(p);
+ uptr chunk = reinterpret_cast<uptr>(allocator.GetBlockBeginFastLocked(p));
+ if (!chunk) return 0;
+ // LargeMmapAllocator considers pointers to the meta-region of a chunk to be
+ // valid, but we don't want that.
+ if (addr < chunk) return 0;
+ ChunkMetadata *m = Metadata(reinterpret_cast<void *>(chunk));
+ CHECK(m);
+ if (!m->allocated)
+ return 0;
+ if (addr < chunk + m->requested_size)
+ return chunk;
+ if (IsSpecialCaseOfOperatorNew0(chunk, m->requested_size, addr))
+ return chunk;
+ return 0;
+}
+
+uptr GetUserBegin(uptr chunk) {
+ return chunk;
+}
+
+LsanMetadata::LsanMetadata(uptr chunk) {
+ metadata_ = Metadata(reinterpret_cast<void *>(chunk));
+ CHECK(metadata_);
+}
+
+bool LsanMetadata::allocated() const {
+ return reinterpret_cast<ChunkMetadata *>(metadata_)->allocated;
+}
+
+ChunkTag LsanMetadata::tag() const {
+ return reinterpret_cast<ChunkMetadata *>(metadata_)->tag;
+}
+
+void LsanMetadata::set_tag(ChunkTag value) {
+ reinterpret_cast<ChunkMetadata *>(metadata_)->tag = value;
+}
+
+uptr LsanMetadata::requested_size() const {
+ return reinterpret_cast<ChunkMetadata *>(metadata_)->requested_size;
+}
+
+u32 LsanMetadata::stack_trace_id() const {
+ return reinterpret_cast<ChunkMetadata *>(metadata_)->stack_trace_id;
+}
+
+void ForEachChunk(ForEachChunkCallback callback, void *arg) {
+ allocator.ForEachChunk(callback, arg);
+}
+
+IgnoreObjectResult IgnoreObjectLocked(const void *p) {
+ void *chunk = allocator.GetBlockBegin(p);
+ if (!chunk || p < chunk) return kIgnoreObjectInvalid;
+ ChunkMetadata *m = Metadata(chunk);
+ CHECK(m);
+ if (m->allocated && (uptr)p < (uptr)chunk + m->requested_size) {
+ if (m->tag == kIgnored)
+ return kIgnoreObjectAlreadyIgnored;
+ m->tag = kIgnored;
+ return kIgnoreObjectSuccess;
+ } else {
+ return kIgnoreObjectInvalid;
+ }
+}
+
+void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs) {
+ // This function can be used to treat memory reachable from `tctx` as live.
+ // This is useful for threads that have been created but not yet started.
+
+ // This is currently a no-op because the LSan `pthread_create()` interceptor
+ // blocks until the child thread starts which keeps the thread's `arg` pointer
+ // live.
+}
+
+} // namespace __lsan
+
+using namespace __lsan;
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __sanitizer_get_current_allocated_bytes() {
+ uptr stats[AllocatorStatCount];
+ allocator.GetStats(stats);
+ return stats[AllocatorStatAllocated];
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __sanitizer_get_heap_size() {
+ uptr stats[AllocatorStatCount];
+ allocator.GetStats(stats);
+ return stats[AllocatorStatMapped];
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __sanitizer_get_free_bytes() { return 0; }
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __sanitizer_get_unmapped_bytes() { return 0; }
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; }
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __sanitizer_get_ownership(const void *p) { return Metadata(p) != nullptr; }
+
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __sanitizer_get_allocated_size(const void *p) {
+ return GetMallocUsableSize(p);
+}
+
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_allocator.h b/contrib/libs/clang16-rt/lib/lsan/lsan_allocator.h
new file mode 100644
index 00000000000..b67d9d7750e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_allocator.h
@@ -0,0 +1,117 @@
+//=-- lsan_allocator.h ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Allocator for standalone LSan.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LSAN_ALLOCATOR_H
+#define LSAN_ALLOCATOR_H
+
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "lsan_common.h"
+
+namespace __lsan {
+
+void *Allocate(const StackTrace &stack, uptr size, uptr alignment,
+ bool cleared);
+void Deallocate(void *p);
+void *Reallocate(const StackTrace &stack, void *p, uptr new_size,
+ uptr alignment);
+uptr GetMallocUsableSize(const void *p);
+
+template<typename Callable>
+void ForEachChunk(const Callable &callback);
+
+void GetAllocatorCacheRange(uptr *begin, uptr *end);
+void AllocatorThreadFinish();
+void InitializeAllocator();
+
+const bool kAlwaysClearMemory = true;
+
+struct ChunkMetadata {
+ u8 allocated : 8; // Must be first.
+ ChunkTag tag : 2;
+#if SANITIZER_WORDSIZE == 64
+ uptr requested_size : 54;
+#else
+ uptr requested_size : 32;
+ uptr padding : 22;
+#endif
+ u32 stack_trace_id;
+};
+
+#if !SANITIZER_CAN_USE_ALLOCATOR64
+template <typename AddressSpaceViewTy>
+struct AP32 {
+ static const uptr kSpaceBeg = 0;
+ static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
+ static const uptr kMetadataSize = sizeof(ChunkMetadata);
+ typedef __sanitizer::CompactSizeClassMap SizeClassMap;
+ static const uptr kRegionSizeLog = 20;
+ using AddressSpaceView = AddressSpaceViewTy;
+ typedef NoOpMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+};
+template <typename AddressSpaceView>
+using PrimaryAllocatorASVT = SizeClassAllocator32<AP32<AddressSpaceView>>;
+using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
+#else
+# if SANITIZER_FUCHSIA || defined(__powerpc64__)
+const uptr kAllocatorSpace = ~(uptr)0;
+const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
+#elif defined(__s390x__)
+const uptr kAllocatorSpace = 0x40000000000ULL;
+const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
+# else
+const uptr kAllocatorSpace = 0x600000000000ULL;
+const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
+# endif
+template <typename AddressSpaceViewTy>
+struct AP64 { // Allocator64 parameters. Deliberately using a short name.
+ static const uptr kSpaceBeg = kAllocatorSpace;
+ static const uptr kSpaceSize = kAllocatorSize;
+ static const uptr kMetadataSize = sizeof(ChunkMetadata);
+ typedef DefaultSizeClassMap SizeClassMap;
+ typedef NoOpMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+ using AddressSpaceView = AddressSpaceViewTy;
+};
+
+template <typename AddressSpaceView>
+using PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>;
+using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
+#endif
+
+template <typename AddressSpaceView>
+using AllocatorASVT = CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>>;
+using Allocator = AllocatorASVT<LocalAddressSpaceView>;
+using AllocatorCache = Allocator::AllocatorCache;
+
+Allocator::AllocatorCache *GetAllocatorCache();
+
+int lsan_posix_memalign(void **memptr, uptr alignment, uptr size,
+ const StackTrace &stack);
+void *lsan_aligned_alloc(uptr alignment, uptr size, const StackTrace &stack);
+void *lsan_memalign(uptr alignment, uptr size, const StackTrace &stack);
+void *lsan_malloc(uptr size, const StackTrace &stack);
+void lsan_free(void *p);
+void *lsan_realloc(void *p, uptr size, const StackTrace &stack);
+void *lsan_reallocarray(void *p, uptr nmemb, uptr size,
+ const StackTrace &stack);
+void *lsan_calloc(uptr nmemb, uptr size, const StackTrace &stack);
+void *lsan_valloc(uptr size, const StackTrace &stack);
+void *lsan_pvalloc(uptr size, const StackTrace &stack);
+uptr lsan_mz_size(const void *p);
+
+} // namespace __lsan
+
+#endif // LSAN_ALLOCATOR_H
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_common.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan_common.cpp
new file mode 100644
index 00000000000..1b47e83a105
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_common.cpp
@@ -0,0 +1,1089 @@
+//=-- lsan_common.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Implementation of common leak checking functionality.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lsan_common.h"
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+
+#if CAN_SANITIZE_LEAKS
+
+# if SANITIZER_APPLE
+// https://github.com/apple-oss-distributions/objc4/blob/8701d5672d3fd3cd817aeb84db1077aafe1a1604/runtime/objc-runtime-new.h#L127
+# if SANITIZER_IOS && !SANITIZER_IOSSIM
+# define OBJC_DATA_MASK 0x0000007ffffffff8UL
+# else
+# define OBJC_DATA_MASK 0x00007ffffffffff8UL
+# endif
+// https://github.com/apple-oss-distributions/objc4/blob/8701d5672d3fd3cd817aeb84db1077aafe1a1604/runtime/objc-runtime-new.h#L139
+# define OBJC_FAST_IS_RW 0x8000000000000000UL
+# endif
+
+namespace __lsan {
+
+// This mutex is used to prevent races between DoLeakCheck and IgnoreObject, and
+// also to protect the global list of root regions.
+Mutex global_mutex;
+
+Flags lsan_flags;
+
+void DisableCounterUnderflow() {
+ if (common_flags()->detect_leaks) {
+ Report("Unmatched call to __lsan_enable().\n");
+ Die();
+ }
+}
+
+void Flags::SetDefaults() {
+# define LSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+# include "lsan_flags.inc"
+# undef LSAN_FLAG
+}
+
+void RegisterLsanFlags(FlagParser *parser, Flags *f) {
+# define LSAN_FLAG(Type, Name, DefaultValue, Description) \
+ RegisterFlag(parser, #Name, Description, &f->Name);
+# include "lsan_flags.inc"
+# undef LSAN_FLAG
+}
+
+# define LOG_POINTERS(...) \
+ do { \
+ if (flags()->log_pointers) \
+ Report(__VA_ARGS__); \
+ } while (0)
+
+# define LOG_THREADS(...) \
+ do { \
+ if (flags()->log_threads) \
+ Report(__VA_ARGS__); \
+ } while (0)
+
+class LeakSuppressionContext {
+ bool parsed = false;
+ SuppressionContext context;
+ bool suppressed_stacks_sorted = true;
+ InternalMmapVector<u32> suppressed_stacks;
+ const LoadedModule *suppress_module = nullptr;
+
+ void LazyInit();
+ Suppression *GetSuppressionForAddr(uptr addr);
+ bool SuppressInvalid(const StackTrace &stack);
+ bool SuppressByRule(const StackTrace &stack, uptr hit_count, uptr total_size);
+
+ public:
+ LeakSuppressionContext(const char *supprression_types[],
+ int suppression_types_num)
+ : context(supprression_types, suppression_types_num) {}
+
+ bool Suppress(u32 stack_trace_id, uptr hit_count, uptr total_size);
+
+ const InternalMmapVector<u32> &GetSortedSuppressedStacks() {
+ if (!suppressed_stacks_sorted) {
+ suppressed_stacks_sorted = true;
+ SortAndDedup(suppressed_stacks);
+ }
+ return suppressed_stacks;
+ }
+ void PrintMatchedSuppressions();
+};
+
+ALIGNED(64) static char suppression_placeholder[sizeof(LeakSuppressionContext)];
+static LeakSuppressionContext *suppression_ctx = nullptr;
+static const char kSuppressionLeak[] = "leak";
+static const char *kSuppressionTypes[] = {kSuppressionLeak};
+static const char kStdSuppressions[] =
+# if SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT
+ // For more details refer to the SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT
+ // definition.
+ "leak:*pthread_exit*\n"
+# endif // SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT
+# if SANITIZER_APPLE
+ // For Darwin and os_log/os_trace: https://reviews.llvm.org/D35173
+ "leak:*_os_trace*\n"
+# endif
+ // TLS leak in some glibc versions, described in
+ // https://sourceware.org/bugzilla/show_bug.cgi?id=12650.
+ "leak:*tls_get_addr*\n";
+
+void InitializeSuppressions() {
+ CHECK_EQ(nullptr, suppression_ctx);
+ suppression_ctx = new (suppression_placeholder)
+ LeakSuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
+}
+
+void LeakSuppressionContext::LazyInit() {
+ if (!parsed) {
+ parsed = true;
+ context.ParseFromFile(flags()->suppressions);
+ if (&__lsan_default_suppressions)
+ context.Parse(__lsan_default_suppressions());
+ context.Parse(kStdSuppressions);
+ if (flags()->use_tls && flags()->use_ld_allocations)
+ suppress_module = GetLinker();
+ }
+}
+
+Suppression *LeakSuppressionContext::GetSuppressionForAddr(uptr addr) {
+ Suppression *s = nullptr;
+
+ // Suppress by module name.
+ const char *module_name = Symbolizer::GetOrInit()->GetModuleNameForPc(addr);
+ if (!module_name)
+ module_name = "<unknown module>";
+ if (context.Match(module_name, kSuppressionLeak, &s))
+ return s;
+
+ // Suppress by file or function name.
+ SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(addr);
+ for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
+ if (context.Match(cur->info.function, kSuppressionLeak, &s) ||
+ context.Match(cur->info.file, kSuppressionLeak, &s)) {
+ break;
+ }
+ }
+ frames->ClearAll();
+ return s;
+}
+
+static uptr GetCallerPC(const StackTrace &stack) {
+ // The top frame is our malloc/calloc/etc. The next frame is the caller.
+ if (stack.size >= 2)
+ return stack.trace[1];
+ return 0;
+}
+
+# if SANITIZER_APPLE
+// Objective-C class data pointers are stored with flags in the low bits, so
+// they need to be transformed back into something that looks like a pointer.
+static inline void *MaybeTransformPointer(void *p) {
+ uptr ptr = reinterpret_cast<uptr>(p);
+ if ((ptr & OBJC_FAST_IS_RW) == OBJC_FAST_IS_RW)
+ ptr &= OBJC_DATA_MASK;
+ return reinterpret_cast<void *>(ptr);
+}
+# endif
+
+// On Linux, treats all chunks allocated from ld-linux.so as reachable, which
+// covers dynamically allocated TLS blocks, internal dynamic loader's loaded
+// modules accounting etc.
+// Dynamic TLS blocks contain the TLS variables of dynamically loaded modules.
+// They are allocated with a __libc_memalign() call in allocate_and_init()
+// (elf/dl-tls.c). Glibc won't tell us the address ranges occupied by those
+// blocks, but we can make sure they come from our own allocator by intercepting
+// __libc_memalign(). On top of that, there is no easy way to reach them. Their
+// addresses are stored in a dynamically allocated array (the DTV) which is
+// referenced from the static TLS. Unfortunately, we can't just rely on the DTV
+// being reachable from the static TLS, and the dynamic TLS being reachable from
+// the DTV. This is because the initial DTV is allocated before our interception
+// mechanism kicks in, and thus we don't recognize it as allocated memory. We
+// can't special-case it either, since we don't know its size.
+// Our solution is to include in the root set all allocations made from
+// ld-linux.so (which is where allocate_and_init() is implemented). This is
+// guaranteed to include all dynamic TLS blocks (and possibly other allocations
+// which we don't care about).
+// On all other platforms, this simply checks to ensure that the caller pc is
+// valid before reporting chunks as leaked.
+bool LeakSuppressionContext::SuppressInvalid(const StackTrace &stack) {
+ uptr caller_pc = GetCallerPC(stack);
+ // If caller_pc is unknown, this chunk may be allocated in a coroutine. Mark
+ // it as reachable, as we can't properly report its allocation stack anyway.
+ return !caller_pc ||
+ (suppress_module && suppress_module->containsAddress(caller_pc));
+}
+
+bool LeakSuppressionContext::SuppressByRule(const StackTrace &stack,
+ uptr hit_count, uptr total_size) {
+ for (uptr i = 0; i < stack.size; i++) {
+ Suppression *s = GetSuppressionForAddr(
+ StackTrace::GetPreviousInstructionPc(stack.trace[i]));
+ if (s) {
+ s->weight += total_size;
+ atomic_fetch_add(&s->hit_count, hit_count, memory_order_relaxed);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool LeakSuppressionContext::Suppress(u32 stack_trace_id, uptr hit_count,
+ uptr total_size) {
+ LazyInit();
+ StackTrace stack = StackDepotGet(stack_trace_id);
+ if (!SuppressInvalid(stack) && !SuppressByRule(stack, hit_count, total_size))
+ return false;
+ suppressed_stacks_sorted = false;
+ suppressed_stacks.push_back(stack_trace_id);
+ return true;
+}
+
+static LeakSuppressionContext *GetSuppressionContext() {
+ CHECK(suppression_ctx);
+ return suppression_ctx;
+}
+
+static InternalMmapVectorNoCtor<RootRegion> root_regions;
+
+InternalMmapVectorNoCtor<RootRegion> const *GetRootRegions() {
+ return &root_regions;
+}
+
+void InitCommonLsan() {
+ if (common_flags()->detect_leaks) {
+ // Initialization which can fail or print warnings should only be done if
+ // LSan is actually enabled.
+ InitializeSuppressions();
+ InitializePlatformSpecificModules();
+ }
+}
+
+class Decorator : public __sanitizer::SanitizerCommonDecorator {
+ public:
+ Decorator() : SanitizerCommonDecorator() {}
+ const char *Error() { return Red(); }
+ const char *Leak() { return Blue(); }
+};
+
+static inline bool MaybeUserPointer(uptr p) {
+ // Since our heap is located in mmap-ed memory, we can assume a sensible lower
+ // bound on heap addresses.
+ const uptr kMinAddress = 4 * 4096;
+ if (p < kMinAddress)
+ return false;
+# if defined(__x86_64__)
+ // Accept only canonical form user-space addresses.
+ return ((p >> 47) == 0);
+# elif defined(__mips64)
+ return ((p >> 40) == 0);
+# elif defined(__aarch64__)
+ // Accept up to 48 bit VMA.
+ return ((p >> 48) == 0);
+# elif defined(__loongarch_lp64)
+ // Allow 47-bit user-space VMA at current.
+ return ((p >> 47) == 0);
+# else
+ return true;
+# endif
+}
+
+// Scans the memory range, looking for byte patterns that point into allocator
+// chunks. Marks those chunks with |tag| and adds them to |frontier|.
+// There are two usage modes for this function: finding reachable chunks
+// (|tag| = kReachable) and finding indirectly leaked chunks
+// (|tag| = kIndirectlyLeaked). In the second case, there's no flood fill,
+// so |frontier| = 0.
+void ScanRangeForPointers(uptr begin, uptr end, Frontier *frontier,
+ const char *region_type, ChunkTag tag) {
+ CHECK(tag == kReachable || tag == kIndirectlyLeaked);
+ const uptr alignment = flags()->pointer_alignment();
+ LOG_POINTERS("Scanning %s range %p-%p.\n", region_type, (void *)begin,
+ (void *)end);
+ uptr pp = begin;
+ if (pp % alignment)
+ pp = pp + alignment - pp % alignment;
+ for (; pp + sizeof(void *) <= end; pp += alignment) {
+ void *p = *reinterpret_cast<void **>(pp);
+# if SANITIZER_APPLE
+ p = MaybeTransformPointer(p);
+# endif
+ if (!MaybeUserPointer(reinterpret_cast<uptr>(p)))
+ continue;
+ uptr chunk = PointsIntoChunk(p);
+ if (!chunk)
+ continue;
+ // Pointers to self don't count. This matters when tag == kIndirectlyLeaked.
+ if (chunk == begin)
+ continue;
+ LsanMetadata m(chunk);
+ if (m.tag() == kReachable || m.tag() == kIgnored)
+ continue;
+
+ // Do this check relatively late so we can log only the interesting cases.
+ if (!flags()->use_poisoned && WordIsPoisoned(pp)) {
+ LOG_POINTERS(
+ "%p is poisoned: ignoring %p pointing into chunk %p-%p of size "
+ "%zu.\n",
+ (void *)pp, p, (void *)chunk, (void *)(chunk + m.requested_size()),
+ m.requested_size());
+ continue;
+ }
+
+ m.set_tag(tag);
+ LOG_POINTERS("%p: found %p pointing into chunk %p-%p of size %zu.\n",
+ (void *)pp, p, (void *)chunk,
+ (void *)(chunk + m.requested_size()), m.requested_size());
+ if (frontier)
+ frontier->push_back(chunk);
+ }
+}
+
+// Scans a global range for pointers
+void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier) {
+ uptr allocator_begin = 0, allocator_end = 0;
+ GetAllocatorGlobalRange(&allocator_begin, &allocator_end);
+ if (begin <= allocator_begin && allocator_begin < end) {
+ CHECK_LE(allocator_begin, allocator_end);
+ CHECK_LE(allocator_end, end);
+ if (begin < allocator_begin)
+ ScanRangeForPointers(begin, allocator_begin, frontier, "GLOBAL",
+ kReachable);
+ if (allocator_end < end)
+ ScanRangeForPointers(allocator_end, end, frontier, "GLOBAL", kReachable);
+ } else {
+ ScanRangeForPointers(begin, end, frontier, "GLOBAL", kReachable);
+ }
+}
+
+void ScanExtraStackRanges(const InternalMmapVector<Range> &ranges,
+ Frontier *frontier) {
+ for (uptr i = 0; i < ranges.size(); i++) {
+ ScanRangeForPointers(ranges[i].begin, ranges[i].end, frontier, "FAKE STACK",
+ kReachable);
+ }
+}
+
+# if SANITIZER_FUCHSIA
+
+// Fuchsia handles all threads together with its own callback.
+static void ProcessThreads(SuspendedThreadsList const &, Frontier *, tid_t,
+ uptr) {}
+
+# else
+
+# if SANITIZER_ANDROID
+// FIXME: Move this out into *libcdep.cpp
+extern "C" SANITIZER_WEAK_ATTRIBUTE void __libc_iterate_dynamic_tls(
+ pid_t, void (*cb)(void *, void *, uptr, void *), void *);
+# endif
+
+static void ProcessThreadRegistry(Frontier *frontier) {
+ InternalMmapVector<uptr> ptrs;
+ GetAdditionalThreadContextPtrsLocked(&ptrs);
+
+ for (uptr i = 0; i < ptrs.size(); ++i) {
+ void *ptr = reinterpret_cast<void *>(ptrs[i]);
+ uptr chunk = PointsIntoChunk(ptr);
+ if (!chunk)
+ continue;
+ LsanMetadata m(chunk);
+ if (!m.allocated())
+ continue;
+
+ // Mark as reachable and add to frontier.
+ LOG_POINTERS("Treating pointer %p from ThreadContext as reachable\n", ptr);
+ m.set_tag(kReachable);
+ frontier->push_back(chunk);
+ }
+}
+
+// Scans thread data (stacks and TLS) for heap pointers.
+static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
+ Frontier *frontier, tid_t caller_tid,
+ uptr caller_sp) {
+ InternalMmapVector<uptr> registers;
+ InternalMmapVector<Range> extra_ranges;
+ for (uptr i = 0; i < suspended_threads.ThreadCount(); i++) {
+ tid_t os_id = static_cast<tid_t>(suspended_threads.GetThreadID(i));
+ LOG_THREADS("Processing thread %llu.\n", os_id);
+ uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end;
+ DTLS *dtls;
+ bool thread_found =
+ GetThreadRangesLocked(os_id, &stack_begin, &stack_end, &tls_begin,
+ &tls_end, &cache_begin, &cache_end, &dtls);
+ if (!thread_found) {
+ // If a thread can't be found in the thread registry, it's probably in the
+ // process of destruction. Log this event and move on.
+ LOG_THREADS("Thread %llu not found in registry.\n", os_id);
+ continue;
+ }
+ uptr sp;
+ PtraceRegistersStatus have_registers =
+ suspended_threads.GetRegistersAndSP(i, &registers, &sp);
+ if (have_registers != REGISTERS_AVAILABLE) {
+ Report("Unable to get registers from thread %llu.\n", os_id);
+ // If unable to get SP, consider the entire stack to be reachable unless
+ // GetRegistersAndSP failed with ESRCH.
+ if (have_registers == REGISTERS_UNAVAILABLE_FATAL)
+ continue;
+ sp = stack_begin;
+ }
+ if (suspended_threads.GetThreadID(i) == caller_tid) {
+ sp = caller_sp;
+ }
+
+ if (flags()->use_registers && have_registers) {
+ uptr registers_begin = reinterpret_cast<uptr>(registers.data());
+ uptr registers_end =
+ reinterpret_cast<uptr>(registers.data() + registers.size());
+ ScanRangeForPointers(registers_begin, registers_end, frontier,
+ "REGISTERS", kReachable);
+ }
+
+ if (flags()->use_stacks) {
+ LOG_THREADS("Stack at %p-%p (SP = %p).\n", (void *)stack_begin,
+ (void *)stack_end, (void *)sp);
+ if (sp < stack_begin || sp >= stack_end) {
+ // SP is outside the recorded stack range (e.g. the thread is running a
+ // signal handler on alternate stack, or swapcontext was used).
+ // Again, consider the entire stack range to be reachable.
+ LOG_THREADS("WARNING: stack pointer not in stack range.\n");
+ uptr page_size = GetPageSizeCached();
+ int skipped = 0;
+ while (stack_begin < stack_end &&
+ !IsAccessibleMemoryRange(stack_begin, 1)) {
+ skipped++;
+ stack_begin += page_size;
+ }
+ LOG_THREADS("Skipped %d guard page(s) to obtain stack %p-%p.\n",
+ skipped, (void *)stack_begin, (void *)stack_end);
+ } else {
+ // Shrink the stack range to ignore out-of-scope values.
+ stack_begin = sp;
+ }
+ ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK",
+ kReachable);
+ extra_ranges.clear();
+ GetThreadExtraStackRangesLocked(os_id, &extra_ranges);
+ ScanExtraStackRanges(extra_ranges, frontier);
+ }
+
+ if (flags()->use_tls) {
+ if (tls_begin) {
+ LOG_THREADS("TLS at %p-%p.\n", (void *)tls_begin, (void *)tls_end);
+ // If the tls and cache ranges don't overlap, scan full tls range,
+ // otherwise, only scan the non-overlapping portions
+ if (cache_begin == cache_end || tls_end < cache_begin ||
+ tls_begin > cache_end) {
+ ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable);
+ } else {
+ if (tls_begin < cache_begin)
+ ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS",
+ kReachable);
+ if (tls_end > cache_end)
+ ScanRangeForPointers(cache_end, tls_end, frontier, "TLS",
+ kReachable);
+ }
+ }
+# if SANITIZER_ANDROID
+ auto *cb = +[](void *dtls_begin, void *dtls_end, uptr /*dso_idd*/,
+ void *arg) -> void {
+ ScanRangeForPointers(reinterpret_cast<uptr>(dtls_begin),
+ reinterpret_cast<uptr>(dtls_end),
+ reinterpret_cast<Frontier *>(arg), "DTLS",
+ kReachable);
+ };
+
+ // FIXME: There might be a race-condition here (and in Bionic) if the
+ // thread is suspended in the middle of updating its DTLS. IOWs, we
+ // could scan already freed memory. (probably fine for now)
+ __libc_iterate_dynamic_tls(os_id, cb, frontier);
+# else
+ if (dtls && !DTLSInDestruction(dtls)) {
+ ForEachDVT(dtls, [&](const DTLS::DTV &dtv, int id) {
+ uptr dtls_beg = dtv.beg;
+ uptr dtls_end = dtls_beg + dtv.size;
+ if (dtls_beg < dtls_end) {
+ LOG_THREADS("DTLS %d at %p-%p.\n", id, (void *)dtls_beg,
+ (void *)dtls_end);
+ ScanRangeForPointers(dtls_beg, dtls_end, frontier, "DTLS",
+ kReachable);
+ }
+ });
+ } else {
+ // We are handling a thread with DTLS under destruction. Log about
+ // this and continue.
+ LOG_THREADS("Thread %llu has DTLS under destruction.\n", os_id);
+ }
+# endif
+ }
+ }
+
+ // Add pointers reachable from ThreadContexts
+ ProcessThreadRegistry(frontier);
+}
+
+# endif // SANITIZER_FUCHSIA
+
+void ScanRootRegion(Frontier *frontier, const RootRegion &root_region,
+ uptr region_begin, uptr region_end, bool is_readable) {
+ uptr intersection_begin = Max(root_region.begin, region_begin);
+ uptr intersection_end = Min(region_end, root_region.begin + root_region.size);
+ if (intersection_begin >= intersection_end)
+ return;
+ LOG_POINTERS("Root region %p-%p intersects with mapped region %p-%p (%s)\n",
+ (void *)root_region.begin,
+ (void *)(root_region.begin + root_region.size),
+ (void *)region_begin, (void *)region_end,
+ is_readable ? "readable" : "unreadable");
+ if (is_readable)
+ ScanRangeForPointers(intersection_begin, intersection_end, frontier, "ROOT",
+ kReachable);
+}
+
+static void ProcessRootRegion(Frontier *frontier,
+ const RootRegion &root_region) {
+ MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
+ MemoryMappedSegment segment;
+ while (proc_maps.Next(&segment)) {
+ ScanRootRegion(frontier, root_region, segment.start, segment.end,
+ segment.IsReadable());
+ }
+}
+
+// Scans root regions for heap pointers.
+static void ProcessRootRegions(Frontier *frontier) {
+ if (!flags()->use_root_regions)
+ return;
+ for (uptr i = 0; i < root_regions.size(); i++)
+ ProcessRootRegion(frontier, root_regions[i]);
+}
+
+static void FloodFillTag(Frontier *frontier, ChunkTag tag) {
+ while (frontier->size()) {
+ uptr next_chunk = frontier->back();
+ frontier->pop_back();
+ LsanMetadata m(next_chunk);
+ ScanRangeForPointers(next_chunk, next_chunk + m.requested_size(), frontier,
+ "HEAP", tag);
+ }
+}
+
+// ForEachChunk callback. If the chunk is marked as leaked, marks all chunks
+// which are reachable from it as indirectly leaked.
+static void MarkIndirectlyLeakedCb(uptr chunk, void *arg) {
+ chunk = GetUserBegin(chunk);
+ LsanMetadata m(chunk);
+ if (m.allocated() && m.tag() != kReachable) {
+ ScanRangeForPointers(chunk, chunk + m.requested_size(),
+ /* frontier */ nullptr, "HEAP", kIndirectlyLeaked);
+ }
+}
+
+static void IgnoredSuppressedCb(uptr chunk, void *arg) {
+ CHECK(arg);
+ chunk = GetUserBegin(chunk);
+ LsanMetadata m(chunk);
+ if (!m.allocated() || m.tag() == kIgnored)
+ return;
+
+ const InternalMmapVector<u32> &suppressed =
+ *static_cast<const InternalMmapVector<u32> *>(arg);
+ uptr idx = InternalLowerBound(suppressed, m.stack_trace_id());
+ if (idx >= suppressed.size() || m.stack_trace_id() != suppressed[idx])
+ return;
+
+ LOG_POINTERS("Suppressed: chunk %p-%p of size %zu.\n", (void *)chunk,
+ (void *)(chunk + m.requested_size()), m.requested_size());
+ m.set_tag(kIgnored);
+}
+
+// ForEachChunk callback. If chunk is marked as ignored, adds its address to
+// frontier.
+static void CollectIgnoredCb(uptr chunk, void *arg) {
+ CHECK(arg);
+ chunk = GetUserBegin(chunk);
+ LsanMetadata m(chunk);
+ if (m.allocated() && m.tag() == kIgnored) {
+ LOG_POINTERS("Ignored: chunk %p-%p of size %zu.\n", (void *)chunk,
+ (void *)(chunk + m.requested_size()), m.requested_size());
+ reinterpret_cast<Frontier *>(arg)->push_back(chunk);
+ }
+}
+
+// Sets the appropriate tag on each chunk.
+static void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads,
+ Frontier *frontier, tid_t caller_tid,
+ uptr caller_sp) {
+ const InternalMmapVector<u32> &suppressed_stacks =
+ GetSuppressionContext()->GetSortedSuppressedStacks();
+ if (!suppressed_stacks.empty()) {
+ ForEachChunk(IgnoredSuppressedCb,
+ const_cast<InternalMmapVector<u32> *>(&suppressed_stacks));
+ }
+ ForEachChunk(CollectIgnoredCb, frontier);
+ ProcessGlobalRegions(frontier);
+ ProcessThreads(suspended_threads, frontier, caller_tid, caller_sp);
+ ProcessRootRegions(frontier);
+ FloodFillTag(frontier, kReachable);
+
+ // The check here is relatively expensive, so we do this in a separate flood
+ // fill. That way we can skip the check for chunks that are reachable
+ // otherwise.
+ LOG_POINTERS("Processing platform-specific allocations.\n");
+ ProcessPlatformSpecificAllocations(frontier);
+ FloodFillTag(frontier, kReachable);
+
+ // Iterate over leaked chunks and mark those that are reachable from other
+ // leaked chunks.
+ LOG_POINTERS("Scanning leaked chunks.\n");
+ ForEachChunk(MarkIndirectlyLeakedCb, nullptr);
+}
+
+// ForEachChunk callback. Resets the tags to pre-leak-check state.
+static void ResetTagsCb(uptr chunk, void *arg) {
+ (void)arg;
+ chunk = GetUserBegin(chunk);
+ LsanMetadata m(chunk);
+ if (m.allocated() && m.tag() != kIgnored)
+ m.set_tag(kDirectlyLeaked);
+}
+
+// ForEachChunk callback. Aggregates information about unreachable chunks into
+// a LeakReport.
+static void CollectLeaksCb(uptr chunk, void *arg) {
+ CHECK(arg);
+ LeakedChunks *leaks = reinterpret_cast<LeakedChunks *>(arg);
+ chunk = GetUserBegin(chunk);
+ LsanMetadata m(chunk);
+ if (!m.allocated())
+ return;
+ if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked)
+ leaks->push_back({chunk, m.stack_trace_id(), m.requested_size(), m.tag()});
+}
+
+void LeakSuppressionContext::PrintMatchedSuppressions() {
+ InternalMmapVector<Suppression *> matched;
+ context.GetMatched(&matched);
+ if (!matched.size())
+ return;
+ const char *line = "-----------------------------------------------------";
+ Printf("%s\n", line);
+ Printf("Suppressions used:\n");
+ Printf(" count bytes template\n");
+ for (uptr i = 0; i < matched.size(); i++) {
+ Printf("%7zu %10zu %s\n",
+ static_cast<uptr>(atomic_load_relaxed(&matched[i]->hit_count)),
+ matched[i]->weight, matched[i]->templ);
+ }
+ Printf("%s\n\n", line);
+}
+
+# if SANITIZER_FUCHSIA
+
+// Fuchsia provides a libc interface that guarantees all threads are
+// covered, and SuspendedThreadList is never really used.
+static void ReportUnsuspendedThreads(const SuspendedThreadsList &) {}
+
+# else // !SANITIZER_FUCHSIA
+
+static void ReportUnsuspendedThreads(
+ const SuspendedThreadsList &suspended_threads) {
+ InternalMmapVector<tid_t> threads(suspended_threads.ThreadCount());
+ for (uptr i = 0; i < suspended_threads.ThreadCount(); ++i)
+ threads[i] = suspended_threads.GetThreadID(i);
+
+ Sort(threads.data(), threads.size());
+
+ InternalMmapVector<tid_t> unsuspended;
+ GetRunningThreadsLocked(&unsuspended);
+
+ for (auto os_id : unsuspended) {
+ uptr i = InternalLowerBound(threads, os_id);
+ if (i >= threads.size() || threads[i] != os_id)
+ Report(
+ "Running thread %zu was not suspended. False leaks are possible.\n",
+ os_id);
+ }
+}
+
+# endif // !SANITIZER_FUCHSIA
+
+static void CheckForLeaksCallback(const SuspendedThreadsList &suspended_threads,
+ void *arg) {
+ CheckForLeaksParam *param = reinterpret_cast<CheckForLeaksParam *>(arg);
+ CHECK(param);
+ CHECK(!param->success);
+ ReportUnsuspendedThreads(suspended_threads);
+ ClassifyAllChunks(suspended_threads, &param->frontier, param->caller_tid,
+ param->caller_sp);
+ ForEachChunk(CollectLeaksCb, &param->leaks);
+ // Clean up for subsequent leak checks. This assumes we did not overwrite any
+ // kIgnored tags.
+ ForEachChunk(ResetTagsCb, nullptr);
+ param->success = true;
+}
+
+static bool PrintResults(LeakReport &report) {
+ uptr unsuppressed_count = report.UnsuppressedLeakCount();
+ if (unsuppressed_count) {
+ Decorator d;
+ Printf(
+ "\n"
+ "================================================================="
+ "\n");
+ Printf("%s", d.Error());
+ Report("ERROR: LeakSanitizer: detected memory leaks\n");
+ Printf("%s", d.Default());
+ report.ReportTopLeaks(flags()->max_leaks);
+ }
+ if (common_flags()->print_suppressions)
+ GetSuppressionContext()->PrintMatchedSuppressions();
+ if (unsuppressed_count > 0) {
+ report.PrintSummary();
+ return true;
+ }
+ return false;
+}
+
+static bool CheckForLeaks() {
+ if (&__lsan_is_turned_off && __lsan_is_turned_off()) {
+ VReport(1, "LeakSanitizer is disabled");
+ return false;
+ }
+ VReport(1, "LeakSanitizer: checking for leaks");
+ // Inside LockStuffAndStopTheWorld we can't run symbolizer, so we can't match
+ // suppressions. However if a stack id was previously suppressed, it should be
+ // suppressed in future checks as well.
+ for (int i = 0;; ++i) {
+ EnsureMainThreadIDIsCorrect();
+ CheckForLeaksParam param;
+ // Capture calling thread's stack pointer early, to avoid false negatives.
+ // Old frame with dead pointers might be overlapped by new frame inside
+ // CheckForLeaks which does not use bytes with pointers before the
+ // threads are suspended and stack pointers captured.
+ param.caller_tid = GetTid();
+ param.caller_sp = reinterpret_cast<uptr>(__builtin_frame_address(0));
+ LockStuffAndStopTheWorld(CheckForLeaksCallback, &param);
+ if (!param.success) {
+ Report("LeakSanitizer has encountered a fatal error.\n");
+ Report(
+ "HINT: For debugging, try setting environment variable "
+ "LSAN_OPTIONS=verbosity=1:log_threads=1\n");
+ Report(
+ "HINT: LeakSanitizer does not work under ptrace (strace, gdb, "
+ "etc)\n");
+ Die();
+ }
+ LeakReport leak_report;
+ leak_report.AddLeakedChunks(param.leaks);
+
+ // No new suppressions stacks, so rerun will not help and we can report.
+ if (!leak_report.ApplySuppressions())
+ return PrintResults(leak_report);
+
+ // No indirect leaks to report, so we are done here.
+ if (!leak_report.IndirectUnsuppressedLeakCount())
+ return PrintResults(leak_report);
+
+ if (i >= 8) {
+ Report("WARNING: LeakSanitizer gave up on indirect leaks suppression.\n");
+ return PrintResults(leak_report);
+ }
+
+ // We found a new previously unseen suppressed call stack. Rerun to make
+ // sure it does not hold indirect leaks.
+ VReport(1, "Rerun with %zu suppressed stacks.",
+ GetSuppressionContext()->GetSortedSuppressedStacks().size());
+ }
+}
+
+static bool has_reported_leaks = false;
+bool HasReportedLeaks() { return has_reported_leaks; }
+
+void DoLeakCheck() {
+ Lock l(&global_mutex);
+ static bool already_done;
+ if (already_done)
+ return;
+ already_done = true;
+ has_reported_leaks = CheckForLeaks();
+ if (has_reported_leaks)
+ HandleLeaks();
+}
+
+static int DoRecoverableLeakCheck() {
+ Lock l(&global_mutex);
+ bool have_leaks = CheckForLeaks();
+ return have_leaks ? 1 : 0;
+}
+
+void DoRecoverableLeakCheckVoid() { DoRecoverableLeakCheck(); }
+
+///// LeakReport implementation. /////
+
+// A hard limit on the number of distinct leaks, to avoid quadratic complexity
+// in LeakReport::AddLeakedChunk(). We don't expect to ever see this many leaks
+// in real-world applications.
+// FIXME: Get rid of this limit by moving logic into DedupLeaks.
+const uptr kMaxLeaksConsidered = 5000;
+
+void LeakReport::AddLeakedChunks(const LeakedChunks &chunks) {
+ for (const LeakedChunk &leak : chunks) {
+ uptr chunk = leak.chunk;
+ u32 stack_trace_id = leak.stack_trace_id;
+ uptr leaked_size = leak.leaked_size;
+ ChunkTag tag = leak.tag;
+ CHECK(tag == kDirectlyLeaked || tag == kIndirectlyLeaked);
+
+ if (u32 resolution = flags()->resolution) {
+ StackTrace stack = StackDepotGet(stack_trace_id);
+ stack.size = Min(stack.size, resolution);
+ stack_trace_id = StackDepotPut(stack);
+ }
+
+ bool is_directly_leaked = (tag == kDirectlyLeaked);
+ uptr i;
+ for (i = 0; i < leaks_.size(); i++) {
+ if (leaks_[i].stack_trace_id == stack_trace_id &&
+ leaks_[i].is_directly_leaked == is_directly_leaked) {
+ leaks_[i].hit_count++;
+ leaks_[i].total_size += leaked_size;
+ break;
+ }
+ }
+ if (i == leaks_.size()) {
+ if (leaks_.size() == kMaxLeaksConsidered)
+ return;
+ Leak leak = {next_id_++, /* hit_count */ 1,
+ leaked_size, stack_trace_id,
+ is_directly_leaked, /* is_suppressed */ false};
+ leaks_.push_back(leak);
+ }
+ if (flags()->report_objects) {
+ LeakedObject obj = {leaks_[i].id, chunk, leaked_size};
+ leaked_objects_.push_back(obj);
+ }
+ }
+}
+
+static bool LeakComparator(const Leak &leak1, const Leak &leak2) {
+ if (leak1.is_directly_leaked == leak2.is_directly_leaked)
+ return leak1.total_size > leak2.total_size;
+ else
+ return leak1.is_directly_leaked;
+}
+
+void LeakReport::ReportTopLeaks(uptr num_leaks_to_report) {
+ CHECK(leaks_.size() <= kMaxLeaksConsidered);
+ Printf("\n");
+ if (leaks_.size() == kMaxLeaksConsidered)
+ Printf(
+ "Too many leaks! Only the first %zu leaks encountered will be "
+ "reported.\n",
+ kMaxLeaksConsidered);
+
+ uptr unsuppressed_count = UnsuppressedLeakCount();
+ if (num_leaks_to_report > 0 && num_leaks_to_report < unsuppressed_count)
+ Printf("The %zu top leak(s):\n", num_leaks_to_report);
+ Sort(leaks_.data(), leaks_.size(), &LeakComparator);
+ uptr leaks_reported = 0;
+ for (uptr i = 0; i < leaks_.size(); i++) {
+ if (leaks_[i].is_suppressed)
+ continue;
+ PrintReportForLeak(i);
+ leaks_reported++;
+ if (leaks_reported == num_leaks_to_report)
+ break;
+ }
+ if (leaks_reported < unsuppressed_count) {
+ uptr remaining = unsuppressed_count - leaks_reported;
+ Printf("Omitting %zu more leak(s).\n", remaining);
+ }
+}
+
+void LeakReport::PrintReportForLeak(uptr index) {
+ Decorator d;
+ Printf("%s", d.Leak());
+ Printf("%s leak of %zu byte(s) in %zu object(s) allocated from:\n",
+ leaks_[index].is_directly_leaked ? "Direct" : "Indirect",
+ leaks_[index].total_size, leaks_[index].hit_count);
+ Printf("%s", d.Default());
+
+ CHECK(leaks_[index].stack_trace_id);
+ StackDepotGet(leaks_[index].stack_trace_id).Print();
+
+ if (flags()->report_objects) {
+ Printf("Objects leaked above:\n");
+ PrintLeakedObjectsForLeak(index);
+ Printf("\n");
+ }
+}
+
+void LeakReport::PrintLeakedObjectsForLeak(uptr index) {
+ u32 leak_id = leaks_[index].id;
+ for (uptr j = 0; j < leaked_objects_.size(); j++) {
+ if (leaked_objects_[j].leak_id == leak_id)
+ Printf("%p (%zu bytes)\n", (void *)leaked_objects_[j].addr,
+ leaked_objects_[j].size);
+ }
+}
+
+void LeakReport::PrintSummary() {
+ CHECK(leaks_.size() <= kMaxLeaksConsidered);
+ uptr bytes = 0, allocations = 0;
+ for (uptr i = 0; i < leaks_.size(); i++) {
+ if (leaks_[i].is_suppressed)
+ continue;
+ bytes += leaks_[i].total_size;
+ allocations += leaks_[i].hit_count;
+ }
+ InternalScopedString summary;
+ summary.append("%zu byte(s) leaked in %zu allocation(s).", bytes,
+ allocations);
+ ReportErrorSummary(summary.data());
+}
+
+uptr LeakReport::ApplySuppressions() {
+ LeakSuppressionContext *suppressions = GetSuppressionContext();
+ uptr new_suppressions = false;
+ for (uptr i = 0; i < leaks_.size(); i++) {
+ if (suppressions->Suppress(leaks_[i].stack_trace_id, leaks_[i].hit_count,
+ leaks_[i].total_size)) {
+ leaks_[i].is_suppressed = true;
+ ++new_suppressions;
+ }
+ }
+ return new_suppressions;
+}
+
+uptr LeakReport::UnsuppressedLeakCount() {
+ uptr result = 0;
+ for (uptr i = 0; i < leaks_.size(); i++)
+ if (!leaks_[i].is_suppressed)
+ result++;
+ return result;
+}
+
+uptr LeakReport::IndirectUnsuppressedLeakCount() {
+ uptr result = 0;
+ for (uptr i = 0; i < leaks_.size(); i++)
+ if (!leaks_[i].is_suppressed && !leaks_[i].is_directly_leaked)
+ result++;
+ return result;
+}
+
+} // namespace __lsan
+#else // CAN_SANITIZE_LEAKS
+namespace __lsan {
+void InitCommonLsan() {}
+void DoLeakCheck() {}
+void DoRecoverableLeakCheckVoid() {}
+void DisableInThisThread() {}
+void EnableInThisThread() {}
+} // namespace __lsan
+#endif // CAN_SANITIZE_LEAKS
+
+using namespace __lsan;
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_ignore_object(const void *p) {
+#if CAN_SANITIZE_LEAKS
+ if (!common_flags()->detect_leaks)
+ return;
+ // Cannot use PointsIntoChunk or LsanMetadata here, since the allocator is not
+ // locked.
+ Lock l(&global_mutex);
+ IgnoreObjectResult res = IgnoreObjectLocked(p);
+ if (res == kIgnoreObjectInvalid)
+ VReport(1, "__lsan_ignore_object(): no heap object found at %p\n", p);
+ if (res == kIgnoreObjectAlreadyIgnored)
+ VReport(1,
+ "__lsan_ignore_object(): "
+ "heap object at %p is already being ignored\n",
+ p);
+ if (res == kIgnoreObjectSuccess)
+ VReport(1, "__lsan_ignore_object(): ignoring heap object at %p\n", p);
+#endif // CAN_SANITIZE_LEAKS
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_register_root_region(const void *begin, uptr size) {
+#if CAN_SANITIZE_LEAKS
+ Lock l(&global_mutex);
+ RootRegion region = {reinterpret_cast<uptr>(begin), size};
+ root_regions.push_back(region);
+ VReport(1, "Registered root region at %p of size %zu\n", begin, size);
+#endif // CAN_SANITIZE_LEAKS
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_unregister_root_region(const void *begin, uptr size) {
+#if CAN_SANITIZE_LEAKS
+ Lock l(&global_mutex);
+ bool removed = false;
+ for (uptr i = 0; i < root_regions.size(); i++) {
+ RootRegion region = root_regions[i];
+ if (region.begin == reinterpret_cast<uptr>(begin) && region.size == size) {
+ removed = true;
+ uptr last_index = root_regions.size() - 1;
+ root_regions[i] = root_regions[last_index];
+ root_regions.pop_back();
+ VReport(1, "Unregistered root region at %p of size %zu\n", begin, size);
+ break;
+ }
+ }
+ if (!removed) {
+ Report(
+ "__lsan_unregister_root_region(): region at %p of size %zu has not "
+ "been registered.\n",
+ begin, size);
+ Die();
+ }
+#endif // CAN_SANITIZE_LEAKS
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_disable() {
+#if CAN_SANITIZE_LEAKS
+ __lsan::DisableInThisThread();
+#endif
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_enable() {
+#if CAN_SANITIZE_LEAKS
+ __lsan::EnableInThisThread();
+#endif
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_do_leak_check() {
+#if CAN_SANITIZE_LEAKS
+ if (common_flags()->detect_leaks)
+ __lsan::DoLeakCheck();
+#endif // CAN_SANITIZE_LEAKS
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __lsan_do_recoverable_leak_check() {
+#if CAN_SANITIZE_LEAKS
+ if (common_flags()->detect_leaks)
+ return __lsan::DoRecoverableLeakCheck();
+#endif // CAN_SANITIZE_LEAKS
+ return 0;
+}
+
+SANITIZER_INTERFACE_WEAK_DEF(const char *, __lsan_default_options, void) {
+ return "";
+}
+
+#if !SANITIZER_SUPPORTS_WEAK_HOOKS
+SANITIZER_INTERFACE_WEAK_DEF(int, __lsan_is_turned_off, void) {
+ return 0;
+}
+
+SANITIZER_INTERFACE_WEAK_DEF(const char *, __lsan_default_suppressions, void) {
+ return "";
+}
+#endif
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_common.h b/contrib/libs/clang16-rt/lib/lsan/lsan_common.h
new file mode 100644
index 00000000000..0d5c0031084
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_common.h
@@ -0,0 +1,350 @@
+//=-- lsan_common.h -------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Private LSan header.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LSAN_COMMON_H
+#define LSAN_COMMON_H
+
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_platform.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_stoptheworld.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
+
+// LeakSanitizer relies on some Glibc's internals (e.g. TLS machinery) on Linux.
+// Also, LSan doesn't like 32 bit architectures
+// because of "small" (4 bytes) pointer size that leads to high false negative
+// ratio on large leaks. But we still want to have it for some 32 bit arches
+// (e.g. x86), see https://github.com/google/sanitizers/issues/403.
+// To enable LeakSanitizer on a new architecture, one needs to implement the
+// internal_clone function as well as (probably) adjust the TLS machinery for
+// the new architecture inside the sanitizer library.
+// Exclude leak-detection on arm32 for Android because `__aeabi_read_tp`
+// is missing. This caused a link error.
+#if SANITIZER_ANDROID && (__ANDROID_API__ < 28 || defined(__arm__))
+# define CAN_SANITIZE_LEAKS 0
+#elif (SANITIZER_LINUX || SANITIZER_APPLE) && (SANITIZER_WORDSIZE == 64) && \
+ (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__) || \
+ defined(__powerpc64__) || defined(__s390x__))
+# define CAN_SANITIZE_LEAKS 1
+#elif defined(__i386__) && (SANITIZER_LINUX || SANITIZER_APPLE)
+# define CAN_SANITIZE_LEAKS 1
+#elif defined(__arm__) && SANITIZER_LINUX
+# define CAN_SANITIZE_LEAKS 1
+#elif SANITIZER_LOONGARCH64 && SANITIZER_LINUX
+# define CAN_SANITIZE_LEAKS 1
+#elif SANITIZER_RISCV64 && SANITIZER_LINUX
+# define CAN_SANITIZE_LEAKS 1
+#elif SANITIZER_NETBSD || SANITIZER_FUCHSIA
+# define CAN_SANITIZE_LEAKS 1
+#else
+# define CAN_SANITIZE_LEAKS 0
+#endif
+
+namespace __sanitizer {
+class FlagParser;
+class ThreadRegistry;
+class ThreadContextBase;
+struct DTLS;
+}
+
+// This section defines function and class prototypes which must be implemented
+// by the parent tool linking in LSan. There are implementations provided by the
+// LSan library which will be linked in when LSan is used as a standalone tool.
+namespace __lsan {
+
+// Chunk tags.
+enum ChunkTag {
+ kDirectlyLeaked = 0, // default
+ kIndirectlyLeaked = 1,
+ kReachable = 2,
+ kIgnored = 3
+};
+
+enum IgnoreObjectResult {
+ kIgnoreObjectSuccess,
+ kIgnoreObjectAlreadyIgnored,
+ kIgnoreObjectInvalid
+};
+
+struct Range {
+ uptr begin;
+ uptr end;
+};
+
+//// --------------------------------------------------------------------------
+//// Poisoning prototypes.
+//// --------------------------------------------------------------------------
+
+// Returns true if [addr, addr + sizeof(void *)) is poisoned.
+bool WordIsPoisoned(uptr addr);
+
+//// --------------------------------------------------------------------------
+//// Thread prototypes.
+//// --------------------------------------------------------------------------
+
+// Wrappers for ThreadRegistry access.
+void LockThreadRegistry() SANITIZER_NO_THREAD_SAFETY_ANALYSIS;
+void UnlockThreadRegistry() SANITIZER_NO_THREAD_SAFETY_ANALYSIS;
+// If called from the main thread, updates the main thread's TID in the thread
+// registry. We need this to handle processes that fork() without a subsequent
+// exec(), which invalidates the recorded TID. To update it, we must call
+// gettid() from the main thread. Our solution is to call this function before
+// leak checking and also before every call to pthread_create() (to handle cases
+// where leak checking is initiated from a non-main thread).
+void EnsureMainThreadIDIsCorrect();
+
+bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
+ uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
+ uptr *cache_end, DTLS **dtls);
+void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches);
+void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges);
+void GetThreadExtraStackRangesLocked(tid_t os_id,
+ InternalMmapVector<Range> *ranges);
+void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs);
+void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads);
+
+//// --------------------------------------------------------------------------
+//// Allocator prototypes.
+//// --------------------------------------------------------------------------
+
+// Wrappers for allocator's ForceLock()/ForceUnlock().
+void LockAllocator();
+void UnlockAllocator();
+
+// Returns the address range occupied by the global allocator object.
+void GetAllocatorGlobalRange(uptr *begin, uptr *end);
+// If p points into a chunk that has been allocated to the user, returns its
+// user-visible address. Otherwise, returns 0.
+uptr PointsIntoChunk(void *p);
+// Returns address of user-visible chunk contained in this allocator chunk.
+uptr GetUserBegin(uptr chunk);
+
+// Wrapper for chunk metadata operations.
+class LsanMetadata {
+ public:
+ // Constructor accepts address of user-visible chunk.
+ explicit LsanMetadata(uptr chunk);
+ bool allocated() const;
+ ChunkTag tag() const;
+ void set_tag(ChunkTag value);
+ uptr requested_size() const;
+ u32 stack_trace_id() const;
+
+ private:
+ void *metadata_;
+};
+
+// Iterate over all existing chunks. Allocator must be locked.
+void ForEachChunk(ForEachChunkCallback callback, void *arg);
+
+// Helper for __lsan_ignore_object().
+IgnoreObjectResult IgnoreObjectLocked(const void *p);
+
+// The rest of the LSan interface which is implemented by library.
+
+struct ScopedStopTheWorldLock {
+ ScopedStopTheWorldLock() {
+ LockThreadRegistry();
+ LockAllocator();
+ }
+
+ ~ScopedStopTheWorldLock() {
+ UnlockAllocator();
+ UnlockThreadRegistry();
+ }
+
+ ScopedStopTheWorldLock &operator=(const ScopedStopTheWorldLock &) = delete;
+ ScopedStopTheWorldLock(const ScopedStopTheWorldLock &) = delete;
+};
+
+struct Flags {
+#define LSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "lsan_flags.inc"
+#undef LSAN_FLAG
+
+ void SetDefaults();
+ uptr pointer_alignment() const {
+ return use_unaligned ? 1 : sizeof(uptr);
+ }
+};
+
+extern Flags lsan_flags;
+inline Flags *flags() { return &lsan_flags; }
+void RegisterLsanFlags(FlagParser *parser, Flags *f);
+
+struct LeakedChunk {
+ uptr chunk;
+ u32 stack_trace_id;
+ uptr leaked_size;
+ ChunkTag tag;
+};
+
+using LeakedChunks = InternalMmapVector<LeakedChunk>;
+
+struct Leak {
+ u32 id;
+ uptr hit_count;
+ uptr total_size;
+ u32 stack_trace_id;
+ bool is_directly_leaked;
+ bool is_suppressed;
+};
+
+struct LeakedObject {
+ u32 leak_id;
+ uptr addr;
+ uptr size;
+};
+
+// Aggregates leaks by stack trace prefix.
+class LeakReport {
+ public:
+ LeakReport() {}
+ void AddLeakedChunks(const LeakedChunks &chunks);
+ void ReportTopLeaks(uptr max_leaks);
+ void PrintSummary();
+ uptr ApplySuppressions();
+ uptr UnsuppressedLeakCount();
+ uptr IndirectUnsuppressedLeakCount();
+
+ private:
+ void PrintReportForLeak(uptr index);
+ void PrintLeakedObjectsForLeak(uptr index);
+
+ u32 next_id_ = 0;
+ InternalMmapVector<Leak> leaks_;
+ InternalMmapVector<LeakedObject> leaked_objects_;
+};
+
+typedef InternalMmapVector<uptr> Frontier;
+
+// Platform-specific functions.
+void InitializePlatformSpecificModules();
+void ProcessGlobalRegions(Frontier *frontier);
+void ProcessPlatformSpecificAllocations(Frontier *frontier);
+
+struct RootRegion {
+ uptr begin;
+ uptr size;
+};
+
+// LockStuffAndStopTheWorld can start to use Scan* calls to collect into
+// this Frontier vector before the StopTheWorldCallback actually runs.
+// This is used when the OS has a unified callback API for suspending
+// threads and enumerating roots.
+struct CheckForLeaksParam {
+ Frontier frontier;
+ LeakedChunks leaks;
+ tid_t caller_tid;
+ uptr caller_sp;
+ bool success = false;
+};
+
+InternalMmapVectorNoCtor<RootRegion> const *GetRootRegions();
+void ScanRootRegion(Frontier *frontier, RootRegion const &region,
+ uptr region_begin, uptr region_end, bool is_readable);
+// Run stoptheworld while holding any platform-specific locks, as well as the
+// allocator and thread registry locks.
+void LockStuffAndStopTheWorld(StopTheWorldCallback callback,
+ CheckForLeaksParam* argument);
+
+void ScanRangeForPointers(uptr begin, uptr end,
+ Frontier *frontier,
+ const char *region_type, ChunkTag tag);
+void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier);
+void ScanExtraStackRanges(const InternalMmapVector<Range> &ranges,
+ Frontier *frontier);
+
+// Functions called from the parent tool.
+const char *MaybeCallLsanDefaultOptions();
+void InitCommonLsan();
+void DoLeakCheck();
+void DoRecoverableLeakCheckVoid();
+void DisableCounterUnderflow();
+bool DisabledInThisThread();
+
+// Used to implement __lsan::ScopedDisabler.
+void DisableInThisThread();
+void EnableInThisThread();
+// Can be used to ignore memory allocated by an intercepted
+// function.
+struct ScopedInterceptorDisabler {
+ ScopedInterceptorDisabler() { DisableInThisThread(); }
+ ~ScopedInterceptorDisabler() { EnableInThisThread(); }
+};
+
+// According to Itanium C++ ABI array cookie is a one word containing
+// size of allocated array.
+static inline bool IsItaniumABIArrayCookie(uptr chunk_beg, uptr chunk_size,
+ uptr addr) {
+ return chunk_size == sizeof(uptr) && chunk_beg + chunk_size == addr &&
+ *reinterpret_cast<uptr *>(chunk_beg) == 0;
+}
+
+// According to ARM C++ ABI array cookie consists of two words:
+// struct array_cookie {
+// std::size_t element_size; // element_size != 0
+// std::size_t element_count;
+// };
+static inline bool IsARMABIArrayCookie(uptr chunk_beg, uptr chunk_size,
+ uptr addr) {
+ return chunk_size == 2 * sizeof(uptr) && chunk_beg + chunk_size == addr &&
+ *reinterpret_cast<uptr *>(chunk_beg + sizeof(uptr)) == 0;
+}
+
+// Special case for "new T[0]" where T is a type with DTOR.
+// new T[0] will allocate a cookie (one or two words) for the array size (0)
+// and store a pointer to the end of allocated chunk. The actual cookie layout
+// varies between platforms according to their C++ ABI implementation.
+inline bool IsSpecialCaseOfOperatorNew0(uptr chunk_beg, uptr chunk_size,
+ uptr addr) {
+#if defined(__arm__)
+ return IsARMABIArrayCookie(chunk_beg, chunk_size, addr);
+#else
+ return IsItaniumABIArrayCookie(chunk_beg, chunk_size, addr);
+#endif
+}
+
+// Return the linker module, if valid for the platform.
+LoadedModule *GetLinker();
+
+// Return true if LSan has finished leak checking and reported leaks.
+bool HasReportedLeaks();
+
+// Run platform-specific leak handlers.
+void HandleLeaks();
+
+} // namespace __lsan
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+const char *__lsan_default_options();
+
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+int __lsan_is_turned_off();
+
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+const char *__lsan_default_suppressions();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_register_root_region(const void *p, __lsan::uptr size);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_unregister_root_region(const void *p, __lsan::uptr size);
+
+} // extern "C"
+
+#endif // LSAN_COMMON_H
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_common_fuchsia.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan_common_fuchsia.cpp
new file mode 100644
index 00000000000..3e1bf8eac7f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_common_fuchsia.cpp
@@ -0,0 +1,167 @@
+//=-- lsan_common_fuchsia.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Implementation of common leak checking functionality. Fuchsia-specific code.
+//
+//===---------------------------------------------------------------------===//
+
+#include "lsan_common.h"
+#include "lsan_thread.h"
+#include "sanitizer_common/sanitizer_platform.h"
+
+#if CAN_SANITIZE_LEAKS && SANITIZER_FUCHSIA
+#error #include <zircon/sanitizer.h>
+
+#include "lsan_allocator.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_stoptheworld_fuchsia.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
+
+// Ensure that the Zircon system ABI is linked in.
+#pragma comment(lib, "zircon")
+
+namespace __lsan {
+
+void InitializePlatformSpecificModules() {}
+
+LoadedModule *GetLinker() { return nullptr; }
+
+__attribute__((tls_model("initial-exec"))) THREADLOCAL int disable_counter;
+bool DisabledInThisThread() { return disable_counter > 0; }
+void DisableInThisThread() { disable_counter++; }
+void EnableInThisThread() {
+ if (disable_counter == 0) {
+ DisableCounterUnderflow();
+ }
+ disable_counter--;
+}
+
+// There is nothing left to do after the globals callbacks.
+void ProcessGlobalRegions(Frontier *frontier) {}
+
+// Nothing to do here.
+void ProcessPlatformSpecificAllocations(Frontier *frontier) {}
+
+// On Fuchsia, we can intercept _Exit gracefully, and return a failing exit
+// code if required at that point. Calling Die() here is undefined
+// behavior and causes rare race conditions.
+void HandleLeaks() {}
+
+// This is defined differently in asan_fuchsia.cpp and lsan_fuchsia.cpp.
+bool UseExitcodeOnLeak();
+
+int ExitHook(int status) {
+ if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
+ if (UseExitcodeOnLeak())
+ DoLeakCheck();
+ else
+ DoRecoverableLeakCheckVoid();
+ }
+ return status == 0 && HasReportedLeaks() ? common_flags()->exitcode : status;
+}
+
+void LockStuffAndStopTheWorld(StopTheWorldCallback callback,
+ CheckForLeaksParam *argument) {
+ ScopedStopTheWorldLock lock;
+
+ struct Params {
+ InternalMmapVector<uptr> allocator_caches;
+ StopTheWorldCallback callback;
+ CheckForLeaksParam *argument;
+ } params = {{}, callback, argument};
+
+ // Callback from libc for globals (data/bss modulo relro), when enabled.
+ auto globals = +[](void *chunk, size_t size, void *data) {
+ auto params = static_cast<const Params *>(data);
+ uptr begin = reinterpret_cast<uptr>(chunk);
+ uptr end = begin + size;
+ ScanGlobalRange(begin, end, &params->argument->frontier);
+ };
+
+ // Callback from libc for thread stacks.
+ auto stacks = +[](void *chunk, size_t size, void *data) {
+ auto params = static_cast<const Params *>(data);
+ uptr begin = reinterpret_cast<uptr>(chunk);
+ uptr end = begin + size;
+ ScanRangeForPointers(begin, end, &params->argument->frontier, "STACK",
+ kReachable);
+ };
+
+ // Callback from libc for thread registers.
+ auto registers = +[](void *chunk, size_t size, void *data) {
+ auto params = static_cast<const Params *>(data);
+ uptr begin = reinterpret_cast<uptr>(chunk);
+ uptr end = begin + size;
+ ScanRangeForPointers(begin, end, &params->argument->frontier, "REGISTERS",
+ kReachable);
+ };
+
+ if (flags()->use_tls) {
+ // Collect the allocator cache range from each thread so these
+ // can all be excluded from the reported TLS ranges.
+ GetAllThreadAllocatorCachesLocked(&params.allocator_caches);
+ __sanitizer::Sort(params.allocator_caches.data(),
+ params.allocator_caches.size());
+ }
+
+ // Callback from libc for TLS regions. This includes thread_local
+ // variables as well as C11 tss_set and POSIX pthread_setspecific.
+ auto tls = +[](void *chunk, size_t size, void *data) {
+ auto params = static_cast<const Params *>(data);
+ uptr begin = reinterpret_cast<uptr>(chunk);
+ uptr end = begin + size;
+ auto i = __sanitizer::InternalLowerBound(params->allocator_caches, begin);
+ if (i < params->allocator_caches.size() &&
+ params->allocator_caches[i] >= begin &&
+ end - params->allocator_caches[i] <= sizeof(AllocatorCache)) {
+ // Split the range in two and omit the allocator cache within.
+ ScanRangeForPointers(begin, params->allocator_caches[i],
+ &params->argument->frontier, "TLS", kReachable);
+ uptr begin2 = params->allocator_caches[i] + sizeof(AllocatorCache);
+ ScanRangeForPointers(begin2, end, &params->argument->frontier, "TLS",
+ kReachable);
+ } else {
+ ScanRangeForPointers(begin, end, &params->argument->frontier, "TLS",
+ kReachable);
+ }
+ };
+
+ // This stops the world and then makes callbacks for various memory regions.
+ // The final callback is the last thing before the world starts up again.
+ __sanitizer_memory_snapshot(
+ flags()->use_globals ? globals : nullptr,
+ flags()->use_stacks ? stacks : nullptr,
+ flags()->use_registers ? registers : nullptr,
+ flags()->use_tls ? tls : nullptr,
+ [](zx_status_t, void *data) {
+ auto params = static_cast<const Params *>(data);
+
+ // We don't use the thread registry at all for enumerating the threads
+ // and their stacks, registers, and TLS regions. So use it separately
+ // just for the allocator cache, and to call ScanExtraStackRanges,
+ // which ASan needs.
+ if (flags()->use_stacks) {
+ InternalMmapVector<Range> ranges;
+ GetThreadExtraStackRangesLocked(&ranges);
+ ScanExtraStackRanges(ranges, &params->argument->frontier);
+ }
+ params->callback(SuspendedThreadsListFuchsia(), params->argument);
+ },
+ &params);
+}
+
+} // namespace __lsan
+
+// This is declared (in extern "C") by <zircon/sanitizer.h>.
+// _Exit calls this directly to intercept and change the status value.
+int __sanitizer_process_exit_hook(int status) {
+ return __lsan::ExitHook(status);
+}
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_common_linux.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan_common_linux.cpp
new file mode 100644
index 00000000000..692ad35169e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_common_linux.cpp
@@ -0,0 +1,147 @@
+//=-- lsan_common_linux.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Implementation of common leak checking functionality. Linux/NetBSD-specific
+// code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#include "lsan_common.h"
+
+#if CAN_SANITIZE_LEAKS && (SANITIZER_LINUX || SANITIZER_NETBSD)
+#include <link.h>
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_getauxval.h"
+#include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+namespace __lsan {
+
+static const char kLinkerName[] = "ld";
+
+static char linker_placeholder[sizeof(LoadedModule)] ALIGNED(64);
+static LoadedModule *linker = nullptr;
+
+static bool IsLinker(const LoadedModule& module) {
+#if SANITIZER_USE_GETAUXVAL
+ return module.base_address() == getauxval(AT_BASE);
+#else
+ return LibraryNameIs(module.full_name(), kLinkerName);
+#endif // SANITIZER_USE_GETAUXVAL
+}
+
+__attribute__((tls_model("initial-exec")))
+THREADLOCAL int disable_counter;
+bool DisabledInThisThread() { return disable_counter > 0; }
+void DisableInThisThread() { disable_counter++; }
+void EnableInThisThread() {
+ if (disable_counter == 0) {
+ DisableCounterUnderflow();
+ }
+ disable_counter--;
+}
+
+void InitializePlatformSpecificModules() {
+ ListOfModules modules;
+ modules.init();
+ for (LoadedModule &module : modules) {
+ if (!IsLinker(module))
+ continue;
+ if (linker == nullptr) {
+ linker = reinterpret_cast<LoadedModule *>(linker_placeholder);
+ *linker = module;
+ module = LoadedModule();
+ } else {
+ VReport(1, "LeakSanitizer: Multiple modules match \"%s\". "
+ "TLS and other allocations originating from linker might be "
+ "falsely reported as leaks.\n", kLinkerName);
+ linker->clear();
+ linker = nullptr;
+ return;
+ }
+ }
+ if (linker == nullptr) {
+ VReport(1, "LeakSanitizer: Dynamic linker not found. TLS and other "
+ "allocations originating from linker might be falsely reported "
+ "as leaks.\n");
+ }
+}
+
+static int ProcessGlobalRegionsCallback(struct dl_phdr_info *info, size_t size,
+ void *data) {
+ Frontier *frontier = reinterpret_cast<Frontier *>(data);
+ for (uptr j = 0; j < info->dlpi_phnum; j++) {
+ const ElfW(Phdr) *phdr = &(info->dlpi_phdr[j]);
+ // We're looking for .data and .bss sections, which reside in writeable,
+ // loadable segments.
+ if (!(phdr->p_flags & PF_W) || (phdr->p_type != PT_LOAD) ||
+ (phdr->p_memsz == 0))
+ continue;
+ uptr begin = info->dlpi_addr + phdr->p_vaddr;
+ uptr end = begin + phdr->p_memsz;
+ ScanGlobalRange(begin, end, frontier);
+ }
+ return 0;
+}
+
+#if SANITIZER_ANDROID && __ANDROID_API__ < 21
+extern "C" __attribute__((weak)) int dl_iterate_phdr(
+ int (*)(struct dl_phdr_info *, size_t, void *), void *);
+#endif
+
+// Scans global variables for heap pointers.
+void ProcessGlobalRegions(Frontier *frontier) {
+ if (!flags()->use_globals) return;
+ dl_iterate_phdr(ProcessGlobalRegionsCallback, frontier);
+}
+
+LoadedModule *GetLinker() { return linker; }
+
+void ProcessPlatformSpecificAllocations(Frontier *frontier) {}
+
+struct DoStopTheWorldParam {
+ StopTheWorldCallback callback;
+ void *argument;
+};
+
+// While calling Die() here is undefined behavior and can potentially
+// cause race conditions, it isn't possible to intercept exit on linux,
+// so we have no choice but to call Die() from the atexit handler.
+void HandleLeaks() {
+ if (common_flags()->exitcode) Die();
+}
+
+static int LockStuffAndStopTheWorldCallback(struct dl_phdr_info *info,
+ size_t size, void *data) {
+ ScopedStopTheWorldLock lock;
+ DoStopTheWorldParam *param = reinterpret_cast<DoStopTheWorldParam *>(data);
+ StopTheWorld(param->callback, param->argument);
+ return 1;
+}
+
+// LSan calls dl_iterate_phdr() from the tracer task. This may deadlock: if one
+// of the threads is frozen while holding the libdl lock, the tracer will hang
+// in dl_iterate_phdr() forever.
+// Luckily, (a) the lock is reentrant and (b) libc can't distinguish between the
+// tracer task and the thread that spawned it. Thus, if we run the tracer task
+// while holding the libdl lock in the parent thread, we can safely reenter it
+// in the tracer. The solution is to run stoptheworld from a dl_iterate_phdr()
+// callback in the parent thread.
+void LockStuffAndStopTheWorld(StopTheWorldCallback callback,
+ CheckForLeaksParam *argument) {
+ DoStopTheWorldParam param = {callback, argument};
+ dl_iterate_phdr(LockStuffAndStopTheWorldCallback, &param);
+}
+
+} // namespace __lsan
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_common_mac.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan_common_mac.cpp
new file mode 100644
index 00000000000..b6b15095744
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_common_mac.cpp
@@ -0,0 +1,238 @@
+//=-- lsan_common_mac.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Implementation of common leak checking functionality. Darwin-specific code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "lsan_common.h"
+
+#if CAN_SANITIZE_LEAKS && SANITIZER_APPLE
+
+# include <mach/mach.h>
+# include <mach/vm_statistics.h>
+# include <pthread.h>
+
+# include "lsan_allocator.h"
+# include "sanitizer_common/sanitizer_allocator_internal.h"
+namespace __lsan {
+
+enum class SeenRegion {
+ None = 0,
+ AllocOnce = 1 << 0,
+ LibDispatch = 1 << 1,
+ Foundation = 1 << 2,
+ All = AllocOnce | LibDispatch | Foundation
+};
+
+inline SeenRegion operator|(SeenRegion left, SeenRegion right) {
+ return static_cast<SeenRegion>(static_cast<int>(left) |
+ static_cast<int>(right));
+}
+
+inline SeenRegion &operator|=(SeenRegion &left, const SeenRegion &right) {
+ left = left | right;
+ return left;
+}
+
+struct RegionScanState {
+ SeenRegion seen_regions = SeenRegion::None;
+ bool in_libdispatch = false;
+};
+
+typedef struct {
+ int disable_counter;
+ u32 current_thread_id;
+ AllocatorCache cache;
+} thread_local_data_t;
+
+static pthread_key_t key;
+static pthread_once_t key_once = PTHREAD_ONCE_INIT;
+
+// The main thread destructor requires the current thread id,
+// so we can't destroy it until it's been used and reset to invalid tid
+void restore_tid_data(void *ptr) {
+ thread_local_data_t *data = (thread_local_data_t *)ptr;
+ if (data->current_thread_id != kInvalidTid)
+ pthread_setspecific(key, data);
+}
+
+static void make_tls_key() {
+ CHECK_EQ(pthread_key_create(&key, restore_tid_data), 0);
+}
+
+static thread_local_data_t *get_tls_val(bool alloc) {
+ pthread_once(&key_once, make_tls_key);
+
+ thread_local_data_t *ptr = (thread_local_data_t *)pthread_getspecific(key);
+ if (ptr == NULL && alloc) {
+ ptr = (thread_local_data_t *)InternalAlloc(sizeof(*ptr));
+ ptr->disable_counter = 0;
+ ptr->current_thread_id = kInvalidTid;
+ ptr->cache = AllocatorCache();
+ pthread_setspecific(key, ptr);
+ }
+
+ return ptr;
+}
+
+bool DisabledInThisThread() {
+ thread_local_data_t *data = get_tls_val(false);
+ return data ? data->disable_counter > 0 : false;
+}
+
+void DisableInThisThread() { ++get_tls_val(true)->disable_counter; }
+
+void EnableInThisThread() {
+ int *disable_counter = &get_tls_val(true)->disable_counter;
+ if (*disable_counter == 0) {
+ DisableCounterUnderflow();
+ }
+ --*disable_counter;
+}
+
+u32 GetCurrentThread() {
+ thread_local_data_t *data = get_tls_val(false);
+ return data ? data->current_thread_id : kInvalidTid;
+}
+
+void SetCurrentThread(u32 tid) { get_tls_val(true)->current_thread_id = tid; }
+
+AllocatorCache *GetAllocatorCache() { return &get_tls_val(true)->cache; }
+
+LoadedModule *GetLinker() { return nullptr; }
+
+// Required on Linux for initialization of TLS behavior, but should not be
+// required on Darwin.
+void InitializePlatformSpecificModules() {}
+
+// Sections which can't contain contain global pointers. This list errs on the
+// side of caution to avoid false positives, at the expense of performance.
+//
+// Other potentially safe sections include:
+// __all_image_info, __crash_info, __const, __got, __interpose, __objc_msg_break
+//
+// Sections which definitely cannot be included here are:
+// __objc_data, __objc_const, __data, __bss, __common, __thread_data,
+// __thread_bss, __thread_vars, __objc_opt_rw, __objc_opt_ptrs
+static const char *kSkippedSecNames[] = {
+ "__cfstring", "__la_symbol_ptr", "__mod_init_func",
+ "__mod_term_func", "__nl_symbol_ptr", "__objc_classlist",
+ "__objc_classrefs", "__objc_imageinfo", "__objc_nlclslist",
+ "__objc_protolist", "__objc_selrefs", "__objc_superrefs"};
+
+// Scans global variables for heap pointers.
+void ProcessGlobalRegions(Frontier *frontier) {
+ for (auto name : kSkippedSecNames)
+ CHECK(internal_strnlen(name, kMaxSegName + 1) <= kMaxSegName);
+
+ MemoryMappingLayout memory_mapping(false);
+ InternalMmapVector<LoadedModule> modules;
+ modules.reserve(128);
+ memory_mapping.DumpListOfModules(&modules);
+ for (uptr i = 0; i < modules.size(); ++i) {
+ // Even when global scanning is disabled, we still need to scan
+ // system libraries for stashed pointers
+ if (!flags()->use_globals && modules[i].instrumented()) continue;
+
+ for (const __sanitizer::LoadedModule::AddressRange &range :
+ modules[i].ranges()) {
+ // Sections storing global variables are writable and non-executable
+ if (range.executable || !range.writable) continue;
+
+ for (auto name : kSkippedSecNames) {
+ if (!internal_strcmp(range.name, name)) continue;
+ }
+
+ ScanGlobalRange(range.beg, range.end, frontier);
+ }
+ }
+}
+
+void ProcessPlatformSpecificAllocations(Frontier *frontier) {
+ vm_address_t address = 0;
+ kern_return_t err = KERN_SUCCESS;
+
+ InternalMmapVectorNoCtor<RootRegion> const *root_regions = GetRootRegions();
+
+ RegionScanState scan_state;
+ while (err == KERN_SUCCESS) {
+ vm_size_t size = 0;
+ unsigned depth = 1;
+ struct vm_region_submap_info_64 info;
+ mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
+ err = vm_region_recurse_64(mach_task_self(), &address, &size, &depth,
+ (vm_region_info_t)&info, &count);
+
+ uptr end_address = address + size;
+ if (info.user_tag == VM_MEMORY_OS_ALLOC_ONCE) {
+ // libxpc stashes some pointers in the Kernel Alloc Once page,
+ // make sure not to report those as leaks.
+ scan_state.seen_regions |= SeenRegion::AllocOnce;
+ ScanRangeForPointers(address, end_address, frontier, "GLOBAL",
+ kReachable);
+ } else if (info.user_tag == VM_MEMORY_FOUNDATION) {
+ // Objective-C block trampolines use the Foundation region.
+ scan_state.seen_regions |= SeenRegion::Foundation;
+ ScanRangeForPointers(address, end_address, frontier, "GLOBAL",
+ kReachable);
+ } else if (info.user_tag == VM_MEMORY_LIBDISPATCH) {
+ // Dispatch continuations use the libdispatch region. Empirically, there
+ // can be more than one region with this tag, so we'll optimistically
+ // assume that they're continguous. Otherwise, we would need to scan every
+ // region to ensure we find them all.
+ scan_state.in_libdispatch = true;
+ ScanRangeForPointers(address, end_address, frontier, "GLOBAL",
+ kReachable);
+ } else if (scan_state.in_libdispatch) {
+ scan_state.seen_regions |= SeenRegion::LibDispatch;
+ scan_state.in_libdispatch = false;
+ }
+
+ // Recursing over the full memory map is very slow, break out
+ // early if we don't need the full iteration.
+ if (scan_state.seen_regions == SeenRegion::All &&
+ !(flags()->use_root_regions && root_regions->size() > 0)) {
+ break;
+ }
+
+ // This additional root region scan is required on Darwin in order to
+ // detect root regions contained within mmap'd memory regions, because
+ // the Darwin implementation of sanitizer_procmaps traverses images
+ // as loaded by dyld, and not the complete set of all memory regions.
+ //
+ // TODO(fjricci) - remove this once sanitizer_procmaps_mac has the same
+ // behavior as sanitizer_procmaps_linux and traverses all memory regions
+ if (flags()->use_root_regions) {
+ for (uptr i = 0; i < root_regions->size(); i++) {
+ ScanRootRegion(frontier, (*root_regions)[i], address, end_address,
+ info.protection & kProtectionRead);
+ }
+ }
+
+ address = end_address;
+ }
+}
+
+// On darwin, we can intercept _exit gracefully, and return a failing exit code
+// if required at that point. Calling Die() here is undefined behavior and
+// causes rare race conditions.
+void HandleLeaks() {}
+
+void LockStuffAndStopTheWorld(StopTheWorldCallback callback,
+ CheckForLeaksParam *argument) {
+ ScopedStopTheWorldLock lock;
+ StopTheWorld(callback, argument);
+}
+
+} // namespace __lsan
+
+#endif // CAN_SANITIZE_LEAKS && SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_flags.inc b/contrib/libs/clang16-rt/lib/lsan/lsan_flags.inc
new file mode 100644
index 00000000000..9350f4bcdc3
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_flags.inc
@@ -0,0 +1,46 @@
+//===-- lsan_flags.inc ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// LSan runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LSAN_FLAG
+# error "Define LSAN_FLAG prior to including this file!"
+#endif
+
+// LSAN_FLAG(Type, Name, DefaultValue, Description)
+// See COMMON_FLAG in sanitizer_flags.inc for more details.
+
+LSAN_FLAG(bool, report_objects, false,
+ "Print addresses of leaked objects after main leak report.")
+LSAN_FLAG(
+ int, resolution, 0,
+ "Aggregate two objects into one leak if this many stack frames match. If "
+ "zero, the entire stack trace must match.")
+LSAN_FLAG(int, max_leaks, 0, "The number of leaks reported.")
+
+// Flags controlling the root set of reachable memory.
+LSAN_FLAG(bool, use_globals, true,
+ "Root set: include global variables (.data and .bss)")
+LSAN_FLAG(bool, use_stacks, true, "Root set: include thread stacks")
+LSAN_FLAG(bool, use_registers, true, "Root set: include thread registers")
+LSAN_FLAG(bool, use_tls, true,
+ "Root set: include TLS and thread-specific storage")
+LSAN_FLAG(bool, use_root_regions, true,
+ "Root set: include regions added via __lsan_register_root_region().")
+LSAN_FLAG(bool, use_ld_allocations, true,
+ "Root set: mark as reachable all allocations made from dynamic "
+ "linker. This was the old way to handle dynamic TLS, and will "
+ "be removed soon. Do not use this flag.")
+
+LSAN_FLAG(bool, use_unaligned, false, "Consider unaligned pointers valid.")
+LSAN_FLAG(bool, use_poisoned, false,
+ "Consider pointers found in poisoned memory to be valid.")
+LSAN_FLAG(bool, log_pointers, false, "Debug logging")
+LSAN_FLAG(bool, log_threads, false, "Debug logging")
+LSAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_fuchsia.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan_fuchsia.cpp
new file mode 100644
index 00000000000..755024460d3
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_fuchsia.cpp
@@ -0,0 +1,129 @@
+//=-- lsan_fuchsia.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Standalone LSan RTL code specific to Fuchsia.
+//
+//===---------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+
+#if SANITIZER_FUCHSIA
+#error #include <zircon/sanitizer.h>
+
+#include "lsan.h"
+#include "lsan_allocator.h"
+
+using namespace __lsan;
+
+namespace __lsan {
+
+void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {}
+
+ThreadContext::ThreadContext(int tid) : ThreadContextLsanBase(tid) {}
+
+struct OnCreatedArgs {
+ uptr stack_begin, stack_end;
+};
+
+// On Fuchsia, the stack bounds of a new thread are available before
+// the thread itself has started running.
+void ThreadContext::OnCreated(void *arg) {
+ // Stack bounds passed through from __sanitizer_before_thread_create_hook
+ // or InitializeMainThread.
+ auto args = reinterpret_cast<const OnCreatedArgs *>(arg);
+ stack_begin_ = args->stack_begin;
+ stack_end_ = args->stack_end;
+}
+
+struct OnStartedArgs {
+ uptr cache_begin, cache_end;
+};
+
+void ThreadContext::OnStarted(void *arg) {
+ auto args = reinterpret_cast<const OnStartedArgs *>(arg);
+ cache_begin_ = args->cache_begin;
+ cache_end_ = args->cache_end;
+}
+
+void ThreadStart(u32 tid) {
+ OnStartedArgs args;
+ GetAllocatorCacheRange(&args.cache_begin, &args.cache_end);
+ CHECK_EQ(args.cache_end - args.cache_begin, sizeof(AllocatorCache));
+ ThreadContextLsanBase::ThreadStart(tid, GetTid(), ThreadType::Regular, &args);
+}
+
+void InitializeMainThread() {
+ OnCreatedArgs args;
+ __sanitizer::GetThreadStackTopAndBottom(true, &args.stack_end,
+ &args.stack_begin);
+ u32 tid = ThreadCreate(kMainTid, true, &args);
+ CHECK_EQ(tid, 0);
+ ThreadStart(tid);
+}
+
+void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {
+ GetLsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
+ [](ThreadContextBase *tctx, void *arg) {
+ auto ctx = static_cast<ThreadContext *>(tctx);
+ static_cast<decltype(caches)>(arg)->push_back(ctx->cache_begin());
+ },
+ caches);
+}
+
+// On Fuchsia, leak detection is done by a special hook after atexit hooks.
+// So this doesn't install any atexit hook like on other platforms.
+void InstallAtExitCheckLeaks() {}
+
+// ASan defines this to check its `halt_on_error` flag.
+bool UseExitcodeOnLeak() { return true; }
+
+} // namespace __lsan
+
+// These are declared (in extern "C") by <zircon/sanitizer.h>.
+// The system runtime will call our definitions directly.
+
+// This is called before each thread creation is attempted. So, in
+// its first call, the calling thread is the initial and sole thread.
+void *__sanitizer_before_thread_create_hook(thrd_t thread, bool detached,
+ const char *name, void *stack_base,
+ size_t stack_size) {
+ ENSURE_LSAN_INITED;
+ EnsureMainThreadIDIsCorrect();
+ OnCreatedArgs args;
+ args.stack_begin = reinterpret_cast<uptr>(stack_base);
+ args.stack_end = args.stack_begin + stack_size;
+ u32 parent_tid = GetCurrentThread();
+ u32 tid = ThreadCreate(parent_tid, detached, &args);
+ return reinterpret_cast<void *>(static_cast<uptr>(tid));
+}
+
+// This is called after creating a new thread (in the creating thread),
+// with the pointer returned by __sanitizer_before_thread_create_hook (above).
+void __sanitizer_thread_create_hook(void *hook, thrd_t thread, int error) {
+ u32 tid = static_cast<u32>(reinterpret_cast<uptr>(hook));
+ // On success, there is nothing to do here.
+ if (error != thrd_success) {
+ // Clean up the thread registry for the thread creation that didn't happen.
+ GetLsanThreadRegistryLocked()->FinishThread(tid);
+ }
+}
+
+// This is called in the newly-created thread before it runs anything else,
+// with the pointer returned by __sanitizer_before_thread_create_hook (above).
+void __sanitizer_thread_start_hook(void *hook, thrd_t self) {
+ u32 tid = static_cast<u32>(reinterpret_cast<uptr>(hook));
+ ThreadStart(tid);
+}
+
+// Each thread runs this just before it exits,
+// with the pointer returned by BeforeThreadCreateHook (above).
+// All per-thread destructors have already been called.
+void __sanitizer_thread_exit_hook(void *hook, thrd_t self) { ThreadFinish(); }
+
+#endif // SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_fuchsia.h b/contrib/libs/clang16-rt/lib/lsan/lsan_fuchsia.h
new file mode 100644
index 00000000000..e730d8f25f2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_fuchsia.h
@@ -0,0 +1,35 @@
+//=-- lsan_fuchsia.h ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Standalone LSan RTL code specific to Fuchsia.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef LSAN_FUCHSIA_H
+#define LSAN_FUCHSIA_H
+
+#include "lsan_thread.h"
+#include "sanitizer_common/sanitizer_platform.h"
+
+#if !SANITIZER_FUCHSIA
+#error "lsan_fuchsia.h is used only on Fuchsia systems (SANITIZER_FUCHSIA)"
+#endif
+
+namespace __lsan {
+
+class ThreadContext final : public ThreadContextLsanBase {
+ public:
+ explicit ThreadContext(int tid);
+ void OnCreated(void *arg) override;
+ void OnStarted(void *arg) override;
+};
+
+} // namespace __lsan
+
+#endif // LSAN_FUCHSIA_H
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_interceptors.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan_interceptors.cpp
new file mode 100644
index 00000000000..3a1b2afdbb7
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_interceptors.cpp
@@ -0,0 +1,542 @@
+//=-- lsan_interceptors.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Interceptors for standalone LSan.
+//
+//===----------------------------------------------------------------------===//
+
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_dlsym.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_platform_interceptors.h"
+#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
+#include "sanitizer_common/sanitizer_platform_limits_posix.h"
+#if SANITIZER_POSIX
+#include "sanitizer_common/sanitizer_posix.h"
+#endif
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+#include "lsan.h"
+#include "lsan_allocator.h"
+#include "lsan_common.h"
+#include "lsan_thread.h"
+
+#include <stddef.h>
+
+using namespace __lsan;
+
+extern "C" {
+int pthread_attr_init(void *attr);
+int pthread_attr_destroy(void *attr);
+int pthread_attr_getdetachstate(void *attr, int *v);
+int pthread_key_create(unsigned *key, void (*destructor)(void* v));
+int pthread_setspecific(unsigned key, const void *v);
+}
+
+struct DlsymAlloc : DlSymAllocator<DlsymAlloc> {
+ static bool UseImpl() { return lsan_init_is_running; }
+ static void OnAllocate(const void *ptr, uptr size) {
+#if CAN_SANITIZE_LEAKS
+ // Suppress leaks from dlerror(). Previously dlsym hack on global array was
+ // used by leak sanitizer as a root region.
+ __lsan_register_root_region(ptr, size);
+#endif
+ }
+ static void OnFree(const void *ptr, uptr size) {
+#if CAN_SANITIZE_LEAKS
+ __lsan_unregister_root_region(ptr, size);
+#endif
+ }
+};
+
+///// Malloc/free interceptors. /////
+
+namespace std {
+ struct nothrow_t;
+ enum class align_val_t: size_t;
+}
+
+#if !SANITIZER_APPLE
+INTERCEPTOR(void*, malloc, uptr size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Allocate(size);
+ ENSURE_LSAN_INITED;
+ GET_STACK_TRACE_MALLOC;
+ return lsan_malloc(size, stack);
+}
+
+INTERCEPTOR(void, free, void *p) {
+ if (DlsymAlloc::PointerIsMine(p))
+ return DlsymAlloc::Free(p);
+ ENSURE_LSAN_INITED;
+ lsan_free(p);
+}
+
+INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Callocate(nmemb, size);
+ ENSURE_LSAN_INITED;
+ GET_STACK_TRACE_MALLOC;
+ return lsan_calloc(nmemb, size, stack);
+}
+
+INTERCEPTOR(void *, realloc, void *ptr, uptr size) {
+ if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Realloc(ptr, size);
+ ENSURE_LSAN_INITED;
+ GET_STACK_TRACE_MALLOC;
+ return lsan_realloc(ptr, size, stack);
+}
+
+INTERCEPTOR(void*, reallocarray, void *q, uptr nmemb, uptr size) {
+ ENSURE_LSAN_INITED;
+ GET_STACK_TRACE_MALLOC;
+ return lsan_reallocarray(q, nmemb, size, stack);
+}
+
+INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
+ ENSURE_LSAN_INITED;
+ GET_STACK_TRACE_MALLOC;
+ return lsan_posix_memalign(memptr, alignment, size, stack);
+}
+
+INTERCEPTOR(void*, valloc, uptr size) {
+ ENSURE_LSAN_INITED;
+ GET_STACK_TRACE_MALLOC;
+ return lsan_valloc(size, stack);
+}
+#endif // !SANITIZER_APPLE
+
+#if SANITIZER_INTERCEPT_MEMALIGN
+INTERCEPTOR(void*, memalign, uptr alignment, uptr size) {
+ ENSURE_LSAN_INITED;
+ GET_STACK_TRACE_MALLOC;
+ return lsan_memalign(alignment, size, stack);
+}
+#define LSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
+#else
+#define LSAN_MAYBE_INTERCEPT_MEMALIGN
+#endif // SANITIZER_INTERCEPT_MEMALIGN
+
+#if SANITIZER_INTERCEPT___LIBC_MEMALIGN
+INTERCEPTOR(void *, __libc_memalign, uptr alignment, uptr size) {
+ ENSURE_LSAN_INITED;
+ GET_STACK_TRACE_MALLOC;
+ void *res = lsan_memalign(alignment, size, stack);
+ DTLS_on_libc_memalign(res, size);
+ return res;
+}
+#define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign)
+#else
+#define LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
+#endif // SANITIZER_INTERCEPT___LIBC_MEMALIGN
+
+#if SANITIZER_INTERCEPT_ALIGNED_ALLOC
+INTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) {
+ ENSURE_LSAN_INITED;
+ GET_STACK_TRACE_MALLOC;
+ return lsan_aligned_alloc(alignment, size, stack);
+}
+#define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc)
+#else
+#define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC
+#endif
+
+#if SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE
+INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
+ ENSURE_LSAN_INITED;
+ return GetMallocUsableSize(ptr);
+}
+#define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \
+ INTERCEPT_FUNCTION(malloc_usable_size)
+#else
+#define LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
+#endif
+
+#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
+struct fake_mallinfo {
+ int x[10];
+};
+
+INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
+ struct fake_mallinfo res;
+ internal_memset(&res, 0, sizeof(res));
+ return res;
+}
+#define LSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
+
+INTERCEPTOR(int, mallopt, int cmd, int value) {
+ return 0;
+}
+#define LSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
+#else
+#define LSAN_MAYBE_INTERCEPT_MALLINFO
+#define LSAN_MAYBE_INTERCEPT_MALLOPT
+#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
+
+#if SANITIZER_INTERCEPT_PVALLOC
+INTERCEPTOR(void*, pvalloc, uptr size) {
+ ENSURE_LSAN_INITED;
+ GET_STACK_TRACE_MALLOC;
+ return lsan_pvalloc(size, stack);
+}
+#define LSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
+#else
+#define LSAN_MAYBE_INTERCEPT_PVALLOC
+#endif // SANITIZER_INTERCEPT_PVALLOC
+
+#if SANITIZER_INTERCEPT_CFREE
+INTERCEPTOR(void, cfree, void *p) ALIAS(WRAPPER_NAME(free));
+#define LSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
+#else
+#define LSAN_MAYBE_INTERCEPT_CFREE
+#endif // SANITIZER_INTERCEPT_CFREE
+
+#if SANITIZER_INTERCEPT_MCHECK_MPROBE
+INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
+ return 0;
+}
+
+INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
+ return 0;
+}
+
+INTERCEPTOR(int, mprobe, void *ptr) {
+ return 0;
+}
+#endif // SANITIZER_INTERCEPT_MCHECK_MPROBE
+
+
+// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
+#define OPERATOR_NEW_BODY(nothrow)\
+ ENSURE_LSAN_INITED;\
+ GET_STACK_TRACE_MALLOC;\
+ void *res = lsan_malloc(size, stack);\
+ if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
+ return res;
+#define OPERATOR_NEW_BODY_ALIGN(nothrow)\
+ ENSURE_LSAN_INITED;\
+ GET_STACK_TRACE_MALLOC;\
+ void *res = lsan_memalign((uptr)align, size, stack);\
+ if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
+ return res;
+
+#define OPERATOR_DELETE_BODY\
+ ENSURE_LSAN_INITED;\
+ lsan_free(ptr);
+
+// On OS X it's not enough to just provide our own 'operator new' and
+// 'operator delete' implementations, because they're going to be in the runtime
+// dylib, and the main executable will depend on both the runtime dylib and
+// libstdc++, each of has its implementation of new and delete.
+// To make sure that C++ allocation/deallocation operators are overridden on
+// OS X we need to intercept them using their mangled names.
+#if !SANITIZER_APPLE
+
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY(true /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY(true /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::align_val_t align)
+{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::align_val_t align)
+{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
+
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::nothrow_t const &)
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, size_t size) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, size_t size) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, size_t size, std::align_val_t) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, size_t size, std::align_val_t) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+
+#else // SANITIZER_APPLE
+
+INTERCEPTOR(void *, _Znwm, size_t size)
+{ OPERATOR_NEW_BODY(false /*nothrow*/); }
+INTERCEPTOR(void *, _Znam, size_t size)
+{ OPERATOR_NEW_BODY(false /*nothrow*/); }
+INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY(true /*nothrow*/); }
+INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY(true /*nothrow*/); }
+
+INTERCEPTOR(void, _ZdlPv, void *ptr)
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR(void, _ZdaPv, void *ptr)
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY; }
+
+#endif // !SANITIZER_APPLE
+
+
+///// Thread initialization and finalization. /////
+
+#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD && !SANITIZER_FUCHSIA
+static unsigned g_thread_finalize_key;
+
+static void thread_finalize(void *v) {
+ uptr iter = (uptr)v;
+ if (iter > 1) {
+ if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
+ Report("LeakSanitizer: failed to set thread key.\n");
+ Die();
+ }
+ return;
+ }
+ ThreadFinish();
+}
+#endif
+
+#if SANITIZER_NETBSD
+INTERCEPTOR(void, _lwp_exit) {
+ ENSURE_LSAN_INITED;
+ ThreadFinish();
+ REAL(_lwp_exit)();
+}
+#define LSAN_MAYBE_INTERCEPT__LWP_EXIT INTERCEPT_FUNCTION(_lwp_exit)
+#else
+#define LSAN_MAYBE_INTERCEPT__LWP_EXIT
+#endif
+
+#if SANITIZER_INTERCEPT_THR_EXIT
+INTERCEPTOR(void, thr_exit, tid_t *state) {
+ ENSURE_LSAN_INITED;
+ ThreadFinish();
+ REAL(thr_exit)(state);
+}
+#define LSAN_MAYBE_INTERCEPT_THR_EXIT INTERCEPT_FUNCTION(thr_exit)
+#else
+#define LSAN_MAYBE_INTERCEPT_THR_EXIT
+#endif
+
+#if SANITIZER_INTERCEPT___CXA_ATEXIT
+INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
+ void *dso_handle) {
+ __lsan::ScopedInterceptorDisabler disabler;
+ return REAL(__cxa_atexit)(func, arg, dso_handle);
+}
+#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit)
+#else
+#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT
+#endif
+
+#if SANITIZER_INTERCEPT_ATEXIT
+INTERCEPTOR(int, atexit, void (*f)()) {
+ __lsan::ScopedInterceptorDisabler disabler;
+ return REAL(__cxa_atexit)((void (*)(void *a))f, 0, 0);
+}
+#define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit)
+#else
+#define LSAN_MAYBE_INTERCEPT_ATEXIT
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_ATFORK
+extern "C" {
+extern int _pthread_atfork(void (*prepare)(), void (*parent)(),
+ void (*child)());
+};
+
+INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(),
+ void (*child)()) {
+ __lsan::ScopedInterceptorDisabler disabler;
+ // REAL(pthread_atfork) cannot be called due to symbol indirections at least
+ // on NetBSD
+ return _pthread_atfork(prepare, parent, child);
+}
+#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork)
+#else
+#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK
+#endif
+
+#if SANITIZER_INTERCEPT_STRERROR
+INTERCEPTOR(char *, strerror, int errnum) {
+ __lsan::ScopedInterceptorDisabler disabler;
+ return REAL(strerror)(errnum);
+}
+#define LSAN_MAYBE_INTERCEPT_STRERROR INTERCEPT_FUNCTION(strerror)
+#else
+#define LSAN_MAYBE_INTERCEPT_STRERROR
+#endif
+
+#if SANITIZER_POSIX
+
+struct ThreadParam {
+ void *(*callback)(void *arg);
+ void *param;
+ atomic_uintptr_t tid;
+};
+
+extern "C" void *__lsan_thread_start_func(void *arg) {
+ ThreadParam *p = (ThreadParam*)arg;
+ void* (*callback)(void *arg) = p->callback;
+ void *param = p->param;
+ // Wait until the last iteration to maximize the chance that we are the last
+ // destructor to run.
+#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
+ if (pthread_setspecific(g_thread_finalize_key,
+ (void*)GetPthreadDestructorIterations())) {
+ Report("LeakSanitizer: failed to set thread key.\n");
+ Die();
+ }
+#endif
+ int tid = 0;
+ while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
+ internal_sched_yield();
+ ThreadStart(tid, GetTid());
+ atomic_store(&p->tid, 0, memory_order_release);
+ return callback(param);
+}
+
+INTERCEPTOR(int, pthread_create, void *th, void *attr,
+ void *(*callback)(void *), void *param) {
+ ENSURE_LSAN_INITED;
+ EnsureMainThreadIDIsCorrect();
+ __sanitizer_pthread_attr_t myattr;
+ if (!attr) {
+ pthread_attr_init(&myattr);
+ attr = &myattr;
+ }
+ AdjustStackSize(attr);
+ int detached = 0;
+ pthread_attr_getdetachstate(attr, &detached);
+ ThreadParam p;
+ p.callback = callback;
+ p.param = param;
+ atomic_store(&p.tid, 0, memory_order_relaxed);
+ int res;
+ {
+ // Ignore all allocations made by pthread_create: thread stack/TLS may be
+ // stored by pthread for future reuse even after thread destruction, and
+ // the linked list it's stored in doesn't even hold valid pointers to the
+ // objects, the latter are calculated by obscure pointer arithmetic.
+ ScopedInterceptorDisabler disabler;
+ res = REAL(pthread_create)(th, attr, __lsan_thread_start_func, &p);
+ }
+ if (res == 0) {
+ int tid = ThreadCreate(GetCurrentThread(), IsStateDetached(detached));
+ CHECK_NE(tid, kMainTid);
+ atomic_store(&p.tid, tid, memory_order_release);
+ while (atomic_load(&p.tid, memory_order_acquire) != 0)
+ internal_sched_yield();
+ }
+ if (attr == &myattr)
+ pthread_attr_destroy(&myattr);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_join, void *t, void **arg) {
+ return REAL(pthread_join)(t, arg);
+}
+
+DEFINE_REAL_PTHREAD_FUNCTIONS
+
+INTERCEPTOR(void, _exit, int status) {
+ if (status == 0 && HasReportedLeaks()) status = common_flags()->exitcode;
+ REAL(_exit)(status);
+}
+
+#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
+#include "sanitizer_common/sanitizer_signal_interceptors.inc"
+
+#endif // SANITIZER_POSIX
+
+namespace __lsan {
+
+void InitializeInterceptors() {
+ // Fuchsia doesn't use interceptors that require any setup.
+#if !SANITIZER_FUCHSIA
+ InitializeSignalInterceptors();
+
+ INTERCEPT_FUNCTION(malloc);
+ INTERCEPT_FUNCTION(free);
+ LSAN_MAYBE_INTERCEPT_CFREE;
+ INTERCEPT_FUNCTION(calloc);
+ INTERCEPT_FUNCTION(realloc);
+ LSAN_MAYBE_INTERCEPT_MEMALIGN;
+ LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN;
+ LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC;
+ INTERCEPT_FUNCTION(posix_memalign);
+ INTERCEPT_FUNCTION(valloc);
+ LSAN_MAYBE_INTERCEPT_PVALLOC;
+ LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE;
+ LSAN_MAYBE_INTERCEPT_MALLINFO;
+ LSAN_MAYBE_INTERCEPT_MALLOPT;
+ INTERCEPT_FUNCTION(pthread_create);
+ INTERCEPT_FUNCTION(pthread_join);
+ INTERCEPT_FUNCTION(_exit);
+
+ LSAN_MAYBE_INTERCEPT__LWP_EXIT;
+ LSAN_MAYBE_INTERCEPT_THR_EXIT;
+
+ LSAN_MAYBE_INTERCEPT___CXA_ATEXIT;
+ LSAN_MAYBE_INTERCEPT_ATEXIT;
+ LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK;
+
+ LSAN_MAYBE_INTERCEPT_STRERROR;
+
+#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
+ if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
+ Report("LeakSanitizer: failed to create thread key.\n");
+ Die();
+ }
+#endif
+
+#endif // !SANITIZER_FUCHSIA
+}
+
+} // namespace __lsan
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_linux.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan_linux.cpp
new file mode 100644
index 00000000000..47c2f21b5a6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_linux.cpp
@@ -0,0 +1,32 @@
+//=-- lsan_linux.cpp ------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer. Linux/NetBSD/Fuchsia-specific code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+
+#if SANITIZER_LINUX || SANITIZER_NETBSD || SANITIZER_FUCHSIA
+
+#include "lsan_allocator.h"
+
+namespace __lsan {
+
+static THREADLOCAL u32 current_thread_tid = kInvalidTid;
+u32 GetCurrentThread() { return current_thread_tid; }
+void SetCurrentThread(u32 tid) { current_thread_tid = tid; }
+
+static THREADLOCAL AllocatorCache allocator_cache;
+AllocatorCache *GetAllocatorCache() { return &allocator_cache; }
+
+void ReplaceSystemMalloc() {}
+
+} // namespace __lsan
+
+#endif // SANITIZER_LINUX || SANITIZER_NETBSD || SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_mac.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan_mac.cpp
new file mode 100644
index 00000000000..6964a9ba28d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_mac.cpp
@@ -0,0 +1,191 @@
+//===-- lsan_mac.cpp ------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer, a memory leak checker.
+//
+// Mac-specific details.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_APPLE
+
+#include "interception/interception.h"
+#include "lsan.h"
+#include "lsan_allocator.h"
+#include "lsan_thread.h"
+
+#include <pthread.h>
+
+namespace __lsan {
+// Support for the following functions from libdispatch on Mac OS:
+// dispatch_async_f()
+// dispatch_async()
+// dispatch_sync_f()
+// dispatch_sync()
+// dispatch_after_f()
+// dispatch_after()
+// dispatch_group_async_f()
+// dispatch_group_async()
+// TODO(glider): libdispatch API contains other functions that we don't support
+// yet.
+//
+// dispatch_sync() and dispatch_sync_f() are synchronous, although chances are
+// they can cause jobs to run on a thread different from the current one.
+// TODO(glider): if so, we need a test for this (otherwise we should remove
+// them).
+//
+// The following functions use dispatch_barrier_async_f() (which isn't a library
+// function but is exported) and are thus supported:
+// dispatch_source_set_cancel_handler_f()
+// dispatch_source_set_cancel_handler()
+// dispatch_source_set_event_handler_f()
+// dispatch_source_set_event_handler()
+//
+// The reference manual for Grand Central Dispatch is available at
+// http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html
+// The implementation details are at
+// http://libdispatch.macosforge.org/trac/browser/trunk/src/queue.c
+
+typedef void *dispatch_group_t;
+typedef void *dispatch_queue_t;
+typedef void *dispatch_source_t;
+typedef u64 dispatch_time_t;
+typedef void (*dispatch_function_t)(void *block);
+typedef void *(*worker_t)(void *block);
+
+// A wrapper for the ObjC blocks used to support libdispatch.
+typedef struct {
+ void *block;
+ dispatch_function_t func;
+ u32 parent_tid;
+} lsan_block_context_t;
+
+ALWAYS_INLINE
+void lsan_register_worker_thread(int parent_tid) {
+ if (GetCurrentThread() == kInvalidTid) {
+ u32 tid = ThreadCreate(parent_tid, true);
+ ThreadStart(tid, GetTid());
+ SetCurrentThread(tid);
+ }
+}
+
+// For use by only those functions that allocated the context via
+// alloc_lsan_context().
+extern "C" void lsan_dispatch_call_block_and_release(void *block) {
+ lsan_block_context_t *context = (lsan_block_context_t *)block;
+ VReport(2,
+ "lsan_dispatch_call_block_and_release(): "
+ "context: %p, pthread_self: %p\n",
+ block, pthread_self());
+ lsan_register_worker_thread(context->parent_tid);
+ // Call the original dispatcher for the block.
+ context->func(context->block);
+ lsan_free(context);
+}
+
+} // namespace __lsan
+
+using namespace __lsan;
+
+// Wrap |ctxt| and |func| into an lsan_block_context_t.
+// The caller retains control of the allocated context.
+extern "C" lsan_block_context_t *alloc_lsan_context(void *ctxt,
+ dispatch_function_t func) {
+ GET_STACK_TRACE_THREAD;
+ lsan_block_context_t *lsan_ctxt =
+ (lsan_block_context_t *)lsan_malloc(sizeof(lsan_block_context_t), stack);
+ lsan_ctxt->block = ctxt;
+ lsan_ctxt->func = func;
+ lsan_ctxt->parent_tid = GetCurrentThread();
+ return lsan_ctxt;
+}
+
+// Define interceptor for dispatch_*_f function with the three most common
+// parameters: dispatch_queue_t, context, dispatch_function_t.
+#define INTERCEPT_DISPATCH_X_F_3(dispatch_x_f) \
+ INTERCEPTOR(void, dispatch_x_f, dispatch_queue_t dq, void *ctxt, \
+ dispatch_function_t func) { \
+ lsan_block_context_t *lsan_ctxt = alloc_lsan_context(ctxt, func); \
+ return REAL(dispatch_x_f)(dq, (void *)lsan_ctxt, \
+ lsan_dispatch_call_block_and_release); \
+ }
+
+INTERCEPT_DISPATCH_X_F_3(dispatch_async_f)
+INTERCEPT_DISPATCH_X_F_3(dispatch_sync_f)
+INTERCEPT_DISPATCH_X_F_3(dispatch_barrier_async_f)
+
+INTERCEPTOR(void, dispatch_after_f, dispatch_time_t when, dispatch_queue_t dq,
+ void *ctxt, dispatch_function_t func) {
+ lsan_block_context_t *lsan_ctxt = alloc_lsan_context(ctxt, func);
+ return REAL(dispatch_after_f)(when, dq, (void *)lsan_ctxt,
+ lsan_dispatch_call_block_and_release);
+}
+
+INTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group,
+ dispatch_queue_t dq, void *ctxt, dispatch_function_t func) {
+ lsan_block_context_t *lsan_ctxt = alloc_lsan_context(ctxt, func);
+ REAL(dispatch_group_async_f)
+ (group, dq, (void *)lsan_ctxt, lsan_dispatch_call_block_and_release);
+}
+
+#if !defined(MISSING_BLOCKS_SUPPORT)
+extern "C" {
+void dispatch_async(dispatch_queue_t dq, void (^work)(void));
+void dispatch_group_async(dispatch_group_t dg, dispatch_queue_t dq,
+ void (^work)(void));
+void dispatch_after(dispatch_time_t when, dispatch_queue_t queue,
+ void (^work)(void));
+void dispatch_source_set_cancel_handler(dispatch_source_t ds,
+ void (^work)(void));
+void dispatch_source_set_event_handler(dispatch_source_t ds,
+ void (^work)(void));
+}
+
+#define GET_LSAN_BLOCK(work) \
+ void (^lsan_block)(void); \
+ int parent_tid = GetCurrentThread(); \
+ lsan_block = ^(void) { \
+ lsan_register_worker_thread(parent_tid); \
+ work(); \
+ }
+
+INTERCEPTOR(void, dispatch_async, dispatch_queue_t dq, void (^work)(void)) {
+ GET_LSAN_BLOCK(work);
+ REAL(dispatch_async)(dq, lsan_block);
+}
+
+INTERCEPTOR(void, dispatch_group_async, dispatch_group_t dg,
+ dispatch_queue_t dq, void (^work)(void)) {
+ GET_LSAN_BLOCK(work);
+ REAL(dispatch_group_async)(dg, dq, lsan_block);
+}
+
+INTERCEPTOR(void, dispatch_after, dispatch_time_t when, dispatch_queue_t queue,
+ void (^work)(void)) {
+ GET_LSAN_BLOCK(work);
+ REAL(dispatch_after)(when, queue, lsan_block);
+}
+
+INTERCEPTOR(void, dispatch_source_set_cancel_handler, dispatch_source_t ds,
+ void (^work)(void)) {
+ if (!work) {
+ REAL(dispatch_source_set_cancel_handler)(ds, work);
+ return;
+ }
+ GET_LSAN_BLOCK(work);
+ REAL(dispatch_source_set_cancel_handler)(ds, lsan_block);
+}
+
+INTERCEPTOR(void, dispatch_source_set_event_handler, dispatch_source_t ds,
+ void (^work)(void)) {
+ GET_LSAN_BLOCK(work);
+ REAL(dispatch_source_set_event_handler)(ds, lsan_block);
+}
+#endif
+
+#endif // SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_malloc_mac.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan_malloc_mac.cpp
new file mode 100644
index 00000000000..525c30272cc
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_malloc_mac.cpp
@@ -0,0 +1,59 @@
+//===-- lsan_malloc_mac.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer (LSan), a memory leak detector.
+//
+// Mac-specific malloc interception.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_APPLE
+
+#include "lsan.h"
+#include "lsan_allocator.h"
+#include "lsan_thread.h"
+
+using namespace __lsan;
+#define COMMON_MALLOC_ZONE_NAME "lsan"
+#define COMMON_MALLOC_ENTER() ENSURE_LSAN_INITED
+#define COMMON_MALLOC_SANITIZER_INITIALIZED lsan_inited
+#define COMMON_MALLOC_FORCE_LOCK()
+#define COMMON_MALLOC_FORCE_UNLOCK()
+#define COMMON_MALLOC_MEMALIGN(alignment, size) \
+ GET_STACK_TRACE_MALLOC; \
+ void *p = lsan_memalign(alignment, size, stack)
+#define COMMON_MALLOC_MALLOC(size) \
+ GET_STACK_TRACE_MALLOC; \
+ void *p = lsan_malloc(size, stack)
+#define COMMON_MALLOC_REALLOC(ptr, size) \
+ GET_STACK_TRACE_MALLOC; \
+ void *p = lsan_realloc(ptr, size, stack)
+#define COMMON_MALLOC_CALLOC(count, size) \
+ GET_STACK_TRACE_MALLOC; \
+ void *p = lsan_calloc(count, size, stack)
+#define COMMON_MALLOC_POSIX_MEMALIGN(memptr, alignment, size) \
+ GET_STACK_TRACE_MALLOC; \
+ int res = lsan_posix_memalign(memptr, alignment, size, stack)
+#define COMMON_MALLOC_VALLOC(size) \
+ GET_STACK_TRACE_MALLOC; \
+ void *p = lsan_valloc(size, stack)
+#define COMMON_MALLOC_FREE(ptr) \
+ lsan_free(ptr)
+#define COMMON_MALLOC_SIZE(ptr) \
+ uptr size = lsan_mz_size(ptr)
+#define COMMON_MALLOC_FILL_STATS(zone, stats)
+#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \
+ (void)zone_name; \
+ Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", ptr);
+#define COMMON_MALLOC_NAMESPACE __lsan
+#define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0
+#define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 0
+
+#include "sanitizer_common/sanitizer_malloc_mac.inc"
+
+#endif // SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_posix.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan_posix.cpp
new file mode 100644
index 00000000000..3c7bc15a851
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_posix.cpp
@@ -0,0 +1,102 @@
+//=-- lsan_posix.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Standalone LSan RTL code common to POSIX-like systems.
+//
+//===---------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+
+#if SANITIZER_POSIX
+#include "lsan.h"
+#include "lsan_allocator.h"
+#include "lsan_thread.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+
+namespace __lsan {
+
+ThreadContext::ThreadContext(int tid) : ThreadContextLsanBase(tid) {}
+
+struct OnStartedArgs {
+ uptr stack_begin;
+ uptr stack_end;
+ uptr cache_begin;
+ uptr cache_end;
+ uptr tls_begin;
+ uptr tls_end;
+ DTLS *dtls;
+};
+
+void ThreadContext::OnStarted(void *arg) {
+ auto args = reinterpret_cast<const OnStartedArgs *>(arg);
+ stack_begin_ = args->stack_begin;
+ stack_end_ = args->stack_end;
+ tls_begin_ = args->tls_begin;
+ tls_end_ = args->tls_end;
+ cache_begin_ = args->cache_begin;
+ cache_end_ = args->cache_end;
+ dtls_ = args->dtls;
+}
+
+void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type) {
+ OnStartedArgs args;
+ uptr stack_size = 0;
+ uptr tls_size = 0;
+ GetThreadStackAndTls(tid == kMainTid, &args.stack_begin, &stack_size,
+ &args.tls_begin, &tls_size);
+ args.stack_end = args.stack_begin + stack_size;
+ args.tls_end = args.tls_begin + tls_size;
+ GetAllocatorCacheRange(&args.cache_begin, &args.cache_end);
+ args.dtls = DTLS_Get();
+ ThreadContextLsanBase::ThreadStart(tid, os_id, thread_type, &args);
+}
+
+bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
+ uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
+ uptr *cache_end, DTLS **dtls) {
+ ThreadContext *context = static_cast<ThreadContext *>(
+ GetLsanThreadRegistryLocked()->FindThreadContextByOsIDLocked(os_id));
+ if (!context)
+ return false;
+ *stack_begin = context->stack_begin();
+ *stack_end = context->stack_end();
+ *tls_begin = context->tls_begin();
+ *tls_end = context->tls_end();
+ *cache_begin = context->cache_begin();
+ *cache_end = context->cache_end();
+ *dtls = context->dtls();
+ return true;
+}
+
+void InitializeMainThread() {
+ u32 tid = ThreadCreate(kMainTid, true);
+ CHECK_EQ(tid, kMainTid);
+ ThreadStart(tid, GetTid());
+}
+
+static void OnStackUnwind(const SignalContext &sig, const void *,
+ BufferedStackTrace *stack) {
+ stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
+ common_flags()->fast_unwind_on_fatal);
+}
+
+void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {
+ HandleDeadlySignal(siginfo, context, GetCurrentThread(), &OnStackUnwind,
+ nullptr);
+}
+
+void InstallAtExitCheckLeaks() {
+ if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
+ Atexit(DoLeakCheck);
+}
+
+} // namespace __lsan
+
+#endif // SANITIZER_POSIX
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_posix.h b/contrib/libs/clang16-rt/lib/lsan/lsan_posix.h
new file mode 100644
index 00000000000..b1265f233f3
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_posix.h
@@ -0,0 +1,49 @@
+//=-- lsan_posix.h -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Standalone LSan RTL code common to POSIX-like systems.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef LSAN_POSIX_H
+#define LSAN_POSIX_H
+
+#include "lsan_thread.h"
+#include "sanitizer_common/sanitizer_platform.h"
+
+#if !SANITIZER_POSIX
+#error "lsan_posix.h is used only on POSIX-like systems (SANITIZER_POSIX)"
+#endif
+
+namespace __sanitizer {
+struct DTLS;
+}
+
+namespace __lsan {
+
+class ThreadContext final : public ThreadContextLsanBase {
+ public:
+ explicit ThreadContext(int tid);
+ void OnStarted(void *arg) override;
+ uptr tls_begin() { return tls_begin_; }
+ uptr tls_end() { return tls_end_; }
+ DTLS *dtls() { return dtls_; }
+
+ private:
+ uptr tls_begin_ = 0;
+ uptr tls_end_ = 0;
+ DTLS *dtls_ = nullptr;
+};
+
+void ThreadStart(u32 tid, tid_t os_id,
+ ThreadType thread_type = ThreadType::Regular);
+
+} // namespace __lsan
+
+#endif // LSAN_POSIX_H
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_preinit.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan_preinit.cpp
new file mode 100644
index 00000000000..cd94e1e8718
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_preinit.cpp
@@ -0,0 +1,21 @@
+//===-- lsan_preinit.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+//
+// Call __lsan_init at the very early stage of process startup.
+//===----------------------------------------------------------------------===//
+
+#include "lsan.h"
+
+#if SANITIZER_CAN_USE_PREINIT_ARRAY
+ // We force __lsan_init to be called before anyone else by placing it into
+ // .preinit_array section.
+ __attribute__((section(".preinit_array"), used))
+ void (*__local_lsan_preinit)(void) = __lsan_init;
+#endif
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_thread.cpp b/contrib/libs/clang16-rt/lib/lsan/lsan_thread.cpp
new file mode 100644
index 00000000000..137c7e4e4f1
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_thread.cpp
@@ -0,0 +1,102 @@
+//=-- lsan_thread.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// See lsan_thread.h for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lsan_thread.h"
+
+#include "lsan.h"
+#include "lsan_allocator.h"
+#include "lsan_common.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+
+namespace __lsan {
+
+static ThreadRegistry *thread_registry;
+
+static ThreadContextBase *CreateThreadContext(u32 tid) {
+ void *mem = MmapOrDie(sizeof(ThreadContext), "ThreadContext");
+ return new (mem) ThreadContext(tid);
+}
+
+void InitializeThreadRegistry() {
+ static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)];
+ thread_registry =
+ new (thread_registry_placeholder) ThreadRegistry(CreateThreadContext);
+}
+
+ThreadContextLsanBase::ThreadContextLsanBase(int tid)
+ : ThreadContextBase(tid) {}
+
+void ThreadContextLsanBase::OnFinished() {
+ AllocatorThreadFinish();
+ DTLS_Destroy();
+}
+
+u32 ThreadCreate(u32 parent_tid, bool detached, void *arg) {
+ return thread_registry->CreateThread(0, detached, parent_tid, arg);
+}
+
+void ThreadContextLsanBase::ThreadStart(u32 tid, tid_t os_id,
+ ThreadType thread_type, void *arg) {
+ thread_registry->StartThread(tid, os_id, thread_type, arg);
+ SetCurrentThread(tid);
+}
+
+void ThreadFinish() {
+ thread_registry->FinishThread(GetCurrentThread());
+ SetCurrentThread(kInvalidTid);
+}
+
+ThreadContext *CurrentThreadContext() {
+ if (!thread_registry)
+ return nullptr;
+ if (GetCurrentThread() == kInvalidTid)
+ return nullptr;
+ // No lock needed when getting current thread.
+ return (ThreadContext *)thread_registry->GetThreadLocked(GetCurrentThread());
+}
+
+void EnsureMainThreadIDIsCorrect() {
+ if (GetCurrentThread() == kMainTid)
+ CurrentThreadContext()->os_id = GetTid();
+}
+
+///// Interface to the common LSan module. /////
+
+void GetThreadExtraStackRangesLocked(tid_t os_id,
+ InternalMmapVector<Range> *ranges) {}
+void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges) {}
+
+void LockThreadRegistry() { thread_registry->Lock(); }
+
+void UnlockThreadRegistry() { thread_registry->Unlock(); }
+
+ThreadRegistry *GetLsanThreadRegistryLocked() {
+ thread_registry->CheckLocked();
+ return thread_registry;
+}
+
+void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads) {
+ GetLsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
+ [](ThreadContextBase *tctx, void *threads) {
+ if (tctx->status == ThreadStatusRunning) {
+ reinterpret_cast<InternalMmapVector<tid_t> *>(threads)->push_back(
+ tctx->os_id);
+ }
+ },
+ threads);
+}
+
+} // namespace __lsan
diff --git a/contrib/libs/clang16-rt/lib/lsan/lsan_thread.h b/contrib/libs/clang16-rt/lib/lsan/lsan_thread.h
new file mode 100644
index 00000000000..049c7e20380
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/lsan_thread.h
@@ -0,0 +1,60 @@
+//=-- lsan_thread.h -------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Thread registry for standalone LSan.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LSAN_THREAD_H
+#define LSAN_THREAD_H
+
+#include "sanitizer_common/sanitizer_thread_registry.h"
+
+namespace __lsan {
+
+class ThreadContextLsanBase : public ThreadContextBase {
+ public:
+ explicit ThreadContextLsanBase(int tid);
+ void OnFinished() override;
+ uptr stack_begin() { return stack_begin_; }
+ uptr stack_end() { return stack_end_; }
+ uptr cache_begin() { return cache_begin_; }
+ uptr cache_end() { return cache_end_; }
+
+ // The argument is passed on to the subclass's OnStarted member function.
+ static void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type,
+ void *onstarted_arg);
+
+ protected:
+ ~ThreadContextLsanBase() {}
+ uptr stack_begin_ = 0;
+ uptr stack_end_ = 0;
+ uptr cache_begin_ = 0;
+ uptr cache_end_ = 0;
+};
+
+// This subclass of ThreadContextLsanBase is declared in an OS-specific header.
+class ThreadContext;
+
+void InitializeThreadRegistry();
+void InitializeMainThread();
+
+ThreadRegistry *GetLsanThreadRegistryLocked();
+
+u32 ThreadCreate(u32 tid, bool detached, void *arg = nullptr);
+void ThreadFinish();
+
+u32 GetCurrentThread();
+void SetCurrentThread(u32 tid);
+ThreadContext *CurrentThreadContext();
+void EnsureMainThreadIDIsCorrect();
+
+} // namespace __lsan
+
+#endif // LSAN_THREAD_H
diff --git a/contrib/libs/clang16-rt/lib/lsan/ya.make b/contrib/libs/clang16-rt/lib/lsan/ya.make
new file mode 100644
index 00000000000..64677c9588c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/lsan/ya.make
@@ -0,0 +1,131 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.lsan${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHAVE_RPC_XDR_H=0
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ interception/interception_linux.cpp
+ interception/interception_mac.cpp
+ interception/interception_type_test.cpp
+ interception/interception_win.cpp
+ lsan/lsan.cpp
+ lsan/lsan_allocator.cpp
+ lsan/lsan_common.cpp
+ lsan/lsan_common_fuchsia.cpp
+ lsan/lsan_common_linux.cpp
+ lsan/lsan_common_mac.cpp
+ lsan/lsan_fuchsia.cpp
+ lsan/lsan_interceptors.cpp
+ lsan/lsan_linux.cpp
+ lsan/lsan_mac.cpp
+ lsan/lsan_malloc_mac.cpp
+ lsan/lsan_posix.cpp
+ lsan/lsan_preinit.cpp
+ lsan/lsan_thread.cpp
+ sanitizer_common/sancov_flags.cpp
+ sanitizer_common/sanitizer_allocator.cpp
+ sanitizer_common/sanitizer_allocator_checks.cpp
+ sanitizer_common/sanitizer_allocator_report.cpp
+ sanitizer_common/sanitizer_chained_origin_depot.cpp
+ sanitizer_common/sanitizer_common.cpp
+ sanitizer_common/sanitizer_common_libcdep.cpp
+ sanitizer_common/sanitizer_coverage_fuchsia.cpp
+ sanitizer_common/sanitizer_coverage_libcdep_new.cpp
+ sanitizer_common/sanitizer_coverage_win_sections.cpp
+ sanitizer_common/sanitizer_deadlock_detector1.cpp
+ sanitizer_common/sanitizer_deadlock_detector2.cpp
+ sanitizer_common/sanitizer_errno.cpp
+ sanitizer_common/sanitizer_file.cpp
+ sanitizer_common/sanitizer_flag_parser.cpp
+ sanitizer_common/sanitizer_flags.cpp
+ sanitizer_common/sanitizer_fuchsia.cpp
+ sanitizer_common/sanitizer_libc.cpp
+ sanitizer_common/sanitizer_libignore.cpp
+ sanitizer_common/sanitizer_linux.cpp
+ sanitizer_common/sanitizer_linux_libcdep.cpp
+ sanitizer_common/sanitizer_linux_s390.cpp
+ sanitizer_common/sanitizer_mac.cpp
+ sanitizer_common/sanitizer_mac_libcdep.cpp
+ sanitizer_common/sanitizer_mutex.cpp
+ sanitizer_common/sanitizer_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+ sanitizer_common/sanitizer_platform_limits_linux.cpp
+ sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_posix.cpp
+ sanitizer_common/sanitizer_platform_limits_solaris.cpp
+ sanitizer_common/sanitizer_posix.cpp
+ sanitizer_common/sanitizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_printf.cpp
+ sanitizer_common/sanitizer_procmaps_bsd.cpp
+ sanitizer_common/sanitizer_procmaps_common.cpp
+ sanitizer_common/sanitizer_procmaps_fuchsia.cpp
+ sanitizer_common/sanitizer_procmaps_linux.cpp
+ sanitizer_common/sanitizer_procmaps_mac.cpp
+ sanitizer_common/sanitizer_procmaps_solaris.cpp
+ sanitizer_common/sanitizer_solaris.cpp
+ sanitizer_common/sanitizer_stack_store.cpp
+ sanitizer_common/sanitizer_stackdepot.cpp
+ sanitizer_common/sanitizer_stacktrace.cpp
+ sanitizer_common/sanitizer_stacktrace_libcdep.cpp
+ sanitizer_common/sanitizer_stacktrace_printer.cpp
+ sanitizer_common/sanitizer_stacktrace_sparc.cpp
+ sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
+ sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_mac.cpp
+ sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_win.cpp
+ sanitizer_common/sanitizer_suppressions.cpp
+ sanitizer_common/sanitizer_symbolizer.cpp
+ sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
+ sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_mac.cpp
+ sanitizer_common/sanitizer_symbolizer_markup.cpp
+ sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_report.cpp
+ sanitizer_common/sanitizer_symbolizer_win.cpp
+ sanitizer_common/sanitizer_termination.cpp
+ sanitizer_common/sanitizer_thread_registry.cpp
+ sanitizer_common/sanitizer_tls_get_addr.cpp
+ sanitizer_common/sanitizer_type_traits.cpp
+ sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
+ sanitizer_common/sanitizer_unwind_win.cpp
+ sanitizer_common/sanitizer_win.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/memprof-preinit/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/memprof-preinit/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof-preinit/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/memprof-preinit/ya.make b/contrib/libs/clang16-rt/lib/memprof-preinit/ya.make
new file mode 100644
index 00000000000..7a5ada8f052
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof-preinit/ya.make
@@ -0,0 +1,45 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.memprof-preinit${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib/memprof)
+
+SRCS(
+ memprof_preinit.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/memprof/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/memprof/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/memprof/README.txt b/contrib/libs/clang16-rt/lib/memprof/README.txt
new file mode 100644
index 00000000000..82012c5e71b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/README.txt
@@ -0,0 +1,17 @@
+MemProfiling RT
+================================
+This directory contains sources of the MemProfiling (MemProf) runtime library.
+
+Directory structure:
+README.txt : This file.
+CMakeLists.txt : File for cmake-based build.
+memprof_*.{cc,h} : Sources of the memprof runtime library.
+
+Also MemProf runtime needs the following libraries:
+lib/interception/ : Machinery used to intercept function calls.
+lib/sanitizer_common/ : Code shared between various sanitizers.
+
+MemProf runtime can only be built by CMake. You can run MemProf tests
+from the root of your CMake build tree:
+
+make check-memprof
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_allocator.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_allocator.cpp
new file mode 100644
index 00000000000..c21e4e8a569
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_allocator.cpp
@@ -0,0 +1,710 @@
+//===-- memprof_allocator.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// Implementation of MemProf's memory allocator, which uses the allocator
+// from sanitizer_common.
+//
+//===----------------------------------------------------------------------===//
+
+#include "memprof_allocator.h"
+#include "memprof_mapping.h"
+#include "memprof_mibmap.h"
+#include "memprof_rawprofile.h"
+#include "memprof_stack.h"
+#include "memprof_thread.h"
+#include "profile/MemProfData.inc"
+#include "sanitizer_common/sanitizer_allocator_checks.h"
+#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
+#include "sanitizer_common/sanitizer_errno.h"
+#include "sanitizer_common/sanitizer_file.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+#include <sched.h>
+#include <time.h>
+
+namespace __memprof {
+namespace {
+using ::llvm::memprof::MemInfoBlock;
+
+void Print(const MemInfoBlock &M, const u64 id, bool print_terse) {
+ u64 p;
+
+ if (print_terse) {
+ p = M.TotalSize * 100 / M.AllocCount;
+ Printf("MIB:%llu/%u/%llu.%02llu/%u/%u/", id, M.AllocCount, p / 100, p % 100,
+ M.MinSize, M.MaxSize);
+ p = M.TotalAccessCount * 100 / M.AllocCount;
+ Printf("%llu.%02llu/%llu/%llu/", p / 100, p % 100, M.MinAccessCount,
+ M.MaxAccessCount);
+ p = M.TotalLifetime * 100 / M.AllocCount;
+ Printf("%llu.%02llu/%u/%u/", p / 100, p % 100, M.MinLifetime,
+ M.MaxLifetime);
+ Printf("%u/%u/%u/%u\n", M.NumMigratedCpu, M.NumLifetimeOverlaps,
+ M.NumSameAllocCpu, M.NumSameDeallocCpu);
+ } else {
+ p = M.TotalSize * 100 / M.AllocCount;
+ Printf("Memory allocation stack id = %llu\n", id);
+ Printf("\talloc_count %u, size (ave/min/max) %llu.%02llu / %u / %u\n",
+ M.AllocCount, p / 100, p % 100, M.MinSize, M.MaxSize);
+ p = M.TotalAccessCount * 100 / M.AllocCount;
+ Printf("\taccess_count (ave/min/max): %llu.%02llu / %llu / %llu\n", p / 100,
+ p % 100, M.MinAccessCount, M.MaxAccessCount);
+ p = M.TotalLifetime * 100 / M.AllocCount;
+ Printf("\tlifetime (ave/min/max): %llu.%02llu / %u / %u\n", p / 100,
+ p % 100, M.MinLifetime, M.MaxLifetime);
+ Printf("\tnum migrated: %u, num lifetime overlaps: %u, num same alloc "
+ "cpu: %u, num same dealloc_cpu: %u\n",
+ M.NumMigratedCpu, M.NumLifetimeOverlaps, M.NumSameAllocCpu,
+ M.NumSameDeallocCpu);
+ }
+}
+} // namespace
+
+static int GetCpuId(void) {
+ // _memprof_preinit is called via the preinit_array, which subsequently calls
+ // malloc. Since this is before _dl_init calls VDSO_SETUP, sched_getcpu
+ // will seg fault as the address of __vdso_getcpu will be null.
+ if (!memprof_init_done)
+ return -1;
+ return sched_getcpu();
+}
+
+// Compute the timestamp in ms.
+static int GetTimestamp(void) {
+ // timespec_get will segfault if called from dl_init
+ if (!memprof_timestamp_inited) {
+ // By returning 0, this will be effectively treated as being
+ // timestamped at memprof init time (when memprof_init_timestamp_s
+ // is initialized).
+ return 0;
+ }
+ timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ return (ts.tv_sec - memprof_init_timestamp_s) * 1000 + ts.tv_nsec / 1000000;
+}
+
+static MemprofAllocator &get_allocator();
+
+// The memory chunk allocated from the underlying allocator looks like this:
+// H H U U U U U U
+// H -- ChunkHeader (32 bytes)
+// U -- user memory.
+
+// If there is left padding before the ChunkHeader (due to use of memalign),
+// we store a magic value in the first uptr word of the memory block and
+// store the address of ChunkHeader in the next uptr.
+// M B L L L L L L L L L H H U U U U U U
+// | ^
+// ---------------------|
+// M -- magic value kAllocBegMagic
+// B -- address of ChunkHeader pointing to the first 'H'
+
+constexpr uptr kMaxAllowedMallocBits = 40;
+
+// Should be no more than 32-bytes
+struct ChunkHeader {
+ // 1-st 4 bytes.
+ u32 alloc_context_id;
+ // 2-nd 4 bytes
+ u32 cpu_id;
+ // 3-rd 4 bytes
+ u32 timestamp_ms;
+ // 4-th 4 bytes
+ // Note only 1 bit is needed for this flag if we need space in the future for
+ // more fields.
+ u32 from_memalign;
+ // 5-th and 6-th 4 bytes
+ // The max size of an allocation is 2^40 (kMaxAllowedMallocSize), so this
+ // could be shrunk to kMaxAllowedMallocBits if we need space in the future for
+ // more fields.
+ atomic_uint64_t user_requested_size;
+ // 23 bits available
+ // 7-th and 8-th 4 bytes
+ u64 data_type_id; // TODO: hash of type name
+};
+
+static const uptr kChunkHeaderSize = sizeof(ChunkHeader);
+COMPILER_CHECK(kChunkHeaderSize == 32);
+
+struct MemprofChunk : ChunkHeader {
+ uptr Beg() { return reinterpret_cast<uptr>(this) + kChunkHeaderSize; }
+ uptr UsedSize() {
+ return atomic_load(&user_requested_size, memory_order_relaxed);
+ }
+ void *AllocBeg() {
+ if (from_memalign)
+ return get_allocator().GetBlockBegin(reinterpret_cast<void *>(this));
+ return reinterpret_cast<void *>(this);
+ }
+};
+
+class LargeChunkHeader {
+ static constexpr uptr kAllocBegMagic =
+ FIRST_32_SECOND_64(0xCC6E96B9, 0xCC6E96B9CC6E96B9ULL);
+ atomic_uintptr_t magic;
+ MemprofChunk *chunk_header;
+
+public:
+ MemprofChunk *Get() const {
+ return atomic_load(&magic, memory_order_acquire) == kAllocBegMagic
+ ? chunk_header
+ : nullptr;
+ }
+
+ void Set(MemprofChunk *p) {
+ if (p) {
+ chunk_header = p;
+ atomic_store(&magic, kAllocBegMagic, memory_order_release);
+ return;
+ }
+
+ uptr old = kAllocBegMagic;
+ if (!atomic_compare_exchange_strong(&magic, &old, 0,
+ memory_order_release)) {
+ CHECK_EQ(old, kAllocBegMagic);
+ }
+ }
+};
+
+void FlushUnneededMemProfShadowMemory(uptr p, uptr size) {
+ // Since memprof's mapping is compacting, the shadow chunk may be
+ // not page-aligned, so we only flush the page-aligned portion.
+ ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
+}
+
+void MemprofMapUnmapCallback::OnMap(uptr p, uptr size) const {
+ // Statistics.
+ MemprofStats &thread_stats = GetCurrentThreadStats();
+ thread_stats.mmaps++;
+ thread_stats.mmaped += size;
+}
+void MemprofMapUnmapCallback::OnUnmap(uptr p, uptr size) const {
+ // We are about to unmap a chunk of user memory.
+ // Mark the corresponding shadow memory as not needed.
+ FlushUnneededMemProfShadowMemory(p, size);
+ // Statistics.
+ MemprofStats &thread_stats = GetCurrentThreadStats();
+ thread_stats.munmaps++;
+ thread_stats.munmaped += size;
+}
+
+AllocatorCache *GetAllocatorCache(MemprofThreadLocalMallocStorage *ms) {
+ CHECK(ms);
+ return &ms->allocator_cache;
+}
+
+// Accumulates the access count from the shadow for the given pointer and size.
+u64 GetShadowCount(uptr p, u32 size) {
+ u64 *shadow = (u64 *)MEM_TO_SHADOW(p);
+ u64 *shadow_end = (u64 *)MEM_TO_SHADOW(p + size);
+ u64 count = 0;
+ for (; shadow <= shadow_end; shadow++)
+ count += *shadow;
+ return count;
+}
+
+// Clears the shadow counters (when memory is allocated).
+void ClearShadow(uptr addr, uptr size) {
+ CHECK(AddrIsAlignedByGranularity(addr));
+ CHECK(AddrIsInMem(addr));
+ CHECK(AddrIsAlignedByGranularity(addr + size));
+ CHECK(AddrIsInMem(addr + size - SHADOW_GRANULARITY));
+ CHECK(REAL(memset));
+ uptr shadow_beg = MEM_TO_SHADOW(addr);
+ uptr shadow_end = MEM_TO_SHADOW(addr + size - SHADOW_GRANULARITY) + 1;
+ if (shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) {
+ REAL(memset)((void *)shadow_beg, 0, shadow_end - shadow_beg);
+ } else {
+ uptr page_size = GetPageSizeCached();
+ uptr page_beg = RoundUpTo(shadow_beg, page_size);
+ uptr page_end = RoundDownTo(shadow_end, page_size);
+
+ if (page_beg >= page_end) {
+ REAL(memset)((void *)shadow_beg, 0, shadow_end - shadow_beg);
+ } else {
+ if (page_beg != shadow_beg) {
+ REAL(memset)((void *)shadow_beg, 0, page_beg - shadow_beg);
+ }
+ if (page_end != shadow_end) {
+ REAL(memset)((void *)page_end, 0, shadow_end - page_end);
+ }
+ ReserveShadowMemoryRange(page_beg, page_end - 1, nullptr);
+ }
+ }
+}
+
+struct Allocator {
+ static const uptr kMaxAllowedMallocSize = 1ULL << kMaxAllowedMallocBits;
+
+ MemprofAllocator allocator;
+ StaticSpinMutex fallback_mutex;
+ AllocatorCache fallback_allocator_cache;
+
+ uptr max_user_defined_malloc_size;
+
+ // Holds the mapping of stack ids to MemInfoBlocks.
+ MIBMapTy MIBMap;
+
+ atomic_uint8_t destructing;
+ atomic_uint8_t constructed;
+ bool print_text;
+
+ // ------------------- Initialization ------------------------
+ explicit Allocator(LinkerInitialized) : print_text(flags()->print_text) {
+ atomic_store_relaxed(&destructing, 0);
+ atomic_store_relaxed(&constructed, 1);
+ }
+
+ ~Allocator() {
+ atomic_store_relaxed(&destructing, 1);
+ FinishAndWrite();
+ }
+
+ static void PrintCallback(const uptr Key, LockedMemInfoBlock *const &Value,
+ void *Arg) {
+ SpinMutexLock l(&Value->mutex);
+ Print(Value->mib, Key, bool(Arg));
+ }
+
+ void FinishAndWrite() {
+ if (print_text && common_flags()->print_module_map)
+ DumpProcessMap();
+
+ allocator.ForceLock();
+
+ InsertLiveBlocks();
+ if (print_text) {
+ if (!flags()->print_terse)
+ Printf("Recorded MIBs (incl. live on exit):\n");
+ MIBMap.ForEach(PrintCallback,
+ reinterpret_cast<void *>(flags()->print_terse));
+ StackDepotPrintAll();
+ } else {
+ // Serialize the contents to a raw profile. Format documented in
+ // memprof_rawprofile.h.
+ char *Buffer = nullptr;
+
+ MemoryMappingLayout Layout(/*cache_enabled=*/true);
+ u64 BytesSerialized = SerializeToRawProfile(MIBMap, Layout, Buffer);
+ CHECK(Buffer && BytesSerialized && "could not serialize to buffer");
+ report_file.Write(Buffer, BytesSerialized);
+ }
+
+ allocator.ForceUnlock();
+ }
+
+ // Inserts any blocks which have been allocated but not yet deallocated.
+ void InsertLiveBlocks() {
+ allocator.ForEachChunk(
+ [](uptr chunk, void *alloc) {
+ u64 user_requested_size;
+ Allocator *A = (Allocator *)alloc;
+ MemprofChunk *m =
+ A->GetMemprofChunk((void *)chunk, user_requested_size);
+ if (!m)
+ return;
+ uptr user_beg = ((uptr)m) + kChunkHeaderSize;
+ u64 c = GetShadowCount(user_beg, user_requested_size);
+ long curtime = GetTimestamp();
+ MemInfoBlock newMIB(user_requested_size, c, m->timestamp_ms, curtime,
+ m->cpu_id, GetCpuId());
+ InsertOrMerge(m->alloc_context_id, newMIB, A->MIBMap);
+ },
+ this);
+ }
+
+ void InitLinkerInitialized() {
+ SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null);
+ allocator.InitLinkerInitialized(
+ common_flags()->allocator_release_to_os_interval_ms);
+ max_user_defined_malloc_size = common_flags()->max_allocation_size_mb
+ ? common_flags()->max_allocation_size_mb
+ << 20
+ : kMaxAllowedMallocSize;
+ }
+
+ // -------------------- Allocation/Deallocation routines ---------------
+ void *Allocate(uptr size, uptr alignment, BufferedStackTrace *stack,
+ AllocType alloc_type) {
+ if (UNLIKELY(!memprof_inited))
+ MemprofInitFromRtl();
+ if (UNLIKELY(IsRssLimitExceeded())) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportRssLimitExceeded(stack);
+ }
+ CHECK(stack);
+ const uptr min_alignment = MEMPROF_ALIGNMENT;
+ if (alignment < min_alignment)
+ alignment = min_alignment;
+ if (size == 0) {
+ // We'd be happy to avoid allocating memory for zero-size requests, but
+ // some programs/tests depend on this behavior and assume that malloc
+ // would not return NULL even for zero-size allocations. Moreover, it
+ // looks like operator new should never return NULL, and results of
+ // consecutive "new" calls must be different even if the allocated size
+ // is zero.
+ size = 1;
+ }
+ CHECK(IsPowerOfTwo(alignment));
+ uptr rounded_size = RoundUpTo(size, alignment);
+ uptr needed_size = rounded_size + kChunkHeaderSize;
+ if (alignment > min_alignment)
+ needed_size += alignment;
+ CHECK(IsAligned(needed_size, min_alignment));
+ if (size > kMaxAllowedMallocSize || needed_size > kMaxAllowedMallocSize ||
+ size > max_user_defined_malloc_size) {
+ if (AllocatorMayReturnNull()) {
+ Report("WARNING: MemProfiler failed to allocate 0x%zx bytes\n", size);
+ return nullptr;
+ }
+ uptr malloc_limit =
+ Min(kMaxAllowedMallocSize, max_user_defined_malloc_size);
+ ReportAllocationSizeTooBig(size, malloc_limit, stack);
+ }
+
+ MemprofThread *t = GetCurrentThread();
+ void *allocated;
+ if (t) {
+ AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
+ allocated = allocator.Allocate(cache, needed_size, 8);
+ } else {
+ SpinMutexLock l(&fallback_mutex);
+ AllocatorCache *cache = &fallback_allocator_cache;
+ allocated = allocator.Allocate(cache, needed_size, 8);
+ }
+ if (UNLIKELY(!allocated)) {
+ SetAllocatorOutOfMemory();
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportOutOfMemory(size, stack);
+ }
+
+ uptr alloc_beg = reinterpret_cast<uptr>(allocated);
+ uptr alloc_end = alloc_beg + needed_size;
+ uptr beg_plus_header = alloc_beg + kChunkHeaderSize;
+ uptr user_beg = beg_plus_header;
+ if (!IsAligned(user_beg, alignment))
+ user_beg = RoundUpTo(user_beg, alignment);
+ uptr user_end = user_beg + size;
+ CHECK_LE(user_end, alloc_end);
+ uptr chunk_beg = user_beg - kChunkHeaderSize;
+ MemprofChunk *m = reinterpret_cast<MemprofChunk *>(chunk_beg);
+ m->from_memalign = alloc_beg != chunk_beg;
+ CHECK(size);
+
+ m->cpu_id = GetCpuId();
+ m->timestamp_ms = GetTimestamp();
+ m->alloc_context_id = StackDepotPut(*stack);
+
+ uptr size_rounded_down_to_granularity =
+ RoundDownTo(size, SHADOW_GRANULARITY);
+ if (size_rounded_down_to_granularity)
+ ClearShadow(user_beg, size_rounded_down_to_granularity);
+
+ MemprofStats &thread_stats = GetCurrentThreadStats();
+ thread_stats.mallocs++;
+ thread_stats.malloced += size;
+ thread_stats.malloced_overhead += needed_size - size;
+ if (needed_size > SizeClassMap::kMaxSize)
+ thread_stats.malloc_large++;
+ else
+ thread_stats.malloced_by_size[SizeClassMap::ClassID(needed_size)]++;
+
+ void *res = reinterpret_cast<void *>(user_beg);
+ atomic_store(&m->user_requested_size, size, memory_order_release);
+ if (alloc_beg != chunk_beg) {
+ CHECK_LE(alloc_beg + sizeof(LargeChunkHeader), chunk_beg);
+ reinterpret_cast<LargeChunkHeader *>(alloc_beg)->Set(m);
+ }
+ RunMallocHooks(res, size);
+ return res;
+ }
+
+ void Deallocate(void *ptr, uptr delete_size, uptr delete_alignment,
+ BufferedStackTrace *stack, AllocType alloc_type) {
+ uptr p = reinterpret_cast<uptr>(ptr);
+ if (p == 0)
+ return;
+
+ RunFreeHooks(ptr);
+
+ uptr chunk_beg = p - kChunkHeaderSize;
+ MemprofChunk *m = reinterpret_cast<MemprofChunk *>(chunk_beg);
+
+ u64 user_requested_size =
+ atomic_exchange(&m->user_requested_size, 0, memory_order_acquire);
+ if (memprof_inited && memprof_init_done &&
+ atomic_load_relaxed(&constructed) &&
+ !atomic_load_relaxed(&destructing)) {
+ u64 c = GetShadowCount(p, user_requested_size);
+ long curtime = GetTimestamp();
+
+ MemInfoBlock newMIB(user_requested_size, c, m->timestamp_ms, curtime,
+ m->cpu_id, GetCpuId());
+ InsertOrMerge(m->alloc_context_id, newMIB, MIBMap);
+ }
+
+ MemprofStats &thread_stats = GetCurrentThreadStats();
+ thread_stats.frees++;
+ thread_stats.freed += user_requested_size;
+
+ void *alloc_beg = m->AllocBeg();
+ if (alloc_beg != m) {
+ // Clear the magic value, as allocator internals may overwrite the
+ // contents of deallocated chunk, confusing GetMemprofChunk lookup.
+ reinterpret_cast<LargeChunkHeader *>(alloc_beg)->Set(nullptr);
+ }
+
+ MemprofThread *t = GetCurrentThread();
+ if (t) {
+ AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
+ allocator.Deallocate(cache, alloc_beg);
+ } else {
+ SpinMutexLock l(&fallback_mutex);
+ AllocatorCache *cache = &fallback_allocator_cache;
+ allocator.Deallocate(cache, alloc_beg);
+ }
+ }
+
+ void *Reallocate(void *old_ptr, uptr new_size, BufferedStackTrace *stack) {
+ CHECK(old_ptr && new_size);
+ uptr p = reinterpret_cast<uptr>(old_ptr);
+ uptr chunk_beg = p - kChunkHeaderSize;
+ MemprofChunk *m = reinterpret_cast<MemprofChunk *>(chunk_beg);
+
+ MemprofStats &thread_stats = GetCurrentThreadStats();
+ thread_stats.reallocs++;
+ thread_stats.realloced += new_size;
+
+ void *new_ptr = Allocate(new_size, 8, stack, FROM_MALLOC);
+ if (new_ptr) {
+ CHECK_NE(REAL(memcpy), nullptr);
+ uptr memcpy_size = Min(new_size, m->UsedSize());
+ REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
+ Deallocate(old_ptr, 0, 0, stack, FROM_MALLOC);
+ }
+ return new_ptr;
+ }
+
+ void *Calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) {
+ if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportCallocOverflow(nmemb, size, stack);
+ }
+ void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC);
+ // If the memory comes from the secondary allocator no need to clear it
+ // as it comes directly from mmap.
+ if (ptr && allocator.FromPrimary(ptr))
+ REAL(memset)(ptr, 0, nmemb * size);
+ return ptr;
+ }
+
+ void CommitBack(MemprofThreadLocalMallocStorage *ms,
+ BufferedStackTrace *stack) {
+ AllocatorCache *ac = GetAllocatorCache(ms);
+ allocator.SwallowCache(ac);
+ }
+
+ // -------------------------- Chunk lookup ----------------------
+
+ // Assumes alloc_beg == allocator.GetBlockBegin(alloc_beg).
+ MemprofChunk *GetMemprofChunk(void *alloc_beg, u64 &user_requested_size) {
+ if (!alloc_beg)
+ return nullptr;
+ MemprofChunk *p = reinterpret_cast<LargeChunkHeader *>(alloc_beg)->Get();
+ if (!p) {
+ if (!allocator.FromPrimary(alloc_beg))
+ return nullptr;
+ p = reinterpret_cast<MemprofChunk *>(alloc_beg);
+ }
+ // The size is reset to 0 on deallocation (and a min of 1 on
+ // allocation).
+ user_requested_size =
+ atomic_load(&p->user_requested_size, memory_order_acquire);
+ if (user_requested_size)
+ return p;
+ return nullptr;
+ }
+
+ MemprofChunk *GetMemprofChunkByAddr(uptr p, u64 &user_requested_size) {
+ void *alloc_beg = allocator.GetBlockBegin(reinterpret_cast<void *>(p));
+ return GetMemprofChunk(alloc_beg, user_requested_size);
+ }
+
+ uptr AllocationSize(uptr p) {
+ u64 user_requested_size;
+ MemprofChunk *m = GetMemprofChunkByAddr(p, user_requested_size);
+ if (!m)
+ return 0;
+ if (m->Beg() != p)
+ return 0;
+ return user_requested_size;
+ }
+
+ void Purge(BufferedStackTrace *stack) { allocator.ForceReleaseToOS(); }
+
+ void PrintStats() { allocator.PrintStats(); }
+
+ void ForceLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ allocator.ForceLock();
+ fallback_mutex.Lock();
+ }
+
+ void ForceUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ fallback_mutex.Unlock();
+ allocator.ForceUnlock();
+ }
+};
+
+static Allocator instance(LINKER_INITIALIZED);
+
+static MemprofAllocator &get_allocator() { return instance.allocator; }
+
+void InitializeAllocator() { instance.InitLinkerInitialized(); }
+
+void MemprofThreadLocalMallocStorage::CommitBack() {
+ GET_STACK_TRACE_MALLOC;
+ instance.CommitBack(this, &stack);
+}
+
+void PrintInternalAllocatorStats() { instance.PrintStats(); }
+
+void memprof_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type) {
+ instance.Deallocate(ptr, 0, 0, stack, alloc_type);
+}
+
+void memprof_delete(void *ptr, uptr size, uptr alignment,
+ BufferedStackTrace *stack, AllocType alloc_type) {
+ instance.Deallocate(ptr, size, alignment, stack, alloc_type);
+}
+
+void *memprof_malloc(uptr size, BufferedStackTrace *stack) {
+ return SetErrnoOnNull(instance.Allocate(size, 8, stack, FROM_MALLOC));
+}
+
+void *memprof_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) {
+ return SetErrnoOnNull(instance.Calloc(nmemb, size, stack));
+}
+
+void *memprof_reallocarray(void *p, uptr nmemb, uptr size,
+ BufferedStackTrace *stack) {
+ if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+ errno = errno_ENOMEM;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportReallocArrayOverflow(nmemb, size, stack);
+ }
+ return memprof_realloc(p, nmemb * size, stack);
+}
+
+void *memprof_realloc(void *p, uptr size, BufferedStackTrace *stack) {
+ if (!p)
+ return SetErrnoOnNull(instance.Allocate(size, 8, stack, FROM_MALLOC));
+ if (size == 0) {
+ if (flags()->allocator_frees_and_returns_null_on_realloc_zero) {
+ instance.Deallocate(p, 0, 0, stack, FROM_MALLOC);
+ return nullptr;
+ }
+ // Allocate a size of 1 if we shouldn't free() on Realloc to 0
+ size = 1;
+ }
+ return SetErrnoOnNull(instance.Reallocate(p, size, stack));
+}
+
+void *memprof_valloc(uptr size, BufferedStackTrace *stack) {
+ return SetErrnoOnNull(
+ instance.Allocate(size, GetPageSizeCached(), stack, FROM_MALLOC));
+}
+
+void *memprof_pvalloc(uptr size, BufferedStackTrace *stack) {
+ uptr PageSize = GetPageSizeCached();
+ if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) {
+ errno = errno_ENOMEM;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportPvallocOverflow(size, stack);
+ }
+ // pvalloc(0) should allocate one page.
+ size = size ? RoundUpTo(size, PageSize) : PageSize;
+ return SetErrnoOnNull(instance.Allocate(size, PageSize, stack, FROM_MALLOC));
+}
+
+void *memprof_memalign(uptr alignment, uptr size, BufferedStackTrace *stack,
+ AllocType alloc_type) {
+ if (UNLIKELY(!IsPowerOfTwo(alignment))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAllocationAlignment(alignment, stack);
+ }
+ return SetErrnoOnNull(instance.Allocate(size, alignment, stack, alloc_type));
+}
+
+void *memprof_aligned_alloc(uptr alignment, uptr size,
+ BufferedStackTrace *stack) {
+ if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAlignedAllocAlignment(size, alignment, stack);
+ }
+ return SetErrnoOnNull(instance.Allocate(size, alignment, stack, FROM_MALLOC));
+}
+
+int memprof_posix_memalign(void **memptr, uptr alignment, uptr size,
+ BufferedStackTrace *stack) {
+ if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
+ if (AllocatorMayReturnNull())
+ return errno_EINVAL;
+ ReportInvalidPosixMemalignAlignment(alignment, stack);
+ }
+ void *ptr = instance.Allocate(size, alignment, stack, FROM_MALLOC);
+ if (UNLIKELY(!ptr))
+ // OOM error is already taken care of by Allocate.
+ return errno_ENOMEM;
+ CHECK(IsAligned((uptr)ptr, alignment));
+ *memptr = ptr;
+ return 0;
+}
+
+uptr memprof_malloc_usable_size(const void *ptr, uptr pc, uptr bp) {
+ if (!ptr)
+ return 0;
+ uptr usable_size = instance.AllocationSize(reinterpret_cast<uptr>(ptr));
+ return usable_size;
+}
+
+} // namespace __memprof
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __memprof;
+
+uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; }
+
+int __sanitizer_get_ownership(const void *p) {
+ return memprof_malloc_usable_size(p, 0, 0) != 0;
+}
+
+uptr __sanitizer_get_allocated_size(const void *p) {
+ return memprof_malloc_usable_size(p, 0, 0);
+}
+
+int __memprof_profile_dump() {
+ instance.FinishAndWrite();
+ // In the future we may want to return non-zero if there are any errors
+ // detected during the dumping process.
+ return 0;
+}
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_allocator.h b/contrib/libs/clang16-rt/lib/memprof/memprof_allocator.h
new file mode 100644
index 00000000000..001502cde08
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_allocator.h
@@ -0,0 +1,103 @@
+//===-- memprof_allocator.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// MemProf-private header for memprof_allocator.cpp.
+//===----------------------------------------------------------------------===//
+
+#ifndef MEMPROF_ALLOCATOR_H
+#define MEMPROF_ALLOCATOR_H
+
+#include "memprof_flags.h"
+#include "memprof_interceptors.h"
+#include "memprof_internal.h"
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_list.h"
+
+#if !defined(__x86_64__)
+#error Unsupported platform
+#endif
+#if !SANITIZER_CAN_USE_ALLOCATOR64
+#error Only 64-bit allocator supported
+#endif
+
+namespace __memprof {
+
+enum AllocType {
+ FROM_MALLOC = 1, // Memory block came from malloc, calloc, realloc, etc.
+ FROM_NEW = 2, // Memory block came from operator new.
+ FROM_NEW_BR = 3 // Memory block came from operator new [ ]
+};
+
+void InitializeAllocator();
+
+struct MemprofMapUnmapCallback {
+ void OnMap(uptr p, uptr size) const;
+ void OnUnmap(uptr p, uptr size) const;
+};
+
+constexpr uptr kAllocatorSpace = 0x600000000000ULL;
+constexpr uptr kAllocatorSize = 0x40000000000ULL; // 4T.
+typedef DefaultSizeClassMap SizeClassMap;
+template <typename AddressSpaceViewTy>
+struct AP64 { // Allocator64 parameters. Deliberately using a short name.
+ static const uptr kSpaceBeg = kAllocatorSpace;
+ static const uptr kSpaceSize = kAllocatorSize;
+ static const uptr kMetadataSize = 0;
+ typedef __memprof::SizeClassMap SizeClassMap;
+ typedef MemprofMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+ using AddressSpaceView = AddressSpaceViewTy;
+};
+
+template <typename AddressSpaceView>
+using PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>;
+using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
+
+static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses;
+
+template <typename AddressSpaceView>
+using MemprofAllocatorASVT =
+ CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>>;
+using MemprofAllocator = MemprofAllocatorASVT<LocalAddressSpaceView>;
+using AllocatorCache = MemprofAllocator::AllocatorCache;
+
+struct MemprofThreadLocalMallocStorage {
+ AllocatorCache allocator_cache;
+ void CommitBack();
+
+private:
+ // These objects are allocated via mmap() and are zero-initialized.
+ MemprofThreadLocalMallocStorage() {}
+};
+
+void *memprof_memalign(uptr alignment, uptr size, BufferedStackTrace *stack,
+ AllocType alloc_type);
+void memprof_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type);
+void memprof_delete(void *ptr, uptr size, uptr alignment,
+ BufferedStackTrace *stack, AllocType alloc_type);
+
+void *memprof_malloc(uptr size, BufferedStackTrace *stack);
+void *memprof_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack);
+void *memprof_realloc(void *p, uptr size, BufferedStackTrace *stack);
+void *memprof_reallocarray(void *p, uptr nmemb, uptr size,
+ BufferedStackTrace *stack);
+void *memprof_valloc(uptr size, BufferedStackTrace *stack);
+void *memprof_pvalloc(uptr size, BufferedStackTrace *stack);
+
+void *memprof_aligned_alloc(uptr alignment, uptr size,
+ BufferedStackTrace *stack);
+int memprof_posix_memalign(void **memptr, uptr alignment, uptr size,
+ BufferedStackTrace *stack);
+uptr memprof_malloc_usable_size(const void *ptr, uptr pc, uptr bp);
+
+void PrintInternalAllocatorStats();
+
+} // namespace __memprof
+#endif // MEMPROF_ALLOCATOR_H
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_descriptions.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_descriptions.cpp
new file mode 100644
index 00000000000..669b1acd8c7
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_descriptions.cpp
@@ -0,0 +1,70 @@
+//===-- memprof_descriptions.cpp -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// MemProf functions for getting information about an address and/or printing
+// it.
+//===----------------------------------------------------------------------===//
+
+#include "memprof_descriptions.h"
+#include "memprof_mapping.h"
+#include "memprof_stack.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+namespace __memprof {
+
+MemprofThreadIdAndName::MemprofThreadIdAndName(MemprofThreadContext *t) {
+ Init(t->tid, t->name);
+}
+
+MemprofThreadIdAndName::MemprofThreadIdAndName(u32 tid) {
+ if (tid == kInvalidTid) {
+ Init(tid, "");
+ } else {
+ memprofThreadRegistry().CheckLocked();
+ MemprofThreadContext *t = GetThreadContextByTidLocked(tid);
+ Init(tid, t->name);
+ }
+}
+
+void MemprofThreadIdAndName::Init(u32 tid, const char *tname) {
+ int len = internal_snprintf(name, sizeof(name), "T%d", tid);
+ CHECK(((unsigned int)len) < sizeof(name));
+ if (tname[0] != '\0')
+ internal_snprintf(&name[len], sizeof(name) - len, " (%s)", tname);
+}
+
+void DescribeThread(MemprofThreadContext *context) {
+ CHECK(context);
+ memprofThreadRegistry().CheckLocked();
+ // No need to announce the main thread.
+ if (context->tid == kMainTid || context->announced) {
+ return;
+ }
+ context->announced = true;
+ InternalScopedString str;
+ str.append("Thread %s", MemprofThreadIdAndName(context).c_str());
+ if (context->parent_tid == kInvalidTid) {
+ str.append(" created by unknown thread\n");
+ Printf("%s", str.data());
+ return;
+ }
+ str.append(" created by %s here:\n",
+ MemprofThreadIdAndName(context->parent_tid).c_str());
+ Printf("%s", str.data());
+ StackDepotGet(context->stack_id).Print();
+ // Recursively described parent thread if needed.
+ if (flags()->print_full_thread_history) {
+ MemprofThreadContext *parent_context =
+ GetThreadContextByTidLocked(context->parent_tid);
+ DescribeThread(parent_context);
+ }
+}
+
+} // namespace __memprof
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_descriptions.h b/contrib/libs/clang16-rt/lib/memprof/memprof_descriptions.h
new file mode 100644
index 00000000000..e88ea441bf9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_descriptions.h
@@ -0,0 +1,45 @@
+//===-- memprof_descriptions.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// MemProf-private header for memprof_descriptions.cpp.
+//===----------------------------------------------------------------------===//
+#ifndef MEMPROF_DESCRIPTIONS_H
+#define MEMPROF_DESCRIPTIONS_H
+
+#include "memprof_allocator.h"
+#include "memprof_thread.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
+
+namespace __memprof {
+
+void DescribeThread(MemprofThreadContext *context);
+inline void DescribeThread(MemprofThread *t) {
+ if (t)
+ DescribeThread(t->context());
+}
+
+class MemprofThreadIdAndName {
+public:
+ explicit MemprofThreadIdAndName(MemprofThreadContext *t);
+ explicit MemprofThreadIdAndName(u32 tid);
+
+ // Contains "T%tid (%name)" or "T%tid" if the name is empty.
+ const char *c_str() const { return &name[0]; }
+
+private:
+ void Init(u32 tid, const char *tname);
+
+ char name[128];
+};
+
+} // namespace __memprof
+
+#endif // MEMPROF_DESCRIPTIONS_H
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_flags.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_flags.cpp
new file mode 100644
index 00000000000..b107ff8fa0a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_flags.cpp
@@ -0,0 +1,93 @@
+//===-- memprof_flags.cpp --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// MemProf flag parsing logic.
+//===----------------------------------------------------------------------===//
+
+#include "memprof_flags.h"
+#include "memprof_interface_internal.h"
+#include "memprof_stack.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
+
+namespace __memprof {
+
+Flags memprof_flags_dont_use_directly; // use via flags().
+
+static const char *MaybeUseMemprofDefaultOptionsCompileDefinition() {
+#ifdef MEMPROF_DEFAULT_OPTIONS
+ return SANITIZER_STRINGIFY(MEMPROF_DEFAULT_OPTIONS);
+#else
+ return "";
+#endif
+}
+
+void Flags::SetDefaults() {
+#define MEMPROF_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "memprof_flags.inc"
+#undef MEMPROF_FLAG
+}
+
+static void RegisterMemprofFlags(FlagParser *parser, Flags *f) {
+#define MEMPROF_FLAG(Type, Name, DefaultValue, Description) \
+ RegisterFlag(parser, #Name, Description, &f->Name);
+#include "memprof_flags.inc"
+#undef MEMPROF_FLAG
+}
+
+void InitializeFlags() {
+ // Set the default values and prepare for parsing MemProf and common flags.
+ SetCommonFlagsDefaults();
+ {
+ CommonFlags cf;
+ cf.CopyFrom(*common_flags());
+ cf.external_symbolizer_path = GetEnv("MEMPROF_SYMBOLIZER_PATH");
+ cf.malloc_context_size = kDefaultMallocContextSize;
+ cf.intercept_tls_get_addr = true;
+ cf.exitcode = 1;
+ OverrideCommonFlags(cf);
+ }
+ Flags *f = flags();
+ f->SetDefaults();
+
+ FlagParser memprof_parser;
+ RegisterMemprofFlags(&memprof_parser, f);
+ RegisterCommonFlags(&memprof_parser);
+
+ // Override from MemProf compile definition.
+ const char *memprof_compile_def =
+ MaybeUseMemprofDefaultOptionsCompileDefinition();
+ memprof_parser.ParseString(memprof_compile_def);
+
+ // Override from user-specified string.
+ const char *memprof_default_options = __memprof_default_options();
+ memprof_parser.ParseString(memprof_default_options);
+
+ // Override from command line.
+ memprof_parser.ParseStringFromEnv("MEMPROF_OPTIONS");
+
+ InitializeCommonFlags();
+
+ if (Verbosity())
+ ReportUnrecognizedFlags();
+
+ if (common_flags()->help) {
+ memprof_parser.PrintFlagDescriptions();
+ }
+
+ CHECK_LE((uptr)common_flags()->malloc_context_size, kStackTraceMax);
+}
+
+} // namespace __memprof
+
+SANITIZER_INTERFACE_WEAK_DEF(const char *, __memprof_default_options, void) {
+ return "";
+}
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_flags.h b/contrib/libs/clang16-rt/lib/memprof/memprof_flags.h
new file mode 100644
index 00000000000..2f2b628653d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_flags.h
@@ -0,0 +1,45 @@
+//===-- memprof_flags.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// MemProf runtime flags.
+//===----------------------------------------------------------------------===//
+
+#ifndef MEMPROF_FLAGS_H
+#define MEMPROF_FLAGS_H
+
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+// MemProf flag values can be defined in four ways:
+// 1) initialized with default values at startup.
+// 2) overriden during compilation of MemProf runtime by providing
+// compile definition MEMPROF_DEFAULT_OPTIONS.
+// 3) overriden from string returned by user-specified function
+// __memprof_default_options().
+// 4) overriden from env variable MEMPROF_OPTIONS.
+
+namespace __memprof {
+
+struct Flags {
+#define MEMPROF_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "memprof_flags.inc"
+#undef MEMPROF_FLAG
+
+ void SetDefaults();
+};
+
+extern Flags memprof_flags_dont_use_directly;
+inline Flags *flags() { return &memprof_flags_dont_use_directly; }
+
+void InitializeFlags();
+
+} // namespace __memprof
+
+#endif // MEMPROF_FLAGS_H
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_flags.inc b/contrib/libs/clang16-rt/lib/memprof/memprof_flags.inc
new file mode 100644
index 00000000000..ee0760ddc30
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_flags.inc
@@ -0,0 +1,41 @@
+//===-- memprof_flags.inc --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// MemProf runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MEMPROF_FLAG
+#error "Define MEMPROF_FLAG prior to including this file!"
+#endif
+
+// MEMPROF_FLAG(Type, Name, DefaultValue, Description)
+// See COMMON_FLAG in sanitizer_flags.inc for more details.
+
+MEMPROF_FLAG(bool, unmap_shadow_on_exit, false,
+ "If set, explicitly unmaps the (huge) shadow at exit.")
+MEMPROF_FLAG(bool, protect_shadow_gap, true, "If set, mprotect the shadow gap")
+MEMPROF_FLAG(bool, print_legend, true, "Print the legend for the shadow bytes.")
+MEMPROF_FLAG(bool, atexit, false,
+ "If set, prints MemProf exit stats even after program terminates "
+ "successfully.")
+MEMPROF_FLAG(
+ bool, print_full_thread_history, true,
+ "If set, prints thread creation stacks for the threads involved in the "
+ "report and their ancestors up to the main thread.")
+
+MEMPROF_FLAG(bool, halt_on_error, true,
+ "Crash the program after printing the first error report "
+ "(WARNING: USE AT YOUR OWN RISK!)")
+MEMPROF_FLAG(bool, allocator_frees_and_returns_null_on_realloc_zero, true,
+ "realloc(p, 0) is equivalent to free(p) by default (Same as the "
+ "POSIX standard). If set to false, realloc(p, 0) will return a "
+ "pointer to an allocated space which can not be used.")
+MEMPROF_FLAG(bool, print_text, false,
+ "If set, prints the heap profile in text format. Else use the raw binary serialization format.")
+MEMPROF_FLAG(bool, print_terse, false,
+ "If set, prints memory profile in a terse format. Only applicable if print_text = true.")
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_init_version.h b/contrib/libs/clang16-rt/lib/memprof/memprof_init_version.h
new file mode 100644
index 00000000000..26c68f78677
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_init_version.h
@@ -0,0 +1,26 @@
+//===-- memprof_init_version.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// This header defines a versioned __memprof_init function to be called at the
+// startup of the instrumented program.
+//===----------------------------------------------------------------------===//
+#ifndef MEMPROF_INIT_VERSION_H
+#define MEMPROF_INIT_VERSION_H
+
+#include "sanitizer_common/sanitizer_platform.h"
+
+extern "C" {
+// Every time the Memprof ABI changes we also change the version number in the
+// __memprof_init function name. Objects built with incompatible Memprof ABI
+// versions will not link with run-time.
+#define __memprof_version_mismatch_check __memprof_version_mismatch_check_v1
+}
+
+#endif // MEMPROF_INIT_VERSION_H
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_interceptors.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_interceptors.cpp
new file mode 100644
index 00000000000..459ad03e8df
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_interceptors.cpp
@@ -0,0 +1,364 @@
+//===-- memprof_interceptors.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// Intercept various libc functions.
+//===----------------------------------------------------------------------===//
+
+#include "memprof_interceptors.h"
+#include "memprof_allocator.h"
+#include "memprof_internal.h"
+#include "memprof_mapping.h"
+#include "memprof_stack.h"
+#include "memprof_stats.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_posix.h"
+
+namespace __memprof {
+
+#define MEMPROF_READ_STRING(s, n) MEMPROF_READ_RANGE((s), (n))
+
+static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
+#if SANITIZER_INTERCEPT_STRNLEN
+ if (REAL(strnlen)) {
+ return REAL(strnlen)(s, maxlen);
+ }
+#endif
+ return internal_strnlen(s, maxlen);
+}
+
+void SetThreadName(const char *name) {
+ MemprofThread *t = GetCurrentThread();
+ if (t)
+ memprofThreadRegistry().SetThreadName(t->tid(), name);
+}
+
+int OnExit() {
+ // FIXME: ask frontend whether we need to return failure.
+ return 0;
+}
+
+} // namespace __memprof
+
+// ---------------------- Wrappers ---------------- {{{1
+using namespace __memprof;
+
+DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
+DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
+
+#define MEMPROF_INTERCEPTOR_ENTER(ctx, func) \
+ ctx = 0; \
+ (void)ctx;
+
+#define COMMON_INTERCEPT_FUNCTION(name) MEMPROF_INTERCEPT_FUNC(name)
+#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
+ MEMPROF_INTERCEPT_FUNC_VER(name, ver)
+#define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
+ MEMPROF_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
+#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
+ MEMPROF_WRITE_RANGE(ptr, size)
+#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
+ MEMPROF_READ_RANGE(ptr, size)
+#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
+ MEMPROF_INTERCEPTOR_ENTER(ctx, func); \
+ do { \
+ if (memprof_init_is_running) \
+ return REAL(func)(__VA_ARGS__); \
+ ENSURE_MEMPROF_INITED(); \
+ } while (false)
+#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
+// Should be memprofThreadRegistry().SetThreadNameByUserId(thread, name)
+// But memprof does not remember UserId's for threads (pthread_t);
+// and remembers all ever existed threads, so the linear search by UserId
+// can be slow.
+#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
+#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
+#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
+#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
+#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!memprof_inited)
+#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
+ if (MemprofThread *t = GetCurrentThread()) { \
+ *begin = t->tls_begin(); \
+ *end = t->tls_end(); \
+ } else { \
+ *begin = *end = 0; \
+ }
+
+#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
+ do { \
+ MEMPROF_INTERCEPTOR_ENTER(ctx, memmove); \
+ MEMPROF_MEMMOVE_IMPL(to, from, size); \
+ } while (false)
+
+#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
+ do { \
+ MEMPROF_INTERCEPTOR_ENTER(ctx, memcpy); \
+ MEMPROF_MEMCPY_IMPL(to, from, size); \
+ } while (false)
+
+#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
+ do { \
+ MEMPROF_INTERCEPTOR_ENTER(ctx, memset); \
+ MEMPROF_MEMSET_IMPL(block, c, size); \
+ } while (false)
+
+#include "sanitizer_common/sanitizer_common_interceptors.inc"
+
+#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) MEMPROF_READ_RANGE(p, s)
+#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) MEMPROF_WRITE_RANGE(p, s)
+#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
+ do { \
+ (void)(p); \
+ (void)(s); \
+ } while (false)
+#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
+ do { \
+ (void)(p); \
+ (void)(s); \
+ } while (false)
+#include "sanitizer_common/sanitizer_common_syscalls.inc"
+
+struct ThreadStartParam {
+ atomic_uintptr_t t;
+ atomic_uintptr_t is_registered;
+};
+
+static thread_return_t THREAD_CALLING_CONV memprof_thread_start(void *arg) {
+ ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
+ MemprofThread *t = nullptr;
+ while ((t = reinterpret_cast<MemprofThread *>(
+ atomic_load(&param->t, memory_order_acquire))) == nullptr)
+ internal_sched_yield();
+ SetCurrentThread(t);
+ return t->ThreadStart(GetTid(), &param->is_registered);
+}
+
+INTERCEPTOR(int, pthread_create, void *thread, void *attr,
+ void *(*start_routine)(void *), void *arg) {
+ EnsureMainThreadIDIsCorrect();
+ GET_STACK_TRACE_THREAD;
+ int detached = 0;
+ if (attr)
+ REAL(pthread_attr_getdetachstate)(attr, &detached);
+ ThreadStartParam param;
+ atomic_store(&param.t, 0, memory_order_relaxed);
+ atomic_store(&param.is_registered, 0, memory_order_relaxed);
+ int result;
+ {
+ // Ignore all allocations made by pthread_create: thread stack/TLS may be
+ // stored by pthread for future reuse even after thread destruction, and
+ // the linked list it's stored in doesn't even hold valid pointers to the
+ // objects, the latter are calculated by obscure pointer arithmetic.
+ result = REAL(pthread_create)(thread, attr, memprof_thread_start, &param);
+ }
+ if (result == 0) {
+ u32 current_tid = GetCurrentTidOrInvalid();
+ MemprofThread *t = MemprofThread::Create(start_routine, arg, current_tid,
+ &stack, detached);
+ atomic_store(&param.t, reinterpret_cast<uptr>(t), memory_order_release);
+ // Wait until the MemprofThread object is initialized and the
+ // ThreadRegistry entry is in "started" state.
+ while (atomic_load(&param.is_registered, memory_order_acquire) == 0)
+ internal_sched_yield();
+ }
+ return result;
+}
+
+INTERCEPTOR(int, pthread_join, void *t, void **arg) {
+ return real_pthread_join(t, arg);
+}
+
+DEFINE_REAL_PTHREAD_FUNCTIONS
+
+INTERCEPTOR(char *, index, const char *string, int c)
+ALIAS(WRAPPER_NAME(strchr));
+
+// For both strcat() and strncat() we need to check the validity of |to|
+// argument irrespective of the |from| length.
+INTERCEPTOR(char *, strcat, char *to, const char *from) {
+ void *ctx;
+ MEMPROF_INTERCEPTOR_ENTER(ctx, strcat);
+ ENSURE_MEMPROF_INITED();
+ uptr from_length = internal_strlen(from);
+ MEMPROF_READ_RANGE(from, from_length + 1);
+ uptr to_length = internal_strlen(to);
+ MEMPROF_READ_STRING(to, to_length);
+ MEMPROF_WRITE_RANGE(to + to_length, from_length + 1);
+ return REAL(strcat)(to, from);
+}
+
+INTERCEPTOR(char *, strncat, char *to, const char *from, uptr size) {
+ void *ctx;
+ MEMPROF_INTERCEPTOR_ENTER(ctx, strncat);
+ ENSURE_MEMPROF_INITED();
+ uptr from_length = MaybeRealStrnlen(from, size);
+ uptr copy_length = Min(size, from_length + 1);
+ MEMPROF_READ_RANGE(from, copy_length);
+ uptr to_length = internal_strlen(to);
+ MEMPROF_READ_STRING(to, to_length);
+ MEMPROF_WRITE_RANGE(to + to_length, from_length + 1);
+ return REAL(strncat)(to, from, size);
+}
+
+INTERCEPTOR(char *, strcpy, char *to, const char *from) {
+ void *ctx;
+ MEMPROF_INTERCEPTOR_ENTER(ctx, strcpy);
+ if (memprof_init_is_running) {
+ return REAL(strcpy)(to, from);
+ }
+ ENSURE_MEMPROF_INITED();
+ uptr from_size = internal_strlen(from) + 1;
+ MEMPROF_READ_RANGE(from, from_size);
+ MEMPROF_WRITE_RANGE(to, from_size);
+ return REAL(strcpy)(to, from);
+}
+
+INTERCEPTOR(char *, strdup, const char *s) {
+ void *ctx;
+ MEMPROF_INTERCEPTOR_ENTER(ctx, strdup);
+ if (UNLIKELY(!memprof_inited))
+ return internal_strdup(s);
+ ENSURE_MEMPROF_INITED();
+ uptr length = internal_strlen(s);
+ MEMPROF_READ_RANGE(s, length + 1);
+ GET_STACK_TRACE_MALLOC;
+ void *new_mem = memprof_malloc(length + 1, &stack);
+ REAL(memcpy)(new_mem, s, length + 1);
+ return reinterpret_cast<char *>(new_mem);
+}
+
+INTERCEPTOR(char *, __strdup, const char *s) {
+ void *ctx;
+ MEMPROF_INTERCEPTOR_ENTER(ctx, strdup);
+ if (UNLIKELY(!memprof_inited))
+ return internal_strdup(s);
+ ENSURE_MEMPROF_INITED();
+ uptr length = internal_strlen(s);
+ MEMPROF_READ_RANGE(s, length + 1);
+ GET_STACK_TRACE_MALLOC;
+ void *new_mem = memprof_malloc(length + 1, &stack);
+ REAL(memcpy)(new_mem, s, length + 1);
+ return reinterpret_cast<char *>(new_mem);
+}
+
+INTERCEPTOR(char *, strncpy, char *to, const char *from, uptr size) {
+ void *ctx;
+ MEMPROF_INTERCEPTOR_ENTER(ctx, strncpy);
+ ENSURE_MEMPROF_INITED();
+ uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
+ MEMPROF_READ_RANGE(from, from_size);
+ MEMPROF_WRITE_RANGE(to, size);
+ return REAL(strncpy)(to, from, size);
+}
+
+INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) {
+ void *ctx;
+ MEMPROF_INTERCEPTOR_ENTER(ctx, strtol);
+ ENSURE_MEMPROF_INITED();
+ char *real_endptr;
+ long result = REAL(strtol)(nptr, &real_endptr, base);
+ StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
+ return result;
+}
+
+INTERCEPTOR(int, atoi, const char *nptr) {
+ void *ctx;
+ MEMPROF_INTERCEPTOR_ENTER(ctx, atoi);
+ ENSURE_MEMPROF_INITED();
+ char *real_endptr;
+ // "man atoi" tells that behavior of atoi(nptr) is the same as
+ // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
+ // parsed integer can't be stored in *long* type (even if it's
+ // different from int). So, we just imitate this behavior.
+ int result = REAL(strtol)(nptr, &real_endptr, 10);
+ FixRealStrtolEndptr(nptr, &real_endptr);
+ MEMPROF_READ_STRING(nptr, (real_endptr - nptr) + 1);
+ return result;
+}
+
+INTERCEPTOR(long, atol, const char *nptr) {
+ void *ctx;
+ MEMPROF_INTERCEPTOR_ENTER(ctx, atol);
+ ENSURE_MEMPROF_INITED();
+ char *real_endptr;
+ long result = REAL(strtol)(nptr, &real_endptr, 10);
+ FixRealStrtolEndptr(nptr, &real_endptr);
+ MEMPROF_READ_STRING(nptr, (real_endptr - nptr) + 1);
+ return result;
+}
+
+INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) {
+ void *ctx;
+ MEMPROF_INTERCEPTOR_ENTER(ctx, strtoll);
+ ENSURE_MEMPROF_INITED();
+ char *real_endptr;
+ long long result = REAL(strtoll)(nptr, &real_endptr, base);
+ StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
+ return result;
+}
+
+INTERCEPTOR(long long, atoll, const char *nptr) {
+ void *ctx;
+ MEMPROF_INTERCEPTOR_ENTER(ctx, atoll);
+ ENSURE_MEMPROF_INITED();
+ char *real_endptr;
+ long long result = REAL(strtoll)(nptr, &real_endptr, 10);
+ FixRealStrtolEndptr(nptr, &real_endptr);
+ MEMPROF_READ_STRING(nptr, (real_endptr - nptr) + 1);
+ return result;
+}
+
+// ---------------------- InitializeMemprofInterceptors ---------------- {{{1
+namespace __memprof {
+void InitializeMemprofInterceptors() {
+ static bool was_called_once;
+ CHECK(!was_called_once);
+ was_called_once = true;
+ InitializeCommonInterceptors();
+
+ // Intercept str* functions.
+ MEMPROF_INTERCEPT_FUNC(strcat);
+ MEMPROF_INTERCEPT_FUNC(strcpy);
+ MEMPROF_INTERCEPT_FUNC(strncat);
+ MEMPROF_INTERCEPT_FUNC(strncpy);
+ MEMPROF_INTERCEPT_FUNC(strdup);
+ MEMPROF_INTERCEPT_FUNC(__strdup);
+ MEMPROF_INTERCEPT_FUNC(index);
+
+ MEMPROF_INTERCEPT_FUNC(atoi);
+ MEMPROF_INTERCEPT_FUNC(atol);
+ MEMPROF_INTERCEPT_FUNC(strtol);
+ MEMPROF_INTERCEPT_FUNC(atoll);
+ MEMPROF_INTERCEPT_FUNC(strtoll);
+
+ // Intercept threading-related functions
+ MEMPROF_INTERCEPT_FUNC(pthread_create);
+ MEMPROF_INTERCEPT_FUNC(pthread_join);
+
+ InitializePlatformInterceptors();
+
+ VReport(1, "MemProfiler: libc interceptors initialized\n");
+}
+
+} // namespace __memprof
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_interceptors.h b/contrib/libs/clang16-rt/lib/memprof/memprof_interceptors.h
new file mode 100644
index 00000000000..879a1e1061e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_interceptors.h
@@ -0,0 +1,60 @@
+//===-- memprof_interceptors.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// MemProf-private header for memprof_interceptors.cpp
+//===----------------------------------------------------------------------===//
+#ifndef MEMPROF_INTERCEPTORS_H
+#define MEMPROF_INTERCEPTORS_H
+
+#include "interception/interception.h"
+#include "memprof_interceptors_memintrinsics.h"
+#include "memprof_internal.h"
+#include "sanitizer_common/sanitizer_platform_interceptors.h"
+
+namespace __memprof {
+
+void InitializeMemprofInterceptors();
+void InitializePlatformInterceptors();
+
+#define ENSURE_MEMPROF_INITED() \
+ do { \
+ CHECK(!memprof_init_is_running); \
+ if (UNLIKELY(!memprof_inited)) { \
+ MemprofInitFromRtl(); \
+ } \
+ } while (0)
+
+} // namespace __memprof
+
+DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size)
+DECLARE_REAL(char *, strchr, const char *str, int c)
+DECLARE_REAL(SIZE_T, strlen, const char *s)
+DECLARE_REAL(char *, strncpy, char *to, const char *from, uptr size)
+DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen)
+DECLARE_REAL(char *, strstr, const char *s1, const char *s2)
+
+#define MEMPROF_INTERCEPT_FUNC(name) \
+ do { \
+ if (!INTERCEPT_FUNCTION(name)) \
+ VReport(1, "MemProfiler: failed to intercept '%s'\n'", #name); \
+ } while (0)
+#define MEMPROF_INTERCEPT_FUNC_VER(name, ver) \
+ do { \
+ if (!INTERCEPT_FUNCTION_VER(name, ver)) \
+ VReport(1, "MemProfiler: failed to intercept '%s@@%s'\n", #name, ver); \
+ } while (0)
+#define MEMPROF_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
+ do { \
+ if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
+ VReport(1, "MemProfiler: failed to intercept '%s@@%s' or '%s'\n", #name, \
+ ver, #name); \
+ } while (0)
+
+#endif // MEMPROF_INTERCEPTORS_H
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_interceptors_memintrinsics.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_interceptors_memintrinsics.cpp
new file mode 100644
index 00000000000..4eb409362b5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_interceptors_memintrinsics.cpp
@@ -0,0 +1,29 @@
+//===-- memprof_interceptors_memintrinsics.cpp ---------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// MemProf versions of memcpy, memmove, and memset.
+//===---------------------------------------------------------------------===//
+
+#include "memprof_interceptors_memintrinsics.h"
+#include "memprof_stack.h"
+
+using namespace __memprof;
+
+void *__memprof_memcpy(void *to, const void *from, uptr size) {
+ MEMPROF_MEMCPY_IMPL(to, from, size);
+}
+
+void *__memprof_memset(void *block, int c, uptr size) {
+ MEMPROF_MEMSET_IMPL(block, c, size);
+}
+
+void *__memprof_memmove(void *to, const void *from, uptr size) {
+ MEMPROF_MEMMOVE_IMPL(to, from, size);
+}
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_interceptors_memintrinsics.h b/contrib/libs/clang16-rt/lib/memprof/memprof_interceptors_memintrinsics.h
new file mode 100644
index 00000000000..348461d55c4
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_interceptors_memintrinsics.h
@@ -0,0 +1,79 @@
+//===-- memprof_interceptors_memintrinsics.h -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// MemProf-private header for memprof_interceptors_memintrinsics.cpp
+//===---------------------------------------------------------------------===//
+#ifndef MEMPROF_MEMINTRIN_H
+#define MEMPROF_MEMINTRIN_H
+
+#include "interception/interception.h"
+#include "memprof_interface_internal.h"
+#include "memprof_internal.h"
+#include "memprof_mapping.h"
+
+DECLARE_REAL(void *, memcpy, void *to, const void *from, uptr size)
+DECLARE_REAL(void *, memset, void *block, int c, uptr size)
+
+namespace __memprof {
+
+// We implement ACCESS_MEMORY_RANGE, MEMPROF_READ_RANGE,
+// and MEMPROF_WRITE_RANGE as macro instead of function so
+// that no extra frames are created, and stack trace contains
+// relevant information only.
+#define ACCESS_MEMORY_RANGE(offset, size) \
+ do { \
+ __memprof_record_access_range(offset, size); \
+ } while (0)
+
+// memcpy is called during __memprof_init() from the internals of printf(...).
+// We do not treat memcpy with to==from as a bug.
+// See http://llvm.org/bugs/show_bug.cgi?id=11763.
+#define MEMPROF_MEMCPY_IMPL(to, from, size) \
+ do { \
+ if (UNLIKELY(!memprof_inited)) \
+ return internal_memcpy(to, from, size); \
+ if (memprof_init_is_running) { \
+ return REAL(memcpy)(to, from, size); \
+ } \
+ ENSURE_MEMPROF_INITED(); \
+ MEMPROF_READ_RANGE(from, size); \
+ MEMPROF_WRITE_RANGE(to, size); \
+ return REAL(memcpy)(to, from, size); \
+ } while (0)
+
+// memset is called inside Printf.
+#define MEMPROF_MEMSET_IMPL(block, c, size) \
+ do { \
+ if (UNLIKELY(!memprof_inited)) \
+ return internal_memset(block, c, size); \
+ if (memprof_init_is_running) { \
+ return REAL(memset)(block, c, size); \
+ } \
+ ENSURE_MEMPROF_INITED(); \
+ MEMPROF_WRITE_RANGE(block, size); \
+ return REAL(memset)(block, c, size); \
+ } while (0)
+
+#define MEMPROF_MEMMOVE_IMPL(to, from, size) \
+ do { \
+ if (UNLIKELY(!memprof_inited)) \
+ return internal_memmove(to, from, size); \
+ ENSURE_MEMPROF_INITED(); \
+ MEMPROF_READ_RANGE(from, size); \
+ MEMPROF_WRITE_RANGE(to, size); \
+ return internal_memmove(to, from, size); \
+ } while (0)
+
+#define MEMPROF_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size)
+#define MEMPROF_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size)
+
+} // namespace __memprof
+
+#endif // MEMPROF_MEMINTRIN_H
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_interface_internal.h b/contrib/libs/clang16-rt/lib/memprof/memprof_interface_internal.h
new file mode 100644
index 00000000000..0aca4afc9af
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_interface_internal.h
@@ -0,0 +1,64 @@
+//===-- memprof_interface_internal.h ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// This header declares the MemProfiler runtime interface functions.
+// The runtime library has to define these functions so the instrumented program
+// could call them.
+//
+// See also include/sanitizer/memprof_interface.h
+//===----------------------------------------------------------------------===//
+#ifndef MEMPROF_INTERFACE_INTERNAL_H
+#define MEMPROF_INTERFACE_INTERNAL_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+#include "memprof_init_version.h"
+
+using __sanitizer::u32;
+using __sanitizer::u64;
+using __sanitizer::uptr;
+
+extern "C" {
+// This function should be called at the very beginning of the process,
+// before any instrumented code is executed and before any call to malloc.
+SANITIZER_INTERFACE_ATTRIBUTE void __memprof_init();
+SANITIZER_INTERFACE_ATTRIBUTE void __memprof_preinit();
+SANITIZER_INTERFACE_ATTRIBUTE void __memprof_version_mismatch_check_v1();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __memprof_record_access(void const volatile *addr);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __memprof_record_access_range(void const volatile *addr, uptr size);
+
+SANITIZER_INTERFACE_ATTRIBUTE void __memprof_print_accumulated_stats();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+const char *__memprof_default_options();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+extern uptr __memprof_shadow_memory_dynamic_address;
+
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE extern char
+ __memprof_profile_filename[1];
+SANITIZER_INTERFACE_ATTRIBUTE int __memprof_profile_dump();
+
+SANITIZER_INTERFACE_ATTRIBUTE void __memprof_load(uptr p);
+SANITIZER_INTERFACE_ATTRIBUTE void __memprof_store(uptr p);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__memprof_memcpy(void *dst, const void *src, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__memprof_memset(void *s, int c, uptr n);
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__memprof_memmove(void *dest, const void *src, uptr n);
+} // extern "C"
+
+#endif // MEMPROF_INTERFACE_INTERNAL_H
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_internal.h b/contrib/libs/clang16-rt/lib/memprof/memprof_internal.h
new file mode 100644
index 00000000000..bba465e60d8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_internal.h
@@ -0,0 +1,87 @@
+//===-- memprof_internal.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// MemProf-private header which defines various general utilities.
+//===----------------------------------------------------------------------===//
+#ifndef MEMPROF_INTERNAL_H
+#define MEMPROF_INTERNAL_H
+
+#include "memprof_flags.h"
+#include "memprof_interface_internal.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+
+#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+#error "The MemProfiler run-time should not be instrumented by MemProfiler"
+#endif
+
+// Build-time configuration options.
+
+// If set, memprof will intercept C++ exception api call(s).
+#ifndef MEMPROF_HAS_EXCEPTIONS
+#define MEMPROF_HAS_EXCEPTIONS 1
+#endif
+
+#ifndef MEMPROF_DYNAMIC
+#ifdef PIC
+#define MEMPROF_DYNAMIC 1
+#else
+#define MEMPROF_DYNAMIC 0
+#endif
+#endif
+
+// All internal functions in memprof reside inside the __memprof namespace
+// to avoid namespace collisions with the user programs.
+// Separate namespace also makes it simpler to distinguish the memprof
+// run-time functions from the instrumented user code in a profile.
+namespace __memprof {
+
+class MemprofThread;
+using __sanitizer::StackTrace;
+
+void MemprofInitFromRtl();
+
+// memprof_rtl.cpp
+void PrintAddressSpaceLayout();
+
+// memprof_shadow_setup.cpp
+void InitializeShadowMemory();
+
+// memprof_malloc_linux.cpp
+void ReplaceSystemMalloc();
+
+// memprof_linux.cpp
+uptr FindDynamicShadowStart();
+void *MemprofDoesNotSupportStaticLinkage();
+
+// memprof_thread.cpp
+MemprofThread *CreateMainThread();
+
+// Wrapper for TLS/TSD.
+void TSDInit(void (*destructor)(void *tsd));
+void *TSDGet();
+void TSDSet(void *tsd);
+void PlatformTSDDtor(void *tsd);
+
+void *MemprofDlSymNext(const char *sym);
+
+extern int memprof_inited;
+extern int memprof_timestamp_inited;
+extern int memprof_init_done;
+// Used to avoid infinite recursion in __memprof_init().
+extern bool memprof_init_is_running;
+extern void (*death_callback)(void);
+extern long memprof_init_timestamp_s;
+
+} // namespace __memprof
+
+#endif // MEMPROF_INTERNAL_H
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_linux.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_linux.cpp
new file mode 100644
index 00000000000..fcd927023f5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_linux.cpp
@@ -0,0 +1,74 @@
+//===-- memprof_linux.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// Linux-specific details.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if !SANITIZER_LINUX
+#error Unsupported OS
+#endif
+
+#include "memprof_interceptors.h"
+#include "memprof_internal.h"
+#include "memprof_thread.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_freebsd.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <link.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <unistd.h>
+#include <unwind.h>
+
+extern ElfW(Dyn) _DYNAMIC[];
+
+typedef enum {
+ MEMPROF_RT_VERSION_UNDEFINED = 0,
+ MEMPROF_RT_VERSION_DYNAMIC,
+ MEMPROF_RT_VERSION_STATIC,
+} memprof_rt_version_t;
+
+// FIXME: perhaps also store abi version here?
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+memprof_rt_version_t __memprof_rt_version;
+}
+
+namespace __memprof {
+
+void InitializePlatformInterceptors() {}
+void InitializePlatformExceptionHandlers() {}
+
+void *MemprofDoesNotSupportStaticLinkage() {
+ // This will fail to link with -static.
+ return &_DYNAMIC;
+}
+
+uptr FindDynamicShadowStart() {
+ uptr shadow_size_bytes = MemToShadowSize(kHighMemEnd);
+ return MapDynamicShadow(shadow_size_bytes, SHADOW_SCALE,
+ /*min_shadow_base_alignment*/ 0, kHighMemEnd);
+}
+
+void *MemprofDlSymNext(const char *sym) { return dlsym(RTLD_NEXT, sym); }
+
+} // namespace __memprof
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_malloc_linux.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_malloc_linux.cpp
new file mode 100644
index 00000000000..ef753fcaa4a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_malloc_linux.cpp
@@ -0,0 +1,151 @@
+//===-- memprof_malloc_linux.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// Linux-specific malloc interception.
+// We simply define functions like malloc, free, realloc, etc.
+// They will replace the corresponding libc functions automagically.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if !SANITIZER_LINUX
+#error Unsupported OS
+#endif
+
+#include "memprof_allocator.h"
+#include "memprof_interceptors.h"
+#include "memprof_internal.h"
+#include "memprof_stack.h"
+#include "sanitizer_common/sanitizer_allocator_checks.h"
+#include "sanitizer_common/sanitizer_allocator_dlsym.h"
+#include "sanitizer_common/sanitizer_errno.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+
+// ---------------------- Replacement functions ---------------- {{{1
+using namespace __memprof;
+
+struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
+ static bool UseImpl() { return memprof_init_is_running; }
+};
+
+INTERCEPTOR(void, free, void *ptr) {
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+ GET_STACK_TRACE_FREE;
+ memprof_free(ptr, &stack, FROM_MALLOC);
+}
+
+#if SANITIZER_INTERCEPT_CFREE
+INTERCEPTOR(void, cfree, void *ptr) {
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+ GET_STACK_TRACE_FREE;
+ memprof_free(ptr, &stack, FROM_MALLOC);
+}
+#endif // SANITIZER_INTERCEPT_CFREE
+
+INTERCEPTOR(void *, malloc, uptr size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Allocate(size);
+ ENSURE_MEMPROF_INITED();
+ GET_STACK_TRACE_MALLOC;
+ return memprof_malloc(size, &stack);
+}
+
+INTERCEPTOR(void *, calloc, uptr nmemb, uptr size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Callocate(nmemb, size);
+ ENSURE_MEMPROF_INITED();
+ GET_STACK_TRACE_MALLOC;
+ return memprof_calloc(nmemb, size, &stack);
+}
+
+INTERCEPTOR(void *, realloc, void *ptr, uptr size) {
+ if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Realloc(ptr, size);
+ ENSURE_MEMPROF_INITED();
+ GET_STACK_TRACE_MALLOC;
+ return memprof_realloc(ptr, size, &stack);
+}
+
+#if SANITIZER_INTERCEPT_REALLOCARRAY
+INTERCEPTOR(void *, reallocarray, void *ptr, uptr nmemb, uptr size) {
+ ENSURE_MEMPROF_INITED();
+ GET_STACK_TRACE_MALLOC;
+ return memprof_reallocarray(ptr, nmemb, size, &stack);
+}
+#endif // SANITIZER_INTERCEPT_REALLOCARRAY
+
+#if SANITIZER_INTERCEPT_MEMALIGN
+INTERCEPTOR(void *, memalign, uptr boundary, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return memprof_memalign(boundary, size, &stack, FROM_MALLOC);
+}
+
+INTERCEPTOR(void *, __libc_memalign, uptr boundary, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ void *res = memprof_memalign(boundary, size, &stack, FROM_MALLOC);
+ DTLS_on_libc_memalign(res, size);
+ return res;
+}
+#endif // SANITIZER_INTERCEPT_MEMALIGN
+
+#if SANITIZER_INTERCEPT_ALIGNED_ALLOC
+INTERCEPTOR(void *, aligned_alloc, uptr boundary, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return memprof_aligned_alloc(boundary, size, &stack);
+}
+#endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC
+
+INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
+ GET_CURRENT_PC_BP_SP;
+ (void)sp;
+ return memprof_malloc_usable_size(ptr, pc, bp);
+}
+
+#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
+// We avoid including malloc.h for portability reasons.
+// man mallinfo says the fields are "long", but the implementation uses int.
+// It doesn't matter much -- we just need to make sure that the libc's mallinfo
+// is not called.
+struct fake_mallinfo {
+ int x[10];
+};
+
+INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
+ struct fake_mallinfo res;
+ REAL(memset)(&res, 0, sizeof(res));
+ return res;
+}
+
+INTERCEPTOR(int, mallopt, int cmd, int value) { return 0; }
+#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
+
+INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return memprof_posix_memalign(memptr, alignment, size, &stack);
+}
+
+INTERCEPTOR(void *, valloc, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return memprof_valloc(size, &stack);
+}
+
+#if SANITIZER_INTERCEPT_PVALLOC
+INTERCEPTOR(void *, pvalloc, uptr size) {
+ GET_STACK_TRACE_MALLOC;
+ return memprof_pvalloc(size, &stack);
+}
+#endif // SANITIZER_INTERCEPT_PVALLOC
+
+INTERCEPTOR(void, malloc_stats, void) { __memprof_print_accumulated_stats(); }
+
+namespace __memprof {
+void ReplaceSystemMalloc() {}
+} // namespace __memprof
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_mapping.h b/contrib/libs/clang16-rt/lib/memprof/memprof_mapping.h
new file mode 100644
index 00000000000..ba05b88db30
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_mapping.h
@@ -0,0 +1,113 @@
+//===-- memprof_mapping.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// Defines MemProf memory mapping.
+//===----------------------------------------------------------------------===//
+#ifndef MEMPROF_MAPPING_H
+#define MEMPROF_MAPPING_H
+
+#include "memprof_internal.h"
+
+static const u64 kDefaultShadowScale = 3;
+#define SHADOW_SCALE kDefaultShadowScale
+
+#define SHADOW_OFFSET __memprof_shadow_memory_dynamic_address
+
+#define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE)
+#define MEMPROF_ALIGNMENT 32
+
+namespace __memprof {
+
+extern uptr kHighMemEnd; // Initialized in __memprof_init.
+
+} // namespace __memprof
+
+#define SHADOW_ENTRY_SIZE 8
+
+// Size of memory block mapped to a single shadow location
+#define MEM_GRANULARITY 64ULL
+
+#define SHADOW_MASK ~(MEM_GRANULARITY - 1)
+
+#define MEM_TO_SHADOW(mem) \
+ ((((mem) & SHADOW_MASK) >> SHADOW_SCALE) + (SHADOW_OFFSET))
+
+#define kLowMemBeg 0
+#define kLowMemEnd (SHADOW_OFFSET ? SHADOW_OFFSET - 1 : 0)
+
+#define kLowShadowBeg SHADOW_OFFSET
+#define kLowShadowEnd (MEM_TO_SHADOW(kLowMemEnd) + SHADOW_ENTRY_SIZE - 1)
+
+#define kHighMemBeg (MEM_TO_SHADOW(kHighMemEnd) + 1 + SHADOW_ENTRY_SIZE - 1)
+
+#define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg)
+#define kHighShadowEnd (MEM_TO_SHADOW(kHighMemEnd) + SHADOW_ENTRY_SIZE - 1)
+
+// With the zero shadow base we can not actually map pages starting from 0.
+// This constant is somewhat arbitrary.
+#define kZeroBaseShadowStart 0
+#define kZeroBaseMaxShadowStart (1 << 18)
+
+#define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 : kZeroBaseShadowStart)
+#define kShadowGapEnd (kHighShadowBeg - 1)
+
+namespace __memprof {
+
+inline uptr MemToShadowSize(uptr size) { return size >> SHADOW_SCALE; }
+inline bool AddrIsInLowMem(uptr a) { return a <= kLowMemEnd; }
+
+inline bool AddrIsInLowShadow(uptr a) {
+ return a >= kLowShadowBeg && a <= kLowShadowEnd;
+}
+
+inline bool AddrIsInHighMem(uptr a) {
+ return kHighMemBeg && a >= kHighMemBeg && a <= kHighMemEnd;
+}
+
+inline bool AddrIsInHighShadow(uptr a) {
+ return kHighMemBeg && a >= kHighShadowBeg && a <= kHighShadowEnd;
+}
+
+inline bool AddrIsInShadowGap(uptr a) {
+ // In zero-based shadow mode we treat addresses near zero as addresses
+ // in shadow gap as well.
+ if (SHADOW_OFFSET == 0)
+ return a <= kShadowGapEnd;
+ return a >= kShadowGapBeg && a <= kShadowGapEnd;
+}
+
+inline bool AddrIsInMem(uptr a) {
+ return AddrIsInLowMem(a) || AddrIsInHighMem(a) ||
+ (flags()->protect_shadow_gap == 0 && AddrIsInShadowGap(a));
+}
+
+inline uptr MemToShadow(uptr p) {
+ CHECK(AddrIsInMem(p));
+ return MEM_TO_SHADOW(p);
+}
+
+inline bool AddrIsInShadow(uptr a) {
+ return AddrIsInLowShadow(a) || AddrIsInHighShadow(a);
+}
+
+inline bool AddrIsAlignedByGranularity(uptr a) {
+ return (a & (SHADOW_GRANULARITY - 1)) == 0;
+}
+
+inline void RecordAccess(uptr a) {
+ // If we use a different shadow size then the type below needs adjustment.
+ CHECK_EQ(SHADOW_ENTRY_SIZE, 8);
+ u64 *shadow_address = (u64 *)MEM_TO_SHADOW(a);
+ (*shadow_address)++;
+}
+
+} // namespace __memprof
+
+#endif // MEMPROF_MAPPING_H
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_mibmap.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_mibmap.cpp
new file mode 100644
index 00000000000..32f0796c8f2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_mibmap.cpp
@@ -0,0 +1,37 @@
+//===-- memprof_mibmap.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+//===----------------------------------------------------------------------===//
+
+#include "memprof_mibmap.h"
+#include "profile/MemProfData.inc"
+#include "sanitizer_common/sanitizer_allocator_internal.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+
+namespace __memprof {
+using ::llvm::memprof::MemInfoBlock;
+
+void InsertOrMerge(const uptr Id, const MemInfoBlock &Block, MIBMapTy &Map) {
+ MIBMapTy::Handle h(&Map, static_cast<uptr>(Id), /*remove=*/false,
+ /*create=*/true);
+ if (h.created()) {
+ LockedMemInfoBlock *lmib =
+ (LockedMemInfoBlock *)InternalAlloc(sizeof(LockedMemInfoBlock));
+ lmib->mutex.Init();
+ lmib->mib = Block;
+ *h = lmib;
+ } else {
+ LockedMemInfoBlock *lmib = *h;
+ SpinMutexLock lock(&lmib->mutex);
+ lmib->mib.Merge(Block);
+ }
+}
+
+} // namespace __memprof
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_mibmap.h b/contrib/libs/clang16-rt/lib/memprof/memprof_mibmap.h
new file mode 100644
index 00000000000..a7cd420464e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_mibmap.h
@@ -0,0 +1,27 @@
+#ifndef MEMPROF_MIBMAP_H_
+#define MEMPROF_MIBMAP_H_
+
+#include <stdint.h>
+
+#include "profile/MemProfData.inc"
+#include "sanitizer_common/sanitizer_addrhashmap.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+
+namespace __memprof {
+
+struct LockedMemInfoBlock {
+ __sanitizer::StaticSpinMutex mutex;
+ ::llvm::memprof::MemInfoBlock mib;
+};
+
+// The MIB map stores a mapping from stack ids to MemInfoBlocks.
+typedef __sanitizer::AddrHashMap<LockedMemInfoBlock *, 200003> MIBMapTy;
+
+// Insert a new MemInfoBlock or merge with an existing block identified by the
+// stack id.
+void InsertOrMerge(const uptr Id, const ::llvm::memprof::MemInfoBlock &Block,
+ MIBMapTy &Map);
+
+} // namespace __memprof
+
+#endif // MEMPROF_MIBMAP_H_
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_new_delete.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_new_delete.cpp
new file mode 100644
index 00000000000..cae5de30136
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_new_delete.cpp
@@ -0,0 +1,145 @@
+//===-- memprof_interceptors.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// Interceptors for operators new and delete.
+//===----------------------------------------------------------------------===//
+
+#include "memprof_allocator.h"
+#include "memprof_internal.h"
+#include "memprof_stack.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
+
+#include "interception/interception.h"
+
+#include <stddef.h>
+
+#define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE
+
+using namespace __memprof;
+
+// Fake std::nothrow_t and std::align_val_t to avoid including <new>.
+namespace std {
+struct nothrow_t {};
+enum class align_val_t : size_t {};
+} // namespace std
+
+#define OPERATOR_NEW_BODY(type, nothrow) \
+ GET_STACK_TRACE_MALLOC; \
+ void *res = memprof_memalign(0, size, &stack, type); \
+ if (!nothrow && UNLIKELY(!res)) \
+ ReportOutOfMemory(size, &stack); \
+ return res;
+#define OPERATOR_NEW_BODY_ALIGN(type, nothrow) \
+ GET_STACK_TRACE_MALLOC; \
+ void *res = memprof_memalign((uptr)align, size, &stack, type); \
+ if (!nothrow && UNLIKELY(!res)) \
+ ReportOutOfMemory(size, &stack); \
+ return res;
+
+CXX_OPERATOR_ATTRIBUTE
+void *operator new(size_t size) {
+ OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/);
+}
+CXX_OPERATOR_ATTRIBUTE
+void *operator new[](size_t size) {
+ OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/);
+}
+CXX_OPERATOR_ATTRIBUTE
+void *operator new(size_t size, std::nothrow_t const &) {
+ OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/);
+}
+CXX_OPERATOR_ATTRIBUTE
+void *operator new[](size_t size, std::nothrow_t const &) {
+ OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/);
+}
+CXX_OPERATOR_ATTRIBUTE
+void *operator new(size_t size, std::align_val_t align) {
+ OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/);
+}
+CXX_OPERATOR_ATTRIBUTE
+void *operator new[](size_t size, std::align_val_t align) {
+ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/);
+}
+CXX_OPERATOR_ATTRIBUTE
+void *operator new(size_t size, std::align_val_t align,
+ std::nothrow_t const &) {
+ OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/);
+}
+CXX_OPERATOR_ATTRIBUTE
+void *operator new[](size_t size, std::align_val_t align,
+ std::nothrow_t const &) {
+ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/);
+}
+
+#define OPERATOR_DELETE_BODY(type) \
+ GET_STACK_TRACE_FREE; \
+ memprof_delete(ptr, 0, 0, &stack, type);
+
+#define OPERATOR_DELETE_BODY_SIZE(type) \
+ GET_STACK_TRACE_FREE; \
+ memprof_delete(ptr, size, 0, &stack, type);
+
+#define OPERATOR_DELETE_BODY_ALIGN(type) \
+ GET_STACK_TRACE_FREE; \
+ memprof_delete(ptr, 0, static_cast<uptr>(align), &stack, type);
+
+#define OPERATOR_DELETE_BODY_SIZE_ALIGN(type) \
+ GET_STACK_TRACE_FREE; \
+ memprof_delete(ptr, size, static_cast<uptr>(align), &stack, type);
+
+CXX_OPERATOR_ATTRIBUTE
+void operator delete(void *ptr)NOEXCEPT { OPERATOR_DELETE_BODY(FROM_NEW); }
+CXX_OPERATOR_ATTRIBUTE
+void operator delete[](void *ptr) NOEXCEPT {
+ OPERATOR_DELETE_BODY(FROM_NEW_BR);
+}
+CXX_OPERATOR_ATTRIBUTE
+void operator delete(void *ptr, std::nothrow_t const &) {
+ OPERATOR_DELETE_BODY(FROM_NEW);
+}
+CXX_OPERATOR_ATTRIBUTE
+void operator delete[](void *ptr, std::nothrow_t const &) {
+ OPERATOR_DELETE_BODY(FROM_NEW_BR);
+}
+CXX_OPERATOR_ATTRIBUTE
+void operator delete(void *ptr, size_t size)NOEXCEPT {
+ OPERATOR_DELETE_BODY_SIZE(FROM_NEW);
+}
+CXX_OPERATOR_ATTRIBUTE
+void operator delete[](void *ptr, size_t size) NOEXCEPT {
+ OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR);
+}
+CXX_OPERATOR_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align)NOEXCEPT {
+ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW);
+}
+CXX_OPERATOR_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
+ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR);
+}
+CXX_OPERATOR_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align,
+ std::nothrow_t const &) {
+ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW);
+}
+CXX_OPERATOR_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align,
+ std::nothrow_t const &) {
+ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR);
+}
+CXX_OPERATOR_ATTRIBUTE
+void operator delete(void *ptr, size_t size, std::align_val_t align)NOEXCEPT {
+ OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW);
+}
+CXX_OPERATOR_ATTRIBUTE
+void operator delete[](void *ptr, size_t size,
+ std::align_val_t align) NOEXCEPT {
+ OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR);
+}
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_posix.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_posix.cpp
new file mode 100644
index 00000000000..ee0821b8510
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_posix.cpp
@@ -0,0 +1,55 @@
+//===-- memprof_posix.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// Posix-specific details.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if !SANITIZER_POSIX
+#error Only Posix supported
+#endif
+
+#include "memprof_thread.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+#include <pthread.h>
+
+namespace __memprof {
+
+// ---------------------- TSD ---------------- {{{1
+
+static pthread_key_t tsd_key;
+static bool tsd_key_inited = false;
+void TSDInit(void (*destructor)(void *tsd)) {
+ CHECK(!tsd_key_inited);
+ tsd_key_inited = true;
+ CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
+}
+
+void *TSDGet() {
+ CHECK(tsd_key_inited);
+ return pthread_getspecific(tsd_key);
+}
+
+void TSDSet(void *tsd) {
+ CHECK(tsd_key_inited);
+ pthread_setspecific(tsd_key, tsd);
+}
+
+void PlatformTSDDtor(void *tsd) {
+ MemprofThreadContext *context = (MemprofThreadContext *)tsd;
+ if (context->destructor_iterations > 1) {
+ context->destructor_iterations--;
+ CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
+ return;
+ }
+ MemprofThread::TSDDtor(tsd);
+}
+} // namespace __memprof
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_preinit.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_preinit.cpp
new file mode 100644
index 00000000000..7092cd4ee55
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_preinit.cpp
@@ -0,0 +1,23 @@
+//===-- memprof_preinit.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// Call __memprof_init at the very early stage of process startup.
+//===----------------------------------------------------------------------===//
+#include "memprof_internal.h"
+
+using namespace __memprof;
+
+#if SANITIZER_CAN_USE_PREINIT_ARRAY
+// The symbol is called __local_memprof_preinit, because it's not intended to
+// be exported. This code linked into the main executable when -fmemory-profile
+// is in the link flags. It can only use exported interface functions.
+__attribute__((section(".preinit_array"),
+ used)) void (*__local_memprof_preinit)(void) = __memprof_preinit;
+#endif
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_rawprofile.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_rawprofile.cpp
new file mode 100644
index 00000000000..f065e8dbcab
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_rawprofile.cpp
@@ -0,0 +1,246 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "memprof_rawprofile.h"
+#include "profile/MemProfData.inc"
+#include "sanitizer_common/sanitizer_allocator_internal.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_stackdepotbase.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_vector.h"
+
+namespace __memprof {
+using ::__sanitizer::Vector;
+using ::llvm::memprof::MemInfoBlock;
+using SegmentEntry = ::llvm::memprof::SegmentEntry;
+using Header = ::llvm::memprof::Header;
+
+namespace {
+template <class T> char *WriteBytes(T Pod, char *&Buffer) {
+ *(T *)Buffer = Pod;
+ return Buffer + sizeof(T);
+}
+
+void RecordStackId(const uptr Key, UNUSED LockedMemInfoBlock *const &MIB,
+ void *Arg) {
+ // No need to touch the MIB value here since we are only recording the key.
+ auto *StackIds = reinterpret_cast<Vector<u64> *>(Arg);
+ StackIds->PushBack(Key);
+}
+} // namespace
+
+u64 SegmentSizeBytes(MemoryMappingLayoutBase &Layout) {
+ u64 NumSegmentsToRecord = 0;
+ MemoryMappedSegment segment;
+ for (Layout.Reset(); Layout.Next(&segment);)
+ if (segment.IsReadable() && segment.IsExecutable())
+ NumSegmentsToRecord++;
+
+ return sizeof(u64) // A header which stores the number of records.
+ + sizeof(SegmentEntry) * NumSegmentsToRecord;
+}
+
+// The segment section uses the following format:
+// ---------- Segment Info
+// Num Entries
+// ---------- Segment Entry
+// Start
+// End
+// Offset
+// BuildID 32B
+// ----------
+// ...
+void SerializeSegmentsToBuffer(MemoryMappingLayoutBase &Layout,
+ const u64 ExpectedNumBytes, char *&Buffer) {
+ char *Ptr = Buffer;
+ // Reserve space for the final count.
+ Ptr += sizeof(u64);
+
+ u64 NumSegmentsRecorded = 0;
+ MemoryMappedSegment segment;
+
+ for (Layout.Reset(); Layout.Next(&segment);) {
+ if (segment.IsReadable() && segment.IsExecutable()) {
+ // TODO: Record segment.uuid when it is implemented for Linux-Elf.
+ SegmentEntry Entry(segment.start, segment.end, segment.offset);
+ memcpy(Ptr, &Entry, sizeof(SegmentEntry));
+ Ptr += sizeof(SegmentEntry);
+ NumSegmentsRecorded++;
+ }
+ }
+
+ // Store the number of segments we recorded in the space we reserved.
+ *((u64 *)Buffer) = NumSegmentsRecorded;
+ CHECK(ExpectedNumBytes >= static_cast<u64>(Ptr - Buffer) &&
+ "Expected num bytes != actual bytes written");
+}
+
+u64 StackSizeBytes(const Vector<u64> &StackIds) {
+ u64 NumBytesToWrite = sizeof(u64);
+
+ const u64 NumIds = StackIds.Size();
+ for (unsigned k = 0; k < NumIds; ++k) {
+ const u64 Id = StackIds[k];
+ // One entry for the id and then one more for the number of stack pcs.
+ NumBytesToWrite += 2 * sizeof(u64);
+ const StackTrace St = StackDepotGet(Id);
+
+ CHECK(St.trace != nullptr && St.size > 0 && "Empty stack trace");
+ for (uptr i = 0; i < St.size && St.trace[i] != 0; i++) {
+ NumBytesToWrite += sizeof(u64);
+ }
+ }
+ return NumBytesToWrite;
+}
+
+// The stack info section uses the following format:
+//
+// ---------- Stack Info
+// Num Entries
+// ---------- Stack Entry
+// Num Stacks
+// PC1
+// PC2
+// ...
+// ----------
+void SerializeStackToBuffer(const Vector<u64> &StackIds,
+ const u64 ExpectedNumBytes, char *&Buffer) {
+ const u64 NumIds = StackIds.Size();
+ char *Ptr = Buffer;
+ Ptr = WriteBytes(static_cast<u64>(NumIds), Ptr);
+
+ for (unsigned k = 0; k < NumIds; ++k) {
+ const u64 Id = StackIds[k];
+ Ptr = WriteBytes(Id, Ptr);
+ Ptr += sizeof(u64); // Bump it by u64, we will fill this in later.
+ u64 Count = 0;
+ const StackTrace St = StackDepotGet(Id);
+ for (uptr i = 0; i < St.size && St.trace[i] != 0; i++) {
+ // PCs in stack traces are actually the return addresses, that is,
+ // addresses of the next instructions after the call.
+ uptr pc = StackTrace::GetPreviousInstructionPc(St.trace[i]);
+ Ptr = WriteBytes(static_cast<u64>(pc), Ptr);
+ ++Count;
+ }
+ // Store the count in the space we reserved earlier.
+ *(u64 *)(Ptr - (Count + 1) * sizeof(u64)) = Count;
+ }
+
+ CHECK(ExpectedNumBytes >= static_cast<u64>(Ptr - Buffer) &&
+ "Expected num bytes != actual bytes written");
+}
+
+// The MIB section has the following format:
+// ---------- MIB Info
+// Num Entries
+// ---------- MIB Entry 0
+// Alloc Count
+// ...
+// ---------- MIB Entry 1
+// Alloc Count
+// ...
+// ----------
+void SerializeMIBInfoToBuffer(MIBMapTy &MIBMap, const Vector<u64> &StackIds,
+ const u64 ExpectedNumBytes, char *&Buffer) {
+ char *Ptr = Buffer;
+ const u64 NumEntries = StackIds.Size();
+ Ptr = WriteBytes(NumEntries, Ptr);
+
+ for (u64 i = 0; i < NumEntries; i++) {
+ const u64 Key = StackIds[i];
+ MIBMapTy::Handle h(&MIBMap, Key, /*remove=*/true, /*create=*/false);
+ CHECK(h.exists());
+ Ptr = WriteBytes(Key, Ptr);
+ Ptr = WriteBytes((*h)->mib, Ptr);
+ }
+
+ CHECK(ExpectedNumBytes >= static_cast<u64>(Ptr - Buffer) &&
+ "Expected num bytes != actual bytes written");
+}
+
+// Format
+// ---------- Header
+// Magic
+// Version
+// Total Size
+// Segment Offset
+// MIB Info Offset
+// Stack Offset
+// ---------- Segment Info
+// Num Entries
+// ---------- Segment Entry
+// Start
+// End
+// Offset
+// BuildID 32B
+// ----------
+// ...
+// ----------
+// Optional Padding Bytes
+// ---------- MIB Info
+// Num Entries
+// ---------- MIB Entry
+// Alloc Count
+// ...
+// ----------
+// Optional Padding Bytes
+// ---------- Stack Info
+// Num Entries
+// ---------- Stack Entry
+// Num Stacks
+// PC1
+// PC2
+// ...
+// ----------
+// Optional Padding Bytes
+// ...
+u64 SerializeToRawProfile(MIBMapTy &MIBMap, MemoryMappingLayoutBase &Layout,
+ char *&Buffer) {
+ // Each section size is rounded up to 8b since the first entry in each section
+ // is a u64 which holds the number of entries in the section by convention.
+ const u64 NumSegmentBytes = RoundUpTo(SegmentSizeBytes(Layout), 8);
+
+ Vector<u64> StackIds;
+ MIBMap.ForEach(RecordStackId, reinterpret_cast<void *>(&StackIds));
+ // The first 8b are for the total number of MIB records. Each MIB record is
+ // preceded by a 8b stack id which is associated with stack frames in the next
+ // section.
+ const u64 NumMIBInfoBytes = RoundUpTo(
+ sizeof(u64) + StackIds.Size() * (sizeof(u64) + sizeof(MemInfoBlock)), 8);
+
+ const u64 NumStackBytes = RoundUpTo(StackSizeBytes(StackIds), 8);
+
+ // Ensure that the profile is 8b aligned. We allow for some optional padding
+ // at the end so that any subsequent profile serialized to the same file does
+ // not incur unaligned accesses.
+ const u64 TotalSizeBytes = RoundUpTo(
+ sizeof(Header) + NumSegmentBytes + NumStackBytes + NumMIBInfoBytes, 8);
+
+ // Allocate the memory for the entire buffer incl. info blocks.
+ Buffer = (char *)InternalAlloc(TotalSizeBytes);
+ char *Ptr = Buffer;
+
+ Header header{MEMPROF_RAW_MAGIC_64,
+ MEMPROF_RAW_VERSION,
+ static_cast<u64>(TotalSizeBytes),
+ sizeof(Header),
+ sizeof(Header) + NumSegmentBytes,
+ sizeof(Header) + NumSegmentBytes + NumMIBInfoBytes};
+ Ptr = WriteBytes(header, Ptr);
+
+ SerializeSegmentsToBuffer(Layout, NumSegmentBytes, Ptr);
+ Ptr += NumSegmentBytes;
+
+ SerializeMIBInfoToBuffer(MIBMap, StackIds, NumMIBInfoBytes, Ptr);
+ Ptr += NumMIBInfoBytes;
+
+ SerializeStackToBuffer(StackIds, NumStackBytes, Ptr);
+
+ return TotalSizeBytes;
+}
+
+} // namespace __memprof
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_rawprofile.h b/contrib/libs/clang16-rt/lib/memprof/memprof_rawprofile.h
new file mode 100644
index 00000000000..575104e7e34
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_rawprofile.h
@@ -0,0 +1,14 @@
+#ifndef MEMPROF_RAWPROFILE_H_
+#define MEMPROF_RAWPROFILE_H_
+
+#include "memprof_mibmap.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+
+namespace __memprof {
+// Serialize the in-memory representation of the memprof profile to the raw
+// binary format. The format itself is documented memprof_rawprofile.cpp.
+u64 SerializeToRawProfile(MIBMapTy &BlockCache, MemoryMappingLayoutBase &Layout,
+ char *&Buffer);
+} // namespace __memprof
+
+#endif // MEMPROF_RAWPROFILE_H_
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_rtl.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_rtl.cpp
new file mode 100644
index 00000000000..d30b80304f6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_rtl.cpp
@@ -0,0 +1,307 @@
+//===-- memprof_rtl.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// Main file of the MemProf run-time library.
+//===----------------------------------------------------------------------===//
+
+#include "memprof_allocator.h"
+#include "memprof_interceptors.h"
+#include "memprof_interface_internal.h"
+#include "memprof_internal.h"
+#include "memprof_mapping.h"
+#include "memprof_stack.h"
+#include "memprof_stats.h"
+#include "memprof_thread.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_interface_internal.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+
+#include <time.h>
+
+uptr __memprof_shadow_memory_dynamic_address; // Global interface symbol.
+
+// Allow the user to specify a profile output file via the binary.
+SANITIZER_WEAK_ATTRIBUTE char __memprof_profile_filename[1];
+
+namespace __memprof {
+
+static void MemprofDie() {
+ static atomic_uint32_t num_calls;
+ if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
+ // Don't die twice - run a busy loop.
+ while (1) {
+ internal_sched_yield();
+ }
+ }
+ if (common_flags()->print_module_map >= 1)
+ DumpProcessMap();
+ if (flags()->unmap_shadow_on_exit) {
+ if (kHighShadowEnd)
+ UnmapOrDie((void *)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg);
+ }
+}
+
+static void MemprofOnDeadlySignal(int signo, void *siginfo, void *context) {
+ // We call StartReportDeadlySignal not HandleDeadlySignal so we get the
+ // deadly signal message to stderr but no writing to the profile output file
+ StartReportDeadlySignal();
+ __memprof_profile_dump();
+ Die();
+}
+
+static void CheckUnwind() {
+ GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_check);
+ stack.Print();
+}
+
+// -------------------------- Globals --------------------- {{{1
+int memprof_inited;
+int memprof_init_done;
+bool memprof_init_is_running;
+int memprof_timestamp_inited;
+long memprof_init_timestamp_s;
+
+uptr kHighMemEnd;
+
+// -------------------------- Run-time entry ------------------- {{{1
+// exported functions
+
+#define MEMPROF_MEMORY_ACCESS_CALLBACK_BODY() __memprof::RecordAccess(addr);
+
+#define MEMPROF_MEMORY_ACCESS_CALLBACK(type) \
+ extern "C" NOINLINE INTERFACE_ATTRIBUTE void __memprof_##type(uptr addr) { \
+ MEMPROF_MEMORY_ACCESS_CALLBACK_BODY() \
+ }
+
+MEMPROF_MEMORY_ACCESS_CALLBACK(load)
+MEMPROF_MEMORY_ACCESS_CALLBACK(store)
+
+// Force the linker to keep the symbols for various MemProf interface
+// functions. We want to keep those in the executable in order to let the
+// instrumented dynamic libraries access the symbol even if it is not used by
+// the executable itself. This should help if the build system is removing dead
+// code at link time.
+static NOINLINE void force_interface_symbols() {
+ volatile int fake_condition = 0; // prevent dead condition elimination.
+ // clang-format off
+ switch (fake_condition) {
+ case 1: __memprof_record_access(nullptr); break;
+ case 2: __memprof_record_access_range(nullptr, 0); break;
+ }
+ // clang-format on
+}
+
+static void memprof_atexit() {
+ Printf("MemProfiler exit stats:\n");
+ __memprof_print_accumulated_stats();
+}
+
+static void InitializeHighMemEnd() {
+ kHighMemEnd = GetMaxUserVirtualAddress();
+ // Increase kHighMemEnd to make sure it's properly
+ // aligned together with kHighMemBeg:
+ kHighMemEnd |= (GetMmapGranularity() << SHADOW_SCALE) - 1;
+}
+
+void PrintAddressSpaceLayout() {
+ if (kHighMemBeg) {
+ Printf("|| `[%p, %p]` || HighMem ||\n", (void *)kHighMemBeg,
+ (void *)kHighMemEnd);
+ Printf("|| `[%p, %p]` || HighShadow ||\n", (void *)kHighShadowBeg,
+ (void *)kHighShadowEnd);
+ }
+ Printf("|| `[%p, %p]` || ShadowGap ||\n", (void *)kShadowGapBeg,
+ (void *)kShadowGapEnd);
+ if (kLowShadowBeg) {
+ Printf("|| `[%p, %p]` || LowShadow ||\n", (void *)kLowShadowBeg,
+ (void *)kLowShadowEnd);
+ Printf("|| `[%p, %p]` || LowMem ||\n", (void *)kLowMemBeg,
+ (void *)kLowMemEnd);
+ }
+ Printf("MemToShadow(shadow): %p %p", (void *)MEM_TO_SHADOW(kLowShadowBeg),
+ (void *)MEM_TO_SHADOW(kLowShadowEnd));
+ if (kHighMemBeg) {
+ Printf(" %p %p", (void *)MEM_TO_SHADOW(kHighShadowBeg),
+ (void *)MEM_TO_SHADOW(kHighShadowEnd));
+ }
+ Printf("\n");
+ Printf("malloc_context_size=%zu\n",
+ (uptr)common_flags()->malloc_context_size);
+
+ Printf("SHADOW_SCALE: %d\n", (int)SHADOW_SCALE);
+ Printf("SHADOW_GRANULARITY: %d\n", (int)SHADOW_GRANULARITY);
+ Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)SHADOW_OFFSET);
+ CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
+}
+
+static void MemprofInitInternal() {
+ if (LIKELY(memprof_inited))
+ return;
+ SanitizerToolName = "MemProfiler";
+ CHECK(!memprof_init_is_running && "MemProf init calls itself!");
+ memprof_init_is_running = true;
+
+ CacheBinaryName();
+
+ // Initialize flags. This must be done early, because most of the
+ // initialization steps look at flags().
+ InitializeFlags();
+
+ AvoidCVE_2016_2143();
+
+ SetMallocContextSize(common_flags()->malloc_context_size);
+
+ InitializeHighMemEnd();
+
+ // Make sure we are not statically linked.
+ MemprofDoesNotSupportStaticLinkage();
+
+ // Install tool-specific callbacks in sanitizer_common.
+ AddDieCallback(MemprofDie);
+ SetCheckUnwindCallback(CheckUnwind);
+
+ // Use profile name specified via the binary itself if it exists, and hasn't
+ // been overrriden by a flag at runtime.
+ if (__memprof_profile_filename[0] != 0 && !common_flags()->log_path)
+ __sanitizer_set_report_path(__memprof_profile_filename);
+ else
+ __sanitizer_set_report_path(common_flags()->log_path);
+
+ __sanitizer::InitializePlatformEarly();
+
+ // Setup internal allocator callback.
+ SetLowLevelAllocateMinAlignment(SHADOW_GRANULARITY);
+
+ InitializeMemprofInterceptors();
+ CheckASLR();
+
+ ReplaceSystemMalloc();
+
+ DisableCoreDumperIfNecessary();
+
+ InitializeShadowMemory();
+
+ TSDInit(PlatformTSDDtor);
+ InstallDeadlySignalHandlers(MemprofOnDeadlySignal);
+
+ InitializeAllocator();
+
+ // On Linux MemprofThread::ThreadStart() calls malloc() that's why
+ // memprof_inited should be set to 1 prior to initializing the threads.
+ memprof_inited = 1;
+ memprof_init_is_running = false;
+
+ if (flags()->atexit)
+ Atexit(memprof_atexit);
+
+ InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
+
+ // interceptors
+ InitTlsSize();
+
+ // Create main thread.
+ MemprofThread *main_thread = CreateMainThread();
+ CHECK_EQ(0, main_thread->tid());
+ force_interface_symbols(); // no-op.
+ SanitizerInitializeUnwinder();
+
+ Symbolizer::LateInitialize();
+
+ VReport(1, "MemProfiler Init done\n");
+
+ memprof_init_done = 1;
+}
+
+void MemprofInitTime() {
+ if (LIKELY(memprof_timestamp_inited))
+ return;
+ timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ memprof_init_timestamp_s = ts.tv_sec;
+ memprof_timestamp_inited = 1;
+}
+
+// Initialize as requested from some part of MemProf runtime library
+// (interceptors, allocator, etc).
+void MemprofInitFromRtl() { MemprofInitInternal(); }
+
+#if MEMPROF_DYNAMIC
+// Initialize runtime in case it's LD_PRELOAD-ed into uninstrumented executable
+// (and thus normal initializers from .preinit_array or modules haven't run).
+
+class MemprofInitializer {
+public:
+ MemprofInitializer() { MemprofInitFromRtl(); }
+};
+
+static MemprofInitializer memprof_initializer;
+#endif // MEMPROF_DYNAMIC
+
+} // namespace __memprof
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __memprof;
+
+// Initialize as requested from instrumented application code.
+void __memprof_init() {
+ MemprofInitTime();
+ MemprofInitInternal();
+}
+
+void __memprof_preinit() { MemprofInitInternal(); }
+
+void __memprof_version_mismatch_check_v1() {}
+
+void __memprof_record_access(void const volatile *addr) {
+ __memprof::RecordAccess((uptr)addr);
+}
+
+void __memprof_record_access_range(void const volatile *addr, uptr size) {
+ for (uptr a = (uptr)addr; a < (uptr)addr + size; a += kWordSize)
+ __memprof::RecordAccess(a);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE u16
+__sanitizer_unaligned_load16(const uu16 *p) {
+ __memprof_record_access(p);
+ return *p;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE u32
+__sanitizer_unaligned_load32(const uu32 *p) {
+ __memprof_record_access(p);
+ return *p;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE u64
+__sanitizer_unaligned_load64(const uu64 *p) {
+ __memprof_record_access(p);
+ return *p;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__sanitizer_unaligned_store16(uu16 *p, u16 x) {
+ __memprof_record_access(p);
+ *p = x;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__sanitizer_unaligned_store32(uu32 *p, u32 x) {
+ __memprof_record_access(p);
+ *p = x;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__sanitizer_unaligned_store64(uu64 *p, u64 x) {
+ __memprof_record_access(p);
+ *p = x;
+}
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_shadow_setup.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_shadow_setup.cpp
new file mode 100644
index 00000000000..e7832f656ee
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_shadow_setup.cpp
@@ -0,0 +1,62 @@
+//===-- memprof_shadow_setup.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// Set up the shadow memory.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+
+#include "memprof_internal.h"
+#include "memprof_mapping.h"
+
+namespace __memprof {
+
+static void ProtectGap(uptr addr, uptr size) {
+ if (!flags()->protect_shadow_gap) {
+ // The shadow gap is unprotected, so there is a chance that someone
+ // is actually using this memory. Which means it needs a shadow...
+ uptr GapShadowBeg = RoundDownTo(MEM_TO_SHADOW(addr), GetPageSizeCached());
+ uptr GapShadowEnd =
+ RoundUpTo(MEM_TO_SHADOW(addr + size), GetPageSizeCached()) - 1;
+ if (Verbosity())
+ Printf("protect_shadow_gap=0:"
+ " not protecting shadow gap, allocating gap's shadow\n"
+ "|| `[%p, %p]` || ShadowGap's shadow ||\n",
+ GapShadowBeg, GapShadowEnd);
+ ReserveShadowMemoryRange(GapShadowBeg, GapShadowEnd,
+ "unprotected gap shadow");
+ return;
+ }
+ __sanitizer::ProtectGap(addr, size, kZeroBaseShadowStart,
+ kZeroBaseMaxShadowStart);
+}
+
+void InitializeShadowMemory() {
+ uptr shadow_start = FindDynamicShadowStart();
+ // Update the shadow memory address (potentially) used by instrumentation.
+ __memprof_shadow_memory_dynamic_address = shadow_start;
+
+ if (kLowShadowBeg)
+ shadow_start -= GetMmapGranularity();
+
+ if (Verbosity())
+ PrintAddressSpaceLayout();
+
+ // mmap the low shadow plus at least one page at the left.
+ if (kLowShadowBeg)
+ ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
+ // mmap the high shadow.
+ ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
+ // protect the gap.
+ ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
+ CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
+}
+
+} // namespace __memprof
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_stack.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_stack.cpp
new file mode 100644
index 00000000000..b5beeeadafd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_stack.cpp
@@ -0,0 +1,59 @@
+//===-- memprof_stack.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// Code for MemProf stack trace.
+//===----------------------------------------------------------------------===//
+#include "memprof_stack.h"
+#include "memprof_internal.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+
+namespace __memprof {
+
+static atomic_uint32_t malloc_context_size;
+
+void SetMallocContextSize(u32 size) {
+ atomic_store(&malloc_context_size, size, memory_order_release);
+}
+
+u32 GetMallocContextSize() {
+ return atomic_load(&malloc_context_size, memory_order_acquire);
+}
+
+} // namespace __memprof
+
+void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
+ void *context,
+ bool request_fast,
+ u32 max_depth) {
+ using namespace __memprof;
+ size = 0;
+ if (UNLIKELY(!memprof_inited))
+ return;
+ request_fast = StackTrace::WillUseFastUnwind(request_fast);
+ MemprofThread *t = GetCurrentThread();
+ if (request_fast) {
+ if (t) {
+ Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(),
+ true);
+ }
+ return;
+ }
+ Unwind(max_depth, pc, bp, context, 0, 0, false);
+}
+
+// ------------------ Interface -------------- {{{1
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_print_stack_trace() {
+ using namespace __memprof;
+ PRINT_CURRENT_STACK();
+}
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_stack.h b/contrib/libs/clang16-rt/lib/memprof/memprof_stack.h
new file mode 100644
index 00000000000..a8fdfc9def9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_stack.h
@@ -0,0 +1,66 @@
+//===-- memprof_stack.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// MemProf-private header for memprof_stack.cpp.
+//===----------------------------------------------------------------------===//
+
+#ifndef MEMPROF_STACK_H
+#define MEMPROF_STACK_H
+
+#include "memprof_flags.h"
+#include "memprof_thread.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+
+namespace __memprof {
+
+static const u32 kDefaultMallocContextSize = 30;
+
+void SetMallocContextSize(u32 size);
+u32 GetMallocContextSize();
+
+} // namespace __memprof
+
+// NOTE: A Rule of thumb is to retrieve stack trace in the interceptors
+// as early as possible (in functions exposed to the user), as we generally
+// don't want stack trace to contain functions from MemProf internals.
+
+#define GET_STACK_TRACE(max_size, fast) \
+ BufferedStackTrace stack; \
+ if (max_size <= 2) { \
+ stack.size = max_size; \
+ if (max_size > 0) { \
+ stack.top_frame_bp = GET_CURRENT_FRAME(); \
+ stack.trace_buffer[0] = StackTrace::GetCurrentPc(); \
+ if (max_size > 1) \
+ stack.trace_buffer[1] = GET_CALLER_PC(); \
+ } \
+ } else { \
+ stack.Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), nullptr, \
+ fast, max_size); \
+ }
+
+#define GET_STACK_TRACE_FATAL_HERE \
+ GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal)
+
+#define GET_STACK_TRACE_THREAD GET_STACK_TRACE(kStackTraceMax, true)
+
+#define GET_STACK_TRACE_MALLOC \
+ GET_STACK_TRACE(GetMallocContextSize(), common_flags()->fast_unwind_on_malloc)
+
+#define GET_STACK_TRACE_FREE GET_STACK_TRACE_MALLOC
+
+#define PRINT_CURRENT_STACK() \
+ { \
+ GET_STACK_TRACE_FATAL_HERE; \
+ stack.Print(); \
+ }
+
+#endif // MEMPROF_STACK_H
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_stats.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_stats.cpp
new file mode 100644
index 00000000000..c8faebfa12d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_stats.cpp
@@ -0,0 +1,157 @@
+//===-- memprof_stats.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// Code related to statistics collected by MemProfiler.
+//===----------------------------------------------------------------------===//
+#include "memprof_stats.h"
+#include "memprof_interceptors.h"
+#include "memprof_internal.h"
+#include "memprof_thread.h"
+#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+namespace __memprof {
+
+MemprofStats::MemprofStats() { Clear(); }
+
+void MemprofStats::Clear() {
+ if (REAL(memset))
+ return (void)REAL(memset)(this, 0, sizeof(MemprofStats));
+ internal_memset(this, 0, sizeof(MemprofStats));
+}
+
+static void PrintMallocStatsArray(const char *prefix,
+ uptr (&array)[kNumberOfSizeClasses]) {
+ Printf("%s", prefix);
+ for (uptr i = 0; i < kNumberOfSizeClasses; i++) {
+ if (!array[i])
+ continue;
+ Printf("%zu:%zu; ", i, array[i]);
+ }
+ Printf("\n");
+}
+
+void MemprofStats::Print() {
+ Printf("Stats: %zuM malloced (%zuM for overhead) by %zu calls\n",
+ malloced >> 20, malloced_overhead >> 20, mallocs);
+ Printf("Stats: %zuM realloced by %zu calls\n", realloced >> 20, reallocs);
+ Printf("Stats: %zuM freed by %zu calls\n", freed >> 20, frees);
+ Printf("Stats: %zuM really freed by %zu calls\n", really_freed >> 20,
+ real_frees);
+ Printf("Stats: %zuM (%zuM-%zuM) mmaped; %zu maps, %zu unmaps\n",
+ (mmaped - munmaped) >> 20, mmaped >> 20, munmaped >> 20, mmaps,
+ munmaps);
+
+ PrintMallocStatsArray(" mallocs by size class: ", malloced_by_size);
+ Printf("Stats: malloc large: %zu\n", malloc_large);
+}
+
+void MemprofStats::MergeFrom(const MemprofStats *stats) {
+ uptr *dst_ptr = reinterpret_cast<uptr *>(this);
+ const uptr *src_ptr = reinterpret_cast<const uptr *>(stats);
+ uptr num_fields = sizeof(*this) / sizeof(uptr);
+ for (uptr i = 0; i < num_fields; i++)
+ dst_ptr[i] += src_ptr[i];
+}
+
+static Mutex print_lock;
+
+static MemprofStats unknown_thread_stats(LINKER_INITIALIZED);
+static MemprofStats dead_threads_stats(LINKER_INITIALIZED);
+static Mutex dead_threads_stats_lock;
+// Required for malloc_zone_statistics() on OS X. This can't be stored in
+// per-thread MemprofStats.
+static uptr max_malloced_memory;
+
+static void MergeThreadStats(ThreadContextBase *tctx_base, void *arg) {
+ MemprofStats *accumulated_stats = reinterpret_cast<MemprofStats *>(arg);
+ MemprofThreadContext *tctx = static_cast<MemprofThreadContext *>(tctx_base);
+ if (MemprofThread *t = tctx->thread)
+ accumulated_stats->MergeFrom(&t->stats());
+}
+
+static void GetAccumulatedStats(MemprofStats *stats) {
+ stats->Clear();
+ {
+ ThreadRegistryLock l(&memprofThreadRegistry());
+ memprofThreadRegistry().RunCallbackForEachThreadLocked(MergeThreadStats,
+ stats);
+ }
+ stats->MergeFrom(&unknown_thread_stats);
+ {
+ Lock lock(&dead_threads_stats_lock);
+ stats->MergeFrom(&dead_threads_stats);
+ }
+ // This is not very accurate: we may miss allocation peaks that happen
+ // between two updates of accumulated_stats_. For more accurate bookkeeping
+ // the maximum should be updated on every malloc(), which is unacceptable.
+ if (max_malloced_memory < stats->malloced) {
+ max_malloced_memory = stats->malloced;
+ }
+}
+
+void FlushToDeadThreadStats(MemprofStats *stats) {
+ Lock lock(&dead_threads_stats_lock);
+ dead_threads_stats.MergeFrom(stats);
+ stats->Clear();
+}
+
+MemprofStats &GetCurrentThreadStats() {
+ MemprofThread *t = GetCurrentThread();
+ return (t) ? t->stats() : unknown_thread_stats;
+}
+
+static void PrintAccumulatedStats() {
+ MemprofStats stats;
+ GetAccumulatedStats(&stats);
+ // Use lock to keep reports from mixing up.
+ Lock lock(&print_lock);
+ stats.Print();
+ StackDepotStats stack_depot_stats = StackDepotGetStats();
+ Printf("Stats: StackDepot: %zd ids; %zdM allocated\n",
+ stack_depot_stats.n_uniq_ids, stack_depot_stats.allocated >> 20);
+ PrintInternalAllocatorStats();
+}
+
+} // namespace __memprof
+
+// ---------------------- Interface ---------------- {{{1
+using namespace __memprof;
+
+uptr __sanitizer_get_current_allocated_bytes() {
+ MemprofStats stats;
+ GetAccumulatedStats(&stats);
+ uptr malloced = stats.malloced;
+ uptr freed = stats.freed;
+ // Return sane value if malloced < freed due to racy
+ // way we update accumulated stats.
+ return (malloced > freed) ? malloced - freed : 1;
+}
+
+uptr __sanitizer_get_heap_size() {
+ MemprofStats stats;
+ GetAccumulatedStats(&stats);
+ return stats.mmaped - stats.munmaped;
+}
+
+uptr __sanitizer_get_free_bytes() {
+ MemprofStats stats;
+ GetAccumulatedStats(&stats);
+ uptr total_free = stats.mmaped - stats.munmaped + stats.really_freed;
+ uptr total_used = stats.malloced;
+ // Return sane value if total_free < total_used due to racy
+ // way we update accumulated stats.
+ return (total_free > total_used) ? total_free - total_used : 1;
+}
+
+uptr __sanitizer_get_unmapped_bytes() { return 0; }
+
+void __memprof_print_accumulated_stats() { PrintAccumulatedStats(); }
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_stats.h b/contrib/libs/clang16-rt/lib/memprof/memprof_stats.h
new file mode 100644
index 00000000000..ebdaa190981
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_stats.h
@@ -0,0 +1,61 @@
+//===-- memprof_stats.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// MemProf-private header for statistics.
+//===----------------------------------------------------------------------===//
+#ifndef MEMPROF_STATS_H
+#define MEMPROF_STATS_H
+
+#include "memprof_allocator.h"
+#include "memprof_internal.h"
+
+namespace __memprof {
+
+// MemprofStats struct is NOT thread-safe.
+// Each MemprofThread has its own MemprofStats, which are sometimes flushed
+// to the accumulated MemprofStats.
+struct MemprofStats {
+ // MemprofStats must be a struct consisting of uptr fields only.
+ // When merging two MemprofStats structs, we treat them as arrays of uptr.
+ uptr mallocs;
+ uptr malloced;
+ uptr malloced_overhead;
+ uptr frees;
+ uptr freed;
+ uptr real_frees;
+ uptr really_freed;
+ uptr reallocs;
+ uptr realloced;
+ uptr mmaps;
+ uptr mmaped;
+ uptr munmaps;
+ uptr munmaped;
+ uptr malloc_large;
+ uptr malloced_by_size[kNumberOfSizeClasses];
+
+ // Ctor for global MemprofStats (accumulated stats for dead threads).
+ explicit MemprofStats(LinkerInitialized) {}
+ // Creates empty stats.
+ MemprofStats();
+
+ void Print(); // Prints formatted stats to stderr.
+ void Clear();
+ void MergeFrom(const MemprofStats *stats);
+};
+
+// Returns stats for GetCurrentThread(), or stats for fake "unknown thread"
+// if GetCurrentThread() returns 0.
+MemprofStats &GetCurrentThreadStats();
+// Flushes a given stats into accumulated stats of dead threads.
+void FlushToDeadThreadStats(MemprofStats *stats);
+
+} // namespace __memprof
+
+#endif // MEMPROF_STATS_H
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_thread.cpp b/contrib/libs/clang16-rt/lib/memprof/memprof_thread.cpp
new file mode 100644
index 00000000000..9512a87cf98
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_thread.cpp
@@ -0,0 +1,219 @@
+//===-- memprof_thread.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// Thread-related code.
+//===----------------------------------------------------------------------===//
+#include "memprof_thread.h"
+#include "memprof_allocator.h"
+#include "memprof_interceptors.h"
+#include "memprof_mapping.h"
+#include "memprof_stack.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+
+namespace __memprof {
+
+// MemprofThreadContext implementation.
+
+void MemprofThreadContext::OnCreated(void *arg) {
+ CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs *>(arg);
+ if (args->stack)
+ stack_id = StackDepotPut(*args->stack);
+ thread = args->thread;
+ thread->set_context(this);
+}
+
+void MemprofThreadContext::OnFinished() {
+ // Drop the link to the MemprofThread object.
+ thread = nullptr;
+}
+
+static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)];
+static ThreadRegistry *memprof_thread_registry;
+
+static Mutex mu_for_thread_context;
+static LowLevelAllocator allocator_for_thread_context;
+
+static ThreadContextBase *GetMemprofThreadContext(u32 tid) {
+ Lock lock(&mu_for_thread_context);
+ return new (allocator_for_thread_context) MemprofThreadContext(tid);
+}
+
+ThreadRegistry &memprofThreadRegistry() {
+ static bool initialized;
+ // Don't worry about thread_safety - this should be called when there is
+ // a single thread.
+ if (!initialized) {
+ // Never reuse MemProf threads: we store pointer to MemprofThreadContext
+ // in TSD and can't reliably tell when no more TSD destructors will
+ // be called. It would be wrong to reuse MemprofThreadContext for another
+ // thread before all TSD destructors will be called for it.
+ memprof_thread_registry = new (thread_registry_placeholder)
+ ThreadRegistry(GetMemprofThreadContext);
+ initialized = true;
+ }
+ return *memprof_thread_registry;
+}
+
+MemprofThreadContext *GetThreadContextByTidLocked(u32 tid) {
+ return static_cast<MemprofThreadContext *>(
+ memprofThreadRegistry().GetThreadLocked(tid));
+}
+
+// MemprofThread implementation.
+
+MemprofThread *MemprofThread::Create(thread_callback_t start_routine, void *arg,
+ u32 parent_tid, StackTrace *stack,
+ bool detached) {
+ uptr PageSize = GetPageSizeCached();
+ uptr size = RoundUpTo(sizeof(MemprofThread), PageSize);
+ MemprofThread *thread = (MemprofThread *)MmapOrDie(size, __func__);
+ thread->start_routine_ = start_routine;
+ thread->arg_ = arg;
+ MemprofThreadContext::CreateThreadContextArgs args = {thread, stack};
+ memprofThreadRegistry().CreateThread(0, detached, parent_tid, &args);
+
+ return thread;
+}
+
+void MemprofThread::TSDDtor(void *tsd) {
+ MemprofThreadContext *context = (MemprofThreadContext *)tsd;
+ VReport(1, "T%d TSDDtor\n", context->tid);
+ if (context->thread)
+ context->thread->Destroy();
+}
+
+void MemprofThread::Destroy() {
+ int tid = this->tid();
+ VReport(1, "T%d exited\n", tid);
+
+ malloc_storage().CommitBack();
+ memprofThreadRegistry().FinishThread(tid);
+ FlushToDeadThreadStats(&stats_);
+ uptr size = RoundUpTo(sizeof(MemprofThread), GetPageSizeCached());
+ UnmapOrDie(this, size);
+ DTLS_Destroy();
+}
+
+inline MemprofThread::StackBounds MemprofThread::GetStackBounds() const {
+ if (stack_bottom_ >= stack_top_)
+ return {0, 0};
+ return {stack_bottom_, stack_top_};
+}
+
+uptr MemprofThread::stack_top() { return GetStackBounds().top; }
+
+uptr MemprofThread::stack_bottom() { return GetStackBounds().bottom; }
+
+uptr MemprofThread::stack_size() {
+ const auto bounds = GetStackBounds();
+ return bounds.top - bounds.bottom;
+}
+
+void MemprofThread::Init(const InitOptions *options) {
+ CHECK_EQ(this->stack_size(), 0U);
+ SetThreadStackAndTls(options);
+ if (stack_top_ != stack_bottom_) {
+ CHECK_GT(this->stack_size(), 0U);
+ CHECK(AddrIsInMem(stack_bottom_));
+ CHECK(AddrIsInMem(stack_top_ - 1));
+ }
+ int local = 0;
+ VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(),
+ (void *)stack_bottom_, (void *)stack_top_, stack_top_ - stack_bottom_,
+ (void *)&local);
+}
+
+thread_return_t
+MemprofThread::ThreadStart(tid_t os_id,
+ atomic_uintptr_t *signal_thread_is_registered) {
+ Init();
+ memprofThreadRegistry().StartThread(tid(), os_id, ThreadType::Regular,
+ nullptr);
+ if (signal_thread_is_registered)
+ atomic_store(signal_thread_is_registered, 1, memory_order_release);
+
+ if (!start_routine_) {
+ // start_routine_ == 0 if we're on the main thread or on one of the
+ // OS X libdispatch worker threads. But nobody is supposed to call
+ // ThreadStart() for the worker threads.
+ CHECK_EQ(tid(), 0);
+ return 0;
+ }
+
+ return start_routine_(arg_);
+}
+
+MemprofThread *CreateMainThread() {
+ MemprofThread *main_thread = MemprofThread::Create(
+ /* start_routine */ nullptr, /* arg */ nullptr, /* parent_tid */ kMainTid,
+ /* stack */ nullptr, /* detached */ true);
+ SetCurrentThread(main_thread);
+ main_thread->ThreadStart(internal_getpid(),
+ /* signal_thread_is_registered */ nullptr);
+ return main_thread;
+}
+
+// This implementation doesn't use the argument, which is just passed down
+// from the caller of Init (which see, above). It's only there to support
+// OS-specific implementations that need more information passed through.
+void MemprofThread::SetThreadStackAndTls(const InitOptions *options) {
+ DCHECK_EQ(options, nullptr);
+ uptr tls_size = 0;
+ uptr stack_size = 0;
+ GetThreadStackAndTls(tid() == kMainTid, &stack_bottom_, &stack_size,
+ &tls_begin_, &tls_size);
+ stack_top_ = stack_bottom_ + stack_size;
+ tls_end_ = tls_begin_ + tls_size;
+ dtls_ = DTLS_Get();
+
+ if (stack_top_ != stack_bottom_) {
+ int local;
+ CHECK(AddrIsInStack((uptr)&local));
+ }
+}
+
+bool MemprofThread::AddrIsInStack(uptr addr) {
+ const auto bounds = GetStackBounds();
+ return addr >= bounds.bottom && addr < bounds.top;
+}
+
+MemprofThread *GetCurrentThread() {
+ MemprofThreadContext *context =
+ reinterpret_cast<MemprofThreadContext *>(TSDGet());
+ if (!context)
+ return nullptr;
+ return context->thread;
+}
+
+void SetCurrentThread(MemprofThread *t) {
+ CHECK(t->context());
+ VReport(2, "SetCurrentThread: %p for thread %p\n", (void *)t->context(),
+ (void *)GetThreadSelf());
+ // Make sure we do not reset the current MemprofThread.
+ CHECK_EQ(0, TSDGet());
+ TSDSet(t->context());
+ CHECK_EQ(t->context(), TSDGet());
+}
+
+u32 GetCurrentTidOrInvalid() {
+ MemprofThread *t = GetCurrentThread();
+ return t ? t->tid() : kInvalidTid;
+}
+
+void EnsureMainThreadIDIsCorrect() {
+ MemprofThreadContext *context =
+ reinterpret_cast<MemprofThreadContext *>(TSDGet());
+ if (context && (context->tid == kMainTid))
+ context->os_id = GetTid();
+}
+} // namespace __memprof
diff --git a/contrib/libs/clang16-rt/lib/memprof/memprof_thread.h b/contrib/libs/clang16-rt/lib/memprof/memprof_thread.h
new file mode 100644
index 00000000000..4c9313fcb36
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/memprof_thread.h
@@ -0,0 +1,135 @@
+//===-- memprof_thread.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemProfiler, a memory profiler.
+//
+// MemProf-private header for memprof_thread.cpp.
+//===----------------------------------------------------------------------===//
+
+#ifndef MEMPROF_THREAD_H
+#define MEMPROF_THREAD_H
+
+#include "memprof_allocator.h"
+#include "memprof_internal.h"
+#include "memprof_stats.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
+
+namespace __sanitizer {
+struct DTLS;
+} // namespace __sanitizer
+
+namespace __memprof {
+
+class MemprofThread;
+
+// These objects are created for every thread and are never deleted,
+// so we can find them by tid even if the thread is long dead.
+struct MemprofThreadContext final : public ThreadContextBase {
+ explicit MemprofThreadContext(int tid)
+ : ThreadContextBase(tid), announced(false),
+ destructor_iterations(GetPthreadDestructorIterations()), stack_id(0),
+ thread(nullptr) {}
+ bool announced;
+ u8 destructor_iterations;
+ u32 stack_id;
+ MemprofThread *thread;
+
+ void OnCreated(void *arg) override;
+ void OnFinished() override;
+
+ struct CreateThreadContextArgs {
+ MemprofThread *thread;
+ StackTrace *stack;
+ };
+};
+
+// MemprofThreadContext objects are never freed, so we need many of them.
+COMPILER_CHECK(sizeof(MemprofThreadContext) <= 256);
+
+// MemprofThread are stored in TSD and destroyed when the thread dies.
+class MemprofThread {
+public:
+ static MemprofThread *Create(thread_callback_t start_routine, void *arg,
+ u32 parent_tid, StackTrace *stack,
+ bool detached);
+ static void TSDDtor(void *tsd);
+ void Destroy();
+
+ struct InitOptions;
+ void Init(const InitOptions *options = nullptr);
+
+ thread_return_t ThreadStart(tid_t os_id,
+ atomic_uintptr_t *signal_thread_is_registered);
+
+ uptr stack_top();
+ uptr stack_bottom();
+ uptr stack_size();
+ uptr tls_begin() { return tls_begin_; }
+ uptr tls_end() { return tls_end_; }
+ DTLS *dtls() { return dtls_; }
+ u32 tid() { return context_->tid; }
+ MemprofThreadContext *context() { return context_; }
+ void set_context(MemprofThreadContext *context) { context_ = context; }
+
+ bool AddrIsInStack(uptr addr);
+
+ // True is this thread is currently unwinding stack (i.e. collecting a stack
+ // trace). Used to prevent deadlocks on platforms where libc unwinder calls
+ // malloc internally. See PR17116 for more details.
+ bool isUnwinding() const { return unwinding_; }
+ void setUnwinding(bool b) { unwinding_ = b; }
+
+ MemprofThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
+ MemprofStats &stats() { return stats_; }
+
+private:
+ // NOTE: There is no MemprofThread constructor. It is allocated
+ // via mmap() and *must* be valid in zero-initialized state.
+
+ void SetThreadStackAndTls(const InitOptions *options);
+
+ struct StackBounds {
+ uptr bottom;
+ uptr top;
+ };
+ StackBounds GetStackBounds() const;
+
+ MemprofThreadContext *context_;
+ thread_callback_t start_routine_;
+ void *arg_;
+
+ uptr stack_top_;
+ uptr stack_bottom_;
+
+ uptr tls_begin_;
+ uptr tls_end_;
+ DTLS *dtls_;
+
+ MemprofThreadLocalMallocStorage malloc_storage_;
+ MemprofStats stats_;
+ bool unwinding_;
+};
+
+// Returns a single instance of registry.
+ThreadRegistry &memprofThreadRegistry();
+
+// Must be called under ThreadRegistryLock.
+MemprofThreadContext *GetThreadContextByTidLocked(u32 tid);
+
+// Get the current thread. May return 0.
+MemprofThread *GetCurrentThread();
+void SetCurrentThread(MemprofThread *t);
+u32 GetCurrentTidOrInvalid();
+
+// Used to handle fork().
+void EnsureMainThreadIDIsCorrect();
+} // namespace __memprof
+
+#endif // MEMPROF_THREAD_H
diff --git a/contrib/libs/clang16-rt/lib/memprof/ya.make b/contrib/libs/clang16-rt/lib/memprof/ya.make
new file mode 100644
index 00000000000..facc1181c7f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof/ya.make
@@ -0,0 +1,134 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.memprof${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/include
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHAVE_RPC_XDR_H=0
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ interception/interception_linux.cpp
+ interception/interception_mac.cpp
+ interception/interception_type_test.cpp
+ interception/interception_win.cpp
+ memprof/memprof_allocator.cpp
+ memprof/memprof_descriptions.cpp
+ memprof/memprof_flags.cpp
+ memprof/memprof_interceptors.cpp
+ memprof/memprof_interceptors_memintrinsics.cpp
+ memprof/memprof_linux.cpp
+ memprof/memprof_malloc_linux.cpp
+ memprof/memprof_mibmap.cpp
+ memprof/memprof_posix.cpp
+ memprof/memprof_preinit.cpp
+ memprof/memprof_rawprofile.cpp
+ memprof/memprof_rtl.cpp
+ memprof/memprof_shadow_setup.cpp
+ memprof/memprof_stack.cpp
+ memprof/memprof_stats.cpp
+ memprof/memprof_thread.cpp
+ sanitizer_common/sancov_flags.cpp
+ sanitizer_common/sanitizer_allocator.cpp
+ sanitizer_common/sanitizer_allocator_checks.cpp
+ sanitizer_common/sanitizer_allocator_report.cpp
+ sanitizer_common/sanitizer_chained_origin_depot.cpp
+ sanitizer_common/sanitizer_common.cpp
+ sanitizer_common/sanitizer_common_libcdep.cpp
+ sanitizer_common/sanitizer_coverage_fuchsia.cpp
+ sanitizer_common/sanitizer_coverage_libcdep_new.cpp
+ sanitizer_common/sanitizer_coverage_win_sections.cpp
+ sanitizer_common/sanitizer_deadlock_detector1.cpp
+ sanitizer_common/sanitizer_deadlock_detector2.cpp
+ sanitizer_common/sanitizer_errno.cpp
+ sanitizer_common/sanitizer_file.cpp
+ sanitizer_common/sanitizer_flag_parser.cpp
+ sanitizer_common/sanitizer_flags.cpp
+ sanitizer_common/sanitizer_fuchsia.cpp
+ sanitizer_common/sanitizer_libc.cpp
+ sanitizer_common/sanitizer_libignore.cpp
+ sanitizer_common/sanitizer_linux.cpp
+ sanitizer_common/sanitizer_linux_libcdep.cpp
+ sanitizer_common/sanitizer_linux_s390.cpp
+ sanitizer_common/sanitizer_mac.cpp
+ sanitizer_common/sanitizer_mac_libcdep.cpp
+ sanitizer_common/sanitizer_mutex.cpp
+ sanitizer_common/sanitizer_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+ sanitizer_common/sanitizer_platform_limits_linux.cpp
+ sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_posix.cpp
+ sanitizer_common/sanitizer_platform_limits_solaris.cpp
+ sanitizer_common/sanitizer_posix.cpp
+ sanitizer_common/sanitizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_printf.cpp
+ sanitizer_common/sanitizer_procmaps_bsd.cpp
+ sanitizer_common/sanitizer_procmaps_common.cpp
+ sanitizer_common/sanitizer_procmaps_fuchsia.cpp
+ sanitizer_common/sanitizer_procmaps_linux.cpp
+ sanitizer_common/sanitizer_procmaps_mac.cpp
+ sanitizer_common/sanitizer_procmaps_solaris.cpp
+ sanitizer_common/sanitizer_solaris.cpp
+ sanitizer_common/sanitizer_stack_store.cpp
+ sanitizer_common/sanitizer_stackdepot.cpp
+ sanitizer_common/sanitizer_stacktrace.cpp
+ sanitizer_common/sanitizer_stacktrace_libcdep.cpp
+ sanitizer_common/sanitizer_stacktrace_printer.cpp
+ sanitizer_common/sanitizer_stacktrace_sparc.cpp
+ sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
+ sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_mac.cpp
+ sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_win.cpp
+ sanitizer_common/sanitizer_suppressions.cpp
+ sanitizer_common/sanitizer_symbolizer.cpp
+ sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
+ sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_mac.cpp
+ sanitizer_common/sanitizer_symbolizer_markup.cpp
+ sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_report.cpp
+ sanitizer_common/sanitizer_symbolizer_win.cpp
+ sanitizer_common/sanitizer_termination.cpp
+ sanitizer_common/sanitizer_thread_registry.cpp
+ sanitizer_common/sanitizer_tls_get_addr.cpp
+ sanitizer_common/sanitizer_type_traits.cpp
+ sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
+ sanitizer_common/sanitizer_unwind_win.cpp
+ sanitizer_common/sanitizer_win.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/memprof_cxx/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/memprof_cxx/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof_cxx/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/memprof_cxx/ya.make b/contrib/libs/clang16-rt/lib/memprof_cxx/ya.make
new file mode 100644
index 00000000000..9bd65a4cc98
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/memprof_cxx/ya.make
@@ -0,0 +1,45 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.memprof_cxx${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib/memprof)
+
+SRCS(
+ memprof_new_delete.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/msan/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/msan/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/msan/msan.cpp b/contrib/libs/clang16-rt/lib/msan/msan.cpp
new file mode 100644
index 00000000000..3e3bc3cb979
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan.cpp
@@ -0,0 +1,745 @@
+//===-- msan.cpp ----------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+// MemorySanitizer runtime.
+//===----------------------------------------------------------------------===//
+
+#include "msan.h"
+
+#include "msan_chained_origin_depot.h"
+#include "msan_origin.h"
+#include "msan_poisoning.h"
+#include "msan_report.h"
+#include "msan_thread.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_interface_internal.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+#include "ubsan/ubsan_flags.h"
+#include "ubsan/ubsan_init.h"
+
+// ACHTUNG! No system header includes in this file.
+
+using namespace __sanitizer;
+
+// Globals.
+static THREADLOCAL int msan_expect_umr = 0;
+static THREADLOCAL int msan_expected_umr_found = 0;
+
+// Function argument shadow. Each argument starts at the next available 8-byte
+// aligned address.
+SANITIZER_INTERFACE_ATTRIBUTE
+THREADLOCAL u64 __msan_param_tls[kMsanParamTlsSize / sizeof(u64)];
+
+// Function argument origin. Each argument starts at the same offset as the
+// corresponding shadow in (__msan_param_tls). Slightly weird, but changing this
+// would break compatibility with older prebuilt binaries.
+SANITIZER_INTERFACE_ATTRIBUTE
+THREADLOCAL u32 __msan_param_origin_tls[kMsanParamTlsSize / sizeof(u32)];
+
+SANITIZER_INTERFACE_ATTRIBUTE
+THREADLOCAL u64 __msan_retval_tls[kMsanRetvalTlsSize / sizeof(u64)];
+
+SANITIZER_INTERFACE_ATTRIBUTE
+THREADLOCAL u32 __msan_retval_origin_tls;
+
+SANITIZER_INTERFACE_ATTRIBUTE
+ALIGNED(16) THREADLOCAL u64 __msan_va_arg_tls[kMsanParamTlsSize / sizeof(u64)];
+
+SANITIZER_INTERFACE_ATTRIBUTE
+ALIGNED(16)
+THREADLOCAL u32 __msan_va_arg_origin_tls[kMsanParamTlsSize / sizeof(u32)];
+
+SANITIZER_INTERFACE_ATTRIBUTE
+THREADLOCAL u64 __msan_va_arg_overflow_size_tls;
+
+SANITIZER_INTERFACE_ATTRIBUTE
+THREADLOCAL u32 __msan_origin_tls;
+
+extern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_track_origins;
+
+int __msan_get_track_origins() {
+ return &__msan_track_origins ? __msan_track_origins : 0;
+}
+
+extern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_keep_going;
+
+namespace __msan {
+
+static THREADLOCAL int is_in_symbolizer_or_unwinder;
+static void EnterSymbolizerOrUnwider() { ++is_in_symbolizer_or_unwinder; }
+static void ExitSymbolizerOrUnwider() { --is_in_symbolizer_or_unwinder; }
+bool IsInSymbolizerOrUnwider() { return is_in_symbolizer_or_unwinder; }
+
+struct UnwinderScope {
+ UnwinderScope() { EnterSymbolizerOrUnwider(); }
+ ~UnwinderScope() { ExitSymbolizerOrUnwider(); }
+};
+
+static Flags msan_flags;
+
+Flags *flags() { return &msan_flags; }
+
+int msan_inited = 0;
+bool msan_init_is_running;
+
+int msan_report_count = 0;
+
+// Array of stack origins.
+// FIXME: make it resizable.
+static const uptr kNumStackOriginDescrs = 1024 * 1024;
+static const char *StackOriginDescr[kNumStackOriginDescrs];
+static uptr StackOriginPC[kNumStackOriginDescrs];
+static atomic_uint32_t NumStackOriginDescrs;
+
+void Flags::SetDefaults() {
+#define MSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "msan_flags.inc"
+#undef MSAN_FLAG
+}
+
+// keep_going is an old name for halt_on_error,
+// and it has inverse meaning.
+class FlagHandlerKeepGoing final : public FlagHandlerBase {
+ bool *halt_on_error_;
+
+ public:
+ explicit FlagHandlerKeepGoing(bool *halt_on_error)
+ : halt_on_error_(halt_on_error) {}
+ bool Parse(const char *value) final {
+ bool tmp;
+ FlagHandler<bool> h(&tmp);
+ if (!h.Parse(value)) return false;
+ *halt_on_error_ = !tmp;
+ return true;
+ }
+ bool Format(char *buffer, uptr size) final {
+ const char *keep_going_str = (*halt_on_error_) ? "false" : "true";
+ return FormatString(buffer, size, keep_going_str);
+ }
+};
+
+static void RegisterMsanFlags(FlagParser *parser, Flags *f) {
+#define MSAN_FLAG(Type, Name, DefaultValue, Description) \
+ RegisterFlag(parser, #Name, Description, &f->Name);
+#include "msan_flags.inc"
+#undef MSAN_FLAG
+
+ FlagHandlerKeepGoing *fh_keep_going =
+ new (FlagParser::Alloc) FlagHandlerKeepGoing(&f->halt_on_error);
+ parser->RegisterHandler("keep_going", fh_keep_going,
+ "deprecated, use halt_on_error");
+}
+
+static void InitializeFlags() {
+ SetCommonFlagsDefaults();
+ {
+ CommonFlags cf;
+ cf.CopyFrom(*common_flags());
+ cf.external_symbolizer_path = GetEnv("MSAN_SYMBOLIZER_PATH");
+ cf.malloc_context_size = 20;
+ cf.handle_ioctl = true;
+ // FIXME: test and enable.
+ cf.check_printf = false;
+ cf.intercept_tls_get_addr = true;
+ OverrideCommonFlags(cf);
+ }
+
+ Flags *f = flags();
+ f->SetDefaults();
+
+ FlagParser parser;
+ RegisterMsanFlags(&parser, f);
+ RegisterCommonFlags(&parser);
+
+#if MSAN_CONTAINS_UBSAN
+ __ubsan::Flags *uf = __ubsan::flags();
+ uf->SetDefaults();
+
+ FlagParser ubsan_parser;
+ __ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
+ RegisterCommonFlags(&ubsan_parser);
+#endif
+
+ // Override from user-specified string.
+ parser.ParseString(__msan_default_options());
+#if MSAN_CONTAINS_UBSAN
+ const char *ubsan_default_options = __ubsan_default_options();
+ ubsan_parser.ParseString(ubsan_default_options);
+#endif
+
+ parser.ParseStringFromEnv("MSAN_OPTIONS");
+#if MSAN_CONTAINS_UBSAN
+ ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
+#endif
+
+ InitializeCommonFlags();
+
+ if (Verbosity()) ReportUnrecognizedFlags();
+
+ if (common_flags()->help) parser.PrintFlagDescriptions();
+
+ // Check if deprecated exit_code MSan flag is set.
+ if (f->exit_code != -1) {
+ if (Verbosity())
+ Printf("MSAN_OPTIONS=exit_code is deprecated! "
+ "Please use MSAN_OPTIONS=exitcode instead.\n");
+ CommonFlags cf;
+ cf.CopyFrom(*common_flags());
+ cf.exitcode = f->exit_code;
+ OverrideCommonFlags(cf);
+ }
+
+ // Check flag values:
+ if (f->origin_history_size < 0 ||
+ f->origin_history_size > Origin::kMaxDepth) {
+ Printf(
+ "Origin history size invalid: %d. Must be 0 (unlimited) or in [1, %d] "
+ "range.\n",
+ f->origin_history_size, Origin::kMaxDepth);
+ Die();
+ }
+ // Limiting to kStackDepotMaxUseCount / 2 to avoid overflow in
+ // StackDepotHandle::inc_use_count_unsafe.
+ if (f->origin_history_per_stack_limit < 0 ||
+ f->origin_history_per_stack_limit > kStackDepotMaxUseCount / 2) {
+ Printf(
+ "Origin per-stack limit invalid: %d. Must be 0 (unlimited) or in [1, "
+ "%d] range.\n",
+ f->origin_history_per_stack_limit, kStackDepotMaxUseCount / 2);
+ Die();
+ }
+ if (f->store_context_size < 1) f->store_context_size = 1;
+}
+
+void PrintWarningWithOrigin(uptr pc, uptr bp, u32 origin) {
+ if (msan_expect_umr) {
+ // Printf("Expected UMR\n");
+ __msan_origin_tls = origin;
+ msan_expected_umr_found = 1;
+ return;
+ }
+
+ ++msan_report_count;
+
+ GET_FATAL_STACK_TRACE_PC_BP(pc, bp);
+
+ u32 report_origin =
+ (__msan_get_track_origins() && Origin::isValidId(origin)) ? origin : 0;
+ ReportUMR(&stack, report_origin);
+
+ if (__msan_get_track_origins() && !Origin::isValidId(origin)) {
+ Printf(
+ " ORIGIN: invalid (%x). Might be a bug in MemorySanitizer origin "
+ "tracking.\n This could still be a bug in your code, too!\n",
+ origin);
+ }
+}
+
+void UnpoisonParam(uptr n) {
+ internal_memset(__msan_param_tls, 0, n * sizeof(*__msan_param_tls));
+}
+
+// Backup MSan runtime TLS state.
+// Implementation must be async-signal-safe.
+// Instances of this class may live on the signal handler stack, and data size
+// may be an issue.
+void ScopedThreadLocalStateBackup::Backup() {
+ va_arg_overflow_size_tls = __msan_va_arg_overflow_size_tls;
+}
+
+void ScopedThreadLocalStateBackup::Restore() {
+ // A lame implementation that only keeps essential state and resets the rest.
+ __msan_va_arg_overflow_size_tls = va_arg_overflow_size_tls;
+
+ internal_memset(__msan_param_tls, 0, sizeof(__msan_param_tls));
+ internal_memset(__msan_retval_tls, 0, sizeof(__msan_retval_tls));
+ internal_memset(__msan_va_arg_tls, 0, sizeof(__msan_va_arg_tls));
+ internal_memset(__msan_va_arg_origin_tls, 0,
+ sizeof(__msan_va_arg_origin_tls));
+
+ if (__msan_get_track_origins()) {
+ internal_memset(&__msan_retval_origin_tls, 0,
+ sizeof(__msan_retval_origin_tls));
+ internal_memset(__msan_param_origin_tls, 0,
+ sizeof(__msan_param_origin_tls));
+ }
+}
+
+void UnpoisonThreadLocalState() {
+}
+
+const char *GetStackOriginDescr(u32 id, uptr *pc) {
+ CHECK_LT(id, kNumStackOriginDescrs);
+ if (pc) *pc = StackOriginPC[id];
+ return StackOriginDescr[id];
+}
+
+u32 ChainOrigin(u32 id, StackTrace *stack) {
+ MsanThread *t = GetCurrentThread();
+ if (t && t->InSignalHandler())
+ return id;
+
+ Origin o = Origin::FromRawId(id);
+ stack->tag = StackTrace::TAG_UNKNOWN;
+ Origin chained = Origin::CreateChainedOrigin(o, stack);
+ return chained.raw_id();
+}
+
+// Current implementation separates the 'id_ptr' from the 'descr' and makes
+// 'descr' constant.
+// Previous implementation 'descr' is created at compile time and contains
+// '----' in the beginning. When we see descr for the first time we replace
+// '----' with a uniq id and set the origin to (id | (31-th bit)).
+static inline void SetAllocaOrigin(void *a, uptr size, u32 *id_ptr, char *descr,
+ uptr pc) {
+ static const u32 dash = '-';
+ static const u32 first_timer =
+ dash + (dash << 8) + (dash << 16) + (dash << 24);
+ u32 id = *id_ptr;
+ if (id == 0 || id == first_timer) {
+ u32 idx = atomic_fetch_add(&NumStackOriginDescrs, 1, memory_order_relaxed);
+ CHECK_LT(idx, kNumStackOriginDescrs);
+ StackOriginDescr[idx] = descr;
+ StackOriginPC[idx] = pc;
+ id = Origin::CreateStackOrigin(idx).raw_id();
+ *id_ptr = id;
+ }
+ __msan_set_origin(a, size, id);
+}
+
+} // namespace __msan
+
+void __sanitizer::BufferedStackTrace::UnwindImpl(
+ uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
+ using namespace __msan;
+ MsanThread *t = GetCurrentThread();
+ if (!t || !StackTrace::WillUseFastUnwind(request_fast)) {
+ // Block reports from our interceptors during _Unwind_Backtrace.
+ UnwinderScope sym_scope;
+ return Unwind(max_depth, pc, bp, context, t ? t->stack_top() : 0,
+ t ? t->stack_bottom() : 0, false);
+ }
+ if (StackTrace::WillUseFastUnwind(request_fast))
+ Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), true);
+ else
+ Unwind(max_depth, pc, 0, context, 0, 0, false);
+}
+
+// Interface.
+
+using namespace __msan;
+
+#define MSAN_MAYBE_WARNING(type, size) \
+ void __msan_maybe_warning_##size(type s, u32 o) { \
+ GET_CALLER_PC_BP_SP; \
+ (void) sp; \
+ if (UNLIKELY(s)) { \
+ PrintWarningWithOrigin(pc, bp, o); \
+ if (__msan::flags()->halt_on_error) { \
+ Printf("Exiting\n"); \
+ Die(); \
+ } \
+ } \
+ }
+
+MSAN_MAYBE_WARNING(u8, 1)
+MSAN_MAYBE_WARNING(u16, 2)
+MSAN_MAYBE_WARNING(u32, 4)
+MSAN_MAYBE_WARNING(u64, 8)
+
+#define MSAN_MAYBE_STORE_ORIGIN(type, size) \
+ void __msan_maybe_store_origin_##size(type s, void *p, u32 o) { \
+ if (UNLIKELY(s)) { \
+ if (__msan_get_track_origins() > 1) { \
+ GET_CALLER_PC_BP_SP; \
+ (void) sp; \
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp); \
+ o = ChainOrigin(o, &stack); \
+ } \
+ *(u32 *)MEM_TO_ORIGIN((uptr)p & ~3UL) = o; \
+ } \
+ }
+
+MSAN_MAYBE_STORE_ORIGIN(u8, 1)
+MSAN_MAYBE_STORE_ORIGIN(u16, 2)
+MSAN_MAYBE_STORE_ORIGIN(u32, 4)
+MSAN_MAYBE_STORE_ORIGIN(u64, 8)
+
+void __msan_warning() {
+ GET_CALLER_PC_BP_SP;
+ (void)sp;
+ PrintWarningWithOrigin(pc, bp, 0);
+ if (__msan::flags()->halt_on_error) {
+ if (__msan::flags()->print_stats)
+ ReportStats();
+ Printf("Exiting\n");
+ Die();
+ }
+}
+
+void __msan_warning_noreturn() {
+ GET_CALLER_PC_BP_SP;
+ (void)sp;
+ PrintWarningWithOrigin(pc, bp, 0);
+ if (__msan::flags()->print_stats)
+ ReportStats();
+ Printf("Exiting\n");
+ Die();
+}
+
+void __msan_warning_with_origin(u32 origin) {
+ GET_CALLER_PC_BP_SP;
+ (void)sp;
+ PrintWarningWithOrigin(pc, bp, origin);
+ if (__msan::flags()->halt_on_error) {
+ if (__msan::flags()->print_stats)
+ ReportStats();
+ Printf("Exiting\n");
+ Die();
+ }
+}
+
+void __msan_warning_with_origin_noreturn(u32 origin) {
+ GET_CALLER_PC_BP_SP;
+ (void)sp;
+ PrintWarningWithOrigin(pc, bp, origin);
+ if (__msan::flags()->print_stats)
+ ReportStats();
+ Printf("Exiting\n");
+ Die();
+}
+
+static void OnStackUnwind(const SignalContext &sig, const void *,
+ BufferedStackTrace *stack) {
+ stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
+ common_flags()->fast_unwind_on_fatal);
+}
+
+static void MsanOnDeadlySignal(int signo, void *siginfo, void *context) {
+ HandleDeadlySignal(siginfo, context, GetTid(), &OnStackUnwind, nullptr);
+}
+
+static void CheckUnwind() {
+ GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME());
+ stack.Print();
+}
+
+void __msan_init() {
+ CHECK(!msan_init_is_running);
+ if (msan_inited) return;
+ msan_init_is_running = 1;
+ SanitizerToolName = "MemorySanitizer";
+
+ AvoidCVE_2016_2143();
+
+ CacheBinaryName();
+ InitializeFlags();
+
+ // Install tool-specific callbacks in sanitizer_common.
+ SetCheckUnwindCallback(CheckUnwind);
+
+ __sanitizer_set_report_path(common_flags()->log_path);
+
+ InitializeInterceptors();
+ CheckASLR();
+ InitTlsSize();
+ InstallDeadlySignalHandlers(MsanOnDeadlySignal);
+ InstallAtExitHandler(); // Needs __cxa_atexit interceptor.
+
+ DisableCoreDumperIfNecessary();
+ if (StackSizeIsUnlimited()) {
+ VPrintf(1, "Unlimited stack, doing reexec\n");
+ // A reasonably large stack size. It is bigger than the usual 8Mb, because,
+ // well, the program could have been run with unlimited stack for a reason.
+ SetStackSizeLimitInBytes(32 * 1024 * 1024);
+ ReExec();
+ }
+
+ __msan_clear_on_return();
+ if (__msan_get_track_origins())
+ VPrintf(1, "msan_track_origins\n");
+ if (!InitShadow(__msan_get_track_origins())) {
+ Printf("FATAL: MemorySanitizer can not mmap the shadow memory.\n");
+ Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n");
+ Printf("FATAL: Disabling ASLR is known to cause this error.\n");
+ Printf("FATAL: If running under GDB, try "
+ "'set disable-randomization off'.\n");
+ DumpProcessMap();
+ Die();
+ }
+
+ Symbolizer::GetOrInit()->AddHooks(EnterSymbolizerOrUnwider,
+ ExitSymbolizerOrUnwider);
+
+ InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
+
+ MsanTSDInit(MsanTSDDtor);
+
+ MsanAllocatorInit();
+
+ MsanThread *main_thread = MsanThread::Create(nullptr, nullptr);
+ SetCurrentThread(main_thread);
+ main_thread->Init();
+
+#if MSAN_CONTAINS_UBSAN
+ __ubsan::InitAsPlugin();
+#endif
+
+ VPrintf(1, "MemorySanitizer init done\n");
+
+ msan_init_is_running = 0;
+ msan_inited = 1;
+}
+
+void __msan_set_keep_going(int keep_going) {
+ flags()->halt_on_error = !keep_going;
+}
+
+void __msan_set_expect_umr(int expect_umr) {
+ if (expect_umr) {
+ msan_expected_umr_found = 0;
+ } else if (!msan_expected_umr_found) {
+ GET_CALLER_PC_BP_SP;
+ (void)sp;
+ GET_FATAL_STACK_TRACE_PC_BP(pc, bp);
+ ReportExpectedUMRNotFound(&stack);
+ Die();
+ }
+ msan_expect_umr = expect_umr;
+}
+
+void __msan_print_shadow(const void *x, uptr size) {
+ if (!MEM_IS_APP(x)) {
+ Printf("Not a valid application address: %p\n", x);
+ return;
+ }
+
+ DescribeMemoryRange(x, size);
+}
+
+void __msan_dump_shadow(const void *x, uptr size) {
+ if (!MEM_IS_APP(x)) {
+ Printf("Not a valid application address: %p\n", x);
+ return;
+ }
+
+ unsigned char *s = (unsigned char*)MEM_TO_SHADOW(x);
+ Printf("%p[%p] ", (void *)s, x);
+ for (uptr i = 0; i < size; i++)
+ Printf("%x%x ", s[i] >> 4, s[i] & 0xf);
+ Printf("\n");
+}
+
+sptr __msan_test_shadow(const void *x, uptr size) {
+ if (!MEM_IS_APP(x)) return -1;
+ unsigned char *s = (unsigned char *)MEM_TO_SHADOW((uptr)x);
+ if (__sanitizer::mem_is_zero((const char *)s, size))
+ return -1;
+ // Slow path: loop through again to find the location.
+ for (uptr i = 0; i < size; ++i)
+ if (s[i])
+ return i;
+ return -1;
+}
+
+void __msan_check_mem_is_initialized(const void *x, uptr size) {
+ if (!__msan::flags()->report_umrs) return;
+ sptr offset = __msan_test_shadow(x, size);
+ if (offset < 0)
+ return;
+
+ GET_CALLER_PC_BP_SP;
+ (void)sp;
+ ReportUMRInsideAddressRange(__func__, x, size, offset);
+ __msan::PrintWarningWithOrigin(pc, bp,
+ __msan_get_origin(((const char *)x) + offset));
+ if (__msan::flags()->halt_on_error) {
+ Printf("Exiting\n");
+ Die();
+ }
+}
+
+int __msan_set_poison_in_malloc(int do_poison) {
+ int old = flags()->poison_in_malloc;
+ flags()->poison_in_malloc = do_poison;
+ return old;
+}
+
+int __msan_has_dynamic_component() { return false; }
+
+NOINLINE
+void __msan_clear_on_return() {
+ __msan_param_tls[0] = 0;
+}
+
+void __msan_partial_poison(const void* data, void* shadow, uptr size) {
+ internal_memcpy((void*)MEM_TO_SHADOW((uptr)data), shadow, size);
+}
+
+void __msan_load_unpoisoned(const void *src, uptr size, void *dst) {
+ internal_memcpy(dst, src, size);
+ __msan_unpoison(dst, size);
+}
+
+void __msan_set_origin(const void *a, uptr size, u32 origin) {
+ if (__msan_get_track_origins()) SetOrigin(a, size, origin);
+}
+
+void __msan_set_alloca_origin(void *a, uptr size, char *descr) {
+ SetAllocaOrigin(a, size, reinterpret_cast<u32 *>(descr), descr + 4,
+ GET_CALLER_PC());
+}
+
+void __msan_set_alloca_origin4(void *a, uptr size, char *descr, uptr pc) {
+ // Intentionally ignore pc and use return address. This function is here for
+ // compatibility, in case program is linked with library instrumented by
+ // older clang.
+ SetAllocaOrigin(a, size, reinterpret_cast<u32 *>(descr), descr + 4,
+ GET_CALLER_PC());
+}
+
+void __msan_set_alloca_origin_with_descr(void *a, uptr size, u32 *id_ptr,
+ char *descr) {
+ SetAllocaOrigin(a, size, id_ptr, descr, GET_CALLER_PC());
+}
+
+void __msan_set_alloca_origin_no_descr(void *a, uptr size, u32 *id_ptr) {
+ SetAllocaOrigin(a, size, id_ptr, nullptr, GET_CALLER_PC());
+}
+
+u32 __msan_chain_origin(u32 id) {
+ GET_CALLER_PC_BP_SP;
+ (void)sp;
+ GET_STORE_STACK_TRACE_PC_BP(pc, bp);
+ return ChainOrigin(id, &stack);
+}
+
+u32 __msan_get_origin(const void *a) {
+ if (!__msan_get_track_origins()) return 0;
+ uptr x = (uptr)a;
+ uptr aligned = x & ~3ULL;
+ uptr origin_ptr = MEM_TO_ORIGIN(aligned);
+ return *(u32*)origin_ptr;
+}
+
+int __msan_origin_is_descendant_or_same(u32 this_id, u32 prev_id) {
+ Origin o = Origin::FromRawId(this_id);
+ while (o.raw_id() != prev_id && o.isChainedOrigin())
+ o = o.getNextChainedOrigin(nullptr);
+ return o.raw_id() == prev_id;
+}
+
+u32 __msan_get_umr_origin() {
+ return __msan_origin_tls;
+}
+
+u16 __sanitizer_unaligned_load16(const uu16 *p) {
+ internal_memcpy(&__msan_retval_tls[0], (void *)MEM_TO_SHADOW((uptr)p),
+ sizeof(uu16));
+ if (__msan_get_track_origins())
+ __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p));
+ return *p;
+}
+u32 __sanitizer_unaligned_load32(const uu32 *p) {
+ internal_memcpy(&__msan_retval_tls[0], (void *)MEM_TO_SHADOW((uptr)p),
+ sizeof(uu32));
+ if (__msan_get_track_origins())
+ __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p));
+ return *p;
+}
+u64 __sanitizer_unaligned_load64(const uu64 *p) {
+ internal_memcpy(&__msan_retval_tls[0], (void *)MEM_TO_SHADOW((uptr)p),
+ sizeof(uu64));
+ if (__msan_get_track_origins())
+ __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p));
+ return *p;
+}
+void __sanitizer_unaligned_store16(uu16 *p, u16 x) {
+ static_assert(sizeof(uu16) == sizeof(u16), "incompatible types");
+ u16 s;
+ internal_memcpy(&s, &__msan_param_tls[1], sizeof(uu16));
+ internal_memcpy((void *)MEM_TO_SHADOW((uptr)p), &s, sizeof(uu16));
+ if (s && __msan_get_track_origins())
+ if (uu32 o = __msan_param_origin_tls[2])
+ SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o);
+ *p = x;
+}
+void __sanitizer_unaligned_store32(uu32 *p, u32 x) {
+ static_assert(sizeof(uu32) == sizeof(u32), "incompatible types");
+ u32 s;
+ internal_memcpy(&s, &__msan_param_tls[1], sizeof(uu32));
+ internal_memcpy((void *)MEM_TO_SHADOW((uptr)p), &s, sizeof(uu32));
+ if (s && __msan_get_track_origins())
+ if (uu32 o = __msan_param_origin_tls[2])
+ SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o);
+ *p = x;
+}
+void __sanitizer_unaligned_store64(uu64 *p, u64 x) {
+ u64 s = __msan_param_tls[1];
+ *(uu64 *)MEM_TO_SHADOW((uptr)p) = s;
+ if (s && __msan_get_track_origins())
+ if (uu32 o = __msan_param_origin_tls[2])
+ SetOriginIfPoisoned((uptr)p, (uptr)&s, sizeof(s), o);
+ *p = x;
+}
+
+void __msan_set_death_callback(void (*callback)(void)) {
+ SetUserDieCallback(callback);
+}
+
+void __msan_start_switch_fiber(const void *bottom, uptr size) {
+ MsanThread *t = GetCurrentThread();
+ if (!t) {
+ VReport(1, "__msan_start_switch_fiber called from unknown thread\n");
+ return;
+ }
+ t->StartSwitchFiber((uptr)bottom, size);
+}
+
+void __msan_finish_switch_fiber(const void **bottom_old, uptr *size_old) {
+ MsanThread *t = GetCurrentThread();
+ if (!t) {
+ VReport(1, "__msan_finish_switch_fiber called from unknown thread\n");
+ return;
+ }
+ t->FinishSwitchFiber((uptr *)bottom_old, (uptr *)size_old);
+
+ internal_memset(__msan_param_tls, 0, sizeof(__msan_param_tls));
+ internal_memset(__msan_retval_tls, 0, sizeof(__msan_retval_tls));
+ internal_memset(__msan_va_arg_tls, 0, sizeof(__msan_va_arg_tls));
+
+ if (__msan_get_track_origins()) {
+ internal_memset(__msan_param_origin_tls, 0,
+ sizeof(__msan_param_origin_tls));
+ internal_memset(&__msan_retval_origin_tls, 0,
+ sizeof(__msan_retval_origin_tls));
+ internal_memset(__msan_va_arg_origin_tls, 0,
+ sizeof(__msan_va_arg_origin_tls));
+ }
+}
+
+SANITIZER_INTERFACE_WEAK_DEF(const char *, __msan_default_options, void) {
+ return "";
+}
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_print_stack_trace() {
+ GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME());
+ stack.Print();
+}
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/msan/msan.h b/contrib/libs/clang16-rt/lib/msan/msan.h
new file mode 100644
index 00000000000..5d8ea52668a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan.h
@@ -0,0 +1,318 @@
+//===-- msan.h --------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+// Private MSan header.
+//===----------------------------------------------------------------------===//
+
+#ifndef MSAN_H
+#define MSAN_H
+
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "msan_interface_internal.h"
+#include "msan_flags.h"
+#include "ubsan/ubsan_platform.h"
+
+#ifndef MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
+# define MSAN_REPLACE_OPERATORS_NEW_AND_DELETE 1
+#endif
+
+#ifndef MSAN_CONTAINS_UBSAN
+# define MSAN_CONTAINS_UBSAN CAN_SANITIZE_UB
+#endif
+
+struct MappingDesc {
+ uptr start;
+ uptr end;
+ enum Type {
+ INVALID, APP, SHADOW, ORIGIN
+ } type;
+ const char *name;
+};
+
+
+#if SANITIZER_LINUX && defined(__mips64)
+
+// MIPS64 maps:
+// - 0x0000000000-0x0200000000: Program own segments
+// - 0xa200000000-0xc000000000: PIE program segments
+// - 0xe200000000-0xffffffffff: libraries segments.
+const MappingDesc kMemoryLayout[] = {
+ {0x000000000000ULL, 0x000200000000ULL, MappingDesc::APP, "app-1"},
+ {0x000200000000ULL, 0x002200000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x002200000000ULL, 0x004000000000ULL, MappingDesc::SHADOW, "shadow-2"},
+ {0x004000000000ULL, 0x004200000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x004200000000ULL, 0x006000000000ULL, MappingDesc::ORIGIN, "origin-2"},
+ {0x006000000000ULL, 0x006200000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x006200000000ULL, 0x008000000000ULL, MappingDesc::SHADOW, "shadow-3"},
+ {0x008000000000ULL, 0x008200000000ULL, MappingDesc::SHADOW, "shadow-1"},
+ {0x008200000000ULL, 0x00a000000000ULL, MappingDesc::ORIGIN, "origin-3"},
+ {0x00a000000000ULL, 0x00a200000000ULL, MappingDesc::ORIGIN, "origin-1"},
+ {0x00a200000000ULL, 0x00c000000000ULL, MappingDesc::APP, "app-2"},
+ {0x00c000000000ULL, 0x00e200000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x00e200000000ULL, 0x00ffffffffffULL, MappingDesc::APP, "app-3"}};
+
+#define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x8000000000ULL)
+#define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x2000000000ULL)
+
+#elif SANITIZER_LINUX && defined(__aarch64__)
+
+// The mapping assumes 48-bit VMA. AArch64 maps:
+// - 0x0000000000000-0x0100000000000: 39/42/48-bits program own segments
+// - 0x0a00000000000-0x0b00000000000: 48-bits PIE program segments
+// Ideally, this would extend to 0x0c00000000000 (2^45 bytes - the
+// maximum ASLR region for 48-bit VMA) but it is too hard to fit in
+// the larger app/shadow/origin regions.
+// - 0x0e00000000000-0x1000000000000: 48-bits libraries segments
+const MappingDesc kMemoryLayout[] = {
+ {0X0000000000000, 0X0100000000000, MappingDesc::APP, "app-10-13"},
+ {0X0100000000000, 0X0200000000000, MappingDesc::SHADOW, "shadow-14"},
+ {0X0200000000000, 0X0300000000000, MappingDesc::INVALID, "invalid"},
+ {0X0300000000000, 0X0400000000000, MappingDesc::ORIGIN, "origin-14"},
+ {0X0400000000000, 0X0600000000000, MappingDesc::SHADOW, "shadow-15"},
+ {0X0600000000000, 0X0800000000000, MappingDesc::ORIGIN, "origin-15"},
+ {0X0800000000000, 0X0A00000000000, MappingDesc::INVALID, "invalid"},
+ {0X0A00000000000, 0X0B00000000000, MappingDesc::APP, "app-14"},
+ {0X0B00000000000, 0X0C00000000000, MappingDesc::SHADOW, "shadow-10-13"},
+ {0X0C00000000000, 0X0D00000000000, MappingDesc::INVALID, "invalid"},
+ {0X0D00000000000, 0X0E00000000000, MappingDesc::ORIGIN, "origin-10-13"},
+ {0X0E00000000000, 0X1000000000000, MappingDesc::APP, "app-15"},
+};
+# define MEM_TO_SHADOW(mem) ((uptr)mem ^ 0xB00000000000ULL)
+# define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x200000000000ULL)
+
+#elif SANITIZER_LINUX && SANITIZER_PPC64
+const MappingDesc kMemoryLayout[] = {
+ {0x000000000000ULL, 0x000200000000ULL, MappingDesc::APP, "low memory"},
+ {0x000200000000ULL, 0x080000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x080000000000ULL, 0x180200000000ULL, MappingDesc::SHADOW, "shadow"},
+ {0x180200000000ULL, 0x1C0000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x1C0000000000ULL, 0x2C0200000000ULL, MappingDesc::ORIGIN, "origin"},
+ {0x2C0200000000ULL, 0x300000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x300000000000ULL, 0x800000000000ULL, MappingDesc::APP, "high memory"}};
+
+// Various kernels use different low end ranges but we can combine them into one
+// big range. They also use different high end ranges but we can map them all to
+// one range.
+// Maps low and high app ranges to contiguous space with zero base:
+// Low: 0000 0000 0000 - 0001 ffff ffff -> 1000 0000 0000 - 1001 ffff ffff
+// High: 3000 0000 0000 - 3fff ffff ffff -> 0000 0000 0000 - 0fff ffff ffff
+// High: 4000 0000 0000 - 4fff ffff ffff -> 0000 0000 0000 - 0fff ffff ffff
+// High: 7000 0000 0000 - 7fff ffff ffff -> 0000 0000 0000 - 0fff ffff ffff
+#define LINEARIZE_MEM(mem) \
+ (((uptr)(mem) & ~0xE00000000000ULL) ^ 0x100000000000ULL)
+#define MEM_TO_SHADOW(mem) (LINEARIZE_MEM((mem)) + 0x080000000000ULL)
+#define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x140000000000ULL)
+
+#elif SANITIZER_LINUX && SANITIZER_S390_64
+const MappingDesc kMemoryLayout[] = {
+ {0x000000000000ULL, 0x040000000000ULL, MappingDesc::APP, "low memory"},
+ {0x040000000000ULL, 0x080000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x080000000000ULL, 0x180000000000ULL, MappingDesc::SHADOW, "shadow"},
+ {0x180000000000ULL, 0x1C0000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x1C0000000000ULL, 0x2C0000000000ULL, MappingDesc::ORIGIN, "origin"},
+ {0x2C0000000000ULL, 0x440000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x440000000000ULL, 0x500000000000ULL, MappingDesc::APP, "high memory"}};
+
+#define MEM_TO_SHADOW(mem) \
+ ((((uptr)(mem)) & ~0xC00000000000ULL) + 0x080000000000ULL)
+#define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x140000000000ULL)
+
+#elif SANITIZER_FREEBSD && defined(__aarch64__)
+
+// Low memory: main binary, MAP_32BIT mappings and modules
+// High memory: heap, modules and main thread stack
+const MappingDesc kMemoryLayout[] = {
+ {0x000000000000ULL, 0x020000000000ULL, MappingDesc::APP, "low memory"},
+ {0x020000000000ULL, 0x200000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x200000000000ULL, 0x620000000000ULL, MappingDesc::SHADOW, "shadow"},
+ {0x620000000000ULL, 0x700000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x700000000000ULL, 0xb20000000000ULL, MappingDesc::ORIGIN, "origin"},
+ {0xb20000000000ULL, 0xc00000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0xc00000000000ULL, 0x1000000000000ULL, MappingDesc::APP, "high memory"}};
+
+// Maps low and high app ranges to contiguous space with zero base:
+// Low: 0000 0000 0000 - 01ff ffff ffff -> 4000 0000 0000 - 41ff ffff ffff
+// High: c000 0000 0000 - ffff ffff ffff -> 0000 0000 0000 - 3fff ffff ffff
+#define LINEARIZE_MEM(mem) \
+ (((uptr)(mem) & ~0x1800000000000ULL) ^ 0x400000000000ULL)
+#define MEM_TO_SHADOW(mem) (LINEARIZE_MEM((mem)) + 0x200000000000ULL)
+#define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x500000000000)
+
+#elif SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 64
+
+// Low memory: main binary, MAP_32BIT mappings and modules
+// High memory: heap, modules and main thread stack
+const MappingDesc kMemoryLayout[] = {
+ {0x000000000000ULL, 0x010000000000ULL, MappingDesc::APP, "low memory"},
+ {0x010000000000ULL, 0x100000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x100000000000ULL, 0x310000000000ULL, MappingDesc::SHADOW, "shadow"},
+ {0x310000000000ULL, 0x380000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x380000000000ULL, 0x590000000000ULL, MappingDesc::ORIGIN, "origin"},
+ {0x590000000000ULL, 0x600000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x600000000000ULL, 0x800000000000ULL, MappingDesc::APP, "high memory"}};
+
+// Maps low and high app ranges to contiguous space with zero base:
+// Low: 0000 0000 0000 - 00ff ffff ffff -> 2000 0000 0000 - 20ff ffff ffff
+// High: 6000 0000 0000 - 7fff ffff ffff -> 0000 0000 0000 - 1fff ffff ffff
+#define LINEARIZE_MEM(mem) \
+ (((uptr)(mem) & ~0xc00000000000ULL) ^ 0x200000000000ULL)
+#define MEM_TO_SHADOW(mem) (LINEARIZE_MEM((mem)) + 0x100000000000ULL)
+#define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x280000000000)
+
+#elif SANITIZER_NETBSD || (SANITIZER_LINUX && SANITIZER_WORDSIZE == 64)
+
+// All of the following configurations are supported.
+// ASLR disabled: main executable and DSOs at 0x555550000000
+// PIE and ASLR: main executable and DSOs at 0x7f0000000000
+// non-PIE: main executable below 0x100000000, DSOs at 0x7f0000000000
+// Heap at 0x700000000000.
+const MappingDesc kMemoryLayout[] = {
+ {0x000000000000ULL, 0x010000000000ULL, MappingDesc::APP, "app-1"},
+ {0x010000000000ULL, 0x100000000000ULL, MappingDesc::SHADOW, "shadow-2"},
+ {0x100000000000ULL, 0x110000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x110000000000ULL, 0x200000000000ULL, MappingDesc::ORIGIN, "origin-2"},
+ {0x200000000000ULL, 0x300000000000ULL, MappingDesc::SHADOW, "shadow-3"},
+ {0x300000000000ULL, 0x400000000000ULL, MappingDesc::ORIGIN, "origin-3"},
+ {0x400000000000ULL, 0x500000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x500000000000ULL, 0x510000000000ULL, MappingDesc::SHADOW, "shadow-1"},
+ {0x510000000000ULL, 0x600000000000ULL, MappingDesc::APP, "app-2"},
+ {0x600000000000ULL, 0x610000000000ULL, MappingDesc::ORIGIN, "origin-1"},
+ {0x610000000000ULL, 0x700000000000ULL, MappingDesc::INVALID, "invalid"},
+ {0x700000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}};
+#define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL)
+#define SHADOW_TO_ORIGIN(mem) (((uptr)(mem)) + 0x100000000000ULL)
+
+#else
+#error "Unsupported platform"
+#endif
+
+const uptr kMemoryLayoutSize = sizeof(kMemoryLayout) / sizeof(kMemoryLayout[0]);
+
+#define MEM_TO_ORIGIN(mem) (SHADOW_TO_ORIGIN(MEM_TO_SHADOW((mem))))
+
+#ifndef __clang__
+__attribute__((optimize("unroll-loops")))
+#endif
+inline bool addr_is_type(uptr addr, MappingDesc::Type mapping_type) {
+// It is critical for performance that this loop is unrolled (because then it is
+// simplified into just a few constant comparisons).
+#ifdef __clang__
+#pragma unroll
+#endif
+ for (unsigned i = 0; i < kMemoryLayoutSize; ++i)
+ if (kMemoryLayout[i].type == mapping_type &&
+ addr >= kMemoryLayout[i].start && addr < kMemoryLayout[i].end)
+ return true;
+ return false;
+}
+
+#define MEM_IS_APP(mem) addr_is_type((uptr)(mem), MappingDesc::APP)
+#define MEM_IS_SHADOW(mem) addr_is_type((uptr)(mem), MappingDesc::SHADOW)
+#define MEM_IS_ORIGIN(mem) addr_is_type((uptr)(mem), MappingDesc::ORIGIN)
+
+// These constants must be kept in sync with the ones in MemorySanitizer.cpp.
+const int kMsanParamTlsSize = 800;
+const int kMsanRetvalTlsSize = 800;
+
+namespace __msan {
+extern int msan_inited;
+extern bool msan_init_is_running;
+extern int msan_report_count;
+
+bool ProtectRange(uptr beg, uptr end);
+bool InitShadow(bool init_origins);
+char *GetProcSelfMaps();
+void InitializeInterceptors();
+
+void MsanAllocatorInit();
+void MsanDeallocate(StackTrace *stack, void *ptr);
+
+void *msan_malloc(uptr size, StackTrace *stack);
+void *msan_calloc(uptr nmemb, uptr size, StackTrace *stack);
+void *msan_realloc(void *ptr, uptr size, StackTrace *stack);
+void *msan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack);
+void *msan_valloc(uptr size, StackTrace *stack);
+void *msan_pvalloc(uptr size, StackTrace *stack);
+void *msan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack);
+void *msan_memalign(uptr alignment, uptr size, StackTrace *stack);
+int msan_posix_memalign(void **memptr, uptr alignment, uptr size,
+ StackTrace *stack);
+
+void InstallTrapHandler();
+void InstallAtExitHandler();
+
+const char *GetStackOriginDescr(u32 id, uptr *pc);
+
+bool IsInSymbolizerOrUnwider();
+
+void PrintWarning(uptr pc, uptr bp);
+void PrintWarningWithOrigin(uptr pc, uptr bp, u32 origin);
+
+// Unpoison first n function arguments.
+void UnpoisonParam(uptr n);
+void UnpoisonThreadLocalState();
+
+// Returns a "chained" origin id, pointing to the given stack trace followed by
+// the previous origin id.
+u32 ChainOrigin(u32 id, StackTrace *stack);
+
+const int STACK_TRACE_TAG_POISON = StackTrace::TAG_CUSTOM + 1;
+const int STACK_TRACE_TAG_FIELDS = STACK_TRACE_TAG_POISON + 1;
+const int STACK_TRACE_TAG_VPTR = STACK_TRACE_TAG_FIELDS + 1;
+
+#define GET_MALLOC_STACK_TRACE \
+ BufferedStackTrace stack; \
+ if (__msan_get_track_origins() && msan_inited) \
+ stack.Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), \
+ nullptr, common_flags()->fast_unwind_on_malloc, \
+ common_flags()->malloc_context_size)
+
+// For platforms which support slow unwinder only, we restrict the store context
+// size to 1, basically only storing the current pc. We do this because the slow
+// unwinder which is based on libunwind is not async signal safe and causes
+// random freezes in forking applications as well as in signal handlers.
+#define GET_STORE_STACK_TRACE_PC_BP(pc, bp) \
+ BufferedStackTrace stack; \
+ if (__msan_get_track_origins() > 1 && msan_inited) { \
+ int size = flags()->store_context_size; \
+ if (!SANITIZER_CAN_FAST_UNWIND) \
+ size = Min(size, 1); \
+ stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_malloc, size);\
+ }
+
+#define GET_STORE_STACK_TRACE \
+ GET_STORE_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME())
+
+#define GET_FATAL_STACK_TRACE_PC_BP(pc, bp) \
+ BufferedStackTrace stack; \
+ if (msan_inited) { \
+ stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal); \
+ }
+
+class ScopedThreadLocalStateBackup {
+ public:
+ ScopedThreadLocalStateBackup() { Backup(); }
+ ~ScopedThreadLocalStateBackup() { Restore(); }
+ void Backup();
+ void Restore();
+ private:
+ u64 va_arg_overflow_size_tls;
+};
+
+void MsanTSDInit(void (*destructor)(void *tsd));
+void *MsanTSDGet();
+void MsanTSDSet(void *tsd);
+void MsanTSDDtor(void *tsd);
+
+} // namespace __msan
+
+#endif // MSAN_H
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_allocator.cpp b/contrib/libs/clang16-rt/lib/msan/msan_allocator.cpp
new file mode 100644
index 00000000000..3308ee7053a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_allocator.cpp
@@ -0,0 +1,376 @@
+//===-- msan_allocator.cpp -------------------------- ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+// MemorySanitizer allocator.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_checks.h"
+#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
+#include "sanitizer_common/sanitizer_errno.h"
+#include "msan.h"
+#include "msan_allocator.h"
+#include "msan_origin.h"
+#include "msan_thread.h"
+#include "msan_poisoning.h"
+
+namespace __msan {
+
+struct Metadata {
+ uptr requested_size;
+};
+
+struct MsanMapUnmapCallback {
+ void OnMap(uptr p, uptr size) const {}
+ void OnUnmap(uptr p, uptr size) const {
+ __msan_unpoison((void *)p, size);
+
+ // We are about to unmap a chunk of user memory.
+ // Mark the corresponding shadow memory as not needed.
+ uptr shadow_p = MEM_TO_SHADOW(p);
+ ReleaseMemoryPagesToOS(shadow_p, shadow_p + size);
+ if (__msan_get_track_origins()) {
+ uptr origin_p = MEM_TO_ORIGIN(p);
+ ReleaseMemoryPagesToOS(origin_p, origin_p + size);
+ }
+ }
+};
+
+#if defined(__mips64)
+static const uptr kMaxAllowedMallocSize = 2UL << 30;
+
+struct AP32 {
+ static const uptr kSpaceBeg = 0;
+ static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
+ static const uptr kMetadataSize = sizeof(Metadata);
+ typedef __sanitizer::CompactSizeClassMap SizeClassMap;
+ static const uptr kRegionSizeLog = 20;
+ using AddressSpaceView = LocalAddressSpaceView;
+ typedef MsanMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+};
+typedef SizeClassAllocator32<AP32> PrimaryAllocator;
+#elif defined(__x86_64__)
+#if SANITIZER_NETBSD || SANITIZER_LINUX
+static const uptr kAllocatorSpace = 0x700000000000ULL;
+#else
+static const uptr kAllocatorSpace = 0x600000000000ULL;
+#endif
+static const uptr kMaxAllowedMallocSize = 8UL << 30;
+
+struct AP64 { // Allocator64 parameters. Deliberately using a short name.
+ static const uptr kSpaceBeg = kAllocatorSpace;
+ static const uptr kSpaceSize = 0x40000000000; // 4T.
+ static const uptr kMetadataSize = sizeof(Metadata);
+ typedef DefaultSizeClassMap SizeClassMap;
+ typedef MsanMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+ using AddressSpaceView = LocalAddressSpaceView;
+};
+
+typedef SizeClassAllocator64<AP64> PrimaryAllocator;
+
+#elif defined(__powerpc64__)
+static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G
+
+struct AP64 { // Allocator64 parameters. Deliberately using a short name.
+ static const uptr kSpaceBeg = 0x300000000000;
+ static const uptr kSpaceSize = 0x020000000000; // 2T.
+ static const uptr kMetadataSize = sizeof(Metadata);
+ typedef DefaultSizeClassMap SizeClassMap;
+ typedef MsanMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+ using AddressSpaceView = LocalAddressSpaceView;
+};
+
+typedef SizeClassAllocator64<AP64> PrimaryAllocator;
+#elif defined(__s390x__)
+static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G
+
+struct AP64 { // Allocator64 parameters. Deliberately using a short name.
+ static const uptr kSpaceBeg = 0x440000000000;
+ static const uptr kSpaceSize = 0x020000000000; // 2T.
+ static const uptr kMetadataSize = sizeof(Metadata);
+ typedef DefaultSizeClassMap SizeClassMap;
+ typedef MsanMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+ using AddressSpaceView = LocalAddressSpaceView;
+};
+
+typedef SizeClassAllocator64<AP64> PrimaryAllocator;
+#elif defined(__aarch64__)
+static const uptr kMaxAllowedMallocSize = 8UL << 30;
+
+struct AP64 {
+ static const uptr kSpaceBeg = 0xE00000000000ULL;
+ static const uptr kSpaceSize = 0x40000000000; // 4T.
+ static const uptr kMetadataSize = sizeof(Metadata);
+ typedef DefaultSizeClassMap SizeClassMap;
+ typedef MsanMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+ using AddressSpaceView = LocalAddressSpaceView;
+};
+typedef SizeClassAllocator64<AP64> PrimaryAllocator;
+#endif
+typedef CombinedAllocator<PrimaryAllocator> Allocator;
+typedef Allocator::AllocatorCache AllocatorCache;
+
+static Allocator allocator;
+static AllocatorCache fallback_allocator_cache;
+static StaticSpinMutex fallback_mutex;
+
+static uptr max_malloc_size;
+
+void MsanAllocatorInit() {
+ SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null);
+ allocator.Init(common_flags()->allocator_release_to_os_interval_ms);
+ if (common_flags()->max_allocation_size_mb)
+ max_malloc_size = Min(common_flags()->max_allocation_size_mb << 20,
+ kMaxAllowedMallocSize);
+ else
+ max_malloc_size = kMaxAllowedMallocSize;
+}
+
+AllocatorCache *GetAllocatorCache(MsanThreadLocalMallocStorage *ms) {
+ CHECK(ms);
+ CHECK_LE(sizeof(AllocatorCache), sizeof(ms->allocator_cache));
+ return reinterpret_cast<AllocatorCache *>(ms->allocator_cache);
+}
+
+void MsanThreadLocalMallocStorage::CommitBack() {
+ allocator.SwallowCache(GetAllocatorCache(this));
+}
+
+static void *MsanAllocate(StackTrace *stack, uptr size, uptr alignment,
+ bool zeroise) {
+ if (size > max_malloc_size) {
+ if (AllocatorMayReturnNull()) {
+ Report("WARNING: MemorySanitizer failed to allocate 0x%zx bytes\n", size);
+ return nullptr;
+ }
+ ReportAllocationSizeTooBig(size, max_malloc_size, stack);
+ }
+ if (UNLIKELY(IsRssLimitExceeded())) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportRssLimitExceeded(stack);
+ }
+ MsanThread *t = GetCurrentThread();
+ void *allocated;
+ if (t) {
+ AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
+ allocated = allocator.Allocate(cache, size, alignment);
+ } else {
+ SpinMutexLock l(&fallback_mutex);
+ AllocatorCache *cache = &fallback_allocator_cache;
+ allocated = allocator.Allocate(cache, size, alignment);
+ }
+ if (UNLIKELY(!allocated)) {
+ SetAllocatorOutOfMemory();
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportOutOfMemory(size, stack);
+ }
+ Metadata *meta =
+ reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated));
+ meta->requested_size = size;
+ if (zeroise) {
+ __msan_clear_and_unpoison(allocated, size);
+ } else if (flags()->poison_in_malloc) {
+ __msan_poison(allocated, size);
+ if (__msan_get_track_origins()) {
+ stack->tag = StackTrace::TAG_ALLOC;
+ Origin o = Origin::CreateHeapOrigin(stack);
+ __msan_set_origin(allocated, size, o.raw_id());
+ }
+ }
+ UnpoisonParam(2);
+ RunMallocHooks(allocated, size);
+ return allocated;
+}
+
+void MsanDeallocate(StackTrace *stack, void *p) {
+ CHECK(p);
+ UnpoisonParam(1);
+ RunFreeHooks(p);
+
+ Metadata *meta = reinterpret_cast<Metadata *>(allocator.GetMetaData(p));
+ uptr size = meta->requested_size;
+ meta->requested_size = 0;
+ // This memory will not be reused by anyone else, so we are free to keep it
+ // poisoned.
+ if (flags()->poison_in_free) {
+ __msan_poison(p, size);
+ if (__msan_get_track_origins()) {
+ stack->tag = StackTrace::TAG_DEALLOC;
+ Origin o = Origin::CreateHeapOrigin(stack);
+ __msan_set_origin(p, size, o.raw_id());
+ }
+ }
+ MsanThread *t = GetCurrentThread();
+ if (t) {
+ AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
+ allocator.Deallocate(cache, p);
+ } else {
+ SpinMutexLock l(&fallback_mutex);
+ AllocatorCache *cache = &fallback_allocator_cache;
+ allocator.Deallocate(cache, p);
+ }
+}
+
+static void *MsanReallocate(StackTrace *stack, void *old_p, uptr new_size,
+ uptr alignment) {
+ Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(old_p));
+ uptr old_size = meta->requested_size;
+ uptr actually_allocated_size = allocator.GetActuallyAllocatedSize(old_p);
+ if (new_size <= actually_allocated_size) {
+ // We are not reallocating here.
+ meta->requested_size = new_size;
+ if (new_size > old_size) {
+ if (flags()->poison_in_malloc) {
+ stack->tag = StackTrace::TAG_ALLOC;
+ PoisonMemory((char *)old_p + old_size, new_size - old_size, stack);
+ }
+ }
+ return old_p;
+ }
+ uptr memcpy_size = Min(new_size, old_size);
+ void *new_p = MsanAllocate(stack, new_size, alignment, false /*zeroise*/);
+ if (new_p) {
+ CopyMemory(new_p, old_p, memcpy_size, stack);
+ MsanDeallocate(stack, old_p);
+ }
+ return new_p;
+}
+
+static void *MsanCalloc(StackTrace *stack, uptr nmemb, uptr size) {
+ if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportCallocOverflow(nmemb, size, stack);
+ }
+ return MsanAllocate(stack, nmemb * size, sizeof(u64), true);
+}
+
+static uptr AllocationSize(const void *p) {
+ if (!p) return 0;
+ const void *beg = allocator.GetBlockBegin(p);
+ if (beg != p) return 0;
+ Metadata *b = (Metadata *)allocator.GetMetaData(p);
+ return b->requested_size;
+}
+
+void *msan_malloc(uptr size, StackTrace *stack) {
+ return SetErrnoOnNull(MsanAllocate(stack, size, sizeof(u64), false));
+}
+
+void *msan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
+ return SetErrnoOnNull(MsanCalloc(stack, nmemb, size));
+}
+
+void *msan_realloc(void *ptr, uptr size, StackTrace *stack) {
+ if (!ptr)
+ return SetErrnoOnNull(MsanAllocate(stack, size, sizeof(u64), false));
+ if (size == 0) {
+ MsanDeallocate(stack, ptr);
+ return nullptr;
+ }
+ return SetErrnoOnNull(MsanReallocate(stack, ptr, size, sizeof(u64)));
+}
+
+void *msan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack) {
+ if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+ errno = errno_ENOMEM;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportReallocArrayOverflow(nmemb, size, stack);
+ }
+ return msan_realloc(ptr, nmemb * size, stack);
+}
+
+void *msan_valloc(uptr size, StackTrace *stack) {
+ return SetErrnoOnNull(MsanAllocate(stack, size, GetPageSizeCached(), false));
+}
+
+void *msan_pvalloc(uptr size, StackTrace *stack) {
+ uptr PageSize = GetPageSizeCached();
+ if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) {
+ errno = errno_ENOMEM;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportPvallocOverflow(size, stack);
+ }
+ // pvalloc(0) should allocate one page.
+ size = size ? RoundUpTo(size, PageSize) : PageSize;
+ return SetErrnoOnNull(MsanAllocate(stack, size, PageSize, false));
+}
+
+void *msan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack) {
+ if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAlignedAllocAlignment(size, alignment, stack);
+ }
+ return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
+}
+
+void *msan_memalign(uptr alignment, uptr size, StackTrace *stack) {
+ if (UNLIKELY(!IsPowerOfTwo(alignment))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAllocationAlignment(alignment, stack);
+ }
+ return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
+}
+
+int msan_posix_memalign(void **memptr, uptr alignment, uptr size,
+ StackTrace *stack) {
+ if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
+ if (AllocatorMayReturnNull())
+ return errno_EINVAL;
+ ReportInvalidPosixMemalignAlignment(alignment, stack);
+ }
+ void *ptr = MsanAllocate(stack, size, alignment, false);
+ if (UNLIKELY(!ptr))
+ // OOM error is already taken care of by MsanAllocate.
+ return errno_ENOMEM;
+ CHECK(IsAligned((uptr)ptr, alignment));
+ *memptr = ptr;
+ return 0;
+}
+
+} // namespace __msan
+
+using namespace __msan;
+
+uptr __sanitizer_get_current_allocated_bytes() {
+ uptr stats[AllocatorStatCount];
+ allocator.GetStats(stats);
+ return stats[AllocatorStatAllocated];
+}
+
+uptr __sanitizer_get_heap_size() {
+ uptr stats[AllocatorStatCount];
+ allocator.GetStats(stats);
+ return stats[AllocatorStatMapped];
+}
+
+uptr __sanitizer_get_free_bytes() { return 1; }
+
+uptr __sanitizer_get_unmapped_bytes() { return 1; }
+
+uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; }
+
+int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; }
+
+uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); }
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_allocator.h b/contrib/libs/clang16-rt/lib/msan/msan_allocator.h
new file mode 100644
index 00000000000..365af4d0c4d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_allocator.h
@@ -0,0 +1,31 @@
+//===-- msan_allocator.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MSAN_ALLOCATOR_H
+#define MSAN_ALLOCATOR_H
+
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace __msan {
+
+struct MsanThreadLocalMallocStorage {
+ // Allocator cache contains atomic_uint64_t which must be 8-byte aligned.
+ ALIGNED(8) uptr allocator_cache[96 * (512 * 8 + 16)]; // Opaque.
+ void CommitBack();
+
+ private:
+ // These objects are allocated via mmap() and are zero-initialized.
+ MsanThreadLocalMallocStorage() {}
+};
+
+} // namespace __msan
+#endif // MSAN_ALLOCATOR_H
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_chained_origin_depot.cpp b/contrib/libs/clang16-rt/lib/msan/msan_chained_origin_depot.cpp
new file mode 100644
index 00000000000..49b14131a89
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_chained_origin_depot.cpp
@@ -0,0 +1,42 @@
+//===-- msan_chained_origin_depot.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+// A storage for chained origins.
+//===----------------------------------------------------------------------===//
+
+#include "msan_chained_origin_depot.h"
+
+#include "sanitizer_common/sanitizer_chained_origin_depot.h"
+
+namespace __msan {
+
+static ChainedOriginDepot chainedOriginDepot;
+
+StackDepotStats ChainedOriginDepotGetStats() {
+ return chainedOriginDepot.GetStats();
+}
+
+bool ChainedOriginDepotPut(u32 here_id, u32 prev_id, u32 *new_id) {
+ return chainedOriginDepot.Put(here_id, prev_id, new_id);
+}
+
+u32 ChainedOriginDepotGet(u32 id, u32 *other) {
+ return chainedOriginDepot.Get(id, other);
+}
+
+void ChainedOriginDepotLockAll() {
+ chainedOriginDepot.LockAll();
+}
+
+void ChainedOriginDepotUnlockAll() {
+ chainedOriginDepot.UnlockAll();
+}
+
+} // namespace __msan
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_chained_origin_depot.h b/contrib/libs/clang16-rt/lib/msan/msan_chained_origin_depot.h
new file mode 100644
index 00000000000..ea51c77a905
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_chained_origin_depot.h
@@ -0,0 +1,38 @@
+//===-- msan_chained_origin_depot.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+// A storage for chained origins.
+//===----------------------------------------------------------------------===//
+
+#ifndef MSAN_CHAINED_ORIGIN_DEPOT_H
+#define MSAN_CHAINED_ORIGIN_DEPOT_H
+
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace __msan {
+
+// Gets the statistic of the origin chain storage.
+StackDepotStats ChainedOriginDepotGetStats();
+
+// Stores a chain with StackDepot ID here_id and previous chain ID prev_id.
+// If successful, returns true and the new chain id new_id.
+// If the same element already exists, returns false and sets new_id to the
+// existing ID.
+bool ChainedOriginDepotPut(u32 here_id, u32 prev_id, u32 *new_id);
+
+// Retrieves the stored StackDepot ID for the given origin ID.
+u32 ChainedOriginDepotGet(u32 id, u32 *other);
+
+void ChainedOriginDepotLockAll();
+void ChainedOriginDepotUnlockAll();
+
+} // namespace __msan
+
+#endif // MSAN_CHAINED_ORIGIN_DEPOT_H
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_flags.h b/contrib/libs/clang16-rt/lib/msan/msan_flags.h
new file mode 100644
index 00000000000..836dbbaa164
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_flags.h
@@ -0,0 +1,29 @@
+//===-- msan_flags.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MSAN_FLAGS_H
+#define MSAN_FLAGS_H
+
+namespace __msan {
+
+struct Flags {
+#define MSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "msan_flags.inc"
+#undef MSAN_FLAG
+
+ void SetDefaults();
+};
+
+Flags *flags();
+
+} // namespace __msan
+
+#endif // MSAN_FLAGS_H
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_flags.inc b/contrib/libs/clang16-rt/lib/msan/msan_flags.inc
new file mode 100644
index 00000000000..16db26bd42e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_flags.inc
@@ -0,0 +1,34 @@
+//===-- msan_flags.inc ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// MSan runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MSAN_FLAG
+# error "Define MSAN_FLAG prior to including this file!"
+#endif
+
+// MSAN_FLAG(Type, Name, DefaultValue, Description)
+// See COMMON_FLAG in sanitizer_flags.inc for more details.
+
+MSAN_FLAG(int, exit_code, -1,
+ "DEPRECATED. Use exitcode from common flags instead.")
+MSAN_FLAG(int, origin_history_size, Origin::kMaxDepth, "")
+MSAN_FLAG(int, origin_history_per_stack_limit, 20000, "")
+MSAN_FLAG(bool, poison_heap_with_zeroes, false, "")
+MSAN_FLAG(bool, poison_stack_with_zeroes, false, "")
+MSAN_FLAG(bool, poison_in_malloc, true, "")
+MSAN_FLAG(bool, poison_in_free, true, "")
+MSAN_FLAG(bool, poison_in_dtor, true, "")
+MSAN_FLAG(bool, report_umrs, true, "")
+MSAN_FLAG(bool, wrap_signals, true, "")
+MSAN_FLAG(bool, print_stats, false, "")
+MSAN_FLAG(bool, halt_on_error, !&__msan_keep_going, "")
+MSAN_FLAG(bool, atexit, false, "")
+MSAN_FLAG(int, store_context_size, 20,
+ "Like malloc_context_size, but for uninit stores.")
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_interceptors.cpp b/contrib/libs/clang16-rt/lib/msan/msan_interceptors.cpp
new file mode 100644
index 00000000000..058c10a1942
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_interceptors.cpp
@@ -0,0 +1,1797 @@
+//===-- msan_interceptors.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+// Interceptors for standard library functions.
+//
+// FIXME: move as many interceptors as possible into
+// sanitizer_common/sanitizer_common_interceptors.h
+//===----------------------------------------------------------------------===//
+
+#include "interception/interception.h"
+#include "msan.h"
+#include "msan_chained_origin_depot.h"
+#include "msan_origin.h"
+#include "msan_poisoning.h"
+#include "msan_report.h"
+#include "msan_thread.h"
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_dlsym.h"
+#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_errno.h"
+#include "sanitizer_common/sanitizer_errno_codes.h"
+#include "sanitizer_common/sanitizer_glibc_version.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
+#include "sanitizer_common/sanitizer_platform_limits_posix.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+#include "sanitizer_common/sanitizer_vector.h"
+
+#if SANITIZER_NETBSD
+#define fstat __fstat50
+#define gettimeofday __gettimeofday50
+#define getrusage __getrusage50
+#define tzset __tzset50
+#endif
+
+#include <stdarg.h>
+// ACHTUNG! No other system header includes in this file.
+// Ideally, we should get rid of stdarg.h as well.
+
+using namespace __msan;
+
+using __sanitizer::memory_order;
+using __sanitizer::atomic_load;
+using __sanitizer::atomic_store;
+using __sanitizer::atomic_uintptr_t;
+
+DECLARE_REAL(SIZE_T, strlen, const char *s)
+DECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen)
+DECLARE_REAL(void *, memcpy, void *dest, const void *src, uptr n)
+DECLARE_REAL(void *, memset, void *dest, int c, uptr n)
+
+// True if this is a nested interceptor.
+static THREADLOCAL int in_interceptor_scope;
+
+void __msan_scoped_disable_interceptor_checks() { ++in_interceptor_scope; }
+void __msan_scoped_enable_interceptor_checks() { --in_interceptor_scope; }
+
+struct InterceptorScope {
+ InterceptorScope() { ++in_interceptor_scope; }
+ ~InterceptorScope() { --in_interceptor_scope; }
+};
+
+bool IsInInterceptorScope() {
+ return in_interceptor_scope;
+}
+
+struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
+ static bool UseImpl() { return !msan_inited; }
+};
+
+#define ENSURE_MSAN_INITED() do { \
+ CHECK(!msan_init_is_running); \
+ if (!msan_inited) { \
+ __msan_init(); \
+ } \
+} while (0)
+
+// Check that [x, x+n) range is unpoisoned.
+#define CHECK_UNPOISONED_0(x, n) \
+ do { \
+ sptr __offset = __msan_test_shadow(x, n); \
+ if (__msan::IsInSymbolizerOrUnwider()) \
+ break; \
+ if (__offset >= 0 && __msan::flags()->report_umrs) { \
+ GET_CALLER_PC_BP_SP; \
+ (void)sp; \
+ ReportUMRInsideAddressRange(__func__, x, n, __offset); \
+ __msan::PrintWarningWithOrigin( \
+ pc, bp, __msan_get_origin((const char *)x + __offset)); \
+ if (__msan::flags()->halt_on_error) { \
+ Printf("Exiting\n"); \
+ Die(); \
+ } \
+ } \
+ } while (0)
+
+// Check that [x, x+n) range is unpoisoned unless we are in a nested
+// interceptor.
+#define CHECK_UNPOISONED(x, n) \
+ do { \
+ if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \
+ } while (0)
+
+#define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n) \
+ CHECK_UNPOISONED((x), \
+ common_flags()->strict_string_checks ? (len) + 1 : (n) )
+
+#define CHECK_UNPOISONED_STRING(x, n) \
+ CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n))
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb,
+ void *file) {
+ ENSURE_MSAN_INITED();
+ SIZE_T res = REAL(fread_unlocked)(ptr, size, nmemb, file);
+ if (res > 0)
+ __msan_unpoison(ptr, res *size);
+ return res;
+}
+#define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED INTERCEPT_FUNCTION(fread_unlocked)
+#else
+#define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
+#endif
+
+#if !SANITIZER_NETBSD
+INTERCEPTOR(void *, mempcpy, void *dest, const void *src, SIZE_T n) {
+ return (char *)__msan_memcpy(dest, src, n) + n;
+}
+#define MSAN_MAYBE_INTERCEPT_MEMPCPY INTERCEPT_FUNCTION(mempcpy)
+#else
+#define MSAN_MAYBE_INTERCEPT_MEMPCPY
+#endif
+
+INTERCEPTOR(void *, memccpy, void *dest, const void *src, int c, SIZE_T n) {
+ ENSURE_MSAN_INITED();
+ void *res = REAL(memccpy)(dest, src, c, n);
+ CHECK(!res || (res >= dest && res <= (char *)dest + n));
+ SIZE_T sz = res ? (char *)res - (char *)dest : n;
+ CHECK_UNPOISONED(src, sz);
+ __msan_unpoison(dest, sz);
+ return res;
+}
+
+INTERCEPTOR(void *, bcopy, const void *src, void *dest, SIZE_T n) {
+ return __msan_memmove(dest, src, n);
+}
+
+INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) {
+ GET_MALLOC_STACK_TRACE;
+ CHECK_NE(memptr, 0);
+ int res = msan_posix_memalign(memptr, alignment, size, &stack);
+ if (!res)
+ __msan_unpoison(memptr, sizeof(*memptr));
+ return res;
+}
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR(void *, memalign, SIZE_T alignment, SIZE_T size) {
+ GET_MALLOC_STACK_TRACE;
+ return msan_memalign(alignment, size, &stack);
+}
+#define MSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
+#else
+#define MSAN_MAYBE_INTERCEPT_MEMALIGN
+#endif
+
+INTERCEPTOR(void *, aligned_alloc, SIZE_T alignment, SIZE_T size) {
+ GET_MALLOC_STACK_TRACE;
+ return msan_aligned_alloc(alignment, size, &stack);
+}
+
+#if !SANITIZER_NETBSD
+INTERCEPTOR(void *, __libc_memalign, SIZE_T alignment, SIZE_T size) {
+ GET_MALLOC_STACK_TRACE;
+ void *ptr = msan_memalign(alignment, size, &stack);
+ if (ptr)
+ DTLS_on_libc_memalign(ptr, size);
+ return ptr;
+}
+#define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN INTERCEPT_FUNCTION(__libc_memalign)
+#else
+#define MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN
+#endif
+
+INTERCEPTOR(void *, valloc, SIZE_T size) {
+ GET_MALLOC_STACK_TRACE;
+ return msan_valloc(size, &stack);
+}
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR(void *, pvalloc, SIZE_T size) {
+ GET_MALLOC_STACK_TRACE;
+ return msan_pvalloc(size, &stack);
+}
+#define MSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
+#else
+#define MSAN_MAYBE_INTERCEPT_PVALLOC
+#endif
+
+INTERCEPTOR(void, free, void *ptr) {
+ if (UNLIKELY(!ptr))
+ return;
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+ GET_MALLOC_STACK_TRACE;
+ MsanDeallocate(&stack, ptr);
+}
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR(void, cfree, void *ptr) {
+ if (UNLIKELY(!ptr))
+ return;
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+ GET_MALLOC_STACK_TRACE;
+ MsanDeallocate(&stack, ptr);
+}
+# define MSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
+#else
+#define MSAN_MAYBE_INTERCEPT_CFREE
+#endif
+
+#if !SANITIZER_NETBSD
+INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
+ return __sanitizer_get_allocated_size(ptr);
+}
+#define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE \
+ INTERCEPT_FUNCTION(malloc_usable_size)
+#else
+#define MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE
+#endif
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+// This function actually returns a struct by value, but we can't unpoison a
+// temporary! The following is equivalent on all supported platforms but
+// aarch64 (which uses a different register for sret value). We have a test
+// to confirm that.
+INTERCEPTOR(void, mallinfo, __sanitizer_struct_mallinfo *sret) {
+#ifdef __aarch64__
+ uptr r8;
+ asm volatile("mov %0,x8" : "=r" (r8));
+ sret = reinterpret_cast<__sanitizer_struct_mallinfo*>(r8);
+#endif
+ REAL(memset)(sret, 0, sizeof(*sret));
+ __msan_unpoison(sret, sizeof(*sret));
+}
+#define MSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
+#else
+#define MSAN_MAYBE_INTERCEPT_MALLINFO
+#endif
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR(int, mallopt, int cmd, int value) {
+ return 0;
+}
+#define MSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
+#else
+#define MSAN_MAYBE_INTERCEPT_MALLOPT
+#endif
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR(void, malloc_stats, void) {
+ // FIXME: implement, but don't call REAL(malloc_stats)!
+}
+#define MSAN_MAYBE_INTERCEPT_MALLOC_STATS INTERCEPT_FUNCTION(malloc_stats)
+#else
+#define MSAN_MAYBE_INTERCEPT_MALLOC_STATS
+#endif
+
+INTERCEPTOR(char *, strcpy, char *dest, const char *src) {
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ SIZE_T n = internal_strlen(src);
+ CHECK_UNPOISONED_STRING(src + n, 0);
+ char *res = REAL(strcpy)(dest, src);
+ CopyShadowAndOrigin(dest, src, n + 1, &stack);
+ return res;
+}
+
+INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) {
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ SIZE_T copy_size = internal_strnlen(src, n);
+ if (copy_size < n)
+ copy_size++; // trailing \0
+ char *res = REAL(strncpy)(dest, src, n);
+ CopyShadowAndOrigin(dest, src, copy_size, &stack);
+ __msan_unpoison(dest + copy_size, n - copy_size);
+ return res;
+}
+
+#if !SANITIZER_NETBSD
+INTERCEPTOR(char *, stpcpy, char *dest, const char *src) {
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ SIZE_T n = internal_strlen(src);
+ CHECK_UNPOISONED_STRING(src + n, 0);
+ char *res = REAL(stpcpy)(dest, src);
+ CopyShadowAndOrigin(dest, src, n + 1, &stack);
+ return res;
+}
+
+INTERCEPTOR(char *, stpncpy, char *dest, const char *src, SIZE_T n) {
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ SIZE_T copy_size = Min(n, internal_strnlen(src, n) + 1);
+ char *res = REAL(stpncpy)(dest, src, n);
+ CopyShadowAndOrigin(dest, src, copy_size, &stack);
+ __msan_unpoison(dest + copy_size, n - copy_size);
+ return res;
+}
+# define MSAN_MAYBE_INTERCEPT_STPCPY INTERCEPT_FUNCTION(stpcpy)
+# define MSAN_MAYBE_INTERCEPT_STPNCPY INTERCEPT_FUNCTION(stpncpy)
+#else
+#define MSAN_MAYBE_INTERCEPT_STPCPY
+# define MSAN_MAYBE_INTERCEPT_STPNCPY
+#endif
+
+INTERCEPTOR(char *, strdup, char *src) {
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ // On FreeBSD strdup() leverages strlen().
+ InterceptorScope interceptor_scope;
+ SIZE_T n = internal_strlen(src);
+ CHECK_UNPOISONED_STRING(src + n, 0);
+ char *res = REAL(strdup)(src);
+ CopyShadowAndOrigin(res, src, n + 1, &stack);
+ return res;
+}
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR(char *, __strdup, char *src) {
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ SIZE_T n = internal_strlen(src);
+ CHECK_UNPOISONED_STRING(src + n, 0);
+ char *res = REAL(__strdup)(src);
+ CopyShadowAndOrigin(res, src, n + 1, &stack);
+ return res;
+}
+#define MSAN_MAYBE_INTERCEPT___STRDUP INTERCEPT_FUNCTION(__strdup)
+#else
+#define MSAN_MAYBE_INTERCEPT___STRDUP
+#endif
+
+#if !SANITIZER_NETBSD
+INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) {
+ ENSURE_MSAN_INITED();
+ char *res = REAL(gcvt)(number, ndigit, buf);
+ SIZE_T n = internal_strlen(buf);
+ __msan_unpoison(buf, n + 1);
+ return res;
+}
+#define MSAN_MAYBE_INTERCEPT_GCVT INTERCEPT_FUNCTION(gcvt)
+#else
+#define MSAN_MAYBE_INTERCEPT_GCVT
+#endif
+
+INTERCEPTOR(char *, strcat, char *dest, const char *src) {
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ SIZE_T src_size = internal_strlen(src);
+ SIZE_T dest_size = internal_strlen(dest);
+ CHECK_UNPOISONED_STRING(src + src_size, 0);
+ CHECK_UNPOISONED_STRING(dest + dest_size, 0);
+ char *res = REAL(strcat)(dest, src);
+ CopyShadowAndOrigin(dest + dest_size, src, src_size + 1, &stack);
+ return res;
+}
+
+INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) {
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ SIZE_T dest_size = internal_strlen(dest);
+ SIZE_T copy_size = internal_strnlen(src, n);
+ CHECK_UNPOISONED_STRING(dest + dest_size, 0);
+ char *res = REAL(strncat)(dest, src, n);
+ CopyShadowAndOrigin(dest + dest_size, src, copy_size, &stack);
+ __msan_unpoison(dest + dest_size + copy_size, 1); // \0
+ return res;
+}
+
+// Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to
+// deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO.
+#define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \
+ ENSURE_MSAN_INITED(); \
+ ret_type res = REAL(func)(__VA_ARGS__); \
+ __msan_unpoison(endptr, sizeof(*endptr)); \
+ return res;
+
+#define INTERCEPTOR_STRTO(ret_type, func, char_type) \
+ INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr) { \
+ INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr); \
+ }
+
+#define INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
+ INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
+ int base) { \
+ INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base); \
+ }
+
+#define INTERCEPTOR_STRTO_LOC(ret_type, func, char_type) \
+ INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
+ void *loc) { \
+ INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc); \
+ }
+
+#define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func, char_type) \
+ INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
+ int base, void *loc) { \
+ INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc); \
+ }
+
+#if SANITIZER_NETBSD
+#define INTERCEPTORS_STRTO(ret_type, func, char_type) \
+ INTERCEPTOR_STRTO(ret_type, func, char_type) \
+ INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type)
+
+#define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
+ INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
+ INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type)
+
+#else
+#define INTERCEPTORS_STRTO(ret_type, func, char_type) \
+ INTERCEPTOR_STRTO(ret_type, func, char_type) \
+ INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type) \
+ INTERCEPTOR_STRTO_LOC(ret_type, __##func##_l, char_type) \
+ INTERCEPTOR_STRTO_LOC(ret_type, __##func##_internal, char_type)
+
+#define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
+ INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
+ INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type) \
+ INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_l, char_type) \
+ INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_internal, char_type)
+#endif
+
+INTERCEPTORS_STRTO(double, strtod, char)
+INTERCEPTORS_STRTO(float, strtof, char)
+INTERCEPTORS_STRTO(long double, strtold, char)
+INTERCEPTORS_STRTO_BASE(long, strtol, char)
+INTERCEPTORS_STRTO_BASE(long long, strtoll, char)
+INTERCEPTORS_STRTO_BASE(unsigned long, strtoul, char)
+INTERCEPTORS_STRTO_BASE(unsigned long long, strtoull, char)
+INTERCEPTORS_STRTO_BASE(u64, strtouq, char)
+
+INTERCEPTORS_STRTO(double, wcstod, wchar_t)
+INTERCEPTORS_STRTO(float, wcstof, wchar_t)
+INTERCEPTORS_STRTO(long double, wcstold, wchar_t)
+INTERCEPTORS_STRTO_BASE(long, wcstol, wchar_t)
+INTERCEPTORS_STRTO_BASE(long long, wcstoll, wchar_t)
+INTERCEPTORS_STRTO_BASE(unsigned long, wcstoul, wchar_t)
+INTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull, wchar_t)
+
+#if SANITIZER_NETBSD
+#define INTERCEPT_STRTO(func) \
+ INTERCEPT_FUNCTION(func); \
+ INTERCEPT_FUNCTION(func##_l);
+#else
+#define INTERCEPT_STRTO(func) \
+ INTERCEPT_FUNCTION(func); \
+ INTERCEPT_FUNCTION(func##_l); \
+ INTERCEPT_FUNCTION(__##func##_l); \
+ INTERCEPT_FUNCTION(__##func##_internal);
+#endif
+
+
+// FIXME: support *wprintf in common format interceptors.
+INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(vswprintf)(str, size, format, ap);
+ if (res >= 0) {
+ __msan_unpoison(str, 4 * (res + 1));
+ }
+ return res;
+}
+
+INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) {
+ ENSURE_MSAN_INITED();
+ va_list ap;
+ va_start(ap, format);
+ int res = vswprintf(str, size, format, ap);
+ va_end(ap);
+ return res;
+}
+
+#define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \
+ ENSURE_MSAN_INITED(); \
+ InterceptorScope interceptor_scope; \
+ ret_type res = REAL(func)(s, __VA_ARGS__); \
+ if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1)); \
+ return res;
+
+INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format,
+ __sanitizer_tm *tm) {
+ INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime, s, max, format, tm);
+}
+
+INTERCEPTOR(SIZE_T, strftime_l, char *s, SIZE_T max, const char *format,
+ __sanitizer_tm *tm, void *loc) {
+ INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime_l, s, max, format, tm, loc);
+}
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR(SIZE_T, __strftime_l, char *s, SIZE_T max, const char *format,
+ __sanitizer_tm *tm, void *loc) {
+ INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, __strftime_l, s, max, format, tm,
+ loc);
+}
+#define MSAN_MAYBE_INTERCEPT___STRFTIME_L INTERCEPT_FUNCTION(__strftime_l)
+#else
+#define MSAN_MAYBE_INTERCEPT___STRFTIME_L
+#endif
+
+INTERCEPTOR(SIZE_T, wcsftime, wchar_t *s, SIZE_T max, const wchar_t *format,
+ __sanitizer_tm *tm) {
+ INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime, s, max, format, tm);
+}
+
+INTERCEPTOR(SIZE_T, wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
+ __sanitizer_tm *tm, void *loc) {
+ INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime_l, s, max, format, tm,
+ loc);
+}
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR(SIZE_T, __wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
+ __sanitizer_tm *tm, void *loc) {
+ INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, __wcsftime_l, s, max, format, tm,
+ loc);
+}
+#define MSAN_MAYBE_INTERCEPT___WCSFTIME_L INTERCEPT_FUNCTION(__wcsftime_l)
+#else
+#define MSAN_MAYBE_INTERCEPT___WCSFTIME_L
+#endif
+
+INTERCEPTOR(int, mbtowc, wchar_t *dest, const char *src, SIZE_T n) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(mbtowc)(dest, src, n);
+ if (res != -1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
+ return res;
+}
+
+INTERCEPTOR(SIZE_T, mbrtowc, wchar_t *dest, const char *src, SIZE_T n,
+ void *ps) {
+ ENSURE_MSAN_INITED();
+ SIZE_T res = REAL(mbrtowc)(dest, src, n, ps);
+ if (res != (SIZE_T)-1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
+ return res;
+}
+
+// wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
+INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ wchar_t *res = REAL(wmemcpy)(dest, src, n);
+ CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
+ return res;
+}
+
+#if !SANITIZER_NETBSD
+INTERCEPTOR(wchar_t *, wmempcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ wchar_t *res = REAL(wmempcpy)(dest, src, n);
+ CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
+ return res;
+}
+#define MSAN_MAYBE_INTERCEPT_WMEMPCPY INTERCEPT_FUNCTION(wmempcpy)
+#else
+#define MSAN_MAYBE_INTERCEPT_WMEMPCPY
+#endif
+
+INTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) {
+ CHECK(MEM_IS_APP(s));
+ ENSURE_MSAN_INITED();
+ wchar_t *res = REAL(wmemset)(s, c, n);
+ __msan_unpoison(s, n * sizeof(wchar_t));
+ return res;
+}
+
+INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) {
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ wchar_t *res = REAL(wmemmove)(dest, src, n);
+ MoveShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
+ return res;
+}
+
+INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(wcscmp)(s1, s2);
+ return res;
+}
+
+INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(gettimeofday)(tv, tz);
+ if (tv)
+ __msan_unpoison(tv, 16);
+ if (tz)
+ __msan_unpoison(tz, 8);
+ return res;
+}
+
+#if !SANITIZER_NETBSD
+INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) {
+ ENSURE_MSAN_INITED();
+ char *res = REAL(fcvt)(x, a, b, c);
+ __msan_unpoison(b, sizeof(*b));
+ __msan_unpoison(c, sizeof(*c));
+ if (res)
+ __msan_unpoison(res, internal_strlen(res) + 1);
+ return res;
+}
+#define MSAN_MAYBE_INTERCEPT_FCVT INTERCEPT_FUNCTION(fcvt)
+#else
+#define MSAN_MAYBE_INTERCEPT_FCVT
+#endif
+
+INTERCEPTOR(char *, getenv, char *name) {
+ if (msan_init_is_running)
+ return REAL(getenv)(name);
+ ENSURE_MSAN_INITED();
+ char *res = REAL(getenv)(name);
+ if (res)
+ __msan_unpoison(res, internal_strlen(res) + 1);
+ return res;
+}
+
+extern char **environ;
+
+static void UnpoisonEnviron() {
+ char **envp = environ;
+ for (; *envp; ++envp) {
+ __msan_unpoison(envp, sizeof(*envp));
+ __msan_unpoison(*envp, internal_strlen(*envp) + 1);
+ }
+ // Trailing NULL pointer.
+ __msan_unpoison(envp, sizeof(*envp));
+}
+
+INTERCEPTOR(int, setenv, const char *name, const char *value, int overwrite) {
+ ENSURE_MSAN_INITED();
+ CHECK_UNPOISONED_STRING(name, 0);
+ int res = REAL(setenv)(name, value, overwrite);
+ if (!res) UnpoisonEnviron();
+ return res;
+}
+
+INTERCEPTOR(int, putenv, char *string) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(putenv)(string);
+ if (!res) UnpoisonEnviron();
+ return res;
+}
+
+#define SANITIZER_STAT_LINUX (SANITIZER_LINUX && __GLIBC_PREREQ(2, 33))
+#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
+INTERCEPTOR(int, fstat, int fd, void *buf) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(fstat)(fd, buf);
+ if (!res)
+ __msan_unpoison(buf, __sanitizer::struct_stat_sz);
+ return res;
+}
+# define MSAN_MAYBE_INTERCEPT_FSTAT MSAN_INTERCEPT_FUNC(fstat)
+#else
+#define MSAN_MAYBE_INTERCEPT_FSTAT
+#endif
+
+#if SANITIZER_STAT_LINUX
+INTERCEPTOR(int, fstat64, int fd, void *buf) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(fstat64)(fd, buf);
+ if (!res)
+ __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
+ return res;
+}
+# define MSAN_MAYBE_INTERCEPT_FSTAT64 MSAN_INTERCEPT_FUNC(fstat64)
+#else
+# define MSAN_MAYBE_INTERCEPT_FSTAT64
+#endif
+
+#if SANITIZER_GLIBC
+INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(__fxstat)(magic, fd, buf);
+ if (!res)
+ __msan_unpoison(buf, __sanitizer::struct_stat_sz);
+ return res;
+}
+# define MSAN_MAYBE_INTERCEPT___FXSTAT MSAN_INTERCEPT_FUNC(__fxstat)
+#else
+#define MSAN_MAYBE_INTERCEPT___FXSTAT
+#endif
+
+#if SANITIZER_GLIBC
+INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(__fxstat64)(magic, fd, buf);
+ if (!res)
+ __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
+ return res;
+}
+# define MSAN_MAYBE_INTERCEPT___FXSTAT64 MSAN_INTERCEPT_FUNC(__fxstat64)
+#else
+# define MSAN_MAYBE_INTERCEPT___FXSTAT64
+#endif
+
+#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
+INTERCEPTOR(int, fstatat, int fd, char *pathname, void *buf, int flags) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(fstatat)(fd, pathname, buf, flags);
+ if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
+ return res;
+}
+# define MSAN_MAYBE_INTERCEPT_FSTATAT MSAN_INTERCEPT_FUNC(fstatat)
+#else
+# define MSAN_MAYBE_INTERCEPT_FSTATAT
+#endif
+
+#if SANITIZER_STAT_LINUX
+INTERCEPTOR(int, fstatat64, int fd, char *pathname, void *buf, int flags) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(fstatat64)(fd, pathname, buf, flags);
+ if (!res)
+ __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
+ return res;
+}
+# define MSAN_MAYBE_INTERCEPT_FSTATAT64 MSAN_INTERCEPT_FUNC(fstatat64)
+#else
+# define MSAN_MAYBE_INTERCEPT_FSTATAT64
+#endif
+
+#if SANITIZER_GLIBC
+INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf,
+ int flags) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(__fxstatat)(magic, fd, pathname, buf, flags);
+ if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
+ return res;
+}
+# define MSAN_MAYBE_INTERCEPT___FXSTATAT MSAN_INTERCEPT_FUNC(__fxstatat)
+#else
+# define MSAN_MAYBE_INTERCEPT___FXSTATAT
+#endif
+
+#if SANITIZER_GLIBC
+INTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf,
+ int flags) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(__fxstatat64)(magic, fd, pathname, buf, flags);
+ if (!res) __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
+ return res;
+}
+# define MSAN_MAYBE_INTERCEPT___FXSTATAT64 MSAN_INTERCEPT_FUNC(__fxstatat64)
+#else
+# define MSAN_MAYBE_INTERCEPT___FXSTATAT64
+#endif
+
+INTERCEPTOR(int, pipe, int pipefd[2]) {
+ if (msan_init_is_running)
+ return REAL(pipe)(pipefd);
+ ENSURE_MSAN_INITED();
+ int res = REAL(pipe)(pipefd);
+ if (!res)
+ __msan_unpoison(pipefd, sizeof(int[2]));
+ return res;
+}
+
+INTERCEPTOR(int, pipe2, int pipefd[2], int flags) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(pipe2)(pipefd, flags);
+ if (!res)
+ __msan_unpoison(pipefd, sizeof(int[2]));
+ return res;
+}
+
+INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int sv[2]) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(socketpair)(domain, type, protocol, sv);
+ if (!res)
+ __msan_unpoison(sv, sizeof(int[2]));
+ return res;
+}
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) {
+ ENSURE_MSAN_INITED();
+ char *res = REAL(fgets_unlocked)(s, size, stream);
+ if (res)
+ __msan_unpoison(s, internal_strlen(s) + 1);
+ return res;
+}
+#define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED INTERCEPT_FUNCTION(fgets_unlocked)
+#else
+#define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
+#endif
+
+#define INTERCEPTOR_GETRLIMIT_BODY(func, resource, rlim) \
+ if (msan_init_is_running) \
+ return REAL(getrlimit)(resource, rlim); \
+ ENSURE_MSAN_INITED(); \
+ int res = REAL(func)(resource, rlim); \
+ if (!res) \
+ __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz); \
+ return res
+
+INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
+ INTERCEPTOR_GETRLIMIT_BODY(getrlimit, resource, rlim);
+}
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR(int, __getrlimit, int resource, void *rlim) {
+ INTERCEPTOR_GETRLIMIT_BODY(__getrlimit, resource, rlim);
+}
+
+INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
+ if (msan_init_is_running) return REAL(getrlimit64)(resource, rlim);
+ ENSURE_MSAN_INITED();
+ int res = REAL(getrlimit64)(resource, rlim);
+ if (!res) __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz);
+ return res;
+}
+
+INTERCEPTOR(int, prlimit, int pid, int resource, void *new_rlimit,
+ void *old_rlimit) {
+ if (msan_init_is_running)
+ return REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
+ ENSURE_MSAN_INITED();
+ CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit_sz);
+ int res = REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
+ if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit_sz);
+ return res;
+}
+
+INTERCEPTOR(int, prlimit64, int pid, int resource, void *new_rlimit,
+ void *old_rlimit) {
+ if (msan_init_is_running)
+ return REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
+ ENSURE_MSAN_INITED();
+ CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit64_sz);
+ int res = REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
+ if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit64_sz);
+ return res;
+}
+
+#define MSAN_MAYBE_INTERCEPT___GETRLIMIT INTERCEPT_FUNCTION(__getrlimit)
+#define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64)
+#define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit)
+#define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64)
+#else
+#define MSAN_MAYBE_INTERCEPT___GETRLIMIT
+#define MSAN_MAYBE_INTERCEPT_GETRLIMIT64
+#define MSAN_MAYBE_INTERCEPT_PRLIMIT
+#define MSAN_MAYBE_INTERCEPT_PRLIMIT64
+#endif
+
+INTERCEPTOR(int, gethostname, char *name, SIZE_T len) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(gethostname)(name, len);
+ if (!res || (res == -1 && errno == errno_ENAMETOOLONG)) {
+ SIZE_T real_len = internal_strnlen(name, len);
+ if (real_len < len)
+ ++real_len;
+ __msan_unpoison(name, real_len);
+ }
+ return res;
+}
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
+ int timeout) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(epoll_wait)(epfd, events, maxevents, timeout);
+ if (res > 0) {
+ __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
+ }
+ return res;
+}
+#define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait)
+#else
+#define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
+#endif
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
+ int timeout, void *sigmask) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
+ if (res > 0) {
+ __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
+ }
+ return res;
+}
+#define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait)
+#else
+#define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
+#endif
+
+INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
+ GET_MALLOC_STACK_TRACE;
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Callocate(nmemb, size);
+ return msan_calloc(nmemb, size, &stack);
+}
+
+INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
+ if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Realloc(ptr, size);
+ GET_MALLOC_STACK_TRACE;
+ return msan_realloc(ptr, size, &stack);
+}
+
+INTERCEPTOR(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size) {
+ GET_MALLOC_STACK_TRACE;
+ return msan_reallocarray(ptr, nmemb, size, &stack);
+}
+
+INTERCEPTOR(void *, malloc, SIZE_T size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Allocate(size);
+ GET_MALLOC_STACK_TRACE;
+ return msan_malloc(size, &stack);
+}
+
+void __msan_allocated_memory(const void *data, uptr size) {
+ if (flags()->poison_in_malloc) {
+ GET_MALLOC_STACK_TRACE;
+ stack.tag = STACK_TRACE_TAG_POISON;
+ PoisonMemory(data, size, &stack);
+ }
+}
+
+void __msan_copy_shadow(void *dest, const void *src, uptr n) {
+ GET_STORE_STACK_TRACE;
+ MoveShadowAndOrigin(dest, src, n, &stack);
+}
+
+void __sanitizer_dtor_callback(const void *data, uptr size) {
+ if (flags()->poison_in_dtor) {
+ GET_MALLOC_STACK_TRACE;
+ stack.tag = STACK_TRACE_TAG_POISON;
+ PoisonMemory(data, size, &stack);
+ }
+}
+
+void __sanitizer_dtor_callback_fields(const void *data, uptr size) {
+ if (flags()->poison_in_dtor) {
+ GET_MALLOC_STACK_TRACE;
+ stack.tag = STACK_TRACE_TAG_FIELDS;
+ PoisonMemory(data, size, &stack);
+ }
+}
+
+void __sanitizer_dtor_callback_vptr(const void *data) {
+ if (flags()->poison_in_dtor) {
+ GET_MALLOC_STACK_TRACE;
+ stack.tag = STACK_TRACE_TAG_VPTR;
+ PoisonMemory(data, sizeof(void *), &stack);
+ }
+}
+
+template <class Mmap>
+static void *mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length,
+ int prot, int flags, int fd, OFF64_T offset) {
+ SIZE_T rounded_length = RoundUpTo(length, GetPageSize());
+ void *end_addr = (char *)addr + (rounded_length - 1);
+ if (addr && (!MEM_IS_APP(addr) || !MEM_IS_APP(end_addr))) {
+ if (flags & map_fixed) {
+ errno = errno_EINVAL;
+ return (void *)-1;
+ } else {
+ addr = nullptr;
+ }
+ }
+ void *res = real_mmap(addr, length, prot, flags, fd, offset);
+ if (res != (void *)-1) {
+ void *end_res = (char *)res + (rounded_length - 1);
+ if (MEM_IS_APP(res) && MEM_IS_APP(end_res)) {
+ __msan_unpoison(res, rounded_length);
+ } else {
+ // Application has attempted to map more memory than is supported by
+ // MSAN. Act as if we ran out of memory.
+ internal_munmap(res, length);
+ errno = errno_ENOMEM;
+ return (void *)-1;
+ }
+ }
+ return res;
+}
+
+INTERCEPTOR(int, getrusage, int who, void *usage) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(getrusage)(who, usage);
+ if (res == 0) {
+ __msan_unpoison(usage, __sanitizer::struct_rusage_sz);
+ }
+ return res;
+}
+
+class SignalHandlerScope {
+ public:
+ SignalHandlerScope() {
+ if (MsanThread *t = GetCurrentThread())
+ t->EnterSignalHandler();
+ }
+ ~SignalHandlerScope() {
+ if (MsanThread *t = GetCurrentThread())
+ t->LeaveSignalHandler();
+ }
+};
+
+// sigactions_mu guarantees atomicity of sigaction() and signal() calls.
+// Access to sigactions[] is gone with relaxed atomics to avoid data race with
+// the signal handler.
+const int kMaxSignals = 1024;
+static atomic_uintptr_t sigactions[kMaxSignals];
+static StaticSpinMutex sigactions_mu;
+
+static void SignalHandler(int signo) {
+ SignalHandlerScope signal_handler_scope;
+ ScopedThreadLocalStateBackup stlsb;
+ UnpoisonParam(1);
+
+ typedef void (*signal_cb)(int x);
+ signal_cb cb =
+ (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
+ cb(signo);
+}
+
+static void SignalAction(int signo, void *si, void *uc) {
+ SignalHandlerScope signal_handler_scope;
+ ScopedThreadLocalStateBackup stlsb;
+ UnpoisonParam(3);
+ __msan_unpoison(si, sizeof(__sanitizer_sigaction));
+ __msan_unpoison(uc, ucontext_t_sz(uc));
+
+ typedef void (*sigaction_cb)(int, void *, void *);
+ sigaction_cb cb =
+ (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
+ cb(signo, si, uc);
+ CHECK_UNPOISONED(uc, ucontext_t_sz(uc));
+}
+
+static void read_sigaction(const __sanitizer_sigaction *act) {
+ CHECK_UNPOISONED(&act->sa_flags, sizeof(act->sa_flags));
+ if (act->sa_flags & __sanitizer::sa_siginfo)
+ CHECK_UNPOISONED(&act->sigaction, sizeof(act->sigaction));
+ else
+ CHECK_UNPOISONED(&act->handler, sizeof(act->handler));
+ CHECK_UNPOISONED(&act->sa_mask, sizeof(act->sa_mask));
+}
+
+extern "C" int pthread_attr_init(void *attr);
+extern "C" int pthread_attr_destroy(void *attr);
+
+static void *MsanThreadStartFunc(void *arg) {
+ MsanThread *t = (MsanThread *)arg;
+ SetCurrentThread(t);
+ t->Init();
+ SetSigProcMask(&t->starting_sigset_, nullptr);
+ return t->ThreadStart();
+}
+
+INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
+ void * param) {
+ ENSURE_MSAN_INITED(); // for GetTlsSize()
+ __sanitizer_pthread_attr_t myattr;
+ if (!attr) {
+ pthread_attr_init(&myattr);
+ attr = &myattr;
+ }
+
+ AdjustStackSize(attr);
+
+ MsanThread *t = MsanThread::Create(callback, param);
+ ScopedBlockSignals block(&t->starting_sigset_);
+ int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, t);
+
+ if (attr == &myattr)
+ pthread_attr_destroy(&myattr);
+ if (!res) {
+ __msan_unpoison(th, __sanitizer::pthread_t_sz);
+ }
+ return res;
+}
+
+INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key,
+ void (*dtor)(void *value)) {
+ if (msan_init_is_running) return REAL(pthread_key_create)(key, dtor);
+ ENSURE_MSAN_INITED();
+ int res = REAL(pthread_key_create)(key, dtor);
+ if (!res && key)
+ __msan_unpoison(key, sizeof(*key));
+ return res;
+}
+
+#if SANITIZER_NETBSD
+INTERCEPTOR(int, __libc_thr_keycreate, __sanitizer_pthread_key_t *m,
+ void (*dtor)(void *value))
+ALIAS(WRAPPER_NAME(pthread_key_create));
+#endif
+
+INTERCEPTOR(int, pthread_join, void *th, void **retval) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(pthread_join)(th, retval);
+ if (!res && retval)
+ __msan_unpoison(retval, sizeof(*retval));
+ return res;
+}
+
+DEFINE_REAL_PTHREAD_FUNCTIONS
+
+extern char *tzname[2];
+
+INTERCEPTOR(void, tzset, int fake) {
+ ENSURE_MSAN_INITED();
+ InterceptorScope interceptor_scope;
+ REAL(tzset)(fake);
+ if (tzname[0])
+ __msan_unpoison(tzname[0], internal_strlen(tzname[0]) + 1);
+ if (tzname[1])
+ __msan_unpoison(tzname[1], internal_strlen(tzname[1]) + 1);
+ return;
+}
+
+struct MSanAtExitRecord {
+ void (*func)(void *arg);
+ void *arg;
+};
+
+struct InterceptorContext {
+ Mutex atexit_mu;
+ Vector<struct MSanAtExitRecord *> AtExitStack;
+
+ InterceptorContext()
+ : AtExitStack() {
+ }
+};
+
+static ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)];
+InterceptorContext *interceptor_ctx() {
+ return reinterpret_cast<InterceptorContext*>(&interceptor_placeholder[0]);
+}
+
+void MSanAtExitWrapper() {
+ MSanAtExitRecord *r;
+ {
+ Lock l(&interceptor_ctx()->atexit_mu);
+
+ uptr element = interceptor_ctx()->AtExitStack.Size() - 1;
+ r = interceptor_ctx()->AtExitStack[element];
+ interceptor_ctx()->AtExitStack.PopBack();
+ }
+
+ UnpoisonParam(1);
+ ((void(*)())r->func)();
+ InternalFree(r);
+}
+
+void MSanCxaAtExitWrapper(void *arg) {
+ UnpoisonParam(1);
+ MSanAtExitRecord *r = (MSanAtExitRecord *)arg;
+ // libc before 2.27 had race which caused occasional double handler execution
+ // https://sourceware.org/ml/libc-alpha/2017-08/msg01204.html
+ if (!r->func)
+ return;
+ r->func(r->arg);
+ r->func = nullptr;
+}
+
+static int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso);
+
+// Unpoison argument shadow for C++ module destructors.
+INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
+ void *dso_handle) {
+ if (msan_init_is_running) return REAL(__cxa_atexit)(func, arg, dso_handle);
+ return setup_at_exit_wrapper((void(*)())func, arg, dso_handle);
+}
+
+// Unpoison argument shadow for C++ module destructors.
+INTERCEPTOR(int, atexit, void (*func)()) {
+ // Avoid calling real atexit as it is unreachable on at least on Linux.
+ if (msan_init_is_running)
+ return REAL(__cxa_atexit)((void (*)(void *a))func, 0, 0);
+ return setup_at_exit_wrapper((void(*)())func, 0, 0);
+}
+
+static int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso) {
+ ENSURE_MSAN_INITED();
+ MSanAtExitRecord *r =
+ (MSanAtExitRecord *)InternalAlloc(sizeof(MSanAtExitRecord));
+ r->func = (void(*)(void *a))f;
+ r->arg = arg;
+ int res;
+ if (!dso) {
+ // NetBSD does not preserve the 2nd argument if dso is equal to 0
+ // Store ctx in a local stack-like structure
+
+ Lock l(&interceptor_ctx()->atexit_mu);
+
+ res = REAL(__cxa_atexit)((void (*)(void *a))MSanAtExitWrapper, 0, 0);
+ if (!res) {
+ interceptor_ctx()->AtExitStack.PushBack(r);
+ }
+ } else {
+ res = REAL(__cxa_atexit)(MSanCxaAtExitWrapper, r, dso);
+ }
+ return res;
+}
+
+static void BeforeFork() {
+ StackDepotLockAll();
+ ChainedOriginDepotLockAll();
+}
+
+static void AfterFork() {
+ ChainedOriginDepotUnlockAll();
+ StackDepotUnlockAll();
+}
+
+INTERCEPTOR(int, fork, void) {
+ ENSURE_MSAN_INITED();
+ BeforeFork();
+ int pid = REAL(fork)();
+ AfterFork();
+ return pid;
+}
+
+// NetBSD ships with openpty(3) in -lutil, that needs to be prebuilt explicitly
+// with MSan.
+#if SANITIZER_LINUX
+INTERCEPTOR(int, openpty, int *aparent, int *aworker, char *name,
+ const void *termp, const void *winp) {
+ ENSURE_MSAN_INITED();
+ InterceptorScope interceptor_scope;
+ int res = REAL(openpty)(aparent, aworker, name, termp, winp);
+ if (!res) {
+ __msan_unpoison(aparent, sizeof(*aparent));
+ __msan_unpoison(aworker, sizeof(*aworker));
+ }
+ return res;
+}
+#define MSAN_MAYBE_INTERCEPT_OPENPTY INTERCEPT_FUNCTION(openpty)
+#else
+#define MSAN_MAYBE_INTERCEPT_OPENPTY
+#endif
+
+// NetBSD ships with forkpty(3) in -lutil, that needs to be prebuilt explicitly
+// with MSan.
+#if SANITIZER_LINUX
+INTERCEPTOR(int, forkpty, int *aparent, char *name, const void *termp,
+ const void *winp) {
+ ENSURE_MSAN_INITED();
+ InterceptorScope interceptor_scope;
+ int res = REAL(forkpty)(aparent, name, termp, winp);
+ if (res != -1)
+ __msan_unpoison(aparent, sizeof(*aparent));
+ return res;
+}
+#define MSAN_MAYBE_INTERCEPT_FORKPTY INTERCEPT_FUNCTION(forkpty)
+#else
+#define MSAN_MAYBE_INTERCEPT_FORKPTY
+#endif
+
+struct MSanInterceptorContext {
+ bool in_interceptor_scope;
+};
+
+namespace __msan {
+
+int OnExit() {
+ // FIXME: ask frontend whether we need to return failure.
+ return 0;
+}
+
+} // namespace __msan
+
+// A version of CHECK_UNPOISONED using a saved scope value. Used in common
+// interceptors.
+#define CHECK_UNPOISONED_CTX(ctx, x, n) \
+ do { \
+ if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
+ CHECK_UNPOISONED_0(x, n); \
+ } while (0)
+
+#define MSAN_INTERCEPT_FUNC(name) \
+ do { \
+ if (!INTERCEPT_FUNCTION(name)) \
+ VReport(1, "MemorySanitizer: failed to intercept '%s'\n", #name); \
+ } while (0)
+
+#define MSAN_INTERCEPT_FUNC_VER(name, ver) \
+ do { \
+ if (!INTERCEPT_FUNCTION_VER(name, ver)) \
+ VReport(1, "MemorySanitizer: failed to intercept '%s@@%s'\n", #name, \
+ ver); \
+ } while (0)
+#define MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
+ do { \
+ if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
+ VReport(1, "MemorySanitizer: failed to intercept '%s@@%s' or '%s'\n", \
+ #name, ver, #name); \
+ } while (0)
+
+#define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name)
+#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
+ MSAN_INTERCEPT_FUNC_VER(name, ver)
+#define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
+ MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
+#define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) \
+ UnpoisonParam(count)
+#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
+ __msan_unpoison(ptr, size)
+#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
+ CHECK_UNPOISONED_CTX(ctx, ptr, size)
+#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
+ __msan_unpoison(ptr, size)
+#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
+ if (msan_init_is_running) \
+ return REAL(func)(__VA_ARGS__); \
+ ENSURE_MSAN_INITED(); \
+ MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
+ ctx = (void *)&msan_ctx; \
+ (void)ctx; \
+ InterceptorScope interceptor_scope; \
+ __msan_unpoison(__errno_location(), sizeof(int));
+#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
+ do { \
+ } while (false) // FIXME
+#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
+ do { \
+ } while (false) // FIXME
+#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
+#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
+#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
+ do { \
+ link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle)); \
+ if (filename && map) \
+ ForEachMappedRegion(map, __msan_unpoison); \
+ } while (false)
+
+#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!msan_inited)
+
+#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
+ if (MsanThread *t = GetCurrentThread()) { \
+ *begin = t->tls_begin(); \
+ *end = t->tls_end(); \
+ } else { \
+ *begin = *end = 0; \
+ }
+
+#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
+ { \
+ (void)ctx; \
+ return __msan_memset(block, c, size); \
+ }
+#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
+ { \
+ (void)ctx; \
+ return __msan_memmove(to, from, size); \
+ }
+#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
+ { \
+ (void)ctx; \
+ return __msan_memcpy(to, from, size); \
+ }
+
+#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \
+ do { \
+ GET_STORE_STACK_TRACE; \
+ CopyShadowAndOrigin(to, from, size, &stack); \
+ __msan_unpoison(to + size, 1); \
+ } while (false)
+
+#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, fd, \
+ offset) \
+ do { \
+ return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \
+ } while (false)
+
+#include "sanitizer_common/sanitizer_platform_interceptors.h"
+#include "sanitizer_common/sanitizer_common_interceptors.inc"
+
+static uptr signal_impl(int signo, uptr cb);
+static int sigaction_impl(int signo, const __sanitizer_sigaction *act,
+ __sanitizer_sigaction *oldact);
+
+#define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signo, act, oldact) \
+ { return sigaction_impl(signo, act, oldact); }
+
+#define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
+ { \
+ handler = signal_impl(signo, handler); \
+ InterceptorScope interceptor_scope; \
+ return REAL(func)(signo, handler); \
+ }
+
+#include "sanitizer_common/sanitizer_signal_interceptors.inc"
+
+static int sigaction_impl(int signo, const __sanitizer_sigaction *act,
+ __sanitizer_sigaction *oldact) {
+ ENSURE_MSAN_INITED();
+ if (signo <= 0 || signo >= kMaxSignals) {
+ errno = errno_EINVAL;
+ return -1;
+ }
+ if (act) read_sigaction(act);
+ int res;
+ if (flags()->wrap_signals) {
+ SpinMutexLock lock(&sigactions_mu);
+ uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed);
+ __sanitizer_sigaction new_act;
+ __sanitizer_sigaction *pnew_act = act ? &new_act : nullptr;
+ if (act) {
+ REAL(memcpy)(pnew_act, act, sizeof(__sanitizer_sigaction));
+ uptr cb = (uptr)pnew_act->sigaction;
+ uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo)
+ ? (uptr)SignalAction
+ : (uptr)SignalHandler;
+ if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
+ atomic_store(&sigactions[signo], cb, memory_order_relaxed);
+ pnew_act->sigaction = (decltype(pnew_act->sigaction))new_cb;
+ }
+ }
+ res = REAL(SIGACTION_SYMNAME)(signo, pnew_act, oldact);
+ if (res == 0 && oldact) {
+ uptr cb = (uptr)oldact->sigaction;
+ if (cb == (uptr)SignalAction || cb == (uptr)SignalHandler) {
+ oldact->sigaction = (decltype(oldact->sigaction))old_cb;
+ }
+ }
+ } else {
+ res = REAL(SIGACTION_SYMNAME)(signo, act, oldact);
+ }
+
+ if (res == 0 && oldact) {
+ __msan_unpoison(oldact, sizeof(__sanitizer_sigaction));
+ }
+ return res;
+}
+
+static uptr signal_impl(int signo, uptr cb) {
+ ENSURE_MSAN_INITED();
+ if (signo <= 0 || signo >= kMaxSignals) {
+ errno = errno_EINVAL;
+ return -1;
+ }
+ if (flags()->wrap_signals) {
+ SpinMutexLock lock(&sigactions_mu);
+ if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
+ atomic_store(&sigactions[signo], cb, memory_order_relaxed);
+ cb = (uptr)&SignalHandler;
+ }
+ }
+ return cb;
+}
+
+#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
+#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
+ do { \
+ } while (false)
+#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
+ do { \
+ } while (false)
+#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
+#include "sanitizer_common/sanitizer_common_syscalls.inc"
+#include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
+
+INTERCEPTOR(const char *, strsignal, int sig) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strsignal, sig);
+ const char *res = REAL(strsignal)(sig);
+ if (res)
+ __msan_unpoison(res, internal_strlen(res) + 1);
+ return res;
+}
+
+struct dlinfo {
+ char *dli_fname;
+ void *dli_fbase;
+ char *dli_sname;
+ void *dli_saddr;
+};
+
+INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, dladdr, addr, info);
+ int res = REAL(dladdr)(addr, info);
+ if (res != 0) {
+ __msan_unpoison(info, sizeof(*info));
+ if (info->dli_fname)
+ __msan_unpoison(info->dli_fname, internal_strlen(info->dli_fname) + 1);
+ if (info->dli_sname)
+ __msan_unpoison(info->dli_sname, internal_strlen(info->dli_sname) + 1);
+ }
+ return res;
+}
+
+INTERCEPTOR(char *, dlerror, int fake) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, dlerror, fake);
+ char *res = REAL(dlerror)(fake);
+ if (res)
+ __msan_unpoison(res, internal_strlen(res) + 1);
+ return res;
+}
+
+typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size,
+ void *data);
+struct dl_iterate_phdr_data {
+ dl_iterate_phdr_cb callback;
+ void *data;
+};
+
+static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
+ void *data) {
+ if (info) {
+ __msan_unpoison(info, size);
+ if (info->dlpi_phdr && info->dlpi_phnum)
+ __msan_unpoison(info->dlpi_phdr, struct_ElfW_Phdr_sz * info->dlpi_phnum);
+ if (info->dlpi_name)
+ __msan_unpoison(info->dlpi_name, internal_strlen(info->dlpi_name) + 1);
+ }
+ dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
+ UnpoisonParam(3);
+ return cbdata->callback(info, size, cbdata->data);
+}
+
+INTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) {
+ ENSURE_MSAN_INITED();
+ void *p = REAL(shmat)(shmid, shmaddr, shmflg);
+ if (p != (void *)-1) {
+ __sanitizer_shmid_ds ds;
+ int res = REAL(shmctl)(shmid, shmctl_ipc_stat, &ds);
+ if (!res) {
+ __msan_unpoison(p, ds.shm_segsz);
+ }
+ }
+ return p;
+}
+
+INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, dl_iterate_phdr, callback, data);
+ dl_iterate_phdr_data cbdata;
+ cbdata.callback = callback;
+ cbdata.data = data;
+ int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata);
+ return res;
+}
+
+// wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
+INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) {
+ ENSURE_MSAN_INITED();
+ wchar_t *res = REAL(wcschr)(s, wc, ps);
+ return res;
+}
+
+// wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
+INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ wchar_t *res = REAL(wcscpy)(dest, src);
+ CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (internal_wcslen(src) + 1),
+ &stack);
+ return res;
+}
+
+INTERCEPTOR(wchar_t *, wcsncpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ SIZE_T copy_size = internal_wcsnlen(src, n);
+ if (copy_size < n) copy_size++; // trailing \0
+ wchar_t *res = REAL(wcsncpy)(dest, src, n);
+ CopyShadowAndOrigin(dest, src, copy_size * sizeof(wchar_t), &stack);
+ __msan_unpoison(dest + copy_size, (n - copy_size) * sizeof(wchar_t));
+ return res;
+}
+
+// These interface functions reside here so that they can use
+// REAL(memset), etc.
+void __msan_unpoison(const void *a, uptr size) {
+ if (!MEM_IS_APP(a)) return;
+ SetShadow(a, size, 0);
+}
+
+void __msan_poison(const void *a, uptr size) {
+ if (!MEM_IS_APP(a)) return;
+ SetShadow(a, size, __msan::flags()->poison_heap_with_zeroes ? 0 : -1);
+}
+
+void __msan_poison_stack(void *a, uptr size) {
+ if (!MEM_IS_APP(a)) return;
+ SetShadow(a, size, __msan::flags()->poison_stack_with_zeroes ? 0 : -1);
+}
+
+void __msan_unpoison_param(uptr n) { UnpoisonParam(n); }
+
+void __msan_clear_and_unpoison(void *a, uptr size) {
+ REAL(memset)(a, 0, size);
+ SetShadow(a, size, 0);
+}
+
+void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
+ if (!msan_inited) return internal_memcpy(dest, src, n);
+ if (msan_init_is_running || __msan::IsInSymbolizerOrUnwider())
+ return REAL(memcpy)(dest, src, n);
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ void *res = REAL(memcpy)(dest, src, n);
+ CopyShadowAndOrigin(dest, src, n, &stack);
+ return res;
+}
+
+void *__msan_memset(void *s, int c, SIZE_T n) {
+ if (!msan_inited) return internal_memset(s, c, n);
+ if (msan_init_is_running) return REAL(memset)(s, c, n);
+ ENSURE_MSAN_INITED();
+ void *res = REAL(memset)(s, c, n);
+ __msan_unpoison(s, n);
+ return res;
+}
+
+void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
+ if (!msan_inited) return internal_memmove(dest, src, n);
+ if (msan_init_is_running) return REAL(memmove)(dest, src, n);
+ ENSURE_MSAN_INITED();
+ GET_STORE_STACK_TRACE;
+ void *res = REAL(memmove)(dest, src, n);
+ MoveShadowAndOrigin(dest, src, n, &stack);
+ return res;
+}
+
+void __msan_unpoison_string(const char* s) {
+ if (!MEM_IS_APP(s)) return;
+ __msan_unpoison(s, internal_strlen(s) + 1);
+}
+
+namespace __msan {
+
+void InitializeInterceptors() {
+ static int inited = 0;
+ CHECK_EQ(inited, 0);
+
+ new(interceptor_ctx()) InterceptorContext();
+
+ InitializeCommonInterceptors();
+ InitializeSignalInterceptors();
+
+ INTERCEPT_FUNCTION(posix_memalign);
+ MSAN_MAYBE_INTERCEPT_MEMALIGN;
+ MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN;
+ INTERCEPT_FUNCTION(valloc);
+ MSAN_MAYBE_INTERCEPT_PVALLOC;
+ INTERCEPT_FUNCTION(malloc);
+ INTERCEPT_FUNCTION(calloc);
+ INTERCEPT_FUNCTION(realloc);
+ INTERCEPT_FUNCTION(reallocarray);
+ INTERCEPT_FUNCTION(free);
+ MSAN_MAYBE_INTERCEPT_CFREE;
+ MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE;
+ MSAN_MAYBE_INTERCEPT_MALLINFO;
+ MSAN_MAYBE_INTERCEPT_MALLOPT;
+ MSAN_MAYBE_INTERCEPT_MALLOC_STATS;
+ INTERCEPT_FUNCTION(fread);
+ MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED;
+ INTERCEPT_FUNCTION(memccpy);
+ MSAN_MAYBE_INTERCEPT_MEMPCPY;
+ INTERCEPT_FUNCTION(bcopy);
+ INTERCEPT_FUNCTION(wmemset);
+ INTERCEPT_FUNCTION(wmemcpy);
+ MSAN_MAYBE_INTERCEPT_WMEMPCPY;
+ INTERCEPT_FUNCTION(wmemmove);
+ INTERCEPT_FUNCTION(strcpy);
+ MSAN_MAYBE_INTERCEPT_STPCPY;
+ MSAN_MAYBE_INTERCEPT_STPNCPY;
+ INTERCEPT_FUNCTION(strdup);
+ MSAN_MAYBE_INTERCEPT___STRDUP;
+ INTERCEPT_FUNCTION(strncpy);
+ MSAN_MAYBE_INTERCEPT_GCVT;
+ INTERCEPT_FUNCTION(strcat);
+ INTERCEPT_FUNCTION(strncat);
+ INTERCEPT_STRTO(strtod);
+ INTERCEPT_STRTO(strtof);
+ INTERCEPT_STRTO(strtold);
+ INTERCEPT_STRTO(strtol);
+ INTERCEPT_STRTO(strtoul);
+ INTERCEPT_STRTO(strtoll);
+ INTERCEPT_STRTO(strtoull);
+ INTERCEPT_STRTO(strtouq);
+ INTERCEPT_STRTO(wcstod);
+ INTERCEPT_STRTO(wcstof);
+ INTERCEPT_STRTO(wcstold);
+ INTERCEPT_STRTO(wcstol);
+ INTERCEPT_STRTO(wcstoul);
+ INTERCEPT_STRTO(wcstoll);
+ INTERCEPT_STRTO(wcstoull);
+#ifdef SANITIZER_NLDBL_VERSION
+ INTERCEPT_FUNCTION_VER(vswprintf, SANITIZER_NLDBL_VERSION);
+ INTERCEPT_FUNCTION_VER(swprintf, SANITIZER_NLDBL_VERSION);
+#else
+ INTERCEPT_FUNCTION(vswprintf);
+ INTERCEPT_FUNCTION(swprintf);
+#endif
+ INTERCEPT_FUNCTION(strftime);
+ INTERCEPT_FUNCTION(strftime_l);
+ MSAN_MAYBE_INTERCEPT___STRFTIME_L;
+ INTERCEPT_FUNCTION(wcsftime);
+ INTERCEPT_FUNCTION(wcsftime_l);
+ MSAN_MAYBE_INTERCEPT___WCSFTIME_L;
+ INTERCEPT_FUNCTION(mbtowc);
+ INTERCEPT_FUNCTION(mbrtowc);
+ INTERCEPT_FUNCTION(wcslen);
+ INTERCEPT_FUNCTION(wcsnlen);
+ INTERCEPT_FUNCTION(wcschr);
+ INTERCEPT_FUNCTION(wcscpy);
+ INTERCEPT_FUNCTION(wcsncpy);
+ INTERCEPT_FUNCTION(wcscmp);
+ INTERCEPT_FUNCTION(getenv);
+ INTERCEPT_FUNCTION(setenv);
+ INTERCEPT_FUNCTION(putenv);
+ INTERCEPT_FUNCTION(gettimeofday);
+ MSAN_MAYBE_INTERCEPT_FCVT;
+ MSAN_MAYBE_INTERCEPT_FSTAT;
+ MSAN_MAYBE_INTERCEPT_FSTAT64;
+ MSAN_MAYBE_INTERCEPT___FXSTAT;
+ MSAN_MAYBE_INTERCEPT_FSTATAT;
+ MSAN_MAYBE_INTERCEPT_FSTATAT64;
+ MSAN_MAYBE_INTERCEPT___FXSTATAT;
+ MSAN_MAYBE_INTERCEPT___FXSTAT64;
+ MSAN_MAYBE_INTERCEPT___FXSTATAT64;
+ INTERCEPT_FUNCTION(pipe);
+ INTERCEPT_FUNCTION(pipe2);
+ INTERCEPT_FUNCTION(socketpair);
+ MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED;
+ INTERCEPT_FUNCTION(getrlimit);
+ MSAN_MAYBE_INTERCEPT___GETRLIMIT;
+ MSAN_MAYBE_INTERCEPT_GETRLIMIT64;
+ MSAN_MAYBE_INTERCEPT_PRLIMIT;
+ MSAN_MAYBE_INTERCEPT_PRLIMIT64;
+ INTERCEPT_FUNCTION(gethostname);
+ MSAN_MAYBE_INTERCEPT_EPOLL_WAIT;
+ MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT;
+ INTERCEPT_FUNCTION(strsignal);
+ INTERCEPT_FUNCTION(dladdr);
+ INTERCEPT_FUNCTION(dlerror);
+ INTERCEPT_FUNCTION(dl_iterate_phdr);
+ INTERCEPT_FUNCTION(getrusage);
+#if defined(__mips__)
+ INTERCEPT_FUNCTION_VER(pthread_create, "GLIBC_2.2");
+#else
+ INTERCEPT_FUNCTION(pthread_create);
+#endif
+ INTERCEPT_FUNCTION(pthread_join);
+ INTERCEPT_FUNCTION(pthread_key_create);
+
+#if SANITIZER_NETBSD
+ INTERCEPT_FUNCTION(__libc_thr_keycreate);
+#endif
+
+ INTERCEPT_FUNCTION(pthread_join);
+ INTERCEPT_FUNCTION(tzset);
+ INTERCEPT_FUNCTION(atexit);
+ INTERCEPT_FUNCTION(__cxa_atexit);
+ INTERCEPT_FUNCTION(shmat);
+ INTERCEPT_FUNCTION(fork);
+ MSAN_MAYBE_INTERCEPT_OPENPTY;
+ MSAN_MAYBE_INTERCEPT_FORKPTY;
+
+ inited = 1;
+}
+} // namespace __msan
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_interface_internal.h b/contrib/libs/clang16-rt/lib/msan/msan_interface_internal.h
new file mode 100644
index 00000000000..c2eead13c20
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_interface_internal.h
@@ -0,0 +1,207 @@
+//===-- msan_interface_internal.h -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+// Private MSan interface header.
+//===----------------------------------------------------------------------===//
+
+#ifndef MSAN_INTERFACE_INTERNAL_H
+#define MSAN_INTERFACE_INTERNAL_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+extern "C" {
+// FIXME: document all interface functions.
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __msan_get_track_origins();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_init();
+
+// Print a warning and maybe return.
+// This function can die based on common_flags()->exitcode.
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_warning();
+
+// Print a warning and die.
+// Instrumentation inserts calls to this function when building in "fast" mode
+// (i.e. -mllvm -msan-keep-going)
+SANITIZER_INTERFACE_ATTRIBUTE __attribute__((noreturn))
+void __msan_warning_noreturn();
+
+using __sanitizer::uptr;
+using __sanitizer::sptr;
+using __sanitizer::uu64;
+using __sanitizer::uu32;
+using __sanitizer::uu16;
+using __sanitizer::u64;
+using __sanitizer::u32;
+using __sanitizer::u16;
+using __sanitizer::u8;
+
+// Versions of the above which take Origin as a parameter
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_warning_with_origin(u32 origin);
+SANITIZER_INTERFACE_ATTRIBUTE __attribute__((noreturn)) void
+__msan_warning_with_origin_noreturn(u32 origin);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_maybe_warning_1(u8 s, u32 o);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_maybe_warning_2(u16 s, u32 o);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_maybe_warning_4(u32 s, u32 o);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_maybe_warning_8(u64 s, u32 o);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_maybe_store_origin_1(u8 s, void *p, u32 o);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_maybe_store_origin_2(u16 s, void *p, u32 o);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_maybe_store_origin_4(u32 s, void *p, u32 o);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_maybe_store_origin_8(u64 s, void *p, u32 o);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_unpoison(const void *a, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_unpoison_string(const char *s);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_unpoison_param(uptr n);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_clear_and_unpoison(void *a, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void* __msan_memcpy(void *dst, const void *src, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void* __msan_memset(void *s, int c, uptr n);
+SANITIZER_INTERFACE_ATTRIBUTE
+void* __msan_memmove(void* dest, const void* src, uptr n);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_poison(const void *a, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_poison_stack(void *a, uptr size);
+
+// Copy size bytes from src to dst and unpoison the result.
+// Useful to implement unsafe loads.
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_load_unpoisoned(void *src, uptr size, void *dst);
+
+// Returns the offset of the first (at least partially) poisoned byte,
+// or -1 if the whole range is good.
+SANITIZER_INTERFACE_ATTRIBUTE
+sptr __msan_test_shadow(const void *x, uptr size);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_check_mem_is_initialized(const void *x, uptr size);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_set_origin(const void *a, uptr size, u32 origin);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_set_alloca_origin(void *a, uptr size, char *descr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_set_alloca_origin4(void *a, uptr size, char *descr, uptr pc);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_set_alloca_origin_with_descr(void *a, uptr size, u32 *id_ptr,
+ char *descr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_set_alloca_origin_no_descr(void *a, uptr size, u32 *id_ptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+u32 __msan_chain_origin(u32 id);
+SANITIZER_INTERFACE_ATTRIBUTE
+u32 __msan_get_origin(const void *a);
+
+// Test that this_id is a descendant of prev_id (or they are simply equal).
+// "descendant" here means that are part of the same chain, created with
+// __msan_chain_origin.
+SANITIZER_INTERFACE_ATTRIBUTE
+int __msan_origin_is_descendant_or_same(u32 this_id, u32 prev_id);
+
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_clear_on_return();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_set_keep_going(int keep_going);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __msan_set_poison_in_malloc(int do_poison);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+const char *__msan_default_options();
+
+// For testing.
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_set_expect_umr(int expect_umr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_print_shadow(const void *x, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_dump_shadow(const void *x, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+int __msan_has_dynamic_component();
+
+// For testing.
+SANITIZER_INTERFACE_ATTRIBUTE
+u32 __msan_get_umr_origin();
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_partial_poison(const void* data, void* shadow, uptr size);
+
+// Tell MSan about newly allocated memory (ex.: custom allocator).
+// Memory will be marked uninitialized, with origin at the call site.
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_allocated_memory(const void* data, uptr size);
+
+// Tell MSan about newly destroyed memory. Memory will be marked
+// uninitialized.
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_dtor_callback(const void* data, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_dtor_callback_fields(const void *data, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_dtor_callback_vptr(const void *data);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+u16 __sanitizer_unaligned_load16(const uu16 *p);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+u32 __sanitizer_unaligned_load32(const uu32 *p);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+u64 __sanitizer_unaligned_load64(const uu64 *p);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store16(uu16 *p, u16 x);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store32(uu32 *p, u32 x);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store64(uu64 *p, u64 x);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_set_death_callback(void (*callback)(void));
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_copy_shadow(void *dst, const void *src, uptr size);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_scoped_disable_interceptor_checks();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_scoped_enable_interceptor_checks();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_start_switch_fiber(const void *bottom, uptr size);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_finish_switch_fiber(const void **bottom_old, uptr *size_old);
+} // extern "C"
+
+#endif // MSAN_INTERFACE_INTERNAL_H
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_linux.cpp b/contrib/libs/clang16-rt/lib/msan/msan_linux.cpp
new file mode 100644
index 00000000000..bced00ba242
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_linux.cpp
@@ -0,0 +1,261 @@
+//===-- msan_linux.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+// Linux-, NetBSD- and FreeBSD-specific code.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
+
+#include "msan.h"
+#include "msan_report.h"
+#include "msan_thread.h"
+
+#include <elf.h>
+#include <link.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <unwind.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+
+namespace __msan {
+
+void ReportMapRange(const char *descr, uptr beg, uptr size) {
+ if (size > 0) {
+ uptr end = beg + size - 1;
+ VPrintf(1, "%s : 0x%zx - 0x%zx\n", descr, beg, end);
+ }
+}
+
+static bool CheckMemoryRangeAvailability(uptr beg, uptr size) {
+ if (size > 0) {
+ uptr end = beg + size - 1;
+ if (!MemoryRangeIsAvailable(beg, end)) {
+ Printf("FATAL: Memory range 0x%zx - 0x%zx is not available.\n", beg, end);
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) {
+ if (size > 0) {
+ void *addr = MmapFixedNoAccess(beg, size, name);
+ if (beg == 0 && addr) {
+ // Depending on the kernel configuration, we may not be able to protect
+ // the page at address zero.
+ uptr gap = 16 * GetPageSizeCached();
+ beg += gap;
+ size -= gap;
+ addr = MmapFixedNoAccess(beg, size, name);
+ }
+ if ((uptr)addr != beg) {
+ uptr end = beg + size - 1;
+ Printf("FATAL: Cannot protect memory range 0x%zx - 0x%zx (%s).\n", beg,
+ end, name);
+ return false;
+ }
+ }
+ return true;
+}
+
+static void CheckMemoryLayoutSanity() {
+ uptr prev_end = 0;
+ for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
+ uptr start = kMemoryLayout[i].start;
+ uptr end = kMemoryLayout[i].end;
+ MappingDesc::Type type = kMemoryLayout[i].type;
+ CHECK_LT(start, end);
+ CHECK_EQ(prev_end, start);
+ CHECK(addr_is_type(start, type));
+ CHECK(addr_is_type((start + end) / 2, type));
+ CHECK(addr_is_type(end - 1, type));
+ if (type == MappingDesc::APP) {
+ uptr addr = start;
+ CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
+ CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
+ CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
+
+ addr = (start + end) / 2;
+ CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
+ CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
+ CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
+
+ addr = end - 1;
+ CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
+ CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
+ CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
+ }
+ prev_end = end;
+ }
+}
+
+bool InitShadow(bool init_origins) {
+ // Let user know mapping parameters first.
+ VPrintf(1, "__msan_init %p\n", reinterpret_cast<void *>(&__msan_init));
+ for (unsigned i = 0; i < kMemoryLayoutSize; ++i)
+ VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout[i].name, kMemoryLayout[i].start,
+ kMemoryLayout[i].end - 1);
+
+ CheckMemoryLayoutSanity();
+
+ if (!MEM_IS_APP(&__msan_init)) {
+ Printf("FATAL: Code %p is out of application range. Non-PIE build?\n",
+ reinterpret_cast<void *>(&__msan_init));
+ return false;
+ }
+
+ const uptr maxVirtualAddress = GetMaxUserVirtualAddress();
+
+ for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
+ uptr start = kMemoryLayout[i].start;
+ uptr end = kMemoryLayout[i].end;
+ uptr size = end - start;
+ MappingDesc::Type type = kMemoryLayout[i].type;
+
+ // Check if the segment should be mapped based on platform constraints.
+ if (start >= maxVirtualAddress)
+ continue;
+
+ bool map = type == MappingDesc::SHADOW ||
+ (init_origins && type == MappingDesc::ORIGIN);
+ bool protect = type == MappingDesc::INVALID ||
+ (!init_origins && type == MappingDesc::ORIGIN);
+ CHECK(!(map && protect));
+ if (!map && !protect)
+ CHECK(type == MappingDesc::APP);
+ if (map) {
+ if (!CheckMemoryRangeAvailability(start, size))
+ return false;
+ if (!MmapFixedSuperNoReserve(start, size, kMemoryLayout[i].name))
+ return false;
+ if (common_flags()->use_madv_dontdump)
+ DontDumpShadowMemory(start, size);
+ }
+ if (protect) {
+ if (!CheckMemoryRangeAvailability(start, size))
+ return false;
+ if (!ProtectMemoryRange(start, size, kMemoryLayout[i].name))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void MsanAtExit(void) {
+ if (flags()->print_stats && (flags()->atexit || msan_report_count > 0))
+ ReportStats();
+ if (msan_report_count > 0) {
+ ReportAtExitStatistics();
+ if (common_flags()->exitcode)
+ internal__exit(common_flags()->exitcode);
+ }
+}
+
+void InstallAtExitHandler() {
+ atexit(MsanAtExit);
+}
+
+// ---------------------- TSD ---------------- {{{1
+
+#if SANITIZER_NETBSD
+// Thread Static Data cannot be used in early init on NetBSD.
+// Reuse the MSan TSD API for compatibility with existing code
+// with an alternative implementation.
+
+static void (*tsd_destructor)(void *tsd) = nullptr;
+
+struct tsd_key {
+ tsd_key() : key(nullptr) {}
+ ~tsd_key() {
+ CHECK(tsd_destructor);
+ if (key)
+ (*tsd_destructor)(key);
+ }
+ MsanThread *key;
+};
+
+static thread_local struct tsd_key key;
+
+void MsanTSDInit(void (*destructor)(void *tsd)) {
+ CHECK(!tsd_destructor);
+ tsd_destructor = destructor;
+}
+
+MsanThread *GetCurrentThread() {
+ CHECK(tsd_destructor);
+ return key.key;
+}
+
+void SetCurrentThread(MsanThread *tsd) {
+ CHECK(tsd_destructor);
+ CHECK(tsd);
+ CHECK(!key.key);
+ key.key = tsd;
+}
+
+void MsanTSDDtor(void *tsd) {
+ CHECK(tsd_destructor);
+ CHECK_EQ(key.key, tsd);
+ key.key = nullptr;
+ // Make sure that signal handler can not see a stale current thread pointer.
+ atomic_signal_fence(memory_order_seq_cst);
+ MsanThread::TSDDtor(tsd);
+}
+#else
+static pthread_key_t tsd_key;
+static bool tsd_key_inited = false;
+
+void MsanTSDInit(void (*destructor)(void *tsd)) {
+ CHECK(!tsd_key_inited);
+ tsd_key_inited = true;
+ CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
+}
+
+static THREADLOCAL MsanThread* msan_current_thread;
+
+MsanThread *GetCurrentThread() {
+ return msan_current_thread;
+}
+
+void SetCurrentThread(MsanThread *t) {
+ // Make sure we do not reset the current MsanThread.
+ CHECK_EQ(0, msan_current_thread);
+ msan_current_thread = t;
+ // Make sure that MsanTSDDtor gets called at the end.
+ CHECK(tsd_key_inited);
+ pthread_setspecific(tsd_key, (void *)t);
+}
+
+void MsanTSDDtor(void *tsd) {
+ MsanThread *t = (MsanThread*)tsd;
+ if (t->destructor_iterations_ > 1) {
+ t->destructor_iterations_--;
+ CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
+ return;
+ }
+ msan_current_thread = nullptr;
+ // Make sure that signal handler can not see a stale current thread pointer.
+ atomic_signal_fence(memory_order_seq_cst);
+ MsanThread::TSDDtor(tsd);
+}
+#endif
+
+} // namespace __msan
+
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_new_delete.cpp b/contrib/libs/clang16-rt/lib/msan/msan_new_delete.cpp
new file mode 100644
index 00000000000..d4e95c0f651
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_new_delete.cpp
@@ -0,0 +1,108 @@
+//===-- msan_new_delete.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+// Interceptors for operators new and delete.
+//===----------------------------------------------------------------------===//
+
+#include "msan.h"
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
+
+#if MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
+
+#include <stddef.h>
+
+using namespace __msan;
+
+// Fake std::nothrow_t and std::align_val_t to avoid including <new>.
+namespace std {
+ struct nothrow_t {};
+ enum class align_val_t: size_t {};
+} // namespace std
+
+
+// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
+#define OPERATOR_NEW_BODY(nothrow) \
+ GET_MALLOC_STACK_TRACE; \
+ void *res = msan_malloc(size, &stack);\
+ if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
+ return res
+#define OPERATOR_NEW_BODY_ALIGN(nothrow) \
+ GET_MALLOC_STACK_TRACE;\
+ void *res = msan_memalign((uptr)align, size, &stack);\
+ if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
+ return res;
+
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::nothrow_t const&) {
+ OPERATOR_NEW_BODY(true /*nothrow*/);
+}
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::nothrow_t const&) {
+ OPERATOR_NEW_BODY(true /*nothrow*/);
+}
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::align_val_t align)
+{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::align_val_t align)
+{ OPERATOR_NEW_BODY_ALIGN(false /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); }
+
+#define OPERATOR_DELETE_BODY \
+ GET_MALLOC_STACK_TRACE; \
+ if (ptr) MsanDeallocate(&stack, ptr)
+
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::nothrow_t const&) {
+ OPERATOR_DELETE_BODY;
+}
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, size_t size) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY; }
+
+
+#endif // MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_origin.h b/contrib/libs/clang16-rt/lib/msan/msan_origin.h
new file mode 100644
index 00000000000..e291f538cbd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_origin.h
@@ -0,0 +1,168 @@
+//===-- msan_origin.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Origin id utils.
+//===----------------------------------------------------------------------===//
+#ifndef MSAN_ORIGIN_H
+#define MSAN_ORIGIN_H
+
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "msan_chained_origin_depot.h"
+
+namespace __msan {
+
+// Origin handling.
+//
+// Origin is a 32-bit identifier that is attached to any uninitialized value in
+// the program and describes, more or less exactly, how this memory came to be
+// uninitialized.
+//
+// There are 3 kinds of origin ids:
+// 1xxx xxxx xxxx xxxx heap origin id
+// 0000 xxxx xxxx xxxx stack origin id
+// 0zzz xxxx xxxx xxxx chained origin id
+//
+// Heap origin id describes a heap memory allocation and contains (in the xxx
+// part) a value of StackDepot.
+//
+// Stack origin id describes a stack memory allocation and contains (in the xxx
+// part) an index into StackOriginDescr and StackOriginPC. We don't store a
+// stack trace for such origins for performance reasons.
+//
+// Chained origin id describes an event of storing an uninitialized value to
+// memory. The xxx part is a value of ChainedOriginDepot, which is a mapping of
+// (stack_id, prev_id) -> id, where
+// * stack_id describes the event.
+// StackDepot keeps a mapping between those and corresponding stack traces.
+// * prev_id is another origin id that describes the earlier part of the
+// uninitialized value history.
+// Following a chain of prev_id provides the full recorded history of an
+// uninitialized value.
+//
+// This, effectively, defines a tree (or 2 trees, see below) where nodes are
+// points in value history marked with origin ids, and edges are events that are
+// marked with stack_id.
+//
+// The "zzz" bits of chained origin id are used to store the length (or depth)
+// of the origin chain.
+
+class Origin {
+ public:
+ static bool isValidId(u32 id) { return id != 0 && id != (u32)-1; }
+
+ u32 raw_id() const { return raw_id_; }
+ bool isHeapOrigin() const {
+ // 0xxx xxxx xxxx xxxx
+ return raw_id_ >> kHeapShift == 0;
+ }
+ bool isStackOrigin() const {
+ // 1000 xxxx xxxx xxxx
+ return (raw_id_ >> kDepthShift) == (1 << kDepthBits);
+ }
+ bool isChainedOrigin() const {
+ // 1zzz xxxx xxxx xxxx, zzz != 000
+ return (raw_id_ >> kDepthShift) > (1 << kDepthBits);
+ }
+ u32 getChainedId() const {
+ CHECK(isChainedOrigin());
+ return raw_id_ & kChainedIdMask;
+ }
+ u32 getStackId() const {
+ CHECK(isStackOrigin());
+ return raw_id_ & kChainedIdMask;
+ }
+ u32 getHeapId() const {
+ CHECK(isHeapOrigin());
+ return raw_id_ & kHeapIdMask;
+ }
+
+ // Returns the next origin in the chain and the current stack trace.
+ Origin getNextChainedOrigin(StackTrace *stack) const {
+ CHECK(isChainedOrigin());
+ u32 prev_id;
+ u32 stack_id = ChainedOriginDepotGet(getChainedId(), &prev_id);
+ if (stack) *stack = StackDepotGet(stack_id);
+ return Origin(prev_id);
+ }
+
+ StackTrace getStackTraceForHeapOrigin() const {
+ return StackDepotGet(getHeapId());
+ }
+
+ static Origin CreateStackOrigin(u32 id) {
+ CHECK((id & kStackIdMask) == id);
+ return Origin((1 << kHeapShift) | id);
+ }
+
+ static Origin CreateHeapOrigin(StackTrace *stack) {
+ u32 stack_id = StackDepotPut(*stack);
+ CHECK(stack_id);
+ CHECK((stack_id & kHeapIdMask) == stack_id);
+ return Origin(stack_id);
+ }
+
+ static Origin CreateChainedOrigin(Origin prev, StackTrace *stack) {
+ int depth = prev.isChainedOrigin() ? prev.depth() : 0;
+ // depth is the length of the chain minus 1.
+ // origin_history_size of 0 means unlimited depth.
+ if (flags()->origin_history_size > 0) {
+ if (depth + 1 >= flags()->origin_history_size) {
+ return prev;
+ } else {
+ ++depth;
+ CHECK(depth < (1 << kDepthBits));
+ }
+ }
+
+ StackDepotHandle h = StackDepotPut_WithHandle(*stack);
+ if (!h.valid()) return prev;
+
+ if (flags()->origin_history_per_stack_limit > 0) {
+ int use_count = h.use_count();
+ if (use_count > flags()->origin_history_per_stack_limit) return prev;
+ }
+
+ u32 chained_id;
+ bool inserted = ChainedOriginDepotPut(h.id(), prev.raw_id(), &chained_id);
+ CHECK((chained_id & kChainedIdMask) == chained_id);
+
+ if (inserted && flags()->origin_history_per_stack_limit > 0)
+ h.inc_use_count_unsafe();
+
+ return Origin((1 << kHeapShift) | (depth << kDepthShift) | chained_id);
+ }
+
+ static Origin FromRawId(u32 id) {
+ return Origin(id);
+ }
+
+ private:
+ static const int kDepthBits = 3;
+ static const int kDepthShift = 32 - kDepthBits - 1;
+
+ static const int kHeapShift = 31;
+ static const u32 kChainedIdMask = ((u32)-1) >> (32 - kDepthShift);
+ static const u32 kStackIdMask = ((u32)-1) >> (32 - kDepthShift);
+ static const u32 kHeapIdMask = ((u32)-1) >> (32 - kHeapShift);
+
+ u32 raw_id_;
+
+ explicit Origin(u32 raw_id) : raw_id_(raw_id) {}
+
+ int depth() const {
+ CHECK(isChainedOrigin());
+ return (raw_id_ >> kDepthShift) & ((1 << kDepthBits) - 1);
+ }
+
+ public:
+ static const int kMaxDepth = (1 << kDepthBits) - 1;
+};
+
+} // namespace __msan
+
+#endif // MSAN_ORIGIN_H
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_poisoning.cpp b/contrib/libs/clang16-rt/lib/msan/msan_poisoning.cpp
new file mode 100644
index 00000000000..af01aa69f78
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_poisoning.cpp
@@ -0,0 +1,253 @@
+//===-- msan_poisoning.cpp --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "msan_poisoning.h"
+
+#include "interception/interception.h"
+#include "msan_origin.h"
+#include "msan_thread.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+DECLARE_REAL(void *, memset, void *dest, int c, uptr n)
+DECLARE_REAL(void *, memcpy, void *dest, const void *src, uptr n)
+DECLARE_REAL(void *, memmove, void *dest, const void *src, uptr n)
+
+namespace __msan {
+
+u32 GetOriginIfPoisoned(uptr addr, uptr size) {
+ unsigned char *s = (unsigned char *)MEM_TO_SHADOW(addr);
+ for (uptr i = 0; i < size; ++i)
+ if (s[i]) return *(u32 *)SHADOW_TO_ORIGIN(((uptr)s + i) & ~3UL);
+ return 0;
+}
+
+void SetOriginIfPoisoned(uptr addr, uptr src_shadow, uptr size,
+ u32 src_origin) {
+ uptr dst_s = MEM_TO_SHADOW(addr);
+ uptr src_s = src_shadow;
+ uptr src_s_end = src_s + size;
+
+ for (; src_s < src_s_end; ++dst_s, ++src_s)
+ if (*(u8 *)src_s) *(u32 *)SHADOW_TO_ORIGIN(dst_s & ~3UL) = src_origin;
+}
+
+void CopyOrigin(const void *dst, const void *src, uptr size,
+ StackTrace *stack) {
+ if (!MEM_IS_APP(dst) || !MEM_IS_APP(src)) return;
+
+ uptr d = (uptr)dst;
+ uptr beg = d & ~3UL;
+ // Copy left unaligned origin if that memory is poisoned.
+ if (beg < d) {
+ u32 o = GetOriginIfPoisoned((uptr)src, beg + 4 - d);
+ if (o) {
+ if (__msan_get_track_origins() > 1) o = ChainOrigin(o, stack);
+ *(u32 *)MEM_TO_ORIGIN(beg) = o;
+ }
+ beg += 4;
+ }
+
+ uptr end = (d + size) & ~3UL;
+ // If both ends fall into the same 4-byte slot, we are done.
+ if (end < beg) return;
+
+ // Copy right unaligned origin if that memory is poisoned.
+ if (end < d + size) {
+ u32 o = GetOriginIfPoisoned((uptr)src + (end - d), (d + size) - end);
+ if (o) {
+ if (__msan_get_track_origins() > 1) o = ChainOrigin(o, stack);
+ *(u32 *)MEM_TO_ORIGIN(end) = o;
+ }
+ }
+
+ if (beg < end) {
+ // Align src up.
+ uptr s = ((uptr)src + 3) & ~3UL;
+ // FIXME: factor out to msan_copy_origin_aligned
+ if (__msan_get_track_origins() > 1) {
+ u32 *src = (u32 *)MEM_TO_ORIGIN(s);
+ u32 *src_s = (u32 *)MEM_TO_SHADOW(s);
+ u32 *src_end = (u32 *)MEM_TO_ORIGIN(s + (end - beg));
+ u32 *dst = (u32 *)MEM_TO_ORIGIN(beg);
+ u32 src_o = 0;
+ u32 dst_o = 0;
+ for (; src < src_end; ++src, ++src_s, ++dst) {
+ if (!*src_s) continue;
+ if (*src != src_o) {
+ src_o = *src;
+ dst_o = ChainOrigin(src_o, stack);
+ }
+ *dst = dst_o;
+ }
+ } else {
+ REAL(memcpy)((void *)MEM_TO_ORIGIN(beg), (void *)MEM_TO_ORIGIN(s),
+ end - beg);
+ }
+ }
+}
+
+void ReverseCopyOrigin(const void *dst, const void *src, uptr size,
+ StackTrace *stack) {
+ if (!MEM_IS_APP(dst) || !MEM_IS_APP(src))
+ return;
+
+ uptr d = (uptr)dst;
+ uptr end = (d + size) & ~3UL;
+
+ // Copy right unaligned origin if that memory is poisoned.
+ if (end < d + size) {
+ u32 o = GetOriginIfPoisoned((uptr)src + (end - d), (d + size) - end);
+ if (o) {
+ if (__msan_get_track_origins() > 1)
+ o = ChainOrigin(o, stack);
+ *(u32 *)MEM_TO_ORIGIN(end) = o;
+ }
+ }
+
+ uptr beg = d & ~3UL;
+
+ if (beg + 4 < end) {
+ // Align src up.
+ uptr s = ((uptr)src + 3) & ~3UL;
+ if (__msan_get_track_origins() > 1) {
+ u32 *src = (u32 *)MEM_TO_ORIGIN(s + end - beg - 4);
+ u32 *src_s = (u32 *)MEM_TO_SHADOW(s + end - beg - 4);
+ u32 *src_begin = (u32 *)MEM_TO_ORIGIN(s);
+ u32 *dst = (u32 *)MEM_TO_ORIGIN(end - 4);
+ u32 src_o = 0;
+ u32 dst_o = 0;
+ for (; src >= src_begin; --src, --src_s, --dst) {
+ if (!*src_s)
+ continue;
+ if (*src != src_o) {
+ src_o = *src;
+ dst_o = ChainOrigin(src_o, stack);
+ }
+ *dst = dst_o;
+ }
+ } else {
+ REAL(memmove)
+ ((void *)MEM_TO_ORIGIN(beg), (void *)MEM_TO_ORIGIN(s), end - beg - 4);
+ }
+ }
+
+ // Copy left unaligned origin if that memory is poisoned.
+ if (beg < d) {
+ u32 o = GetOriginIfPoisoned((uptr)src, beg + 4 - d);
+ if (o) {
+ if (__msan_get_track_origins() > 1)
+ o = ChainOrigin(o, stack);
+ *(u32 *)MEM_TO_ORIGIN(beg) = o;
+ }
+ }
+}
+
+void MoveOrigin(const void *dst, const void *src, uptr size,
+ StackTrace *stack) {
+ // If destination origin range overlaps with source origin range, move
+ // origins by coping origins in a reverse order; otherwise, copy origins in
+ // a normal order.
+ uptr src_aligned_beg = reinterpret_cast<uptr>(src) & ~3UL;
+ uptr src_aligned_end = (reinterpret_cast<uptr>(src) + size) & ~3UL;
+ uptr dst_aligned_beg = reinterpret_cast<uptr>(dst) & ~3UL;
+ if (dst_aligned_beg < src_aligned_end && dst_aligned_beg >= src_aligned_beg)
+ return ReverseCopyOrigin(dst, src, size, stack);
+ return CopyOrigin(dst, src, size, stack);
+}
+
+void MoveShadowAndOrigin(const void *dst, const void *src, uptr size,
+ StackTrace *stack) {
+ if (!MEM_IS_APP(dst)) return;
+ if (!MEM_IS_APP(src)) return;
+ if (src == dst) return;
+ // MoveOrigin transfers origins by refering to their shadows. So we
+ // need to move origins before moving shadows.
+ if (__msan_get_track_origins())
+ MoveOrigin(dst, src, size, stack);
+ REAL(memmove)((void *)MEM_TO_SHADOW((uptr)dst),
+ (void *)MEM_TO_SHADOW((uptr)src), size);
+}
+
+void CopyShadowAndOrigin(const void *dst, const void *src, uptr size,
+ StackTrace *stack) {
+ if (!MEM_IS_APP(dst)) return;
+ if (!MEM_IS_APP(src)) return;
+ // Because origin's range is slightly larger than app range, memcpy may also
+ // cause overlapped origin ranges.
+ REAL(memcpy)((void *)MEM_TO_SHADOW((uptr)dst),
+ (void *)MEM_TO_SHADOW((uptr)src), size);
+ if (__msan_get_track_origins())
+ MoveOrigin(dst, src, size, stack);
+}
+
+void CopyMemory(void *dst, const void *src, uptr size, StackTrace *stack) {
+ REAL(memcpy)(dst, src, size);
+ CopyShadowAndOrigin(dst, src, size, stack);
+}
+
+void SetShadow(const void *ptr, uptr size, u8 value) {
+ uptr PageSize = GetPageSizeCached();
+ uptr shadow_beg = MEM_TO_SHADOW(ptr);
+ uptr shadow_end = shadow_beg + size;
+ if (value ||
+ shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) {
+ REAL(memset)((void *)shadow_beg, value, shadow_end - shadow_beg);
+ } else {
+ uptr page_beg = RoundUpTo(shadow_beg, PageSize);
+ uptr page_end = RoundDownTo(shadow_end, PageSize);
+
+ if (page_beg >= page_end) {
+ REAL(memset)((void *)shadow_beg, 0, shadow_end - shadow_beg);
+ } else {
+ if (page_beg != shadow_beg) {
+ REAL(memset)((void *)shadow_beg, 0, page_beg - shadow_beg);
+ }
+ if (page_end != shadow_end) {
+ REAL(memset)((void *)page_end, 0, shadow_end - page_end);
+ }
+ if (!MmapFixedSuperNoReserve(page_beg, page_end - page_beg))
+ Die();
+ }
+ }
+}
+
+void SetOrigin(const void *dst, uptr size, u32 origin) {
+ // Origin mapping is 4 bytes per 4 bytes of application memory.
+ // Here we extend the range such that its left and right bounds are both
+ // 4 byte aligned.
+ uptr x = MEM_TO_ORIGIN((uptr)dst);
+ uptr beg = x & ~3UL; // align down.
+ uptr end = (x + size + 3) & ~3UL; // align up.
+ u64 origin64 = ((u64)origin << 32) | origin;
+ // This is like memset, but the value is 32-bit. We unroll by 2 to write
+ // 64 bits at once. May want to unroll further to get 128-bit stores.
+ if (beg & 7ULL) {
+ *(u32 *)beg = origin;
+ beg += 4;
+ }
+ for (uptr addr = beg; addr < (end & ~7UL); addr += 8) *(u64 *)addr = origin64;
+ if (end & 7ULL) *(u32 *)(end - 4) = origin;
+}
+
+void PoisonMemory(const void *dst, uptr size, StackTrace *stack) {
+ SetShadow(dst, size, (u8)-1);
+
+ if (__msan_get_track_origins()) {
+ MsanThread *t = GetCurrentThread();
+ if (t && t->InSignalHandler())
+ return;
+ Origin o = Origin::CreateHeapOrigin(stack);
+ SetOrigin(dst, size, o.raw_id());
+ }
+}
+
+} // namespace __msan
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_poisoning.h b/contrib/libs/clang16-rt/lib/msan/msan_poisoning.h
new file mode 100644
index 00000000000..270f1e24991
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_poisoning.h
@@ -0,0 +1,58 @@
+//===-- msan_poisoning.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MSAN_POISONING_H
+#define MSAN_POISONING_H
+
+#include "msan.h"
+
+namespace __msan {
+
+// Return origin for the first poisoned byte in the memory range, or 0.
+u32 GetOriginIfPoisoned(uptr addr, uptr size);
+
+// Walk [addr, addr+size) app memory region, copying origin tags from the
+// corresponding positions in [src_origin, src_origin+size) where the
+// corresponding shadow in [src_shadow, src_shadow+size) is non-zero.
+void SetOriginIfPoisoned(uptr addr, uptr src_shadow, uptr size, u32 src_origin);
+
+// Copy origin from src (app address) to dst (app address), creating chained
+// origin ids as necessary, without overriding origin for fully initialized
+// quads.
+void CopyOrigin(const void *dst, const void *src, uptr size, StackTrace *stack);
+
+// memmove() shadow and origin. Dst and src are application addresses.
+// See CopyOrigin() for the origin copying logic.
+void MoveShadowAndOrigin(const void *dst, const void *src, uptr size,
+ StackTrace *stack);
+
+// memcpy() shadow and origin. Dst and src are application addresses.
+// See CopyOrigin() for the origin copying logic.
+void CopyShadowAndOrigin(const void *dst, const void *src, uptr size,
+ StackTrace *stack);
+
+// memcpy() app memory, and do "the right thing" to the corresponding shadow and
+// origin regions.
+void CopyMemory(void *dst, const void *src, uptr size, StackTrace *stack);
+
+// Fill shadow will value. Ptr is an application address.
+void SetShadow(const void *ptr, uptr size, u8 value);
+
+// Set origin for the memory region.
+void SetOrigin(const void *dst, uptr size, u32 origin);
+
+// Mark memory region uninitialized, with origins.
+void PoisonMemory(const void *dst, uptr size, StackTrace *stack);
+
+} // namespace __msan
+
+#endif // MSAN_POISONING_H
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_report.cpp b/contrib/libs/clang16-rt/lib/msan/msan_report.cpp
new file mode 100644
index 00000000000..d1ef36d9a32
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_report.cpp
@@ -0,0 +1,279 @@
+//===-- msan_report.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+// Error reporting.
+//===----------------------------------------------------------------------===//
+
+#include "msan.h"
+#include "msan_chained_origin_depot.h"
+#include "msan_origin.h"
+#include "msan_report.h"
+#include "sanitizer_common/sanitizer_allocator_internal.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+
+using namespace __sanitizer;
+
+namespace __msan {
+
+class Decorator: public __sanitizer::SanitizerCommonDecorator {
+ public:
+ Decorator() : SanitizerCommonDecorator() { }
+ const char *Origin() const { return Magenta(); }
+ const char *Name() const { return Green(); }
+};
+
+static void DescribeStackOrigin(const char *so, uptr pc) {
+ Decorator d;
+ Printf("%s", d.Origin());
+ if (so) {
+ Printf(
+ " %sUninitialized value was created by an allocation of '%s%s%s'"
+ " in the stack frame%s\n",
+ d.Origin(), d.Name(), so, d.Origin(), d.Default());
+ } else {
+ Printf(" %sUninitialized value was created in the stack frame%s\n",
+ d.Origin(), d.Default());
+ }
+
+ if (pc)
+ StackTrace(&pc, 1).Print();
+}
+
+static void DescribeOrigin(u32 id) {
+ VPrintf(1, " raw origin id: %d\n", id);
+ Decorator d;
+ Origin o = Origin::FromRawId(id);
+ while (o.isChainedOrigin()) {
+ StackTrace stack;
+ o = o.getNextChainedOrigin(&stack);
+ Printf(" %sUninitialized value was stored to memory at%s\n", d.Origin(),
+ d.Default());
+ stack.Print();
+ }
+ if (o.isStackOrigin()) {
+ uptr pc;
+ const char *so = GetStackOriginDescr(o.getStackId(), &pc);
+ DescribeStackOrigin(so, pc);
+ } else {
+ StackTrace stack = o.getStackTraceForHeapOrigin();
+ switch (stack.tag) {
+ case StackTrace::TAG_ALLOC:
+ Printf(" %sUninitialized value was created by a heap allocation%s\n",
+ d.Origin(), d.Default());
+ break;
+ case StackTrace::TAG_DEALLOC:
+ Printf(" %sUninitialized value was created by a heap deallocation%s\n",
+ d.Origin(), d.Default());
+ break;
+ case STACK_TRACE_TAG_POISON:
+ Printf(" %sMemory was marked as uninitialized%s\n", d.Origin(),
+ d.Default());
+ break;
+ case STACK_TRACE_TAG_FIELDS:
+ Printf(" %sMember fields were destroyed%s\n", d.Origin(), d.Default());
+ break;
+ case STACK_TRACE_TAG_VPTR:
+ Printf(" %sVirtual table ptr was destroyed%s\n", d.Origin(),
+ d.Default());
+ break;
+ default:
+ Printf(" %sUninitialized value was created%s\n", d.Origin(),
+ d.Default());
+ break;
+ }
+ stack.Print();
+ }
+}
+
+void ReportUMR(StackTrace *stack, u32 origin) {
+ if (!__msan::flags()->report_umrs) return;
+
+ ScopedErrorReportLock l;
+
+ Decorator d;
+ Printf("%s", d.Warning());
+ Report("WARNING: MemorySanitizer: use-of-uninitialized-value\n");
+ Printf("%s", d.Default());
+ stack->Print();
+ if (origin) {
+ DescribeOrigin(origin);
+ }
+ ReportErrorSummary("use-of-uninitialized-value", stack);
+}
+
+void ReportExpectedUMRNotFound(StackTrace *stack) {
+ ScopedErrorReportLock l;
+
+ Printf("WARNING: Expected use of uninitialized value not found\n");
+ stack->Print();
+}
+
+void ReportStats() {
+ ScopedErrorReportLock l;
+
+ if (__msan_get_track_origins() > 0) {
+ StackDepotStats stack_depot_stats = StackDepotGetStats();
+ // FIXME: we want this at normal exit, too!
+ // FIXME: but only with verbosity=1 or something
+ Printf("Unique heap origins: %zu\n", stack_depot_stats.n_uniq_ids);
+ Printf("Stack depot allocated bytes: %zu\n", stack_depot_stats.allocated);
+
+ StackDepotStats chained_origin_depot_stats = ChainedOriginDepotGetStats();
+ Printf("Unique origin histories: %zu\n",
+ chained_origin_depot_stats.n_uniq_ids);
+ Printf("History depot allocated bytes: %zu\n",
+ chained_origin_depot_stats.allocated);
+ }
+}
+
+void ReportAtExitStatistics() {
+ ScopedErrorReportLock l;
+
+ if (msan_report_count > 0) {
+ Decorator d;
+ Printf("%s", d.Warning());
+ Printf("MemorySanitizer: %d warnings reported.\n", msan_report_count);
+ Printf("%s", d.Default());
+ }
+}
+
+class OriginSet {
+ public:
+ OriginSet() : next_id_(0) {}
+ int insert(u32 o) {
+ // Scan from the end for better locality.
+ for (int i = next_id_ - 1; i >= 0; --i)
+ if (origins_[i] == o) return i;
+ if (next_id_ == kMaxSize_) return OVERFLOW;
+ int id = next_id_++;
+ origins_[id] = o;
+ return id;
+ }
+ int size() { return next_id_; }
+ u32 get(int id) { return origins_[id]; }
+ static char asChar(int id) {
+ switch (id) {
+ case MISSING:
+ return '.';
+ case OVERFLOW:
+ return '*';
+ default:
+ return 'A' + id;
+ }
+ }
+ static const int OVERFLOW = -1;
+ static const int MISSING = -2;
+
+ private:
+ static const int kMaxSize_ = 'Z' - 'A' + 1;
+ u32 origins_[kMaxSize_];
+ int next_id_;
+};
+
+void DescribeMemoryRange(const void *x, uptr size) {
+ // Real limits.
+ uptr start = MEM_TO_SHADOW(x);
+ uptr end = start + size;
+ // Scan limits: align start down to 4; align size up to 16.
+ uptr s = start & ~3UL;
+ size = end - s;
+ size = (size + 15) & ~15UL;
+ uptr e = s + size;
+
+ // Single letter names to origin id mapping.
+ OriginSet origin_set;
+
+ uptr pos = 0; // Offset from aligned start.
+ bool with_origins = __msan_get_track_origins();
+ // True if there is at least 1 poisoned bit in the last 4-byte group.
+ bool last_quad_poisoned;
+ int origin_ids[4]; // Single letter origin ids for the current line.
+
+ Decorator d;
+ Printf("%s", d.Warning());
+ uptr start_x = reinterpret_cast<uptr>(x);
+ Printf("Shadow map [%p, %p) of [%p, %p), %zu bytes:\n",
+ reinterpret_cast<void *>(start), reinterpret_cast<void *>(end),
+ reinterpret_cast<void *>(start_x),
+ reinterpret_cast<void *>(start_x + end - start), end - start);
+ Printf("%s", d.Default());
+ while (s < e) {
+ // Line start.
+ if (pos % 16 == 0) {
+ for (int i = 0; i < 4; ++i) origin_ids[i] = -1;
+ Printf("%p[%p]:", reinterpret_cast<void *>(s),
+ reinterpret_cast<void *>(start_x - start + s));
+ }
+ // Group start.
+ if (pos % 4 == 0) {
+ Printf(" ");
+ last_quad_poisoned = false;
+ }
+ // Print shadow byte.
+ if (s < start || s >= end) {
+ Printf("..");
+ } else {
+ unsigned char v = *(unsigned char *)s;
+ if (v) last_quad_poisoned = true;
+ Printf("%x%x", v >> 4, v & 0xf);
+ }
+ // Group end.
+ if (pos % 4 == 3 && with_origins) {
+ int id = OriginSet::MISSING;
+ if (last_quad_poisoned) {
+ u32 o = *(u32 *)SHADOW_TO_ORIGIN(s - 3);
+ id = origin_set.insert(o);
+ }
+ origin_ids[(pos % 16) / 4] = id;
+ }
+ // Line end.
+ if (pos % 16 == 15) {
+ if (with_origins) {
+ Printf(" |");
+ for (int i = 0; i < 4; ++i) {
+ char c = OriginSet::asChar(origin_ids[i]);
+ Printf("%c", c);
+ if (i != 3) Printf(" ");
+ }
+ Printf("|");
+ }
+ Printf("\n");
+ }
+ size--;
+ s++;
+ pos++;
+ }
+
+ Printf("\n");
+
+ for (int i = 0; i < origin_set.size(); ++i) {
+ u32 o = origin_set.get(i);
+ Printf("Origin %c (origin_id %x):\n", OriginSet::asChar(i), o);
+ DescribeOrigin(o);
+ }
+}
+
+void ReportUMRInsideAddressRange(const char *what, const void *start, uptr size,
+ uptr offset) {
+ Decorator d;
+ Printf("%s", d.Warning());
+ Printf("%sUninitialized bytes in %s%s%s at offset %zu inside [%p, %zu)%s\n",
+ d.Warning(), d.Name(), what, d.Warning(), offset, start, size,
+ d.Default());
+ if (__sanitizer::Verbosity())
+ DescribeMemoryRange(start, size);
+}
+
+} // namespace __msan
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_report.h b/contrib/libs/clang16-rt/lib/msan/msan_report.h
new file mode 100644
index 00000000000..0965b8cb681
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_report.h
@@ -0,0 +1,33 @@
+//===-- msan_report.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is a part of MemorySanitizer. MSan-private header for error
+/// reporting functions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef MSAN_REPORT_H
+#define MSAN_REPORT_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+
+namespace __msan {
+
+void ReportUMR(StackTrace *stack, u32 origin);
+void ReportExpectedUMRNotFound(StackTrace *stack);
+void ReportStats();
+void ReportAtExitStatistics();
+void DescribeMemoryRange(const void *x, uptr size);
+void ReportUMRInsideAddressRange(const char *what, const void *start, uptr size,
+ uptr offset);
+
+} // namespace __msan
+
+#endif // MSAN_REPORT_H
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_thread.cpp b/contrib/libs/clang16-rt/lib/msan/msan_thread.cpp
new file mode 100644
index 00000000000..40ad6a5019c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_thread.cpp
@@ -0,0 +1,122 @@
+
+#include "msan.h"
+#include "msan_thread.h"
+#include "msan_interface_internal.h"
+
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+
+namespace __msan {
+
+MsanThread *MsanThread::Create(thread_callback_t start_routine,
+ void *arg) {
+ uptr PageSize = GetPageSizeCached();
+ uptr size = RoundUpTo(sizeof(MsanThread), PageSize);
+ MsanThread *thread = (MsanThread*)MmapOrDie(size, __func__);
+ thread->start_routine_ = start_routine;
+ thread->arg_ = arg;
+ thread->destructor_iterations_ = GetPthreadDestructorIterations();
+
+ return thread;
+}
+
+void MsanThread::SetThreadStackAndTls() {
+ uptr tls_size = 0;
+ uptr stack_size = 0;
+ GetThreadStackAndTls(IsMainThread(), &stack_.bottom, &stack_size, &tls_begin_,
+ &tls_size);
+ stack_.top = stack_.bottom + stack_size;
+ tls_end_ = tls_begin_ + tls_size;
+
+ int local;
+ CHECK(AddrIsInStack((uptr)&local));
+}
+
+void MsanThread::ClearShadowForThreadStackAndTLS() {
+ __msan_unpoison((void *)stack_.bottom, stack_.top - stack_.bottom);
+ if (tls_begin_ != tls_end_)
+ __msan_unpoison((void *)tls_begin_, tls_end_ - tls_begin_);
+ DTLS *dtls = DTLS_Get();
+ CHECK_NE(dtls, 0);
+ ForEachDVT(dtls, [](const DTLS::DTV &dtv, int id) {
+ __msan_unpoison((void *)(dtv.beg), dtv.size);
+ });
+}
+
+void MsanThread::Init() {
+ SetThreadStackAndTls();
+ CHECK(MEM_IS_APP(stack_.bottom));
+ CHECK(MEM_IS_APP(stack_.top - 1));
+ ClearShadowForThreadStackAndTLS();
+}
+
+void MsanThread::TSDDtor(void *tsd) {
+ MsanThread *t = (MsanThread*)tsd;
+ t->Destroy();
+}
+
+void MsanThread::Destroy() {
+ malloc_storage().CommitBack();
+ // We also clear the shadow on thread destruction because
+ // some code may still be executing in later TSD destructors
+ // and we don't want it to have any poisoned stack.
+ ClearShadowForThreadStackAndTLS();
+ uptr size = RoundUpTo(sizeof(MsanThread), GetPageSizeCached());
+ UnmapOrDie(this, size);
+ DTLS_Destroy();
+}
+
+thread_return_t MsanThread::ThreadStart() {
+ if (!start_routine_) {
+ // start_routine_ == 0 if we're on the main thread or on one of the
+ // OS X libdispatch worker threads. But nobody is supposed to call
+ // ThreadStart() for the worker threads.
+ return 0;
+ }
+
+ thread_return_t res = start_routine_(arg_);
+
+ return res;
+}
+
+MsanThread::StackBounds MsanThread::GetStackBounds() const {
+ if (!stack_switching_)
+ return {stack_.bottom, stack_.top};
+ const uptr cur_stack = GET_CURRENT_FRAME();
+ // Note: need to check next stack first, because FinishSwitchFiber
+ // may be in process of overwriting stack_.top/bottom_. But in such case
+ // we are already on the next stack.
+ if (cur_stack >= next_stack_.bottom && cur_stack < next_stack_.top)
+ return {next_stack_.bottom, next_stack_.top};
+ return {stack_.bottom, stack_.top};
+}
+
+uptr MsanThread::stack_top() { return GetStackBounds().top; }
+
+uptr MsanThread::stack_bottom() { return GetStackBounds().bottom; }
+
+bool MsanThread::AddrIsInStack(uptr addr) {
+ const auto bounds = GetStackBounds();
+ return addr >= bounds.bottom && addr < bounds.top;
+}
+
+void MsanThread::StartSwitchFiber(uptr bottom, uptr size) {
+ CHECK(!stack_switching_);
+ next_stack_.bottom = bottom;
+ next_stack_.top = bottom + size;
+ stack_switching_ = true;
+}
+
+void MsanThread::FinishSwitchFiber(uptr *bottom_old, uptr *size_old) {
+ CHECK(stack_switching_);
+ if (bottom_old)
+ *bottom_old = stack_.bottom;
+ if (size_old)
+ *size_old = stack_.top - stack_.bottom;
+ stack_.bottom = next_stack_.bottom;
+ stack_.top = next_stack_.top;
+ stack_switching_ = false;
+ next_stack_.top = 0;
+ next_stack_.bottom = 0;
+}
+
+} // namespace __msan
diff --git a/contrib/libs/clang16-rt/lib/msan/msan_thread.h b/contrib/libs/clang16-rt/lib/msan/msan_thread.h
new file mode 100644
index 00000000000..f6ed1534ccc
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/msan_thread.h
@@ -0,0 +1,81 @@
+//===-- msan_thread.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MSAN_THREAD_H
+#define MSAN_THREAD_H
+
+#include "msan_allocator.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_posix.h"
+namespace __msan {
+
+class MsanThread {
+ public:
+ static MsanThread *Create(thread_callback_t start_routine, void *arg);
+ static void TSDDtor(void *tsd);
+ void Destroy();
+
+ void Init(); // Should be called from the thread itself.
+ thread_return_t ThreadStart();
+
+ uptr stack_top();
+ uptr stack_bottom();
+ uptr tls_begin() { return tls_begin_; }
+ uptr tls_end() { return tls_end_; }
+ bool IsMainThread() { return start_routine_ == nullptr; }
+
+ bool AddrIsInStack(uptr addr);
+
+ bool InSignalHandler() { return in_signal_handler_; }
+ void EnterSignalHandler() { in_signal_handler_++; }
+ void LeaveSignalHandler() { in_signal_handler_--; }
+
+ void StartSwitchFiber(uptr bottom, uptr size);
+ void FinishSwitchFiber(uptr *bottom_old, uptr *size_old);
+
+ MsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
+
+ int destructor_iterations_;
+ __sanitizer_sigset_t starting_sigset_;
+
+ private:
+ // NOTE: There is no MsanThread constructor. It is allocated
+ // via mmap() and *must* be valid in zero-initialized state.
+ void SetThreadStackAndTls();
+ void ClearShadowForThreadStackAndTLS();
+ struct StackBounds {
+ uptr bottom;
+ uptr top;
+ };
+ StackBounds GetStackBounds() const;
+ thread_callback_t start_routine_;
+ void *arg_;
+
+ bool stack_switching_;
+
+ StackBounds stack_;
+ StackBounds next_stack_;
+
+ uptr tls_begin_;
+ uptr tls_end_;
+
+ unsigned in_signal_handler_;
+
+ MsanThreadLocalMallocStorage malloc_storage_;
+};
+
+MsanThread *GetCurrentThread();
+void SetCurrentThread(MsanThread *t);
+
+} // namespace __msan
+
+#endif // MSAN_THREAD_H
diff --git a/contrib/libs/clang16-rt/lib/msan/ya.make b/contrib/libs/clang16-rt/lib/msan/ya.make
new file mode 100644
index 00000000000..bcbdf424a3c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan/ya.make
@@ -0,0 +1,134 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.msan${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHAVE_RPC_XDR_H=0
+ -DUBSAN_CAN_USE_CXXABI
+ -fPIE
+ -ffreestanding
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ interception/interception_linux.cpp
+ interception/interception_mac.cpp
+ interception/interception_type_test.cpp
+ interception/interception_win.cpp
+ msan/msan.cpp
+ msan/msan_allocator.cpp
+ msan/msan_chained_origin_depot.cpp
+ msan/msan_interceptors.cpp
+ msan/msan_linux.cpp
+ msan/msan_poisoning.cpp
+ msan/msan_report.cpp
+ msan/msan_thread.cpp
+ sanitizer_common/sancov_flags.cpp
+ sanitizer_common/sanitizer_allocator.cpp
+ sanitizer_common/sanitizer_allocator_checks.cpp
+ sanitizer_common/sanitizer_allocator_report.cpp
+ sanitizer_common/sanitizer_chained_origin_depot.cpp
+ sanitizer_common/sanitizer_common.cpp
+ sanitizer_common/sanitizer_common_libcdep.cpp
+ sanitizer_common/sanitizer_coverage_fuchsia.cpp
+ sanitizer_common/sanitizer_coverage_libcdep_new.cpp
+ sanitizer_common/sanitizer_coverage_win_sections.cpp
+ sanitizer_common/sanitizer_deadlock_detector1.cpp
+ sanitizer_common/sanitizer_deadlock_detector2.cpp
+ sanitizer_common/sanitizer_errno.cpp
+ sanitizer_common/sanitizer_file.cpp
+ sanitizer_common/sanitizer_flag_parser.cpp
+ sanitizer_common/sanitizer_flags.cpp
+ sanitizer_common/sanitizer_fuchsia.cpp
+ sanitizer_common/sanitizer_libc.cpp
+ sanitizer_common/sanitizer_libignore.cpp
+ sanitizer_common/sanitizer_linux.cpp
+ sanitizer_common/sanitizer_linux_libcdep.cpp
+ sanitizer_common/sanitizer_linux_s390.cpp
+ sanitizer_common/sanitizer_mac.cpp
+ sanitizer_common/sanitizer_mac_libcdep.cpp
+ sanitizer_common/sanitizer_mutex.cpp
+ sanitizer_common/sanitizer_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+ sanitizer_common/sanitizer_platform_limits_linux.cpp
+ sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_posix.cpp
+ sanitizer_common/sanitizer_platform_limits_solaris.cpp
+ sanitizer_common/sanitizer_posix.cpp
+ sanitizer_common/sanitizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_printf.cpp
+ sanitizer_common/sanitizer_procmaps_bsd.cpp
+ sanitizer_common/sanitizer_procmaps_common.cpp
+ sanitizer_common/sanitizer_procmaps_fuchsia.cpp
+ sanitizer_common/sanitizer_procmaps_linux.cpp
+ sanitizer_common/sanitizer_procmaps_mac.cpp
+ sanitizer_common/sanitizer_procmaps_solaris.cpp
+ sanitizer_common/sanitizer_solaris.cpp
+ sanitizer_common/sanitizer_stack_store.cpp
+ sanitizer_common/sanitizer_stackdepot.cpp
+ sanitizer_common/sanitizer_stacktrace.cpp
+ sanitizer_common/sanitizer_stacktrace_libcdep.cpp
+ sanitizer_common/sanitizer_stacktrace_printer.cpp
+ sanitizer_common/sanitizer_stacktrace_sparc.cpp
+ sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
+ sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_mac.cpp
+ sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_win.cpp
+ sanitizer_common/sanitizer_suppressions.cpp
+ sanitizer_common/sanitizer_symbolizer.cpp
+ sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
+ sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_mac.cpp
+ sanitizer_common/sanitizer_symbolizer_markup.cpp
+ sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_report.cpp
+ sanitizer_common/sanitizer_symbolizer_win.cpp
+ sanitizer_common/sanitizer_termination.cpp
+ sanitizer_common/sanitizer_thread_registry.cpp
+ sanitizer_common/sanitizer_tls_get_addr.cpp
+ sanitizer_common/sanitizer_type_traits.cpp
+ sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
+ sanitizer_common/sanitizer_unwind_win.cpp
+ sanitizer_common/sanitizer_win.cpp
+ ubsan/ubsan_diag.cpp
+ ubsan/ubsan_flags.cpp
+ ubsan/ubsan_handlers.cpp
+ ubsan/ubsan_init.cpp
+ ubsan/ubsan_monitor.cpp
+ ubsan/ubsan_value.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/msan_cxx/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/msan_cxx/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan_cxx/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/msan_cxx/ya.make b/contrib/libs/clang16-rt/lib/msan_cxx/ya.make
new file mode 100644
index 00000000000..2bb733ce0d7
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/msan_cxx/ya.make
@@ -0,0 +1,53 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.msan_cxx${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DUBSAN_CAN_USE_CXXABI
+ -fPIE
+ -ffreestanding
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -frtti
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ msan/msan_new_delete.cpp
+ ubsan/ubsan_handlers_cxx.cpp
+ ubsan/ubsan_type_hash.cpp
+ ubsan/ubsan_type_hash_itanium.cpp
+ ubsan/ubsan_type_hash_win.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/profile/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/profile/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/profile/GCDAProfiling.c b/contrib/libs/clang16-rt/lib/profile/GCDAProfiling.c
new file mode 100644
index 00000000000..4f46fd2839b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/GCDAProfiling.c
@@ -0,0 +1,637 @@
+/*===- GCDAProfiling.c - Support library for GCDA file emission -----------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+|*===----------------------------------------------------------------------===*|
+|*
+|* This file implements the call back routines for the gcov profiling
+|* instrumentation pass. Link against this library when running code through
+|* the -insert-gcov-profiling LLVM pass.
+|*
+|* We emit files in a corrupt version of GCOV's "gcda" file format. These files
+|* are only close enough that LCOV will happily parse them. Anything that lcov
+|* ignores is missing.
+|*
+|* TODO: gcov is multi-process safe by having each exit open the existing file
+|* and append to it. We'd like to achieve that and be thread-safe too.
+|*
+\*===----------------------------------------------------------------------===*/
+
+#if !defined(__Fuchsia__)
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(_WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include "WindowsMMap.h"
+#else
+#include <sys/file.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#include "InstrProfiling.h"
+#include "InstrProfilingUtil.h"
+
+/* #define DEBUG_GCDAPROFILING */
+
+enum {
+ GCOV_DATA_MAGIC = 0x67636461, // "gcda"
+
+ GCOV_TAG_FUNCTION = 0x01000000,
+ GCOV_TAG_COUNTER_ARCS = 0x01a10000,
+ // GCOV_TAG_OBJECT_SUMMARY superseded GCOV_TAG_PROGRAM_SUMMARY in GCC 9.
+ GCOV_TAG_OBJECT_SUMMARY = 0xa1000000,
+ GCOV_TAG_PROGRAM_SUMMARY = 0xa3000000,
+};
+
+/*
+ * --- GCOV file format I/O primitives ---
+ */
+
+/*
+ * The current file name we're outputting. Used primarily for error logging.
+ */
+static char *filename = NULL;
+
+/*
+ * The current file we're outputting.
+ */
+static FILE *output_file = NULL;
+
+/*
+ * Buffer that we write things into.
+ */
+#define WRITE_BUFFER_SIZE (128 * 1024)
+static unsigned char *write_buffer = NULL;
+static uint64_t cur_buffer_size = 0;
+static uint64_t cur_pos = 0;
+static uint64_t file_size = 0;
+static int new_file = 0;
+static int gcov_version;
+#if defined(_WIN32)
+static HANDLE mmap_handle = NULL;
+#endif
+static int fd = -1;
+
+typedef void (*fn_ptr)(void);
+
+typedef void* dynamic_object_id;
+// The address of this variable identifies a given dynamic object.
+static dynamic_object_id current_id;
+#define CURRENT_ID (&current_id)
+
+struct fn_node {
+ dynamic_object_id id;
+ fn_ptr fn;
+ struct fn_node* next;
+};
+
+struct fn_list {
+ struct fn_node *head, *tail;
+};
+
+/*
+ * A list of functions to write out the data, shared between all dynamic objects.
+ */
+struct fn_list writeout_fn_list;
+
+/*
+ * A list of reset functions, shared between all dynamic objects.
+ */
+struct fn_list reset_fn_list;
+
+static void fn_list_insert(struct fn_list* list, fn_ptr fn) {
+ struct fn_node* new_node = malloc(sizeof(struct fn_node));
+ new_node->fn = fn;
+ new_node->next = NULL;
+ new_node->id = CURRENT_ID;
+
+ if (!list->head) {
+ list->head = list->tail = new_node;
+ } else {
+ list->tail->next = new_node;
+ list->tail = new_node;
+ }
+}
+
+static void fn_list_remove(struct fn_list* list) {
+ struct fn_node* curr = list->head;
+ struct fn_node* prev = NULL;
+ struct fn_node* next = NULL;
+
+ while (curr) {
+ next = curr->next;
+
+ if (curr->id == CURRENT_ID) {
+ if (curr == list->head) {
+ list->head = next;
+ }
+
+ if (curr == list->tail) {
+ list->tail = prev;
+ }
+
+ if (prev) {
+ prev->next = next;
+ }
+
+ free(curr);
+ } else {
+ prev = curr;
+ }
+
+ curr = next;
+ }
+}
+
+static void resize_write_buffer(uint64_t size) {
+ if (!new_file) return;
+ size += cur_pos;
+ if (size <= cur_buffer_size) return;
+ size = (size - 1) / WRITE_BUFFER_SIZE + 1;
+ size *= WRITE_BUFFER_SIZE;
+ write_buffer = realloc(write_buffer, size);
+ cur_buffer_size = size;
+}
+
+static void write_bytes(const char *s, size_t len) {
+ resize_write_buffer(len);
+ memcpy(&write_buffer[cur_pos], s, len);
+ cur_pos += len;
+}
+
+static void write_32bit_value(uint32_t i) {
+ write_bytes((char*)&i, 4);
+}
+
+static void write_64bit_value(uint64_t i) {
+ // GCOV uses a lo-/hi-word format even on big-endian systems.
+ // See also GCOVBuffer::readInt64 in LLVM.
+ uint32_t lo = (uint32_t) i;
+ uint32_t hi = (uint32_t) (i >> 32);
+ write_32bit_value(lo);
+ write_32bit_value(hi);
+}
+
+static uint32_t read_32bit_value(void) {
+ uint32_t val;
+
+ if (new_file)
+ return (uint32_t)-1;
+
+ val = *(uint32_t*)&write_buffer[cur_pos];
+ cur_pos += 4;
+ return val;
+}
+
+static uint64_t read_64bit_value(void) {
+ // GCOV uses a lo-/hi-word format even on big-endian systems.
+ // See also GCOVBuffer::readInt64 in LLVM.
+ uint32_t lo = read_32bit_value();
+ uint32_t hi = read_32bit_value();
+ return ((uint64_t)hi << 32) | ((uint64_t)lo);
+}
+
+static char *mangle_filename(const char *orig_filename) {
+ char *new_filename;
+ size_t prefix_len;
+ int prefix_strip;
+ const char *prefix = lprofGetPathPrefix(&prefix_strip, &prefix_len);
+
+ if (prefix == NULL)
+ return strdup(orig_filename);
+
+ new_filename = malloc(prefix_len + 1 + strlen(orig_filename) + 1);
+ lprofApplyPathPrefix(new_filename, orig_filename, prefix, prefix_len,
+ prefix_strip);
+
+ return new_filename;
+}
+
+static int map_file(void) {
+ fseek(output_file, 0L, SEEK_END);
+ file_size = ftell(output_file);
+
+ /* A size of 0 means the file has been created just now (possibly by another
+ * process in lock-after-open race condition). No need to mmap. */
+ if (file_size == 0)
+ return -1;
+
+#if defined(_WIN32)
+ HANDLE mmap_fd;
+ if (fd == -1)
+ mmap_fd = INVALID_HANDLE_VALUE;
+ else
+ mmap_fd = (HANDLE)_get_osfhandle(fd);
+
+ mmap_handle = CreateFileMapping(mmap_fd, NULL, PAGE_READWRITE, DWORD_HI(file_size), DWORD_LO(file_size), NULL);
+ if (mmap_handle == NULL) {
+ fprintf(stderr, "profiling: %s: cannot create file mapping: %lu\n",
+ filename, GetLastError());
+ return -1;
+ }
+
+ write_buffer = MapViewOfFile(mmap_handle, FILE_MAP_WRITE, 0, 0, file_size);
+ if (write_buffer == NULL) {
+ fprintf(stderr, "profiling: %s: cannot map: %lu\n", filename,
+ GetLastError());
+ CloseHandle(mmap_handle);
+ return -1;
+ }
+#else
+ write_buffer = mmap(0, file_size, PROT_READ | PROT_WRITE,
+ MAP_FILE | MAP_SHARED, fd, 0);
+ if (write_buffer == (void *)-1) {
+ int errnum = errno;
+ fprintf(stderr, "profiling: %s: cannot map: %s\n", filename,
+ strerror(errnum));
+ return -1;
+ }
+#endif
+
+ return 0;
+}
+
+static void unmap_file(void) {
+#if defined(_WIN32)
+ if (!UnmapViewOfFile(write_buffer)) {
+ fprintf(stderr, "profiling: %s: cannot unmap mapped view: %lu\n", filename,
+ GetLastError());
+ }
+
+ if (!CloseHandle(mmap_handle)) {
+ fprintf(stderr, "profiling: %s: cannot close file mapping handle: %lu\n",
+ filename, GetLastError());
+ }
+
+ mmap_handle = NULL;
+#else
+ if (munmap(write_buffer, file_size) == -1) {
+ int errnum = errno;
+ fprintf(stderr, "profiling: %s: cannot munmap: %s\n", filename,
+ strerror(errnum));
+ }
+#endif
+
+ write_buffer = NULL;
+ file_size = 0;
+}
+
+/*
+ * --- LLVM line counter API ---
+ */
+
+/* A file in this case is a translation unit. Each .o file built with line
+ * profiling enabled will emit to a different file. Only one file may be
+ * started at a time.
+ */
+COMPILER_RT_VISIBILITY
+void llvm_gcda_start_file(const char *orig_filename, uint32_t version,
+ uint32_t checksum) {
+ const char *mode = "r+b";
+ filename = mangle_filename(orig_filename);
+
+ /* Try just opening the file. */
+ fd = open(filename, O_RDWR | O_BINARY);
+
+ if (fd == -1) {
+ /* Try creating the file. */
+ fd = open(filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0644);
+ if (fd != -1) {
+ mode = "w+b";
+ } else {
+ /* Try creating the directories first then opening the file. */
+ __llvm_profile_recursive_mkdir(filename);
+ fd = open(filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0644);
+ if (fd != -1) {
+ mode = "w+b";
+ } else {
+ /* Another process may have created the file just now.
+ * Try opening it without O_CREAT and O_EXCL. */
+ fd = open(filename, O_RDWR | O_BINARY);
+ if (fd == -1) {
+ /* Bah! It's hopeless. */
+ int errnum = errno;
+ fprintf(stderr, "profiling: %s: cannot open: %s\n", filename,
+ strerror(errnum));
+ return;
+ }
+ }
+ }
+ }
+
+ /* Try to flock the file to serialize concurrent processes writing out to the
+ * same GCDA. This can fail if the filesystem doesn't support it, but in that
+ * case we'll just carry on with the old racy behaviour and hope for the best.
+ */
+ lprofLockFd(fd);
+ output_file = fdopen(fd, mode);
+
+ /* Initialize the write buffer. */
+ new_file = 0;
+ write_buffer = NULL;
+ cur_buffer_size = 0;
+ cur_pos = 0;
+
+ if (map_file() == -1) {
+ /* The file has been created just now (file_size == 0) or mmap failed
+ * unexpectedly. In the latter case, try to recover by clobbering. */
+ new_file = 1;
+ write_buffer = NULL;
+ resize_write_buffer(WRITE_BUFFER_SIZE);
+ memset(write_buffer, 0, WRITE_BUFFER_SIZE);
+ }
+
+ /* gcda file, version, stamp checksum. */
+ {
+ uint8_t c3 = version >> 24;
+ uint8_t c2 = (version >> 16) & 255;
+ uint8_t c1 = (version >> 8) & 255;
+ gcov_version = c3 >= 'A' ? (c3 - 'A') * 100 + (c2 - '0') * 10 + c1 - '0'
+ : (c3 - '0') * 10 + c1 - '0';
+ }
+ write_32bit_value(GCOV_DATA_MAGIC);
+ write_32bit_value(version);
+ write_32bit_value(checksum);
+
+#ifdef DEBUG_GCDAPROFILING
+ fprintf(stderr, "llvmgcda: [%s]\n", orig_filename);
+#endif
+}
+
+COMPILER_RT_VISIBILITY
+void llvm_gcda_emit_function(uint32_t ident, uint32_t func_checksum,
+ uint32_t cfg_checksum) {
+ uint32_t len = 2;
+ int use_extra_checksum = gcov_version >= 47;
+
+ if (use_extra_checksum)
+ len++;
+#ifdef DEBUG_GCDAPROFILING
+ fprintf(stderr, "llvmgcda: function id=0x%08x\n", ident);
+#endif
+ if (!output_file) return;
+
+ /* function tag */
+ write_32bit_value(GCOV_TAG_FUNCTION);
+ write_32bit_value(len);
+ write_32bit_value(ident);
+ write_32bit_value(func_checksum);
+ if (use_extra_checksum)
+ write_32bit_value(cfg_checksum);
+}
+
+COMPILER_RT_VISIBILITY
+void llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) {
+ uint32_t i;
+ uint64_t *old_ctrs = NULL;
+ uint32_t val = 0;
+ uint64_t save_cur_pos = cur_pos;
+
+ if (!output_file) return;
+
+ val = read_32bit_value();
+
+ if (val != (uint32_t)-1) {
+ /* There are counters present in the file. Merge them. */
+ if (val != GCOV_TAG_COUNTER_ARCS) {
+ fprintf(stderr, "profiling: %s: cannot merge previous GCDA file: "
+ "corrupt arc tag (0x%08x)\n",
+ filename, val);
+ return;
+ }
+
+ val = read_32bit_value();
+ if (val == (uint32_t)-1 || val / 2 != num_counters) {
+ fprintf(stderr, "profiling: %s: cannot merge previous GCDA file: "
+ "mismatched number of counters (%d)\n",
+ filename, val);
+ return;
+ }
+
+ old_ctrs = malloc(sizeof(uint64_t) * num_counters);
+ for (i = 0; i < num_counters; ++i)
+ old_ctrs[i] = read_64bit_value();
+ }
+
+ cur_pos = save_cur_pos;
+
+ /* Counter #1 (arcs) tag */
+ write_32bit_value(GCOV_TAG_COUNTER_ARCS);
+ write_32bit_value(num_counters * 2);
+ for (i = 0; i < num_counters; ++i) {
+ counters[i] += (old_ctrs ? old_ctrs[i] : 0);
+ write_64bit_value(counters[i]);
+ }
+
+ free(old_ctrs);
+
+#ifdef DEBUG_GCDAPROFILING
+ fprintf(stderr, "llvmgcda: %u arcs\n", num_counters);
+ for (i = 0; i < num_counters; ++i)
+ fprintf(stderr, "llvmgcda: %llu\n", (unsigned long long)counters[i]);
+#endif
+}
+
+COMPILER_RT_VISIBILITY
+void llvm_gcda_summary_info(void) {
+ uint32_t runs = 1;
+ static uint32_t run_counted = 0; // We only want to increase the run count once.
+ uint32_t val = 0;
+ uint64_t save_cur_pos = cur_pos;
+
+ if (!output_file) return;
+
+ val = read_32bit_value();
+
+ if (val != (uint32_t)-1) {
+ /* There are counters present in the file. Merge them. */
+ uint32_t gcov_tag =
+ gcov_version >= 90 ? GCOV_TAG_OBJECT_SUMMARY : GCOV_TAG_PROGRAM_SUMMARY;
+ if (val != gcov_tag) {
+ fprintf(stderr,
+ "profiling: %s: cannot merge previous run count: "
+ "corrupt object tag (0x%08x)\n",
+ filename, val);
+ return;
+ }
+
+ val = read_32bit_value(); /* length */
+ uint32_t prev_runs;
+ if (gcov_version < 90) {
+ read_32bit_value();
+ read_32bit_value();
+ prev_runs = read_32bit_value();
+ } else {
+ prev_runs = read_32bit_value();
+ read_32bit_value();
+ }
+ for (uint32_t i = gcov_version < 90 ? 3 : 2; i < val; ++i)
+ read_32bit_value();
+ /* Add previous run count to new counter, if not already counted before. */
+ runs = run_counted ? prev_runs : prev_runs + 1;
+ }
+
+ cur_pos = save_cur_pos;
+
+ if (gcov_version >= 90) {
+ write_32bit_value(GCOV_TAG_OBJECT_SUMMARY);
+ write_32bit_value(2);
+ write_32bit_value(runs);
+ write_32bit_value(0); // sum_max
+ } else {
+ // Before gcov 4.8 (r190952), GCOV_TAG_SUMMARY_LENGTH was 9. r190952 set
+ // GCOV_TAG_SUMMARY_LENGTH to 22. We simply use the smallest length which
+ // can make gcov read "Runs:".
+ write_32bit_value(GCOV_TAG_PROGRAM_SUMMARY);
+ write_32bit_value(3);
+ write_32bit_value(0);
+ write_32bit_value(0);
+ write_32bit_value(runs);
+ }
+
+ run_counted = 1;
+
+#ifdef DEBUG_GCDAPROFILING
+ fprintf(stderr, "llvmgcda: %u runs\n", runs);
+#endif
+}
+
+COMPILER_RT_VISIBILITY
+void llvm_gcda_end_file(void) {
+ /* Write out EOF record. */
+ if (output_file) {
+ write_bytes("\0\0\0\0\0\0\0\0", 8);
+
+ if (new_file) {
+ fwrite(write_buffer, cur_pos, 1, output_file);
+ free(write_buffer);
+ } else {
+ unmap_file();
+ }
+
+ fflush(output_file);
+ lprofUnlockFd(fd);
+ fclose(output_file);
+ output_file = NULL;
+ write_buffer = NULL;
+ }
+ free(filename);
+
+#ifdef DEBUG_GCDAPROFILING
+ fprintf(stderr, "llvmgcda: -----\n");
+#endif
+}
+
+COMPILER_RT_VISIBILITY
+void llvm_register_writeout_function(fn_ptr fn) {
+ fn_list_insert(&writeout_fn_list, fn);
+}
+
+COMPILER_RT_VISIBILITY
+void llvm_writeout_files(void) {
+ struct fn_node *curr = writeout_fn_list.head;
+
+ while (curr) {
+ if (curr->id == CURRENT_ID) {
+ curr->fn();
+ }
+ curr = curr->next;
+ }
+}
+
+#ifndef _WIN32
+// __attribute__((destructor)) and destructors whose priorities are greater than
+// 100 run before this function and can thus be tracked. The priority is
+// compatible with GCC 7 onwards.
+#if __GNUC__ >= 9
+#pragma GCC diagnostic ignored "-Wprio-ctor-dtor"
+#endif
+__attribute__((destructor(100)))
+#endif
+static void llvm_writeout_and_clear(void) {
+ llvm_writeout_files();
+ fn_list_remove(&writeout_fn_list);
+}
+
+COMPILER_RT_VISIBILITY
+void llvm_register_reset_function(fn_ptr fn) {
+ fn_list_insert(&reset_fn_list, fn);
+}
+
+COMPILER_RT_VISIBILITY
+void llvm_delete_reset_function_list(void) { fn_list_remove(&reset_fn_list); }
+
+COMPILER_RT_VISIBILITY
+void llvm_reset_counters(void) {
+ struct fn_node *curr = reset_fn_list.head;
+
+ while (curr) {
+ if (curr->id == CURRENT_ID) {
+ curr->fn();
+ }
+ curr = curr->next;
+ }
+}
+
+#if !defined(_WIN32)
+COMPILER_RT_VISIBILITY
+pid_t __gcov_fork() {
+ pid_t parent_pid = getpid();
+ pid_t pid = fork();
+
+ if (pid == 0) {
+ pid_t child_pid = getpid();
+ if (child_pid != parent_pid) {
+ // The pid changed so we've a fork (one could have its own fork function)
+ // Just reset the counters for this child process
+ // threads.
+ llvm_reset_counters();
+ }
+ }
+ return pid;
+}
+#endif
+
+COMPILER_RT_VISIBILITY
+void llvm_gcov_init(fn_ptr wfn, fn_ptr rfn) {
+ static int atexit_ran = 0;
+
+ if (wfn)
+ llvm_register_writeout_function(wfn);
+
+ if (rfn)
+ llvm_register_reset_function(rfn);
+
+ if (atexit_ran == 0) {
+ atexit_ran = 1;
+
+ /* Make sure we write out the data and delete the data structures. */
+ atexit(llvm_delete_reset_function_list);
+#ifdef _WIN32
+ atexit(llvm_writeout_and_clear);
+#endif
+ }
+}
+
+void __gcov_dump(void) {
+ for (struct fn_node *f = writeout_fn_list.head; f; f = f->next)
+ f->fn();
+}
+
+void __gcov_reset(void) {
+ for (struct fn_node *f = reset_fn_list.head; f; f = f->next)
+ f->fn();
+}
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfiling.c b/contrib/libs/clang16-rt/lib/profile/InstrProfiling.c
new file mode 100644
index 00000000000..fdb7b7cd806
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfiling.c
@@ -0,0 +1,76 @@
+/*===- InstrProfiling.c - Support library for PGO instrumentation ---------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+// Note: This is linked into the Darwin kernel, and must remain compatible
+// with freestanding compilation. See `darwin_add_builtin_libraries`.
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+
+#define INSTR_PROF_VALUE_PROF_DATA
+#include "profile/InstrProfData.inc"
+
+COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_magic(void) {
+ return sizeof(void *) == sizeof(uint64_t) ? (INSTR_PROF_RAW_MAGIC_64)
+ : (INSTR_PROF_RAW_MAGIC_32);
+}
+
+COMPILER_RT_VISIBILITY void __llvm_profile_set_dumped(void) {
+ lprofSetProfileDumped(1);
+}
+
+/* Return the number of bytes needed to add to SizeInBytes to make it
+ * the result a multiple of 8.
+ */
+COMPILER_RT_VISIBILITY uint8_t
+__llvm_profile_get_num_padding_bytes(uint64_t SizeInBytes) {
+ return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
+}
+
+COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_version(void) {
+ return INSTR_PROF_RAW_VERSION_VAR;
+}
+
+COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) {
+ char *I = __llvm_profile_begin_counters();
+ char *E = __llvm_profile_end_counters();
+
+ char ResetValue =
+ (__llvm_profile_get_version() & VARIANT_MASK_BYTE_COVERAGE) ? 0xFF : 0;
+ memset(I, ResetValue, E - I);
+
+ const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
+ const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
+ const __llvm_profile_data *DI;
+ for (DI = DataBegin; DI < DataEnd; ++DI) {
+ uint64_t CurrentVSiteCount = 0;
+ uint32_t VKI, i;
+ if (!DI->Values)
+ continue;
+
+ ValueProfNode **ValueCounters = (ValueProfNode **)DI->Values;
+
+ for (VKI = IPVK_First; VKI <= IPVK_Last; ++VKI)
+ CurrentVSiteCount += DI->NumValueSites[VKI];
+
+ for (i = 0; i < CurrentVSiteCount; ++i) {
+ ValueProfNode *CurrVNode = ValueCounters[i];
+
+ while (CurrVNode) {
+ CurrVNode->Count = 0;
+ CurrVNode = CurrVNode->Next;
+ }
+ }
+ }
+ lprofSetProfileDumped(0);
+}
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfiling.h b/contrib/libs/clang16-rt/lib/profile/InstrProfiling.h
new file mode 100644
index 00000000000..4433d7bd488
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfiling.h
@@ -0,0 +1,329 @@
+/*===- InstrProfiling.h- Support library for PGO instrumentation ----------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+#ifndef PROFILE_INSTRPROFILING_H_
+#define PROFILE_INSTRPROFILING_H_
+
+#include "InstrProfilingPort.h"
+#include <stdio.h>
+
+#define INSTR_PROF_VISIBILITY COMPILER_RT_VISIBILITY
+#include "profile/InstrProfData.inc"
+
+enum ValueKind {
+#define VALUE_PROF_KIND(Enumerator, Value, Descr) Enumerator = Value,
+#include "profile/InstrProfData.inc"
+};
+
+typedef void *IntPtrT;
+typedef struct COMPILER_RT_ALIGNAS(INSTR_PROF_DATA_ALIGNMENT)
+ __llvm_profile_data {
+#define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) Type Name;
+#include "profile/InstrProfData.inc"
+} __llvm_profile_data;
+
+typedef struct __llvm_profile_header {
+#define INSTR_PROF_RAW_HEADER(Type, Name, Initializer) Type Name;
+#include "profile/InstrProfData.inc"
+} __llvm_profile_header;
+
+typedef struct ValueProfNode * PtrToNodeT;
+typedef struct ValueProfNode {
+#define INSTR_PROF_VALUE_NODE(Type, LLVMType, Name, Initializer) Type Name;
+#include "profile/InstrProfData.inc"
+} ValueProfNode;
+
+/*!
+ * \brief Return 1 if profile counters are continuously synced to the raw
+ * profile via an mmap(). This is in contrast to the default mode, in which
+ * the raw profile is written out at program exit time.
+ */
+int __llvm_profile_is_continuous_mode_enabled(void);
+
+/*!
+ * \brief Enable continuous mode.
+ *
+ * See \ref __llvm_profile_is_continuous_mode_enabled. The behavior is undefined
+ * if continuous mode is already enabled, or if it cannot be enable due to
+ * conflicting options.
+ */
+void __llvm_profile_enable_continuous_mode(void);
+
+/*!
+ * \brief Set the page size.
+ *
+ * This is a pre-requisite for enabling continuous mode. The buffer size
+ * calculation code inside of libprofile cannot simply call getpagesize(), as
+ * it is not allowed to depend on libc.
+ */
+void __llvm_profile_set_page_size(unsigned PageSize);
+
+/*!
+ * \brief Get number of bytes necessary to pad the argument to eight
+ * byte boundary.
+ */
+uint8_t __llvm_profile_get_num_padding_bytes(uint64_t SizeInBytes);
+
+/*!
+ * \brief Get required size for profile buffer.
+ */
+uint64_t __llvm_profile_get_size_for_buffer(void);
+
+/*!
+ * \brief Write instrumentation data to the given buffer.
+ *
+ * \pre \c Buffer is the start of a buffer at least as big as \a
+ * __llvm_profile_get_size_for_buffer().
+ */
+int __llvm_profile_write_buffer(char *Buffer);
+
+const __llvm_profile_data *__llvm_profile_begin_data(void);
+const __llvm_profile_data *__llvm_profile_end_data(void);
+const char *__llvm_profile_begin_names(void);
+const char *__llvm_profile_end_names(void);
+char *__llvm_profile_begin_counters(void);
+char *__llvm_profile_end_counters(void);
+ValueProfNode *__llvm_profile_begin_vnodes();
+ValueProfNode *__llvm_profile_end_vnodes();
+uint32_t *__llvm_profile_begin_orderfile();
+
+/*!
+ * \brief Clear profile counters to zero.
+ *
+ */
+void __llvm_profile_reset_counters(void);
+
+/*!
+ * \brief Merge profile data from buffer.
+ *
+ * Read profile data form buffer \p Profile and merge with in-process profile
+ * counters. The client is expected to have checked or already knows the profile
+ * data in the buffer matches the in-process counter structure before calling
+ * it. Returns 0 (success) if the profile data is valid. Upon reading
+ * invalid/corrupted profile data, returns 1 (failure).
+ */
+int __llvm_profile_merge_from_buffer(const char *Profile, uint64_t Size);
+
+/*! \brief Check if profile in buffer matches the current binary.
+ *
+ * Returns 0 (success) if the profile data in buffer \p Profile with size
+ * \p Size was generated by the same binary and therefore matches
+ * structurally the in-process counters. If the profile data in buffer is
+ * not compatible, the interface returns 1 (failure).
+ */
+int __llvm_profile_check_compatibility(const char *Profile,
+ uint64_t Size);
+
+/*!
+ * \brief Counts the number of times a target value is seen.
+ *
+ * Records the target value for the CounterIndex if not seen before. Otherwise,
+ * increments the counter associated w/ the target value.
+ * void __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
+ * uint32_t CounterIndex);
+ */
+void INSTR_PROF_VALUE_PROF_FUNC(
+#define VALUE_PROF_FUNC_PARAM(ArgType, ArgName, ArgLLVMType) ArgType ArgName
+#include "profile/InstrProfData.inc"
+ );
+
+void __llvm_profile_instrument_target_value(uint64_t TargetValue, void *Data,
+ uint32_t CounterIndex,
+ uint64_t CounterValue);
+
+/*!
+ * \brief Write instrumentation data to the current file.
+ *
+ * Writes to the file with the last name given to \a *
+ * __llvm_profile_set_filename(),
+ * or if it hasn't been called, the \c LLVM_PROFILE_FILE environment variable,
+ * or if that's not set, the last name set to INSTR_PROF_PROFILE_NAME_VAR,
+ * or if that's not set, \c "default.profraw".
+ */
+int __llvm_profile_write_file(void);
+
+int __llvm_orderfile_write_file(void);
+/*!
+ * \brief this is a wrapper interface to \c __llvm_profile_write_file.
+ * After this interface is invoked, an already dumped flag will be set
+ * so that profile won't be dumped again during program exit.
+ * Invocation of interface __llvm_profile_reset_counters will clear
+ * the flag. This interface is designed to be used to collect profile
+ * data from user selected hot regions. The use model is
+ * __llvm_profile_reset_counters();
+ * ... hot region 1
+ * __llvm_profile_dump();
+ * .. some other code
+ * __llvm_profile_reset_counters();
+ * ... hot region 2
+ * __llvm_profile_dump();
+ *
+ * It is expected that on-line profile merging is on with \c %m specifier
+ * used in profile filename . If merging is not turned on, user is expected
+ * to invoke __llvm_profile_set_filename to specify different profile names
+ * for different regions before dumping to avoid profile write clobbering.
+ */
+int __llvm_profile_dump(void);
+
+int __llvm_orderfile_dump(void);
+
+/*!
+ * \brief Set the filename for writing instrumentation data.
+ *
+ * Sets the filename to be used for subsequent calls to
+ * \a __llvm_profile_write_file().
+ *
+ * \c Name is not copied, so it must remain valid. Passing NULL resets the
+ * filename logic to the default behaviour.
+ *
+ * Note: There may be multiple copies of the profile runtime (one for each
+ * instrumented image/DSO). This API only modifies the filename within the
+ * copy of the runtime available to the calling image.
+ *
+ * Warning: This is a no-op if continuous mode (\ref
+ * __llvm_profile_is_continuous_mode_enabled) is on. The reason for this is
+ * that in continuous mode, profile counters are mmap()'d to the profile at
+ * program initialization time. Support for transferring the mmap'd profile
+ * counts to a new file has not been implemented.
+ */
+void __llvm_profile_set_filename(const char *Name);
+
+/*!
+ * \brief Set the FILE object for writing instrumentation data. Return 0 if set
+ * successfully or return 1 if failed.
+ *
+ * Sets the FILE object to be used for subsequent calls to
+ * \a __llvm_profile_write_file(). The profile file name set by environment
+ * variable, command-line option, or calls to \a __llvm_profile_set_filename
+ * will be ignored.
+ *
+ * \c File will not be closed after a call to \a __llvm_profile_write_file() but
+ * it may be flushed. Passing NULL restores default behavior.
+ *
+ * If \c EnableMerge is nonzero, the runtime will always merge profiling data
+ * with the contents of the profiling file. If EnableMerge is zero, the runtime
+ * may still merge the data if it would have merged for another reason (for
+ * example, because of a %m specifier in the file name).
+ *
+ * Note: There may be multiple copies of the profile runtime (one for each
+ * instrumented image/DSO). This API only modifies the file object within the
+ * copy of the runtime available to the calling image.
+ *
+ * Warning: This is a no-op if EnableMerge is 0 in continuous mode (\ref
+ * __llvm_profile_is_continuous_mode_enabled), because disable merging requires
+ * copying the old profile file to new profile file and this function is usually
+ * used when the proess doesn't have permission to open file.
+ */
+int __llvm_profile_set_file_object(FILE *File, int EnableMerge);
+
+/*! \brief Register to write instrumentation data to file at exit. */
+int __llvm_profile_register_write_file_atexit(void);
+
+/*! \brief Initialize file handling. */
+void __llvm_profile_initialize_file(void);
+
+/*! \brief Initialize the profile runtime. */
+void __llvm_profile_initialize(void);
+
+/*!
+ * \brief Return path prefix (excluding the base filename) of the profile data.
+ * This is useful for users using \c -fprofile-generate=./path_prefix who do
+ * not care about the default raw profile name. It is also useful to collect
+ * more than more profile data files dumped in the same directory (Online
+ * merge mode is turned on for instrumented programs with shared libs).
+ * Side-effect: this API call will invoke malloc with dynamic memory allocation.
+ */
+const char *__llvm_profile_get_path_prefix();
+
+/*!
+ * \brief Return filename (including path) of the profile data. Note that if the
+ * user calls __llvm_profile_set_filename later after invoking this interface,
+ * the actual file name may differ from what is returned here.
+ * Side-effect: this API call will invoke malloc with dynamic memory allocation
+ * (the returned pointer must be passed to `free` to avoid a leak).
+ *
+ * Note: There may be multiple copies of the profile runtime (one for each
+ * instrumented image/DSO). This API only retrieves the filename from the copy
+ * of the runtime available to the calling image.
+ */
+const char *__llvm_profile_get_filename();
+
+/*! \brief Get the magic token for the file format. */
+uint64_t __llvm_profile_get_magic(void);
+
+/*! \brief Get the version of the file format. */
+uint64_t __llvm_profile_get_version(void);
+
+/*! \brief Get the number of entries in the profile data section. */
+uint64_t __llvm_profile_get_num_data(const __llvm_profile_data *Begin,
+ const __llvm_profile_data *End);
+
+/*! \brief Get the size of the profile data section in bytes. */
+uint64_t __llvm_profile_get_data_size(const __llvm_profile_data *Begin,
+ const __llvm_profile_data *End);
+
+/*! \brief Get the size in bytes of a single counter entry. */
+size_t __llvm_profile_counter_entry_size(void);
+
+/*! \brief Get the number of entries in the profile counters section. */
+uint64_t __llvm_profile_get_num_counters(const char *Begin, const char *End);
+
+/*! \brief Get the size of the profile counters section in bytes. */
+uint64_t __llvm_profile_get_counters_size(const char *Begin, const char *End);
+
+/* ! \brief Given the sizes of the data and counter information, return the
+ * number of padding bytes before and after the counters, and after the names,
+ * in the raw profile.
+ *
+ * Note: When mmap() mode is disabled, no padding bytes before/after counters
+ * are needed. However, in mmap() mode, the counter section in the raw profile
+ * must be page-aligned: this API computes the number of padding bytes
+ * needed to achieve that.
+ */
+void __llvm_profile_get_padding_sizes_for_counters(
+ uint64_t DataSize, uint64_t CountersSize, uint64_t NamesSize,
+ uint64_t *PaddingBytesBeforeCounters, uint64_t *PaddingBytesAfterCounters,
+ uint64_t *PaddingBytesAfterNames);
+
+/*!
+ * \brief Set the flag that profile data has been dumped to the file.
+ * This is useful for users to disable dumping profile data to the file for
+ * certain processes in case the processes don't have permission to write to
+ * the disks, and trying to do so would result in side effects such as crashes.
+ */
+void __llvm_profile_set_dumped();
+
+/*!
+ * This variable is defined in InstrProfilingRuntime.cpp as a hidden
+ * symbol. Its main purpose is to enable profile runtime user to
+ * bypass runtime initialization code -- if the client code explicitly
+ * define this variable, then InstProfileRuntime.o won't be linked in.
+ * Note that this variable's visibility needs to be hidden so that the
+ * definition of this variable in an instrumented shared library won't
+ * affect runtime initialization decision of the main program.
+ * __llvm_profile_profile_runtime. */
+COMPILER_RT_VISIBILITY extern int INSTR_PROF_PROFILE_RUNTIME_VAR;
+
+/*!
+ * This variable is defined in InstrProfilingVersionVar.c as a hidden symbol
+ * (except on Apple platforms where this symbol is checked by TAPI). Its main
+ * purpose is to encode the raw profile version value and other format related
+ * information such as whether the profile is from IR based instrumentation. The
+ * variable is defined as weak so that compiler can emit an overriding
+ * definition depending on user option.
+ */
+extern uint64_t INSTR_PROF_RAW_VERSION_VAR; /* __llvm_profile_raw_version */
+
+/*!
+ * This variable is a weak symbol defined in InstrProfiling.c. It allows
+ * compiler instrumentation to provide overriding definition with value
+ * from compiler command line. This variable has default visibility.
+ */
+extern char INSTR_PROF_PROFILE_NAME_VAR[1]; /* __llvm_profile_filename. */
+
+#endif /* PROFILE_INSTRPROFILING_H_ */
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingBuffer.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingBuffer.c
new file mode 100644
index 00000000000..57f8b68919b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingBuffer.c
@@ -0,0 +1,167 @@
+/*===- InstrProfilingBuffer.c - Write instrumentation to a memory buffer --===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+// Note: This is linked into the Darwin kernel, and must remain compatible
+// with freestanding compilation. See `darwin_add_builtin_libraries`.
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+#include "InstrProfilingPort.h"
+
+/* When continuous mode is enabled (%c), this parameter is set to 1.
+ *
+ * This parameter is defined here in InstrProfilingBuffer.o, instead of in
+ * InstrProfilingFile.o, to sequester all libc-dependent code in
+ * InstrProfilingFile.o. The test `instrprof-without-libc` will break if this
+ * layering is violated. */
+static int ContinuouslySyncProfile = 0;
+
+/* The system page size. Only valid when non-zero. If 0, the page size is
+ * unavailable. */
+static unsigned PageSize = 0;
+
+COMPILER_RT_VISIBILITY int __llvm_profile_is_continuous_mode_enabled(void) {
+ return ContinuouslySyncProfile && PageSize;
+}
+
+COMPILER_RT_VISIBILITY void __llvm_profile_enable_continuous_mode(void) {
+ ContinuouslySyncProfile = 1;
+}
+
+COMPILER_RT_VISIBILITY void __llvm_profile_set_page_size(unsigned PS) {
+ PageSize = PS;
+}
+
+COMPILER_RT_VISIBILITY
+uint64_t __llvm_profile_get_size_for_buffer(void) {
+ const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
+ const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
+ const char *CountersBegin = __llvm_profile_begin_counters();
+ const char *CountersEnd = __llvm_profile_end_counters();
+ const char *NamesBegin = __llvm_profile_begin_names();
+ const char *NamesEnd = __llvm_profile_end_names();
+
+ return __llvm_profile_get_size_for_buffer_internal(
+ DataBegin, DataEnd, CountersBegin, CountersEnd, NamesBegin, NamesEnd);
+}
+
+COMPILER_RT_VISIBILITY
+uint64_t __llvm_profile_get_num_data(const __llvm_profile_data *Begin,
+ const __llvm_profile_data *End) {
+ intptr_t BeginI = (intptr_t)Begin, EndI = (intptr_t)End;
+ return ((EndI + sizeof(__llvm_profile_data) - 1) - BeginI) /
+ sizeof(__llvm_profile_data);
+}
+
+COMPILER_RT_VISIBILITY
+uint64_t __llvm_profile_get_data_size(const __llvm_profile_data *Begin,
+ const __llvm_profile_data *End) {
+ return __llvm_profile_get_num_data(Begin, End) * sizeof(__llvm_profile_data);
+}
+
+COMPILER_RT_VISIBILITY size_t __llvm_profile_counter_entry_size(void) {
+ if (__llvm_profile_get_version() & VARIANT_MASK_BYTE_COVERAGE)
+ return sizeof(uint8_t);
+ return sizeof(uint64_t);
+}
+
+COMPILER_RT_VISIBILITY
+uint64_t __llvm_profile_get_num_counters(const char *Begin, const char *End) {
+ intptr_t BeginI = (intptr_t)Begin, EndI = (intptr_t)End;
+ return ((EndI + __llvm_profile_counter_entry_size() - 1) - BeginI) /
+ __llvm_profile_counter_entry_size();
+}
+
+COMPILER_RT_VISIBILITY
+uint64_t __llvm_profile_get_counters_size(const char *Begin, const char *End) {
+ return __llvm_profile_get_num_counters(Begin, End) *
+ __llvm_profile_counter_entry_size();
+}
+
+/// Calculate the number of padding bytes needed to add to \p Offset in order
+/// for (\p Offset + Padding) to be page-aligned.
+static uint64_t calculateBytesNeededToPageAlign(uint64_t Offset) {
+ uint64_t OffsetModPage = Offset % PageSize;
+ if (OffsetModPage > 0)
+ return PageSize - OffsetModPage;
+ return 0;
+}
+
+static int needsCounterPadding(void) {
+#if defined(__APPLE__)
+ return __llvm_profile_is_continuous_mode_enabled();
+#else
+ return 0;
+#endif
+}
+
+COMPILER_RT_VISIBILITY
+void __llvm_profile_get_padding_sizes_for_counters(
+ uint64_t DataSize, uint64_t CountersSize, uint64_t NamesSize,
+ uint64_t *PaddingBytesBeforeCounters, uint64_t *PaddingBytesAfterCounters,
+ uint64_t *PaddingBytesAfterNames) {
+ if (!needsCounterPadding()) {
+ *PaddingBytesBeforeCounters = 0;
+ *PaddingBytesAfterCounters = 0;
+ *PaddingBytesAfterNames = __llvm_profile_get_num_padding_bytes(NamesSize);
+ return;
+ }
+
+ // In continuous mode, the file offsets for headers and for the start of
+ // counter sections need to be page-aligned.
+ *PaddingBytesBeforeCounters =
+ calculateBytesNeededToPageAlign(sizeof(__llvm_profile_header) + DataSize);
+ *PaddingBytesAfterCounters = calculateBytesNeededToPageAlign(CountersSize);
+ *PaddingBytesAfterNames = calculateBytesNeededToPageAlign(NamesSize);
+}
+
+COMPILER_RT_VISIBILITY
+uint64_t __llvm_profile_get_size_for_buffer_internal(
+ const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd,
+ const char *CountersBegin, const char *CountersEnd, const char *NamesBegin,
+ const char *NamesEnd) {
+ /* Match logic in __llvm_profile_write_buffer(). */
+ const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
+ uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
+ uint64_t CountersSize =
+ __llvm_profile_get_counters_size(CountersBegin, CountersEnd);
+
+ /* Determine how much padding is needed before/after the counters and after
+ * the names. */
+ uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
+ PaddingBytesAfterNames;
+ __llvm_profile_get_padding_sizes_for_counters(
+ DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
+ &PaddingBytesAfterCounters, &PaddingBytesAfterNames);
+
+ return sizeof(__llvm_profile_header) + __llvm_write_binary_ids(NULL) +
+ DataSize + PaddingBytesBeforeCounters + CountersSize +
+ PaddingBytesAfterCounters + NamesSize + PaddingBytesAfterNames;
+}
+
+COMPILER_RT_VISIBILITY
+void initBufferWriter(ProfDataWriter *BufferWriter, char *Buffer) {
+ BufferWriter->Write = lprofBufferWriter;
+ BufferWriter->WriterCtx = Buffer;
+}
+
+COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer(char *Buffer) {
+ ProfDataWriter BufferWriter;
+ initBufferWriter(&BufferWriter, Buffer);
+ return lprofWriteData(&BufferWriter, 0, 0);
+}
+
+COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
+ char *Buffer, const __llvm_profile_data *DataBegin,
+ const __llvm_profile_data *DataEnd, const char *CountersBegin,
+ const char *CountersEnd, const char *NamesBegin, const char *NamesEnd) {
+ ProfDataWriter BufferWriter;
+ initBufferWriter(&BufferWriter, Buffer);
+ return lprofWriteDataImpl(&BufferWriter, DataBegin, DataEnd, CountersBegin,
+ CountersEnd, 0, NamesBegin, NamesEnd, 0);
+}
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingFile.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingFile.c
new file mode 100644
index 00000000000..f74be55bcd5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingFile.c
@@ -0,0 +1,1194 @@
+/*===- InstrProfilingFile.c - Write instrumentation to a file -------------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+#if !defined(__Fuchsia__)
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _MSC_VER
+/* For _alloca. */
+#include <malloc.h>
+#endif
+#if defined(_WIN32)
+#include "WindowsMMap.h"
+/* For _chsize_s */
+#include <io.h>
+#include <process.h>
+#else
+#include <sys/file.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#if defined(__linux__)
+#include <sys/types.h>
+#endif
+#endif
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+#include "InstrProfilingPort.h"
+#include "InstrProfilingUtil.h"
+
+/* From where is profile name specified.
+ * The order the enumerators define their
+ * precedence. Re-order them may lead to
+ * runtime behavior change. */
+typedef enum ProfileNameSpecifier {
+ PNS_unknown = 0,
+ PNS_default,
+ PNS_command_line,
+ PNS_environment,
+ PNS_runtime_api
+} ProfileNameSpecifier;
+
+static const char *getPNSStr(ProfileNameSpecifier PNS) {
+ switch (PNS) {
+ case PNS_default:
+ return "default setting";
+ case PNS_command_line:
+ return "command line";
+ case PNS_environment:
+ return "environment variable";
+ case PNS_runtime_api:
+ return "runtime API";
+ default:
+ return "Unknown";
+ }
+}
+
+#define MAX_PID_SIZE 16
+/* Data structure holding the result of parsed filename pattern. */
+typedef struct lprofFilename {
+ /* File name string possibly with %p or %h specifiers. */
+ const char *FilenamePat;
+ /* A flag indicating if FilenamePat's memory is allocated
+ * by runtime. */
+ unsigned OwnsFilenamePat;
+ const char *ProfilePathPrefix;
+ char PidChars[MAX_PID_SIZE];
+ char *TmpDir;
+ char Hostname[COMPILER_RT_MAX_HOSTLEN];
+ unsigned NumPids;
+ unsigned NumHosts;
+ /* When in-process merging is enabled, this parameter specifies
+ * the total number of profile data files shared by all the processes
+ * spawned from the same binary. By default the value is 1. If merging
+ * is not enabled, its value should be 0. This parameter is specified
+ * by the %[0-9]m specifier. For instance %2m enables merging using
+ * 2 profile data files. %1m is equivalent to %m. Also %m specifier
+ * can only appear once at the end of the name pattern. */
+ unsigned MergePoolSize;
+ ProfileNameSpecifier PNS;
+} lprofFilename;
+
+static lprofFilename lprofCurFilename = {0, 0, 0, {0}, NULL,
+ {0}, 0, 0, 0, PNS_unknown};
+
+static int ProfileMergeRequested = 0;
+static int getProfileFileSizeForMerging(FILE *ProfileFile,
+ uint64_t *ProfileFileSize);
+
+#if defined(__APPLE__)
+static const int ContinuousModeSupported = 1;
+static const int UseBiasVar = 0;
+static const char *FileOpenMode = "a+b";
+static void *BiasAddr = NULL;
+static void *BiasDefaultAddr = NULL;
+static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
+ /* Get the sizes of various profile data sections. Taken from
+ * __llvm_profile_get_size_for_buffer(). */
+ const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
+ const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
+ const char *CountersBegin = __llvm_profile_begin_counters();
+ const char *CountersEnd = __llvm_profile_end_counters();
+ const char *NamesBegin = __llvm_profile_begin_names();
+ const char *NamesEnd = __llvm_profile_end_names();
+ const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
+ uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
+ uint64_t CountersSize =
+ __llvm_profile_get_counters_size(CountersBegin, CountersEnd);
+
+ /* Check that the counter and data sections in this image are
+ * page-aligned. */
+ unsigned PageSize = getpagesize();
+ if ((intptr_t)CountersBegin % PageSize != 0) {
+ PROF_ERR("Counters section not page-aligned (start = %p, pagesz = %u).\n",
+ CountersBegin, PageSize);
+ return 1;
+ }
+ if ((intptr_t)DataBegin % PageSize != 0) {
+ PROF_ERR("Data section not page-aligned (start = %p, pagesz = %u).\n",
+ DataBegin, PageSize);
+ return 1;
+ }
+ int Fileno = fileno(File);
+ /* Determine how much padding is needed before/after the counters and
+ * after the names. */
+ uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
+ PaddingBytesAfterNames;
+ __llvm_profile_get_padding_sizes_for_counters(
+ DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
+ &PaddingBytesAfterCounters, &PaddingBytesAfterNames);
+
+ uint64_t PageAlignedCountersLength = CountersSize + PaddingBytesAfterCounters;
+ uint64_t FileOffsetToCounters = CurrentFileOffset +
+ sizeof(__llvm_profile_header) + DataSize +
+ PaddingBytesBeforeCounters;
+ void *CounterMmap = mmap((void *)CountersBegin, PageAlignedCountersLength,
+ PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
+ Fileno, FileOffsetToCounters);
+ if (CounterMmap != CountersBegin) {
+ PROF_ERR(
+ "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
+ " - CountersBegin: %p\n"
+ " - PageAlignedCountersLength: %" PRIu64 "\n"
+ " - Fileno: %d\n"
+ " - FileOffsetToCounters: %" PRIu64 "\n",
+ strerror(errno), CountersBegin, PageAlignedCountersLength, Fileno,
+ FileOffsetToCounters);
+ return 1;
+ }
+ return 0;
+}
+#elif defined(__ELF__) || defined(_WIN32)
+
+#define INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR \
+ INSTR_PROF_CONCAT(INSTR_PROF_PROFILE_COUNTER_BIAS_VAR, _default)
+COMPILER_RT_VISIBILITY intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR = 0;
+
+/* This variable is a weak external reference which could be used to detect
+ * whether or not the compiler defined this symbol. */
+#if defined(_MSC_VER)
+COMPILER_RT_VISIBILITY extern intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_VAR;
+#if defined(_M_IX86) || defined(__i386__)
+#define WIN_SYM_PREFIX "_"
+#else
+#define WIN_SYM_PREFIX
+#endif
+#pragma comment( \
+ linker, "/alternatename:" WIN_SYM_PREFIX INSTR_PROF_QUOTE( \
+ INSTR_PROF_PROFILE_COUNTER_BIAS_VAR) "=" WIN_SYM_PREFIX \
+ INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR))
+#else
+COMPILER_RT_VISIBILITY extern intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_VAR
+ __attribute__((weak, alias(INSTR_PROF_QUOTE(
+ INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR))));
+#endif
+static const int ContinuousModeSupported = 1;
+static const int UseBiasVar = 1;
+/* TODO: If there are two DSOs, the second DSO initilization will truncate the
+ * first profile file. */
+static const char *FileOpenMode = "w+b";
+/* This symbol is defined by the compiler when runtime counter relocation is
+ * used and runtime provides a weak alias so we can check if it's defined. */
+static void *BiasAddr = &INSTR_PROF_PROFILE_COUNTER_BIAS_VAR;
+static void *BiasDefaultAddr = &INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR;
+static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
+ /* Get the sizes of various profile data sections. Taken from
+ * __llvm_profile_get_size_for_buffer(). */
+ const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
+ const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
+ const char *CountersBegin = __llvm_profile_begin_counters();
+ const char *CountersEnd = __llvm_profile_end_counters();
+ uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
+ /* Get the file size. */
+ uint64_t FileSize = 0;
+ if (getProfileFileSizeForMerging(File, &FileSize))
+ return 1;
+
+ /* Map the profile. */
+ char *Profile = (char *)mmap(NULL, FileSize, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fileno(File), 0);
+ if (Profile == MAP_FAILED) {
+ PROF_ERR("Unable to mmap profile: %s\n", strerror(errno));
+ return 1;
+ }
+ const uint64_t CountersOffsetInBiasMode =
+ sizeof(__llvm_profile_header) + __llvm_write_binary_ids(NULL) + DataSize;
+ /* Update the profile fields based on the current mapping. */
+ INSTR_PROF_PROFILE_COUNTER_BIAS_VAR =
+ (intptr_t)Profile - (uintptr_t)CountersBegin + CountersOffsetInBiasMode;
+
+ /* Return the memory allocated for counters to OS. */
+ lprofReleaseMemoryPagesToOS((uintptr_t)CountersBegin, (uintptr_t)CountersEnd);
+ return 0;
+}
+#else
+static const int ContinuousModeSupported = 0;
+static const int UseBiasVar = 0;
+static const char *FileOpenMode = "a+b";
+static void *BiasAddr = NULL;
+static void *BiasDefaultAddr = NULL;
+static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
+ return 0;
+}
+#endif
+
+static int isProfileMergeRequested(void) { return ProfileMergeRequested; }
+static void setProfileMergeRequested(int EnableMerge) {
+ ProfileMergeRequested = EnableMerge;
+}
+
+static FILE *ProfileFile = NULL;
+static FILE *getProfileFile(void) { return ProfileFile; }
+static void setProfileFile(FILE *File) { ProfileFile = File; }
+
+static int getCurFilenameLength(void);
+static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf);
+static unsigned doMerging(void) {
+ return lprofCurFilename.MergePoolSize || isProfileMergeRequested();
+}
+
+/* Return 1 if there is an error, otherwise return 0. */
+static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
+ uint32_t NumIOVecs) {
+ uint32_t I;
+ FILE *File = (FILE *)This->WriterCtx;
+ char Zeroes[sizeof(uint64_t)] = {0};
+ for (I = 0; I < NumIOVecs; I++) {
+ if (IOVecs[I].Data) {
+ if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
+ IOVecs[I].NumElm)
+ return 1;
+ } else if (IOVecs[I].UseZeroPadding) {
+ size_t BytesToWrite = IOVecs[I].ElmSize * IOVecs[I].NumElm;
+ while (BytesToWrite > 0) {
+ size_t PartialWriteLen =
+ (sizeof(uint64_t) > BytesToWrite) ? BytesToWrite : sizeof(uint64_t);
+ if (fwrite(Zeroes, sizeof(uint8_t), PartialWriteLen, File) !=
+ PartialWriteLen) {
+ return 1;
+ }
+ BytesToWrite -= PartialWriteLen;
+ }
+ } else {
+ if (fseek(File, IOVecs[I].ElmSize * IOVecs[I].NumElm, SEEK_CUR) == -1)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* TODO: make buffer size controllable by an internal option, and compiler can pass the size
+ to runtime via a variable. */
+static uint32_t orderFileWriter(FILE *File, const uint32_t *DataStart) {
+ if (fwrite(DataStart, sizeof(uint32_t), INSTR_ORDER_FILE_BUFFER_SIZE, File) !=
+ INSTR_ORDER_FILE_BUFFER_SIZE)
+ return 1;
+ return 0;
+}
+
+static void initFileWriter(ProfDataWriter *This, FILE *File) {
+ This->Write = fileWriter;
+ This->WriterCtx = File;
+}
+
+COMPILER_RT_VISIBILITY ProfBufferIO *
+lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
+ FreeHook = &free;
+ DynamicBufferIOBuffer = (uint8_t *)calloc(BufferSz, 1);
+ VPBufferSize = BufferSz;
+ ProfDataWriter *fileWriter =
+ (ProfDataWriter *)calloc(sizeof(ProfDataWriter), 1);
+ initFileWriter(fileWriter, File);
+ ProfBufferIO *IO = lprofCreateBufferIO(fileWriter);
+ IO->OwnFileWriter = 1;
+ return IO;
+}
+
+static void setupIOBuffer(void) {
+ const char *BufferSzStr = 0;
+ BufferSzStr = getenv("LLVM_VP_BUFFER_SIZE");
+ if (BufferSzStr && BufferSzStr[0]) {
+ VPBufferSize = atoi(BufferSzStr);
+ DynamicBufferIOBuffer = (uint8_t *)calloc(VPBufferSize, 1);
+ }
+}
+
+/* Get the size of the profile file. If there are any errors, print the
+ * message under the assumption that the profile is being read for merging
+ * purposes, and return -1. Otherwise return the file size in the inout param
+ * \p ProfileFileSize. */
+static int getProfileFileSizeForMerging(FILE *ProfileFile,
+ uint64_t *ProfileFileSize) {
+ if (fseek(ProfileFile, 0L, SEEK_END) == -1) {
+ PROF_ERR("Unable to merge profile data, unable to get size: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ *ProfileFileSize = ftell(ProfileFile);
+
+ /* Restore file offset. */
+ if (fseek(ProfileFile, 0L, SEEK_SET) == -1) {
+ PROF_ERR("Unable to merge profile data, unable to rewind: %s\n",
+ strerror(errno));
+ return -1;
+ }
+
+ if (*ProfileFileSize > 0 &&
+ *ProfileFileSize < sizeof(__llvm_profile_header)) {
+ PROF_WARN("Unable to merge profile data: %s\n",
+ "source profile file is too small.");
+ return -1;
+ }
+ return 0;
+}
+
+/* mmap() \p ProfileFile for profile merging purposes, assuming that an
+ * exclusive lock is held on the file and that \p ProfileFileSize is the
+ * length of the file. Return the mmap'd buffer in the inout variable
+ * \p ProfileBuffer. Returns -1 on failure. On success, the caller is
+ * responsible for unmapping the mmap'd buffer in \p ProfileBuffer. */
+static int mmapProfileForMerging(FILE *ProfileFile, uint64_t ProfileFileSize,
+ char **ProfileBuffer) {
+ *ProfileBuffer = mmap(NULL, ProfileFileSize, PROT_READ, MAP_SHARED | MAP_FILE,
+ fileno(ProfileFile), 0);
+ if (*ProfileBuffer == MAP_FAILED) {
+ PROF_ERR("Unable to merge profile data, mmap failed: %s\n",
+ strerror(errno));
+ return -1;
+ }
+
+ if (__llvm_profile_check_compatibility(*ProfileBuffer, ProfileFileSize)) {
+ (void)munmap(*ProfileBuffer, ProfileFileSize);
+ PROF_WARN("Unable to merge profile data: %s\n",
+ "source profile file is not compatible.");
+ return -1;
+ }
+ return 0;
+}
+
+/* Read profile data in \c ProfileFile and merge with in-memory
+ profile counters. Returns -1 if there is fatal error, otheriwse
+ 0 is returned. Returning 0 does not mean merge is actually
+ performed. If merge is actually done, *MergeDone is set to 1.
+*/
+static int doProfileMerging(FILE *ProfileFile, int *MergeDone) {
+ uint64_t ProfileFileSize;
+ char *ProfileBuffer;
+
+ /* Get the size of the profile on disk. */
+ if (getProfileFileSizeForMerging(ProfileFile, &ProfileFileSize) == -1)
+ return -1;
+
+ /* Nothing to merge. */
+ if (!ProfileFileSize)
+ return 0;
+
+ /* mmap() the profile and check that it is compatible with the data in
+ * the current image. */
+ if (mmapProfileForMerging(ProfileFile, ProfileFileSize, &ProfileBuffer) == -1)
+ return -1;
+
+ /* Now start merging */
+ if (__llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize)) {
+ PROF_ERR("%s\n", "Invalid profile data to merge");
+ (void)munmap(ProfileBuffer, ProfileFileSize);
+ return -1;
+ }
+
+ // Truncate the file in case merging of value profile did not happen to
+ // prevent from leaving garbage data at the end of the profile file.
+ (void)COMPILER_RT_FTRUNCATE(ProfileFile,
+ __llvm_profile_get_size_for_buffer());
+
+ (void)munmap(ProfileBuffer, ProfileFileSize);
+ *MergeDone = 1;
+
+ return 0;
+}
+
+/* Create the directory holding the file, if needed. */
+static void createProfileDir(const char *Filename) {
+ size_t Length = strlen(Filename);
+ if (lprofFindFirstDirSeparator(Filename)) {
+ char *Copy = (char *)COMPILER_RT_ALLOCA(Length + 1);
+ strncpy(Copy, Filename, Length + 1);
+ __llvm_profile_recursive_mkdir(Copy);
+ }
+}
+
+/* Open the profile data for merging. It opens the file in r+b mode with
+ * file locking. If the file has content which is compatible with the
+ * current process, it also reads in the profile data in the file and merge
+ * it with in-memory counters. After the profile data is merged in memory,
+ * the original profile data is truncated and gets ready for the profile
+ * dumper. With profile merging enabled, each executable as well as any of
+ * its instrumented shared libraries dump profile data into their own data file.
+*/
+static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) {
+ FILE *ProfileFile = NULL;
+ int rc;
+
+ ProfileFile = getProfileFile();
+ if (ProfileFile) {
+ lprofLockFileHandle(ProfileFile);
+ } else {
+ createProfileDir(ProfileFileName);
+ ProfileFile = lprofOpenFileEx(ProfileFileName);
+ }
+ if (!ProfileFile)
+ return NULL;
+
+ rc = doProfileMerging(ProfileFile, MergeDone);
+ if (rc || (!*MergeDone && COMPILER_RT_FTRUNCATE(ProfileFile, 0L)) ||
+ fseek(ProfileFile, 0L, SEEK_SET) == -1) {
+ PROF_ERR("Profile Merging of file %s failed: %s\n", ProfileFileName,
+ strerror(errno));
+ fclose(ProfileFile);
+ return NULL;
+ }
+ return ProfileFile;
+}
+
+static FILE *getFileObject(const char *OutputName) {
+ FILE *File;
+ File = getProfileFile();
+ if (File != NULL) {
+ return File;
+ }
+
+ return fopen(OutputName, "ab");
+}
+
+/* Write profile data to file \c OutputName. */
+static int writeFile(const char *OutputName) {
+ int RetVal;
+ FILE *OutputFile;
+
+ int MergeDone = 0;
+ VPMergeHook = &lprofMergeValueProfData;
+ if (doMerging())
+ OutputFile = openFileForMerging(OutputName, &MergeDone);
+ else
+ OutputFile = getFileObject(OutputName);
+
+ if (!OutputFile)
+ return -1;
+
+ FreeHook = &free;
+ setupIOBuffer();
+ ProfDataWriter fileWriter;
+ initFileWriter(&fileWriter, OutputFile);
+ RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone);
+
+ if (OutputFile == getProfileFile()) {
+ fflush(OutputFile);
+ if (doMerging()) {
+ lprofUnlockFileHandle(OutputFile);
+ }
+ } else {
+ fclose(OutputFile);
+ }
+
+ return RetVal;
+}
+
+/* Write order data to file \c OutputName. */
+static int writeOrderFile(const char *OutputName) {
+ int RetVal;
+ FILE *OutputFile;
+
+ OutputFile = fopen(OutputName, "w");
+
+ if (!OutputFile) {
+ PROF_WARN("can't open file with mode ab: %s\n", OutputName);
+ return -1;
+ }
+
+ FreeHook = &free;
+ setupIOBuffer();
+ const uint32_t *DataBegin = __llvm_profile_begin_orderfile();
+ RetVal = orderFileWriter(OutputFile, DataBegin);
+
+ fclose(OutputFile);
+ return RetVal;
+}
+
+#define LPROF_INIT_ONCE_ENV "__LLVM_PROFILE_RT_INIT_ONCE"
+
+static void truncateCurrentFile(void) {
+ const char *Filename;
+ char *FilenameBuf;
+ FILE *File;
+ int Length;
+
+ Length = getCurFilenameLength();
+ FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
+ Filename = getCurFilename(FilenameBuf, 0);
+ if (!Filename)
+ return;
+
+ /* Only create the profile directory and truncate an existing profile once.
+ * In continuous mode, this is necessary, as the profile is written-to by the
+ * runtime initializer. */
+ int initialized = getenv(LPROF_INIT_ONCE_ENV) != NULL;
+ if (initialized)
+ return;
+#if defined(_WIN32)
+ _putenv(LPROF_INIT_ONCE_ENV "=" LPROF_INIT_ONCE_ENV);
+#else
+ setenv(LPROF_INIT_ONCE_ENV, LPROF_INIT_ONCE_ENV, 1);
+#endif
+
+ /* Create the profile dir (even if online merging is enabled), so that
+ * the profile file can be set up if continuous mode is enabled. */
+ createProfileDir(Filename);
+
+ /* By pass file truncation to allow online raw profile merging. */
+ if (lprofCurFilename.MergePoolSize)
+ return;
+
+ /* Truncate the file. Later we'll reopen and append. */
+ File = fopen(Filename, "w");
+ if (!File)
+ return;
+ fclose(File);
+}
+
+/* Write a partial profile to \p Filename, which is required to be backed by
+ * the open file object \p File. */
+static int writeProfileWithFileObject(const char *Filename, FILE *File) {
+ setProfileFile(File);
+ int rc = writeFile(Filename);
+ if (rc)
+ PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
+ setProfileFile(NULL);
+ return rc;
+}
+
+static void initializeProfileForContinuousMode(void) {
+ if (!__llvm_profile_is_continuous_mode_enabled())
+ return;
+ if (!ContinuousModeSupported) {
+ PROF_ERR("%s\n", "continuous mode is unsupported on this platform");
+ return;
+ }
+ if (UseBiasVar && BiasAddr == BiasDefaultAddr) {
+ PROF_ERR("%s\n", "__llvm_profile_counter_bias is undefined");
+ return;
+ }
+
+ /* Get the sizes of counter section. */
+ uint64_t CountersSize = __llvm_profile_get_counters_size(
+ __llvm_profile_begin_counters(), __llvm_profile_end_counters());
+
+ int Length = getCurFilenameLength();
+ char *FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
+ const char *Filename = getCurFilename(FilenameBuf, 0);
+ if (!Filename)
+ return;
+
+ FILE *File = NULL;
+ uint64_t CurrentFileOffset = 0;
+ if (doMerging()) {
+ /* We are merging profiles. Map the counter section as shared memory into
+ * the profile, i.e. into each participating process. An increment in one
+ * process should be visible to every other process with the same counter
+ * section mapped. */
+ File = lprofOpenFileEx(Filename);
+ if (!File)
+ return;
+
+ uint64_t ProfileFileSize = 0;
+ if (getProfileFileSizeForMerging(File, &ProfileFileSize) == -1) {
+ lprofUnlockFileHandle(File);
+ fclose(File);
+ return;
+ }
+ if (ProfileFileSize == 0) {
+ /* Grow the profile so that mmap() can succeed. Leak the file handle, as
+ * the file should stay open. */
+ if (writeProfileWithFileObject(Filename, File) != 0) {
+ lprofUnlockFileHandle(File);
+ fclose(File);
+ return;
+ }
+ } else {
+ /* The merged profile has a non-zero length. Check that it is compatible
+ * with the data in this process. */
+ char *ProfileBuffer;
+ if (mmapProfileForMerging(File, ProfileFileSize, &ProfileBuffer) == -1) {
+ lprofUnlockFileHandle(File);
+ fclose(File);
+ return;
+ }
+ (void)munmap(ProfileBuffer, ProfileFileSize);
+ }
+ } else {
+ File = fopen(Filename, FileOpenMode);
+ if (!File)
+ return;
+ /* Check that the offset within the file is page-aligned. */
+ CurrentFileOffset = ftell(File);
+ unsigned PageSize = getpagesize();
+ if (CurrentFileOffset % PageSize != 0) {
+ PROF_ERR("Continuous counter sync mode is enabled, but raw profile is not"
+ "page-aligned. CurrentFileOffset = %" PRIu64 ", pagesz = %u.\n",
+ (uint64_t)CurrentFileOffset, PageSize);
+ return;
+ }
+ if (writeProfileWithFileObject(Filename, File) != 0) {
+ fclose(File);
+ return;
+ }
+ }
+
+ /* mmap() the profile counters so long as there is at least one counter.
+ * If there aren't any counters, mmap() would fail with EINVAL. */
+ if (CountersSize > 0)
+ mmapForContinuousMode(CurrentFileOffset, File);
+
+ if (doMerging()) {
+ lprofUnlockFileHandle(File);
+ fclose(File);
+ }
+}
+
+static const char *DefaultProfileName = "default.profraw";
+static void resetFilenameToDefault(void) {
+ if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
+ free((void *)lprofCurFilename.FilenamePat);
+ }
+ memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
+ lprofCurFilename.FilenamePat = DefaultProfileName;
+ lprofCurFilename.PNS = PNS_default;
+}
+
+static unsigned getMergePoolSize(const char *FilenamePat, int *I) {
+ unsigned J = 0, Num = 0;
+ for (;; ++J) {
+ char C = FilenamePat[*I + J];
+ if (C == 'm') {
+ *I += J;
+ return Num ? Num : 1;
+ }
+ if (C < '0' || C > '9')
+ break;
+ Num = Num * 10 + C - '0';
+
+ /* If FilenamePat[*I+J] is between '0' and '9', the next byte is guaranteed
+ * to be in-bound as the string is null terminated. */
+ }
+ return 0;
+}
+
+/* Assert that Idx does index past a string null terminator. Return the
+ * result of the check. */
+static int checkBounds(int Idx, int Strlen) {
+ assert(Idx <= Strlen && "Indexing past string null terminator");
+ return Idx <= Strlen;
+}
+
+/* Parses the pattern string \p FilenamePat and stores the result to
+ * lprofcurFilename structure. */
+static int parseFilenamePattern(const char *FilenamePat,
+ unsigned CopyFilenamePat) {
+ int NumPids = 0, NumHosts = 0, I;
+ char *PidChars = &lprofCurFilename.PidChars[0];
+ char *Hostname = &lprofCurFilename.Hostname[0];
+ int MergingEnabled = 0;
+ int FilenamePatLen = strlen(FilenamePat);
+
+ /* Clean up cached prefix and filename. */
+ if (lprofCurFilename.ProfilePathPrefix)
+ free((void *)lprofCurFilename.ProfilePathPrefix);
+
+ if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
+ free((void *)lprofCurFilename.FilenamePat);
+ }
+
+ memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
+
+ if (!CopyFilenamePat)
+ lprofCurFilename.FilenamePat = FilenamePat;
+ else {
+ lprofCurFilename.FilenamePat = strdup(FilenamePat);
+ lprofCurFilename.OwnsFilenamePat = 1;
+ }
+ /* Check the filename for "%p", which indicates a pid-substitution. */
+ for (I = 0; checkBounds(I, FilenamePatLen) && FilenamePat[I]; ++I) {
+ if (FilenamePat[I] == '%') {
+ ++I; /* Advance to the next character. */
+ if (!checkBounds(I, FilenamePatLen))
+ break;
+ if (FilenamePat[I] == 'p') {
+ if (!NumPids++) {
+ if (snprintf(PidChars, MAX_PID_SIZE, "%ld", (long)getpid()) <= 0) {
+ PROF_WARN("Unable to get pid for filename pattern %s. Using the "
+ "default name.",
+ FilenamePat);
+ return -1;
+ }
+ }
+ } else if (FilenamePat[I] == 'h') {
+ if (!NumHosts++)
+ if (COMPILER_RT_GETHOSTNAME(Hostname, COMPILER_RT_MAX_HOSTLEN)) {
+ PROF_WARN("Unable to get hostname for filename pattern %s. Using "
+ "the default name.",
+ FilenamePat);
+ return -1;
+ }
+ } else if (FilenamePat[I] == 't') {
+ lprofCurFilename.TmpDir = getenv("TMPDIR");
+ if (!lprofCurFilename.TmpDir) {
+ PROF_WARN("Unable to get the TMPDIR environment variable, referenced "
+ "in %s. Using the default path.",
+ FilenamePat);
+ return -1;
+ }
+ } else if (FilenamePat[I] == 'c') {
+ if (__llvm_profile_is_continuous_mode_enabled()) {
+ PROF_WARN("%%c specifier can only be specified once in %s.\n",
+ FilenamePat);
+ return -1;
+ }
+#if defined(__APPLE__) || defined(__ELF__) || defined(_WIN32)
+ __llvm_profile_set_page_size(getpagesize());
+ __llvm_profile_enable_continuous_mode();
+#else
+ PROF_WARN("%s", "Continous mode is currently only supported for Mach-O,"
+ " ELF and COFF formats.");
+ return -1;
+#endif
+ } else {
+ unsigned MergePoolSize = getMergePoolSize(FilenamePat, &I);
+ if (!MergePoolSize)
+ continue;
+ if (MergingEnabled) {
+ PROF_WARN("%%m specifier can only be specified once in %s.\n",
+ FilenamePat);
+ return -1;
+ }
+ MergingEnabled = 1;
+ lprofCurFilename.MergePoolSize = MergePoolSize;
+ }
+ }
+ }
+
+ lprofCurFilename.NumPids = NumPids;
+ lprofCurFilename.NumHosts = NumHosts;
+ return 0;
+}
+
+static void parseAndSetFilename(const char *FilenamePat,
+ ProfileNameSpecifier PNS,
+ unsigned CopyFilenamePat) {
+
+ const char *OldFilenamePat = lprofCurFilename.FilenamePat;
+ ProfileNameSpecifier OldPNS = lprofCurFilename.PNS;
+
+ /* The old profile name specifier takes precedence over the old one. */
+ if (PNS < OldPNS)
+ return;
+
+ if (!FilenamePat)
+ FilenamePat = DefaultProfileName;
+
+ if (OldFilenamePat && !strcmp(OldFilenamePat, FilenamePat)) {
+ lprofCurFilename.PNS = PNS;
+ return;
+ }
+
+ /* When PNS >= OldPNS, the last one wins. */
+ if (!FilenamePat || parseFilenamePattern(FilenamePat, CopyFilenamePat))
+ resetFilenameToDefault();
+ lprofCurFilename.PNS = PNS;
+
+ if (!OldFilenamePat) {
+ if (getenv("LLVM_PROFILE_VERBOSE"))
+ PROF_NOTE("Set profile file path to \"%s\" via %s.\n",
+ lprofCurFilename.FilenamePat, getPNSStr(PNS));
+ } else {
+ if (getenv("LLVM_PROFILE_VERBOSE"))
+ PROF_NOTE("Override old profile path \"%s\" via %s to \"%s\" via %s.\n",
+ OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat,
+ getPNSStr(PNS));
+ }
+
+ truncateCurrentFile();
+ if (__llvm_profile_is_continuous_mode_enabled())
+ initializeProfileForContinuousMode();
+}
+
+/* Return buffer length that is required to store the current profile
+ * filename with PID and hostname substitutions. */
+/* The length to hold uint64_t followed by 3 digits pool id including '_' */
+#define SIGLEN 24
+static int getCurFilenameLength(void) {
+ int Len;
+ if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
+ return 0;
+
+ if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
+ lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize))
+ return strlen(lprofCurFilename.FilenamePat);
+
+ Len = strlen(lprofCurFilename.FilenamePat) +
+ lprofCurFilename.NumPids * (strlen(lprofCurFilename.PidChars) - 2) +
+ lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2) +
+ (lprofCurFilename.TmpDir ? (strlen(lprofCurFilename.TmpDir) - 1) : 0);
+ if (lprofCurFilename.MergePoolSize)
+ Len += SIGLEN;
+ return Len;
+}
+
+/* Return the pointer to the current profile file name (after substituting
+ * PIDs and Hostnames in filename pattern. \p FilenameBuf is the buffer
+ * to store the resulting filename. If no substitution is needed, the
+ * current filename pattern string is directly returned, unless ForceUseBuf
+ * is enabled. */
+static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
+ int I, J, PidLength, HostNameLength, TmpDirLength, FilenamePatLength;
+ const char *FilenamePat = lprofCurFilename.FilenamePat;
+
+ if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
+ return 0;
+
+ if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
+ lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize ||
+ __llvm_profile_is_continuous_mode_enabled())) {
+ if (!ForceUseBuf)
+ return lprofCurFilename.FilenamePat;
+
+ FilenamePatLength = strlen(lprofCurFilename.FilenamePat);
+ memcpy(FilenameBuf, lprofCurFilename.FilenamePat, FilenamePatLength);
+ FilenameBuf[FilenamePatLength] = '\0';
+ return FilenameBuf;
+ }
+
+ PidLength = strlen(lprofCurFilename.PidChars);
+ HostNameLength = strlen(lprofCurFilename.Hostname);
+ TmpDirLength = lprofCurFilename.TmpDir ? strlen(lprofCurFilename.TmpDir) : 0;
+ /* Construct the new filename. */
+ for (I = 0, J = 0; FilenamePat[I]; ++I)
+ if (FilenamePat[I] == '%') {
+ if (FilenamePat[++I] == 'p') {
+ memcpy(FilenameBuf + J, lprofCurFilename.PidChars, PidLength);
+ J += PidLength;
+ } else if (FilenamePat[I] == 'h') {
+ memcpy(FilenameBuf + J, lprofCurFilename.Hostname, HostNameLength);
+ J += HostNameLength;
+ } else if (FilenamePat[I] == 't') {
+ memcpy(FilenameBuf + J, lprofCurFilename.TmpDir, TmpDirLength);
+ FilenameBuf[J + TmpDirLength] = DIR_SEPARATOR;
+ J += TmpDirLength + 1;
+ } else {
+ if (!getMergePoolSize(FilenamePat, &I))
+ continue;
+ char LoadModuleSignature[SIGLEN + 1];
+ int S;
+ int ProfilePoolId = getpid() % lprofCurFilename.MergePoolSize;
+ S = snprintf(LoadModuleSignature, SIGLEN + 1, "%" PRIu64 "_%d",
+ lprofGetLoadModuleSignature(), ProfilePoolId);
+ if (S == -1 || S > SIGLEN)
+ S = SIGLEN;
+ memcpy(FilenameBuf + J, LoadModuleSignature, S);
+ J += S;
+ }
+ /* Drop any unknown substitutions. */
+ } else
+ FilenameBuf[J++] = FilenamePat[I];
+ FilenameBuf[J] = 0;
+
+ return FilenameBuf;
+}
+
+/* Returns the pointer to the environment variable
+ * string. Returns null if the env var is not set. */
+static const char *getFilenamePatFromEnv(void) {
+ const char *Filename = getenv("LLVM_PROFILE_FILE");
+ if (!Filename || !Filename[0])
+ return 0;
+ return Filename;
+}
+
+COMPILER_RT_VISIBILITY
+const char *__llvm_profile_get_path_prefix(void) {
+ int Length;
+ char *FilenameBuf, *Prefix;
+ const char *Filename, *PrefixEnd;
+
+ if (lprofCurFilename.ProfilePathPrefix)
+ return lprofCurFilename.ProfilePathPrefix;
+
+ Length = getCurFilenameLength();
+ FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
+ Filename = getCurFilename(FilenameBuf, 0);
+ if (!Filename)
+ return "\0";
+
+ PrefixEnd = lprofFindLastDirSeparator(Filename);
+ if (!PrefixEnd)
+ return "\0";
+
+ Length = PrefixEnd - Filename + 1;
+ Prefix = (char *)malloc(Length + 1);
+ if (!Prefix) {
+ PROF_ERR("Failed to %s\n", "allocate memory.");
+ return "\0";
+ }
+ memcpy(Prefix, Filename, Length);
+ Prefix[Length] = '\0';
+ lprofCurFilename.ProfilePathPrefix = Prefix;
+ return Prefix;
+}
+
+COMPILER_RT_VISIBILITY
+const char *__llvm_profile_get_filename(void) {
+ int Length;
+ char *FilenameBuf;
+ const char *Filename;
+
+ Length = getCurFilenameLength();
+ FilenameBuf = (char *)malloc(Length + 1);
+ if (!FilenameBuf) {
+ PROF_ERR("Failed to %s\n", "allocate memory.");
+ return "\0";
+ }
+ Filename = getCurFilename(FilenameBuf, 1);
+ if (!Filename)
+ return "\0";
+
+ return FilenameBuf;
+}
+
+/* This API initializes the file handling, both user specified
+ * profile path via -fprofile-instr-generate= and LLVM_PROFILE_FILE
+ * environment variable can override this default value.
+ */
+COMPILER_RT_VISIBILITY
+void __llvm_profile_initialize_file(void) {
+ const char *EnvFilenamePat;
+ const char *SelectedPat = NULL;
+ ProfileNameSpecifier PNS = PNS_unknown;
+ int hasCommandLineOverrider = (INSTR_PROF_PROFILE_NAME_VAR[0] != 0);
+
+ EnvFilenamePat = getFilenamePatFromEnv();
+ if (EnvFilenamePat) {
+ /* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
+ at the moment when __llvm_profile_write_file() gets executed. */
+ parseAndSetFilename(EnvFilenamePat, PNS_environment, 1);
+ return;
+ } else if (hasCommandLineOverrider) {
+ SelectedPat = INSTR_PROF_PROFILE_NAME_VAR;
+ PNS = PNS_command_line;
+ } else {
+ SelectedPat = NULL;
+ PNS = PNS_default;
+ }
+
+ parseAndSetFilename(SelectedPat, PNS, 0);
+}
+
+/* This method is invoked by the runtime initialization hook
+ * InstrProfilingRuntime.o if it is linked in.
+ */
+COMPILER_RT_VISIBILITY
+void __llvm_profile_initialize(void) {
+ __llvm_profile_initialize_file();
+ if (!__llvm_profile_is_continuous_mode_enabled())
+ __llvm_profile_register_write_file_atexit();
+}
+
+/* This API is directly called by the user application code. It has the
+ * highest precedence compared with LLVM_PROFILE_FILE environment variable
+ * and command line option -fprofile-instr-generate=<profile_name>.
+ */
+COMPILER_RT_VISIBILITY
+void __llvm_profile_set_filename(const char *FilenamePat) {
+ if (__llvm_profile_is_continuous_mode_enabled())
+ return;
+ parseAndSetFilename(FilenamePat, PNS_runtime_api, 1);
+}
+
+/* The public API for writing profile data into the file with name
+ * set by previous calls to __llvm_profile_set_filename or
+ * __llvm_profile_override_default_filename or
+ * __llvm_profile_initialize_file. */
+COMPILER_RT_VISIBILITY
+int __llvm_profile_write_file(void) {
+ int rc, Length;
+ const char *Filename;
+ char *FilenameBuf;
+ int PDeathSig = 0;
+
+ if (lprofProfileDumped() || __llvm_profile_is_continuous_mode_enabled()) {
+ PROF_NOTE("Profile data not written to file: %s.\n", "already written");
+ return 0;
+ }
+
+ Length = getCurFilenameLength();
+ FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
+ Filename = getCurFilename(FilenameBuf, 0);
+
+ /* Check the filename. */
+ if (!Filename) {
+ PROF_ERR("Failed to write file : %s\n", "Filename not set");
+ return -1;
+ }
+
+ /* Check if there is llvm/runtime version mismatch. */
+ if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
+ PROF_ERR("Runtime and instrumentation version mismatch : "
+ "expected %d, but get %d\n",
+ INSTR_PROF_RAW_VERSION,
+ (int)GET_VERSION(__llvm_profile_get_version()));
+ return -1;
+ }
+
+ // Temporarily suspend getting SIGKILL when the parent exits.
+ PDeathSig = lprofSuspendSigKill();
+
+ /* Write profile data to the file. */
+ rc = writeFile(Filename);
+ if (rc)
+ PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
+
+ // Restore SIGKILL.
+ if (PDeathSig == 1)
+ lprofRestoreSigKill();
+
+ return rc;
+}
+
+COMPILER_RT_VISIBILITY
+int __llvm_profile_dump(void) {
+ if (!doMerging())
+ PROF_WARN("Later invocation of __llvm_profile_dump can lead to clobbering "
+ " of previously dumped profile data : %s. Either use %%m "
+ "in profile name or change profile name before dumping.\n",
+ "online profile merging is not on");
+ int rc = __llvm_profile_write_file();
+ lprofSetProfileDumped(1);
+ return rc;
+}
+
+/* Order file data will be saved in a file with suffx .order. */
+static const char *OrderFileSuffix = ".order";
+
+COMPILER_RT_VISIBILITY
+int __llvm_orderfile_write_file(void) {
+ int rc, Length, LengthBeforeAppend, SuffixLength;
+ const char *Filename;
+ char *FilenameBuf;
+ int PDeathSig = 0;
+
+ SuffixLength = strlen(OrderFileSuffix);
+ Length = getCurFilenameLength() + SuffixLength;
+ FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
+ Filename = getCurFilename(FilenameBuf, 1);
+
+ /* Check the filename. */
+ if (!Filename) {
+ PROF_ERR("Failed to write file : %s\n", "Filename not set");
+ return -1;
+ }
+
+ /* Append order file suffix */
+ LengthBeforeAppend = strlen(Filename);
+ memcpy(FilenameBuf + LengthBeforeAppend, OrderFileSuffix, SuffixLength);
+ FilenameBuf[LengthBeforeAppend + SuffixLength] = '\0';
+
+ /* Check if there is llvm/runtime version mismatch. */
+ if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
+ PROF_ERR("Runtime and instrumentation version mismatch : "
+ "expected %d, but get %d\n",
+ INSTR_PROF_RAW_VERSION,
+ (int)GET_VERSION(__llvm_profile_get_version()));
+ return -1;
+ }
+
+ // Temporarily suspend getting SIGKILL when the parent exits.
+ PDeathSig = lprofSuspendSigKill();
+
+ /* Write order data to the file. */
+ rc = writeOrderFile(Filename);
+ if (rc)
+ PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
+
+ // Restore SIGKILL.
+ if (PDeathSig == 1)
+ lprofRestoreSigKill();
+
+ return rc;
+}
+
+COMPILER_RT_VISIBILITY
+int __llvm_orderfile_dump(void) {
+ int rc = __llvm_orderfile_write_file();
+ return rc;
+}
+
+static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); }
+
+COMPILER_RT_VISIBILITY
+int __llvm_profile_register_write_file_atexit(void) {
+ static int HasBeenRegistered = 0;
+
+ if (HasBeenRegistered)
+ return 0;
+
+ lprofSetupValueProfiler();
+
+ HasBeenRegistered = 1;
+ return atexit(writeFileWithoutReturn);
+}
+
+COMPILER_RT_VISIBILITY int __llvm_profile_set_file_object(FILE *File,
+ int EnableMerge) {
+ if (__llvm_profile_is_continuous_mode_enabled()) {
+ if (!EnableMerge) {
+ PROF_WARN("__llvm_profile_set_file_object(fd=%d) not supported in "
+ "continuous sync mode when merging is disabled\n",
+ fileno(File));
+ return 1;
+ }
+ if (lprofLockFileHandle(File) != 0) {
+ PROF_WARN("Data may be corrupted during profile merging : %s\n",
+ "Fail to obtain file lock due to system limit.");
+ }
+ uint64_t ProfileFileSize = 0;
+ if (getProfileFileSizeForMerging(File, &ProfileFileSize) == -1) {
+ lprofUnlockFileHandle(File);
+ return 1;
+ }
+ if (ProfileFileSize == 0) {
+ FreeHook = &free;
+ setupIOBuffer();
+ ProfDataWriter fileWriter;
+ initFileWriter(&fileWriter, File);
+ if (lprofWriteData(&fileWriter, 0, 0)) {
+ lprofUnlockFileHandle(File);
+ PROF_ERR("Failed to write file \"%d\": %s\n", fileno(File),
+ strerror(errno));
+ return 1;
+ }
+ fflush(File);
+ } else {
+ /* The merged profile has a non-zero length. Check that it is compatible
+ * with the data in this process. */
+ char *ProfileBuffer;
+ if (mmapProfileForMerging(File, ProfileFileSize, &ProfileBuffer) == -1) {
+ lprofUnlockFileHandle(File);
+ return 1;
+ }
+ (void)munmap(ProfileBuffer, ProfileFileSize);
+ }
+ mmapForContinuousMode(0, File);
+ lprofUnlockFileHandle(File);
+ } else {
+ setProfileFile(File);
+ setProfileMergeRequested(EnableMerge);
+ }
+ return 0;
+}
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingInternal.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingInternal.c
new file mode 100644
index 00000000000..3dd659f9051
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingInternal.c
@@ -0,0 +1,26 @@
+/*===- InstrProfilingInternal.c - Support library for PGO instrumentation -===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+// Note: This is linked into the Darwin kernel, and must remain compatible
+// with freestanding compilation. See `darwin_add_builtin_libraries`.
+
+#if !defined(__Fuchsia__)
+
+#include "InstrProfilingInternal.h"
+
+static unsigned ProfileDumped = 0;
+
+COMPILER_RT_VISIBILITY unsigned lprofProfileDumped(void) {
+ return ProfileDumped;
+}
+
+COMPILER_RT_VISIBILITY void lprofSetProfileDumped(unsigned Value) {
+ ProfileDumped = Value;
+}
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingInternal.h b/contrib/libs/clang16-rt/lib/profile/InstrProfilingInternal.h
new file mode 100644
index 00000000000..b2ce11067ab
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingInternal.h
@@ -0,0 +1,201 @@
+/*===- InstrProfiling.h- Support library for PGO instrumentation ----------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+#ifndef PROFILE_INSTRPROFILING_INTERNALH_
+#define PROFILE_INSTRPROFILING_INTERNALH_
+
+#include <stddef.h>
+
+#include "InstrProfiling.h"
+
+/*!
+ * \brief Write instrumentation data to the given buffer, given explicit
+ * pointers to the live data in memory. This function is probably not what you
+ * want. Use __llvm_profile_get_size_for_buffer instead. Use this function if
+ * your program has a custom memory layout.
+ */
+uint64_t __llvm_profile_get_size_for_buffer_internal(
+ const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd,
+ const char *CountersBegin, const char *CountersEnd, const char *NamesBegin,
+ const char *NamesEnd);
+
+/*!
+ * \brief Write instrumentation data to the given buffer, given explicit
+ * pointers to the live data in memory. This function is probably not what you
+ * want. Use __llvm_profile_write_buffer instead. Use this function if your
+ * program has a custom memory layout.
+ *
+ * \pre \c Buffer is the start of a buffer at least as big as \a
+ * __llvm_profile_get_size_for_buffer_internal().
+ */
+int __llvm_profile_write_buffer_internal(
+ char *Buffer, const __llvm_profile_data *DataBegin,
+ const __llvm_profile_data *DataEnd, const char *CountersBegin,
+ const char *CountersEnd, const char *NamesBegin, const char *NamesEnd);
+
+/*!
+ * The data structure describing the data to be written by the
+ * low level writer callback function.
+ *
+ * If \ref ProfDataIOVec.Data is null, and \ref ProfDataIOVec.UseZeroPadding is
+ * 0, the write is skipped (the writer simply advances ElmSize*NumElm bytes).
+ *
+ * If \ref ProfDataIOVec.Data is null, and \ref ProfDataIOVec.UseZeroPadding is
+ * nonzero, ElmSize*NumElm zero bytes are written.
+ */
+typedef struct ProfDataIOVec {
+ const void *Data;
+ size_t ElmSize;
+ size_t NumElm;
+ int UseZeroPadding;
+} ProfDataIOVec;
+
+struct ProfDataWriter;
+typedef uint32_t (*WriterCallback)(struct ProfDataWriter *This, ProfDataIOVec *,
+ uint32_t NumIOVecs);
+
+typedef struct ProfDataWriter {
+ WriterCallback Write;
+ void *WriterCtx;
+} ProfDataWriter;
+
+/*!
+ * The data structure for buffered IO of profile data.
+ */
+typedef struct ProfBufferIO {
+ ProfDataWriter *FileWriter;
+ uint32_t OwnFileWriter;
+ /* The start of the buffer. */
+ uint8_t *BufferStart;
+ /* Total size of the buffer. */
+ uint32_t BufferSz;
+ /* Current byte offset from the start of the buffer. */
+ uint32_t CurOffset;
+} ProfBufferIO;
+
+/* The creator interface used by testing. */
+ProfBufferIO *lprofCreateBufferIOInternal(void *File, uint32_t BufferSz);
+
+/*!
+ * This is the interface to create a handle for buffered IO.
+ */
+ProfBufferIO *lprofCreateBufferIO(ProfDataWriter *FileWriter);
+
+/*!
+ * The interface to destroy the bufferIO handle and reclaim
+ * the memory.
+ */
+void lprofDeleteBufferIO(ProfBufferIO *BufferIO);
+
+/*!
+ * This is the interface to write \c Data of \c Size bytes through
+ * \c BufferIO. Returns 0 if successful, otherwise return -1.
+ */
+int lprofBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data,
+ uint32_t Size);
+/*!
+ * The interface to flush the remaining data in the buffer.
+ * through the low level writer callback.
+ */
+int lprofBufferIOFlush(ProfBufferIO *BufferIO);
+
+/* The low level interface to write data into a buffer. It is used as the
+ * callback by other high level writer methods such as buffered IO writer
+ * and profile data writer. */
+uint32_t lprofBufferWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
+ uint32_t NumIOVecs);
+void initBufferWriter(ProfDataWriter *BufferWriter, char *Buffer);
+
+struct ValueProfData;
+struct ValueProfRecord;
+struct InstrProfValueData;
+struct ValueProfNode;
+
+/*!
+ * The class that defines a set of methods to read value profile
+ * data for streaming/serialization from the instrumentation runtime.
+ */
+typedef struct VPDataReaderType {
+ uint32_t (*InitRTRecord)(const __llvm_profile_data *Data,
+ uint8_t *SiteCountArray[]);
+ /* Function pointer to getValueProfRecordHeader method. */
+ uint32_t (*GetValueProfRecordHeaderSize)(uint32_t NumSites);
+ /* Function pointer to getFristValueProfRecord method. */
+ struct ValueProfRecord *(*GetFirstValueProfRecord)(struct ValueProfData *);
+ /* Return the number of value data for site \p Site. */
+ uint32_t (*GetNumValueDataForSite)(uint32_t VK, uint32_t Site);
+ /* Return the total size of the value profile data of the
+ * current function. */
+ uint32_t (*GetValueProfDataSize)(void);
+ /*!
+ * Read the next \p N value data for site \p Site and store the data
+ * in \p Dst. \p StartNode is the first value node to start with if
+ * it is not null. The function returns the pointer to the value
+ * node pointer to be used as the \p StartNode of the next batch reading.
+ * If there is nothing left, it returns NULL.
+ */
+ struct ValueProfNode *(*GetValueData)(uint32_t ValueKind, uint32_t Site,
+ struct InstrProfValueData *Dst,
+ struct ValueProfNode *StartNode,
+ uint32_t N);
+} VPDataReaderType;
+
+/* Write profile data to destination. If SkipNameDataWrite is set to 1,
+ the name data is already in destination, we just skip over it. */
+int lprofWriteData(ProfDataWriter *Writer, VPDataReaderType *VPDataReader,
+ int SkipNameDataWrite);
+int lprofWriteDataImpl(ProfDataWriter *Writer,
+ const __llvm_profile_data *DataBegin,
+ const __llvm_profile_data *DataEnd,
+ const char *CountersBegin, const char *CountersEnd,
+ VPDataReaderType *VPDataReader, const char *NamesBegin,
+ const char *NamesEnd, int SkipNameDataWrite);
+
+/* Merge value profile data pointed to by SrcValueProfData into
+ * in-memory profile counters pointed by to DstData. */
+void lprofMergeValueProfData(struct ValueProfData *SrcValueProfData,
+ __llvm_profile_data *DstData);
+
+VPDataReaderType *lprofGetVPDataReader();
+
+/* Internal interface used by test to reset the max number of
+ * tracked values per value site to be \p MaxVals.
+ */
+void lprofSetMaxValsPerSite(uint32_t MaxVals);
+void lprofSetupValueProfiler();
+
+/* Return the profile header 'signature' value associated with the current
+ * executable or shared library. The signature value can be used to for
+ * a profile name that is unique to this load module so that it does not
+ * collide with profiles from other binaries. It also allows shared libraries
+ * to dump merged profile data into its own profile file. */
+uint64_t lprofGetLoadModuleSignature();
+
+/*
+ * Return non zero value if the profile data has already been
+ * dumped to the file.
+ */
+unsigned lprofProfileDumped(void);
+void lprofSetProfileDumped(unsigned);
+
+COMPILER_RT_VISIBILITY extern void (*FreeHook)(void *);
+COMPILER_RT_VISIBILITY extern uint8_t *DynamicBufferIOBuffer;
+COMPILER_RT_VISIBILITY extern uint32_t VPBufferSize;
+COMPILER_RT_VISIBILITY extern uint32_t VPMaxNumValsPerSite;
+/* Pointer to the start of static value counters to be allocted. */
+COMPILER_RT_VISIBILITY extern ValueProfNode *CurrentVNode;
+COMPILER_RT_VISIBILITY extern ValueProfNode *EndVNode;
+extern void (*VPMergeHook)(struct ValueProfData *, __llvm_profile_data *);
+
+/*
+ * Write binary ids into profiles if writer is given.
+ * Return -1 if an error occurs, otherwise, return total size of binary ids.
+ */
+int __llvm_write_binary_ids(ProfDataWriter *Writer);
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingMerge.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingMerge.c
new file mode 100644
index 00000000000..4da88b7d7bd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingMerge.c
@@ -0,0 +1,185 @@
+/*===- InstrProfilingMerge.c - Profile in-process Merging ---------------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+|*===----------------------------------------------------------------------===*
+|* This file defines the API needed for in-process merging of profile data
+|* stored in memory buffer.
+\*===---------------------------------------------------------------------===*/
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+#include "InstrProfilingUtil.h"
+
+#define INSTR_PROF_VALUE_PROF_DATA
+#include "profile/InstrProfData.inc"
+
+COMPILER_RT_VISIBILITY
+void (*VPMergeHook)(ValueProfData *, __llvm_profile_data *);
+
+COMPILER_RT_VISIBILITY
+uint64_t lprofGetLoadModuleSignature(void) {
+ /* A very fast way to compute a module signature. */
+ uint64_t Version = __llvm_profile_get_version();
+ uint64_t NumCounters = __llvm_profile_get_num_counters(
+ __llvm_profile_begin_counters(), __llvm_profile_end_counters());
+ uint64_t NumData = __llvm_profile_get_num_data(__llvm_profile_begin_data(),
+ __llvm_profile_end_data());
+ uint64_t NamesSize =
+ (uint64_t)(__llvm_profile_end_names() - __llvm_profile_begin_names());
+ uint64_t NumVnodes =
+ (uint64_t)(__llvm_profile_end_vnodes() - __llvm_profile_begin_vnodes());
+ const __llvm_profile_data *FirstD = __llvm_profile_begin_data();
+
+ return (NamesSize << 40) + (NumCounters << 30) + (NumData << 20) +
+ (NumVnodes << 10) + (NumData > 0 ? FirstD->NameRef : 0) + Version +
+ __llvm_profile_get_magic();
+}
+
+/* Returns 1 if profile is not structurally compatible. */
+COMPILER_RT_VISIBILITY
+int __llvm_profile_check_compatibility(const char *ProfileData,
+ uint64_t ProfileSize) {
+ /* Check profile header only for now */
+ __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData;
+ __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData;
+ SrcDataStart =
+ (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header) +
+ Header->BinaryIdsSize);
+ SrcDataEnd = SrcDataStart + Header->DataSize;
+
+ if (ProfileSize < sizeof(__llvm_profile_header))
+ return 1;
+
+ /* Check the header first. */
+ if (Header->Magic != __llvm_profile_get_magic() ||
+ Header->Version != __llvm_profile_get_version() ||
+ Header->DataSize !=
+ __llvm_profile_get_num_data(__llvm_profile_begin_data(),
+ __llvm_profile_end_data()) ||
+ Header->CountersSize !=
+ __llvm_profile_get_num_counters(__llvm_profile_begin_counters(),
+ __llvm_profile_end_counters()) ||
+ Header->NamesSize != (uint64_t)(__llvm_profile_end_names() -
+ __llvm_profile_begin_names()) ||
+ Header->ValueKindLast != IPVK_Last)
+ return 1;
+
+ if (ProfileSize <
+ sizeof(__llvm_profile_header) + Header->BinaryIdsSize +
+ Header->DataSize * sizeof(__llvm_profile_data) + Header->NamesSize +
+ Header->CountersSize * __llvm_profile_counter_entry_size())
+ return 1;
+
+ for (SrcData = SrcDataStart,
+ DstData = (__llvm_profile_data *)__llvm_profile_begin_data();
+ SrcData < SrcDataEnd; ++SrcData, ++DstData) {
+ if (SrcData->NameRef != DstData->NameRef ||
+ SrcData->FuncHash != DstData->FuncHash ||
+ SrcData->NumCounters != DstData->NumCounters)
+ return 1;
+ }
+
+ /* Matched! */
+ return 0;
+}
+
+static uintptr_t signextIfWin64(void *V) {
+#ifdef _WIN64
+ return (uintptr_t)(int32_t)(uintptr_t)V;
+#else
+ return (uintptr_t)V;
+#endif
+}
+
+COMPILER_RT_VISIBILITY
+int __llvm_profile_merge_from_buffer(const char *ProfileData,
+ uint64_t ProfileSize) {
+ if (__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) {
+ PROF_ERR(
+ "%s\n",
+ "Debug info correlation does not support profile merging at runtime. "
+ "Instead, merge raw profiles using the llvm-profdata tool.");
+ return 1;
+ }
+
+ __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData;
+ __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData;
+ char *SrcCountersStart;
+ const char *SrcNameStart;
+ const char *SrcValueProfDataStart, *SrcValueProfData;
+ uintptr_t CountersDelta = Header->CountersDelta;
+
+ SrcDataStart =
+ (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header) +
+ Header->BinaryIdsSize);
+ SrcDataEnd = SrcDataStart + Header->DataSize;
+ SrcCountersStart = (char *)SrcDataEnd;
+ SrcNameStart = SrcCountersStart +
+ Header->CountersSize * __llvm_profile_counter_entry_size();
+ SrcValueProfDataStart =
+ SrcNameStart + Header->NamesSize +
+ __llvm_profile_get_num_padding_bytes(Header->NamesSize);
+ if (SrcNameStart < SrcCountersStart)
+ return 1;
+
+ for (SrcData = SrcDataStart,
+ DstData = (__llvm_profile_data *)__llvm_profile_begin_data(),
+ SrcValueProfData = SrcValueProfDataStart;
+ SrcData < SrcDataEnd; ++SrcData, ++DstData) {
+ // For the in-memory destination, CounterPtr is the distance from the start
+ // address of the data to the start address of the counter. On WIN64,
+ // CounterPtr is a truncated 32-bit value due to COFF limitation. Sign
+ // extend CounterPtr to get the original value.
+ char *DstCounters =
+ (char *)((uintptr_t)DstData + signextIfWin64(DstData->CounterPtr));
+ unsigned NVK = 0;
+
+ // SrcData is a serialized representation of the memory image. We need to
+ // compute the in-buffer counter offset from the in-memory address distance.
+ // The initial CountersDelta is the in-memory address difference
+ // start(__llvm_prf_cnts)-start(__llvm_prf_data), so SrcData->CounterPtr -
+ // CountersDelta computes the offset into the in-buffer counter section.
+ //
+ // On WIN64, CountersDelta is truncated as well, so no need for signext.
+ char *SrcCounters =
+ SrcCountersStart + ((uintptr_t)SrcData->CounterPtr - CountersDelta);
+ // CountersDelta needs to be decreased as we advance to the next data
+ // record.
+ CountersDelta -= sizeof(*SrcData);
+ unsigned NC = SrcData->NumCounters;
+ if (NC == 0)
+ return 1;
+ if (SrcCounters < SrcCountersStart || SrcCounters >= SrcNameStart ||
+ (SrcCounters + __llvm_profile_counter_entry_size() * NC) > SrcNameStart)
+ return 1;
+ for (unsigned I = 0; I < NC; I++) {
+ if (__llvm_profile_get_version() & VARIANT_MASK_BYTE_COVERAGE) {
+ // A value of zero signifies the function is covered.
+ DstCounters[I] &= SrcCounters[I];
+ } else {
+ ((uint64_t *)DstCounters)[I] += ((uint64_t *)SrcCounters)[I];
+ }
+ }
+
+ /* Now merge value profile data. */
+ if (!VPMergeHook)
+ continue;
+
+ for (unsigned I = 0; I <= IPVK_Last; I++)
+ NVK += (SrcData->NumValueSites[I] != 0);
+
+ if (!NVK)
+ continue;
+
+ if (SrcValueProfData >= ProfileData + ProfileSize)
+ return 1;
+ VPMergeHook((ValueProfData *)SrcValueProfData, DstData);
+ SrcValueProfData =
+ SrcValueProfData + ((ValueProfData *)SrcValueProfData)->TotalSize;
+ }
+
+ return 0;
+}
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingMergeFile.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingMergeFile.c
new file mode 100644
index 00000000000..8923ba21cc5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingMergeFile.c
@@ -0,0 +1,45 @@
+/*===- InstrProfilingMergeFile.c - Profile in-process Merging ------------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+|*===----------------------------------------------------------------------===
+|* This file defines APIs needed to support in-process merging for profile data
+|* stored in files.
+\*===----------------------------------------------------------------------===*/
+
+#if !defined(__Fuchsia__)
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+#include "InstrProfilingUtil.h"
+
+#define INSTR_PROF_VALUE_PROF_DATA
+#include "profile/InstrProfData.inc"
+
+/* Merge value profile data pointed to by SrcValueProfData into
+ * in-memory profile counters pointed by to DstData. */
+COMPILER_RT_VISIBILITY
+void lprofMergeValueProfData(ValueProfData *SrcValueProfData,
+ __llvm_profile_data *DstData) {
+ unsigned I, S, V, DstIndex = 0;
+ InstrProfValueData *VData;
+ ValueProfRecord *VR = getFirstValueProfRecord(SrcValueProfData);
+ for (I = 0; I < SrcValueProfData->NumValueKinds; I++) {
+ VData = getValueProfRecordValueData(VR);
+ unsigned SrcIndex = 0;
+ for (S = 0; S < VR->NumValueSites; S++) {
+ uint8_t NV = VR->SiteCountArray[S];
+ for (V = 0; V < NV; V++) {
+ __llvm_profile_instrument_target_value(VData[SrcIndex].Value, DstData,
+ DstIndex, VData[SrcIndex].Count);
+ ++SrcIndex;
+ }
+ ++DstIndex;
+ }
+ VR = getValueProfRecordNext(VR);
+ }
+}
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingNameVar.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingNameVar.c
new file mode 100644
index 00000000000..407272806ba
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingNameVar.c
@@ -0,0 +1,17 @@
+/*===- InstrProfilingNameVar.c - profile name variable setup -------------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+#include "InstrProfiling.h"
+
+/* char __llvm_profile_filename[1]
+ *
+ * The runtime should only provide its own definition of this symbol when the
+ * user has not specified one. Set this up by moving the runtime's copy of this
+ * symbol to an object file within the archive.
+ */
+COMPILER_RT_WEAK COMPILER_RT_VISIBILITY char INSTR_PROF_PROFILE_NAME_VAR[1] = {0};
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformDarwin.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformDarwin.c
new file mode 100644
index 00000000000..d9f2a113f5b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformDarwin.c
@@ -0,0 +1,75 @@
+/*===- InstrProfilingPlatformDarwin.c - Profile data on Darwin ------------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+// Note: This is linked into the Darwin kernel, and must remain compatible
+// with freestanding compilation. See `darwin_add_builtin_libraries`.
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+
+#if defined(__APPLE__)
+/* Use linker magic to find the bounds of the Data section. */
+COMPILER_RT_VISIBILITY
+extern __llvm_profile_data
+ DataStart __asm("section$start$__DATA$" INSTR_PROF_DATA_SECT_NAME);
+COMPILER_RT_VISIBILITY
+extern __llvm_profile_data
+ DataEnd __asm("section$end$__DATA$" INSTR_PROF_DATA_SECT_NAME);
+COMPILER_RT_VISIBILITY
+extern char
+ NamesStart __asm("section$start$__DATA$" INSTR_PROF_NAME_SECT_NAME);
+COMPILER_RT_VISIBILITY
+extern char NamesEnd __asm("section$end$__DATA$" INSTR_PROF_NAME_SECT_NAME);
+COMPILER_RT_VISIBILITY
+extern char
+ CountersStart __asm("section$start$__DATA$" INSTR_PROF_CNTS_SECT_NAME);
+COMPILER_RT_VISIBILITY
+extern char CountersEnd __asm("section$end$__DATA$" INSTR_PROF_CNTS_SECT_NAME);
+COMPILER_RT_VISIBILITY
+extern uint32_t
+ OrderFileStart __asm("section$start$__DATA$" INSTR_PROF_ORDERFILE_SECT_NAME);
+
+COMPILER_RT_VISIBILITY
+extern ValueProfNode
+ VNodesStart __asm("section$start$__DATA$" INSTR_PROF_VNODES_SECT_NAME);
+COMPILER_RT_VISIBILITY
+extern ValueProfNode
+ VNodesEnd __asm("section$end$__DATA$" INSTR_PROF_VNODES_SECT_NAME);
+
+COMPILER_RT_VISIBILITY
+const __llvm_profile_data *__llvm_profile_begin_data(void) {
+ return &DataStart;
+}
+COMPILER_RT_VISIBILITY
+const __llvm_profile_data *__llvm_profile_end_data(void) { return &DataEnd; }
+COMPILER_RT_VISIBILITY
+const char *__llvm_profile_begin_names(void) { return &NamesStart; }
+COMPILER_RT_VISIBILITY
+const char *__llvm_profile_end_names(void) { return &NamesEnd; }
+COMPILER_RT_VISIBILITY
+char *__llvm_profile_begin_counters(void) { return &CountersStart; }
+COMPILER_RT_VISIBILITY
+char *__llvm_profile_end_counters(void) { return &CountersEnd; }
+COMPILER_RT_VISIBILITY
+uint32_t *__llvm_profile_begin_orderfile(void) { return &OrderFileStart; }
+
+COMPILER_RT_VISIBILITY
+ValueProfNode *__llvm_profile_begin_vnodes(void) {
+ return &VNodesStart;
+}
+COMPILER_RT_VISIBILITY
+ValueProfNode *__llvm_profile_end_vnodes(void) { return &VNodesEnd; }
+
+COMPILER_RT_VISIBILITY ValueProfNode *CurrentVNode = &VNodesStart;
+COMPILER_RT_VISIBILITY ValueProfNode *EndVNode = &VNodesEnd;
+
+COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
+ return 0;
+}
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformFuchsia.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformFuchsia.c
new file mode 100644
index 00000000000..eae1402b6c0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformFuchsia.c
@@ -0,0 +1,190 @@
+/*===- InstrProfilingPlatformFuchsia.c - Profile data Fuchsia platform ----===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+/*
+ * This file implements the profiling runtime for Fuchsia and defines the
+ * shared profile runtime interface. Each module (executable or DSO) statically
+ * links in the whole profile runtime to satisfy the calls from its
+ * instrumented code. Several modules in the same program might be separately
+ * compiled and even use different versions of the instrumentation ABI and data
+ * format. All they share in common is the VMO and the offset, which live in
+ * exported globals so that exactly one definition will be shared across all
+ * modules. Each module has its own independent runtime that registers its own
+ * atexit hook to append its own data into the shared VMO which is published
+ * via the data sink hook provided by Fuchsia's dynamic linker.
+ */
+
+#if defined(__Fuchsia__)
+
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#error #include <zircon/process.h>
+#error #include <zircon/sanitizer.h>
+#error #include <zircon/status.h>
+#error #include <zircon/syscalls.h>
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+#include "InstrProfilingUtil.h"
+
+/* This variable is an external reference to symbol defined by the compiler. */
+COMPILER_RT_VISIBILITY extern intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_VAR;
+
+COMPILER_RT_VISIBILITY unsigned lprofProfileDumped(void) {
+ return 1;
+}
+COMPILER_RT_VISIBILITY void lprofSetProfileDumped(unsigned Value) {}
+
+static const char ProfileSinkName[] = "llvm-profile";
+
+static inline void lprofWrite(const char *fmt, ...) {
+ char s[256];
+
+ va_list ap;
+ va_start(ap, fmt);
+ int ret = vsnprintf(s, sizeof(s), fmt, ap);
+ va_end(ap);
+
+ __sanitizer_log_write(s, ret);
+}
+
+struct lprofVMOWriterCtx {
+ /* VMO that contains the profile data for this module. */
+ zx_handle_t Vmo;
+ /* Current offset within the VMO where data should be written next. */
+ uint64_t Offset;
+};
+
+static uint32_t lprofVMOWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
+ uint32_t NumIOVecs) {
+ struct lprofVMOWriterCtx *Ctx = (struct lprofVMOWriterCtx *)This->WriterCtx;
+
+ /* Compute the total length of data to be written. */
+ size_t Length = 0;
+ for (uint32_t I = 0; I < NumIOVecs; I++)
+ Length += IOVecs[I].ElmSize * IOVecs[I].NumElm;
+
+ /* Resize the VMO to ensure there's sufficient space for the data. */
+ zx_status_t Status = _zx_vmo_set_size(Ctx->Vmo, Ctx->Offset + Length);
+ if (Status != ZX_OK)
+ return -1;
+
+ /* Copy the data into VMO. */
+ for (uint32_t I = 0; I < NumIOVecs; I++) {
+ size_t Length = IOVecs[I].ElmSize * IOVecs[I].NumElm;
+ if (IOVecs[I].Data) {
+ Status = _zx_vmo_write(Ctx->Vmo, IOVecs[I].Data, Ctx->Offset, Length);
+ if (Status != ZX_OK)
+ return -1;
+ } else if (IOVecs[I].UseZeroPadding) {
+ /* Resizing the VMO should zero fill. */
+ }
+ Ctx->Offset += Length;
+ }
+
+ /* Record the profile size as a property of the VMO. */
+ _zx_object_set_property(Ctx->Vmo, ZX_PROP_VMO_CONTENT_SIZE, &Ctx->Offset,
+ sizeof(Ctx->Offset));
+
+ return 0;
+}
+
+static void initVMOWriter(ProfDataWriter *This, struct lprofVMOWriterCtx *Ctx) {
+ This->Write = lprofVMOWriter;
+ This->WriterCtx = Ctx;
+}
+
+/* This method is invoked by the runtime initialization hook
+ * InstrProfilingRuntime.o if it is linked in. */
+COMPILER_RT_VISIBILITY
+void __llvm_profile_initialize(void) {
+ /* Check if there is llvm/runtime version mismatch. */
+ if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
+ lprofWrite("LLVM Profile: runtime and instrumentation version mismatch: "
+ "expected %d, but got %d\n",
+ INSTR_PROF_RAW_VERSION,
+ (int)GET_VERSION(__llvm_profile_get_version()));
+ return;
+ }
+
+ const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
+ const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
+ const char *CountersBegin = __llvm_profile_begin_counters();
+ const char *CountersEnd = __llvm_profile_end_counters();
+ const uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
+ const uint64_t CountersOffset =
+ sizeof(__llvm_profile_header) + __llvm_write_binary_ids(NULL) + DataSize;
+ uint64_t CountersSize =
+ __llvm_profile_get_counters_size(CountersBegin, CountersEnd);
+
+ /* Don't publish a VMO if there are no counters. */
+ if (!CountersSize)
+ return;
+
+ zx_status_t Status;
+
+ /* Create a VMO to hold the profile data. */
+ zx_handle_t Vmo = ZX_HANDLE_INVALID;
+ Status = _zx_vmo_create(0, ZX_VMO_RESIZABLE, &Vmo);
+ if (Status != ZX_OK) {
+ lprofWrite("LLVM Profile: cannot create VMO: %s\n",
+ _zx_status_get_string(Status));
+ return;
+ }
+
+ /* Give the VMO a name that includes the module signature. */
+ char VmoName[ZX_MAX_NAME_LEN];
+ snprintf(VmoName, sizeof(VmoName), "%" PRIu64 ".profraw",
+ lprofGetLoadModuleSignature());
+ _zx_object_set_property(Vmo, ZX_PROP_NAME, VmoName, strlen(VmoName));
+
+ /* Write the profile data into the mapped region. */
+ ProfDataWriter VMOWriter;
+ struct lprofVMOWriterCtx Ctx = {.Vmo = Vmo, .Offset = 0};
+ initVMOWriter(&VMOWriter, &Ctx);
+ if (lprofWriteData(&VMOWriter, 0, 0) != 0) {
+ lprofWrite("LLVM Profile: failed to write data\n");
+ _zx_handle_close(Vmo);
+ return;
+ }
+
+ uint64_t Len = 0;
+ Status = _zx_vmo_get_size(Vmo, &Len);
+ if (Status != ZX_OK) {
+ lprofWrite("LLVM Profile: failed to get the VMO size: %s\n",
+ _zx_status_get_string(Status));
+ _zx_handle_close(Vmo);
+ return;
+ }
+
+ uintptr_t Mapping;
+ Status =
+ _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0,
+ Vmo, 0, Len, &Mapping);
+ if (Status != ZX_OK) {
+ lprofWrite("LLVM Profile: failed to map the VMO: %s\n",
+ _zx_status_get_string(Status));
+ _zx_handle_close(Vmo);
+ return;
+ }
+
+ /* Publish the VMO which contains profile data to the system. Note that this
+ * also consumes the VMO handle. */
+ __sanitizer_publish_data(ProfileSinkName, Vmo);
+
+ /* Update the profile fields based on the current mapping. */
+ INSTR_PROF_PROFILE_COUNTER_BIAS_VAR =
+ (intptr_t)Mapping - (uintptr_t)CountersBegin + CountersOffset;
+
+ /* Return the memory allocated for counters to OS. */
+ lprofReleaseMemoryPagesToOS((uintptr_t)CountersBegin, (uintptr_t)CountersEnd);
+}
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformLinux.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformLinux.c
new file mode 100644
index 00000000000..adf4132c6b4
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformLinux.c
@@ -0,0 +1,270 @@
+/*===- InstrProfilingPlatformLinux.c - Profile data Linux platform ------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
+ (defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__) || \
+ defined(_AIX)
+
+#if !defined(_AIX)
+#include <elf.h>
+#include <link.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+
+#if defined(__FreeBSD__) && !defined(ElfW)
+/*
+ * FreeBSD's elf.h and link.h headers do not define the ElfW(type) macro yet.
+ * If this is added to all supported FreeBSD versions in the future, this
+ * compatibility macro can be removed.
+ */
+#define ElfW(type) __ElfN(type)
+#endif
+
+#define PROF_DATA_START INSTR_PROF_SECT_START(INSTR_PROF_DATA_COMMON)
+#define PROF_DATA_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_DATA_COMMON)
+#define PROF_NAME_START INSTR_PROF_SECT_START(INSTR_PROF_NAME_COMMON)
+#define PROF_NAME_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_NAME_COMMON)
+#define PROF_CNTS_START INSTR_PROF_SECT_START(INSTR_PROF_CNTS_COMMON)
+#define PROF_CNTS_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_CNTS_COMMON)
+#define PROF_ORDERFILE_START INSTR_PROF_SECT_START(INSTR_PROF_ORDERFILE_COMMON)
+#define PROF_VNODES_START INSTR_PROF_SECT_START(INSTR_PROF_VNODES_COMMON)
+#define PROF_VNODES_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_VNODES_COMMON)
+
+/* Declare section start and stop symbols for various sections
+ * generated by compiler instrumentation.
+ */
+extern __llvm_profile_data PROF_DATA_START COMPILER_RT_VISIBILITY
+ COMPILER_RT_WEAK;
+extern __llvm_profile_data PROF_DATA_STOP COMPILER_RT_VISIBILITY
+ COMPILER_RT_WEAK;
+extern char PROF_CNTS_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
+extern char PROF_CNTS_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
+extern uint32_t PROF_ORDERFILE_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
+extern char PROF_NAME_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
+extern char PROF_NAME_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
+extern ValueProfNode PROF_VNODES_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
+extern ValueProfNode PROF_VNODES_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
+
+COMPILER_RT_VISIBILITY const __llvm_profile_data *
+__llvm_profile_begin_data(void) {
+ return &PROF_DATA_START;
+}
+COMPILER_RT_VISIBILITY const __llvm_profile_data *
+__llvm_profile_end_data(void) {
+ return &PROF_DATA_STOP;
+}
+COMPILER_RT_VISIBILITY const char *__llvm_profile_begin_names(void) {
+ return &PROF_NAME_START;
+}
+COMPILER_RT_VISIBILITY const char *__llvm_profile_end_names(void) {
+ return &PROF_NAME_STOP;
+}
+COMPILER_RT_VISIBILITY char *__llvm_profile_begin_counters(void) {
+ return &PROF_CNTS_START;
+}
+COMPILER_RT_VISIBILITY char *__llvm_profile_end_counters(void) {
+ return &PROF_CNTS_STOP;
+}
+COMPILER_RT_VISIBILITY uint32_t *__llvm_profile_begin_orderfile(void) {
+ return &PROF_ORDERFILE_START;
+}
+
+COMPILER_RT_VISIBILITY ValueProfNode *
+__llvm_profile_begin_vnodes(void) {
+ return &PROF_VNODES_START;
+}
+COMPILER_RT_VISIBILITY ValueProfNode *__llvm_profile_end_vnodes(void) {
+ return &PROF_VNODES_STOP;
+}
+COMPILER_RT_VISIBILITY ValueProfNode *CurrentVNode = &PROF_VNODES_START;
+COMPILER_RT_VISIBILITY ValueProfNode *EndVNode = &PROF_VNODES_STOP;
+
+#ifdef NT_GNU_BUILD_ID
+static size_t RoundUp(size_t size, size_t align) {
+ return (size + align - 1) & ~(align - 1);
+}
+
+/*
+ * Write binary id length and then its data, because binary id does not
+ * have a fixed length.
+ */
+static int WriteOneBinaryId(ProfDataWriter *Writer, uint64_t BinaryIdLen,
+ const uint8_t *BinaryIdData,
+ uint64_t BinaryIdPadding) {
+ ProfDataIOVec BinaryIdIOVec[] = {
+ {&BinaryIdLen, sizeof(uint64_t), 1, 0},
+ {BinaryIdData, sizeof(uint8_t), BinaryIdLen, 0},
+ {NULL, sizeof(uint8_t), BinaryIdPadding, 1},
+ };
+ if (Writer->Write(Writer, BinaryIdIOVec,
+ sizeof(BinaryIdIOVec) / sizeof(*BinaryIdIOVec)))
+ return -1;
+
+ /* Successfully wrote binary id, report success. */
+ return 0;
+}
+
+/*
+ * Look for the note that has the name "GNU\0" and type NT_GNU_BUILD_ID
+ * that contains build id. If build id exists, write binary id.
+ *
+ * Each note in notes section starts with a struct which includes
+ * n_namesz, n_descsz, and n_type members. It is followed by the name
+ * (whose length is defined in n_namesz) and then by the descriptor
+ * (whose length is defined in n_descsz).
+ *
+ * Note sections like .note.ABI-tag and .note.gnu.build-id are aligned
+ * to 4 bytes, so round n_namesz and n_descsz to the nearest 4 bytes.
+ */
+static int WriteBinaryIdForNote(ProfDataWriter *Writer,
+ const ElfW(Nhdr) * Note) {
+ int BinaryIdSize = 0;
+ const char *NoteName = (const char *)Note + sizeof(ElfW(Nhdr));
+ if (Note->n_type == NT_GNU_BUILD_ID && Note->n_namesz == 4 &&
+ memcmp(NoteName, "GNU\0", 4) == 0) {
+ uint64_t BinaryIdLen = Note->n_descsz;
+ const uint8_t *BinaryIdData =
+ (const uint8_t *)(NoteName + RoundUp(Note->n_namesz, 4));
+ uint8_t BinaryIdPadding = __llvm_profile_get_num_padding_bytes(BinaryIdLen);
+ if (Writer != NULL && WriteOneBinaryId(Writer, BinaryIdLen, BinaryIdData,
+ BinaryIdPadding) == -1)
+ return -1;
+
+ BinaryIdSize = sizeof(BinaryIdLen) + BinaryIdLen + BinaryIdPadding;
+ }
+
+ return BinaryIdSize;
+}
+
+/*
+ * Helper function that iterates through notes section and find build ids.
+ * If writer is given, write binary ids into profiles.
+ * If an error happens while writing, return -1.
+ */
+static int WriteBinaryIds(ProfDataWriter *Writer, const ElfW(Nhdr) * Note,
+ const ElfW(Nhdr) * NotesEnd) {
+ int BinaryIdsSize = 0;
+ while (Note < NotesEnd) {
+ int OneBinaryIdSize = WriteBinaryIdForNote(Writer, Note);
+ if (OneBinaryIdSize == -1)
+ return -1;
+ BinaryIdsSize += OneBinaryIdSize;
+
+ /* Calculate the offset of the next note in notes section. */
+ size_t NoteOffset = sizeof(ElfW(Nhdr)) + RoundUp(Note->n_namesz, 4) +
+ RoundUp(Note->n_descsz, 4);
+ Note = (const ElfW(Nhdr) *)((const char *)(Note) + NoteOffset);
+ }
+
+ return BinaryIdsSize;
+}
+
+/*
+ * Write binary ids into profiles if writer is given.
+ * Return the total size of binary ids.
+ * If an error happens while writing, return -1.
+ */
+COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
+ extern const ElfW(Ehdr) __ehdr_start __attribute__((visibility("hidden")));
+ const ElfW(Ehdr) *ElfHeader = &__ehdr_start;
+ const ElfW(Phdr) *ProgramHeader =
+ (const ElfW(Phdr) *)((uintptr_t)ElfHeader + ElfHeader->e_phoff);
+
+ int TotalBinaryIdsSize = 0;
+ uint32_t I;
+ /* Iterate through entries in the program header. */
+ for (I = 0; I < ElfHeader->e_phnum; I++) {
+ /* Look for the notes segment in program header entries. */
+ if (ProgramHeader[I].p_type != PT_NOTE)
+ continue;
+
+ /* There can be multiple notes segment, and examine each of them. */
+ const ElfW(Nhdr) * Note;
+ const ElfW(Nhdr) * NotesEnd;
+ /*
+ * When examining notes in file, use p_offset, which is the offset within
+ * the elf file, to find the start of notes.
+ */
+ if (ProgramHeader[I].p_memsz == 0 ||
+ ProgramHeader[I].p_memsz == ProgramHeader[I].p_filesz) {
+ Note = (const ElfW(Nhdr) *)((uintptr_t)ElfHeader +
+ ProgramHeader[I].p_offset);
+ NotesEnd = (const ElfW(Nhdr) *)((const char *)(Note) +
+ ProgramHeader[I].p_filesz);
+ } else {
+ /*
+ * When examining notes in memory, use p_vaddr, which is the address of
+ * section after loaded to memory, to find the start of notes.
+ */
+ Note =
+ (const ElfW(Nhdr) *)((uintptr_t)ElfHeader + ProgramHeader[I].p_vaddr);
+ NotesEnd =
+ (const ElfW(Nhdr) *)((const char *)(Note) + ProgramHeader[I].p_memsz);
+ }
+
+ int BinaryIdsSize = WriteBinaryIds(Writer, Note, NotesEnd);
+ if (TotalBinaryIdsSize == -1)
+ return -1;
+
+ TotalBinaryIdsSize += BinaryIdsSize;
+ }
+
+ return TotalBinaryIdsSize;
+}
+#else /* !NT_GNU_BUILD_ID */
+/*
+ * Fallback implementation for targets that don't support the GNU
+ * extensions NT_GNU_BUILD_ID and __ehdr_start.
+ */
+COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
+ return 0;
+}
+#endif
+
+#if defined(_AIX)
+// Empty stubs to allow linking object files using the registration-based scheme
+COMPILER_RT_VISIBILITY
+void __llvm_profile_register_function(void *Data_) {}
+
+COMPILER_RT_VISIBILITY
+void __llvm_profile_register_names_function(void *NamesStart,
+ uint64_t NamesSize) {}
+
+// The __start_SECNAME and __stop_SECNAME symbols (for SECNAME \in
+// {"__llvm_prf_cnts", "__llvm_prf_data", "__llvm_prf_name", "__llvm_prf_vnds"})
+// are always live when linking on AIX, regardless if the .o's being linked
+// reference symbols from the profile library (for example when no files were
+// compiled with -fprofile-generate). That's because these symbols are kept
+// alive through references in constructor functions that are always live in the
+// default linking model on AIX (-bcdtors:all). The __start_SECNAME and
+// __stop_SECNAME symbols are only resolved by the linker when the SECNAME
+// section exists. So for the scenario where the user objects have no such
+// section (i.e. when they are compiled with -fno-profile-generate), we always
+// define these zero length variables in each of the above 4 sections.
+static int dummy_cnts[0] COMPILER_RT_SECTION(
+ COMPILER_RT_SEG INSTR_PROF_CNTS_SECT_NAME);
+static int dummy_data[0] COMPILER_RT_SECTION(
+ COMPILER_RT_SEG INSTR_PROF_DATA_SECT_NAME);
+static const int dummy_name[0] COMPILER_RT_SECTION(
+ COMPILER_RT_SEG INSTR_PROF_NAME_SECT_NAME);
+static int dummy_vnds[0] COMPILER_RT_SECTION(
+ COMPILER_RT_SEG INSTR_PROF_VNODES_SECT_NAME);
+
+// To avoid GC'ing of the dummy variables by the linker, reference them in an
+// array and reference the array in the runtime registration code
+// (InstrProfilingRuntime.cpp)
+COMPILER_RT_VISIBILITY
+void *__llvm_profile_keep[] = {(void *)&dummy_cnts, (void *)&dummy_data,
+ (void *)&dummy_name, (void *)&dummy_vnds};
+#endif
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformOther.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformOther.c
new file mode 100644
index 00000000000..c7b6e842c9f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformOther.c
@@ -0,0 +1,109 @@
+/*===- InstrProfilingPlatformOther.c - Profile data default platform ------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+#if !defined(__APPLE__) && !defined(__linux__) && !defined(__FreeBSD__) && \
+ !defined(__Fuchsia__) && !(defined(__sun__) && defined(__svr4__)) && \
+ !defined(__NetBSD__) && !defined(_WIN32) && !defined(_AIX)
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+
+static const __llvm_profile_data *DataFirst = NULL;
+static const __llvm_profile_data *DataLast = NULL;
+static const char *NamesFirst = NULL;
+static const char *NamesLast = NULL;
+static char *CountersFirst = NULL;
+static char *CountersLast = NULL;
+static uint32_t *OrderFileFirst = NULL;
+
+static const void *getMinAddr(const void *A1, const void *A2) {
+ return A1 < A2 ? A1 : A2;
+}
+
+static const void *getMaxAddr(const void *A1, const void *A2) {
+ return A1 > A2 ? A1 : A2;
+}
+
+/*!
+ * \brief Register an instrumented function.
+ *
+ * Calls to this are emitted by clang with -fprofile-instr-generate. Such
+ * calls are only required (and only emitted) on targets where we haven't
+ * implemented linker magic to find the bounds of the sections.
+ */
+COMPILER_RT_VISIBILITY
+void __llvm_profile_register_function(void *Data_) {
+ /* TODO: Only emit this function if we can't use linker magic. */
+ const __llvm_profile_data *Data = (__llvm_profile_data *)Data_;
+ if (!DataFirst) {
+ DataFirst = Data;
+ DataLast = Data + 1;
+ CountersFirst = (char *)((uintptr_t)Data_ + Data->CounterPtr);
+ CountersLast =
+ CountersFirst + Data->NumCounters * __llvm_profile_counter_entry_size();
+ return;
+ }
+
+ DataFirst = (const __llvm_profile_data *)getMinAddr(DataFirst, Data);
+ CountersFirst = (char *)getMinAddr(
+ CountersFirst, (char *)((uintptr_t)Data_ + Data->CounterPtr));
+
+ DataLast = (const __llvm_profile_data *)getMaxAddr(DataLast, Data + 1);
+ CountersLast = (char *)getMaxAddr(
+ CountersLast,
+ (char *)((uintptr_t)Data_ + Data->CounterPtr) +
+ Data->NumCounters * __llvm_profile_counter_entry_size());
+}
+
+COMPILER_RT_VISIBILITY
+void __llvm_profile_register_names_function(void *NamesStart,
+ uint64_t NamesSize) {
+ if (!NamesFirst) {
+ NamesFirst = (const char *)NamesStart;
+ NamesLast = (const char *)NamesStart + NamesSize;
+ return;
+ }
+ NamesFirst = (const char *)getMinAddr(NamesFirst, NamesStart);
+ NamesLast =
+ (const char *)getMaxAddr(NamesLast, (const char *)NamesStart + NamesSize);
+}
+
+COMPILER_RT_VISIBILITY
+const __llvm_profile_data *__llvm_profile_begin_data(void) { return DataFirst; }
+COMPILER_RT_VISIBILITY
+const __llvm_profile_data *__llvm_profile_end_data(void) { return DataLast; }
+COMPILER_RT_VISIBILITY
+const char *__llvm_profile_begin_names(void) { return NamesFirst; }
+COMPILER_RT_VISIBILITY
+const char *__llvm_profile_end_names(void) { return NamesLast; }
+COMPILER_RT_VISIBILITY
+char *__llvm_profile_begin_counters(void) { return CountersFirst; }
+COMPILER_RT_VISIBILITY
+char *__llvm_profile_end_counters(void) { return CountersLast; }
+/* TODO: correctly set up OrderFileFirst. */
+COMPILER_RT_VISIBILITY
+uint32_t *__llvm_profile_begin_orderfile(void) { return OrderFileFirst; }
+
+COMPILER_RT_VISIBILITY
+ValueProfNode *__llvm_profile_begin_vnodes(void) {
+ return 0;
+}
+COMPILER_RT_VISIBILITY
+ValueProfNode *__llvm_profile_end_vnodes(void) { return 0; }
+
+COMPILER_RT_VISIBILITY ValueProfNode *CurrentVNode = 0;
+COMPILER_RT_VISIBILITY ValueProfNode *EndVNode = 0;
+
+COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
+ return 0;
+}
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformWindows.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformWindows.c
new file mode 100644
index 00000000000..dd576b2f835
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingPlatformWindows.c
@@ -0,0 +1,73 @@
+/*===- InstrProfilingPlatformWindows.c - Profile data on Windows ----------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+
+#if defined(_WIN32)
+
+#if defined(_MSC_VER)
+/* Merge read-write sections into .data. */
+#pragma comment(linker, "/MERGE:.lprfc=.data")
+#pragma comment(linker, "/MERGE:.lprfd=.data")
+#pragma comment(linker, "/MERGE:.lprfv=.data")
+#pragma comment(linker, "/MERGE:.lprfnd=.data")
+/* Do *NOT* merge .lprfn and .lcovmap into .rdata. llvm-cov must be able to find
+ * after the fact.
+ */
+
+/* Allocate read-only section bounds. */
+#pragma section(".lprfn$A", read)
+#pragma section(".lprfn$Z", read)
+
+/* Allocate read-write section bounds. */
+#pragma section(".lprfd$A", read, write)
+#pragma section(".lprfd$Z", read, write)
+#pragma section(".lprfc$A", read, write)
+#pragma section(".lprfc$Z", read, write)
+#pragma section(".lorderfile$A", read, write)
+#pragma section(".lprfnd$A", read, write)
+#pragma section(".lprfnd$Z", read, write)
+#endif
+
+__llvm_profile_data COMPILER_RT_SECTION(".lprfd$A") DataStart = {0};
+__llvm_profile_data COMPILER_RT_SECTION(".lprfd$Z") DataEnd = {0};
+
+const char COMPILER_RT_SECTION(".lprfn$A") NamesStart = '\0';
+const char COMPILER_RT_SECTION(".lprfn$Z") NamesEnd = '\0';
+
+char COMPILER_RT_SECTION(".lprfc$A") CountersStart;
+char COMPILER_RT_SECTION(".lprfc$Z") CountersEnd;
+uint32_t COMPILER_RT_SECTION(".lorderfile$A") OrderFileStart;
+
+ValueProfNode COMPILER_RT_SECTION(".lprfnd$A") VNodesStart;
+ValueProfNode COMPILER_RT_SECTION(".lprfnd$Z") VNodesEnd;
+
+const __llvm_profile_data *__llvm_profile_begin_data(void) {
+ return &DataStart + 1;
+}
+const __llvm_profile_data *__llvm_profile_end_data(void) { return &DataEnd; }
+
+const char *__llvm_profile_begin_names(void) { return &NamesStart + 1; }
+const char *__llvm_profile_end_names(void) { return &NamesEnd; }
+
+char *__llvm_profile_begin_counters(void) { return &CountersStart + 1; }
+char *__llvm_profile_end_counters(void) { return &CountersEnd; }
+uint32_t *__llvm_profile_begin_orderfile(void) { return &OrderFileStart; }
+
+ValueProfNode *__llvm_profile_begin_vnodes(void) { return &VNodesStart + 1; }
+ValueProfNode *__llvm_profile_end_vnodes(void) { return &VNodesEnd; }
+
+ValueProfNode *CurrentVNode = &VNodesStart + 1;
+ValueProfNode *EndVNode = &VNodesEnd;
+
+COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
+ return 0;
+}
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingPort.h b/contrib/libs/clang16-rt/lib/profile/InstrProfilingPort.h
new file mode 100644
index 00000000000..ed0905cc5f2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingPort.h
@@ -0,0 +1,152 @@
+/*===- InstrProfilingPort.h- Support library for PGO instrumentation ------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+/* This header must be included after all others so it can provide fallback
+ definitions for stuff missing in system headers. */
+
+#ifndef PROFILE_INSTRPROFILING_PORT_H_
+#define PROFILE_INSTRPROFILING_PORT_H_
+
+#ifdef _MSC_VER
+#define COMPILER_RT_ALIGNAS(x) __declspec(align(x))
+#define COMPILER_RT_VISIBILITY
+/* FIXME: selectany does not have the same semantics as weak. */
+#define COMPILER_RT_WEAK __declspec(selectany)
+/* Need to include <windows.h> */
+#define COMPILER_RT_ALLOCA _alloca
+/* Need to include <stdio.h> and <io.h> */
+#define COMPILER_RT_FTRUNCATE(f,l) _chsize(_fileno(f),l)
+#define COMPILER_RT_ALWAYS_INLINE __forceinline
+#define COMPILER_RT_CLEANUP(x)
+#define COMPILER_RT_USED
+#elif __GNUC__
+#ifdef _WIN32
+#define COMPILER_RT_FTRUNCATE(f, l) _chsize(fileno(f), l)
+#define COMPILER_RT_VISIBILITY
+#define COMPILER_RT_WEAK __attribute__((selectany))
+#else
+#define COMPILER_RT_FTRUNCATE(f, l) ftruncate(fileno(f), l)
+#define COMPILER_RT_VISIBILITY __attribute__((visibility("hidden")))
+#define COMPILER_RT_WEAK __attribute__((weak))
+#endif
+#define COMPILER_RT_ALIGNAS(x) __attribute__((aligned(x)))
+#define COMPILER_RT_ALLOCA __builtin_alloca
+#define COMPILER_RT_ALWAYS_INLINE inline __attribute((always_inline))
+#define COMPILER_RT_CLEANUP(x) __attribute__((cleanup(x)))
+#define COMPILER_RT_USED __attribute__((used))
+#endif
+
+#if defined(__APPLE__)
+#define COMPILER_RT_SEG "__DATA,"
+#else
+#define COMPILER_RT_SEG ""
+#endif
+
+#ifdef _MSC_VER
+#define COMPILER_RT_SECTION(Sect) __declspec(allocate(Sect))
+#else
+#define COMPILER_RT_SECTION(Sect) __attribute__((section(Sect)))
+#endif
+
+#define COMPILER_RT_MAX_HOSTLEN 128
+#ifdef __ORBIS__
+#define COMPILER_RT_GETHOSTNAME(Name, Len) ((void)(Name), (void)(Len), (-1))
+#else
+#define COMPILER_RT_GETHOSTNAME(Name, Len) lprofGetHostName(Name, Len)
+#endif
+
+#if COMPILER_RT_HAS_ATOMICS == 1
+#ifdef _WIN32
+#include <windows.h>
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#define snprintf _snprintf
+#endif
+#if defined(_WIN64)
+#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
+ (InterlockedCompareExchange64((LONGLONG volatile *)Ptr, (LONGLONG)NewV, \
+ (LONGLONG)OldV) == (LONGLONG)OldV)
+#define COMPILER_RT_PTR_FETCH_ADD(DomType, PtrVar, PtrIncr) \
+ (DomType *)InterlockedExchangeAdd64((LONGLONG volatile *)&PtrVar, \
+ (LONGLONG)sizeof(DomType) * PtrIncr)
+#else /* !defined(_WIN64) */
+#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
+ (InterlockedCompareExchange((LONG volatile *)Ptr, (LONG)NewV, (LONG)OldV) == \
+ (LONG)OldV)
+#define COMPILER_RT_PTR_FETCH_ADD(DomType, PtrVar, PtrIncr) \
+ (DomType *)InterlockedExchangeAdd((LONG volatile *)&PtrVar, \
+ (LONG)sizeof(DomType) * PtrIncr)
+#endif
+#else /* !defined(_WIN32) */
+#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
+ __sync_bool_compare_and_swap(Ptr, OldV, NewV)
+#define COMPILER_RT_PTR_FETCH_ADD(DomType, PtrVar, PtrIncr) \
+ (DomType *)__sync_fetch_and_add((long *)&PtrVar, sizeof(DomType) * PtrIncr)
+#endif
+#else /* COMPILER_RT_HAS_ATOMICS != 1 */
+#include "InstrProfilingUtil.h"
+#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
+ lprofBoolCmpXchg((void **)Ptr, OldV, NewV)
+#define COMPILER_RT_PTR_FETCH_ADD(DomType, PtrVar, PtrIncr) \
+ (DomType *)lprofPtrFetchAdd((void **)&PtrVar, sizeof(DomType) * PtrIncr)
+#endif
+
+#if defined(_WIN32)
+#define DIR_SEPARATOR '\\'
+#define DIR_SEPARATOR_2 '/'
+#else
+#define DIR_SEPARATOR '/'
+#endif
+
+#ifndef DIR_SEPARATOR_2
+#define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+#define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#if defined(_WIN32)
+#include <windows.h>
+static inline size_t getpagesize() {
+ SYSTEM_INFO S;
+ GetNativeSystemInfo(&S);
+ return S.dwPageSize;
+}
+#else /* defined(_WIN32) */
+#include <unistd.h>
+#endif /* defined(_WIN32) */
+
+#define PROF_ERR(Format, ...) \
+ fprintf(stderr, "LLVM Profile Error: " Format, __VA_ARGS__);
+
+#define PROF_WARN(Format, ...) \
+ fprintf(stderr, "LLVM Profile Warning: " Format, __VA_ARGS__);
+
+#define PROF_NOTE(Format, ...) \
+ fprintf(stderr, "LLVM Profile Note: " Format, __VA_ARGS__);
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#if defined(__FreeBSD__)
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+#else /* defined(__FreeBSD__) */
+
+#include <inttypes.h>
+#include <stdint.h>
+
+#endif /* defined(__FreeBSD__) && defined(__i386__) */
+
+#endif /* PROFILE_INSTRPROFILING_PORT_H_ */
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingRuntime.cpp b/contrib/libs/clang16-rt/lib/profile/InstrProfilingRuntime.cpp
new file mode 100644
index 00000000000..6b2ce970017
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingRuntime.cpp
@@ -0,0 +1,24 @@
+//===- InstrProfilingRuntime.cpp - PGO runtime initialization -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+
+#include "InstrProfiling.h"
+
+static int RegisterRuntime() {
+ __llvm_profile_initialize();
+#ifdef _AIX
+ extern COMPILER_RT_VISIBILITY void *__llvm_profile_keep[];
+ (void)*(void *volatile *)__llvm_profile_keep;
+#endif
+ return 0;
+}
+
+/* int __llvm_profile_runtime */
+COMPILER_RT_VISIBILITY int INSTR_PROF_PROFILE_RUNTIME_VAR = RegisterRuntime();
+}
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingUtil.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingUtil.c
new file mode 100644
index 00000000000..d630a2cf64c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingUtil.c
@@ -0,0 +1,375 @@
+/*===- InstrProfilingUtil.c - Support library for PGO instrumentation -----===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+#ifdef _WIN32
+#include <direct.h>
+#include <process.h>
+#include <windows.h>
+#include "WindowsMMap.h"
+#else
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#ifdef COMPILER_RT_HAS_UNAME
+#include <sys/utsname.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(__linux__)
+#include <signal.h>
+#include <sys/prctl.h>
+#endif
+
+#if defined(__Fuchsia__)
+#error #include <zircon/process.h>
+#error #include <zircon/syscalls.h>
+#endif
+
+#if defined(__FreeBSD__)
+#include <signal.h>
+#error #include <sys/procctl.h>
+#endif
+
+#include "InstrProfiling.h"
+#include "InstrProfilingUtil.h"
+
+COMPILER_RT_VISIBILITY unsigned lprofDirMode = 0755;
+
+COMPILER_RT_VISIBILITY
+void __llvm_profile_recursive_mkdir(char *path) {
+ int i;
+ int start = 1;
+
+#if defined(__ANDROID__) && defined(__ANDROID_API__) && \
+ defined(__ANDROID_API_FUTURE__) && \
+ __ANDROID_API__ == __ANDROID_API_FUTURE__
+ // Avoid spammy selinux denial messages in Android by not attempting to
+ // create directories in GCOV_PREFIX. These denials occur when creating (or
+ // even attempting to stat()) top-level directories like "/data".
+ //
+ // Do so by ignoring ${GCOV_PREFIX} when invoking mkdir().
+ const char *gcov_prefix = getenv("GCOV_PREFIX");
+ if (gcov_prefix != NULL) {
+ const int gcov_prefix_len = strlen(gcov_prefix);
+ if (strncmp(path, gcov_prefix, gcov_prefix_len) == 0)
+ start = gcov_prefix_len;
+ }
+#endif
+
+ for (i = start; path[i] != '\0'; ++i) {
+ char save = path[i];
+ if (!IS_DIR_SEPARATOR(path[i]))
+ continue;
+ path[i] = '\0';
+#ifdef _WIN32
+ _mkdir(path);
+#else
+ /* Some of these will fail, ignore it. */
+ mkdir(path, __llvm_profile_get_dir_mode());
+#endif
+ path[i] = save;
+ }
+}
+
+COMPILER_RT_VISIBILITY
+void __llvm_profile_set_dir_mode(unsigned Mode) { lprofDirMode = Mode; }
+
+COMPILER_RT_VISIBILITY
+unsigned __llvm_profile_get_dir_mode(void) { return lprofDirMode; }
+
+#if COMPILER_RT_HAS_ATOMICS != 1
+COMPILER_RT_VISIBILITY
+uint32_t lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV) {
+ void *R = *Ptr;
+ if (R == OldV) {
+ *Ptr = NewV;
+ return 1;
+ }
+ return 0;
+}
+COMPILER_RT_VISIBILITY
+void *lprofPtrFetchAdd(void **Mem, long ByteIncr) {
+ void *Old = *Mem;
+ *((char **)Mem) += ByteIncr;
+ return Old;
+}
+
+#endif
+
+#ifdef _WIN32
+COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) {
+ WCHAR Buffer[COMPILER_RT_MAX_HOSTLEN];
+ DWORD BufferSize = sizeof(Buffer);
+ BOOL Result =
+ GetComputerNameExW(ComputerNameDnsFullyQualified, Buffer, &BufferSize);
+ if (!Result)
+ return -1;
+ if (WideCharToMultiByte(CP_UTF8, 0, Buffer, -1, Name, Len, NULL, NULL) == 0)
+ return -1;
+ return 0;
+}
+#elif defined(COMPILER_RT_HAS_UNAME)
+COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) {
+ struct utsname N;
+ int R = uname(&N);
+ if (R >= 0) {
+ strncpy(Name, N.nodename, Len);
+ return 0;
+ }
+ return R;
+}
+#endif
+
+COMPILER_RT_VISIBILITY int lprofLockFd(int fd) {
+#ifdef COMPILER_RT_HAS_FCNTL_LCK
+ struct flock s_flock;
+
+ s_flock.l_whence = SEEK_SET;
+ s_flock.l_start = 0;
+ s_flock.l_len = 0; /* Until EOF. */
+ s_flock.l_pid = getpid();
+ s_flock.l_type = F_WRLCK;
+
+ while (fcntl(fd, F_SETLKW, &s_flock) == -1) {
+ if (errno != EINTR) {
+ if (errno == ENOLCK) {
+ return -1;
+ }
+ break;
+ }
+ }
+ return 0;
+#else
+ flock(fd, LOCK_EX);
+ return 0;
+#endif
+}
+
+COMPILER_RT_VISIBILITY int lprofUnlockFd(int fd) {
+#ifdef COMPILER_RT_HAS_FCNTL_LCK
+ struct flock s_flock;
+
+ s_flock.l_whence = SEEK_SET;
+ s_flock.l_start = 0;
+ s_flock.l_len = 0; /* Until EOF. */
+ s_flock.l_pid = getpid();
+ s_flock.l_type = F_UNLCK;
+
+ while (fcntl(fd, F_SETLKW, &s_flock) == -1) {
+ if (errno != EINTR) {
+ if (errno == ENOLCK) {
+ return -1;
+ }
+ break;
+ }
+ }
+ return 0;
+#else
+ flock(fd, LOCK_UN);
+ return 0;
+#endif
+}
+
+COMPILER_RT_VISIBILITY int lprofLockFileHandle(FILE *F) {
+ int fd;
+#if defined(_WIN32)
+ fd = _fileno(F);
+#else
+ fd = fileno(F);
+#endif
+ return lprofLockFd(fd);
+}
+
+COMPILER_RT_VISIBILITY int lprofUnlockFileHandle(FILE *F) {
+ int fd;
+#if defined(_WIN32)
+ fd = _fileno(F);
+#else
+ fd = fileno(F);
+#endif
+ return lprofUnlockFd(fd);
+}
+
+COMPILER_RT_VISIBILITY FILE *lprofOpenFileEx(const char *ProfileName) {
+ FILE *f;
+ int fd;
+#ifdef COMPILER_RT_HAS_FCNTL_LCK
+ fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
+ if (fd < 0)
+ return NULL;
+
+ if (lprofLockFd(fd) != 0)
+ PROF_WARN("Data may be corrupted during profile merging : %s\n",
+ "Fail to obtain file lock due to system limit.");
+
+ f = fdopen(fd, "r+b");
+#elif defined(_WIN32)
+ // FIXME: Use the wide variants to handle Unicode filenames.
+ HANDLE h = CreateFileA(ProfileName, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ if (h == INVALID_HANDLE_VALUE)
+ return NULL;
+
+ fd = _open_osfhandle((intptr_t)h, 0);
+ if (fd == -1) {
+ CloseHandle(h);
+ return NULL;
+ }
+
+ if (lprofLockFd(fd) != 0)
+ PROF_WARN("Data may be corrupted during profile merging : %s\n",
+ "Fail to obtain file lock due to system limit.");
+
+ f = _fdopen(fd, "r+b");
+ if (f == 0) {
+ CloseHandle(h);
+ return NULL;
+ }
+#else
+ /* Worst case no locking applied. */
+ PROF_WARN("Concurrent file access is not supported : %s\n",
+ "lack file locking");
+ fd = open(ProfileName, O_RDWR | O_CREAT, 0666);
+ if (fd < 0)
+ return NULL;
+ f = fdopen(fd, "r+b");
+#endif
+
+ return f;
+}
+
+COMPILER_RT_VISIBILITY const char *lprofGetPathPrefix(int *PrefixStrip,
+ size_t *PrefixLen) {
+ const char *Prefix = getenv("GCOV_PREFIX");
+ const char *PrefixStripStr = getenv("GCOV_PREFIX_STRIP");
+
+ *PrefixLen = 0;
+ *PrefixStrip = 0;
+ if (Prefix == NULL || Prefix[0] == '\0')
+ return NULL;
+
+ if (PrefixStripStr) {
+ *PrefixStrip = atoi(PrefixStripStr);
+
+ /* Negative GCOV_PREFIX_STRIP values are ignored */
+ if (*PrefixStrip < 0)
+ *PrefixStrip = 0;
+ } else {
+ *PrefixStrip = 0;
+ }
+ *PrefixLen = strlen(Prefix);
+
+ return Prefix;
+}
+
+COMPILER_RT_VISIBILITY void
+lprofApplyPathPrefix(char *Dest, const char *PathStr, const char *Prefix,
+ size_t PrefixLen, int PrefixStrip) {
+
+ const char *Ptr;
+ int Level;
+ const char *StrippedPathStr = PathStr;
+
+ for (Level = 0, Ptr = PathStr + 1; Level < PrefixStrip; ++Ptr) {
+ if (*Ptr == '\0')
+ break;
+
+ if (!IS_DIR_SEPARATOR(*Ptr))
+ continue;
+
+ StrippedPathStr = Ptr;
+ ++Level;
+ }
+
+ memcpy(Dest, Prefix, PrefixLen);
+
+ if (!IS_DIR_SEPARATOR(Prefix[PrefixLen - 1]))
+ Dest[PrefixLen++] = DIR_SEPARATOR;
+
+ memcpy(Dest + PrefixLen, StrippedPathStr, strlen(StrippedPathStr) + 1);
+}
+
+COMPILER_RT_VISIBILITY const char *
+lprofFindFirstDirSeparator(const char *Path) {
+ const char *Sep = strchr(Path, DIR_SEPARATOR);
+#if defined(DIR_SEPARATOR_2)
+ const char *Sep2 = strchr(Path, DIR_SEPARATOR_2);
+ if (Sep2 && (!Sep || Sep2 < Sep))
+ Sep = Sep2;
+#endif
+ return Sep;
+}
+
+COMPILER_RT_VISIBILITY const char *lprofFindLastDirSeparator(const char *Path) {
+ const char *Sep = strrchr(Path, DIR_SEPARATOR);
+#if defined(DIR_SEPARATOR_2)
+ const char *Sep2 = strrchr(Path, DIR_SEPARATOR_2);
+ if (Sep2 && (!Sep || Sep2 > Sep))
+ Sep = Sep2;
+#endif
+ return Sep;
+}
+
+COMPILER_RT_VISIBILITY int lprofSuspendSigKill(void) {
+#if defined(__linux__)
+ int PDeachSig = 0;
+ /* Temporarily suspend getting SIGKILL upon exit of the parent process. */
+ if (prctl(PR_GET_PDEATHSIG, &PDeachSig) == 0 && PDeachSig == SIGKILL)
+ prctl(PR_SET_PDEATHSIG, 0);
+ return (PDeachSig == SIGKILL);
+#elif defined(__FreeBSD__)
+ int PDeachSig = 0, PDisableSig = 0;
+ if (procctl(P_PID, 0, PROC_PDEATHSIG_STATUS, &PDeachSig) == 0 &&
+ PDeachSig == SIGKILL)
+ procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &PDisableSig);
+ return (PDeachSig == SIGKILL);
+#else
+ return 0;
+#endif
+}
+
+COMPILER_RT_VISIBILITY void lprofRestoreSigKill(void) {
+#if defined(__linux__)
+ prctl(PR_SET_PDEATHSIG, SIGKILL);
+#elif defined(__FreeBSD__)
+ int PEnableSig = SIGKILL;
+ procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &PEnableSig);
+#endif
+}
+
+COMPILER_RT_VISIBILITY int lprofReleaseMemoryPagesToOS(uintptr_t Begin,
+ uintptr_t End) {
+#if defined(__ve__)
+ // VE doesn't support madvise.
+ return 0;
+#else
+ size_t PageSize = getpagesize();
+ uintptr_t BeginAligned = lprofRoundUpTo((uintptr_t)Begin, PageSize);
+ uintptr_t EndAligned = lprofRoundDownTo((uintptr_t)End, PageSize);
+ if (BeginAligned < EndAligned) {
+#if defined(__Fuchsia__)
+ return _zx_vmar_op_range(_zx_vmar_root_self(), ZX_VMAR_OP_DECOMMIT,
+ (zx_vaddr_t)BeginAligned,
+ EndAligned - BeginAligned, NULL, 0);
+#else
+ return madvise((void *)BeginAligned, EndAligned - BeginAligned,
+ MADV_DONTNEED);
+#endif
+ }
+ return 0;
+#endif
+}
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingUtil.h b/contrib/libs/clang16-rt/lib/profile/InstrProfilingUtil.h
new file mode 100644
index 00000000000..4a88a035809
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingUtil.h
@@ -0,0 +1,87 @@
+/*===- InstrProfilingUtil.h - Support library for PGO instrumentation -----===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+#ifndef PROFILE_INSTRPROFILINGUTIL_H
+#define PROFILE_INSTRPROFILINGUTIL_H
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+
+/*! \brief Create a directory tree. */
+void __llvm_profile_recursive_mkdir(char *Pathname);
+
+/*! Set the mode used when creating profile directories. */
+void __llvm_profile_set_dir_mode(unsigned Mode);
+
+/*! Return the directory creation mode. */
+unsigned __llvm_profile_get_dir_mode(void);
+
+int lprofLockFd(int fd);
+int lprofUnlockFd(int fd);
+int lprofLockFileHandle(FILE *F);
+int lprofUnlockFileHandle(FILE *F);
+
+/*! Open file \c Filename for read+write with write
+ * lock for exclusive access. The caller will block
+ * if the lock is already held by another process. */
+FILE *lprofOpenFileEx(const char *Filename);
+/* PS4 doesn't have setenv/getenv/fork. Define a shim. */
+#if __ORBIS__
+#include <sys/types.h>
+static inline char *getenv(const char *name) { return NULL; }
+static inline int setenv(const char *name, const char *value, int overwrite)
+{ return 0; }
+static pid_t fork() { return -1; }
+#endif /* #if __ORBIS__ */
+
+/* GCOV_PREFIX and GCOV_PREFIX_STRIP support */
+/* Return the path prefix specified by GCOV_PREFIX environment variable.
+ * If GCOV_PREFIX_STRIP is also specified, the strip level (integer value)
+ * is returned via \c *PrefixStrip. The prefix length is stored in *PrefixLen.
+ */
+const char *lprofGetPathPrefix(int *PrefixStrip, size_t *PrefixLen);
+/* Apply the path prefix specified in \c Prefix to path string in \c PathStr,
+ * and store the result to buffer pointed to by \c Buffer. If \c PrefixStrip
+ * is not zero, path prefixes are stripped from \c PathStr (the level of
+ * stripping is specified by \c PrefixStrip) before \c Prefix is added.
+ */
+void lprofApplyPathPrefix(char *Dest, const char *PathStr, const char *Prefix,
+ size_t PrefixLen, int PrefixStrip);
+
+/* Returns a pointer to the first occurrence of \c DIR_SEPARATOR char in
+ * the string \c Path, or NULL if the char is not found. */
+const char *lprofFindFirstDirSeparator(const char *Path);
+/* Returns a pointer to the last occurrence of \c DIR_SEPARATOR char in
+ * the string \c Path, or NULL if the char is not found. */
+const char *lprofFindLastDirSeparator(const char *Path);
+
+int lprofGetHostName(char *Name, int Len);
+
+unsigned lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV);
+void *lprofPtrFetchAdd(void **Mem, long ByteIncr);
+
+/* Temporarily suspend SIGKILL. Return value of 1 means a restore is needed.
+ * Other return values mean no restore is needed.
+ */
+int lprofSuspendSigKill();
+
+/* Restore previously suspended SIGKILL. */
+void lprofRestoreSigKill();
+
+static inline size_t lprofRoundUpTo(size_t x, size_t boundary) {
+ return (x + boundary - 1) & ~(boundary - 1);
+}
+
+static inline size_t lprofRoundDownTo(size_t x, size_t boundary) {
+ return x & ~(boundary - 1);
+}
+
+int lprofReleaseMemoryPagesToOS(uintptr_t Begin, uintptr_t End);
+
+#endif /* PROFILE_INSTRPROFILINGUTIL_H */
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingValue.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingValue.c
new file mode 100644
index 00000000000..c819a38553f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingValue.c
@@ -0,0 +1,358 @@
+/*===- InstrProfilingValue.c - Support library for PGO instrumentation ----===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+#include "InstrProfilingUtil.h"
+
+#define INSTR_PROF_VALUE_PROF_DATA
+#define INSTR_PROF_COMMON_API_IMPL
+#define INSTR_PROF_VALUE_PROF_MEMOP_API
+#include "profile/InstrProfData.inc"
+
+static int hasStaticCounters = 1;
+static int OutOfNodesWarnings = 0;
+static int hasNonDefaultValsPerSite = 0;
+#define INSTR_PROF_MAX_VP_WARNS 10
+#define INSTR_PROF_DEFAULT_NUM_VAL_PER_SITE 24
+#define INSTR_PROF_VNODE_POOL_SIZE 1024
+
+#ifndef _MSC_VER
+/* A shared static pool in addition to the vnodes statically
+ * allocated by the compiler. */
+COMPILER_RT_VISIBILITY ValueProfNode
+ lprofValueProfNodes[INSTR_PROF_VNODE_POOL_SIZE] COMPILER_RT_SECTION(
+ COMPILER_RT_SEG INSTR_PROF_VNODES_SECT_NAME);
+#endif
+
+COMPILER_RT_VISIBILITY uint32_t VPMaxNumValsPerSite =
+ INSTR_PROF_DEFAULT_NUM_VAL_PER_SITE;
+
+COMPILER_RT_VISIBILITY void lprofSetupValueProfiler(void) {
+ const char *Str = 0;
+ Str = getenv("LLVM_VP_MAX_NUM_VALS_PER_SITE");
+ if (Str && Str[0]) {
+ VPMaxNumValsPerSite = atoi(Str);
+ hasNonDefaultValsPerSite = 1;
+ }
+ if (VPMaxNumValsPerSite > INSTR_PROF_MAX_NUM_VAL_PER_SITE)
+ VPMaxNumValsPerSite = INSTR_PROF_MAX_NUM_VAL_PER_SITE;
+}
+
+COMPILER_RT_VISIBILITY void lprofSetMaxValsPerSite(uint32_t MaxVals) {
+ VPMaxNumValsPerSite = MaxVals;
+ hasNonDefaultValsPerSite = 1;
+}
+
+/* This method is only used in value profiler mock testing. */
+COMPILER_RT_VISIBILITY void
+__llvm_profile_set_num_value_sites(__llvm_profile_data *Data,
+ uint32_t ValueKind, uint16_t NumValueSites) {
+ *((uint16_t *)&Data->NumValueSites[ValueKind]) = NumValueSites;
+}
+
+/* This method is only used in value profiler mock testing. */
+COMPILER_RT_VISIBILITY const __llvm_profile_data *
+__llvm_profile_iterate_data(const __llvm_profile_data *Data) {
+ return Data + 1;
+}
+
+/* This method is only used in value profiler mock testing. */
+COMPILER_RT_VISIBILITY void *
+__llvm_get_function_addr(const __llvm_profile_data *Data) {
+ return Data->FunctionPointer;
+}
+
+/* Allocate an array that holds the pointers to the linked lists of
+ * value profile counter nodes. The number of element of the array
+ * is the total number of value profile sites instrumented. Returns
+ * 0 if allocation fails.
+ */
+
+static int allocateValueProfileCounters(__llvm_profile_data *Data) {
+ uint64_t NumVSites = 0;
+ uint32_t VKI;
+
+ /* This function will never be called when value site array is allocated
+ statically at compile time. */
+ hasStaticCounters = 0;
+ /* When dynamic allocation is enabled, allow tracking the max number of
+ * values allowd. */
+ if (!hasNonDefaultValsPerSite)
+ VPMaxNumValsPerSite = INSTR_PROF_MAX_NUM_VAL_PER_SITE;
+
+ for (VKI = IPVK_First; VKI <= IPVK_Last; ++VKI)
+ NumVSites += Data->NumValueSites[VKI];
+
+ // If NumVSites = 0, calloc is allowed to return a non-null pointer.
+ assert(NumVSites > 0 && "NumVSites can't be zero");
+ ValueProfNode **Mem =
+ (ValueProfNode **)calloc(NumVSites, sizeof(ValueProfNode *));
+ if (!Mem)
+ return 0;
+ if (!COMPILER_RT_BOOL_CMPXCHG(&Data->Values, 0, Mem)) {
+ free(Mem);
+ return 0;
+ }
+ return 1;
+}
+
+static ValueProfNode *allocateOneNode(void) {
+ ValueProfNode *Node;
+
+ if (!hasStaticCounters)
+ return (ValueProfNode *)calloc(1, sizeof(ValueProfNode));
+
+ /* Early check to avoid value wrapping around. */
+ if (CurrentVNode + 1 > EndVNode) {
+ if (OutOfNodesWarnings++ < INSTR_PROF_MAX_VP_WARNS) {
+ PROF_WARN("Unable to track new values: %s. "
+ " Consider using option -mllvm -vp-counters-per-site=<n> to "
+ "allocate more"
+ " value profile counters at compile time. \n",
+ "Running out of static counters");
+ }
+ return 0;
+ }
+ Node = COMPILER_RT_PTR_FETCH_ADD(ValueProfNode, CurrentVNode, 1);
+ /* Due to section padding, EndVNode point to a byte which is one pass
+ * an incomplete VNode, so we need to skip the last incomplete node. */
+ if (Node + 1 > EndVNode)
+ return 0;
+
+ return Node;
+}
+
+static COMPILER_RT_ALWAYS_INLINE void
+instrumentTargetValueImpl(uint64_t TargetValue, void *Data,
+ uint32_t CounterIndex, uint64_t CountValue) {
+ __llvm_profile_data *PData = (__llvm_profile_data *)Data;
+ if (!PData)
+ return;
+ if (!CountValue)
+ return;
+ if (!PData->Values) {
+ if (!allocateValueProfileCounters(PData))
+ return;
+ }
+
+ ValueProfNode **ValueCounters = (ValueProfNode **)PData->Values;
+ ValueProfNode *PrevVNode = NULL;
+ ValueProfNode *MinCountVNode = NULL;
+ ValueProfNode *CurVNode = ValueCounters[CounterIndex];
+ uint64_t MinCount = UINT64_MAX;
+
+ uint8_t VDataCount = 0;
+ while (CurVNode) {
+ if (TargetValue == CurVNode->Value) {
+ CurVNode->Count += CountValue;
+ return;
+ }
+ if (CurVNode->Count < MinCount) {
+ MinCount = CurVNode->Count;
+ MinCountVNode = CurVNode;
+ }
+ PrevVNode = CurVNode;
+ CurVNode = CurVNode->Next;
+ ++VDataCount;
+ }
+
+ if (VDataCount >= VPMaxNumValsPerSite) {
+ /* Bump down the min count node's count. If it reaches 0,
+ * evict it. This eviction/replacement policy makes hot
+ * targets more sticky while cold targets less so. In other
+ * words, it makes it less likely for the hot targets to be
+ * prematurally evicted during warmup/establishment period,
+ * when their counts are still low. In a special case when
+ * the number of values tracked is reduced to only one, this
+ * policy will guarantee that the dominating target with >50%
+ * total count will survive in the end. Note that this scheme
+ * allows the runtime to track the min count node in an adaptive
+ * manner. It can correct previous mistakes and eventually
+ * lock on a cold target that is alread in stable state.
+ *
+ * In very rare cases, this replacement scheme may still lead
+ * to target loss. For instance, out of \c N value slots, \c N-1
+ * slots are occupied by luke warm targets during the warmup
+ * period and the remaining one slot is competed by two or more
+ * very hot targets. If those hot targets occur in an interleaved
+ * way, none of them will survive (gain enough weight to throw out
+ * other established entries) due to the ping-pong effect.
+ * To handle this situation, user can choose to increase the max
+ * number of tracked values per value site. Alternatively, a more
+ * expensive eviction mechanism can be implemented. It requires
+ * the runtime to track the total number of evictions per-site.
+ * When the total number of evictions reaches certain threshold,
+ * the runtime can wipe out more than one lowest count entries
+ * to give space for hot targets.
+ */
+ if (MinCountVNode->Count <= CountValue) {
+ CurVNode = MinCountVNode;
+ CurVNode->Value = TargetValue;
+ CurVNode->Count = CountValue;
+ } else
+ MinCountVNode->Count -= CountValue;
+
+ return;
+ }
+
+ CurVNode = allocateOneNode();
+ if (!CurVNode)
+ return;
+ CurVNode->Value = TargetValue;
+ CurVNode->Count += CountValue;
+
+ uint32_t Success = 0;
+ if (!ValueCounters[CounterIndex])
+ Success =
+ COMPILER_RT_BOOL_CMPXCHG(&ValueCounters[CounterIndex], 0, CurVNode);
+ else if (PrevVNode && !PrevVNode->Next)
+ Success = COMPILER_RT_BOOL_CMPXCHG(&(PrevVNode->Next), 0, CurVNode);
+
+ if (!Success && !hasStaticCounters) {
+ free(CurVNode);
+ return;
+ }
+}
+
+COMPILER_RT_VISIBILITY void
+__llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
+ uint32_t CounterIndex) {
+ instrumentTargetValueImpl(TargetValue, Data, CounterIndex, 1);
+}
+COMPILER_RT_VISIBILITY void
+__llvm_profile_instrument_target_value(uint64_t TargetValue, void *Data,
+ uint32_t CounterIndex,
+ uint64_t CountValue) {
+ instrumentTargetValueImpl(TargetValue, Data, CounterIndex, CountValue);
+}
+
+/*
+ * The target values are partitioned into multiple ranges. The range spec is
+ * defined in InstrProfData.inc.
+ */
+COMPILER_RT_VISIBILITY void
+__llvm_profile_instrument_memop(uint64_t TargetValue, void *Data,
+ uint32_t CounterIndex) {
+ // Map the target value to the representative value of its range.
+ uint64_t RepValue = InstrProfGetRangeRepValue(TargetValue);
+ __llvm_profile_instrument_target(RepValue, Data, CounterIndex);
+}
+
+/*
+ * A wrapper struct that represents value profile runtime data.
+ * Like InstrProfRecord class which is used by profiling host tools,
+ * ValueProfRuntimeRecord also implements the abstract interfaces defined in
+ * ValueProfRecordClosure so that the runtime data can be serialized using
+ * shared C implementation.
+ */
+typedef struct ValueProfRuntimeRecord {
+ const __llvm_profile_data *Data;
+ ValueProfNode **NodesKind[IPVK_Last + 1];
+ uint8_t **SiteCountArray;
+} ValueProfRuntimeRecord;
+
+/* ValueProfRecordClosure Interface implementation. */
+
+static uint32_t getNumValueSitesRT(const void *R, uint32_t VK) {
+ return ((const ValueProfRuntimeRecord *)R)->Data->NumValueSites[VK];
+}
+
+static uint32_t getNumValueDataRT(const void *R, uint32_t VK) {
+ uint32_t S = 0, I;
+ const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
+ if (Record->SiteCountArray[VK] == INSTR_PROF_NULLPTR)
+ return 0;
+ for (I = 0; I < Record->Data->NumValueSites[VK]; I++)
+ S += Record->SiteCountArray[VK][I];
+ return S;
+}
+
+static uint32_t getNumValueDataForSiteRT(const void *R, uint32_t VK,
+ uint32_t S) {
+ const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
+ return Record->SiteCountArray[VK][S];
+}
+
+static ValueProfRuntimeRecord RTRecord;
+static ValueProfRecordClosure RTRecordClosure = {
+ &RTRecord, INSTR_PROF_NULLPTR, /* GetNumValueKinds */
+ getNumValueSitesRT, getNumValueDataRT, getNumValueDataForSiteRT,
+ INSTR_PROF_NULLPTR, /* RemapValueData */
+ INSTR_PROF_NULLPTR, /* GetValueForSite, */
+ INSTR_PROF_NULLPTR /* AllocValueProfData */
+};
+
+static uint32_t
+initializeValueProfRuntimeRecord(const __llvm_profile_data *Data,
+ uint8_t *SiteCountArray[]) {
+ unsigned I, J, S = 0, NumValueKinds = 0;
+ ValueProfNode **Nodes = (ValueProfNode **)Data->Values;
+ RTRecord.Data = Data;
+ RTRecord.SiteCountArray = SiteCountArray;
+ for (I = 0; I <= IPVK_Last; I++) {
+ uint16_t N = Data->NumValueSites[I];
+ if (!N)
+ continue;
+
+ NumValueKinds++;
+
+ RTRecord.NodesKind[I] = Nodes ? &Nodes[S] : INSTR_PROF_NULLPTR;
+ for (J = 0; J < N; J++) {
+ /* Compute value count for each site. */
+ uint32_t C = 0;
+ ValueProfNode *Site =
+ Nodes ? RTRecord.NodesKind[I][J] : INSTR_PROF_NULLPTR;
+ while (Site) {
+ C++;
+ Site = Site->Next;
+ }
+ if (C > UCHAR_MAX)
+ C = UCHAR_MAX;
+ RTRecord.SiteCountArray[I][J] = C;
+ }
+ S += N;
+ }
+ return NumValueKinds;
+}
+
+static ValueProfNode *getNextNValueData(uint32_t VK, uint32_t Site,
+ InstrProfValueData *Dst,
+ ValueProfNode *StartNode, uint32_t N) {
+ unsigned I;
+ ValueProfNode *VNode = StartNode ? StartNode : RTRecord.NodesKind[VK][Site];
+ for (I = 0; I < N; I++) {
+ Dst[I].Value = VNode->Value;
+ Dst[I].Count = VNode->Count;
+ VNode = VNode->Next;
+ }
+ return VNode;
+}
+
+static uint32_t getValueProfDataSizeWrapper(void) {
+ return getValueProfDataSize(&RTRecordClosure);
+}
+
+static uint32_t getNumValueDataForSiteWrapper(uint32_t VK, uint32_t S) {
+ return getNumValueDataForSiteRT(&RTRecord, VK, S);
+}
+
+static VPDataReaderType TheVPDataReader = {
+ initializeValueProfRuntimeRecord, getValueProfRecordHeaderSize,
+ getFirstValueProfRecord, getNumValueDataForSiteWrapper,
+ getValueProfDataSizeWrapper, getNextNValueData};
+
+COMPILER_RT_VISIBILITY VPDataReaderType *lprofGetVPDataReader(void) {
+ return &TheVPDataReader;
+}
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingVersionVar.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingVersionVar.c
new file mode 100644
index 00000000000..21400bfb2ca
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingVersionVar.c
@@ -0,0 +1,18 @@
+/*===- InstrProfilingVersionVar.c - profile version variable setup -------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+#include "InstrProfiling.h"
+
+/* uint64 __llvm_profile_raw_version
+ *
+ * The runtime should only provide its own definition of this symbol when the
+ * user has not specified one. Set this up by moving the runtime's copy of this
+ * symbol to an object file within the archive.
+ */
+COMPILER_RT_VISIBILITY COMPILER_RT_WEAK uint64_t INSTR_PROF_RAW_VERSION_VAR =
+ INSTR_PROF_RAW_VERSION;
diff --git a/contrib/libs/clang16-rt/lib/profile/InstrProfilingWriter.c b/contrib/libs/clang16-rt/lib/profile/InstrProfilingWriter.c
new file mode 100644
index 00000000000..366451a686c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/InstrProfilingWriter.c
@@ -0,0 +1,338 @@
+/*===- InstrProfilingWriter.c - Write instrumentation to a file or buffer -===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+// Note: This is linked into the Darwin kernel, and must remain compatible
+// with freestanding compilation. See `darwin_add_builtin_libraries`.
+
+#ifdef _MSC_VER
+/* For _alloca */
+#include <malloc.h>
+#endif
+#include <string.h>
+
+#include "InstrProfiling.h"
+#include "InstrProfilingInternal.h"
+#include "InstrProfilingPort.h"
+
+#define INSTR_PROF_VALUE_PROF_DATA
+#include "profile/InstrProfData.inc"
+
+COMPILER_RT_VISIBILITY void (*FreeHook)(void *) = NULL;
+static ProfBufferIO TheBufferIO;
+#define VP_BUFFER_SIZE 8 * 1024
+static uint8_t BufferIOBuffer[VP_BUFFER_SIZE];
+static InstrProfValueData VPDataArray[16];
+static uint32_t VPDataArraySize = sizeof(VPDataArray) / sizeof(*VPDataArray);
+
+COMPILER_RT_VISIBILITY uint8_t *DynamicBufferIOBuffer = 0;
+COMPILER_RT_VISIBILITY uint32_t VPBufferSize = 0;
+
+/* The buffer writer is responsible in keeping writer state
+ * across the call.
+ */
+COMPILER_RT_VISIBILITY uint32_t lprofBufferWriter(ProfDataWriter *This,
+ ProfDataIOVec *IOVecs,
+ uint32_t NumIOVecs) {
+ uint32_t I;
+ char **Buffer = (char **)&This->WriterCtx;
+ for (I = 0; I < NumIOVecs; I++) {
+ size_t Length = IOVecs[I].ElmSize * IOVecs[I].NumElm;
+ if (IOVecs[I].Data)
+ memcpy(*Buffer, IOVecs[I].Data, Length);
+ else if (IOVecs[I].UseZeroPadding) {
+ /* Allocating the buffer should zero fill. */
+ }
+ *Buffer += Length;
+ }
+ return 0;
+}
+
+static void llvmInitBufferIO(ProfBufferIO *BufferIO, ProfDataWriter *FileWriter,
+ uint8_t *Buffer, uint32_t BufferSz) {
+ BufferIO->FileWriter = FileWriter;
+ BufferIO->OwnFileWriter = 0;
+ BufferIO->BufferStart = Buffer;
+ BufferIO->BufferSz = BufferSz;
+ BufferIO->CurOffset = 0;
+}
+
+COMPILER_RT_VISIBILITY ProfBufferIO *
+lprofCreateBufferIO(ProfDataWriter *FileWriter) {
+ uint8_t *Buffer = DynamicBufferIOBuffer;
+ uint32_t BufferSize = VPBufferSize;
+ if (!Buffer) {
+ Buffer = &BufferIOBuffer[0];
+ BufferSize = sizeof(BufferIOBuffer);
+ }
+ llvmInitBufferIO(&TheBufferIO, FileWriter, Buffer, BufferSize);
+ return &TheBufferIO;
+}
+
+COMPILER_RT_VISIBILITY void lprofDeleteBufferIO(ProfBufferIO *BufferIO) {
+ if (BufferIO->OwnFileWriter)
+ FreeHook(BufferIO->FileWriter);
+ if (DynamicBufferIOBuffer) {
+ FreeHook(DynamicBufferIOBuffer);
+ DynamicBufferIOBuffer = 0;
+ VPBufferSize = 0;
+ }
+}
+
+COMPILER_RT_VISIBILITY int
+lprofBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, uint32_t Size) {
+ /* Buffer is not large enough, it is time to flush. */
+ if (Size + BufferIO->CurOffset > BufferIO->BufferSz) {
+ if (lprofBufferIOFlush(BufferIO) != 0)
+ return -1;
+ }
+ /* Special case, bypass the buffer completely. */
+ ProfDataIOVec IO[] = {{Data, sizeof(uint8_t), Size, 0}};
+ if (Size > BufferIO->BufferSz) {
+ if (BufferIO->FileWriter->Write(BufferIO->FileWriter, IO, 1))
+ return -1;
+ } else {
+ /* Write the data to buffer */
+ uint8_t *Buffer = BufferIO->BufferStart + BufferIO->CurOffset;
+ ProfDataWriter BufferWriter;
+ initBufferWriter(&BufferWriter, (char *)Buffer);
+ lprofBufferWriter(&BufferWriter, IO, 1);
+ BufferIO->CurOffset =
+ (uint8_t *)BufferWriter.WriterCtx - BufferIO->BufferStart;
+ }
+ return 0;
+}
+
+COMPILER_RT_VISIBILITY int lprofBufferIOFlush(ProfBufferIO *BufferIO) {
+ if (BufferIO->CurOffset) {
+ ProfDataIOVec IO[] = {
+ {BufferIO->BufferStart, sizeof(uint8_t), BufferIO->CurOffset, 0}};
+ if (BufferIO->FileWriter->Write(BufferIO->FileWriter, IO, 1))
+ return -1;
+ BufferIO->CurOffset = 0;
+ }
+ return 0;
+}
+
+/* Write out value profile data for function specified with \c Data.
+ * The implementation does not use the method \c serializeValueProfData
+ * which depends on dynamic memory allocation. In this implementation,
+ * value profile data is written out to \c BufferIO piecemeal.
+ */
+static int writeOneValueProfData(ProfBufferIO *BufferIO,
+ VPDataReaderType *VPDataReader,
+ const __llvm_profile_data *Data) {
+ unsigned I, NumValueKinds = 0;
+ ValueProfData VPHeader;
+ uint8_t *SiteCountArray[IPVK_Last + 1];
+
+ for (I = 0; I <= IPVK_Last; I++) {
+ if (!Data->NumValueSites[I])
+ SiteCountArray[I] = 0;
+ else {
+ uint32_t Sz =
+ VPDataReader->GetValueProfRecordHeaderSize(Data->NumValueSites[I]) -
+ offsetof(ValueProfRecord, SiteCountArray);
+ /* Only use alloca for this small byte array to avoid excessive
+ * stack growth. */
+ SiteCountArray[I] = (uint8_t *)COMPILER_RT_ALLOCA(Sz);
+ memset(SiteCountArray[I], 0, Sz);
+ }
+ }
+
+ /* If NumValueKinds returned is 0, there is nothing to write, report
+ success and return. This should match the raw profile reader's behavior. */
+ if (!(NumValueKinds = VPDataReader->InitRTRecord(Data, SiteCountArray)))
+ return 0;
+
+ /* First write the header structure. */
+ VPHeader.TotalSize = VPDataReader->GetValueProfDataSize();
+ VPHeader.NumValueKinds = NumValueKinds;
+ if (lprofBufferIOWrite(BufferIO, (const uint8_t *)&VPHeader,
+ sizeof(ValueProfData)))
+ return -1;
+
+ /* Make sure nothing else needs to be written before value profile
+ * records. */
+ if ((void *)VPDataReader->GetFirstValueProfRecord(&VPHeader) !=
+ (void *)(&VPHeader + 1))
+ return -1;
+
+ /* Write out the value profile record for each value kind
+ * one by one. */
+ for (I = 0; I <= IPVK_Last; I++) {
+ uint32_t J;
+ ValueProfRecord RecordHeader;
+ /* The size of the value prof record header without counting the
+ * site count array .*/
+ uint32_t RecordHeaderSize = offsetof(ValueProfRecord, SiteCountArray);
+ uint32_t SiteCountArraySize;
+
+ if (!Data->NumValueSites[I])
+ continue;
+
+ /* Write out the record header. */
+ RecordHeader.Kind = I;
+ RecordHeader.NumValueSites = Data->NumValueSites[I];
+ if (lprofBufferIOWrite(BufferIO, (const uint8_t *)&RecordHeader,
+ RecordHeaderSize))
+ return -1;
+
+ /* Write out the site value count array including padding space. */
+ SiteCountArraySize =
+ VPDataReader->GetValueProfRecordHeaderSize(Data->NumValueSites[I]) -
+ RecordHeaderSize;
+ if (lprofBufferIOWrite(BufferIO, SiteCountArray[I], SiteCountArraySize))
+ return -1;
+
+ /* Write out the value profile data for each value site. */
+ for (J = 0; J < Data->NumValueSites[I]; J++) {
+ uint32_t NRead, NRemain;
+ ValueProfNode *NextStartNode = 0;
+ NRemain = VPDataReader->GetNumValueDataForSite(I, J);
+ if (!NRemain)
+ continue;
+ /* Read and write out value data in small chunks till it is done. */
+ do {
+ NRead = (NRemain > VPDataArraySize ? VPDataArraySize : NRemain);
+ NextStartNode =
+ VPDataReader->GetValueData(I, /* ValueKind */
+ J, /* Site */
+ &VPDataArray[0], NextStartNode, NRead);
+ if (lprofBufferIOWrite(BufferIO, (const uint8_t *)&VPDataArray[0],
+ NRead * sizeof(InstrProfValueData)))
+ return -1;
+ NRemain -= NRead;
+ } while (NRemain != 0);
+ }
+ }
+ /* All done report success. */
+ return 0;
+}
+
+static int writeValueProfData(ProfDataWriter *Writer,
+ VPDataReaderType *VPDataReader,
+ const __llvm_profile_data *DataBegin,
+ const __llvm_profile_data *DataEnd) {
+ ProfBufferIO *BufferIO;
+ const __llvm_profile_data *DI = 0;
+
+ if (!VPDataReader)
+ return 0;
+
+ BufferIO = lprofCreateBufferIO(Writer);
+
+ for (DI = DataBegin; DI < DataEnd; DI++) {
+ if (writeOneValueProfData(BufferIO, VPDataReader, DI))
+ return -1;
+ }
+
+ if (lprofBufferIOFlush(BufferIO) != 0)
+ return -1;
+ lprofDeleteBufferIO(BufferIO);
+
+ return 0;
+}
+
+COMPILER_RT_VISIBILITY int lprofWriteData(ProfDataWriter *Writer,
+ VPDataReaderType *VPDataReader,
+ int SkipNameDataWrite) {
+ /* Match logic in __llvm_profile_write_buffer(). */
+ const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
+ const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
+ const char *CountersBegin = __llvm_profile_begin_counters();
+ const char *CountersEnd = __llvm_profile_end_counters();
+ const char *NamesBegin = __llvm_profile_begin_names();
+ const char *NamesEnd = __llvm_profile_end_names();
+ return lprofWriteDataImpl(Writer, DataBegin, DataEnd, CountersBegin,
+ CountersEnd, VPDataReader, NamesBegin, NamesEnd,
+ SkipNameDataWrite);
+}
+
+COMPILER_RT_VISIBILITY int
+lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
+ const __llvm_profile_data *DataEnd,
+ const char *CountersBegin, const char *CountersEnd,
+ VPDataReaderType *VPDataReader, const char *NamesBegin,
+ const char *NamesEnd, int SkipNameDataWrite) {
+ int DebugInfoCorrelate =
+ (__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) != 0ULL;
+
+ /* Calculate size of sections. */
+ const uint64_t DataSectionSize =
+ DebugInfoCorrelate ? 0 : __llvm_profile_get_data_size(DataBegin, DataEnd);
+ const uint64_t NumData =
+ DebugInfoCorrelate ? 0 : __llvm_profile_get_num_data(DataBegin, DataEnd);
+ const uint64_t CountersSectionSize =
+ __llvm_profile_get_counters_size(CountersBegin, CountersEnd);
+ const uint64_t NumCounters =
+ __llvm_profile_get_num_counters(CountersBegin, CountersEnd);
+ const uint64_t NamesSize = DebugInfoCorrelate ? 0 : NamesEnd - NamesBegin;
+
+ /* Create the header. */
+ __llvm_profile_header Header;
+
+ /* Determine how much padding is needed before/after the counters and after
+ * the names. */
+ uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
+ PaddingBytesAfterNames;
+ __llvm_profile_get_padding_sizes_for_counters(
+ DataSectionSize, CountersSectionSize, NamesSize,
+ &PaddingBytesBeforeCounters, &PaddingBytesAfterCounters,
+ &PaddingBytesAfterNames);
+
+ {
+ // TODO: Unfortunately the header's fields are named DataSize and
+ // CountersSize when they should be named NumData and NumCounters,
+ // respectively.
+ const uint64_t CountersSize = NumCounters;
+ const uint64_t DataSize = NumData;
+/* Initialize header structure. */
+#define INSTR_PROF_RAW_HEADER(Type, Name, Init) Header.Name = Init;
+#include "profile/InstrProfData.inc"
+ }
+
+ /* On WIN64, label differences are truncated 32-bit values. Truncate
+ * CountersDelta to match. */
+#ifdef _WIN64
+ Header.CountersDelta = (uint32_t)Header.CountersDelta;
+#endif
+
+ /* The data and names sections are omitted in lightweight mode. */
+ if (DebugInfoCorrelate) {
+ Header.CountersDelta = 0;
+ Header.NamesDelta = 0;
+ }
+
+ /* Write the profile header. */
+ ProfDataIOVec IOVec[] = {{&Header, sizeof(__llvm_profile_header), 1, 0}};
+ if (Writer->Write(Writer, IOVec, sizeof(IOVec) / sizeof(*IOVec)))
+ return -1;
+
+ /* Write the binary id lengths and data. */
+ if (__llvm_write_binary_ids(Writer) == -1)
+ return -1;
+
+ /* Write the profile data. */
+ ProfDataIOVec IOVecData[] = {
+ {DebugInfoCorrelate ? NULL : DataBegin, sizeof(uint8_t), DataSectionSize,
+ 0},
+ {NULL, sizeof(uint8_t), PaddingBytesBeforeCounters, 1},
+ {CountersBegin, sizeof(uint8_t), CountersSectionSize, 0},
+ {NULL, sizeof(uint8_t), PaddingBytesAfterCounters, 1},
+ {(SkipNameDataWrite || DebugInfoCorrelate) ? NULL : NamesBegin,
+ sizeof(uint8_t), NamesSize, 0},
+ {NULL, sizeof(uint8_t), PaddingBytesAfterNames, 1}};
+ if (Writer->Write(Writer, IOVecData, sizeof(IOVecData) / sizeof(*IOVecData)))
+ return -1;
+
+ /* Value profiling is not yet supported in continuous mode. */
+ if (__llvm_profile_is_continuous_mode_enabled())
+ return 0;
+
+ return writeValueProfData(Writer, VPDataReader, DataBegin, DataEnd);
+}
diff --git a/contrib/libs/clang16-rt/lib/profile/WindowsMMap.h b/contrib/libs/clang16-rt/lib/profile/WindowsMMap.h
new file mode 100644
index 00000000000..68b8de2398d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/WindowsMMap.h
@@ -0,0 +1,76 @@
+/*===- WindowsMMap.h - Support library for PGO instrumentation ------------===*\
+|*
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+|*
+\*===----------------------------------------------------------------------===*/
+
+#ifndef PROFILE_INSTRPROFILING_WINDOWS_MMAP_H
+#define PROFILE_INSTRPROFILING_WINDOWS_MMAP_H
+
+#if defined(_WIN32)
+
+#include <basetsd.h>
+#include <io.h>
+#include <sys/types.h>
+
+/*
+ * mmap() flags
+ */
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+#define PROT_EXEC 0x0
+
+#define MAP_FILE 0x00
+#define MAP_SHARED 0x01
+#define MAP_PRIVATE 0x02
+#define MAP_ANONYMOUS 0x20
+#define MAP_ANON MAP_ANONYMOUS
+#define MAP_FAILED ((void *) -1)
+
+/*
+ * msync() flags
+ */
+#define MS_ASYNC 0x0001 /* return immediately */
+#define MS_INVALIDATE 0x0002 /* invalidate all cached data */
+#define MS_SYNC 0x0010 /* msync synchronously */
+
+/*
+ * madvise() flags
+ */
+
+#define MADV_NORMAL 0 /* no special treatment */
+#define MADV_WILLNEED 3 /* expect access in the near future */
+#define MADV_DONTNEED 4 /* do not expect access in the near future */
+
+/*
+ * flock() operations
+ */
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* don't block when locking */
+#define LOCK_UN 8 /* unlock */
+
+#ifdef __USE_FILE_OFFSET64
+# define DWORD_HI(x) (x >> 32)
+# define DWORD_LO(x) ((x) & 0xffffffff)
+#else
+# define DWORD_HI(x) (0)
+# define DWORD_LO(x) (x)
+#endif
+
+void *mmap(void *start, size_t length, int prot, int flags, int fd,
+ off_t offset);
+
+void munmap(void *addr, size_t length);
+
+int msync(void *addr, size_t length, int flags);
+
+int madvise(void *addr, size_t length, int advice);
+
+int flock(int fd, int operation);
+
+#endif /* _WIN32 */
+
+#endif /* PROFILE_INSTRPROFILING_WINDOWS_MMAP_H */
diff --git a/contrib/libs/clang16-rt/lib/profile/ya.make b/contrib/libs/clang16-rt/lib/profile/ya.make
new file mode 100644
index 00000000000..5403ebac4d8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/profile/ya.make
@@ -0,0 +1,58 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.profile${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/include
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DCOMPILER_RT_HAS_ATOMICS=1
+ -DCOMPILER_RT_HAS_FCNTL_LCK=1
+ -DCOMPILER_RT_HAS_UNAME=1
+ -fno-lto
+ -fno-exceptions
+)
+
+SRCS(
+ GCDAProfiling.c
+ InstrProfiling.c
+ InstrProfilingBuffer.c
+ InstrProfilingFile.c
+ InstrProfilingInternal.c
+ InstrProfilingMerge.c
+ InstrProfilingMergeFile.c
+ InstrProfilingNameVar.c
+ InstrProfilingPlatformDarwin.c
+ InstrProfilingPlatformFuchsia.c
+ InstrProfilingPlatformLinux.c
+ InstrProfilingPlatformOther.c
+ InstrProfilingPlatformWindows.c
+ InstrProfilingRuntime.cpp
+ InstrProfilingUtil.c
+ InstrProfilingValue.c
+ InstrProfilingVersionVar.c
+ InstrProfilingWriter.c
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/safestack/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/safestack/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/safestack/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/safestack/safestack.cpp b/contrib/libs/clang16-rt/lib/safestack/safestack.cpp
new file mode 100644
index 00000000000..0751f3988b9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/safestack/safestack.cpp
@@ -0,0 +1,310 @@
+//===-- safestack.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the runtime support for the safe stack protection
+// mechanism. The runtime manages allocation/deallocation of the unsafe stack
+// for the main thread, as well as all pthreads that are created/destroyed
+// during program execution.
+//
+//===----------------------------------------------------------------------===//
+
+#include "safestack_platform.h"
+#include "safestack_util.h"
+
+#include <errno.h>
+#include <sys/resource.h>
+
+#include "interception/interception.h"
+
+using namespace safestack;
+
+// TODO: To make accessing the unsafe stack pointer faster, we plan to
+// eventually store it directly in the thread control block data structure on
+// platforms where this structure is pointed to by %fs or %gs. This is exactly
+// the same mechanism as currently being used by the traditional stack
+// protector pass to store the stack guard (see getStackCookieLocation()
+// function above). Doing so requires changing the tcbhead_t struct in glibc
+// on Linux and tcb struct in libc on FreeBSD.
+//
+// For now, store it in a thread-local variable.
+extern "C" {
+__attribute__((visibility(
+ "default"))) __thread void *__safestack_unsafe_stack_ptr = nullptr;
+}
+
+namespace {
+
+// TODO: The runtime library does not currently protect the safe stack beyond
+// relying on the system-enforced ASLR. The protection of the (safe) stack can
+// be provided by three alternative features:
+//
+// 1) Protection via hardware segmentation on x86-32 and some x86-64
+// architectures: the (safe) stack segment (implicitly accessed via the %ss
+// segment register) can be separated from the data segment (implicitly
+// accessed via the %ds segment register). Dereferencing a pointer to the safe
+// segment would result in a segmentation fault.
+//
+// 2) Protection via software fault isolation: memory writes that are not meant
+// to access the safe stack can be prevented from doing so through runtime
+// instrumentation. One way to do it is to allocate the safe stack(s) in the
+// upper half of the userspace and bitmask the corresponding upper bit of the
+// memory addresses of memory writes that are not meant to access the safe
+// stack.
+//
+// 3) Protection via information hiding on 64 bit architectures: the location
+// of the safe stack(s) can be randomized through secure mechanisms, and the
+// leakage of the stack pointer can be prevented. Currently, libc can leak the
+// stack pointer in several ways (e.g. in longjmp, signal handling, user-level
+// context switching related functions, etc.). These can be fixed in libc and
+// in other low-level libraries, by either eliminating the escaping/dumping of
+// the stack pointer (i.e., %rsp) when that's possible, or by using
+// encryption/PTR_MANGLE (XOR-ing the dumped stack pointer with another secret
+// we control and protect better, as is already done for setjmp in glibc.)
+// Furthermore, a static machine code level verifier can be ran after code
+// generation to make sure that the stack pointer is never written to memory,
+// or if it is, its written on the safe stack.
+//
+// Finally, while the Unsafe Stack pointer is currently stored in a thread
+// local variable, with libc support it could be stored in the TCB (thread
+// control block) as well, eliminating another level of indirection and making
+// such accesses faster. Alternatively, dedicating a separate register for
+// storing it would also be possible.
+
+/// Minimum stack alignment for the unsafe stack.
+const unsigned kStackAlign = 16;
+
+/// Default size of the unsafe stack. This value is only used if the stack
+/// size rlimit is set to infinity.
+const unsigned kDefaultUnsafeStackSize = 0x2800000;
+
+// Per-thread unsafe stack information. It's not frequently accessed, so there
+// it can be kept out of the tcb in normal thread-local variables.
+__thread void *unsafe_stack_start = nullptr;
+__thread size_t unsafe_stack_size = 0;
+__thread size_t unsafe_stack_guard = 0;
+
+inline void *unsafe_stack_alloc(size_t size, size_t guard) {
+ SFS_CHECK(size + guard >= size);
+ void *addr = Mmap(nullptr, size + guard, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON, -1, 0);
+ SFS_CHECK(MAP_FAILED != addr);
+ Mprotect(addr, guard, PROT_NONE);
+ return (char *)addr + guard;
+}
+
+inline void unsafe_stack_setup(void *start, size_t size, size_t guard) {
+ SFS_CHECK((char *)start + size >= (char *)start);
+ SFS_CHECK((char *)start + guard >= (char *)start);
+ void *stack_ptr = (char *)start + size;
+ SFS_CHECK((((size_t)stack_ptr) & (kStackAlign - 1)) == 0);
+
+ __safestack_unsafe_stack_ptr = stack_ptr;
+ unsafe_stack_start = start;
+ unsafe_stack_size = size;
+ unsafe_stack_guard = guard;
+}
+
+/// Thread data for the cleanup handler
+pthread_key_t thread_cleanup_key;
+
+/// Safe stack per-thread information passed to the thread_start function
+struct tinfo {
+ void *(*start_routine)(void *);
+ void *start_routine_arg;
+
+ void *unsafe_stack_start;
+ size_t unsafe_stack_size;
+ size_t unsafe_stack_guard;
+};
+
+/// Wrap the thread function in order to deallocate the unsafe stack when the
+/// thread terminates by returning from its main function.
+void *thread_start(void *arg) {
+ struct tinfo *tinfo = (struct tinfo *)arg;
+
+ void *(*start_routine)(void *) = tinfo->start_routine;
+ void *start_routine_arg = tinfo->start_routine_arg;
+
+ // Setup the unsafe stack; this will destroy tinfo content
+ unsafe_stack_setup(tinfo->unsafe_stack_start, tinfo->unsafe_stack_size,
+ tinfo->unsafe_stack_guard);
+
+ // Make sure out thread-specific destructor will be called
+ pthread_setspecific(thread_cleanup_key, (void *)1);
+
+ return start_routine(start_routine_arg);
+}
+
+/// Linked list used to store exiting threads stack/thread information.
+struct thread_stack_ll {
+ struct thread_stack_ll *next;
+ void *stack_base;
+ size_t size;
+ pid_t pid;
+ ThreadId tid;
+};
+
+/// Linked list of unsafe stacks for threads that are exiting. We delay
+/// unmapping them until the thread exits.
+thread_stack_ll *thread_stacks = nullptr;
+pthread_mutex_t thread_stacks_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/// Thread-specific data destructor. We want to free the unsafe stack only after
+/// this thread is terminated. libc can call functions in safestack-instrumented
+/// code (like free) after thread-specific data destructors have run.
+void thread_cleanup_handler(void *_iter) {
+ SFS_CHECK(unsafe_stack_start != nullptr);
+ pthread_setspecific(thread_cleanup_key, NULL);
+
+ pthread_mutex_lock(&thread_stacks_mutex);
+ // Temporary list to hold the previous threads stacks so we don't hold the
+ // thread_stacks_mutex for long.
+ thread_stack_ll *temp_stacks = thread_stacks;
+ thread_stacks = nullptr;
+ pthread_mutex_unlock(&thread_stacks_mutex);
+
+ pid_t pid = getpid();
+ ThreadId tid = GetTid();
+
+ // Free stacks for dead threads
+ thread_stack_ll **stackp = &temp_stacks;
+ while (*stackp) {
+ thread_stack_ll *stack = *stackp;
+ if (stack->pid != pid ||
+ (-1 == TgKill(stack->pid, stack->tid, 0) && errno == ESRCH)) {
+ Munmap(stack->stack_base, stack->size);
+ *stackp = stack->next;
+ free(stack);
+ } else
+ stackp = &stack->next;
+ }
+
+ thread_stack_ll *cur_stack =
+ (thread_stack_ll *)malloc(sizeof(thread_stack_ll));
+ cur_stack->stack_base = (char *)unsafe_stack_start - unsafe_stack_guard;
+ cur_stack->size = unsafe_stack_size + unsafe_stack_guard;
+ cur_stack->pid = pid;
+ cur_stack->tid = tid;
+
+ pthread_mutex_lock(&thread_stacks_mutex);
+ // Merge thread_stacks with the current thread's stack and any remaining
+ // temp_stacks
+ *stackp = thread_stacks;
+ cur_stack->next = temp_stacks;
+ thread_stacks = cur_stack;
+ pthread_mutex_unlock(&thread_stacks_mutex);
+
+ unsafe_stack_start = nullptr;
+}
+
+void EnsureInterceptorsInitialized();
+
+/// Intercept thread creation operation to allocate and setup the unsafe stack
+INTERCEPTOR(int, pthread_create, pthread_t *thread,
+ const pthread_attr_t *attr,
+ void *(*start_routine)(void*), void *arg) {
+ EnsureInterceptorsInitialized();
+ size_t size = 0;
+ size_t guard = 0;
+
+ if (attr) {
+ pthread_attr_getstacksize(attr, &size);
+ pthread_attr_getguardsize(attr, &guard);
+ } else {
+ // get pthread default stack size
+ pthread_attr_t tmpattr;
+ pthread_attr_init(&tmpattr);
+ pthread_attr_getstacksize(&tmpattr, &size);
+ pthread_attr_getguardsize(&tmpattr, &guard);
+ pthread_attr_destroy(&tmpattr);
+ }
+
+ SFS_CHECK(size);
+ size = RoundUpTo(size, kStackAlign);
+
+ void *addr = unsafe_stack_alloc(size, guard);
+ // Put tinfo at the end of the buffer. guard may be not page aligned.
+ // If that is so then some bytes after addr can be mprotected.
+ struct tinfo *tinfo =
+ (struct tinfo *)(((char *)addr) + size - sizeof(struct tinfo));
+ tinfo->start_routine = start_routine;
+ tinfo->start_routine_arg = arg;
+ tinfo->unsafe_stack_start = addr;
+ tinfo->unsafe_stack_size = size;
+ tinfo->unsafe_stack_guard = guard;
+
+ return REAL(pthread_create)(thread, attr, thread_start, tinfo);
+}
+
+pthread_mutex_t interceptor_init_mutex = PTHREAD_MUTEX_INITIALIZER;
+bool interceptors_inited = false;
+
+void EnsureInterceptorsInitialized() {
+ MutexLock lock(interceptor_init_mutex);
+ if (interceptors_inited)
+ return;
+
+ // Initialize pthread interceptors for thread allocation
+ INTERCEPT_FUNCTION(pthread_create);
+
+ interceptors_inited = true;
+}
+
+} // namespace
+
+extern "C" __attribute__((visibility("default")))
+#if !SANITIZER_CAN_USE_PREINIT_ARRAY
+// On ELF platforms, the constructor is invoked using .preinit_array (see below)
+__attribute__((constructor(0)))
+#endif
+void __safestack_init() {
+ // Determine the stack size for the main thread.
+ size_t size = kDefaultUnsafeStackSize;
+ size_t guard = 4096;
+
+ struct rlimit limit;
+ if (getrlimit(RLIMIT_STACK, &limit) == 0 && limit.rlim_cur != RLIM_INFINITY)
+ size = limit.rlim_cur;
+
+ // Allocate unsafe stack for main thread
+ void *addr = unsafe_stack_alloc(size, guard);
+ unsafe_stack_setup(addr, size, guard);
+
+ // Setup the cleanup handler
+ pthread_key_create(&thread_cleanup_key, thread_cleanup_handler);
+}
+
+#if SANITIZER_CAN_USE_PREINIT_ARRAY
+// On ELF platforms, run safestack initialization before any other constructors.
+// On other platforms we use the constructor attribute to arrange to run our
+// initialization early.
+extern "C" {
+__attribute__((section(".preinit_array"),
+ used)) void (*__safestack_preinit)(void) = __safestack_init;
+}
+#endif
+
+extern "C"
+ __attribute__((visibility("default"))) void *__get_unsafe_stack_bottom() {
+ return unsafe_stack_start;
+}
+
+extern "C"
+ __attribute__((visibility("default"))) void *__get_unsafe_stack_top() {
+ return (char*)unsafe_stack_start + unsafe_stack_size;
+}
+
+extern "C"
+ __attribute__((visibility("default"))) void *__get_unsafe_stack_start() {
+ return unsafe_stack_start;
+}
+
+extern "C"
+ __attribute__((visibility("default"))) void *__get_unsafe_stack_ptr() {
+ return __safestack_unsafe_stack_ptr;
+}
diff --git a/contrib/libs/clang16-rt/lib/safestack/safestack_platform.h b/contrib/libs/clang16-rt/lib/safestack/safestack_platform.h
new file mode 100644
index 00000000000..2b1fc139baa
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/safestack/safestack_platform.h
@@ -0,0 +1,124 @@
+//===-- safestack_platform.h ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements platform specific parts of SafeStack runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SAFESTACK_PLATFORM_H
+#define SAFESTACK_PLATFORM_H
+
+#include "safestack_util.h"
+#include "sanitizer_common/sanitizer_platform.h"
+
+#include <dlfcn.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#if !(SANITIZER_NETBSD || SANITIZER_FREEBSD || SANITIZER_LINUX)
+#error "Support for your platform has not been implemented"
+#endif
+
+#if SANITIZER_NETBSD
+#include <lwp.h>
+
+extern "C" void *__mmap(void *, size_t, int, int, int, int, off_t);
+#endif
+
+#if SANITIZER_FREEBSD
+#include <sys/thr.h>
+#endif
+
+namespace safestack {
+
+#if SANITIZER_NETBSD
+static void *GetRealLibcAddress(const char *symbol) {
+ void *real = dlsym(RTLD_NEXT, symbol);
+ if (!real)
+ real = dlsym(RTLD_DEFAULT, symbol);
+ if (!real) {
+ fprintf(stderr, "safestack GetRealLibcAddress failed for symbol=%s",
+ symbol);
+ abort();
+ }
+ return real;
+}
+
+#define _REAL(func, ...) real##_##func(__VA_ARGS__)
+#define DEFINE__REAL(ret_type, func, ...) \
+ static ret_type (*real_##func)(__VA_ARGS__) = NULL; \
+ if (!real_##func) { \
+ real_##func = (ret_type(*)(__VA_ARGS__))GetRealLibcAddress(#func); \
+ } \
+ SFS_CHECK(real_##func);
+#endif
+
+using ThreadId = uint64_t;
+
+inline ThreadId GetTid() {
+#if SANITIZER_NETBSD
+ DEFINE__REAL(int, _lwp_self);
+ return _REAL(_lwp_self);
+#elif SANITIZER_FREEBSD
+ long Tid;
+ thr_self(&Tid);
+ return Tid;
+#else
+ return syscall(SYS_gettid);
+#endif
+}
+
+inline int TgKill(pid_t pid, ThreadId tid, int sig) {
+#if SANITIZER_NETBSD
+ DEFINE__REAL(int, _lwp_kill, int a, int b);
+ (void)pid;
+ return _REAL(_lwp_kill, tid, sig);
+#elif SANITIZER_FREEBSD
+ return syscall(SYS_thr_kill2, pid, tid, sig);
+#else
+ return syscall(SYS_tgkill, pid, tid, sig);
+#endif
+}
+
+inline void *Mmap(void *addr, size_t length, int prot, int flags, int fd,
+ off_t offset) {
+#if SANITIZER_NETBSD
+ return __mmap(addr, length, prot, flags, fd, 0, offset);
+#elif SANITIZER_FREEBSD && (defined(__aarch64__) || defined(__x86_64__))
+ return (void *)__syscall(SYS_mmap, addr, length, prot, flags, fd, offset);
+#else
+ return (void *)syscall(SYS_mmap, addr, length, prot, flags, fd, offset);
+#endif
+}
+
+inline int Munmap(void *addr, size_t length) {
+#if SANITIZER_NETBSD
+ DEFINE__REAL(int, munmap, void *a, size_t b);
+ return _REAL(munmap, addr, length);
+#else
+ return syscall(SYS_munmap, addr, length);
+#endif
+}
+
+inline int Mprotect(void *addr, size_t length, int prot) {
+#if SANITIZER_NETBSD
+ DEFINE__REAL(int, mprotect, void *a, size_t b, int c);
+ return _REAL(mprotect, addr, length, prot);
+#else
+ return syscall(SYS_mprotect, addr, length, prot);
+#endif
+}
+
+} // namespace safestack
+
+#endif // SAFESTACK_PLATFORM_H
diff --git a/contrib/libs/clang16-rt/lib/safestack/safestack_util.h b/contrib/libs/clang16-rt/lib/safestack/safestack_util.h
new file mode 100644
index 00000000000..da3f11b54ca
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/safestack/safestack_util.h
@@ -0,0 +1,49 @@
+//===-- safestack_util.h --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains utility code for SafeStack implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SAFESTACK_UTIL_H
+#define SAFESTACK_UTIL_H
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+namespace safestack {
+
+#define SFS_CHECK(a) \
+ do { \
+ if (!(a)) { \
+ fprintf(stderr, "safestack CHECK failed: %s:%d %s\n", __FILE__, \
+ __LINE__, #a); \
+ abort(); \
+ }; \
+ } while (false)
+
+inline size_t RoundUpTo(size_t size, size_t boundary) {
+ SFS_CHECK((boundary & (boundary - 1)) == 0);
+ return (size + boundary - 1) & ~(boundary - 1);
+}
+
+class MutexLock {
+ public:
+ explicit MutexLock(pthread_mutex_t &mutex) : mutex_(&mutex) {
+ pthread_mutex_lock(mutex_);
+ }
+ ~MutexLock() { pthread_mutex_unlock(mutex_); }
+
+ private:
+ pthread_mutex_t *mutex_ = nullptr;
+};
+
+} // namespace safestack
+
+#endif // SAFESTACK_UTIL_H
diff --git a/contrib/libs/clang16-rt/lib/safestack/ya.make b/contrib/libs/clang16-rt/lib/safestack/ya.make
new file mode 100644
index 00000000000..6597f95daff
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/safestack/ya.make
@@ -0,0 +1,49 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.safestack${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ interception/interception_linux.cpp
+ interception/interception_mac.cpp
+ interception/interception_type_test.cpp
+ interception/interception_win.cpp
+ safestack/safestack.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sancov_flags.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sancov_flags.cpp
new file mode 100644
index 00000000000..ed46e88acdf
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sancov_flags.cpp
@@ -0,0 +1,58 @@
+//===-- sancov_flags.cpp ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Sanitizer Coverage runtime flags.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sancov_flags.h"
+#include "sanitizer_flag_parser.h"
+#include "sanitizer_platform.h"
+
+SANITIZER_INTERFACE_WEAK_DEF(const char*, __sancov_default_options, void) {
+ return "";
+}
+
+using namespace __sanitizer;
+
+namespace __sancov {
+
+SancovFlags sancov_flags_dont_use_directly; // use via flags();
+
+void SancovFlags::SetDefaults() {
+#define SANCOV_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "sancov_flags.inc"
+#undef SANCOV_FLAG
+}
+
+static void RegisterSancovFlags(FlagParser *parser, SancovFlags *f) {
+#define SANCOV_FLAG(Type, Name, DefaultValue, Description) \
+ RegisterFlag(parser, #Name, Description, &f->Name);
+#include "sancov_flags.inc"
+#undef SANCOV_FLAG
+}
+
+static const char *MaybeCallSancovDefaultOptions() {
+ return (&__sancov_default_options) ? __sancov_default_options() : "";
+}
+
+void InitializeSancovFlags() {
+ SancovFlags *f = sancov_flags();
+ f->SetDefaults();
+
+ FlagParser parser;
+ RegisterSancovFlags(&parser, f);
+
+ parser.ParseString(MaybeCallSancovDefaultOptions());
+ parser.ParseStringFromEnv("SANCOV_OPTIONS");
+
+ ReportUnrecognizedFlags();
+ if (f->help) parser.PrintFlagDescriptions();
+}
+
+} // namespace __sancov
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sancov_flags.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sancov_flags.h
new file mode 100644
index 00000000000..95d4ee5ca43
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sancov_flags.h
@@ -0,0 +1,39 @@
+//===-- sancov_flags.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Sanitizer Coverage runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANCOV_FLAGS_H
+#define SANCOV_FLAGS_H
+
+#include "sanitizer_flag_parser.h"
+#include "sanitizer_internal_defs.h"
+
+namespace __sancov {
+
+struct SancovFlags {
+#define SANCOV_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "sancov_flags.inc"
+#undef SANCOV_FLAG
+
+ void SetDefaults();
+};
+
+extern SancovFlags sancov_flags_dont_use_directly;
+
+inline SancovFlags* sancov_flags() { return &sancov_flags_dont_use_directly; }
+
+void InitializeSancovFlags();
+
+} // namespace __sancov
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE const char*
+__sancov_default_options();
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sancov_flags.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sancov_flags.inc
new file mode 100644
index 00000000000..de9ede217fc
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sancov_flags.inc
@@ -0,0 +1,20 @@
+//===-- sancov_flags.inc ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Sanitizer Coverage runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANCOV_FLAG
+#error "Defnine SANCOV_FLAG prior to including this file!"
+#endif
+
+SANCOV_FLAG(bool, symbolize, true,
+ "If set, coverage information will be symbolized by sancov tool "
+ "after dumping.")
+
+SANCOV_FLAG(bool, help, false, "Print flags help.")
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_addrhashmap.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_addrhashmap.h
new file mode 100644
index 00000000000..fe48b9caf06
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_addrhashmap.h
@@ -0,0 +1,393 @@
+//===-- sanitizer_addrhashmap.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Concurrent uptr->T hashmap.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ADDRHASHMAP_H
+#define SANITIZER_ADDRHASHMAP_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_mutex.h"
+#include "sanitizer_atomic.h"
+#include "sanitizer_allocator_internal.h"
+
+namespace __sanitizer {
+
+// Concurrent uptr->T hashmap.
+// T must be a POD type, kSize is preferably a prime but can be any number.
+// Usage example:
+//
+// typedef AddrHashMap<uptr, 11> Map;
+// Map m;
+// {
+// Map::Handle h(&m, addr);
+// use h.operator->() to access the data
+// if h.created() then the element was just created, and the current thread
+// has exclusive access to it
+// otherwise the current thread has only read access to the data
+// }
+// {
+// Map::Handle h(&m, addr, true);
+// this will remove the data from the map in Handle dtor
+// the current thread has exclusive access to the data
+// if !h.exists() then the element never existed
+// }
+// {
+// Map::Handle h(&m, addr, false, true);
+// this will create a new element or return a handle to an existing element
+// if !h.created() this thread does *not* have exclusive access to the data
+// }
+template<typename T, uptr kSize>
+class AddrHashMap {
+ private:
+ struct Cell {
+ atomic_uintptr_t addr;
+ T val;
+ };
+
+ struct AddBucket {
+ uptr cap;
+ uptr size;
+ Cell cells[1]; // variable len
+ };
+
+ static const uptr kBucketSize = 3;
+
+ struct Bucket {
+ Mutex mtx;
+ atomic_uintptr_t add;
+ Cell cells[kBucketSize];
+ };
+
+ public:
+ AddrHashMap();
+
+ class Handle {
+ public:
+ Handle(AddrHashMap<T, kSize> *map, uptr addr);
+ Handle(AddrHashMap<T, kSize> *map, uptr addr, bool remove);
+ Handle(AddrHashMap<T, kSize> *map, uptr addr, bool remove, bool create);
+
+ ~Handle();
+ T *operator->();
+ T &operator*();
+ const T &operator*() const;
+ bool created() const;
+ bool exists() const;
+
+ private:
+ friend AddrHashMap<T, kSize>;
+ AddrHashMap<T, kSize> *map_;
+ Bucket *bucket_;
+ Cell *cell_;
+ uptr addr_;
+ uptr addidx_;
+ bool created_;
+ bool remove_;
+ bool create_;
+ };
+
+ typedef void (*ForEachCallback)(const uptr key, const T &val, void *arg);
+ // ForEach acquires a lock on each bucket while iterating over
+ // elements. Note that this only ensures that the structure of the hashmap is
+ // unchanged, there may be a data race to the element itself.
+ void ForEach(ForEachCallback cb, void *arg);
+
+ private:
+ friend class Handle;
+ Bucket *table_;
+
+ void acquire(Handle *h);
+ void release(Handle *h);
+ uptr calcHash(uptr addr);
+};
+
+template <typename T, uptr kSize>
+void AddrHashMap<T, kSize>::ForEach(ForEachCallback cb, void *arg) {
+ for (uptr n = 0; n < kSize; n++) {
+ Bucket *bucket = &table_[n];
+
+ ReadLock lock(&bucket->mtx);
+
+ for (uptr i = 0; i < kBucketSize; i++) {
+ Cell *c = &bucket->cells[i];
+ uptr addr1 = atomic_load(&c->addr, memory_order_acquire);
+ if (addr1 != 0)
+ cb(addr1, c->val, arg);
+ }
+
+ // Iterate over any additional cells.
+ if (AddBucket *add =
+ (AddBucket *)atomic_load(&bucket->add, memory_order_acquire)) {
+ for (uptr i = 0; i < add->size; i++) {
+ Cell *c = &add->cells[i];
+ uptr addr1 = atomic_load(&c->addr, memory_order_acquire);
+ if (addr1 != 0)
+ cb(addr1, c->val, arg);
+ }
+ }
+ }
+}
+
+template<typename T, uptr kSize>
+AddrHashMap<T, kSize>::Handle::Handle(AddrHashMap<T, kSize> *map, uptr addr) {
+ map_ = map;
+ addr_ = addr;
+ remove_ = false;
+ create_ = true;
+ map_->acquire(this);
+}
+
+template<typename T, uptr kSize>
+AddrHashMap<T, kSize>::Handle::Handle(AddrHashMap<T, kSize> *map, uptr addr,
+ bool remove) {
+ map_ = map;
+ addr_ = addr;
+ remove_ = remove;
+ create_ = true;
+ map_->acquire(this);
+}
+
+template<typename T, uptr kSize>
+AddrHashMap<T, kSize>::Handle::Handle(AddrHashMap<T, kSize> *map, uptr addr,
+ bool remove, bool create) {
+ map_ = map;
+ addr_ = addr;
+ remove_ = remove;
+ create_ = create;
+ map_->acquire(this);
+}
+
+template<typename T, uptr kSize>
+AddrHashMap<T, kSize>::Handle::~Handle() {
+ map_->release(this);
+}
+
+template <typename T, uptr kSize>
+T *AddrHashMap<T, kSize>::Handle::operator->() {
+ return &cell_->val;
+}
+
+template <typename T, uptr kSize>
+const T &AddrHashMap<T, kSize>::Handle::operator*() const {
+ return cell_->val;
+}
+
+template <typename T, uptr kSize>
+T &AddrHashMap<T, kSize>::Handle::operator*() {
+ return cell_->val;
+}
+
+template<typename T, uptr kSize>
+bool AddrHashMap<T, kSize>::Handle::created() const {
+ return created_;
+}
+
+template<typename T, uptr kSize>
+bool AddrHashMap<T, kSize>::Handle::exists() const {
+ return cell_ != nullptr;
+}
+
+template<typename T, uptr kSize>
+AddrHashMap<T, kSize>::AddrHashMap() {
+ table_ = (Bucket*)MmapOrDie(kSize * sizeof(table_[0]), "AddrHashMap");
+}
+
+template <typename T, uptr kSize>
+void AddrHashMap<T, kSize>::acquire(Handle *h)
+ SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ uptr addr = h->addr_;
+ uptr hash = calcHash(addr);
+ Bucket *b = &table_[hash];
+
+ h->created_ = false;
+ h->addidx_ = -1U;
+ h->bucket_ = b;
+ h->cell_ = nullptr;
+
+ // If we want to remove the element, we need exclusive access to the bucket,
+ // so skip the lock-free phase.
+ if (h->remove_)
+ goto locked;
+
+ retry:
+ // First try to find an existing element w/o read mutex.
+ CHECK(!h->remove_);
+ // Check the embed cells.
+ for (uptr i = 0; i < kBucketSize; i++) {
+ Cell *c = &b->cells[i];
+ uptr addr1 = atomic_load(&c->addr, memory_order_acquire);
+ if (addr1 == addr) {
+ h->cell_ = c;
+ return;
+ }
+ }
+
+ // Check the add cells with read lock.
+ if (atomic_load(&b->add, memory_order_relaxed)) {
+ b->mtx.ReadLock();
+ AddBucket *add = (AddBucket*)atomic_load(&b->add, memory_order_relaxed);
+ for (uptr i = 0; i < add->size; i++) {
+ Cell *c = &add->cells[i];
+ uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
+ if (addr1 == addr) {
+ h->addidx_ = i;
+ h->cell_ = c;
+ return;
+ }
+ }
+ b->mtx.ReadUnlock();
+ }
+
+ locked:
+ // Re-check existence under write lock.
+ // Embed cells.
+ b->mtx.Lock();
+ for (uptr i = 0; i < kBucketSize; i++) {
+ Cell *c = &b->cells[i];
+ uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
+ if (addr1 == addr) {
+ if (h->remove_) {
+ h->cell_ = c;
+ return;
+ }
+ b->mtx.Unlock();
+ goto retry;
+ }
+ }
+
+ // Add cells.
+ AddBucket *add = (AddBucket*)atomic_load(&b->add, memory_order_relaxed);
+ if (add) {
+ for (uptr i = 0; i < add->size; i++) {
+ Cell *c = &add->cells[i];
+ uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
+ if (addr1 == addr) {
+ if (h->remove_) {
+ h->addidx_ = i;
+ h->cell_ = c;
+ return;
+ }
+ b->mtx.Unlock();
+ goto retry;
+ }
+ }
+ }
+
+ // The element does not exist, no need to create it if we want to remove.
+ if (h->remove_ || !h->create_) {
+ b->mtx.Unlock();
+ return;
+ }
+
+ // Now try to create it under the mutex.
+ h->created_ = true;
+ // See if we have a free embed cell.
+ for (uptr i = 0; i < kBucketSize; i++) {
+ Cell *c = &b->cells[i];
+ uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
+ if (addr1 == 0) {
+ h->cell_ = c;
+ return;
+ }
+ }
+
+ // Store in the add cells.
+ if (!add) {
+ // Allocate a new add array.
+ const uptr kInitSize = 64;
+ add = (AddBucket*)InternalAlloc(kInitSize);
+ internal_memset(add, 0, kInitSize);
+ add->cap = (kInitSize - sizeof(*add)) / sizeof(add->cells[0]) + 1;
+ add->size = 0;
+ atomic_store(&b->add, (uptr)add, memory_order_relaxed);
+ }
+ if (add->size == add->cap) {
+ // Grow existing add array.
+ uptr oldsize = sizeof(*add) + (add->cap - 1) * sizeof(add->cells[0]);
+ uptr newsize = oldsize * 2;
+ AddBucket *add1 = (AddBucket*)InternalAlloc(newsize);
+ internal_memset(add1, 0, newsize);
+ add1->cap = (newsize - sizeof(*add)) / sizeof(add->cells[0]) + 1;
+ add1->size = add->size;
+ internal_memcpy(add1->cells, add->cells, add->size * sizeof(add->cells[0]));
+ InternalFree(add);
+ atomic_store(&b->add, (uptr)add1, memory_order_relaxed);
+ add = add1;
+ }
+ // Store.
+ uptr i = add->size++;
+ Cell *c = &add->cells[i];
+ CHECK_EQ(atomic_load(&c->addr, memory_order_relaxed), 0);
+ h->addidx_ = i;
+ h->cell_ = c;
+ }
+
+ template <typename T, uptr kSize>
+ void AddrHashMap<T, kSize>::release(Handle *h)
+ SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ if (!h->cell_)
+ return;
+ Bucket *b = h->bucket_;
+ Cell *c = h->cell_;
+ uptr addr1 = atomic_load(&c->addr, memory_order_relaxed);
+ if (h->created_) {
+ // Denote completion of insertion.
+ CHECK_EQ(addr1, 0);
+ // After the following store, the element becomes available
+ // for lock-free reads.
+ atomic_store(&c->addr, h->addr_, memory_order_release);
+ b->mtx.Unlock();
+ } else if (h->remove_) {
+ // Denote that the cell is empty now.
+ CHECK_EQ(addr1, h->addr_);
+ atomic_store(&c->addr, 0, memory_order_release);
+ // See if we need to compact the bucket.
+ AddBucket *add = (AddBucket *)atomic_load(&b->add, memory_order_relaxed);
+ if (h->addidx_ == -1U) {
+ // Removed from embed array, move an add element into the freed cell.
+ if (add && add->size != 0) {
+ uptr last = --add->size;
+ Cell *c1 = &add->cells[last];
+ c->val = c1->val;
+ uptr addr1 = atomic_load(&c1->addr, memory_order_relaxed);
+ atomic_store(&c->addr, addr1, memory_order_release);
+ atomic_store(&c1->addr, 0, memory_order_release);
+ }
+ } else {
+ // Removed from add array, compact it.
+ uptr last = --add->size;
+ Cell *c1 = &add->cells[last];
+ if (c != c1) {
+ *c = *c1;
+ atomic_store(&c1->addr, 0, memory_order_relaxed);
+ }
+ }
+ if (add && add->size == 0) {
+ // FIXME(dvyukov): free add?
+ }
+ b->mtx.Unlock();
+ } else {
+ CHECK_EQ(addr1, h->addr_);
+ if (h->addidx_ != -1U)
+ b->mtx.ReadUnlock();
+ }
+ }
+
+template<typename T, uptr kSize>
+uptr AddrHashMap<T, kSize>::calcHash(uptr addr) {
+ addr += addr << 10;
+ addr ^= addr >> 6;
+ return addr % kSize;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_ADDRHASHMAP_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator.cpp
new file mode 100644
index 00000000000..25a43a59f04
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator.cpp
@@ -0,0 +1,209 @@
+//===-- sanitizer_allocator.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+// This allocator is used inside run-times.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_allocator.h"
+
+#include "sanitizer_allocator_checks.h"
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_atomic.h"
+#include "sanitizer_common.h"
+#include "sanitizer_platform.h"
+
+namespace __sanitizer {
+
+// Default allocator names.
+const char *PrimaryAllocatorName = "SizeClassAllocator";
+const char *SecondaryAllocatorName = "LargeMmapAllocator";
+
+static ALIGNED(64) char internal_alloc_placeholder[sizeof(InternalAllocator)];
+static atomic_uint8_t internal_allocator_initialized;
+static StaticSpinMutex internal_alloc_init_mu;
+
+static InternalAllocatorCache internal_allocator_cache;
+static StaticSpinMutex internal_allocator_cache_mu;
+
+InternalAllocator *internal_allocator() {
+ InternalAllocator *internal_allocator_instance =
+ reinterpret_cast<InternalAllocator *>(&internal_alloc_placeholder);
+ if (atomic_load(&internal_allocator_initialized, memory_order_acquire) == 0) {
+ SpinMutexLock l(&internal_alloc_init_mu);
+ if (atomic_load(&internal_allocator_initialized, memory_order_relaxed) ==
+ 0) {
+ internal_allocator_instance->Init(kReleaseToOSIntervalNever);
+ atomic_store(&internal_allocator_initialized, 1, memory_order_release);
+ }
+ }
+ return internal_allocator_instance;
+}
+
+static void *RawInternalAlloc(uptr size, InternalAllocatorCache *cache,
+ uptr alignment) {
+ if (alignment == 0) alignment = 8;
+ if (cache == 0) {
+ SpinMutexLock l(&internal_allocator_cache_mu);
+ return internal_allocator()->Allocate(&internal_allocator_cache, size,
+ alignment);
+ }
+ return internal_allocator()->Allocate(cache, size, alignment);
+}
+
+static void *RawInternalRealloc(void *ptr, uptr size,
+ InternalAllocatorCache *cache) {
+ uptr alignment = 8;
+ if (cache == 0) {
+ SpinMutexLock l(&internal_allocator_cache_mu);
+ return internal_allocator()->Reallocate(&internal_allocator_cache, ptr,
+ size, alignment);
+ }
+ return internal_allocator()->Reallocate(cache, ptr, size, alignment);
+}
+
+static void RawInternalFree(void *ptr, InternalAllocatorCache *cache) {
+ if (!cache) {
+ SpinMutexLock l(&internal_allocator_cache_mu);
+ return internal_allocator()->Deallocate(&internal_allocator_cache, ptr);
+ }
+ internal_allocator()->Deallocate(cache, ptr);
+}
+
+static void NORETURN ReportInternalAllocatorOutOfMemory(uptr requested_size) {
+ SetAllocatorOutOfMemory();
+ Report("FATAL: %s: internal allocator is out of memory trying to allocate "
+ "0x%zx bytes\n", SanitizerToolName, requested_size);
+ Die();
+}
+
+void *InternalAlloc(uptr size, InternalAllocatorCache *cache, uptr alignment) {
+ void *p = RawInternalAlloc(size, cache, alignment);
+ if (UNLIKELY(!p))
+ ReportInternalAllocatorOutOfMemory(size);
+ return p;
+}
+
+void *InternalRealloc(void *addr, uptr size, InternalAllocatorCache *cache) {
+ void *p = RawInternalRealloc(addr, size, cache);
+ if (UNLIKELY(!p))
+ ReportInternalAllocatorOutOfMemory(size);
+ return p;
+}
+
+void *InternalReallocArray(void *addr, uptr count, uptr size,
+ InternalAllocatorCache *cache) {
+ if (UNLIKELY(CheckForCallocOverflow(count, size))) {
+ Report(
+ "FATAL: %s: reallocarray parameters overflow: count * size (%zd * %zd) "
+ "cannot be represented in type size_t\n",
+ SanitizerToolName, count, size);
+ Die();
+ }
+ return InternalRealloc(addr, count * size, cache);
+}
+
+void *InternalCalloc(uptr count, uptr size, InternalAllocatorCache *cache) {
+ if (UNLIKELY(CheckForCallocOverflow(count, size))) {
+ Report("FATAL: %s: calloc parameters overflow: count * size (%zd * %zd) "
+ "cannot be represented in type size_t\n", SanitizerToolName, count,
+ size);
+ Die();
+ }
+ void *p = InternalAlloc(count * size, cache);
+ if (LIKELY(p))
+ internal_memset(p, 0, count * size);
+ return p;
+}
+
+void InternalFree(void *addr, InternalAllocatorCache *cache) {
+ RawInternalFree(addr, cache);
+}
+
+void InternalAllocatorLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ internal_allocator_cache_mu.Lock();
+ internal_allocator()->ForceLock();
+}
+
+void InternalAllocatorUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ internal_allocator()->ForceUnlock();
+ internal_allocator_cache_mu.Unlock();
+}
+
+// LowLevelAllocator
+constexpr uptr kLowLevelAllocatorDefaultAlignment = 8;
+static uptr low_level_alloc_min_alignment = kLowLevelAllocatorDefaultAlignment;
+static LowLevelAllocateCallback low_level_alloc_callback;
+
+void *LowLevelAllocator::Allocate(uptr size) {
+ // Align allocation size.
+ size = RoundUpTo(size, low_level_alloc_min_alignment);
+ if (allocated_end_ - allocated_current_ < (sptr)size) {
+ uptr size_to_allocate = RoundUpTo(size, GetPageSizeCached());
+ allocated_current_ =
+ (char*)MmapOrDie(size_to_allocate, __func__);
+ allocated_end_ = allocated_current_ + size_to_allocate;
+ if (low_level_alloc_callback) {
+ low_level_alloc_callback((uptr)allocated_current_,
+ size_to_allocate);
+ }
+ }
+ CHECK(allocated_end_ - allocated_current_ >= (sptr)size);
+ void *res = allocated_current_;
+ allocated_current_ += size;
+ return res;
+}
+
+void SetLowLevelAllocateMinAlignment(uptr alignment) {
+ CHECK(IsPowerOfTwo(alignment));
+ low_level_alloc_min_alignment = Max(alignment, low_level_alloc_min_alignment);
+}
+
+void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback) {
+ low_level_alloc_callback = callback;
+}
+
+// Allocator's OOM and other errors handling support.
+
+static atomic_uint8_t allocator_out_of_memory = {0};
+static atomic_uint8_t allocator_may_return_null = {0};
+
+bool IsAllocatorOutOfMemory() {
+ return atomic_load_relaxed(&allocator_out_of_memory);
+}
+
+void SetAllocatorOutOfMemory() {
+ atomic_store_relaxed(&allocator_out_of_memory, 1);
+}
+
+bool AllocatorMayReturnNull() {
+ return atomic_load(&allocator_may_return_null, memory_order_relaxed);
+}
+
+void SetAllocatorMayReturnNull(bool may_return_null) {
+ atomic_store(&allocator_may_return_null, may_return_null,
+ memory_order_relaxed);
+}
+
+void PrintHintAllocatorCannotReturnNull() {
+ Report("HINT: if you don't care about these errors you may set "
+ "allocator_may_return_null=1\n");
+}
+
+static atomic_uint8_t rss_limit_exceeded;
+
+bool IsRssLimitExceeded() {
+ return atomic_load(&rss_limit_exceeded, memory_order_relaxed);
+}
+
+void SetRssLimitExceeded(bool limit_exceeded) {
+ atomic_store(&rss_limit_exceeded, limit_exceeded, memory_order_relaxed);
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator.h
new file mode 100644
index 00000000000..76b936ff5ea
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator.h
@@ -0,0 +1,78 @@
+//===-- sanitizer_allocator.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Specialized memory allocator for ThreadSanitizer, MemorySanitizer, etc.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ALLOCATOR_H
+#define SANITIZER_ALLOCATOR_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_flat_map.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_lfstack.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_list.h"
+#include "sanitizer_local_address_space_view.h"
+#include "sanitizer_mutex.h"
+#include "sanitizer_procmaps.h"
+#include "sanitizer_type_traits.h"
+
+namespace __sanitizer {
+
+// Allows the tools to name their allocations appropriately.
+extern const char *PrimaryAllocatorName;
+extern const char *SecondaryAllocatorName;
+
+// Since flags are immutable and allocator behavior can be changed at runtime
+// (unit tests or ASan on Android are some examples), allocator_may_return_null
+// flag value is cached here and can be altered later.
+bool AllocatorMayReturnNull();
+void SetAllocatorMayReturnNull(bool may_return_null);
+
+// Returns true if allocator detected OOM condition. Can be used to avoid memory
+// hungry operations.
+bool IsAllocatorOutOfMemory();
+// Should be called by a particular allocator when OOM is detected.
+void SetAllocatorOutOfMemory();
+
+void PrintHintAllocatorCannotReturnNull();
+
+// Callback type for iterating over chunks.
+typedef void (*ForEachChunkCallback)(uptr chunk, void *arg);
+
+inline u32 Rand(u32 *state) { // ANSI C linear congruential PRNG.
+ return (*state = *state * 1103515245 + 12345) >> 16;
+}
+
+inline u32 RandN(u32 *state, u32 n) { return Rand(state) % n; } // [0, n)
+
+template<typename T>
+inline void RandomShuffle(T *a, u32 n, u32 *rand_state) {
+ if (n <= 1) return;
+ u32 state = *rand_state;
+ for (u32 i = n - 1; i > 0; i--)
+ Swap(a[i], a[RandN(&state, i + 1)]);
+ *rand_state = state;
+}
+
+#include "sanitizer_allocator_size_class_map.h"
+#include "sanitizer_allocator_stats.h"
+#include "sanitizer_allocator_primary64.h"
+#include "sanitizer_allocator_primary32.h"
+#include "sanitizer_allocator_local_cache.h"
+#include "sanitizer_allocator_secondary.h"
+#include "sanitizer_allocator_combined.h"
+
+bool IsRssLimitExceeded();
+void SetRssLimitExceeded(bool limit_exceeded);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_ALLOCATOR_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_checks.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_checks.cpp
new file mode 100644
index 00000000000..9d67f679b56
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_checks.cpp
@@ -0,0 +1,22 @@
+//===-- sanitizer_allocator_checks.cpp --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Various checks shared between ThreadSanitizer, MemorySanitizer, etc. memory
+// allocators.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_errno.h"
+
+namespace __sanitizer {
+
+void SetErrnoToENOMEM() {
+ errno = errno_ENOMEM;
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_checks.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_checks.h
new file mode 100644
index 00000000000..1cc3992c4c9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_checks.h
@@ -0,0 +1,76 @@
+//===-- sanitizer_allocator_checks.h ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Various checks shared between ThreadSanitizer, MemorySanitizer, etc. memory
+// allocators.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ALLOCATOR_CHECKS_H
+#define SANITIZER_ALLOCATOR_CHECKS_H
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_common.h"
+#include "sanitizer_platform.h"
+
+namespace __sanitizer {
+
+// The following is defined in a separate compilation unit to avoid pulling in
+// sanitizer_errno.h in this header, which leads to conflicts when other system
+// headers include errno.h. This is usually the result of an unlikely event,
+// and as such we do not care as much about having it inlined.
+void SetErrnoToENOMEM();
+
+// A common errno setting logic shared by almost all sanitizer allocator APIs.
+inline void *SetErrnoOnNull(void *ptr) {
+ if (UNLIKELY(!ptr))
+ SetErrnoToENOMEM();
+ return ptr;
+}
+
+// In case of the check failure, the caller of the following Check... functions
+// should "return POLICY::OnBadRequest();" where POLICY is the current allocator
+// failure handling policy.
+
+// Checks aligned_alloc() parameters, verifies that the alignment is a power of
+// two and that the size is a multiple of alignment for POSIX implementation,
+// and a bit relaxed requirement for non-POSIX ones, that the size is a multiple
+// of alignment.
+inline bool CheckAlignedAllocAlignmentAndSize(uptr alignment, uptr size) {
+#if SANITIZER_POSIX
+ return alignment != 0 && IsPowerOfTwo(alignment) &&
+ (size & (alignment - 1)) == 0;
+#else
+ return alignment != 0 && size % alignment == 0;
+#endif
+}
+
+// Checks posix_memalign() parameters, verifies that alignment is a power of two
+// and a multiple of sizeof(void *).
+inline bool CheckPosixMemalignAlignment(uptr alignment) {
+ return alignment != 0 && IsPowerOfTwo(alignment) &&
+ (alignment % sizeof(void *)) == 0;
+}
+
+// Returns true if calloc(size, n) call overflows on size*n calculation.
+inline bool CheckForCallocOverflow(uptr size, uptr n) {
+ if (!size)
+ return false;
+ uptr max = (uptr)-1L;
+ return (max / size) < n;
+}
+
+// Returns true if the size passed to pvalloc overflows when rounded to the next
+// multiple of page_size.
+inline bool CheckForPvallocOverflow(uptr size, uptr page_size) {
+ return RoundUpTo(size, page_size) < size;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_ALLOCATOR_CHECKS_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_combined.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_combined.h
new file mode 100644
index 00000000000..b76d36dcf5a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_combined.h
@@ -0,0 +1,199 @@
+//===-- sanitizer_allocator_combined.h --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Part of the Sanitizer Allocator.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_ALLOCATOR_H
+#error This file must be included inside sanitizer_allocator.h
+#endif
+
+// This class implements a complete memory allocator by using two
+// internal allocators:
+// PrimaryAllocator is efficient, but may not allocate some sizes (alignments).
+// When allocating 2^x bytes it should return 2^x aligned chunk.
+// PrimaryAllocator is used via a local AllocatorCache.
+// SecondaryAllocator can allocate anything, but is not efficient.
+template <class PrimaryAllocator,
+ class LargeMmapAllocatorPtrArray = DefaultLargeMmapAllocatorPtrArray>
+class CombinedAllocator {
+ public:
+ using AllocatorCache = typename PrimaryAllocator::AllocatorCache;
+ using SecondaryAllocator =
+ LargeMmapAllocator<typename PrimaryAllocator::MapUnmapCallback,
+ LargeMmapAllocatorPtrArray,
+ typename PrimaryAllocator::AddressSpaceView>;
+
+ void InitLinkerInitialized(s32 release_to_os_interval_ms) {
+ stats_.InitLinkerInitialized();
+ primary_.Init(release_to_os_interval_ms);
+ secondary_.InitLinkerInitialized();
+ }
+
+ void Init(s32 release_to_os_interval_ms, uptr heap_start = 0) {
+ stats_.Init();
+ primary_.Init(release_to_os_interval_ms, heap_start);
+ secondary_.Init();
+ }
+
+ void *Allocate(AllocatorCache *cache, uptr size, uptr alignment) {
+ // Returning 0 on malloc(0) may break a lot of code.
+ if (size == 0)
+ size = 1;
+ if (size + alignment < size) {
+ Report("WARNING: %s: CombinedAllocator allocation overflow: "
+ "0x%zx bytes with 0x%zx alignment requested\n",
+ SanitizerToolName, size, alignment);
+ return nullptr;
+ }
+ uptr original_size = size;
+ // If alignment requirements are to be fulfilled by the frontend allocator
+ // rather than by the primary or secondary, passing an alignment lower than
+ // or equal to 8 will prevent any further rounding up, as well as the later
+ // alignment check.
+ if (alignment > 8)
+ size = RoundUpTo(size, alignment);
+ // The primary allocator should return a 2^x aligned allocation when
+ // requested 2^x bytes, hence using the rounded up 'size' when being
+ // serviced by the primary (this is no longer true when the primary is
+ // using a non-fixed base address). The secondary takes care of the
+ // alignment without such requirement, and allocating 'size' would use
+ // extraneous memory, so we employ 'original_size'.
+ void *res;
+ if (primary_.CanAllocate(size, alignment))
+ res = cache->Allocate(&primary_, primary_.ClassID(size));
+ else
+ res = secondary_.Allocate(&stats_, original_size, alignment);
+ if (alignment > 8)
+ CHECK_EQ(reinterpret_cast<uptr>(res) & (alignment - 1), 0);
+ return res;
+ }
+
+ s32 ReleaseToOSIntervalMs() const {
+ return primary_.ReleaseToOSIntervalMs();
+ }
+
+ void SetReleaseToOSIntervalMs(s32 release_to_os_interval_ms) {
+ primary_.SetReleaseToOSIntervalMs(release_to_os_interval_ms);
+ }
+
+ void ForceReleaseToOS() {
+ primary_.ForceReleaseToOS();
+ }
+
+ void Deallocate(AllocatorCache *cache, void *p) {
+ if (!p) return;
+ if (primary_.PointerIsMine(p))
+ cache->Deallocate(&primary_, primary_.GetSizeClass(p), p);
+ else
+ secondary_.Deallocate(&stats_, p);
+ }
+
+ void *Reallocate(AllocatorCache *cache, void *p, uptr new_size,
+ uptr alignment) {
+ if (!p)
+ return Allocate(cache, new_size, alignment);
+ if (!new_size) {
+ Deallocate(cache, p);
+ return nullptr;
+ }
+ CHECK(PointerIsMine(p));
+ uptr old_size = GetActuallyAllocatedSize(p);
+ uptr memcpy_size = Min(new_size, old_size);
+ void *new_p = Allocate(cache, new_size, alignment);
+ if (new_p)
+ internal_memcpy(new_p, p, memcpy_size);
+ Deallocate(cache, p);
+ return new_p;
+ }
+
+ bool PointerIsMine(const void *p) const {
+ if (primary_.PointerIsMine(p))
+ return true;
+ return secondary_.PointerIsMine(p);
+ }
+
+ bool FromPrimary(const void *p) const { return primary_.PointerIsMine(p); }
+
+ void *GetMetaData(const void *p) {
+ if (primary_.PointerIsMine(p))
+ return primary_.GetMetaData(p);
+ return secondary_.GetMetaData(p);
+ }
+
+ void *GetBlockBegin(const void *p) {
+ if (primary_.PointerIsMine(p))
+ return primary_.GetBlockBegin(p);
+ return secondary_.GetBlockBegin(p);
+ }
+
+ // This function does the same as GetBlockBegin, but is much faster.
+ // Must be called with the allocator locked.
+ void *GetBlockBeginFastLocked(const void *p) {
+ if (primary_.PointerIsMine(p))
+ return primary_.GetBlockBegin(p);
+ return secondary_.GetBlockBeginFastLocked(p);
+ }
+
+ uptr GetActuallyAllocatedSize(void *p) {
+ if (primary_.PointerIsMine(p))
+ return primary_.GetActuallyAllocatedSize(p);
+ return secondary_.GetActuallyAllocatedSize(p);
+ }
+
+ uptr TotalMemoryUsed() {
+ return primary_.TotalMemoryUsed() + secondary_.TotalMemoryUsed();
+ }
+
+ void TestOnlyUnmap() { primary_.TestOnlyUnmap(); }
+
+ void InitCache(AllocatorCache *cache) {
+ cache->Init(&stats_);
+ }
+
+ void DestroyCache(AllocatorCache *cache) {
+ cache->Destroy(&primary_, &stats_);
+ }
+
+ void SwallowCache(AllocatorCache *cache) {
+ cache->Drain(&primary_);
+ }
+
+ void GetStats(AllocatorStatCounters s) const {
+ stats_.Get(s);
+ }
+
+ void PrintStats() {
+ primary_.PrintStats();
+ secondary_.PrintStats();
+ }
+
+ // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
+ // introspection API.
+ void ForceLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ primary_.ForceLock();
+ secondary_.ForceLock();
+ }
+
+ void ForceUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ secondary_.ForceUnlock();
+ primary_.ForceUnlock();
+ }
+
+ // Iterate over all existing chunks.
+ // The allocator must be locked when calling this function.
+ void ForEachChunk(ForEachChunkCallback callback, void *arg) {
+ primary_.ForEachChunk(callback, arg);
+ secondary_.ForEachChunk(callback, arg);
+ }
+
+ private:
+ PrimaryAllocator primary_;
+ SecondaryAllocator secondary_;
+ AllocatorGlobalStats stats_;
+};
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h
new file mode 100644
index 00000000000..92b1373ef84
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_dlsym.h
@@ -0,0 +1,79 @@
+//===-- sanitizer_allocator_dlsym.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Hack: Sanitizer initializer calls dlsym which may need to allocate and call
+// back into uninitialized sanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ALLOCATOR_DLSYM_H
+#define SANITIZER_ALLOCATOR_DLSYM_H
+
+#include "sanitizer_allocator_internal.h"
+
+namespace __sanitizer {
+
+template <typename Details>
+struct DlSymAllocator {
+ static bool Use() {
+ // Fuchsia doesn't use dlsym-based interceptors.
+ return !SANITIZER_FUCHSIA && UNLIKELY(Details::UseImpl());
+ }
+
+ static bool PointerIsMine(const void *ptr) {
+ // Fuchsia doesn't use dlsym-based interceptors.
+ return !SANITIZER_FUCHSIA &&
+ UNLIKELY(internal_allocator()->FromPrimary(ptr));
+ }
+
+ static void *Allocate(uptr size_in_bytes) {
+ void *ptr = InternalAlloc(size_in_bytes, nullptr, kWordSize);
+ CHECK(internal_allocator()->FromPrimary(ptr));
+ Details::OnAllocate(ptr,
+ internal_allocator()->GetActuallyAllocatedSize(ptr));
+ return ptr;
+ }
+
+ static void *Callocate(SIZE_T nmemb, SIZE_T size) {
+ void *ptr = InternalCalloc(nmemb, size);
+ CHECK(internal_allocator()->FromPrimary(ptr));
+ Details::OnAllocate(ptr,
+ internal_allocator()->GetActuallyAllocatedSize(ptr));
+ return ptr;
+ }
+
+ static void Free(void *ptr) {
+ uptr size = internal_allocator()->GetActuallyAllocatedSize(ptr);
+ Details::OnFree(ptr, size);
+ InternalFree(ptr);
+ }
+
+ static void *Realloc(void *ptr, uptr new_size) {
+ if (!ptr)
+ return Allocate(new_size);
+ CHECK(internal_allocator()->FromPrimary(ptr));
+ if (!new_size) {
+ Free(ptr);
+ return nullptr;
+ }
+ uptr size = internal_allocator()->GetActuallyAllocatedSize(ptr);
+ uptr memcpy_size = Min(new_size, size);
+ void *new_ptr = Allocate(new_size);
+ if (new_ptr)
+ internal_memcpy(new_ptr, ptr, memcpy_size);
+ Free(ptr);
+ return new_ptr;
+ }
+
+ static void OnAllocate(const void *ptr, uptr size) {}
+ static void OnFree(const void *ptr, uptr size) {}
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_ALLOCATOR_DLSYM_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_interface.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_interface.h
new file mode 100644
index 00000000000..c1b27563e2f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_interface.h
@@ -0,0 +1,47 @@
+//===-- sanitizer_allocator_interface.h ------------------------- C++ -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Re-declaration of functions from public sanitizer allocator interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ALLOCATOR_INTERFACE_H
+#define SANITIZER_ALLOCATOR_INTERFACE_H
+
+#include "sanitizer_internal_defs.h"
+
+using __sanitizer::uptr;
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+uptr __sanitizer_get_estimated_allocated_size(uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_get_ownership(const void *p);
+SANITIZER_INTERFACE_ATTRIBUTE uptr
+__sanitizer_get_allocated_size(const void *p);
+SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_current_allocated_bytes();
+SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_heap_size();
+SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_free_bytes();
+SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_unmapped_bytes();
+
+SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_install_malloc_and_free_hooks(
+ void (*malloc_hook)(const void *, uptr),
+ void (*free_hook)(const void *));
+
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ void __sanitizer_malloc_hook(void *ptr, uptr size);
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ void __sanitizer_free_hook(void *ptr);
+
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_purge_allocator();
+
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_print_memory_profile(uptr top_percent, uptr max_number_of_contexts);
+} // extern "C"
+
+#endif // SANITIZER_ALLOCATOR_INTERFACE_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_internal.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_internal.h
new file mode 100644
index 00000000000..38994736877
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_internal.h
@@ -0,0 +1,57 @@
+//===-- sanitizer_allocator_internal.h --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This allocator is used inside run-times.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ALLOCATOR_INTERNAL_H
+#define SANITIZER_ALLOCATOR_INTERNAL_H
+
+#include "sanitizer_allocator.h"
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+// FIXME: Check if we may use even more compact size class map for internal
+// purposes.
+typedef CompactSizeClassMap InternalSizeClassMap;
+
+struct AP32 {
+ static const uptr kSpaceBeg = 0;
+ static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
+ static const uptr kMetadataSize = 0;
+ typedef InternalSizeClassMap SizeClassMap;
+ static const uptr kRegionSizeLog = 20;
+ using AddressSpaceView = LocalAddressSpaceView;
+ typedef NoOpMapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+};
+typedef SizeClassAllocator32<AP32> PrimaryInternalAllocator;
+
+typedef CombinedAllocator<PrimaryInternalAllocator,
+ LargeMmapAllocatorPtrArrayStatic>
+ InternalAllocator;
+typedef InternalAllocator::AllocatorCache InternalAllocatorCache;
+
+void *InternalAlloc(uptr size, InternalAllocatorCache *cache = nullptr,
+ uptr alignment = 0);
+void *InternalRealloc(void *p, uptr size,
+ InternalAllocatorCache *cache = nullptr);
+void *InternalReallocArray(void *p, uptr count, uptr size,
+ InternalAllocatorCache *cache = nullptr);
+void *InternalCalloc(uptr count, uptr size,
+ InternalAllocatorCache *cache = nullptr);
+void InternalFree(void *p, InternalAllocatorCache *cache = nullptr);
+void InternalAllocatorLock();
+void InternalAllocatorUnlock();
+InternalAllocator *internal_allocator();
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_ALLOCATOR_INTERNAL_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h
new file mode 100644
index 00000000000..e495c56f037
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h
@@ -0,0 +1,271 @@
+//===-- sanitizer_allocator_local_cache.h -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Part of the Sanitizer Allocator.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_ALLOCATOR_H
+#error This file must be included inside sanitizer_allocator.h
+#endif
+
+// Cache used by SizeClassAllocator64.
+template <class SizeClassAllocator>
+struct SizeClassAllocator64LocalCache {
+ typedef SizeClassAllocator Allocator;
+ typedef MemoryMapper<Allocator> MemoryMapperT;
+
+ void Init(AllocatorGlobalStats *s) {
+ stats_.Init();
+ if (s)
+ s->Register(&stats_);
+ }
+
+ void Destroy(SizeClassAllocator *allocator, AllocatorGlobalStats *s) {
+ Drain(allocator);
+ if (s)
+ s->Unregister(&stats_);
+ }
+
+ void *Allocate(SizeClassAllocator *allocator, uptr class_id) {
+ CHECK_NE(class_id, 0UL);
+ CHECK_LT(class_id, kNumClasses);
+ PerClass *c = &per_class_[class_id];
+ if (UNLIKELY(c->count == 0)) {
+ if (UNLIKELY(!Refill(c, allocator, class_id)))
+ return nullptr;
+ DCHECK_GT(c->count, 0);
+ }
+ CompactPtrT chunk = c->chunks[--c->count];
+ stats_.Add(AllocatorStatAllocated, c->class_size);
+ return reinterpret_cast<void *>(allocator->CompactPtrToPointer(
+ allocator->GetRegionBeginBySizeClass(class_id), chunk));
+ }
+
+ void Deallocate(SizeClassAllocator *allocator, uptr class_id, void *p) {
+ CHECK_NE(class_id, 0UL);
+ CHECK_LT(class_id, kNumClasses);
+ // If the first allocator call on a new thread is a deallocation, then
+ // max_count will be zero, leading to check failure.
+ PerClass *c = &per_class_[class_id];
+ InitCache(c);
+ if (UNLIKELY(c->count == c->max_count))
+ DrainHalfMax(c, allocator, class_id);
+ CompactPtrT chunk = allocator->PointerToCompactPtr(
+ allocator->GetRegionBeginBySizeClass(class_id),
+ reinterpret_cast<uptr>(p));
+ c->chunks[c->count++] = chunk;
+ stats_.Sub(AllocatorStatAllocated, c->class_size);
+ }
+
+ void Drain(SizeClassAllocator *allocator) {
+ MemoryMapperT memory_mapper(*allocator);
+ for (uptr i = 1; i < kNumClasses; i++) {
+ PerClass *c = &per_class_[i];
+ while (c->count > 0) Drain(&memory_mapper, c, allocator, i, c->count);
+ }
+ }
+
+ private:
+ typedef typename Allocator::SizeClassMapT SizeClassMap;
+ static const uptr kNumClasses = SizeClassMap::kNumClasses;
+ typedef typename Allocator::CompactPtrT CompactPtrT;
+
+ struct PerClass {
+ u32 count;
+ u32 max_count;
+ uptr class_size;
+ CompactPtrT chunks[2 * SizeClassMap::kMaxNumCachedHint];
+ };
+ PerClass per_class_[kNumClasses];
+ AllocatorStats stats_;
+
+ void InitCache(PerClass *c) {
+ if (LIKELY(c->max_count))
+ return;
+ for (uptr i = 1; i < kNumClasses; i++) {
+ PerClass *c = &per_class_[i];
+ const uptr size = Allocator::ClassIdToSize(i);
+ c->max_count = 2 * SizeClassMap::MaxCachedHint(size);
+ c->class_size = size;
+ }
+ DCHECK_NE(c->max_count, 0UL);
+ }
+
+ NOINLINE bool Refill(PerClass *c, SizeClassAllocator *allocator,
+ uptr class_id) {
+ InitCache(c);
+ const uptr num_requested_chunks = c->max_count / 2;
+ if (UNLIKELY(!allocator->GetFromAllocator(&stats_, class_id, c->chunks,
+ num_requested_chunks)))
+ return false;
+ c->count = num_requested_chunks;
+ return true;
+ }
+
+ NOINLINE void DrainHalfMax(PerClass *c, SizeClassAllocator *allocator,
+ uptr class_id) {
+ MemoryMapperT memory_mapper(*allocator);
+ Drain(&memory_mapper, c, allocator, class_id, c->max_count / 2);
+ }
+
+ void Drain(MemoryMapperT *memory_mapper, PerClass *c,
+ SizeClassAllocator *allocator, uptr class_id, uptr count) {
+ CHECK_GE(c->count, count);
+ const uptr first_idx_to_drain = c->count - count;
+ c->count -= count;
+ allocator->ReturnToAllocator(memory_mapper, &stats_, class_id,
+ &c->chunks[first_idx_to_drain], count);
+ }
+};
+
+// Cache used by SizeClassAllocator32.
+template <class SizeClassAllocator>
+struct SizeClassAllocator32LocalCache {
+ typedef SizeClassAllocator Allocator;
+ typedef typename Allocator::TransferBatch TransferBatch;
+
+ void Init(AllocatorGlobalStats *s) {
+ stats_.Init();
+ if (s)
+ s->Register(&stats_);
+ }
+
+ // Returns a TransferBatch suitable for class_id.
+ TransferBatch *CreateBatch(uptr class_id, SizeClassAllocator *allocator,
+ TransferBatch *b) {
+ if (uptr batch_class_id = per_class_[class_id].batch_class_id)
+ return (TransferBatch*)Allocate(allocator, batch_class_id);
+ return b;
+ }
+
+ // Destroys TransferBatch b.
+ void DestroyBatch(uptr class_id, SizeClassAllocator *allocator,
+ TransferBatch *b) {
+ if (uptr batch_class_id = per_class_[class_id].batch_class_id)
+ Deallocate(allocator, batch_class_id, b);
+ }
+
+ void Destroy(SizeClassAllocator *allocator, AllocatorGlobalStats *s) {
+ Drain(allocator);
+ if (s)
+ s->Unregister(&stats_);
+ }
+
+ void *Allocate(SizeClassAllocator *allocator, uptr class_id) {
+ CHECK_NE(class_id, 0UL);
+ CHECK_LT(class_id, kNumClasses);
+ PerClass *c = &per_class_[class_id];
+ if (UNLIKELY(c->count == 0)) {
+ if (UNLIKELY(!Refill(c, allocator, class_id)))
+ return nullptr;
+ DCHECK_GT(c->count, 0);
+ }
+ void *res = c->batch[--c->count];
+ PREFETCH(c->batch[c->count - 1]);
+ stats_.Add(AllocatorStatAllocated, c->class_size);
+ return res;
+ }
+
+ void Deallocate(SizeClassAllocator *allocator, uptr class_id, void *p) {
+ CHECK_NE(class_id, 0UL);
+ CHECK_LT(class_id, kNumClasses);
+ // If the first allocator call on a new thread is a deallocation, then
+ // max_count will be zero, leading to check failure.
+ PerClass *c = &per_class_[class_id];
+ InitCache(c);
+ if (UNLIKELY(c->count == c->max_count))
+ Drain(c, allocator, class_id);
+ c->batch[c->count++] = p;
+ stats_.Sub(AllocatorStatAllocated, c->class_size);
+ }
+
+ void Drain(SizeClassAllocator *allocator) {
+ for (uptr i = 1; i < kNumClasses; i++) {
+ PerClass *c = &per_class_[i];
+ while (c->count > 0)
+ Drain(c, allocator, i);
+ }
+ }
+
+ private:
+ typedef typename Allocator::SizeClassMapT SizeClassMap;
+ static const uptr kBatchClassID = SizeClassMap::kBatchClassID;
+ static const uptr kNumClasses = SizeClassMap::kNumClasses;
+ // If kUseSeparateSizeClassForBatch is true, all TransferBatch objects are
+ // allocated from kBatchClassID size class (except for those that are needed
+ // for kBatchClassID itself). The goal is to have TransferBatches in a totally
+ // different region of RAM to improve security.
+ static const bool kUseSeparateSizeClassForBatch =
+ Allocator::kUseSeparateSizeClassForBatch;
+
+ struct PerClass {
+ uptr count;
+ uptr max_count;
+ uptr class_size;
+ uptr batch_class_id;
+ void *batch[2 * TransferBatch::kMaxNumCached];
+ };
+ PerClass per_class_[kNumClasses];
+ AllocatorStats stats_;
+
+ void InitCache(PerClass *c) {
+ if (LIKELY(c->max_count))
+ return;
+ const uptr batch_class_id = SizeClassMap::ClassID(sizeof(TransferBatch));
+ for (uptr i = 1; i < kNumClasses; i++) {
+ PerClass *c = &per_class_[i];
+ const uptr size = Allocator::ClassIdToSize(i);
+ const uptr max_cached = TransferBatch::MaxCached(size);
+ c->max_count = 2 * max_cached;
+ c->class_size = size;
+ // Precompute the class id to use to store batches for the current class
+ // id. 0 means the class size is large enough to store a batch within one
+ // of the chunks. If using a separate size class, it will always be
+ // kBatchClassID, except for kBatchClassID itself.
+ if (kUseSeparateSizeClassForBatch) {
+ c->batch_class_id = (i == kBatchClassID) ? 0 : kBatchClassID;
+ } else {
+ c->batch_class_id = (size <
+ TransferBatch::AllocationSizeRequiredForNElements(max_cached)) ?
+ batch_class_id : 0;
+ }
+ }
+ DCHECK_NE(c->max_count, 0UL);
+ }
+
+ NOINLINE bool Refill(PerClass *c, SizeClassAllocator *allocator,
+ uptr class_id) {
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+ return false;
+ CHECK_GT(b->Count(), 0);
+ b->CopyToArray(c->batch);
+ c->count = b->Count();
+ DestroyBatch(class_id, allocator, b);
+ return true;
+ }
+
+ NOINLINE void Drain(PerClass *c, SizeClassAllocator *allocator,
+ uptr class_id) {
+ const uptr count = Min(c->max_count / 2, c->count);
+ const uptr first_idx_to_drain = c->count - count;
+ TransferBatch *b = CreateBatch(
+ class_id, allocator, (TransferBatch *)c->batch[first_idx_to_drain]);
+ // Failure to allocate a batch while releasing memory is non recoverable.
+ // TODO(alekseys): Figure out how to do it without allocating a new batch.
+ if (UNLIKELY(!b)) {
+ Report("FATAL: Internal error: %s's allocator failed to allocate a "
+ "transfer batch.\n", SanitizerToolName);
+ Die();
+ }
+ b->SetFromArray(&c->batch[first_idx_to_drain], count);
+ c->count -= count;
+ allocator->DeallocateBatch(&stats_, class_id, b);
+ }
+};
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h
new file mode 100644
index 00000000000..f2471efced6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h
@@ -0,0 +1,381 @@
+//===-- sanitizer_allocator_primary32.h -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Part of the Sanitizer Allocator.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_ALLOCATOR_H
+#error This file must be included inside sanitizer_allocator.h
+#endif
+
+template<class SizeClassAllocator> struct SizeClassAllocator32LocalCache;
+
+// SizeClassAllocator32 -- allocator for 32-bit address space.
+// This allocator can theoretically be used on 64-bit arch, but there it is less
+// efficient than SizeClassAllocator64.
+//
+// [kSpaceBeg, kSpaceBeg + kSpaceSize) is the range of addresses which can
+// be returned by MmapOrDie().
+//
+// Region:
+// a result of a single call to MmapAlignedOrDieOnFatalError(kRegionSize,
+// kRegionSize).
+// Since the regions are aligned by kRegionSize, there are exactly
+// kNumPossibleRegions possible regions in the address space and so we keep
+// a ByteMap possible_regions to store the size classes of each Region.
+// 0 size class means the region is not used by the allocator.
+//
+// One Region is used to allocate chunks of a single size class.
+// A Region looks like this:
+// UserChunk1 .. UserChunkN <gap> MetaChunkN .. MetaChunk1
+//
+// In order to avoid false sharing the objects of this class should be
+// chache-line aligned.
+
+struct SizeClassAllocator32FlagMasks { // Bit masks.
+ enum {
+ kRandomShuffleChunks = 1,
+ kUseSeparateSizeClassForBatch = 2,
+ };
+};
+
+template <class Params>
+class SizeClassAllocator32 {
+ private:
+ static const u64 kTwoLevelByteMapSize1 =
+ (Params::kSpaceSize >> Params::kRegionSizeLog) >> 12;
+ static const u64 kMinFirstMapSizeTwoLevelByteMap = 4;
+
+ public:
+ using AddressSpaceView = typename Params::AddressSpaceView;
+ static const uptr kSpaceBeg = Params::kSpaceBeg;
+ static const u64 kSpaceSize = Params::kSpaceSize;
+ static const uptr kMetadataSize = Params::kMetadataSize;
+ typedef typename Params::SizeClassMap SizeClassMap;
+ static const uptr kRegionSizeLog = Params::kRegionSizeLog;
+ typedef typename Params::MapUnmapCallback MapUnmapCallback;
+ using ByteMap = typename conditional<
+ (kTwoLevelByteMapSize1 < kMinFirstMapSizeTwoLevelByteMap),
+ FlatByteMap<(Params::kSpaceSize >> Params::kRegionSizeLog),
+ AddressSpaceView>,
+ TwoLevelByteMap<kTwoLevelByteMapSize1, 1 << 12, AddressSpaceView>>::type;
+
+ COMPILER_CHECK(!SANITIZER_SIGN_EXTENDED_ADDRESSES ||
+ (kSpaceSize & (kSpaceSize - 1)) == 0);
+
+ static const bool kRandomShuffleChunks = Params::kFlags &
+ SizeClassAllocator32FlagMasks::kRandomShuffleChunks;
+ static const bool kUseSeparateSizeClassForBatch = Params::kFlags &
+ SizeClassAllocator32FlagMasks::kUseSeparateSizeClassForBatch;
+
+ struct TransferBatch {
+ static const uptr kMaxNumCached = SizeClassMap::kMaxNumCachedHint - 2;
+ void SetFromArray(void *batch[], uptr count) {
+ DCHECK_LE(count, kMaxNumCached);
+ count_ = count;
+ for (uptr i = 0; i < count; i++)
+ batch_[i] = batch[i];
+ }
+ uptr Count() const { return count_; }
+ void Clear() { count_ = 0; }
+ void Add(void *ptr) {
+ batch_[count_++] = ptr;
+ DCHECK_LE(count_, kMaxNumCached);
+ }
+ void CopyToArray(void *to_batch[]) const {
+ for (uptr i = 0, n = Count(); i < n; i++)
+ to_batch[i] = batch_[i];
+ }
+
+ // How much memory do we need for a batch containing n elements.
+ static uptr AllocationSizeRequiredForNElements(uptr n) {
+ return sizeof(uptr) * 2 + sizeof(void *) * n;
+ }
+ static uptr MaxCached(uptr size) {
+ return Min(kMaxNumCached, SizeClassMap::MaxCachedHint(size));
+ }
+
+ TransferBatch *next;
+
+ private:
+ uptr count_;
+ void *batch_[kMaxNumCached];
+ };
+
+ static const uptr kBatchSize = sizeof(TransferBatch);
+ COMPILER_CHECK((kBatchSize & (kBatchSize - 1)) == 0);
+ COMPILER_CHECK(kBatchSize == SizeClassMap::kMaxNumCachedHint * sizeof(uptr));
+
+ static uptr ClassIdToSize(uptr class_id) {
+ return (class_id == SizeClassMap::kBatchClassID) ?
+ kBatchSize : SizeClassMap::Size(class_id);
+ }
+
+ typedef SizeClassAllocator32<Params> ThisT;
+ typedef SizeClassAllocator32LocalCache<ThisT> AllocatorCache;
+
+ void Init(s32 release_to_os_interval_ms, uptr heap_start = 0) {
+ CHECK(!heap_start);
+ possible_regions.Init();
+ internal_memset(size_class_info_array, 0, sizeof(size_class_info_array));
+ }
+
+ s32 ReleaseToOSIntervalMs() const {
+ return kReleaseToOSIntervalNever;
+ }
+
+ void SetReleaseToOSIntervalMs(s32 release_to_os_interval_ms) {
+ // This is empty here. Currently only implemented in 64-bit allocator.
+ }
+
+ void ForceReleaseToOS() {
+ // Currently implemented in 64-bit allocator only.
+ }
+
+ void *MapWithCallback(uptr size) {
+ void *res = MmapOrDie(size, PrimaryAllocatorName);
+ MapUnmapCallback().OnMap((uptr)res, size);
+ return res;
+ }
+
+ void UnmapWithCallback(uptr beg, uptr size) {
+ MapUnmapCallback().OnUnmap(beg, size);
+ UnmapOrDie(reinterpret_cast<void *>(beg), size);
+ }
+
+ static bool CanAllocate(uptr size, uptr alignment) {
+ return size <= SizeClassMap::kMaxSize &&
+ alignment <= SizeClassMap::kMaxSize;
+ }
+
+ void *GetMetaData(const void *p) {
+ CHECK(kMetadataSize);
+ CHECK(PointerIsMine(p));
+ uptr mem = reinterpret_cast<uptr>(p);
+ uptr beg = ComputeRegionBeg(mem);
+ uptr size = ClassIdToSize(GetSizeClass(p));
+ u32 offset = mem - beg;
+ uptr n = offset / (u32)size; // 32-bit division
+ uptr meta = (beg + kRegionSize) - (n + 1) * kMetadataSize;
+ return reinterpret_cast<void*>(meta);
+ }
+
+ NOINLINE TransferBatch *AllocateBatch(AllocatorStats *stat, AllocatorCache *c,
+ uptr class_id) {
+ DCHECK_LT(class_id, kNumClasses);
+ SizeClassInfo *sci = GetSizeClassInfo(class_id);
+ SpinMutexLock l(&sci->mutex);
+ if (sci->free_list.empty()) {
+ if (UNLIKELY(!PopulateFreeList(stat, c, sci, class_id)))
+ return nullptr;
+ DCHECK(!sci->free_list.empty());
+ }
+ TransferBatch *b = sci->free_list.front();
+ sci->free_list.pop_front();
+ return b;
+ }
+
+ NOINLINE void DeallocateBatch(AllocatorStats *stat, uptr class_id,
+ TransferBatch *b) {
+ DCHECK_LT(class_id, kNumClasses);
+ CHECK_GT(b->Count(), 0);
+ SizeClassInfo *sci = GetSizeClassInfo(class_id);
+ SpinMutexLock l(&sci->mutex);
+ sci->free_list.push_front(b);
+ }
+
+ bool PointerIsMine(const void *p) const {
+ uptr mem = reinterpret_cast<uptr>(p);
+ if (SANITIZER_SIGN_EXTENDED_ADDRESSES)
+ mem &= (kSpaceSize - 1);
+ if (mem < kSpaceBeg || mem >= kSpaceBeg + kSpaceSize)
+ return false;
+ return GetSizeClass(p) != 0;
+ }
+
+ uptr GetSizeClass(const void *p) const {
+ uptr id = ComputeRegionId(reinterpret_cast<uptr>(p));
+ return possible_regions.contains(id) ? possible_regions[id] : 0;
+ }
+
+ void *GetBlockBegin(const void *p) {
+ CHECK(PointerIsMine(p));
+ uptr mem = reinterpret_cast<uptr>(p);
+ uptr beg = ComputeRegionBeg(mem);
+ uptr size = ClassIdToSize(GetSizeClass(p));
+ u32 offset = mem - beg;
+ u32 n = offset / (u32)size; // 32-bit division
+ uptr res = beg + (n * (u32)size);
+ return reinterpret_cast<void*>(res);
+ }
+
+ uptr GetActuallyAllocatedSize(void *p) {
+ CHECK(PointerIsMine(p));
+ return ClassIdToSize(GetSizeClass(p));
+ }
+
+ static uptr ClassID(uptr size) { return SizeClassMap::ClassID(size); }
+
+ uptr TotalMemoryUsed() {
+ // No need to lock here.
+ uptr res = 0;
+ for (uptr i = 0; i < kNumPossibleRegions; i++)
+ if (possible_regions[i])
+ res += kRegionSize;
+ return res;
+ }
+
+ void TestOnlyUnmap() {
+ for (uptr i = 0; i < kNumPossibleRegions; i++)
+ if (possible_regions[i])
+ UnmapWithCallback((i * kRegionSize), kRegionSize);
+ }
+
+ // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
+ // introspection API.
+ void ForceLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ for (uptr i = 0; i < kNumClasses; i++) {
+ GetSizeClassInfo(i)->mutex.Lock();
+ }
+ }
+
+ void ForceUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ for (int i = kNumClasses - 1; i >= 0; i--) {
+ GetSizeClassInfo(i)->mutex.Unlock();
+ }
+ }
+
+ // Iterate over all existing chunks.
+ // The allocator must be locked when calling this function.
+ void ForEachChunk(ForEachChunkCallback callback, void *arg) const {
+ for (uptr region = 0; region < kNumPossibleRegions; region++)
+ if (possible_regions.contains(region) && possible_regions[region]) {
+ uptr chunk_size = ClassIdToSize(possible_regions[region]);
+ uptr max_chunks_in_region = kRegionSize / (chunk_size + kMetadataSize);
+ uptr region_beg = region * kRegionSize;
+ for (uptr chunk = region_beg;
+ chunk < region_beg + max_chunks_in_region * chunk_size;
+ chunk += chunk_size) {
+ // Too slow: CHECK_EQ((void *)chunk, GetBlockBegin((void *)chunk));
+ callback(chunk, arg);
+ }
+ }
+ }
+
+ void PrintStats() {}
+
+ static uptr AdditionalSize() { return 0; }
+
+ typedef SizeClassMap SizeClassMapT;
+ static const uptr kNumClasses = SizeClassMap::kNumClasses;
+
+ private:
+ static const uptr kRegionSize = 1 << kRegionSizeLog;
+ static const uptr kNumPossibleRegions = kSpaceSize / kRegionSize;
+
+ struct ALIGNED(SANITIZER_CACHE_LINE_SIZE) SizeClassInfo {
+ StaticSpinMutex mutex;
+ IntrusiveList<TransferBatch> free_list;
+ u32 rand_state;
+ };
+ COMPILER_CHECK(sizeof(SizeClassInfo) % kCacheLineSize == 0);
+
+ uptr ComputeRegionId(uptr mem) const {
+ if (SANITIZER_SIGN_EXTENDED_ADDRESSES)
+ mem &= (kSpaceSize - 1);
+ const uptr res = mem >> kRegionSizeLog;
+ CHECK_LT(res, kNumPossibleRegions);
+ return res;
+ }
+
+ uptr ComputeRegionBeg(uptr mem) const { return mem & ~(kRegionSize - 1); }
+
+ uptr AllocateRegion(AllocatorStats *stat, uptr class_id) {
+ DCHECK_LT(class_id, kNumClasses);
+ const uptr res = reinterpret_cast<uptr>(MmapAlignedOrDieOnFatalError(
+ kRegionSize, kRegionSize, PrimaryAllocatorName));
+ if (UNLIKELY(!res))
+ return 0;
+ MapUnmapCallback().OnMap(res, kRegionSize);
+ stat->Add(AllocatorStatMapped, kRegionSize);
+ CHECK(IsAligned(res, kRegionSize));
+ possible_regions[ComputeRegionId(res)] = class_id;
+ return res;
+ }
+
+ SizeClassInfo *GetSizeClassInfo(uptr class_id) {
+ DCHECK_LT(class_id, kNumClasses);
+ return &size_class_info_array[class_id];
+ }
+
+ bool PopulateBatches(AllocatorCache *c, SizeClassInfo *sci, uptr class_id,
+ TransferBatch **current_batch, uptr max_count,
+ uptr *pointers_array, uptr count) {
+ // If using a separate class for batches, we do not need to shuffle it.
+ if (kRandomShuffleChunks && (!kUseSeparateSizeClassForBatch ||
+ class_id != SizeClassMap::kBatchClassID))
+ RandomShuffle(pointers_array, count, &sci->rand_state);
+ TransferBatch *b = *current_batch;
+ for (uptr i = 0; i < count; i++) {
+ if (!b) {
+ b = c->CreateBatch(class_id, this, (TransferBatch*)pointers_array[i]);
+ if (UNLIKELY(!b))
+ return false;
+ b->Clear();
+ }
+ b->Add((void*)pointers_array[i]);
+ if (b->Count() == max_count) {
+ sci->free_list.push_back(b);
+ b = nullptr;
+ }
+ }
+ *current_batch = b;
+ return true;
+ }
+
+ bool PopulateFreeList(AllocatorStats *stat, AllocatorCache *c,
+ SizeClassInfo *sci, uptr class_id) {
+ const uptr region = AllocateRegion(stat, class_id);
+ if (UNLIKELY(!region))
+ return false;
+ if (kRandomShuffleChunks)
+ if (UNLIKELY(sci->rand_state == 0))
+ // The random state is initialized from ASLR (PIE) and time.
+ sci->rand_state = reinterpret_cast<uptr>(sci) ^ NanoTime();
+ const uptr size = ClassIdToSize(class_id);
+ const uptr n_chunks = kRegionSize / (size + kMetadataSize);
+ const uptr max_count = TransferBatch::MaxCached(size);
+ DCHECK_GT(max_count, 0);
+ TransferBatch *b = nullptr;
+ constexpr uptr kShuffleArraySize = 48;
+ uptr shuffle_array[kShuffleArraySize];
+ uptr count = 0;
+ for (uptr i = region; i < region + n_chunks * size; i += size) {
+ shuffle_array[count++] = i;
+ if (count == kShuffleArraySize) {
+ if (UNLIKELY(!PopulateBatches(c, sci, class_id, &b, max_count,
+ shuffle_array, count)))
+ return false;
+ count = 0;
+ }
+ }
+ if (count) {
+ if (UNLIKELY(!PopulateBatches(c, sci, class_id, &b, max_count,
+ shuffle_array, count)))
+ return false;
+ }
+ if (b) {
+ CHECK_GT(b->Count(), 0);
+ sci->free_list.push_back(b);
+ }
+ return true;
+ }
+
+ ByteMap possible_regions;
+ SizeClassInfo size_class_info_array[kNumClasses];
+};
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
new file mode 100644
index 00000000000..66ba71d325d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
@@ -0,0 +1,898 @@
+//===-- sanitizer_allocator_primary64.h -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Part of the Sanitizer Allocator.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_ALLOCATOR_H
+#error This file must be included inside sanitizer_allocator.h
+#endif
+
+template<class SizeClassAllocator> struct SizeClassAllocator64LocalCache;
+
+// SizeClassAllocator64 -- allocator for 64-bit address space.
+// The template parameter Params is a class containing the actual parameters.
+//
+// Space: a portion of address space of kSpaceSize bytes starting at SpaceBeg.
+// If kSpaceBeg is ~0 then SpaceBeg is chosen dynamically by mmap.
+// Otherwise SpaceBeg=kSpaceBeg (fixed address).
+// kSpaceSize is a power of two.
+// At the beginning the entire space is mprotect-ed, then small parts of it
+// are mapped on demand.
+//
+// Region: a part of Space dedicated to a single size class.
+// There are kNumClasses Regions of equal size.
+//
+// UserChunk: a piece of memory returned to user.
+// MetaChunk: kMetadataSize bytes of metadata associated with a UserChunk.
+
+// FreeArray is an array free-d chunks (stored as 4-byte offsets)
+//
+// A Region looks like this:
+// UserChunk1 ... UserChunkN <gap> MetaChunkN ... MetaChunk1 FreeArray
+
+struct SizeClassAllocator64FlagMasks { // Bit masks.
+ enum {
+ kRandomShuffleChunks = 1,
+ };
+};
+
+template <typename Allocator>
+class MemoryMapper {
+ public:
+ typedef typename Allocator::CompactPtrT CompactPtrT;
+
+ explicit MemoryMapper(const Allocator &allocator) : allocator_(allocator) {}
+
+ bool GetAndResetStats(uptr &ranges, uptr &bytes) {
+ ranges = released_ranges_count_;
+ released_ranges_count_ = 0;
+ bytes = released_bytes_;
+ released_bytes_ = 0;
+ return ranges != 0;
+ }
+
+ u64 *MapPackedCounterArrayBuffer(uptr count) {
+ buffer_.clear();
+ buffer_.resize(count);
+ return buffer_.data();
+ }
+
+ // Releases [from, to) range of pages back to OS.
+ void ReleasePageRangeToOS(uptr class_id, CompactPtrT from, CompactPtrT to) {
+ const uptr region_base = allocator_.GetRegionBeginBySizeClass(class_id);
+ const uptr from_page = allocator_.CompactPtrToPointer(region_base, from);
+ const uptr to_page = allocator_.CompactPtrToPointer(region_base, to);
+ ReleaseMemoryPagesToOS(from_page, to_page);
+ released_ranges_count_++;
+ released_bytes_ += to_page - from_page;
+ }
+
+ private:
+ const Allocator &allocator_;
+ uptr released_ranges_count_ = 0;
+ uptr released_bytes_ = 0;
+ InternalMmapVector<u64> buffer_;
+};
+
+template <class Params>
+class SizeClassAllocator64 {
+ public:
+ using AddressSpaceView = typename Params::AddressSpaceView;
+ static const uptr kSpaceBeg = Params::kSpaceBeg;
+ static const uptr kSpaceSize = Params::kSpaceSize;
+ static const uptr kMetadataSize = Params::kMetadataSize;
+ typedef typename Params::SizeClassMap SizeClassMap;
+ typedef typename Params::MapUnmapCallback MapUnmapCallback;
+
+ static const bool kRandomShuffleChunks =
+ Params::kFlags & SizeClassAllocator64FlagMasks::kRandomShuffleChunks;
+
+ typedef SizeClassAllocator64<Params> ThisT;
+ typedef SizeClassAllocator64LocalCache<ThisT> AllocatorCache;
+ typedef MemoryMapper<ThisT> MemoryMapperT;
+
+ // When we know the size class (the region base) we can represent a pointer
+ // as a 4-byte integer (offset from the region start shifted right by 4).
+ typedef u32 CompactPtrT;
+ static const uptr kCompactPtrScale = 4;
+ CompactPtrT PointerToCompactPtr(uptr base, uptr ptr) const {
+ return static_cast<CompactPtrT>((ptr - base) >> kCompactPtrScale);
+ }
+ uptr CompactPtrToPointer(uptr base, CompactPtrT ptr32) const {
+ return base + (static_cast<uptr>(ptr32) << kCompactPtrScale);
+ }
+
+ // If heap_start is nonzero, assumes kSpaceSize bytes are already mapped R/W
+ // at heap_start and places the heap there. This mode requires kSpaceBeg ==
+ // ~(uptr)0.
+ void Init(s32 release_to_os_interval_ms, uptr heap_start = 0) {
+ uptr TotalSpaceSize = kSpaceSize + AdditionalSize();
+ PremappedHeap = heap_start != 0;
+ if (PremappedHeap) {
+ CHECK(!kUsingConstantSpaceBeg);
+ NonConstSpaceBeg = heap_start;
+ uptr RegionInfoSize = AdditionalSize();
+ RegionInfoSpace =
+ address_range.Init(RegionInfoSize, PrimaryAllocatorName);
+ CHECK_NE(RegionInfoSpace, ~(uptr)0);
+ CHECK_EQ(RegionInfoSpace,
+ address_range.MapOrDie(RegionInfoSpace, RegionInfoSize,
+ "SizeClassAllocator: region info"));
+ MapUnmapCallback().OnMap(RegionInfoSpace, RegionInfoSize);
+ } else {
+ if (kUsingConstantSpaceBeg) {
+ CHECK(IsAligned(kSpaceBeg, SizeClassMap::kMaxSize));
+ CHECK_EQ(kSpaceBeg,
+ address_range.Init(TotalSpaceSize, PrimaryAllocatorName,
+ kSpaceBeg));
+ } else {
+ // Combined allocator expects that an 2^N allocation is always aligned
+ // to 2^N. For this to work, the start of the space needs to be aligned
+ // as high as the largest size class (which also needs to be a power of
+ // 2).
+ NonConstSpaceBeg = address_range.InitAligned(
+ TotalSpaceSize, SizeClassMap::kMaxSize, PrimaryAllocatorName);
+ CHECK_NE(NonConstSpaceBeg, ~(uptr)0);
+ }
+ RegionInfoSpace = SpaceEnd();
+ MapWithCallbackOrDie(RegionInfoSpace, AdditionalSize(),
+ "SizeClassAllocator: region info");
+ }
+ SetReleaseToOSIntervalMs(release_to_os_interval_ms);
+ // Check that the RegionInfo array is aligned on the CacheLine size.
+ DCHECK_EQ(RegionInfoSpace % kCacheLineSize, 0);
+ }
+
+ s32 ReleaseToOSIntervalMs() const {
+ return atomic_load(&release_to_os_interval_ms_, memory_order_relaxed);
+ }
+
+ void SetReleaseToOSIntervalMs(s32 release_to_os_interval_ms) {
+ atomic_store(&release_to_os_interval_ms_, release_to_os_interval_ms,
+ memory_order_relaxed);
+ }
+
+ void ForceReleaseToOS() {
+ MemoryMapperT memory_mapper(*this);
+ for (uptr class_id = 1; class_id < kNumClasses; class_id++) {
+ Lock l(&GetRegionInfo(class_id)->mutex);
+ MaybeReleaseToOS(&memory_mapper, class_id, true /*force*/);
+ }
+ }
+
+ static bool CanAllocate(uptr size, uptr alignment) {
+ return size <= SizeClassMap::kMaxSize &&
+ alignment <= SizeClassMap::kMaxSize;
+ }
+
+ NOINLINE void ReturnToAllocator(MemoryMapperT *memory_mapper,
+ AllocatorStats *stat, uptr class_id,
+ const CompactPtrT *chunks, uptr n_chunks) {
+ RegionInfo *region = GetRegionInfo(class_id);
+ uptr region_beg = GetRegionBeginBySizeClass(class_id);
+ CompactPtrT *free_array = GetFreeArray(region_beg);
+
+ Lock l(&region->mutex);
+ uptr old_num_chunks = region->num_freed_chunks;
+ uptr new_num_freed_chunks = old_num_chunks + n_chunks;
+ // Failure to allocate free array space while releasing memory is non
+ // recoverable.
+ if (UNLIKELY(!EnsureFreeArraySpace(region, region_beg,
+ new_num_freed_chunks))) {
+ Report("FATAL: Internal error: %s's allocator exhausted the free list "
+ "space for size class %zd (%zd bytes).\n", SanitizerToolName,
+ class_id, ClassIdToSize(class_id));
+ Die();
+ }
+ for (uptr i = 0; i < n_chunks; i++)
+ free_array[old_num_chunks + i] = chunks[i];
+ region->num_freed_chunks = new_num_freed_chunks;
+ region->stats.n_freed += n_chunks;
+
+ MaybeReleaseToOS(memory_mapper, class_id, false /*force*/);
+ }
+
+ NOINLINE bool GetFromAllocator(AllocatorStats *stat, uptr class_id,
+ CompactPtrT *chunks, uptr n_chunks) {
+ RegionInfo *region = GetRegionInfo(class_id);
+ uptr region_beg = GetRegionBeginBySizeClass(class_id);
+ CompactPtrT *free_array = GetFreeArray(region_beg);
+
+ Lock l(&region->mutex);
+#if SANITIZER_WINDOWS
+ /* On Windows unmapping of memory during __sanitizer_purge_allocator is
+ explicit and immediate, so unmapped regions must be explicitly mapped back
+ in when they are accessed again. */
+ if (region->rtoi.last_released_bytes > 0) {
+ MmapFixedOrDie(region_beg, region->mapped_user,
+ "SizeClassAllocator: region data");
+ region->rtoi.n_freed_at_last_release = 0;
+ region->rtoi.last_released_bytes = 0;
+ }
+#endif
+ if (UNLIKELY(region->num_freed_chunks < n_chunks)) {
+ if (UNLIKELY(!PopulateFreeArray(stat, class_id, region,
+ n_chunks - region->num_freed_chunks)))
+ return false;
+ CHECK_GE(region->num_freed_chunks, n_chunks);
+ }
+ region->num_freed_chunks -= n_chunks;
+ uptr base_idx = region->num_freed_chunks;
+ for (uptr i = 0; i < n_chunks; i++)
+ chunks[i] = free_array[base_idx + i];
+ region->stats.n_allocated += n_chunks;
+ return true;
+ }
+
+ bool PointerIsMine(const void *p) const {
+ uptr P = reinterpret_cast<uptr>(p);
+ if (kUsingConstantSpaceBeg && (kSpaceBeg % kSpaceSize) == 0)
+ return P / kSpaceSize == kSpaceBeg / kSpaceSize;
+ return P >= SpaceBeg() && P < SpaceEnd();
+ }
+
+ uptr GetRegionBegin(const void *p) {
+ if (kUsingConstantSpaceBeg)
+ return reinterpret_cast<uptr>(p) & ~(kRegionSize - 1);
+ uptr space_beg = SpaceBeg();
+ return ((reinterpret_cast<uptr>(p) - space_beg) & ~(kRegionSize - 1)) +
+ space_beg;
+ }
+
+ uptr GetRegionBeginBySizeClass(uptr class_id) const {
+ return SpaceBeg() + kRegionSize * class_id;
+ }
+
+ uptr GetSizeClass(const void *p) {
+ if (kUsingConstantSpaceBeg && (kSpaceBeg % kSpaceSize) == 0)
+ return ((reinterpret_cast<uptr>(p)) / kRegionSize) % kNumClassesRounded;
+ return ((reinterpret_cast<uptr>(p) - SpaceBeg()) / kRegionSize) %
+ kNumClassesRounded;
+ }
+
+ void *GetBlockBegin(const void *p) {
+ uptr class_id = GetSizeClass(p);
+ if (class_id >= kNumClasses) return nullptr;
+ uptr size = ClassIdToSize(class_id);
+ if (!size) return nullptr;
+ uptr chunk_idx = GetChunkIdx((uptr)p, size);
+ uptr reg_beg = GetRegionBegin(p);
+ uptr beg = chunk_idx * size;
+ uptr next_beg = beg + size;
+ const RegionInfo *region = AddressSpaceView::Load(GetRegionInfo(class_id));
+ if (region->mapped_user >= next_beg)
+ return reinterpret_cast<void*>(reg_beg + beg);
+ return nullptr;
+ }
+
+ uptr GetActuallyAllocatedSize(void *p) {
+ CHECK(PointerIsMine(p));
+ return ClassIdToSize(GetSizeClass(p));
+ }
+
+ static uptr ClassID(uptr size) { return SizeClassMap::ClassID(size); }
+
+ void *GetMetaData(const void *p) {
+ CHECK(kMetadataSize);
+ uptr class_id = GetSizeClass(p);
+ uptr size = ClassIdToSize(class_id);
+ if (!size)
+ return nullptr;
+ uptr chunk_idx = GetChunkIdx(reinterpret_cast<uptr>(p), size);
+ uptr region_beg = GetRegionBeginBySizeClass(class_id);
+ return reinterpret_cast<void *>(GetMetadataEnd(region_beg) -
+ (1 + chunk_idx) * kMetadataSize);
+ }
+
+ uptr TotalMemoryUsed() {
+ uptr res = 0;
+ for (uptr i = 0; i < kNumClasses; i++)
+ res += GetRegionInfo(i)->allocated_user;
+ return res;
+ }
+
+ // Test-only.
+ void TestOnlyUnmap() {
+ UnmapWithCallbackOrDie((uptr)address_range.base(), address_range.size());
+ }
+
+ static void FillMemoryProfile(uptr start, uptr rss, bool file, uptr *stats) {
+ for (uptr class_id = 0; class_id < kNumClasses; class_id++)
+ if (stats[class_id] == start)
+ stats[class_id] = rss;
+ }
+
+ void PrintStats(uptr class_id, uptr rss) {
+ RegionInfo *region = GetRegionInfo(class_id);
+ if (region->mapped_user == 0) return;
+ uptr in_use = region->stats.n_allocated - region->stats.n_freed;
+ uptr avail_chunks = region->allocated_user / ClassIdToSize(class_id);
+ Printf(
+ "%s %02zd (%6zd): mapped: %6zdK allocs: %7zd frees: %7zd inuse: %6zd "
+ "num_freed_chunks %7zd avail: %6zd rss: %6zdK releases: %6zd "
+ "last released: %6lldK region: 0x%zx\n",
+ region->exhausted ? "F" : " ", class_id, ClassIdToSize(class_id),
+ region->mapped_user >> 10, region->stats.n_allocated,
+ region->stats.n_freed, in_use, region->num_freed_chunks, avail_chunks,
+ rss >> 10, region->rtoi.num_releases,
+ region->rtoi.last_released_bytes >> 10,
+ SpaceBeg() + kRegionSize * class_id);
+ }
+
+ void PrintStats() {
+ uptr rss_stats[kNumClasses];
+ for (uptr class_id = 0; class_id < kNumClasses; class_id++)
+ rss_stats[class_id] = SpaceBeg() + kRegionSize * class_id;
+ GetMemoryProfile(FillMemoryProfile, rss_stats);
+
+ uptr total_mapped = 0;
+ uptr total_rss = 0;
+ uptr n_allocated = 0;
+ uptr n_freed = 0;
+ for (uptr class_id = 1; class_id < kNumClasses; class_id++) {
+ RegionInfo *region = GetRegionInfo(class_id);
+ if (region->mapped_user != 0) {
+ total_mapped += region->mapped_user;
+ total_rss += rss_stats[class_id];
+ }
+ n_allocated += region->stats.n_allocated;
+ n_freed += region->stats.n_freed;
+ }
+
+ Printf("Stats: SizeClassAllocator64: %zdM mapped (%zdM rss) in "
+ "%zd allocations; remains %zd\n", total_mapped >> 20,
+ total_rss >> 20, n_allocated, n_allocated - n_freed);
+ for (uptr class_id = 1; class_id < kNumClasses; class_id++)
+ PrintStats(class_id, rss_stats[class_id]);
+ }
+
+ // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
+ // introspection API.
+ void ForceLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ for (uptr i = 0; i < kNumClasses; i++) {
+ GetRegionInfo(i)->mutex.Lock();
+ }
+ }
+
+ void ForceUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ for (int i = (int)kNumClasses - 1; i >= 0; i--) {
+ GetRegionInfo(i)->mutex.Unlock();
+ }
+ }
+
+ // Iterate over all existing chunks.
+ // The allocator must be locked when calling this function.
+ void ForEachChunk(ForEachChunkCallback callback, void *arg) {
+ for (uptr class_id = 1; class_id < kNumClasses; class_id++) {
+ RegionInfo *region = GetRegionInfo(class_id);
+ uptr chunk_size = ClassIdToSize(class_id);
+ uptr region_beg = SpaceBeg() + class_id * kRegionSize;
+ uptr region_allocated_user_size =
+ AddressSpaceView::Load(region)->allocated_user;
+ for (uptr chunk = region_beg;
+ chunk < region_beg + region_allocated_user_size;
+ chunk += chunk_size) {
+ // Too slow: CHECK_EQ((void *)chunk, GetBlockBegin((void *)chunk));
+ callback(chunk, arg);
+ }
+ }
+ }
+
+ static uptr ClassIdToSize(uptr class_id) {
+ return SizeClassMap::Size(class_id);
+ }
+
+ static uptr AdditionalSize() {
+ return RoundUpTo(sizeof(RegionInfo) * kNumClassesRounded,
+ GetPageSizeCached());
+ }
+
+ typedef SizeClassMap SizeClassMapT;
+ static const uptr kNumClasses = SizeClassMap::kNumClasses;
+ static const uptr kNumClassesRounded = SizeClassMap::kNumClassesRounded;
+
+ // A packed array of counters. Each counter occupies 2^n bits, enough to store
+ // counter's max_value. Ctor will try to allocate the required buffer via
+ // mapper->MapPackedCounterArrayBuffer and the caller is expected to check
+ // whether the initialization was successful by checking IsAllocated() result.
+ // For the performance sake, none of the accessors check the validity of the
+ // arguments, it is assumed that index is always in [0, n) range and the value
+ // is not incremented past max_value.
+ class PackedCounterArray {
+ public:
+ template <typename MemoryMapper>
+ PackedCounterArray(u64 num_counters, u64 max_value, MemoryMapper *mapper)
+ : n(num_counters) {
+ CHECK_GT(num_counters, 0);
+ CHECK_GT(max_value, 0);
+ constexpr u64 kMaxCounterBits = sizeof(*buffer) * 8ULL;
+ // Rounding counter storage size up to the power of two allows for using
+ // bit shifts calculating particular counter's index and offset.
+ uptr counter_size_bits =
+ RoundUpToPowerOfTwo(MostSignificantSetBitIndex(max_value) + 1);
+ CHECK_LE(counter_size_bits, kMaxCounterBits);
+ counter_size_bits_log = Log2(counter_size_bits);
+ counter_mask = ~0ULL >> (kMaxCounterBits - counter_size_bits);
+
+ uptr packing_ratio = kMaxCounterBits >> counter_size_bits_log;
+ CHECK_GT(packing_ratio, 0);
+ packing_ratio_log = Log2(packing_ratio);
+ bit_offset_mask = packing_ratio - 1;
+
+ buffer = mapper->MapPackedCounterArrayBuffer(
+ RoundUpTo(n, 1ULL << packing_ratio_log) >> packing_ratio_log);
+ }
+
+ bool IsAllocated() const {
+ return !!buffer;
+ }
+
+ u64 GetCount() const {
+ return n;
+ }
+
+ uptr Get(uptr i) const {
+ DCHECK_LT(i, n);
+ uptr index = i >> packing_ratio_log;
+ uptr bit_offset = (i & bit_offset_mask) << counter_size_bits_log;
+ return (buffer[index] >> bit_offset) & counter_mask;
+ }
+
+ void Inc(uptr i) const {
+ DCHECK_LT(Get(i), counter_mask);
+ uptr index = i >> packing_ratio_log;
+ uptr bit_offset = (i & bit_offset_mask) << counter_size_bits_log;
+ buffer[index] += 1ULL << bit_offset;
+ }
+
+ void IncRange(uptr from, uptr to) const {
+ DCHECK_LE(from, to);
+ for (uptr i = from; i <= to; i++)
+ Inc(i);
+ }
+
+ private:
+ const u64 n;
+ u64 counter_size_bits_log;
+ u64 counter_mask;
+ u64 packing_ratio_log;
+ u64 bit_offset_mask;
+ u64* buffer;
+ };
+
+ template <class MemoryMapperT>
+ class FreePagesRangeTracker {
+ public:
+ FreePagesRangeTracker(MemoryMapperT *mapper, uptr class_id)
+ : memory_mapper(mapper),
+ class_id(class_id),
+ page_size_scaled_log(Log2(GetPageSizeCached() >> kCompactPtrScale)) {}
+
+ void NextPage(bool freed) {
+ if (freed) {
+ if (!in_the_range) {
+ current_range_start_page = current_page;
+ in_the_range = true;
+ }
+ } else {
+ CloseOpenedRange();
+ }
+ current_page++;
+ }
+
+ void Done() {
+ CloseOpenedRange();
+ }
+
+ private:
+ void CloseOpenedRange() {
+ if (in_the_range) {
+ memory_mapper->ReleasePageRangeToOS(
+ class_id, current_range_start_page << page_size_scaled_log,
+ current_page << page_size_scaled_log);
+ in_the_range = false;
+ }
+ }
+
+ MemoryMapperT *const memory_mapper = nullptr;
+ const uptr class_id = 0;
+ const uptr page_size_scaled_log = 0;
+ bool in_the_range = false;
+ uptr current_page = 0;
+ uptr current_range_start_page = 0;
+ };
+
+ // Iterates over the free_array to identify memory pages containing freed
+ // chunks only and returns these pages back to OS.
+ // allocated_pages_count is the total number of pages allocated for the
+ // current bucket.
+ template <typename MemoryMapper>
+ static void ReleaseFreeMemoryToOS(CompactPtrT *free_array,
+ uptr free_array_count, uptr chunk_size,
+ uptr allocated_pages_count,
+ MemoryMapper *memory_mapper,
+ uptr class_id) {
+ const uptr page_size = GetPageSizeCached();
+
+ // Figure out the number of chunks per page and whether we can take a fast
+ // path (the number of chunks per page is the same for all pages).
+ uptr full_pages_chunk_count_max;
+ bool same_chunk_count_per_page;
+ if (chunk_size <= page_size && page_size % chunk_size == 0) {
+ // Same number of chunks per page, no cross overs.
+ full_pages_chunk_count_max = page_size / chunk_size;
+ same_chunk_count_per_page = true;
+ } else if (chunk_size <= page_size && page_size % chunk_size != 0 &&
+ chunk_size % (page_size % chunk_size) == 0) {
+ // Some chunks are crossing page boundaries, which means that the page
+ // contains one or two partial chunks, but all pages contain the same
+ // number of chunks.
+ full_pages_chunk_count_max = page_size / chunk_size + 1;
+ same_chunk_count_per_page = true;
+ } else if (chunk_size <= page_size) {
+ // Some chunks are crossing page boundaries, which means that the page
+ // contains one or two partial chunks.
+ full_pages_chunk_count_max = page_size / chunk_size + 2;
+ same_chunk_count_per_page = false;
+ } else if (chunk_size > page_size && chunk_size % page_size == 0) {
+ // One chunk covers multiple pages, no cross overs.
+ full_pages_chunk_count_max = 1;
+ same_chunk_count_per_page = true;
+ } else if (chunk_size > page_size) {
+ // One chunk covers multiple pages, Some chunks are crossing page
+ // boundaries. Some pages contain one chunk, some contain two.
+ full_pages_chunk_count_max = 2;
+ same_chunk_count_per_page = false;
+ } else {
+ UNREACHABLE("All chunk_size/page_size ratios must be handled.");
+ }
+
+ PackedCounterArray counters(allocated_pages_count,
+ full_pages_chunk_count_max, memory_mapper);
+ if (!counters.IsAllocated())
+ return;
+
+ const uptr chunk_size_scaled = chunk_size >> kCompactPtrScale;
+ const uptr page_size_scaled = page_size >> kCompactPtrScale;
+ const uptr page_size_scaled_log = Log2(page_size_scaled);
+
+ // Iterate over free chunks and count how many free chunks affect each
+ // allocated page.
+ if (chunk_size <= page_size && page_size % chunk_size == 0) {
+ // Each chunk affects one page only.
+ for (uptr i = 0; i < free_array_count; i++)
+ counters.Inc(free_array[i] >> page_size_scaled_log);
+ } else {
+ // In all other cases chunks might affect more than one page.
+ for (uptr i = 0; i < free_array_count; i++) {
+ counters.IncRange(
+ free_array[i] >> page_size_scaled_log,
+ (free_array[i] + chunk_size_scaled - 1) >> page_size_scaled_log);
+ }
+ }
+
+ // Iterate over pages detecting ranges of pages with chunk counters equal
+ // to the expected number of chunks for the particular page.
+ FreePagesRangeTracker<MemoryMapper> range_tracker(memory_mapper, class_id);
+ if (same_chunk_count_per_page) {
+ // Fast path, every page has the same number of chunks affecting it.
+ for (uptr i = 0; i < counters.GetCount(); i++)
+ range_tracker.NextPage(counters.Get(i) == full_pages_chunk_count_max);
+ } else {
+ // Show path, go through the pages keeping count how many chunks affect
+ // each page.
+ const uptr pn =
+ chunk_size < page_size ? page_size_scaled / chunk_size_scaled : 1;
+ const uptr pnc = pn * chunk_size_scaled;
+ // The idea is to increment the current page pointer by the first chunk
+ // size, middle portion size (the portion of the page covered by chunks
+ // except the first and the last one) and then the last chunk size, adding
+ // up the number of chunks on the current page and checking on every step
+ // whether the page boundary was crossed.
+ uptr prev_page_boundary = 0;
+ uptr current_boundary = 0;
+ for (uptr i = 0; i < counters.GetCount(); i++) {
+ uptr page_boundary = prev_page_boundary + page_size_scaled;
+ uptr chunks_per_page = pn;
+ if (current_boundary < page_boundary) {
+ if (current_boundary > prev_page_boundary)
+ chunks_per_page++;
+ current_boundary += pnc;
+ if (current_boundary < page_boundary) {
+ chunks_per_page++;
+ current_boundary += chunk_size_scaled;
+ }
+ }
+ prev_page_boundary = page_boundary;
+
+ range_tracker.NextPage(counters.Get(i) == chunks_per_page);
+ }
+ }
+ range_tracker.Done();
+ }
+
+ private:
+ friend class MemoryMapper<ThisT>;
+
+ ReservedAddressRange address_range;
+
+ static const uptr kRegionSize = kSpaceSize / kNumClassesRounded;
+ // FreeArray is the array of free-d chunks (stored as 4-byte offsets).
+ // In the worst case it may require kRegionSize/SizeClassMap::kMinSize
+ // elements, but in reality this will not happen. For simplicity we
+ // dedicate 1/8 of the region's virtual space to FreeArray.
+ static const uptr kFreeArraySize = kRegionSize / 8;
+
+ static const bool kUsingConstantSpaceBeg = kSpaceBeg != ~(uptr)0;
+ uptr NonConstSpaceBeg;
+ uptr SpaceBeg() const {
+ return kUsingConstantSpaceBeg ? kSpaceBeg : NonConstSpaceBeg;
+ }
+ uptr SpaceEnd() const { return SpaceBeg() + kSpaceSize; }
+ // kRegionSize must be >= 2^32.
+ COMPILER_CHECK((kRegionSize) >= (1ULL << (SANITIZER_WORDSIZE / 2)));
+ // kRegionSize must be <= 2^36, see CompactPtrT.
+ COMPILER_CHECK((kRegionSize) <= (1ULL << (SANITIZER_WORDSIZE / 2 + 4)));
+ // Call mmap for user memory with at least this size.
+ static const uptr kUserMapSize = 1 << 16;
+ // Call mmap for metadata memory with at least this size.
+ static const uptr kMetaMapSize = 1 << 16;
+ // Call mmap for free array memory with at least this size.
+ static const uptr kFreeArrayMapSize = 1 << 16;
+
+ atomic_sint32_t release_to_os_interval_ms_;
+
+ uptr RegionInfoSpace;
+
+ // True if the user has already mapped the entire heap R/W.
+ bool PremappedHeap;
+
+ struct Stats {
+ uptr n_allocated;
+ uptr n_freed;
+ };
+
+ struct ReleaseToOsInfo {
+ uptr n_freed_at_last_release;
+ uptr num_releases;
+ u64 last_release_at_ns;
+ u64 last_released_bytes;
+ };
+
+ struct ALIGNED(SANITIZER_CACHE_LINE_SIZE) RegionInfo {
+ Mutex mutex;
+ uptr num_freed_chunks; // Number of elements in the freearray.
+ uptr mapped_free_array; // Bytes mapped for freearray.
+ uptr allocated_user; // Bytes allocated for user memory.
+ uptr allocated_meta; // Bytes allocated for metadata.
+ uptr mapped_user; // Bytes mapped for user memory.
+ uptr mapped_meta; // Bytes mapped for metadata.
+ u32 rand_state; // Seed for random shuffle, used if kRandomShuffleChunks.
+ bool exhausted; // Whether region is out of space for new chunks.
+ Stats stats;
+ ReleaseToOsInfo rtoi;
+ };
+ COMPILER_CHECK(sizeof(RegionInfo) % kCacheLineSize == 0);
+
+ RegionInfo *GetRegionInfo(uptr class_id) const {
+ DCHECK_LT(class_id, kNumClasses);
+ RegionInfo *regions = reinterpret_cast<RegionInfo *>(RegionInfoSpace);
+ return &regions[class_id];
+ }
+
+ uptr GetMetadataEnd(uptr region_beg) const {
+ return region_beg + kRegionSize - kFreeArraySize;
+ }
+
+ uptr GetChunkIdx(uptr chunk, uptr size) const {
+ if (!kUsingConstantSpaceBeg)
+ chunk -= SpaceBeg();
+
+ uptr offset = chunk % kRegionSize;
+ // Here we divide by a non-constant. This is costly.
+ // size always fits into 32-bits. If the offset fits too, use 32-bit div.
+ if (offset >> (SANITIZER_WORDSIZE / 2))
+ return offset / size;
+ return (u32)offset / (u32)size;
+ }
+
+ CompactPtrT *GetFreeArray(uptr region_beg) const {
+ return reinterpret_cast<CompactPtrT *>(GetMetadataEnd(region_beg));
+ }
+
+ bool MapWithCallback(uptr beg, uptr size, const char *name) {
+ if (PremappedHeap)
+ return beg >= NonConstSpaceBeg &&
+ beg + size <= NonConstSpaceBeg + kSpaceSize;
+ uptr mapped = address_range.Map(beg, size, name);
+ if (UNLIKELY(!mapped))
+ return false;
+ CHECK_EQ(beg, mapped);
+ MapUnmapCallback().OnMap(beg, size);
+ return true;
+ }
+
+ void MapWithCallbackOrDie(uptr beg, uptr size, const char *name) {
+ if (PremappedHeap) {
+ CHECK_GE(beg, NonConstSpaceBeg);
+ CHECK_LE(beg + size, NonConstSpaceBeg + kSpaceSize);
+ return;
+ }
+ CHECK_EQ(beg, address_range.MapOrDie(beg, size, name));
+ MapUnmapCallback().OnMap(beg, size);
+ }
+
+ void UnmapWithCallbackOrDie(uptr beg, uptr size) {
+ if (PremappedHeap)
+ return;
+ MapUnmapCallback().OnUnmap(beg, size);
+ address_range.Unmap(beg, size);
+ }
+
+ bool EnsureFreeArraySpace(RegionInfo *region, uptr region_beg,
+ uptr num_freed_chunks) {
+ uptr needed_space = num_freed_chunks * sizeof(CompactPtrT);
+ if (region->mapped_free_array < needed_space) {
+ uptr new_mapped_free_array = RoundUpTo(needed_space, kFreeArrayMapSize);
+ CHECK_LE(new_mapped_free_array, kFreeArraySize);
+ uptr current_map_end = reinterpret_cast<uptr>(GetFreeArray(region_beg)) +
+ region->mapped_free_array;
+ uptr new_map_size = new_mapped_free_array - region->mapped_free_array;
+ if (UNLIKELY(!MapWithCallback(current_map_end, new_map_size,
+ "SizeClassAllocator: freearray")))
+ return false;
+ region->mapped_free_array = new_mapped_free_array;
+ }
+ return true;
+ }
+
+ // Check whether this size class is exhausted.
+ bool IsRegionExhausted(RegionInfo *region, uptr class_id,
+ uptr additional_map_size) {
+ if (LIKELY(region->mapped_user + region->mapped_meta +
+ additional_map_size <= kRegionSize - kFreeArraySize))
+ return false;
+ if (!region->exhausted) {
+ region->exhausted = true;
+ Printf("%s: Out of memory. ", SanitizerToolName);
+ Printf("The process has exhausted %zuMB for size class %zu.\n",
+ kRegionSize >> 20, ClassIdToSize(class_id));
+ }
+ return true;
+ }
+
+ NOINLINE bool PopulateFreeArray(AllocatorStats *stat, uptr class_id,
+ RegionInfo *region, uptr requested_count) {
+ // region->mutex is held.
+ const uptr region_beg = GetRegionBeginBySizeClass(class_id);
+ const uptr size = ClassIdToSize(class_id);
+
+ const uptr total_user_bytes =
+ region->allocated_user + requested_count * size;
+ // Map more space for chunks, if necessary.
+ if (LIKELY(total_user_bytes > region->mapped_user)) {
+ if (UNLIKELY(region->mapped_user == 0)) {
+ if (!kUsingConstantSpaceBeg && kRandomShuffleChunks)
+ // The random state is initialized from ASLR.
+ region->rand_state = static_cast<u32>(region_beg >> 12);
+ // Postpone the first release to OS attempt for ReleaseToOSIntervalMs,
+ // preventing just allocated memory from being released sooner than
+ // necessary and also preventing extraneous ReleaseMemoryPagesToOS calls
+ // for short lived processes.
+ // Do it only when the feature is turned on, to avoid a potentially
+ // extraneous syscall.
+ if (ReleaseToOSIntervalMs() >= 0)
+ region->rtoi.last_release_at_ns = MonotonicNanoTime();
+ }
+ // Do the mmap for the user memory.
+ const uptr user_map_size =
+ RoundUpTo(total_user_bytes - region->mapped_user, kUserMapSize);
+ if (UNLIKELY(IsRegionExhausted(region, class_id, user_map_size)))
+ return false;
+ if (UNLIKELY(!MapWithCallback(region_beg + region->mapped_user,
+ user_map_size,
+ "SizeClassAllocator: region data")))
+ return false;
+ stat->Add(AllocatorStatMapped, user_map_size);
+ region->mapped_user += user_map_size;
+ }
+ const uptr new_chunks_count =
+ (region->mapped_user - region->allocated_user) / size;
+
+ if (kMetadataSize) {
+ // Calculate the required space for metadata.
+ const uptr total_meta_bytes =
+ region->allocated_meta + new_chunks_count * kMetadataSize;
+ const uptr meta_map_size = (total_meta_bytes > region->mapped_meta) ?
+ RoundUpTo(total_meta_bytes - region->mapped_meta, kMetaMapSize) : 0;
+ // Map more space for metadata, if necessary.
+ if (meta_map_size) {
+ if (UNLIKELY(IsRegionExhausted(region, class_id, meta_map_size)))
+ return false;
+ if (UNLIKELY(!MapWithCallback(
+ GetMetadataEnd(region_beg) - region->mapped_meta - meta_map_size,
+ meta_map_size, "SizeClassAllocator: region metadata")))
+ return false;
+ region->mapped_meta += meta_map_size;
+ }
+ }
+
+ // If necessary, allocate more space for the free array and populate it with
+ // newly allocated chunks.
+ const uptr total_freed_chunks = region->num_freed_chunks + new_chunks_count;
+ if (UNLIKELY(!EnsureFreeArraySpace(region, region_beg, total_freed_chunks)))
+ return false;
+ CompactPtrT *free_array = GetFreeArray(region_beg);
+ for (uptr i = 0, chunk = region->allocated_user; i < new_chunks_count;
+ i++, chunk += size)
+ free_array[total_freed_chunks - 1 - i] = PointerToCompactPtr(0, chunk);
+ if (kRandomShuffleChunks)
+ RandomShuffle(&free_array[region->num_freed_chunks], new_chunks_count,
+ &region->rand_state);
+
+ // All necessary memory is mapped and now it is safe to advance all
+ // 'allocated_*' counters.
+ region->num_freed_chunks += new_chunks_count;
+ region->allocated_user += new_chunks_count * size;
+ CHECK_LE(region->allocated_user, region->mapped_user);
+ region->allocated_meta += new_chunks_count * kMetadataSize;
+ CHECK_LE(region->allocated_meta, region->mapped_meta);
+ region->exhausted = false;
+
+ // TODO(alekseyshl): Consider bumping last_release_at_ns here to prevent
+ // MaybeReleaseToOS from releasing just allocated pages or protect these
+ // not yet used chunks some other way.
+
+ return true;
+ }
+
+ // Attempts to release RAM occupied by freed chunks back to OS. The region is
+ // expected to be locked.
+ //
+ // TODO(morehouse): Support a callback on memory release so HWASan can release
+ // aliases as well.
+ void MaybeReleaseToOS(MemoryMapperT *memory_mapper, uptr class_id,
+ bool force) {
+ RegionInfo *region = GetRegionInfo(class_id);
+ const uptr chunk_size = ClassIdToSize(class_id);
+ const uptr page_size = GetPageSizeCached();
+
+ uptr n = region->num_freed_chunks;
+ if (n * chunk_size < page_size)
+ return; // No chance to release anything.
+ if ((region->stats.n_freed -
+ region->rtoi.n_freed_at_last_release) * chunk_size < page_size) {
+ return; // Nothing new to release.
+ }
+
+ if (!force) {
+ s32 interval_ms = ReleaseToOSIntervalMs();
+ if (interval_ms < 0)
+ return;
+
+ if (region->rtoi.last_release_at_ns + interval_ms * 1000000ULL >
+ MonotonicNanoTime()) {
+ return; // Memory was returned recently.
+ }
+ }
+
+ ReleaseFreeMemoryToOS(
+ GetFreeArray(GetRegionBeginBySizeClass(class_id)), n, chunk_size,
+ RoundUpTo(region->allocated_user, page_size) / page_size, memory_mapper,
+ class_id);
+
+ uptr ranges, bytes;
+ if (memory_mapper->GetAndResetStats(ranges, bytes)) {
+ region->rtoi.n_freed_at_last_release = region->stats.n_freed;
+ region->rtoi.num_releases += ranges;
+ region->rtoi.last_released_bytes = bytes;
+ }
+ region->rtoi.last_release_at_ns = MonotonicNanoTime();
+ }
+};
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp
new file mode 100644
index 00000000000..129f925e6fb
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp
@@ -0,0 +1,144 @@
+//===-- sanitizer_allocator_report.cpp --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Shared allocator error reporting for ThreadSanitizer, MemorySanitizer, etc.
+///
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_allocator.h"
+#include "sanitizer_allocator_report.h"
+#include "sanitizer_common.h"
+#include "sanitizer_report_decorator.h"
+
+namespace __sanitizer {
+
+class ScopedAllocatorErrorReport {
+ public:
+ ScopedAllocatorErrorReport(const char *error_summary_,
+ const StackTrace *stack_)
+ : error_summary(error_summary_),
+ stack(stack_) {
+ Printf("%s", d.Error());
+ }
+ ~ScopedAllocatorErrorReport() {
+ Printf("%s", d.Default());
+ stack->Print();
+ PrintHintAllocatorCannotReturnNull();
+ ReportErrorSummary(error_summary, stack);
+ }
+
+ private:
+ ScopedErrorReportLock lock;
+ const char *error_summary;
+ const StackTrace* const stack;
+ const SanitizerCommonDecorator d;
+};
+
+void NORETURN ReportCallocOverflow(uptr count, uptr size,
+ const StackTrace *stack) {
+ {
+ ScopedAllocatorErrorReport report("calloc-overflow", stack);
+ Report("ERROR: %s: calloc parameters overflow: count * size (%zd * %zd) "
+ "cannot be represented in type size_t\n", SanitizerToolName, count,
+ size);
+ }
+ Die();
+}
+
+void NORETURN ReportReallocArrayOverflow(uptr count, uptr size,
+ const StackTrace *stack) {
+ {
+ ScopedAllocatorErrorReport report("reallocarray-overflow", stack);
+ Report(
+ "ERROR: %s: reallocarray parameters overflow: count * size (%zd * %zd) "
+ "cannot be represented in type size_t\n",
+ SanitizerToolName, count, size);
+ }
+ Die();
+}
+
+void NORETURN ReportPvallocOverflow(uptr size, const StackTrace *stack) {
+ {
+ ScopedAllocatorErrorReport report("pvalloc-overflow", stack);
+ Report("ERROR: %s: pvalloc parameters overflow: size 0x%zx rounded up to "
+ "system page size 0x%zx cannot be represented in type size_t\n",
+ SanitizerToolName, size, GetPageSizeCached());
+ }
+ Die();
+}
+
+void NORETURN ReportInvalidAllocationAlignment(uptr alignment,
+ const StackTrace *stack) {
+ {
+ ScopedAllocatorErrorReport report("invalid-allocation-alignment", stack);
+ Report("ERROR: %s: invalid allocation alignment: %zd, alignment must be a "
+ "power of two\n", SanitizerToolName, alignment);
+ }
+ Die();
+}
+
+void NORETURN ReportInvalidAlignedAllocAlignment(uptr size, uptr alignment,
+ const StackTrace *stack) {
+ {
+ ScopedAllocatorErrorReport report("invalid-aligned-alloc-alignment", stack);
+#if SANITIZER_POSIX
+ Report("ERROR: %s: invalid alignment requested in "
+ "aligned_alloc: %zd, alignment must be a power of two and the "
+ "requested size 0x%zx must be a multiple of alignment\n",
+ SanitizerToolName, alignment, size);
+#else
+ Report("ERROR: %s: invalid alignment requested in aligned_alloc: %zd, "
+ "the requested size 0x%zx must be a multiple of alignment\n",
+ SanitizerToolName, alignment, size);
+#endif
+ }
+ Die();
+}
+
+void NORETURN ReportInvalidPosixMemalignAlignment(uptr alignment,
+ const StackTrace *stack) {
+ {
+ ScopedAllocatorErrorReport report("invalid-posix-memalign-alignment",
+ stack);
+ Report(
+ "ERROR: %s: invalid alignment requested in "
+ "posix_memalign: %zd, alignment must be a power of two and a "
+ "multiple of sizeof(void*) == %zd\n",
+ SanitizerToolName, alignment, sizeof(void *));
+ }
+ Die();
+}
+
+void NORETURN ReportAllocationSizeTooBig(uptr user_size, uptr max_size,
+ const StackTrace *stack) {
+ {
+ ScopedAllocatorErrorReport report("allocation-size-too-big", stack);
+ Report("ERROR: %s: requested allocation size 0x%zx exceeds maximum "
+ "supported size of 0x%zx\n", SanitizerToolName, user_size, max_size);
+ }
+ Die();
+}
+
+void NORETURN ReportOutOfMemory(uptr requested_size, const StackTrace *stack) {
+ {
+ ScopedAllocatorErrorReport report("out-of-memory", stack);
+ ERROR_OOM("allocator is trying to allocate 0x%zx bytes\n", requested_size);
+ }
+ Die();
+}
+
+void NORETURN ReportRssLimitExceeded(const StackTrace *stack) {
+ {
+ ScopedAllocatorErrorReport report("rss-limit-exceeded", stack);
+ Report("ERROR: %s: allocator exceeded the RSS limit\n", SanitizerToolName);
+ }
+ Die();
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_report.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_report.h
new file mode 100644
index 00000000000..6e4e6b13549
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_report.h
@@ -0,0 +1,40 @@
+//===-- sanitizer_allocator_report.h ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Shared allocator error reporting for ThreadSanitizer, MemorySanitizer, etc.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ALLOCATOR_REPORT_H
+#define SANITIZER_ALLOCATOR_REPORT_H
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_stacktrace.h"
+
+namespace __sanitizer {
+
+void NORETURN ReportCallocOverflow(uptr count, uptr size,
+ const StackTrace *stack);
+void NORETURN ReportReallocArrayOverflow(uptr count, uptr size,
+ const StackTrace *stack);
+void NORETURN ReportPvallocOverflow(uptr size, const StackTrace *stack);
+void NORETURN ReportInvalidAllocationAlignment(uptr alignment,
+ const StackTrace *stack);
+void NORETURN ReportInvalidAlignedAllocAlignment(uptr size, uptr alignment,
+ const StackTrace *stack);
+void NORETURN ReportInvalidPosixMemalignAlignment(uptr alignment,
+ const StackTrace *stack);
+void NORETURN ReportAllocationSizeTooBig(uptr user_size, uptr max_size,
+ const StackTrace *stack);
+void NORETURN ReportOutOfMemory(uptr requested_size, const StackTrace *stack);
+void NORETURN ReportRssLimitExceeded(const StackTrace *stack);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_ALLOCATOR_REPORT_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_secondary.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_secondary.h
new file mode 100644
index 00000000000..15764555560
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_secondary.h
@@ -0,0 +1,322 @@
+//===-- sanitizer_allocator_secondary.h -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Part of the Sanitizer Allocator.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_ALLOCATOR_H
+#error This file must be included inside sanitizer_allocator.h
+#endif
+
+// Fixed array to store LargeMmapAllocator chunks list, limited to 32K total
+// allocated chunks. To be used in memory constrained or not memory hungry cases
+// (currently, 32 bits and internal allocator).
+class LargeMmapAllocatorPtrArrayStatic {
+ public:
+ inline void *Init() { return &p_[0]; }
+ inline void EnsureSpace(uptr n) { CHECK_LT(n, kMaxNumChunks); }
+ private:
+ static const int kMaxNumChunks = 1 << 15;
+ uptr p_[kMaxNumChunks];
+};
+
+// Much less restricted LargeMmapAllocator chunks list (comparing to
+// PtrArrayStatic). Backed by mmaped memory region and can hold up to 1M chunks.
+// ReservedAddressRange was used instead of just MAP_NORESERVE to achieve the
+// same functionality in Fuchsia case, which does not support MAP_NORESERVE.
+class LargeMmapAllocatorPtrArrayDynamic {
+ public:
+ inline void *Init() {
+ uptr p = address_range_.Init(kMaxNumChunks * sizeof(uptr),
+ SecondaryAllocatorName);
+ CHECK(p);
+ return reinterpret_cast<void*>(p);
+ }
+
+ inline void EnsureSpace(uptr n) {
+ CHECK_LT(n, kMaxNumChunks);
+ DCHECK(n <= n_reserved_);
+ if (UNLIKELY(n == n_reserved_)) {
+ address_range_.MapOrDie(
+ reinterpret_cast<uptr>(address_range_.base()) +
+ n_reserved_ * sizeof(uptr),
+ kChunksBlockCount * sizeof(uptr));
+ n_reserved_ += kChunksBlockCount;
+ }
+ }
+
+ private:
+ static const int kMaxNumChunks = 1 << 20;
+ static const int kChunksBlockCount = 1 << 14;
+ ReservedAddressRange address_range_;
+ uptr n_reserved_;
+};
+
+#if SANITIZER_WORDSIZE == 32
+typedef LargeMmapAllocatorPtrArrayStatic DefaultLargeMmapAllocatorPtrArray;
+#else
+typedef LargeMmapAllocatorPtrArrayDynamic DefaultLargeMmapAllocatorPtrArray;
+#endif
+
+// This class can (de)allocate only large chunks of memory using mmap/unmap.
+// The main purpose of this allocator is to cover large and rare allocation
+// sizes not covered by more efficient allocators (e.g. SizeClassAllocator64).
+template <class MapUnmapCallback = NoOpMapUnmapCallback,
+ class PtrArrayT = DefaultLargeMmapAllocatorPtrArray,
+ class AddressSpaceViewTy = LocalAddressSpaceView>
+class LargeMmapAllocator {
+ public:
+ using AddressSpaceView = AddressSpaceViewTy;
+ void InitLinkerInitialized() {
+ page_size_ = GetPageSizeCached();
+ chunks_ = reinterpret_cast<Header**>(ptr_array_.Init());
+ }
+
+ void Init() {
+ internal_memset(this, 0, sizeof(*this));
+ InitLinkerInitialized();
+ }
+
+ void *Allocate(AllocatorStats *stat, uptr size, uptr alignment) {
+ CHECK(IsPowerOfTwo(alignment));
+ uptr map_size = RoundUpMapSize(size);
+ if (alignment > page_size_)
+ map_size += alignment;
+ // Overflow.
+ if (map_size < size) {
+ Report("WARNING: %s: LargeMmapAllocator allocation overflow: "
+ "0x%zx bytes with 0x%zx alignment requested\n",
+ SanitizerToolName, map_size, alignment);
+ return nullptr;
+ }
+ uptr map_beg = reinterpret_cast<uptr>(
+ MmapOrDieOnFatalError(map_size, SecondaryAllocatorName));
+ if (!map_beg)
+ return nullptr;
+ CHECK(IsAligned(map_beg, page_size_));
+ MapUnmapCallback().OnMap(map_beg, map_size);
+ uptr map_end = map_beg + map_size;
+ uptr res = map_beg + page_size_;
+ if (res & (alignment - 1)) // Align.
+ res += alignment - (res & (alignment - 1));
+ CHECK(IsAligned(res, alignment));
+ CHECK(IsAligned(res, page_size_));
+ CHECK_GE(res + size, map_beg);
+ CHECK_LE(res + size, map_end);
+ Header *h = GetHeader(res);
+ h->size = size;
+ h->map_beg = map_beg;
+ h->map_size = map_size;
+ uptr size_log = MostSignificantSetBitIndex(map_size);
+ CHECK_LT(size_log, ARRAY_SIZE(stats.by_size_log));
+ {
+ SpinMutexLock l(&mutex_);
+ ptr_array_.EnsureSpace(n_chunks_);
+ uptr idx = n_chunks_++;
+ h->chunk_idx = idx;
+ chunks_[idx] = h;
+ chunks_sorted_ = false;
+ stats.n_allocs++;
+ stats.currently_allocated += map_size;
+ stats.max_allocated = Max(stats.max_allocated, stats.currently_allocated);
+ stats.by_size_log[size_log]++;
+ stat->Add(AllocatorStatAllocated, map_size);
+ stat->Add(AllocatorStatMapped, map_size);
+ }
+ return reinterpret_cast<void*>(res);
+ }
+
+ void Deallocate(AllocatorStats *stat, void *p) {
+ Header *h = GetHeader(p);
+ {
+ SpinMutexLock l(&mutex_);
+ uptr idx = h->chunk_idx;
+ CHECK_EQ(chunks_[idx], h);
+ CHECK_LT(idx, n_chunks_);
+ chunks_[idx] = chunks_[--n_chunks_];
+ chunks_[idx]->chunk_idx = idx;
+ chunks_sorted_ = false;
+ stats.n_frees++;
+ stats.currently_allocated -= h->map_size;
+ stat->Sub(AllocatorStatAllocated, h->map_size);
+ stat->Sub(AllocatorStatMapped, h->map_size);
+ }
+ MapUnmapCallback().OnUnmap(h->map_beg, h->map_size);
+ UnmapOrDie(reinterpret_cast<void*>(h->map_beg), h->map_size);
+ }
+
+ uptr TotalMemoryUsed() {
+ SpinMutexLock l(&mutex_);
+ uptr res = 0;
+ for (uptr i = 0; i < n_chunks_; i++) {
+ Header *h = chunks_[i];
+ CHECK_EQ(h->chunk_idx, i);
+ res += RoundUpMapSize(h->size);
+ }
+ return res;
+ }
+
+ bool PointerIsMine(const void *p) const {
+ return GetBlockBegin(p) != nullptr;
+ }
+
+ uptr GetActuallyAllocatedSize(void *p) {
+ return RoundUpTo(GetHeader(p)->size, page_size_);
+ }
+
+ // At least page_size_/2 metadata bytes is available.
+ void *GetMetaData(const void *p) {
+ // Too slow: CHECK_EQ(p, GetBlockBegin(p));
+ if (!IsAligned(reinterpret_cast<uptr>(p), page_size_)) {
+ Printf("%s: bad pointer %p\n", SanitizerToolName, p);
+ CHECK(IsAligned(reinterpret_cast<uptr>(p), page_size_));
+ }
+ return GetHeader(p) + 1;
+ }
+
+ void *GetBlockBegin(const void *ptr) const {
+ uptr p = reinterpret_cast<uptr>(ptr);
+ SpinMutexLock l(&mutex_);
+ uptr nearest_chunk = 0;
+ Header *const *chunks = AddressSpaceView::Load(chunks_, n_chunks_);
+ // Cache-friendly linear search.
+ for (uptr i = 0; i < n_chunks_; i++) {
+ uptr ch = reinterpret_cast<uptr>(chunks[i]);
+ if (p < ch) continue; // p is at left to this chunk, skip it.
+ if (p - ch < p - nearest_chunk)
+ nearest_chunk = ch;
+ }
+ if (!nearest_chunk)
+ return nullptr;
+ const Header *h =
+ AddressSpaceView::Load(reinterpret_cast<Header *>(nearest_chunk));
+ Header *h_ptr = reinterpret_cast<Header *>(nearest_chunk);
+ CHECK_GE(nearest_chunk, h->map_beg);
+ CHECK_LT(nearest_chunk, h->map_beg + h->map_size);
+ CHECK_LE(nearest_chunk, p);
+ if (h->map_beg + h->map_size <= p)
+ return nullptr;
+ return GetUser(h_ptr);
+ }
+
+ void EnsureSortedChunks() {
+ if (chunks_sorted_) return;
+ Header **chunks = AddressSpaceView::LoadWritable(chunks_, n_chunks_);
+ Sort(reinterpret_cast<uptr *>(chunks), n_chunks_);
+ for (uptr i = 0; i < n_chunks_; i++)
+ AddressSpaceView::LoadWritable(chunks[i])->chunk_idx = i;
+ chunks_sorted_ = true;
+ }
+
+ // This function does the same as GetBlockBegin, but is much faster.
+ // Must be called with the allocator locked.
+ void *GetBlockBeginFastLocked(const void *ptr) {
+ mutex_.CheckLocked();
+ uptr p = reinterpret_cast<uptr>(ptr);
+ uptr n = n_chunks_;
+ if (!n) return nullptr;
+ EnsureSortedChunks();
+ Header *const *chunks = AddressSpaceView::Load(chunks_, n_chunks_);
+ auto min_mmap_ = reinterpret_cast<uptr>(chunks[0]);
+ auto max_mmap_ = reinterpret_cast<uptr>(chunks[n - 1]) +
+ AddressSpaceView::Load(chunks[n - 1])->map_size;
+ if (p < min_mmap_ || p >= max_mmap_)
+ return nullptr;
+ uptr beg = 0, end = n - 1;
+ // This loop is a log(n) lower_bound. It does not check for the exact match
+ // to avoid expensive cache-thrashing loads.
+ while (end - beg >= 2) {
+ uptr mid = (beg + end) / 2; // Invariant: mid >= beg + 1
+ if (p < reinterpret_cast<uptr>(chunks[mid]))
+ end = mid - 1; // We are not interested in chunks[mid].
+ else
+ beg = mid; // chunks[mid] may still be what we want.
+ }
+
+ if (beg < end) {
+ CHECK_EQ(beg + 1, end);
+ // There are 2 chunks left, choose one.
+ if (p >= reinterpret_cast<uptr>(chunks[end]))
+ beg = end;
+ }
+
+ const Header *h = AddressSpaceView::Load(chunks[beg]);
+ Header *h_ptr = chunks[beg];
+ if (h->map_beg + h->map_size <= p || p < h->map_beg)
+ return nullptr;
+ return GetUser(h_ptr);
+ }
+
+ void PrintStats() {
+ Printf("Stats: LargeMmapAllocator: allocated %zd times, "
+ "remains %zd (%zd K) max %zd M; by size logs: ",
+ stats.n_allocs, stats.n_allocs - stats.n_frees,
+ stats.currently_allocated >> 10, stats.max_allocated >> 20);
+ for (uptr i = 0; i < ARRAY_SIZE(stats.by_size_log); i++) {
+ uptr c = stats.by_size_log[i];
+ if (!c) continue;
+ Printf("%zd:%zd; ", i, c);
+ }
+ Printf("\n");
+ }
+
+ // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
+ // introspection API.
+ void ForceLock() SANITIZER_ACQUIRE(mutex_) { mutex_.Lock(); }
+
+ void ForceUnlock() SANITIZER_RELEASE(mutex_) { mutex_.Unlock(); }
+
+ // Iterate over all existing chunks.
+ // The allocator must be locked when calling this function.
+ void ForEachChunk(ForEachChunkCallback callback, void *arg) {
+ EnsureSortedChunks(); // Avoid doing the sort while iterating.
+ const Header *const *chunks = AddressSpaceView::Load(chunks_, n_chunks_);
+ for (uptr i = 0; i < n_chunks_; i++) {
+ const Header *t = chunks[i];
+ callback(reinterpret_cast<uptr>(GetUser(t)), arg);
+ // Consistency check: verify that the array did not change.
+ CHECK_EQ(chunks[i], t);
+ CHECK_EQ(AddressSpaceView::Load(chunks[i])->chunk_idx, i);
+ }
+ }
+
+ private:
+ struct Header {
+ uptr map_beg;
+ uptr map_size;
+ uptr size;
+ uptr chunk_idx;
+ };
+
+ Header *GetHeader(uptr p) {
+ CHECK(IsAligned(p, page_size_));
+ return reinterpret_cast<Header*>(p - page_size_);
+ }
+ Header *GetHeader(const void *p) {
+ return GetHeader(reinterpret_cast<uptr>(p));
+ }
+
+ void *GetUser(const Header *h) const {
+ CHECK(IsAligned((uptr)h, page_size_));
+ return reinterpret_cast<void*>(reinterpret_cast<uptr>(h) + page_size_);
+ }
+
+ uptr RoundUpMapSize(uptr size) {
+ return RoundUpTo(size, page_size_) + page_size_;
+ }
+
+ uptr page_size_;
+ Header **chunks_;
+ PtrArrayT ptr_array_;
+ uptr n_chunks_;
+ bool chunks_sorted_;
+ struct Stats {
+ uptr n_allocs, n_frees, currently_allocated, max_allocated, by_size_log[64];
+ } stats;
+ mutable StaticSpinMutex mutex_;
+};
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_size_class_map.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_size_class_map.h
new file mode 100644
index 00000000000..361793f2490
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_size_class_map.h
@@ -0,0 +1,241 @@
+//===-- sanitizer_allocator_size_class_map.h --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Part of the Sanitizer Allocator.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_ALLOCATOR_H
+#error This file must be included inside sanitizer_allocator.h
+#endif
+
+// SizeClassMap maps allocation sizes into size classes and back.
+// Class 0 always corresponds to size 0.
+// The other sizes are controlled by the template parameters:
+// kMinSizeLog: defines the class 1 as 2^kMinSizeLog.
+// kMaxSizeLog: defines the last class as 2^kMaxSizeLog.
+// kMidSizeLog: the classes starting from 1 increase with step
+// 2^kMinSizeLog until 2^kMidSizeLog.
+// kNumBits: the number of non-zero bits in sizes after 2^kMidSizeLog.
+// E.g. with kNumBits==3 all size classes after 2^kMidSizeLog
+// look like 0b1xx0..0, where x is either 0 or 1.
+//
+// Example: kNumBits=3, kMinSizeLog=4, kMidSizeLog=8, kMaxSizeLog=17:
+//
+// Classes 1 - 16 correspond to sizes 16 to 256 (size = class_id * 16).
+// Next 4 classes: 256 + i * 64 (i = 1 to 4).
+// Next 4 classes: 512 + i * 128 (i = 1 to 4).
+// ...
+// Next 4 classes: 2^k + i * 2^(k-2) (i = 1 to 4).
+// Last class corresponds to kMaxSize = 1 << kMaxSizeLog.
+//
+// This structure of the size class map gives us:
+// - Efficient table-free class-to-size and size-to-class functions.
+// - Difference between two consequent size classes is between 14% and 25%
+//
+// This class also gives a hint to a thread-caching allocator about the amount
+// of chunks that need to be cached per-thread:
+// - kMaxNumCachedHint is a hint for maximal number of chunks per size class.
+// The actual number is computed in TransferBatch.
+// - (1 << kMaxBytesCachedLog) is the maximal number of bytes per size class.
+//
+// Part of output of SizeClassMap::Print():
+// c00 => s: 0 diff: +0 00% l 0 cached: 0 0; id 0
+// c01 => s: 16 diff: +16 00% l 4 cached: 256 4096; id 1
+// c02 => s: 32 diff: +16 100% l 5 cached: 256 8192; id 2
+// c03 => s: 48 diff: +16 50% l 5 cached: 256 12288; id 3
+// c04 => s: 64 diff: +16 33% l 6 cached: 256 16384; id 4
+// c05 => s: 80 diff: +16 25% l 6 cached: 256 20480; id 5
+// c06 => s: 96 diff: +16 20% l 6 cached: 256 24576; id 6
+// c07 => s: 112 diff: +16 16% l 6 cached: 256 28672; id 7
+//
+// c08 => s: 128 diff: +16 14% l 7 cached: 256 32768; id 8
+// c09 => s: 144 diff: +16 12% l 7 cached: 256 36864; id 9
+// c10 => s: 160 diff: +16 11% l 7 cached: 256 40960; id 10
+// c11 => s: 176 diff: +16 10% l 7 cached: 256 45056; id 11
+// c12 => s: 192 diff: +16 09% l 7 cached: 256 49152; id 12
+// c13 => s: 208 diff: +16 08% l 7 cached: 256 53248; id 13
+// c14 => s: 224 diff: +16 07% l 7 cached: 256 57344; id 14
+// c15 => s: 240 diff: +16 07% l 7 cached: 256 61440; id 15
+//
+// c16 => s: 256 diff: +16 06% l 8 cached: 256 65536; id 16
+// c17 => s: 320 diff: +64 25% l 8 cached: 204 65280; id 17
+// c18 => s: 384 diff: +64 20% l 8 cached: 170 65280; id 18
+// c19 => s: 448 diff: +64 16% l 8 cached: 146 65408; id 19
+//
+// c20 => s: 512 diff: +64 14% l 9 cached: 128 65536; id 20
+// c21 => s: 640 diff: +128 25% l 9 cached: 102 65280; id 21
+// c22 => s: 768 diff: +128 20% l 9 cached: 85 65280; id 22
+// c23 => s: 896 diff: +128 16% l 9 cached: 73 65408; id 23
+//
+// c24 => s: 1024 diff: +128 14% l 10 cached: 64 65536; id 24
+// c25 => s: 1280 diff: +256 25% l 10 cached: 51 65280; id 25
+// c26 => s: 1536 diff: +256 20% l 10 cached: 42 64512; id 26
+// c27 => s: 1792 diff: +256 16% l 10 cached: 36 64512; id 27
+//
+// ...
+//
+// c48 => s: 65536 diff: +8192 14% l 16 cached: 1 65536; id 48
+// c49 => s: 81920 diff: +16384 25% l 16 cached: 1 81920; id 49
+// c50 => s: 98304 diff: +16384 20% l 16 cached: 1 98304; id 50
+// c51 => s: 114688 diff: +16384 16% l 16 cached: 1 114688; id 51
+//
+// c52 => s: 131072 diff: +16384 14% l 17 cached: 1 131072; id 52
+//
+//
+// Another example (kNumBits=2):
+// c00 => s: 0 diff: +0 00% l 0 cached: 0 0; id 0
+// c01 => s: 32 diff: +32 00% l 5 cached: 64 2048; id 1
+// c02 => s: 64 diff: +32 100% l 6 cached: 64 4096; id 2
+// c03 => s: 96 diff: +32 50% l 6 cached: 64 6144; id 3
+// c04 => s: 128 diff: +32 33% l 7 cached: 64 8192; id 4
+// c05 => s: 160 diff: +32 25% l 7 cached: 64 10240; id 5
+// c06 => s: 192 diff: +32 20% l 7 cached: 64 12288; id 6
+// c07 => s: 224 diff: +32 16% l 7 cached: 64 14336; id 7
+// c08 => s: 256 diff: +32 14% l 8 cached: 64 16384; id 8
+// c09 => s: 384 diff: +128 50% l 8 cached: 42 16128; id 9
+// c10 => s: 512 diff: +128 33% l 9 cached: 32 16384; id 10
+// c11 => s: 768 diff: +256 50% l 9 cached: 21 16128; id 11
+// c12 => s: 1024 diff: +256 33% l 10 cached: 16 16384; id 12
+// c13 => s: 1536 diff: +512 50% l 10 cached: 10 15360; id 13
+// c14 => s: 2048 diff: +512 33% l 11 cached: 8 16384; id 14
+// c15 => s: 3072 diff: +1024 50% l 11 cached: 5 15360; id 15
+// c16 => s: 4096 diff: +1024 33% l 12 cached: 4 16384; id 16
+// c17 => s: 6144 diff: +2048 50% l 12 cached: 2 12288; id 17
+// c18 => s: 8192 diff: +2048 33% l 13 cached: 2 16384; id 18
+// c19 => s: 12288 diff: +4096 50% l 13 cached: 1 12288; id 19
+// c20 => s: 16384 diff: +4096 33% l 14 cached: 1 16384; id 20
+// c21 => s: 24576 diff: +8192 50% l 14 cached: 1 24576; id 21
+// c22 => s: 32768 diff: +8192 33% l 15 cached: 1 32768; id 22
+// c23 => s: 49152 diff: +16384 50% l 15 cached: 1 49152; id 23
+// c24 => s: 65536 diff: +16384 33% l 16 cached: 1 65536; id 24
+// c25 => s: 98304 diff: +32768 50% l 16 cached: 1 98304; id 25
+// c26 => s: 131072 diff: +32768 33% l 17 cached: 1 131072; id 26
+
+template <uptr kNumBits, uptr kMinSizeLog, uptr kMidSizeLog, uptr kMaxSizeLog,
+ uptr kMaxNumCachedHintT, uptr kMaxBytesCachedLog>
+class SizeClassMap {
+ static const uptr kMinSize = 1 << kMinSizeLog;
+ static const uptr kMidSize = 1 << kMidSizeLog;
+ static const uptr kMidClass = kMidSize / kMinSize;
+ static const uptr S = kNumBits - 1;
+ static const uptr M = (1 << S) - 1;
+
+ public:
+ // kMaxNumCachedHintT is a power of two. It serves as a hint
+ // for the size of TransferBatch, the actual size could be a bit smaller.
+ static const uptr kMaxNumCachedHint = kMaxNumCachedHintT;
+ COMPILER_CHECK((kMaxNumCachedHint & (kMaxNumCachedHint - 1)) == 0);
+
+ static const uptr kMaxSize = 1UL << kMaxSizeLog;
+ static const uptr kNumClasses =
+ kMidClass + ((kMaxSizeLog - kMidSizeLog) << S) + 1 + 1;
+ static const uptr kLargestClassID = kNumClasses - 2;
+ static const uptr kBatchClassID = kNumClasses - 1;
+ COMPILER_CHECK(kNumClasses >= 16 && kNumClasses <= 256);
+ static const uptr kNumClassesRounded =
+ kNumClasses <= 32 ? 32 :
+ kNumClasses <= 64 ? 64 :
+ kNumClasses <= 128 ? 128 : 256;
+
+ static uptr Size(uptr class_id) {
+ // Estimate the result for kBatchClassID because this class does not know
+ // the exact size of TransferBatch. It's OK since we are using the actual
+ // sizeof(TransferBatch) where it matters.
+ if (UNLIKELY(class_id == kBatchClassID))
+ return kMaxNumCachedHint * sizeof(uptr);
+ if (class_id <= kMidClass)
+ return kMinSize * class_id;
+ class_id -= kMidClass;
+ uptr t = kMidSize << (class_id >> S);
+ return t + (t >> S) * (class_id & M);
+ }
+
+ static uptr ClassID(uptr size) {
+ if (UNLIKELY(size > kMaxSize))
+ return 0;
+ if (size <= kMidSize)
+ return (size + kMinSize - 1) >> kMinSizeLog;
+ const uptr l = MostSignificantSetBitIndex(size);
+ const uptr hbits = (size >> (l - S)) & M;
+ const uptr lbits = size & ((1U << (l - S)) - 1);
+ const uptr l1 = l - kMidSizeLog;
+ return kMidClass + (l1 << S) + hbits + (lbits > 0);
+ }
+
+ static uptr MaxCachedHint(uptr size) {
+ DCHECK_LE(size, kMaxSize);
+ if (UNLIKELY(size == 0))
+ return 0;
+ uptr n;
+ // Force a 32-bit division if the template parameters allow for it.
+ if (kMaxBytesCachedLog > 31 || kMaxSizeLog > 31)
+ n = (1UL << kMaxBytesCachedLog) / size;
+ else
+ n = (1U << kMaxBytesCachedLog) / static_cast<u32>(size);
+ return Max<uptr>(1U, Min(kMaxNumCachedHint, n));
+ }
+
+ static void Print() {
+ uptr prev_s = 0;
+ uptr total_cached = 0;
+ for (uptr i = 0; i < kNumClasses; i++) {
+ uptr s = Size(i);
+ if (s >= kMidSize / 2 && (s & (s - 1)) == 0)
+ Printf("\n");
+ uptr d = s - prev_s;
+ uptr p = prev_s ? (d * 100 / prev_s) : 0;
+ uptr l = s ? MostSignificantSetBitIndex(s) : 0;
+ uptr cached = MaxCachedHint(s) * s;
+ if (i == kBatchClassID)
+ d = p = l = 0;
+ Printf(
+ "c%02zu => s: %zu diff: +%zu %02zu%% l %zu cached: %zu %zu; id %zu\n",
+ i, Size(i), d, p, l, MaxCachedHint(s), cached, ClassID(s));
+ total_cached += cached;
+ prev_s = s;
+ }
+ Printf("Total cached: %zu\n", total_cached);
+ }
+
+ static void Validate() {
+ for (uptr c = 1; c < kNumClasses; c++) {
+ // Printf("Validate: c%zd\n", c);
+ uptr s = Size(c);
+ CHECK_NE(s, 0U);
+ if (c == kBatchClassID)
+ continue;
+ CHECK_EQ(ClassID(s), c);
+ if (c < kLargestClassID)
+ CHECK_EQ(ClassID(s + 1), c + 1);
+ CHECK_EQ(ClassID(s - 1), c);
+ CHECK_GT(Size(c), Size(c - 1));
+ }
+ CHECK_EQ(ClassID(kMaxSize + 1), 0);
+
+ for (uptr s = 1; s <= kMaxSize; s++) {
+ uptr c = ClassID(s);
+ // Printf("s%zd => c%zd\n", s, c);
+ CHECK_LT(c, kNumClasses);
+ CHECK_GE(Size(c), s);
+ if (c > 0)
+ CHECK_LT(Size(c - 1), s);
+ }
+ }
+};
+
+typedef SizeClassMap<3, 4, 8, 17, 128, 16> DefaultSizeClassMap;
+typedef SizeClassMap<3, 4, 8, 17, 64, 14> CompactSizeClassMap;
+typedef SizeClassMap<2, 5, 9, 16, 64, 14> VeryCompactSizeClassMap;
+
+// The following SizeClassMap only holds a way small number of cached entries,
+// allowing for denser per-class arrays, smaller memory footprint and usually
+// better performances in threaded environments.
+typedef SizeClassMap<3, 4, 8, 17, 8, 10> DenseSizeClassMap;
+// Similar to VeryCompact map above, this one has a small number of different
+// size classes, and also reduced thread-local caches.
+typedef SizeClassMap<2, 5, 9, 16, 8, 10> VeryDenseSizeClassMap;
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_stats.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_stats.h
new file mode 100644
index 00000000000..6f14e3863c3
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_allocator_stats.h
@@ -0,0 +1,106 @@
+//===-- sanitizer_allocator_stats.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Part of the Sanitizer Allocator.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_ALLOCATOR_H
+#error This file must be included inside sanitizer_allocator.h
+#endif
+
+// Memory allocator statistics
+enum AllocatorStat {
+ AllocatorStatAllocated,
+ AllocatorStatMapped,
+ AllocatorStatCount
+};
+
+typedef uptr AllocatorStatCounters[AllocatorStatCount];
+
+// Per-thread stats, live in per-thread cache.
+class AllocatorStats {
+ public:
+ void Init() {
+ internal_memset(this, 0, sizeof(*this));
+ }
+ void InitLinkerInitialized() {}
+
+ void Add(AllocatorStat i, uptr v) {
+ v += atomic_load(&stats_[i], memory_order_relaxed);
+ atomic_store(&stats_[i], v, memory_order_relaxed);
+ }
+
+ void Sub(AllocatorStat i, uptr v) {
+ v = atomic_load(&stats_[i], memory_order_relaxed) - v;
+ atomic_store(&stats_[i], v, memory_order_relaxed);
+ }
+
+ void Set(AllocatorStat i, uptr v) {
+ atomic_store(&stats_[i], v, memory_order_relaxed);
+ }
+
+ uptr Get(AllocatorStat i) const {
+ return atomic_load(&stats_[i], memory_order_relaxed);
+ }
+
+ private:
+ friend class AllocatorGlobalStats;
+ AllocatorStats *next_;
+ AllocatorStats *prev_;
+ atomic_uintptr_t stats_[AllocatorStatCount];
+};
+
+// Global stats, used for aggregation and querying.
+class AllocatorGlobalStats : public AllocatorStats {
+ public:
+ void InitLinkerInitialized() {
+ next_ = this;
+ prev_ = this;
+ }
+ void Init() {
+ internal_memset(this, 0, sizeof(*this));
+ InitLinkerInitialized();
+ }
+
+ void Register(AllocatorStats *s) {
+ SpinMutexLock l(&mu_);
+ s->next_ = next_;
+ s->prev_ = this;
+ next_->prev_ = s;
+ next_ = s;
+ }
+
+ void Unregister(AllocatorStats *s) {
+ SpinMutexLock l(&mu_);
+ s->prev_->next_ = s->next_;
+ s->next_->prev_ = s->prev_;
+ for (int i = 0; i < AllocatorStatCount; i++)
+ Add(AllocatorStat(i), s->Get(AllocatorStat(i)));
+ }
+
+ void Get(AllocatorStatCounters s) const {
+ internal_memset(s, 0, AllocatorStatCount * sizeof(uptr));
+ SpinMutexLock l(&mu_);
+ const AllocatorStats *stats = this;
+ for (;;) {
+ for (int i = 0; i < AllocatorStatCount; i++)
+ s[i] += stats->Get(AllocatorStat(i));
+ stats = stats->next_;
+ if (stats == this)
+ break;
+ }
+ // All stats must be non-negative.
+ for (int i = 0; i < AllocatorStatCount; i++)
+ s[i] = ((sptr)s[i]) >= 0 ? s[i] : 0;
+ }
+
+ private:
+ mutable StaticSpinMutex mu_;
+};
+
+
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_asm.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_asm.h
new file mode 100644
index 00000000000..9ebba91da73
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_asm.h
@@ -0,0 +1,75 @@
+//===-- sanitizer_asm.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Various support for assembler.
+//
+//===----------------------------------------------------------------------===//
+
+// Some toolchains do not support .cfi asm directives, so we have to hide
+// them inside macros.
+#if defined(__clang__) || \
+ (defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM))
+ // GCC defined __GCC_HAVE_DWARF2_CFI_ASM if it supports CFI.
+ // Clang seems to support CFI by default (or not?).
+ // We need two versions of macros: for inline asm and standalone asm files.
+# define CFI_INL_ADJUST_CFA_OFFSET(n) ".cfi_adjust_cfa_offset " #n ";"
+
+# define CFI_STARTPROC .cfi_startproc
+# define CFI_ENDPROC .cfi_endproc
+# define CFI_ADJUST_CFA_OFFSET(n) .cfi_adjust_cfa_offset n
+# define CFI_DEF_CFA_OFFSET(n) .cfi_def_cfa_offset n
+# define CFI_REL_OFFSET(reg, n) .cfi_rel_offset reg, n
+# define CFI_OFFSET(reg, n) .cfi_offset reg, n
+# define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
+# define CFI_DEF_CFA(reg, n) .cfi_def_cfa reg, n
+# define CFI_RESTORE(reg) .cfi_restore reg
+
+#else // No CFI
+# define CFI_INL_ADJUST_CFA_OFFSET(n)
+# define CFI_STARTPROC
+# define CFI_ENDPROC
+# define CFI_ADJUST_CFA_OFFSET(n)
+# define CFI_DEF_CFA_OFFSET(n)
+# define CFI_REL_OFFSET(reg, n)
+# define CFI_OFFSET(reg, n)
+# define CFI_DEF_CFA_REGISTER(reg)
+# define CFI_DEF_CFA(reg, n)
+# define CFI_RESTORE(reg)
+#endif
+
+#if !defined(__APPLE__)
+# define ASM_HIDDEN(symbol) .hidden symbol
+# define ASM_TYPE_FUNCTION(symbol) .type symbol, %function
+# define ASM_SIZE(symbol) .size symbol, .-symbol
+# define ASM_SYMBOL(symbol) symbol
+# define ASM_SYMBOL_INTERCEPTOR(symbol) symbol
+# define ASM_WRAPPER_NAME(symbol) __interceptor_##symbol
+#else
+# define ASM_HIDDEN(symbol)
+# define ASM_TYPE_FUNCTION(symbol)
+# define ASM_SIZE(symbol)
+# define ASM_SYMBOL(symbol) _##symbol
+# define ASM_SYMBOL_INTERCEPTOR(symbol) _wrap_##symbol
+# define ASM_WRAPPER_NAME(symbol) __interceptor_##symbol
+#endif
+
+#if defined(__ELF__) && (defined(__GNU__) || defined(__FreeBSD__) || \
+ defined(__Fuchsia__) || defined(__linux__))
+// clang-format off
+#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
+// clang-format on
+#else
+#define NO_EXEC_STACK_DIRECTIVE
+#endif
+
+#if (defined(__x86_64__) || defined(__i386__)) && defined(__has_include) && __has_include(<cet.h>)
+#include <cet.h>
+#endif
+#ifndef _CET_ENDBR
+#define _CET_ENDBR
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic.h
new file mode 100644
index 00000000000..46f06957228
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic.h
@@ -0,0 +1,86 @@
+//===-- sanitizer_atomic.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ATOMIC_H
+#define SANITIZER_ATOMIC_H
+
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+enum memory_order {
+ memory_order_relaxed = 1 << 0,
+ memory_order_consume = 1 << 1,
+ memory_order_acquire = 1 << 2,
+ memory_order_release = 1 << 3,
+ memory_order_acq_rel = 1 << 4,
+ memory_order_seq_cst = 1 << 5
+};
+
+struct atomic_uint8_t {
+ typedef u8 Type;
+ volatile Type val_dont_use;
+};
+
+struct atomic_uint16_t {
+ typedef u16 Type;
+ volatile Type val_dont_use;
+};
+
+struct atomic_sint32_t {
+ typedef s32 Type;
+ volatile Type val_dont_use;
+};
+
+struct atomic_uint32_t {
+ typedef u32 Type;
+ volatile Type val_dont_use;
+};
+
+struct atomic_uint64_t {
+ typedef u64 Type;
+ // On 32-bit platforms u64 is not necessary aligned on 8 bytes.
+ volatile ALIGNED(8) Type val_dont_use;
+};
+
+struct atomic_uintptr_t {
+ typedef uptr Type;
+ volatile Type val_dont_use;
+};
+
+} // namespace __sanitizer
+
+#if defined(__clang__) || defined(__GNUC__)
+# include "sanitizer_atomic_clang.h"
+#elif defined(_MSC_VER)
+# include "sanitizer_atomic_msvc.h"
+#else
+# error "Unsupported compiler"
+#endif
+
+namespace __sanitizer {
+
+// Clutter-reducing helpers.
+
+template<typename T>
+inline typename T::Type atomic_load_relaxed(const volatile T *a) {
+ return atomic_load(a, memory_order_relaxed);
+}
+
+template<typename T>
+inline void atomic_store_relaxed(volatile T *a, typename T::Type v) {
+ atomic_store(a, v, memory_order_relaxed);
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_ATOMIC_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang.h
new file mode 100644
index 00000000000..4318d64d16c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang.h
@@ -0,0 +1,104 @@
+//===-- sanitizer_atomic_clang.h --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+// Not intended for direct inclusion. Include sanitizer_atomic.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ATOMIC_CLANG_H
+#define SANITIZER_ATOMIC_CLANG_H
+
+#if defined(__i386__) || defined(__x86_64__)
+# include "sanitizer_atomic_clang_x86.h"
+#else
+# include "sanitizer_atomic_clang_other.h"
+#endif
+
+namespace __sanitizer {
+
+// We would like to just use compiler builtin atomic operations
+// for loads and stores, but they are mostly broken in clang:
+// - they lead to vastly inefficient code generation
+// (http://llvm.org/bugs/show_bug.cgi?id=17281)
+// - 64-bit atomic operations are not implemented on x86_32
+// (http://llvm.org/bugs/show_bug.cgi?id=15034)
+// - they are not implemented on ARM
+// error: undefined reference to '__atomic_load_4'
+
+// See http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
+// for mappings of the memory model to different processors.
+
+inline void atomic_signal_fence(memory_order) {
+ __asm__ __volatile__("" ::: "memory");
+}
+
+inline void atomic_thread_fence(memory_order) {
+ __sync_synchronize();
+}
+
+template<typename T>
+inline typename T::Type atomic_fetch_add(volatile T *a,
+ typename T::Type v, memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+ return __sync_fetch_and_add(&a->val_dont_use, v);
+}
+
+template<typename T>
+inline typename T::Type atomic_fetch_sub(volatile T *a,
+ typename T::Type v, memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+ return __sync_fetch_and_add(&a->val_dont_use, -v);
+}
+
+template<typename T>
+inline typename T::Type atomic_exchange(volatile T *a,
+ typename T::Type v, memory_order mo) {
+ DCHECK(!((uptr)a % sizeof(*a)));
+ if (mo & (memory_order_release | memory_order_acq_rel | memory_order_seq_cst))
+ __sync_synchronize();
+ v = __sync_lock_test_and_set(&a->val_dont_use, v);
+ if (mo == memory_order_seq_cst)
+ __sync_synchronize();
+ return v;
+}
+
+template <typename T>
+inline bool atomic_compare_exchange_strong(volatile T *a, typename T::Type *cmp,
+ typename T::Type xchg,
+ memory_order mo) {
+ // Transitioned from __sync_val_compare_and_swap to support targets like
+ // SPARC V8 that cannot inline atomic cmpxchg. __atomic_compare_exchange
+ // can then be resolved from libatomic. __ATOMIC_SEQ_CST is used to best
+ // match the __sync builtin memory order.
+ return __atomic_compare_exchange(&a->val_dont_use, cmp, &xchg, false,
+ __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+
+template<typename T>
+inline bool atomic_compare_exchange_weak(volatile T *a,
+ typename T::Type *cmp,
+ typename T::Type xchg,
+ memory_order mo) {
+ return atomic_compare_exchange_strong(a, cmp, xchg, mo);
+}
+
+} // namespace __sanitizer
+
+// This include provides explicit template instantiations for atomic_uint64_t
+// on MIPS32, which does not directly support 8 byte atomics. It has to
+// proceed the template definitions above.
+#if defined(_MIPS_SIM) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
+# include "sanitizer_atomic_clang_mips.h"
+#endif
+
+#undef ATOMIC_ORDER
+
+#endif // SANITIZER_ATOMIC_CLANG_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang_mips.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang_mips.h
new file mode 100644
index 00000000000..f3d3052e5b7
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang_mips.h
@@ -0,0 +1,117 @@
+//===-- sanitizer_atomic_clang_mips.h ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+// Not intended for direct inclusion. Include sanitizer_atomic.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ATOMIC_CLANG_MIPS_H
+#define SANITIZER_ATOMIC_CLANG_MIPS_H
+
+namespace __sanitizer {
+
+// MIPS32 does not support atomics > 4 bytes. To address this lack of
+// functionality, the sanitizer library provides helper methods which use an
+// internal spin lock mechanism to emulate atomic operations when the size is
+// 8 bytes.
+static void __spin_lock(volatile int *lock) {
+ while (__sync_lock_test_and_set(lock, 1))
+ while (*lock) {
+ }
+}
+
+static void __spin_unlock(volatile int *lock) { __sync_lock_release(lock); }
+
+// Make sure the lock is on its own cache line to prevent false sharing.
+// Put it inside a struct that is aligned and padded to the typical MIPS
+// cacheline which is 32 bytes.
+static struct {
+ int lock;
+ char pad[32 - sizeof(int)];
+} __attribute__((aligned(32))) lock = {0, {0}};
+
+template <>
+inline atomic_uint64_t::Type atomic_fetch_add(volatile atomic_uint64_t *ptr,
+ atomic_uint64_t::Type val,
+ memory_order mo) {
+ DCHECK(mo &
+ (memory_order_relaxed | memory_order_release | memory_order_seq_cst));
+ DCHECK(!((uptr)ptr % sizeof(*ptr)));
+
+ atomic_uint64_t::Type ret;
+
+ __spin_lock(&lock.lock);
+ ret = *(const_cast<atomic_uint64_t::Type volatile *>(&ptr->val_dont_use));
+ ptr->val_dont_use = ret + val;
+ __spin_unlock(&lock.lock);
+
+ return ret;
+}
+
+template <>
+inline atomic_uint64_t::Type atomic_fetch_sub(volatile atomic_uint64_t *ptr,
+ atomic_uint64_t::Type val,
+ memory_order mo) {
+ return atomic_fetch_add(ptr, -val, mo);
+}
+
+template <>
+inline bool atomic_compare_exchange_strong(volatile atomic_uint64_t *ptr,
+ atomic_uint64_t::Type *cmp,
+ atomic_uint64_t::Type xchg,
+ memory_order mo) {
+ DCHECK(mo &
+ (memory_order_relaxed | memory_order_release | memory_order_seq_cst));
+ DCHECK(!((uptr)ptr % sizeof(*ptr)));
+
+ typedef atomic_uint64_t::Type Type;
+ Type cmpv = *cmp;
+ Type prev;
+ bool ret = false;
+
+ __spin_lock(&lock.lock);
+ prev = *(const_cast<Type volatile *>(&ptr->val_dont_use));
+ if (prev == cmpv) {
+ ret = true;
+ ptr->val_dont_use = xchg;
+ }
+ __spin_unlock(&lock.lock);
+
+ return ret;
+}
+
+template <>
+inline atomic_uint64_t::Type atomic_load(const volatile atomic_uint64_t *ptr,
+ memory_order mo) {
+ DCHECK(mo &
+ (memory_order_relaxed | memory_order_release | memory_order_seq_cst));
+ DCHECK(!((uptr)ptr % sizeof(*ptr)));
+
+ atomic_uint64_t::Type zero = 0;
+ volatile atomic_uint64_t *Newptr =
+ const_cast<volatile atomic_uint64_t *>(ptr);
+ return atomic_fetch_add(Newptr, zero, mo);
+}
+
+template <>
+inline void atomic_store(volatile atomic_uint64_t *ptr, atomic_uint64_t::Type v,
+ memory_order mo) {
+ DCHECK(mo &
+ (memory_order_relaxed | memory_order_release | memory_order_seq_cst));
+ DCHECK(!((uptr)ptr % sizeof(*ptr)));
+
+ __spin_lock(&lock.lock);
+ ptr->val_dont_use = v;
+ __spin_unlock(&lock.lock);
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_ATOMIC_CLANG_MIPS_H
+
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang_other.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang_other.h
new file mode 100644
index 00000000000..4a39889e534
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang_other.h
@@ -0,0 +1,85 @@
+//===-- sanitizer_atomic_clang_other.h --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+// Not intended for direct inclusion. Include sanitizer_atomic.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ATOMIC_CLANG_OTHER_H
+#define SANITIZER_ATOMIC_CLANG_OTHER_H
+
+namespace __sanitizer {
+
+
+inline void proc_yield(int cnt) {
+ __asm__ __volatile__("" ::: "memory");
+}
+
+template<typename T>
+inline typename T::Type atomic_load(
+ const volatile T *a, memory_order mo) {
+ DCHECK(mo & (memory_order_relaxed | memory_order_consume
+ | memory_order_acquire | memory_order_seq_cst));
+ DCHECK(!((uptr)a % sizeof(*a)));
+ typename T::Type v;
+
+ if (sizeof(*a) < 8 || sizeof(void*) == 8) {
+ // Assume that aligned loads are atomic.
+ if (mo == memory_order_relaxed) {
+ v = a->val_dont_use;
+ } else if (mo == memory_order_consume) {
+ // Assume that processor respects data dependencies
+ // (and that compiler won't break them).
+ __asm__ __volatile__("" ::: "memory");
+ v = a->val_dont_use;
+ __asm__ __volatile__("" ::: "memory");
+ } else if (mo == memory_order_acquire) {
+ __asm__ __volatile__("" ::: "memory");
+ v = a->val_dont_use;
+ __sync_synchronize();
+ } else { // seq_cst
+ // E.g. on POWER we need a hw fence even before the store.
+ __sync_synchronize();
+ v = a->val_dont_use;
+ __sync_synchronize();
+ }
+ } else {
+ __atomic_load(const_cast<typename T::Type volatile *>(&a->val_dont_use), &v,
+ __ATOMIC_SEQ_CST);
+ }
+ return v;
+}
+
+template<typename T>
+inline void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
+ DCHECK(mo & (memory_order_relaxed | memory_order_release
+ | memory_order_seq_cst));
+ DCHECK(!((uptr)a % sizeof(*a)));
+
+ if (sizeof(*a) < 8 || sizeof(void*) == 8) {
+ // Assume that aligned loads are atomic.
+ if (mo == memory_order_relaxed) {
+ a->val_dont_use = v;
+ } else if (mo == memory_order_release) {
+ __sync_synchronize();
+ a->val_dont_use = v;
+ __asm__ __volatile__("" ::: "memory");
+ } else { // seq_cst
+ __sync_synchronize();
+ a->val_dont_use = v;
+ __sync_synchronize();
+ }
+ } else {
+ __atomic_store(&a->val_dont_use, &v, __ATOMIC_SEQ_CST);
+ }
+}
+
+} // namespace __sanitizer
+
+#endif // #ifndef SANITIZER_ATOMIC_CLANG_OTHER_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang_x86.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang_x86.h
new file mode 100644
index 00000000000..51597b49274
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_clang_x86.h
@@ -0,0 +1,113 @@
+//===-- sanitizer_atomic_clang_x86.h ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+// Not intended for direct inclusion. Include sanitizer_atomic.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ATOMIC_CLANG_X86_H
+#define SANITIZER_ATOMIC_CLANG_X86_H
+
+namespace __sanitizer {
+
+inline void proc_yield(int cnt) {
+ __asm__ __volatile__("" ::: "memory");
+ for (int i = 0; i < cnt; i++)
+ __asm__ __volatile__("pause");
+ __asm__ __volatile__("" ::: "memory");
+}
+
+template<typename T>
+inline typename T::Type atomic_load(
+ const volatile T *a, memory_order mo) {
+ DCHECK(mo & (memory_order_relaxed | memory_order_consume
+ | memory_order_acquire | memory_order_seq_cst));
+ DCHECK(!((uptr)a % sizeof(*a)));
+ typename T::Type v;
+
+ if (sizeof(*a) < 8 || sizeof(void*) == 8) {
+ // Assume that aligned loads are atomic.
+ if (mo == memory_order_relaxed) {
+ v = a->val_dont_use;
+ } else if (mo == memory_order_consume) {
+ // Assume that processor respects data dependencies
+ // (and that compiler won't break them).
+ __asm__ __volatile__("" ::: "memory");
+ v = a->val_dont_use;
+ __asm__ __volatile__("" ::: "memory");
+ } else if (mo == memory_order_acquire) {
+ __asm__ __volatile__("" ::: "memory");
+ v = a->val_dont_use;
+ // On x86 loads are implicitly acquire.
+ __asm__ __volatile__("" ::: "memory");
+ } else { // seq_cst
+ // On x86 plain MOV is enough for seq_cst store.
+ __asm__ __volatile__("" ::: "memory");
+ v = a->val_dont_use;
+ __asm__ __volatile__("" ::: "memory");
+ }
+ } else {
+ // 64-bit load on 32-bit platform.
+ __asm__ __volatile__(
+ "movq %1, %%mm0;" // Use mmx reg for 64-bit atomic moves
+ "movq %%mm0, %0;" // (ptr could be read-only)
+ "emms;" // Empty mmx state/Reset FP regs
+ : "=m" (v)
+ : "m" (a->val_dont_use)
+ : // mark the mmx registers as clobbered
+#ifdef __MMX__
+ "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
+#endif // #ifdef __MMX__
+ "memory");
+ }
+ return v;
+}
+
+template<typename T>
+inline void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
+ DCHECK(mo & (memory_order_relaxed | memory_order_release
+ | memory_order_seq_cst));
+ DCHECK(!((uptr)a % sizeof(*a)));
+
+ if (sizeof(*a) < 8 || sizeof(void*) == 8) {
+ // Assume that aligned loads are atomic.
+ if (mo == memory_order_relaxed) {
+ a->val_dont_use = v;
+ } else if (mo == memory_order_release) {
+ // On x86 stores are implicitly release.
+ __asm__ __volatile__("" ::: "memory");
+ a->val_dont_use = v;
+ __asm__ __volatile__("" ::: "memory");
+ } else { // seq_cst
+ // On x86 stores are implicitly release.
+ __asm__ __volatile__("" ::: "memory");
+ a->val_dont_use = v;
+ __sync_synchronize();
+ }
+ } else {
+ // 64-bit store on 32-bit platform.
+ __asm__ __volatile__(
+ "movq %1, %%mm0;" // Use mmx reg for 64-bit atomic moves
+ "movq %%mm0, %0;"
+ "emms;" // Empty mmx state/Reset FP regs
+ : "=m" (a->val_dont_use)
+ : "m" (v)
+ : // mark the mmx registers as clobbered
+#ifdef __MMX__
+ "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
+#endif // #ifdef __MMX__
+ "memory");
+ if (mo == memory_order_seq_cst)
+ __sync_synchronize();
+ }
+}
+
+} // namespace __sanitizer
+
+#endif // #ifndef SANITIZER_ATOMIC_CLANG_X86_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h
new file mode 100644
index 00000000000..31317adcdfc
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_atomic_msvc.h
@@ -0,0 +1,256 @@
+//===-- sanitizer_atomic_msvc.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+// Not intended for direct inclusion. Include sanitizer_atomic.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ATOMIC_MSVC_H
+#define SANITIZER_ATOMIC_MSVC_H
+
+extern "C" void _ReadWriteBarrier();
+#pragma intrinsic(_ReadWriteBarrier)
+extern "C" void _mm_mfence();
+#pragma intrinsic(_mm_mfence)
+extern "C" void _mm_pause();
+#pragma intrinsic(_mm_pause)
+extern "C" char _InterlockedExchange8(char volatile *Addend, char Value);
+#pragma intrinsic(_InterlockedExchange8)
+extern "C" short _InterlockedExchange16(short volatile *Addend, short Value);
+#pragma intrinsic(_InterlockedExchange16)
+extern "C" long _InterlockedExchange(long volatile *Addend, long Value);
+#pragma intrinsic(_InterlockedExchange)
+extern "C" long _InterlockedExchangeAdd(long volatile *Addend, long Value);
+#pragma intrinsic(_InterlockedExchangeAdd)
+extern "C" char _InterlockedCompareExchange8(char volatile *Destination,
+ char Exchange, char Comparand);
+#pragma intrinsic(_InterlockedCompareExchange8)
+extern "C" short _InterlockedCompareExchange16(short volatile *Destination,
+ short Exchange, short Comparand);
+#pragma intrinsic(_InterlockedCompareExchange16)
+extern "C" long long _InterlockedCompareExchange64(
+ long long volatile *Destination, long long Exchange, long long Comparand);
+#pragma intrinsic(_InterlockedCompareExchange64)
+extern "C" void *_InterlockedCompareExchangePointer(
+ void *volatile *Destination,
+ void *Exchange, void *Comparand);
+#pragma intrinsic(_InterlockedCompareExchangePointer)
+extern "C" long __cdecl _InterlockedCompareExchange(long volatile *Destination,
+ long Exchange,
+ long Comparand);
+#pragma intrinsic(_InterlockedCompareExchange)
+
+#ifdef _WIN64
+extern "C" long long _InterlockedExchangeAdd64(long long volatile *Addend,
+ long long Value);
+#pragma intrinsic(_InterlockedExchangeAdd64)
+#endif
+
+namespace __sanitizer {
+
+inline void atomic_signal_fence(memory_order) {
+ _ReadWriteBarrier();
+}
+
+inline void atomic_thread_fence(memory_order) {
+ _mm_mfence();
+}
+
+inline void proc_yield(int cnt) {
+ for (int i = 0; i < cnt; i++)
+ _mm_pause();
+}
+
+template<typename T>
+inline typename T::Type atomic_load(
+ const volatile T *a, memory_order mo) {
+ DCHECK(mo & (memory_order_relaxed | memory_order_consume
+ | memory_order_acquire | memory_order_seq_cst));
+ DCHECK(!((uptr)a % sizeof(*a)));
+ typename T::Type v;
+ // FIXME(dvyukov): 64-bit load is not atomic on 32-bits.
+ if (mo == memory_order_relaxed) {
+ v = a->val_dont_use;
+ } else {
+ atomic_signal_fence(memory_order_seq_cst);
+ v = a->val_dont_use;
+ atomic_signal_fence(memory_order_seq_cst);
+ }
+ return v;
+}
+
+template<typename T>
+inline void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
+ DCHECK(mo & (memory_order_relaxed | memory_order_release
+ | memory_order_seq_cst));
+ DCHECK(!((uptr)a % sizeof(*a)));
+ // FIXME(dvyukov): 64-bit store is not atomic on 32-bits.
+ if (mo == memory_order_relaxed) {
+ a->val_dont_use = v;
+ } else {
+ atomic_signal_fence(memory_order_seq_cst);
+ a->val_dont_use = v;
+ atomic_signal_fence(memory_order_seq_cst);
+ }
+ if (mo == memory_order_seq_cst)
+ atomic_thread_fence(memory_order_seq_cst);
+}
+
+inline u32 atomic_fetch_add(volatile atomic_uint32_t *a,
+ u32 v, memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+ return (u32)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
+ (long)v);
+}
+
+inline uptr atomic_fetch_add(volatile atomic_uintptr_t *a,
+ uptr v, memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+#ifdef _WIN64
+ return (uptr)_InterlockedExchangeAdd64((volatile long long *)&a->val_dont_use,
+ (long long)v);
+#else
+ return (uptr)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
+ (long)v);
+#endif
+}
+
+inline u32 atomic_fetch_sub(volatile atomic_uint32_t *a,
+ u32 v, memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+ return (u32)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
+ -(long)v);
+}
+
+inline uptr atomic_fetch_sub(volatile atomic_uintptr_t *a,
+ uptr v, memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+#ifdef _WIN64
+ return (uptr)_InterlockedExchangeAdd64((volatile long long *)&a->val_dont_use,
+ -(long long)v);
+#else
+ return (uptr)_InterlockedExchangeAdd((volatile long *)&a->val_dont_use,
+ -(long)v);
+#endif
+}
+
+inline u8 atomic_exchange(volatile atomic_uint8_t *a,
+ u8 v, memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+ return (u8)_InterlockedExchange8((volatile char*)&a->val_dont_use, v);
+}
+
+inline u16 atomic_exchange(volatile atomic_uint16_t *a,
+ u16 v, memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+ return (u16)_InterlockedExchange16((volatile short*)&a->val_dont_use, v);
+}
+
+inline u32 atomic_exchange(volatile atomic_uint32_t *a,
+ u32 v, memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+ return (u32)_InterlockedExchange((volatile long*)&a->val_dont_use, v);
+}
+
+inline bool atomic_compare_exchange_strong(volatile atomic_uint8_t *a,
+ u8 *cmp,
+ u8 xchgv,
+ memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+ u8 cmpv = *cmp;
+#ifdef _WIN64
+ u8 prev = (u8)_InterlockedCompareExchange8(
+ (volatile char*)&a->val_dont_use, (char)xchgv, (char)cmpv);
+#else
+ u8 prev;
+ __asm {
+ mov al, cmpv
+ mov ecx, a
+ mov dl, xchgv
+ lock cmpxchg [ecx], dl
+ mov prev, al
+ }
+#endif
+ if (prev == cmpv)
+ return true;
+ *cmp = prev;
+ return false;
+}
+
+inline bool atomic_compare_exchange_strong(volatile atomic_uintptr_t *a,
+ uptr *cmp,
+ uptr xchg,
+ memory_order mo) {
+ uptr cmpv = *cmp;
+ uptr prev = (uptr)_InterlockedCompareExchangePointer(
+ (void*volatile*)&a->val_dont_use, (void*)xchg, (void*)cmpv);
+ if (prev == cmpv)
+ return true;
+ *cmp = prev;
+ return false;
+}
+
+inline bool atomic_compare_exchange_strong(volatile atomic_uint16_t *a,
+ u16 *cmp,
+ u16 xchg,
+ memory_order mo) {
+ u16 cmpv = *cmp;
+ u16 prev = (u16)_InterlockedCompareExchange16(
+ (volatile short*)&a->val_dont_use, (short)xchg, (short)cmpv);
+ if (prev == cmpv)
+ return true;
+ *cmp = prev;
+ return false;
+}
+
+inline bool atomic_compare_exchange_strong(volatile atomic_uint32_t *a,
+ u32 *cmp,
+ u32 xchg,
+ memory_order mo) {
+ u32 cmpv = *cmp;
+ u32 prev = (u32)_InterlockedCompareExchange(
+ (volatile long*)&a->val_dont_use, (long)xchg, (long)cmpv);
+ if (prev == cmpv)
+ return true;
+ *cmp = prev;
+ return false;
+}
+
+inline bool atomic_compare_exchange_strong(volatile atomic_uint64_t *a,
+ u64 *cmp,
+ u64 xchg,
+ memory_order mo) {
+ u64 cmpv = *cmp;
+ u64 prev = (u64)_InterlockedCompareExchange64(
+ (volatile long long*)&a->val_dont_use, (long long)xchg, (long long)cmpv);
+ if (prev == cmpv)
+ return true;
+ *cmp = prev;
+ return false;
+}
+
+template<typename T>
+inline bool atomic_compare_exchange_weak(volatile T *a,
+ typename T::Type *cmp,
+ typename T::Type xchg,
+ memory_order mo) {
+ return atomic_compare_exchange_strong(a, cmp, xchg, mo);
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_ATOMIC_CLANG_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_bitvector.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_bitvector.h
new file mode 100644
index 00000000000..07a59ab11c4
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_bitvector.h
@@ -0,0 +1,350 @@
+//===-- sanitizer_bitvector.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Specializer BitVector implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_BITVECTOR_H
+#define SANITIZER_BITVECTOR_H
+
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+
+// Fixed size bit vector based on a single basic integer.
+template <class basic_int_t = uptr>
+class BasicBitVector {
+ public:
+ enum SizeEnum : uptr { kSize = sizeof(basic_int_t) * 8 };
+
+ uptr size() const { return kSize; }
+ // No CTOR.
+ void clear() { bits_ = 0; }
+ void setAll() { bits_ = ~(basic_int_t)0; }
+ bool empty() const { return bits_ == 0; }
+
+ // Returns true if the bit has changed from 0 to 1.
+ bool setBit(uptr idx) {
+ basic_int_t old = bits_;
+ bits_ |= mask(idx);
+ return bits_ != old;
+ }
+
+ // Returns true if the bit has changed from 1 to 0.
+ bool clearBit(uptr idx) {
+ basic_int_t old = bits_;
+ bits_ &= ~mask(idx);
+ return bits_ != old;
+ }
+
+ bool getBit(uptr idx) const { return (bits_ & mask(idx)) != 0; }
+
+ uptr getAndClearFirstOne() {
+ CHECK(!empty());
+ uptr idx = LeastSignificantSetBitIndex(bits_);
+ clearBit(idx);
+ return idx;
+ }
+
+ // Do "this |= v" and return whether new bits have been added.
+ bool setUnion(const BasicBitVector &v) {
+ basic_int_t old = bits_;
+ bits_ |= v.bits_;
+ return bits_ != old;
+ }
+
+ // Do "this &= v" and return whether any bits have been removed.
+ bool setIntersection(const BasicBitVector &v) {
+ basic_int_t old = bits_;
+ bits_ &= v.bits_;
+ return bits_ != old;
+ }
+
+ // Do "this &= ~v" and return whether any bits have been removed.
+ bool setDifference(const BasicBitVector &v) {
+ basic_int_t old = bits_;
+ bits_ &= ~v.bits_;
+ return bits_ != old;
+ }
+
+ void copyFrom(const BasicBitVector &v) { bits_ = v.bits_; }
+
+ // Returns true if 'this' intersects with 'v'.
+ bool intersectsWith(const BasicBitVector &v) const {
+ return (bits_ & v.bits_) != 0;
+ }
+
+ // for (BasicBitVector<>::Iterator it(bv); it.hasNext();) {
+ // uptr idx = it.next();
+ // use(idx);
+ // }
+ class Iterator {
+ public:
+ Iterator() { }
+ explicit Iterator(const BasicBitVector &bv) : bv_(bv) {}
+ bool hasNext() const { return !bv_.empty(); }
+ uptr next() { return bv_.getAndClearFirstOne(); }
+ void clear() { bv_.clear(); }
+ private:
+ BasicBitVector bv_;
+ };
+
+ private:
+ basic_int_t mask(uptr idx) const {
+ CHECK_LT(idx, size());
+ return (basic_int_t)1UL << idx;
+ }
+ basic_int_t bits_;
+};
+
+// Fixed size bit vector of (kLevel1Size*BV::kSize**2) bits.
+// The implementation is optimized for better performance on
+// sparse bit vectors, i.e. the those with few set bits.
+template <uptr kLevel1Size = 1, class BV = BasicBitVector<> >
+class TwoLevelBitVector {
+ // This is essentially a 2-level bit vector.
+ // Set bit in the first level BV indicates that there are set bits
+ // in the corresponding BV of the second level.
+ // This structure allows O(kLevel1Size) time for clear() and empty(),
+ // as well fast handling of sparse BVs.
+ public:
+ enum SizeEnum : uptr { kSize = BV::kSize * BV::kSize * kLevel1Size };
+ // No CTOR.
+
+ uptr size() const { return kSize; }
+
+ void clear() {
+ for (uptr i = 0; i < kLevel1Size; i++)
+ l1_[i].clear();
+ }
+
+ void setAll() {
+ for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
+ l1_[i0].setAll();
+ for (uptr i1 = 0; i1 < BV::kSize; i1++)
+ l2_[i0][i1].setAll();
+ }
+ }
+
+ bool empty() const {
+ for (uptr i = 0; i < kLevel1Size; i++)
+ if (!l1_[i].empty())
+ return false;
+ return true;
+ }
+
+ // Returns true if the bit has changed from 0 to 1.
+ bool setBit(uptr idx) {
+ check(idx);
+ uptr i0 = idx0(idx);
+ uptr i1 = idx1(idx);
+ uptr i2 = idx2(idx);
+ if (!l1_[i0].getBit(i1)) {
+ l1_[i0].setBit(i1);
+ l2_[i0][i1].clear();
+ }
+ bool res = l2_[i0][i1].setBit(i2);
+ // Printf("%s: %zd => %zd %zd %zd; %d\n", __func__,
+ // idx, i0, i1, i2, res);
+ return res;
+ }
+
+ bool clearBit(uptr idx) {
+ check(idx);
+ uptr i0 = idx0(idx);
+ uptr i1 = idx1(idx);
+ uptr i2 = idx2(idx);
+ bool res = false;
+ if (l1_[i0].getBit(i1)) {
+ res = l2_[i0][i1].clearBit(i2);
+ if (l2_[i0][i1].empty())
+ l1_[i0].clearBit(i1);
+ }
+ return res;
+ }
+
+ bool getBit(uptr idx) const {
+ check(idx);
+ uptr i0 = idx0(idx);
+ uptr i1 = idx1(idx);
+ uptr i2 = idx2(idx);
+ // Printf("%s: %zd => %zd %zd %zd\n", __func__, idx, i0, i1, i2);
+ return l1_[i0].getBit(i1) && l2_[i0][i1].getBit(i2);
+ }
+
+ uptr getAndClearFirstOne() {
+ for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
+ if (l1_[i0].empty()) continue;
+ uptr i1 = l1_[i0].getAndClearFirstOne();
+ uptr i2 = l2_[i0][i1].getAndClearFirstOne();
+ if (!l2_[i0][i1].empty())
+ l1_[i0].setBit(i1);
+ uptr res = i0 * BV::kSize * BV::kSize + i1 * BV::kSize + i2;
+ // Printf("getAndClearFirstOne: %zd %zd %zd => %zd\n", i0, i1, i2, res);
+ return res;
+ }
+ CHECK(0);
+ return 0;
+ }
+
+ // Do "this |= v" and return whether new bits have been added.
+ bool setUnion(const TwoLevelBitVector &v) {
+ bool res = false;
+ for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
+ BV t = v.l1_[i0];
+ while (!t.empty()) {
+ uptr i1 = t.getAndClearFirstOne();
+ if (l1_[i0].setBit(i1))
+ l2_[i0][i1].clear();
+ if (l2_[i0][i1].setUnion(v.l2_[i0][i1]))
+ res = true;
+ }
+ }
+ return res;
+ }
+
+ // Do "this &= v" and return whether any bits have been removed.
+ bool setIntersection(const TwoLevelBitVector &v) {
+ bool res = false;
+ for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
+ if (l1_[i0].setIntersection(v.l1_[i0]))
+ res = true;
+ if (!l1_[i0].empty()) {
+ BV t = l1_[i0];
+ while (!t.empty()) {
+ uptr i1 = t.getAndClearFirstOne();
+ if (l2_[i0][i1].setIntersection(v.l2_[i0][i1]))
+ res = true;
+ if (l2_[i0][i1].empty())
+ l1_[i0].clearBit(i1);
+ }
+ }
+ }
+ return res;
+ }
+
+ // Do "this &= ~v" and return whether any bits have been removed.
+ bool setDifference(const TwoLevelBitVector &v) {
+ bool res = false;
+ for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
+ BV t = l1_[i0];
+ t.setIntersection(v.l1_[i0]);
+ while (!t.empty()) {
+ uptr i1 = t.getAndClearFirstOne();
+ if (l2_[i0][i1].setDifference(v.l2_[i0][i1]))
+ res = true;
+ if (l2_[i0][i1].empty())
+ l1_[i0].clearBit(i1);
+ }
+ }
+ return res;
+ }
+
+ void copyFrom(const TwoLevelBitVector &v) {
+ clear();
+ setUnion(v);
+ }
+
+ // Returns true if 'this' intersects with 'v'.
+ bool intersectsWith(const TwoLevelBitVector &v) const {
+ for (uptr i0 = 0; i0 < kLevel1Size; i0++) {
+ BV t = l1_[i0];
+ t.setIntersection(v.l1_[i0]);
+ while (!t.empty()) {
+ uptr i1 = t.getAndClearFirstOne();
+ if (!v.l1_[i0].getBit(i1)) continue;
+ if (l2_[i0][i1].intersectsWith(v.l2_[i0][i1]))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // for (TwoLevelBitVector<>::Iterator it(bv); it.hasNext();) {
+ // uptr idx = it.next();
+ // use(idx);
+ // }
+ class Iterator {
+ public:
+ Iterator() { }
+ explicit Iterator(const TwoLevelBitVector &bv) : bv_(bv), i0_(0), i1_(0) {
+ it1_.clear();
+ it2_.clear();
+ }
+
+ bool hasNext() const {
+ if (it1_.hasNext()) return true;
+ for (uptr i = i0_; i < kLevel1Size; i++)
+ if (!bv_.l1_[i].empty()) return true;
+ return false;
+ }
+
+ uptr next() {
+ // Printf("++++: %zd %zd; %d %d; size %zd\n", i0_, i1_, it1_.hasNext(),
+ // it2_.hasNext(), kSize);
+ if (!it1_.hasNext() && !it2_.hasNext()) {
+ for (; i0_ < kLevel1Size; i0_++) {
+ if (bv_.l1_[i0_].empty()) continue;
+ it1_ = typename BV::Iterator(bv_.l1_[i0_]);
+ // Printf("+i0: %zd %zd; %d %d; size %zd\n", i0_, i1_, it1_.hasNext(),
+ // it2_.hasNext(), kSize);
+ break;
+ }
+ }
+ if (!it2_.hasNext()) {
+ CHECK(it1_.hasNext());
+ i1_ = it1_.next();
+ it2_ = typename BV::Iterator(bv_.l2_[i0_][i1_]);
+ // Printf("++i1: %zd %zd; %d %d; size %zd\n", i0_, i1_, it1_.hasNext(),
+ // it2_.hasNext(), kSize);
+ }
+ CHECK(it2_.hasNext());
+ uptr i2 = it2_.next();
+ uptr res = i0_ * BV::kSize * BV::kSize + i1_ * BV::kSize + i2;
+ // Printf("+ret: %zd %zd; %d %d; size %zd; res: %zd\n", i0_, i1_,
+ // it1_.hasNext(), it2_.hasNext(), kSize, res);
+ if (!it1_.hasNext() && !it2_.hasNext())
+ i0_++;
+ return res;
+ }
+
+ private:
+ const TwoLevelBitVector &bv_;
+ uptr i0_, i1_;
+ typename BV::Iterator it1_, it2_;
+ };
+
+ private:
+ void check(uptr idx) const { CHECK_LE(idx, size()); }
+
+ uptr idx0(uptr idx) const {
+ uptr res = idx / (BV::kSize * BV::kSize);
+ CHECK_LE(res, kLevel1Size);
+ return res;
+ }
+
+ uptr idx1(uptr idx) const {
+ uptr res = (idx / BV::kSize) % BV::kSize;
+ CHECK_LE(res, BV::kSize);
+ return res;
+ }
+
+ uptr idx2(uptr idx) const {
+ uptr res = idx % BV::kSize;
+ CHECK_LE(res, BV::kSize);
+ return res;
+ }
+
+ BV l1_[kLevel1Size];
+ BV l2_[kLevel1Size][BV::kSize];
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_BITVECTOR_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_bvgraph.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_bvgraph.h
new file mode 100644
index 00000000000..e7249055bee
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_bvgraph.h
@@ -0,0 +1,164 @@
+//===-- sanitizer_bvgraph.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer runtime.
+// BVGraph -- a directed graph.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_BVGRAPH_H
+#define SANITIZER_BVGRAPH_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_bitvector.h"
+
+namespace __sanitizer {
+
+// Directed graph of fixed size implemented as an array of bit vectors.
+// Not thread-safe, all accesses should be protected by an external lock.
+template<class BV>
+class BVGraph {
+ public:
+ enum SizeEnum : uptr { kSize = BV::kSize };
+ uptr size() const { return kSize; }
+ // No CTOR.
+ void clear() {
+ for (uptr i = 0; i < size(); i++)
+ v[i].clear();
+ }
+
+ bool empty() const {
+ for (uptr i = 0; i < size(); i++)
+ if (!v[i].empty())
+ return false;
+ return true;
+ }
+
+ // Returns true if a new edge was added.
+ bool addEdge(uptr from, uptr to) {
+ check(from, to);
+ return v[from].setBit(to);
+ }
+
+ // Returns true if at least one new edge was added.
+ uptr addEdges(const BV &from, uptr to, uptr added_edges[],
+ uptr max_added_edges) {
+ uptr res = 0;
+ t1.copyFrom(from);
+ while (!t1.empty()) {
+ uptr node = t1.getAndClearFirstOne();
+ if (v[node].setBit(to))
+ if (res < max_added_edges)
+ added_edges[res++] = node;
+ }
+ return res;
+ }
+
+ // *EXPERIMENTAL*
+ // Returns true if an edge from=>to exist.
+ // This function does not use any global state except for 'this' itself,
+ // and thus can be called from different threads w/o locking.
+ // This would be racy.
+ // FIXME: investigate how much we can prove about this race being "benign".
+ bool hasEdge(uptr from, uptr to) { return v[from].getBit(to); }
+
+ // Returns true if the edge from=>to was removed.
+ bool removeEdge(uptr from, uptr to) {
+ return v[from].clearBit(to);
+ }
+
+ // Returns true if at least one edge *=>to was removed.
+ bool removeEdgesTo(const BV &to) {
+ bool res = 0;
+ for (uptr from = 0; from < size(); from++) {
+ if (v[from].setDifference(to))
+ res = true;
+ }
+ return res;
+ }
+
+ // Returns true if at least one edge from=>* was removed.
+ bool removeEdgesFrom(const BV &from) {
+ bool res = false;
+ t1.copyFrom(from);
+ while (!t1.empty()) {
+ uptr idx = t1.getAndClearFirstOne();
+ if (!v[idx].empty()) {
+ v[idx].clear();
+ res = true;
+ }
+ }
+ return res;
+ }
+
+ void removeEdgesFrom(uptr from) {
+ return v[from].clear();
+ }
+
+ bool hasEdge(uptr from, uptr to) const {
+ check(from, to);
+ return v[from].getBit(to);
+ }
+
+ // Returns true if there is a path from the node 'from'
+ // to any of the nodes in 'targets'.
+ bool isReachable(uptr from, const BV &targets) {
+ BV &to_visit = t1,
+ &visited = t2;
+ to_visit.copyFrom(v[from]);
+ visited.clear();
+ visited.setBit(from);
+ while (!to_visit.empty()) {
+ uptr idx = to_visit.getAndClearFirstOne();
+ if (visited.setBit(idx))
+ to_visit.setUnion(v[idx]);
+ }
+ return targets.intersectsWith(visited);
+ }
+
+ // Finds a path from 'from' to one of the nodes in 'target',
+ // stores up to 'path_size' items of the path into 'path',
+ // returns the path length, or 0 if there is no path of size 'path_size'.
+ uptr findPath(uptr from, const BV &targets, uptr *path, uptr path_size) {
+ if (path_size == 0)
+ return 0;
+ path[0] = from;
+ if (targets.getBit(from))
+ return 1;
+ // The function is recursive, so we don't want to create BV on stack.
+ // Instead of a getAndClearFirstOne loop we use the slower iterator.
+ for (typename BV::Iterator it(v[from]); it.hasNext(); ) {
+ uptr idx = it.next();
+ if (uptr res = findPath(idx, targets, path + 1, path_size - 1))
+ return res + 1;
+ }
+ return 0;
+ }
+
+ // Same as findPath, but finds a shortest path.
+ uptr findShortestPath(uptr from, const BV &targets, uptr *path,
+ uptr path_size) {
+ for (uptr p = 1; p <= path_size; p++)
+ if (findPath(from, targets, path, p) == p)
+ return p;
+ return 0;
+ }
+
+ private:
+ void check(uptr idx1, uptr idx2) const {
+ CHECK_LT(idx1, size());
+ CHECK_LT(idx2, size());
+ }
+ BV v[kSize];
+ // Keep temporary vectors here since we can not create large objects on stack.
+ BV t1, t2;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_BVGRAPH_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_chained_origin_depot.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_chained_origin_depot.cpp
new file mode 100644
index 00000000000..e0e2bd01069
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_chained_origin_depot.cpp
@@ -0,0 +1,148 @@
+//===-- sanitizer_chained_origin_depot.cpp --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// A storage for chained origins.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_chained_origin_depot.h"
+
+#include "sanitizer_stackdepotbase.h"
+
+namespace __sanitizer {
+
+namespace {
+struct ChainedOriginDepotDesc {
+ u32 here_id;
+ u32 prev_id;
+};
+
+struct ChainedOriginDepotNode {
+ using hash_type = u32;
+ u32 link;
+ u32 here_id;
+ u32 prev_id;
+
+ typedef ChainedOriginDepotDesc args_type;
+
+ bool eq(hash_type hash, const args_type &args) const;
+
+ static uptr allocated() { return 0; }
+
+ static hash_type hash(const args_type &args);
+
+ static bool is_valid(const args_type &args);
+
+ void store(u32 id, const args_type &args, hash_type other_hash);
+
+ args_type load(u32 id) const;
+
+ struct Handle {
+ const ChainedOriginDepotNode *node_ = nullptr;
+ u32 id_ = 0;
+ Handle(const ChainedOriginDepotNode *node, u32 id) : node_(node), id_(id) {}
+ bool valid() const { return node_; }
+ u32 id() const { return id_; }
+ int here_id() const { return node_->here_id; }
+ int prev_id() const { return node_->prev_id; }
+ };
+
+ static Handle get_handle(u32 id);
+
+ typedef Handle handle_type;
+};
+
+} // namespace
+
+static StackDepotBase<ChainedOriginDepotNode, 4, 20> depot;
+
+bool ChainedOriginDepotNode::eq(hash_type hash, const args_type &args) const {
+ return here_id == args.here_id && prev_id == args.prev_id;
+}
+
+/* This is murmur2 hash for the 64->32 bit case.
+ It does not behave all that well because the keys have a very biased
+ distribution (I've seen 7-element buckets with the table only 14% full).
+
+ here_id is built of
+ * (1 bits) Reserved, zero.
+ * (8 bits) Part id = bits 13..20 of the hash value of here_id's key.
+ * (23 bits) Sequential number (each part has each own sequence).
+
+ prev_id has either the same distribution as here_id (but with 3:8:21)
+ split, or one of two reserved values (-1) or (-2). Either case can
+ dominate depending on the workload.
+*/
+ChainedOriginDepotNode::hash_type ChainedOriginDepotNode::hash(
+ const args_type &args) {
+ const u32 m = 0x5bd1e995;
+ const u32 seed = 0x9747b28c;
+ const u32 r = 24;
+ u32 h = seed;
+ u32 k = args.here_id;
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+ h *= m;
+ h ^= k;
+
+ k = args.prev_id;
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+ h *= m;
+ h ^= k;
+
+ h ^= h >> 13;
+ h *= m;
+ h ^= h >> 15;
+ return h;
+}
+
+bool ChainedOriginDepotNode::is_valid(const args_type &args) { return true; }
+
+void ChainedOriginDepotNode::store(u32 id, const args_type &args,
+ hash_type other_hash) {
+ here_id = args.here_id;
+ prev_id = args.prev_id;
+}
+
+ChainedOriginDepotNode::args_type ChainedOriginDepotNode::load(u32 id) const {
+ args_type ret = {here_id, prev_id};
+ return ret;
+}
+
+ChainedOriginDepotNode::Handle ChainedOriginDepotNode::get_handle(u32 id) {
+ return Handle(&depot.nodes[id], id);
+}
+
+ChainedOriginDepot::ChainedOriginDepot() {}
+
+StackDepotStats ChainedOriginDepot::GetStats() const {
+ return depot.GetStats();
+}
+
+bool ChainedOriginDepot::Put(u32 here_id, u32 prev_id, u32 *new_id) {
+ ChainedOriginDepotDesc desc = {here_id, prev_id};
+ bool inserted;
+ *new_id = depot.Put(desc, &inserted);
+ return inserted;
+}
+
+u32 ChainedOriginDepot::Get(u32 id, u32 *other) {
+ ChainedOriginDepotDesc desc = depot.Get(id);
+ *other = desc.prev_id;
+ return desc.here_id;
+}
+
+void ChainedOriginDepot::LockAll() { depot.LockAll(); }
+
+void ChainedOriginDepot::UnlockAll() { depot.UnlockAll(); }
+
+void ChainedOriginDepot::TestOnlyUnmap() { depot.TestOnlyUnmap(); }
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_chained_origin_depot.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_chained_origin_depot.h
new file mode 100644
index 00000000000..f9f192b6857
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_chained_origin_depot.h
@@ -0,0 +1,46 @@
+//===-- sanitizer_chained_origin_depot.h ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// A storage for chained origins.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_CHAINED_ORIGIN_DEPOT_H
+#define SANITIZER_CHAINED_ORIGIN_DEPOT_H
+
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+
+class ChainedOriginDepot {
+ public:
+ ChainedOriginDepot();
+
+ // Gets the statistic of the origin chain storage.
+ StackDepotStats GetStats() const;
+
+ // Stores a chain with StackDepot ID here_id and previous chain ID prev_id.
+ // If successful, returns true and the new chain id new_id.
+ // If the same element already exists, returns false and sets new_id to the
+ // existing ID.
+ bool Put(u32 here_id, u32 prev_id, u32 *new_id);
+
+ // Retrieves the stored StackDepot ID for the given origin ID.
+ u32 Get(u32 id, u32 *other);
+
+ void LockAll();
+ void UnlockAll();
+ void TestOnlyUnmap();
+
+ private:
+ ChainedOriginDepot(const ChainedOriginDepot &) = delete;
+ void operator=(const ChainedOriginDepot &) = delete;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_CHAINED_ORIGIN_DEPOT_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common.cpp
new file mode 100644
index 00000000000..82236453157
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common.cpp
@@ -0,0 +1,401 @@
+//===-- sanitizer_common.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common.h"
+
+#include "sanitizer_allocator_interface.h"
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_atomic.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_interface_internal.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_placement_new.h"
+
+namespace __sanitizer {
+
+const char *SanitizerToolName = "SanitizerTool";
+
+atomic_uint32_t current_verbosity;
+uptr PageSizeCached;
+u32 NumberOfCPUsCached;
+
+// PID of the tracer task in StopTheWorld. It shares the address space with the
+// main process, but has a different PID and thus requires special handling.
+uptr stoptheworld_tracer_pid = 0;
+// Cached pid of parent process - if the parent process dies, we want to keep
+// writing to the same log file.
+uptr stoptheworld_tracer_ppid = 0;
+
+void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type,
+ const char *mmap_type, error_t err,
+ bool raw_report) {
+ static int recursion_count;
+ if (raw_report || recursion_count) {
+ // If raw report is requested or we went into recursion just die. The
+ // Report() and CHECK calls below may call mmap recursively and fail.
+ RawWrite("ERROR: Failed to mmap\n");
+ Die();
+ }
+ recursion_count++;
+ if (ErrorIsOOM(err)) {
+ ERROR_OOM("failed to %s 0x%zx (%zd) bytes of %s (error code: %d)\n",
+ mmap_type, size, size, mem_type, err);
+ } else {
+ Report(
+ "ERROR: %s failed to "
+ "%s 0x%zx (%zd) bytes of %s (error code: %d)\n",
+ SanitizerToolName, mmap_type, size, size, mem_type, err);
+ }
+#if !SANITIZER_GO
+ DumpProcessMap();
+#endif
+ UNREACHABLE("unable to mmap");
+}
+
+typedef bool UptrComparisonFunction(const uptr &a, const uptr &b);
+typedef bool U32ComparisonFunction(const u32 &a, const u32 &b);
+
+const char *StripPathPrefix(const char *filepath,
+ const char *strip_path_prefix) {
+ if (!filepath) return nullptr;
+ if (!strip_path_prefix) return filepath;
+ const char *res = filepath;
+ if (const char *pos = internal_strstr(filepath, strip_path_prefix))
+ res = pos + internal_strlen(strip_path_prefix);
+ if (res[0] == '.' && res[1] == '/')
+ res += 2;
+ return res;
+}
+
+const char *StripModuleName(const char *module) {
+ if (!module)
+ return nullptr;
+ if (SANITIZER_WINDOWS) {
+ // On Windows, both slash and backslash are possible.
+ // Pick the one that goes last.
+ if (const char *bslash_pos = internal_strrchr(module, '\\'))
+ return StripModuleName(bslash_pos + 1);
+ }
+ if (const char *slash_pos = internal_strrchr(module, '/')) {
+ return slash_pos + 1;
+ }
+ return module;
+}
+
+void ReportErrorSummary(const char *error_message, const char *alt_tool_name) {
+ if (!common_flags()->print_summary)
+ return;
+ InternalScopedString buff;
+ buff.append("SUMMARY: %s: %s",
+ alt_tool_name ? alt_tool_name : SanitizerToolName, error_message);
+ __sanitizer_report_error_summary(buff.data());
+}
+
+// Removes the ANSI escape sequences from the input string (in-place).
+void RemoveANSIEscapeSequencesFromString(char *str) {
+ if (!str)
+ return;
+
+ // We are going to remove the escape sequences in place.
+ char *s = str;
+ char *z = str;
+ while (*s != '\0') {
+ CHECK_GE(s, z);
+ // Skip over ANSI escape sequences with pointer 's'.
+ if (*s == '\033' && *(s + 1) == '[') {
+ s = internal_strchrnul(s, 'm');
+ if (*s == '\0') {
+ break;
+ }
+ s++;
+ continue;
+ }
+ // 's' now points at a character we want to keep. Copy over the buffer
+ // content if the escape sequence has been perviously skipped andadvance
+ // both pointers.
+ if (s != z)
+ *z = *s;
+
+ // If we have not seen an escape sequence, just advance both pointers.
+ z++;
+ s++;
+ }
+
+ // Null terminate the string.
+ *z = '\0';
+}
+
+void LoadedModule::set(const char *module_name, uptr base_address) {
+ clear();
+ full_name_ = internal_strdup(module_name);
+ base_address_ = base_address;
+}
+
+void LoadedModule::set(const char *module_name, uptr base_address,
+ ModuleArch arch, u8 uuid[kModuleUUIDSize],
+ bool instrumented) {
+ set(module_name, base_address);
+ arch_ = arch;
+ internal_memcpy(uuid_, uuid, sizeof(uuid_));
+ uuid_size_ = kModuleUUIDSize;
+ instrumented_ = instrumented;
+}
+
+void LoadedModule::setUuid(const char *uuid, uptr size) {
+ if (size > kModuleUUIDSize)
+ size = kModuleUUIDSize;
+ internal_memcpy(uuid_, uuid, size);
+ uuid_size_ = size;
+}
+
+void LoadedModule::clear() {
+ InternalFree(full_name_);
+ base_address_ = 0;
+ max_address_ = 0;
+ full_name_ = nullptr;
+ arch_ = kModuleArchUnknown;
+ internal_memset(uuid_, 0, kModuleUUIDSize);
+ instrumented_ = false;
+ while (!ranges_.empty()) {
+ AddressRange *r = ranges_.front();
+ ranges_.pop_front();
+ InternalFree(r);
+ }
+}
+
+void LoadedModule::addAddressRange(uptr beg, uptr end, bool executable,
+ bool writable, const char *name) {
+ void *mem = InternalAlloc(sizeof(AddressRange));
+ AddressRange *r =
+ new(mem) AddressRange(beg, end, executable, writable, name);
+ ranges_.push_back(r);
+ max_address_ = Max(max_address_, end);
+}
+
+bool LoadedModule::containsAddress(uptr address) const {
+ for (const AddressRange &r : ranges()) {
+ if (r.beg <= address && address < r.end)
+ return true;
+ }
+ return false;
+}
+
+static atomic_uintptr_t g_total_mmaped;
+
+void IncreaseTotalMmap(uptr size) {
+ if (!common_flags()->mmap_limit_mb) return;
+ uptr total_mmaped =
+ atomic_fetch_add(&g_total_mmaped, size, memory_order_relaxed) + size;
+ // Since for now mmap_limit_mb is not a user-facing flag, just kill
+ // a program. Use RAW_CHECK to avoid extra mmaps in reporting.
+ RAW_CHECK((total_mmaped >> 20) < common_flags()->mmap_limit_mb);
+}
+
+void DecreaseTotalMmap(uptr size) {
+ if (!common_flags()->mmap_limit_mb) return;
+ atomic_fetch_sub(&g_total_mmaped, size, memory_order_relaxed);
+}
+
+bool TemplateMatch(const char *templ, const char *str) {
+ if ((!str) || str[0] == 0)
+ return false;
+ bool start = false;
+ if (templ && templ[0] == '^') {
+ start = true;
+ templ++;
+ }
+ bool asterisk = false;
+ while (templ && templ[0]) {
+ if (templ[0] == '*') {
+ templ++;
+ start = false;
+ asterisk = true;
+ continue;
+ }
+ if (templ[0] == '$')
+ return str[0] == 0 || asterisk;
+ if (str[0] == 0)
+ return false;
+ char *tpos = (char*)internal_strchr(templ, '*');
+ char *tpos1 = (char*)internal_strchr(templ, '$');
+ if ((!tpos) || (tpos1 && tpos1 < tpos))
+ tpos = tpos1;
+ if (tpos)
+ tpos[0] = 0;
+ const char *str0 = str;
+ const char *spos = internal_strstr(str, templ);
+ str = spos + internal_strlen(templ);
+ templ = tpos;
+ if (tpos)
+ tpos[0] = tpos == tpos1 ? '$' : '*';
+ if (!spos)
+ return false;
+ if (start && spos != str0)
+ return false;
+ start = false;
+ asterisk = false;
+ }
+ return true;
+}
+
+static char binary_name_cache_str[kMaxPathLength];
+static char process_name_cache_str[kMaxPathLength];
+
+const char *GetProcessName() {
+ return process_name_cache_str;
+}
+
+static uptr ReadProcessName(/*out*/ char *buf, uptr buf_len) {
+ ReadLongProcessName(buf, buf_len);
+ char *s = const_cast<char *>(StripModuleName(buf));
+ uptr len = internal_strlen(s);
+ if (s != buf) {
+ internal_memmove(buf, s, len);
+ buf[len] = '\0';
+ }
+ return len;
+}
+
+void UpdateProcessName() {
+ ReadProcessName(process_name_cache_str, sizeof(process_name_cache_str));
+}
+
+// Call once to make sure that binary_name_cache_str is initialized
+void CacheBinaryName() {
+ if (binary_name_cache_str[0] != '\0')
+ return;
+ ReadBinaryName(binary_name_cache_str, sizeof(binary_name_cache_str));
+ ReadProcessName(process_name_cache_str, sizeof(process_name_cache_str));
+}
+
+uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len) {
+ CacheBinaryName();
+ uptr name_len = internal_strlen(binary_name_cache_str);
+ name_len = (name_len < buf_len - 1) ? name_len : buf_len - 1;
+ if (buf_len == 0)
+ return 0;
+ internal_memcpy(buf, binary_name_cache_str, name_len);
+ buf[name_len] = '\0';
+ return name_len;
+}
+
+uptr ReadBinaryDir(/*out*/ char *buf, uptr buf_len) {
+ ReadBinaryNameCached(buf, buf_len);
+ const char *exec_name_pos = StripModuleName(buf);
+ uptr name_len = exec_name_pos - buf;
+ buf[name_len] = '\0';
+ return name_len;
+}
+
+#if !SANITIZER_GO
+void PrintCmdline() {
+ char **argv = GetArgv();
+ if (!argv) return;
+ Printf("\nCommand: ");
+ for (uptr i = 0; argv[i]; ++i)
+ Printf("%s ", argv[i]);
+ Printf("\n\n");
+}
+#endif
+
+// Malloc hooks.
+static const int kMaxMallocFreeHooks = 5;
+struct MallocFreeHook {
+ void (*malloc_hook)(const void *, uptr);
+ void (*free_hook)(const void *);
+};
+
+static MallocFreeHook MFHooks[kMaxMallocFreeHooks];
+
+void RunMallocHooks(void *ptr, uptr size) {
+ __sanitizer_malloc_hook(ptr, size);
+ for (int i = 0; i < kMaxMallocFreeHooks; i++) {
+ auto hook = MFHooks[i].malloc_hook;
+ if (!hook)
+ break;
+ hook(ptr, size);
+ }
+}
+
+void RunFreeHooks(void *ptr) {
+ __sanitizer_free_hook(ptr);
+ for (int i = 0; i < kMaxMallocFreeHooks; i++) {
+ auto hook = MFHooks[i].free_hook;
+ if (!hook)
+ break;
+ hook(ptr);
+ }
+}
+
+static int InstallMallocFreeHooks(void (*malloc_hook)(const void *, uptr),
+ void (*free_hook)(const void *)) {
+ if (!malloc_hook || !free_hook) return 0;
+ for (int i = 0; i < kMaxMallocFreeHooks; i++) {
+ if (MFHooks[i].malloc_hook == nullptr) {
+ MFHooks[i].malloc_hook = malloc_hook;
+ MFHooks[i].free_hook = free_hook;
+ return i + 1;
+ }
+ }
+ return 0;
+}
+
+void internal_sleep(unsigned seconds) {
+ internal_usleep((u64)seconds * 1000 * 1000);
+}
+void SleepForSeconds(unsigned seconds) {
+ internal_usleep((u64)seconds * 1000 * 1000);
+}
+void SleepForMillis(unsigned millis) { internal_usleep((u64)millis * 1000); }
+
+void WaitForDebugger(unsigned seconds, const char *label) {
+ if (seconds) {
+ Report("Sleeping for %u second(s) %s\n", seconds, label);
+ SleepForSeconds(seconds);
+ }
+}
+
+} // namespace __sanitizer
+
+using namespace __sanitizer;
+
+extern "C" {
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_report_error_summary,
+ const char *error_summary) {
+ Printf("%s\n", error_summary);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __sanitizer_acquire_crash_state() {
+ static atomic_uint8_t in_crash_state = {};
+ return !atomic_exchange(&in_crash_state, 1, memory_order_relaxed);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __sanitizer_install_malloc_and_free_hooks(void (*malloc_hook)(const void *,
+ uptr),
+ void (*free_hook)(const void *)) {
+ return InstallMallocFreeHooks(malloc_hook, free_hook);
+}
+
+// Provide default (no-op) implementation of malloc hooks.
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_malloc_hook, void *ptr,
+ uptr size) {
+ (void)ptr;
+ (void)size;
+}
+
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_free_hook, void *ptr) {
+ (void)ptr;
+}
+
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common.h
new file mode 100644
index 00000000000..b462e388c23
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common.h
@@ -0,0 +1,1100 @@
+//===-- sanitizer_common.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between run-time libraries of sanitizers.
+//
+// It declares common functions and classes that are used in both runtimes.
+// Implementation of some functions are provided in sanitizer_common, while
+// others must be defined by run-time library itself.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_COMMON_H
+#define SANITIZER_COMMON_H
+
+#include "sanitizer_flags.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_list.h"
+#include "sanitizer_mutex.h"
+
+#if defined(_MSC_VER) && !defined(__clang__)
+extern "C" void _ReadWriteBarrier();
+#pragma intrinsic(_ReadWriteBarrier)
+#endif
+
+namespace __sanitizer {
+
+struct AddressInfo;
+struct BufferedStackTrace;
+struct SignalContext;
+struct StackTrace;
+
+// Constants.
+const uptr kWordSize = SANITIZER_WORDSIZE / 8;
+const uptr kWordSizeInBits = 8 * kWordSize;
+
+const uptr kCacheLineSize = SANITIZER_CACHE_LINE_SIZE;
+
+const uptr kMaxPathLength = 4096;
+
+const uptr kMaxThreadStackSize = 1 << 30; // 1Gb
+
+const uptr kErrorMessageBufferSize = 1 << 16;
+
+// Denotes fake PC values that come from JIT/JAVA/etc.
+// For such PC values __tsan_symbolize_external_ex() will be called.
+const u64 kExternalPCBit = 1ULL << 60;
+
+extern const char *SanitizerToolName; // Can be changed by the tool.
+
+extern atomic_uint32_t current_verbosity;
+inline void SetVerbosity(int verbosity) {
+ atomic_store(&current_verbosity, verbosity, memory_order_relaxed);
+}
+inline int Verbosity() {
+ return atomic_load(&current_verbosity, memory_order_relaxed);
+}
+
+#if SANITIZER_ANDROID
+inline uptr GetPageSize() {
+// Android post-M sysconf(_SC_PAGESIZE) crashes if called from .preinit_array.
+ return 4096;
+}
+inline uptr GetPageSizeCached() {
+ return 4096;
+}
+#else
+uptr GetPageSize();
+extern uptr PageSizeCached;
+inline uptr GetPageSizeCached() {
+ if (!PageSizeCached)
+ PageSizeCached = GetPageSize();
+ return PageSizeCached;
+}
+#endif
+uptr GetMmapGranularity();
+uptr GetMaxVirtualAddress();
+uptr GetMaxUserVirtualAddress();
+// Threads
+tid_t GetTid();
+int TgKill(pid_t pid, tid_t tid, int sig);
+uptr GetThreadSelf();
+void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
+ uptr *stack_bottom);
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+ uptr *tls_addr, uptr *tls_size);
+
+// Memory management
+void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false);
+inline void *MmapOrDieQuietly(uptr size, const char *mem_type) {
+ return MmapOrDie(size, mem_type, /*raw_report*/ true);
+}
+void UnmapOrDie(void *addr, uptr size);
+// Behaves just like MmapOrDie, but tolerates out of memory condition, in that
+// case returns nullptr.
+void *MmapOrDieOnFatalError(uptr size, const char *mem_type);
+bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr)
+ WARN_UNUSED_RESULT;
+bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size,
+ const char *name = nullptr) WARN_UNUSED_RESULT;
+void *MmapNoReserveOrDie(uptr size, const char *mem_type);
+void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name = nullptr);
+// Behaves just like MmapFixedOrDie, but tolerates out of memory condition, in
+// that case returns nullptr.
+void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size,
+ const char *name = nullptr);
+void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name = nullptr);
+void *MmapNoAccess(uptr size);
+// Map aligned chunk of address space; size and alignment are powers of two.
+// Dies on all but out of memory errors, in the latter case returns nullptr.
+void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
+ const char *mem_type);
+// Disallow access to a memory range. Use MmapFixedNoAccess to allocate an
+// unaccessible memory.
+bool MprotectNoAccess(uptr addr, uptr size);
+bool MprotectReadOnly(uptr addr, uptr size);
+
+void MprotectMallocZones(void *addr, int prot);
+
+#if SANITIZER_WINDOWS
+// Zero previously mmap'd memory. Currently used only on Windows.
+bool ZeroMmapFixedRegion(uptr fixed_addr, uptr size) WARN_UNUSED_RESULT;
+#endif
+
+#if SANITIZER_LINUX
+// Unmap memory. Currently only used on Linux.
+void UnmapFromTo(uptr from, uptr to);
+#endif
+
+// Maps shadow_size_bytes of shadow memory and returns shadow address. It will
+// be aligned to the mmap granularity * 2^shadow_scale, or to
+// 2^min_shadow_base_alignment if that is larger. The returned address will
+// have max(2^min_shadow_base_alignment, mmap granularity) on the left, and
+// shadow_size_bytes bytes on the right, which on linux is mapped no access.
+// The high_mem_end may be updated if the original shadow size doesn't fit.
+uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
+ uptr min_shadow_base_alignment, uptr &high_mem_end);
+
+// Let S = max(shadow_size, num_aliases * alias_size, ring_buffer_size).
+// Reserves 2*S bytes of address space to the right of the returned address and
+// ring_buffer_size bytes to the left. The returned address is aligned to 2*S.
+// Also creates num_aliases regions of accessible memory starting at offset S
+// from the returned address. Each region has size alias_size and is backed by
+// the same physical memory.
+uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,
+ uptr num_aliases, uptr ring_buffer_size);
+
+// Reserve memory range [beg, end]. If madvise_shadow is true then apply
+// madvise (e.g. hugepages, core dumping) requested by options.
+void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name,
+ bool madvise_shadow = true);
+
+// Protect size bytes of memory starting at addr. Also try to protect
+// several pages at the start of the address space as specified by
+// zero_base_shadow_start, at most up to the size or zero_base_max_shadow_start.
+void ProtectGap(uptr addr, uptr size, uptr zero_base_shadow_start,
+ uptr zero_base_max_shadow_start);
+
+// Find an available address space.
+uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
+ uptr *largest_gap_found, uptr *max_occupied_addr);
+
+// Used to check if we can map shadow memory to a fixed location.
+bool MemoryRangeIsAvailable(uptr range_start, uptr range_end);
+// Releases memory pages entirely within the [beg, end] address range. Noop if
+// the provided range does not contain at least one entire page.
+void ReleaseMemoryPagesToOS(uptr beg, uptr end);
+void IncreaseTotalMmap(uptr size);
+void DecreaseTotalMmap(uptr size);
+uptr GetRSS();
+void SetShadowRegionHugePageMode(uptr addr, uptr length);
+bool DontDumpShadowMemory(uptr addr, uptr length);
+// Check if the built VMA size matches the runtime one.
+void CheckVMASize();
+void RunMallocHooks(void *ptr, uptr size);
+void RunFreeHooks(void *ptr);
+
+class ReservedAddressRange {
+ public:
+ uptr Init(uptr size, const char *name = nullptr, uptr fixed_addr = 0);
+ uptr InitAligned(uptr size, uptr align, const char *name = nullptr);
+ uptr Map(uptr fixed_addr, uptr size, const char *name = nullptr);
+ uptr MapOrDie(uptr fixed_addr, uptr size, const char *name = nullptr);
+ void Unmap(uptr addr, uptr size);
+ void *base() const { return base_; }
+ uptr size() const { return size_; }
+
+ private:
+ void* base_;
+ uptr size_;
+ const char* name_;
+ uptr os_handle_;
+};
+
+typedef void (*fill_profile_f)(uptr start, uptr rss, bool file,
+ /*out*/ uptr *stats);
+
+// Parse the contents of /proc/self/smaps and generate a memory profile.
+// |cb| is a tool-specific callback that fills the |stats| array.
+void GetMemoryProfile(fill_profile_f cb, uptr *stats);
+void ParseUnixMemoryProfile(fill_profile_f cb, uptr *stats, char *smaps,
+ uptr smaps_len);
+
+// Simple low-level (mmap-based) allocator for internal use. Doesn't have
+// constructor, so all instances of LowLevelAllocator should be
+// linker initialized.
+class LowLevelAllocator {
+ public:
+ // Requires an external lock.
+ void *Allocate(uptr size);
+ private:
+ char *allocated_end_;
+ char *allocated_current_;
+};
+// Set the min alignment of LowLevelAllocator to at least alignment.
+void SetLowLevelAllocateMinAlignment(uptr alignment);
+typedef void (*LowLevelAllocateCallback)(uptr ptr, uptr size);
+// Allows to register tool-specific callbacks for LowLevelAllocator.
+// Passing NULL removes the callback.
+void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback);
+
+// IO
+void CatastrophicErrorWrite(const char *buffer, uptr length);
+void RawWrite(const char *buffer);
+bool ColorizeReports();
+void RemoveANSIEscapeSequencesFromString(char *buffer);
+void Printf(const char *format, ...) FORMAT(1, 2);
+void Report(const char *format, ...) FORMAT(1, 2);
+void SetPrintfAndReportCallback(void (*callback)(const char *));
+#define VReport(level, ...) \
+ do { \
+ if ((uptr)Verbosity() >= (level)) Report(__VA_ARGS__); \
+ } while (0)
+#define VPrintf(level, ...) \
+ do { \
+ if ((uptr)Verbosity() >= (level)) Printf(__VA_ARGS__); \
+ } while (0)
+
+// Lock sanitizer error reporting and protects against nested errors.
+class ScopedErrorReportLock {
+ public:
+ ScopedErrorReportLock() SANITIZER_ACQUIRE(mutex_) { Lock(); }
+ ~ScopedErrorReportLock() SANITIZER_RELEASE(mutex_) { Unlock(); }
+
+ static void Lock() SANITIZER_ACQUIRE(mutex_);
+ static void Unlock() SANITIZER_RELEASE(mutex_);
+ static void CheckLocked() SANITIZER_CHECK_LOCKED(mutex_);
+
+ private:
+ static atomic_uintptr_t reporting_thread_;
+ static StaticSpinMutex mutex_;
+};
+
+extern uptr stoptheworld_tracer_pid;
+extern uptr stoptheworld_tracer_ppid;
+
+bool IsAccessibleMemoryRange(uptr beg, uptr size);
+
+// Error report formatting.
+const char *StripPathPrefix(const char *filepath,
+ const char *strip_file_prefix);
+// Strip the directories from the module name.
+const char *StripModuleName(const char *module);
+
+// OS
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
+uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len);
+uptr ReadBinaryDir(/*out*/ char *buf, uptr buf_len);
+uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len);
+const char *GetProcessName();
+void UpdateProcessName();
+void CacheBinaryName();
+void DisableCoreDumperIfNecessary();
+void DumpProcessMap();
+const char *GetEnv(const char *name);
+bool SetEnv(const char *name, const char *value);
+
+u32 GetUid();
+void ReExec();
+void CheckASLR();
+void CheckMPROTECT();
+char **GetArgv();
+char **GetEnviron();
+void PrintCmdline();
+bool StackSizeIsUnlimited();
+void SetStackSizeLimitInBytes(uptr limit);
+bool AddressSpaceIsUnlimited();
+void SetAddressSpaceUnlimited();
+void AdjustStackSize(void *attr);
+void PlatformPrepareForSandboxing(void *args);
+void SetSandboxingCallback(void (*f)());
+
+void InitializeCoverage(bool enabled, const char *coverage_dir);
+
+void InitTlsSize();
+uptr GetTlsSize();
+
+// Other
+void WaitForDebugger(unsigned seconds, const char *label);
+void SleepForSeconds(unsigned seconds);
+void SleepForMillis(unsigned millis);
+u64 NanoTime();
+u64 MonotonicNanoTime();
+int Atexit(void (*function)(void));
+bool TemplateMatch(const char *templ, const char *str);
+
+// Exit
+void NORETURN Abort();
+void NORETURN Die();
+void NORETURN
+CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2);
+void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type,
+ const char *mmap_type, error_t err,
+ bool raw_report = false);
+
+// Returns true if the platform-specific error reported is an OOM error.
+bool ErrorIsOOM(error_t err);
+
+// This reports an error in the form:
+//
+// `ERROR: {{SanitizerToolName}}: out of memory: {{err_msg}}`
+//
+// Downstream tools that read sanitizer output will know that errors starting
+// in this format are specifically OOM errors.
+#define ERROR_OOM(err_msg, ...) \
+ Report("ERROR: %s: out of memory: " err_msg, SanitizerToolName, __VA_ARGS__)
+
+// Specific tools may override behavior of "Die" function to do tool-specific
+// job.
+typedef void (*DieCallbackType)(void);
+
+// It's possible to add several callbacks that would be run when "Die" is
+// called. The callbacks will be run in the opposite order. The tools are
+// strongly recommended to setup all callbacks during initialization, when there
+// is only a single thread.
+bool AddDieCallback(DieCallbackType callback);
+bool RemoveDieCallback(DieCallbackType callback);
+
+void SetUserDieCallback(DieCallbackType callback);
+
+void SetCheckUnwindCallback(void (*callback)());
+
+// Functions related to signal handling.
+typedef void (*SignalHandlerType)(int, void *, void *);
+HandleSignalMode GetHandleSignalMode(int signum);
+void InstallDeadlySignalHandlers(SignalHandlerType handler);
+
+// Signal reporting.
+// Each sanitizer uses slightly different implementation of stack unwinding.
+typedef void (*UnwindSignalStackCallbackType)(const SignalContext &sig,
+ const void *callback_context,
+ BufferedStackTrace *stack);
+// Print deadly signal report and die.
+void HandleDeadlySignal(void *siginfo, void *context, u32 tid,
+ UnwindSignalStackCallbackType unwind,
+ const void *unwind_context);
+
+// Part of HandleDeadlySignal, exposed for asan.
+void StartReportDeadlySignal();
+// Part of HandleDeadlySignal, exposed for asan.
+void ReportDeadlySignal(const SignalContext &sig, u32 tid,
+ UnwindSignalStackCallbackType unwind,
+ const void *unwind_context);
+
+// Alternative signal stack (POSIX-only).
+void SetAlternateSignalStack();
+void UnsetAlternateSignalStack();
+
+// Construct a one-line string:
+// SUMMARY: SanitizerToolName: error_message
+// and pass it to __sanitizer_report_error_summary.
+// If alt_tool_name is provided, it's used in place of SanitizerToolName.
+void ReportErrorSummary(const char *error_message,
+ const char *alt_tool_name = nullptr);
+// Same as above, but construct error_message as:
+// error_type file:line[:column][ function]
+void ReportErrorSummary(const char *error_type, const AddressInfo &info,
+ const char *alt_tool_name = nullptr);
+// Same as above, but obtains AddressInfo by symbolizing top stack trace frame.
+void ReportErrorSummary(const char *error_type, const StackTrace *trace,
+ const char *alt_tool_name = nullptr);
+
+void ReportMmapWriteExec(int prot, int mflags);
+
+// Math
+#if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
+extern "C" {
+unsigned char _BitScanForward(unsigned long *index, unsigned long mask);
+unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
+#if defined(_WIN64)
+unsigned char _BitScanForward64(unsigned long *index, unsigned __int64 mask);
+unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask);
+#endif
+}
+#endif
+
+inline uptr MostSignificantSetBitIndex(uptr x) {
+ CHECK_NE(x, 0U);
+ unsigned long up;
+#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
+# ifdef _WIN64
+ up = SANITIZER_WORDSIZE - 1 - __builtin_clzll(x);
+# else
+ up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x);
+# endif
+#elif defined(_WIN64)
+ _BitScanReverse64(&up, x);
+#else
+ _BitScanReverse(&up, x);
+#endif
+ return up;
+}
+
+inline uptr LeastSignificantSetBitIndex(uptr x) {
+ CHECK_NE(x, 0U);
+ unsigned long up;
+#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
+# ifdef _WIN64
+ up = __builtin_ctzll(x);
+# else
+ up = __builtin_ctzl(x);
+# endif
+#elif defined(_WIN64)
+ _BitScanForward64(&up, x);
+#else
+ _BitScanForward(&up, x);
+#endif
+ return up;
+}
+
+inline constexpr bool IsPowerOfTwo(uptr x) { return (x & (x - 1)) == 0; }
+
+inline uptr RoundUpToPowerOfTwo(uptr size) {
+ CHECK(size);
+ if (IsPowerOfTwo(size)) return size;
+
+ uptr up = MostSignificantSetBitIndex(size);
+ CHECK_LT(size, (1ULL << (up + 1)));
+ CHECK_GT(size, (1ULL << up));
+ return 1ULL << (up + 1);
+}
+
+inline constexpr uptr RoundUpTo(uptr size, uptr boundary) {
+ RAW_CHECK(IsPowerOfTwo(boundary));
+ return (size + boundary - 1) & ~(boundary - 1);
+}
+
+inline constexpr uptr RoundDownTo(uptr x, uptr boundary) {
+ return x & ~(boundary - 1);
+}
+
+inline constexpr bool IsAligned(uptr a, uptr alignment) {
+ return (a & (alignment - 1)) == 0;
+}
+
+inline uptr Log2(uptr x) {
+ CHECK(IsPowerOfTwo(x));
+ return LeastSignificantSetBitIndex(x);
+}
+
+// Don't use std::min, std::max or std::swap, to minimize dependency
+// on libstdc++.
+template <class T>
+constexpr T Min(T a, T b) {
+ return a < b ? a : b;
+}
+template <class T>
+constexpr T Max(T a, T b) {
+ return a > b ? a : b;
+}
+template <class T>
+constexpr T Abs(T a) {
+ return a < 0 ? -a : a;
+}
+template<class T> void Swap(T& a, T& b) {
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+// Char handling
+inline bool IsSpace(int c) {
+ return (c == ' ') || (c == '\n') || (c == '\t') ||
+ (c == '\f') || (c == '\r') || (c == '\v');
+}
+inline bool IsDigit(int c) {
+ return (c >= '0') && (c <= '9');
+}
+inline int ToLower(int c) {
+ return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c;
+}
+
+// A low-level vector based on mmap. May incur a significant memory overhead for
+// small vectors.
+// WARNING: The current implementation supports only POD types.
+template<typename T>
+class InternalMmapVectorNoCtor {
+ public:
+ using value_type = T;
+ void Initialize(uptr initial_capacity) {
+ capacity_bytes_ = 0;
+ size_ = 0;
+ data_ = 0;
+ reserve(initial_capacity);
+ }
+ void Destroy() { UnmapOrDie(data_, capacity_bytes_); }
+ T &operator[](uptr i) {
+ CHECK_LT(i, size_);
+ return data_[i];
+ }
+ const T &operator[](uptr i) const {
+ CHECK_LT(i, size_);
+ return data_[i];
+ }
+ void push_back(const T &element) {
+ CHECK_LE(size_, capacity());
+ if (size_ == capacity()) {
+ uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1);
+ Realloc(new_capacity);
+ }
+ internal_memcpy(&data_[size_++], &element, sizeof(T));
+ }
+ T &back() {
+ CHECK_GT(size_, 0);
+ return data_[size_ - 1];
+ }
+ void pop_back() {
+ CHECK_GT(size_, 0);
+ size_--;
+ }
+ uptr size() const {
+ return size_;
+ }
+ const T *data() const {
+ return data_;
+ }
+ T *data() {
+ return data_;
+ }
+ uptr capacity() const { return capacity_bytes_ / sizeof(T); }
+ void reserve(uptr new_size) {
+ // Never downsize internal buffer.
+ if (new_size > capacity())
+ Realloc(new_size);
+ }
+ void resize(uptr new_size) {
+ if (new_size > size_) {
+ reserve(new_size);
+ internal_memset(&data_[size_], 0, sizeof(T) * (new_size - size_));
+ }
+ size_ = new_size;
+ }
+
+ void clear() { size_ = 0; }
+ bool empty() const { return size() == 0; }
+
+ const T *begin() const {
+ return data();
+ }
+ T *begin() {
+ return data();
+ }
+ const T *end() const {
+ return data() + size();
+ }
+ T *end() {
+ return data() + size();
+ }
+
+ void swap(InternalMmapVectorNoCtor &other) {
+ Swap(data_, other.data_);
+ Swap(capacity_bytes_, other.capacity_bytes_);
+ Swap(size_, other.size_);
+ }
+
+ private:
+ void Realloc(uptr new_capacity) {
+ CHECK_GT(new_capacity, 0);
+ CHECK_LE(size_, new_capacity);
+ uptr new_capacity_bytes =
+ RoundUpTo(new_capacity * sizeof(T), GetPageSizeCached());
+ T *new_data = (T *)MmapOrDie(new_capacity_bytes, "InternalMmapVector");
+ internal_memcpy(new_data, data_, size_ * sizeof(T));
+ UnmapOrDie(data_, capacity_bytes_);
+ data_ = new_data;
+ capacity_bytes_ = new_capacity_bytes;
+ }
+
+ T *data_;
+ uptr capacity_bytes_;
+ uptr size_;
+};
+
+template <typename T>
+bool operator==(const InternalMmapVectorNoCtor<T> &lhs,
+ const InternalMmapVectorNoCtor<T> &rhs) {
+ if (lhs.size() != rhs.size()) return false;
+ return internal_memcmp(lhs.data(), rhs.data(), lhs.size() * sizeof(T)) == 0;
+}
+
+template <typename T>
+bool operator!=(const InternalMmapVectorNoCtor<T> &lhs,
+ const InternalMmapVectorNoCtor<T> &rhs) {
+ return !(lhs == rhs);
+}
+
+template<typename T>
+class InternalMmapVector : public InternalMmapVectorNoCtor<T> {
+ public:
+ InternalMmapVector() { InternalMmapVectorNoCtor<T>::Initialize(0); }
+ explicit InternalMmapVector(uptr cnt) {
+ InternalMmapVectorNoCtor<T>::Initialize(cnt);
+ this->resize(cnt);
+ }
+ ~InternalMmapVector() { InternalMmapVectorNoCtor<T>::Destroy(); }
+ // Disallow copies and moves.
+ InternalMmapVector(const InternalMmapVector &) = delete;
+ InternalMmapVector &operator=(const InternalMmapVector &) = delete;
+ InternalMmapVector(InternalMmapVector &&) = delete;
+ InternalMmapVector &operator=(InternalMmapVector &&) = delete;
+};
+
+class InternalScopedString {
+ public:
+ InternalScopedString() : buffer_(1) { buffer_[0] = '\0'; }
+
+ uptr length() const { return buffer_.size() - 1; }
+ void clear() {
+ buffer_.resize(1);
+ buffer_[0] = '\0';
+ }
+ void append(const char *format, ...) FORMAT(2, 3);
+ const char *data() const { return buffer_.data(); }
+ char *data() { return buffer_.data(); }
+
+ private:
+ InternalMmapVector<char> buffer_;
+};
+
+template <class T>
+struct CompareLess {
+ bool operator()(const T &a, const T &b) const { return a < b; }
+};
+
+// HeapSort for arrays and InternalMmapVector.
+template <class T, class Compare = CompareLess<T>>
+void Sort(T *v, uptr size, Compare comp = {}) {
+ if (size < 2)
+ return;
+ // Stage 1: insert elements to the heap.
+ for (uptr i = 1; i < size; i++) {
+ uptr j, p;
+ for (j = i; j > 0; j = p) {
+ p = (j - 1) / 2;
+ if (comp(v[p], v[j]))
+ Swap(v[j], v[p]);
+ else
+ break;
+ }
+ }
+ // Stage 2: swap largest element with the last one,
+ // and sink the new top.
+ for (uptr i = size - 1; i > 0; i--) {
+ Swap(v[0], v[i]);
+ uptr j, max_ind;
+ for (j = 0; j < i; j = max_ind) {
+ uptr left = 2 * j + 1;
+ uptr right = 2 * j + 2;
+ max_ind = j;
+ if (left < i && comp(v[max_ind], v[left]))
+ max_ind = left;
+ if (right < i && comp(v[max_ind], v[right]))
+ max_ind = right;
+ if (max_ind != j)
+ Swap(v[j], v[max_ind]);
+ else
+ break;
+ }
+ }
+}
+
+// Works like std::lower_bound: finds the first element that is not less
+// than the val.
+template <class Container, class T,
+ class Compare = CompareLess<typename Container::value_type>>
+uptr InternalLowerBound(const Container &v, const T &val, Compare comp = {}) {
+ uptr first = 0;
+ uptr last = v.size();
+ while (last > first) {
+ uptr mid = (first + last) / 2;
+ if (comp(v[mid], val))
+ first = mid + 1;
+ else
+ last = mid;
+ }
+ return first;
+}
+
+enum ModuleArch {
+ kModuleArchUnknown,
+ kModuleArchI386,
+ kModuleArchX86_64,
+ kModuleArchX86_64H,
+ kModuleArchARMV6,
+ kModuleArchARMV7,
+ kModuleArchARMV7S,
+ kModuleArchARMV7K,
+ kModuleArchARM64,
+ kModuleArchLoongArch64,
+ kModuleArchRISCV64,
+ kModuleArchHexagon
+};
+
+// Sorts and removes duplicates from the container.
+template <class Container,
+ class Compare = CompareLess<typename Container::value_type>>
+void SortAndDedup(Container &v, Compare comp = {}) {
+ Sort(v.data(), v.size(), comp);
+ uptr size = v.size();
+ if (size < 2)
+ return;
+ uptr last = 0;
+ for (uptr i = 1; i < size; ++i) {
+ if (comp(v[last], v[i])) {
+ ++last;
+ if (last != i)
+ v[last] = v[i];
+ } else {
+ CHECK(!comp(v[i], v[last]));
+ }
+ }
+ v.resize(last + 1);
+}
+
+constexpr uptr kDefaultFileMaxSize = FIRST_32_SECOND_64(1 << 26, 1 << 28);
+
+// Opens the file 'file_name" and reads up to 'max_len' bytes.
+// The resulting buffer is mmaped and stored in '*buff'.
+// Returns true if file was successfully opened and read.
+bool ReadFileToVector(const char *file_name,
+ InternalMmapVectorNoCtor<char> *buff,
+ uptr max_len = kDefaultFileMaxSize,
+ error_t *errno_p = nullptr);
+
+// Opens the file 'file_name" and reads up to 'max_len' bytes.
+// This function is less I/O efficient than ReadFileToVector as it may reread
+// file multiple times to avoid mmap during read attempts. It's used to read
+// procmap, so short reads with mmap in between can produce inconsistent result.
+// The resulting buffer is mmaped and stored in '*buff'.
+// The size of the mmaped region is stored in '*buff_size'.
+// The total number of read bytes is stored in '*read_len'.
+// Returns true if file was successfully opened and read.
+bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
+ uptr *read_len, uptr max_len = kDefaultFileMaxSize,
+ error_t *errno_p = nullptr);
+
+int GetModuleAndOffsetForPc(uptr pc, char *module_name, uptr module_name_len,
+ uptr *pc_offset);
+
+// When adding a new architecture, don't forget to also update
+// script/asan_symbolize.py and sanitizer_symbolizer_libcdep.cpp.
+inline const char *ModuleArchToString(ModuleArch arch) {
+ switch (arch) {
+ case kModuleArchUnknown:
+ return "";
+ case kModuleArchI386:
+ return "i386";
+ case kModuleArchX86_64:
+ return "x86_64";
+ case kModuleArchX86_64H:
+ return "x86_64h";
+ case kModuleArchARMV6:
+ return "armv6";
+ case kModuleArchARMV7:
+ return "armv7";
+ case kModuleArchARMV7S:
+ return "armv7s";
+ case kModuleArchARMV7K:
+ return "armv7k";
+ case kModuleArchARM64:
+ return "arm64";
+ case kModuleArchLoongArch64:
+ return "loongarch64";
+ case kModuleArchRISCV64:
+ return "riscv64";
+ case kModuleArchHexagon:
+ return "hexagon";
+ }
+ CHECK(0 && "Invalid module arch");
+ return "";
+}
+
+const uptr kModuleUUIDSize = 32;
+const uptr kMaxSegName = 16;
+
+// Represents a binary loaded into virtual memory (e.g. this can be an
+// executable or a shared object).
+class LoadedModule {
+ public:
+ LoadedModule()
+ : full_name_(nullptr),
+ base_address_(0),
+ max_address_(0),
+ arch_(kModuleArchUnknown),
+ uuid_size_(0),
+ instrumented_(false) {
+ internal_memset(uuid_, 0, kModuleUUIDSize);
+ ranges_.clear();
+ }
+ void set(const char *module_name, uptr base_address);
+ void set(const char *module_name, uptr base_address, ModuleArch arch,
+ u8 uuid[kModuleUUIDSize], bool instrumented);
+ void setUuid(const char *uuid, uptr size);
+ void clear();
+ void addAddressRange(uptr beg, uptr end, bool executable, bool writable,
+ const char *name = nullptr);
+ bool containsAddress(uptr address) const;
+
+ const char *full_name() const { return full_name_; }
+ uptr base_address() const { return base_address_; }
+ uptr max_address() const { return max_address_; }
+ ModuleArch arch() const { return arch_; }
+ const u8 *uuid() const { return uuid_; }
+ uptr uuid_size() const { return uuid_size_; }
+ bool instrumented() const { return instrumented_; }
+
+ struct AddressRange {
+ AddressRange *next;
+ uptr beg;
+ uptr end;
+ bool executable;
+ bool writable;
+ char name[kMaxSegName];
+
+ AddressRange(uptr beg, uptr end, bool executable, bool writable,
+ const char *name)
+ : next(nullptr),
+ beg(beg),
+ end(end),
+ executable(executable),
+ writable(writable) {
+ internal_strncpy(this->name, (name ? name : ""), ARRAY_SIZE(this->name));
+ }
+ };
+
+ const IntrusiveList<AddressRange> &ranges() const { return ranges_; }
+
+ private:
+ char *full_name_; // Owned.
+ uptr base_address_;
+ uptr max_address_;
+ ModuleArch arch_;
+ uptr uuid_size_;
+ u8 uuid_[kModuleUUIDSize];
+ bool instrumented_;
+ IntrusiveList<AddressRange> ranges_;
+};
+
+// List of LoadedModules. OS-dependent implementation is responsible for
+// filling this information.
+class ListOfModules {
+ public:
+ ListOfModules() : initialized(false) {}
+ ~ListOfModules() { clear(); }
+ void init();
+ void fallbackInit(); // Uses fallback init if available, otherwise clears
+ const LoadedModule *begin() const { return modules_.begin(); }
+ LoadedModule *begin() { return modules_.begin(); }
+ const LoadedModule *end() const { return modules_.end(); }
+ LoadedModule *end() { return modules_.end(); }
+ uptr size() const { return modules_.size(); }
+ const LoadedModule &operator[](uptr i) const {
+ CHECK_LT(i, modules_.size());
+ return modules_[i];
+ }
+
+ private:
+ void clear() {
+ for (auto &module : modules_) module.clear();
+ modules_.clear();
+ }
+ void clearOrInit() {
+ initialized ? clear() : modules_.Initialize(kInitialCapacity);
+ initialized = true;
+ }
+
+ InternalMmapVectorNoCtor<LoadedModule> modules_;
+ // We rarely have more than 16K loaded modules.
+ static const uptr kInitialCapacity = 1 << 14;
+ bool initialized;
+};
+
+// Callback type for iterating over a set of memory ranges.
+typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);
+
+enum AndroidApiLevel {
+ ANDROID_NOT_ANDROID = 0,
+ ANDROID_KITKAT = 19,
+ ANDROID_LOLLIPOP_MR1 = 22,
+ ANDROID_POST_LOLLIPOP = 23
+};
+
+void WriteToSyslog(const char *buffer);
+
+#if defined(SANITIZER_WINDOWS) && defined(_MSC_VER) && !defined(__clang__)
+#define SANITIZER_WIN_TRACE 1
+#else
+#define SANITIZER_WIN_TRACE 0
+#endif
+
+#if SANITIZER_APPLE || SANITIZER_WIN_TRACE
+void LogFullErrorReport(const char *buffer);
+#else
+inline void LogFullErrorReport(const char *buffer) {}
+#endif
+
+#if SANITIZER_LINUX || SANITIZER_APPLE
+void WriteOneLineToSyslog(const char *s);
+void LogMessageOnPrintf(const char *str);
+#else
+inline void WriteOneLineToSyslog(const char *s) {}
+inline void LogMessageOnPrintf(const char *str) {}
+#endif
+
+#if SANITIZER_LINUX || SANITIZER_WIN_TRACE
+// Initialize Android logging. Any writes before this are silently lost.
+void AndroidLogInit();
+void SetAbortMessage(const char *);
+#else
+inline void AndroidLogInit() {}
+// FIXME: MacOS implementation could use CRSetCrashLogMessage.
+inline void SetAbortMessage(const char *) {}
+#endif
+
+#if SANITIZER_ANDROID
+void SanitizerInitializeUnwinder();
+AndroidApiLevel AndroidGetApiLevel();
+#else
+inline void AndroidLogWrite(const char *buffer_unused) {}
+inline void SanitizerInitializeUnwinder() {}
+inline AndroidApiLevel AndroidGetApiLevel() { return ANDROID_NOT_ANDROID; }
+#endif
+
+inline uptr GetPthreadDestructorIterations() {
+#if SANITIZER_ANDROID
+ return (AndroidGetApiLevel() == ANDROID_LOLLIPOP_MR1) ? 8 : 4;
+#elif SANITIZER_POSIX
+ return 4;
+#else
+// Unused on Windows.
+ return 0;
+#endif
+}
+
+void *internal_start_thread(void *(*func)(void*), void *arg);
+void internal_join_thread(void *th);
+void MaybeStartBackgroudThread();
+
+// Make the compiler think that something is going on there.
+// Use this inside a loop that looks like memset/memcpy/etc to prevent the
+// compiler from recognising it and turning it into an actual call to
+// memset/memcpy/etc.
+static inline void SanitizerBreakOptimization(void *arg) {
+#if defined(_MSC_VER) && !defined(__clang__)
+ _ReadWriteBarrier();
+#else
+ __asm__ __volatile__("" : : "r" (arg) : "memory");
+#endif
+}
+
+struct SignalContext {
+ void *siginfo;
+ void *context;
+ uptr addr;
+ uptr pc;
+ uptr sp;
+ uptr bp;
+ bool is_memory_access;
+ enum WriteFlag { Unknown, Read, Write } write_flag;
+
+ // In some cases the kernel cannot provide the true faulting address; `addr`
+ // will be zero then. This field allows to distinguish between these cases
+ // and dereferences of null.
+ bool is_true_faulting_addr;
+
+ // VS2013 doesn't implement unrestricted unions, so we need a trivial default
+ // constructor
+ SignalContext() = default;
+
+ // Creates signal context in a platform-specific manner.
+ // SignalContext is going to keep pointers to siginfo and context without
+ // owning them.
+ SignalContext(void *siginfo, void *context)
+ : siginfo(siginfo),
+ context(context),
+ addr(GetAddress()),
+ is_memory_access(IsMemoryAccess()),
+ write_flag(GetWriteFlag()),
+ is_true_faulting_addr(IsTrueFaultingAddress()) {
+ InitPcSpBp();
+ }
+
+ static void DumpAllRegisters(void *context);
+
+ // Type of signal e.g. SIGSEGV or EXCEPTION_ACCESS_VIOLATION.
+ int GetType() const;
+
+ // String description of the signal.
+ const char *Describe() const;
+
+ // Returns true if signal is stack overflow.
+ bool IsStackOverflow() const;
+
+ private:
+ // Platform specific initialization.
+ void InitPcSpBp();
+ uptr GetAddress() const;
+ WriteFlag GetWriteFlag() const;
+ bool IsMemoryAccess() const;
+ bool IsTrueFaultingAddress() const;
+};
+
+void InitializePlatformEarly();
+
+template <typename Fn>
+class RunOnDestruction {
+ public:
+ explicit RunOnDestruction(Fn fn) : fn_(fn) {}
+ ~RunOnDestruction() { fn_(); }
+
+ private:
+ Fn fn_;
+};
+
+// A simple scope guard. Usage:
+// auto cleanup = at_scope_exit([]{ do_cleanup; });
+template <typename Fn>
+RunOnDestruction<Fn> at_scope_exit(Fn fn) {
+ return RunOnDestruction<Fn>(fn);
+}
+
+// Linux on 64-bit s390 had a nasty bug that crashes the whole machine
+// if a process uses virtual memory over 4TB (as many sanitizers like
+// to do). This function will abort the process if running on a kernel
+// that looks vulnerable.
+#if SANITIZER_LINUX && SANITIZER_S390_64
+void AvoidCVE_2016_2143();
+#else
+inline void AvoidCVE_2016_2143() {}
+#endif
+
+struct StackDepotStats {
+ uptr n_uniq_ids;
+ uptr allocated;
+};
+
+// The default value for allocator_release_to_os_interval_ms common flag to
+// indicate that sanitizer allocator should not attempt to release memory to OS.
+const s32 kReleaseToOSIntervalNever = -1;
+
+void CheckNoDeepBind(const char *filename, int flag);
+
+// Returns the requested amount of random data (up to 256 bytes) that can then
+// be used to seed a PRNG. Defaults to blocking like the underlying syscall.
+bool GetRandom(void *buffer, uptr length, bool blocking = true);
+
+// Returns the number of logical processors on the system.
+u32 GetNumberOfCPUs();
+extern u32 NumberOfCPUsCached;
+inline u32 GetNumberOfCPUsCached() {
+ if (!NumberOfCPUsCached)
+ NumberOfCPUsCached = GetNumberOfCPUs();
+ return NumberOfCPUsCached;
+}
+
+template <typename T>
+class ArrayRef {
+ public:
+ ArrayRef() {}
+ ArrayRef(T *begin, T *end) : begin_(begin), end_(end) {}
+
+ T *begin() { return begin_; }
+ T *end() { return end_; }
+
+ private:
+ T *begin_ = nullptr;
+ T *end_ = nullptr;
+};
+
+} // namespace __sanitizer
+
+inline void *operator new(__sanitizer::operator_new_size_type size,
+ __sanitizer::LowLevelAllocator &alloc) {
+ return alloc.Allocate(size);
+}
+
+#endif // SANITIZER_COMMON_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
new file mode 100644
index 00000000000..e999239549c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -0,0 +1,10695 @@
+//===-- sanitizer_common_interceptors.inc -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Common function interceptors for tools like AddressSanitizer,
+// ThreadSanitizer, MemorySanitizer, etc.
+//
+// This file should be included into the tool's interceptor file,
+// which has to define its own macros:
+// COMMON_INTERCEPTOR_ENTER
+// COMMON_INTERCEPTOR_ENTER_NOIGNORE
+// COMMON_INTERCEPTOR_READ_RANGE
+// COMMON_INTERCEPTOR_WRITE_RANGE
+// COMMON_INTERCEPTOR_INITIALIZE_RANGE
+// COMMON_INTERCEPTOR_DIR_ACQUIRE
+// COMMON_INTERCEPTOR_FD_ACQUIRE
+// COMMON_INTERCEPTOR_FD_RELEASE
+// COMMON_INTERCEPTOR_FD_ACCESS
+// COMMON_INTERCEPTOR_SET_THREAD_NAME
+// COMMON_INTERCEPTOR_DLOPEN
+// COMMON_INTERCEPTOR_ON_EXIT
+// COMMON_INTERCEPTOR_SET_PTHREAD_NAME
+// COMMON_INTERCEPTOR_HANDLE_RECVMSG
+// COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
+// COMMON_INTERCEPTOR_MEMSET_IMPL
+// COMMON_INTERCEPTOR_MEMMOVE_IMPL
+// COMMON_INTERCEPTOR_MEMCPY_IMPL
+// COMMON_INTERCEPTOR_MMAP_IMPL
+// COMMON_INTERCEPTOR_COPY_STRING
+// COMMON_INTERCEPTOR_STRNDUP_IMPL
+// COMMON_INTERCEPTOR_STRERROR
+//===----------------------------------------------------------------------===//
+
+#include "interception/interception.h"
+#include "sanitizer_addrhashmap.h"
+#include "sanitizer_errno.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_platform_interceptors.h"
+#include "sanitizer_symbolizer.h"
+#include "sanitizer_tls_get_addr.h"
+
+#include <stdarg.h>
+
+#if SANITIZER_INTERCEPTOR_HOOKS
+#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) f(__VA_ARGS__);
+#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
+ SANITIZER_INTERFACE_WEAK_DEF(void, f, __VA_ARGS__) {}
+#else
+#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...)
+#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...)
+
+#endif // SANITIZER_INTERCEPTOR_HOOKS
+
+#if SANITIZER_WINDOWS && !defined(va_copy)
+#define va_copy(dst, src) ((dst) = (src))
+#endif // _WIN32
+
+#if SANITIZER_FREEBSD
+#define pthread_setname_np pthread_set_name_np
+#define inet_aton __inet_aton
+#define inet_pton __inet_pton
+#define iconv __bsd_iconv
+#endif
+
+#if SANITIZER_NETBSD
+#define clock_getres __clock_getres50
+#define clock_gettime __clock_gettime50
+#define clock_settime __clock_settime50
+#define ctime __ctime50
+#define ctime_r __ctime_r50
+#define devname __devname50
+#define fgetpos __fgetpos50
+#define fsetpos __fsetpos50
+#define fstatvfs __fstatvfs90
+#define fstatvfs1 __fstatvfs190
+#define fts_children __fts_children60
+#define fts_close __fts_close60
+#define fts_open __fts_open60
+#define fts_read __fts_read60
+#define fts_set __fts_set60
+#define getitimer __getitimer50
+#define getmntinfo __getmntinfo90
+#define getpwent __getpwent50
+#define getpwnam __getpwnam50
+#define getpwnam_r __getpwnam_r50
+#define getpwuid __getpwuid50
+#define getpwuid_r __getpwuid_r50
+#define getutent __getutent50
+#define getutxent __getutxent50
+#define getutxid __getutxid50
+#define getutxline __getutxline50
+#define getvfsstat __getvfsstat90
+#define pututxline __pututxline50
+#define glob __glob30
+#define gmtime __gmtime50
+#define gmtime_r __gmtime_r50
+#define localtime __locatime50
+#define localtime_r __localtime_r50
+#define mktime __mktime50
+#define lstat __lstat50
+#define opendir __opendir30
+#define readdir __readdir30
+#define readdir_r __readdir_r30
+#define scandir __scandir30
+#define setitimer __setitimer50
+#define setlocale __setlocale50
+#define shmctl __shmctl50
+#define sigaltstack __sigaltstack14
+#define sigemptyset __sigemptyset14
+#define sigfillset __sigfillset14
+#define sigpending __sigpending14
+#define sigprocmask __sigprocmask14
+#define sigtimedwait __sigtimedwait50
+#define stat __stat50
+#define statvfs __statvfs90
+#define statvfs1 __statvfs190
+#define time __time50
+#define times __times13
+#define unvis __unvis50
+#define wait3 __wait350
+#define wait4 __wait450
+extern const unsigned short *_ctype_tab_;
+extern const short *_toupper_tab_;
+extern const short *_tolower_tab_;
+#endif
+
+#if SANITIZER_MUSL && \
+ (defined(__i386__) || defined(__arm__) || SANITIZER_MIPS32 || SANITIZER_PPC32)
+// musl 1.2.0 on existing 32-bit architectures uses new symbol names for the
+// time-related functions that take 64-bit time_t values. See
+// https://musl.libc.org/time64.html
+#define adjtime __adjtime64
+#define adjtimex __adjtimex_time64
+#define aio_suspend __aio_suspend_time64
+#define clock_adjtime __clock_adjtime64
+#define clock_getres __clock_getres_time64
+#define clock_gettime __clock_gettime64
+#define clock_nanosleep __clock_nanosleep_time64
+#define clock_settime __clock_settime64
+#define cnd_timedwait __cnd_timedwait_time64
+#define ctime __ctime64
+#define ctime_r __ctime64_r
+#define difftime __difftime64
+#define dlsym __dlsym_time64
+#define fstatat __fstatat_time64
+#define fstat __fstat_time64
+#define ftime __ftime64
+#define futimens __futimens_time64
+#define futimesat __futimesat_time64
+#define futimes __futimes_time64
+#define getitimer __getitimer_time64
+#define getrusage __getrusage_time64
+#define gettimeofday __gettimeofday_time64
+#define gmtime __gmtime64
+#define gmtime_r __gmtime64_r
+#define localtime __localtime64
+#define localtime_r __localtime64_r
+#define lstat __lstat_time64
+#define lutimes __lutimes_time64
+#define mktime __mktime64
+#define mq_timedreceive __mq_timedreceive_time64
+#define mq_timedsend __mq_timedsend_time64
+#define mtx_timedlock __mtx_timedlock_time64
+#define nanosleep __nanosleep_time64
+#define ppoll __ppoll_time64
+#define pselect __pselect_time64
+#define pthread_cond_timedwait __pthread_cond_timedwait_time64
+#define pthread_mutex_timedlock __pthread_mutex_timedlock_time64
+#define pthread_rwlock_timedrdlock __pthread_rwlock_timedrdlock_time64
+#define pthread_rwlock_timedwrlock __pthread_rwlock_timedwrlock_time64
+#define pthread_timedjoin_np __pthread_timedjoin_np_time64
+#define recvmmsg __recvmmsg_time64
+#define sched_rr_get_interval __sched_rr_get_interval_time64
+#define select __select_time64
+#define semtimedop __semtimedop_time64
+#define sem_timedwait __sem_timedwait_time64
+#define setitimer __setitimer_time64
+#define settimeofday __settimeofday_time64
+#define sigtimedwait __sigtimedwait_time64
+#define stat __stat_time64
+#define stime __stime64
+#define thrd_sleep __thrd_sleep_time64
+#define timegm __timegm_time64
+#define timerfd_gettime __timerfd_gettime64
+#define timerfd_settime __timerfd_settime64
+#define timer_gettime __timer_gettime64
+#define timer_settime __timer_settime64
+#define timespec_get __timespec_get_time64
+#define time __time64
+#define utimensat __utimensat_time64
+#define utimes __utimes_time64
+#define utime __utime64
+#define wait3 __wait3_time64
+#define wait4 __wait4_time64
+#endif
+
+// Platform-specific options.
+#if SANITIZER_APPLE
+#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
+#elif SANITIZER_WINDOWS64
+#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0
+#else
+#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1
+#endif // SANITIZER_APPLE
+
+#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE
+#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(p, size) {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_UNPOISON_PARAM
+#define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_FD_ACCESS
+#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_HANDLE_RECVMSG
+#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) ((void)(msg))
+#endif
+
+#ifndef COMMON_INTERCEPTOR_FILE_OPEN
+#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_FILE_CLOSE
+#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_LIBRARY_LOADED
+#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_LIBRARY_UNLOADED
+#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_ENTER_NOIGNORE
+#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, ...) \
+ COMMON_INTERCEPTOR_ENTER(ctx, __VA_ARGS__)
+#endif
+
+#ifndef COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
+#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (0)
+#endif
+
+#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n) \
+ COMMON_INTERCEPTOR_READ_RANGE((ctx), (s), \
+ common_flags()->strict_string_checks ? (internal_strlen(s)) + 1 : (n) )
+
+#ifndef COMMON_INTERCEPTOR_DLOPEN
+#define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
+ ({ CheckNoDeepBind(filename, flag); REAL(dlopen)(filename, flag); })
+#endif
+
+#ifndef COMMON_INTERCEPTOR_GET_TLS_RANGE
+#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) *begin = *end = 0;
+#endif
+
+#ifndef COMMON_INTERCEPTOR_ACQUIRE
+#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_RELEASE
+#define COMMON_INTERCEPTOR_RELEASE(ctx, u) {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_START
+#define COMMON_INTERCEPTOR_USER_CALLBACK_START() {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_END
+#define COMMON_INTERCEPTOR_USER_CALLBACK_END() {}
+#endif
+
+#ifdef SANITIZER_NLDBL_VERSION
+#define COMMON_INTERCEPT_FUNCTION_LDBL(fn) \
+ COMMON_INTERCEPT_FUNCTION_VER(fn, SANITIZER_NLDBL_VERSION)
+#else
+#define COMMON_INTERCEPT_FUNCTION_LDBL(fn) \
+ COMMON_INTERCEPT_FUNCTION(fn)
+#endif
+
+#if SANITIZER_GLIBC
+// If we could not find the versioned symbol, fall back to an unversioned
+// lookup. This is needed to work around a GLibc bug that causes dlsym
+// with RTLD_NEXT to return the oldest versioned symbol.
+// See https://sourceware.org/bugzilla/show_bug.cgi?id=14932.
+// For certain symbols (e.g. regexec) we have to perform a versioned lookup,
+// but that versioned symbol will only exist for architectures where the
+// oldest Glibc version pre-dates support for that architecture.
+// For example, regexec@GLIBC_2.3.4 exists on x86_64, but not RISC-V.
+// See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98920.
+#define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \
+ COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(fn, ver)
+#else
+#define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \
+ COMMON_INTERCEPT_FUNCTION(fn)
+#endif
+
+#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
+#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
+ { \
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \
+ return internal_memset(dst, v, size); \
+ COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \
+ if (common_flags()->intercept_intrin) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
+ return REAL(memset)(dst, v, size); \
+ }
+#endif
+
+#ifndef COMMON_INTERCEPTOR_MEMMOVE_IMPL
+#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size) \
+ { \
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \
+ return internal_memmove(dst, src, size); \
+ COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size); \
+ if (common_flags()->intercept_intrin) { \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \
+ } \
+ return REAL(memmove)(dst, src, size); \
+ }
+#endif
+
+#ifndef COMMON_INTERCEPTOR_MEMCPY_IMPL
+#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size) \
+ { \
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { \
+ return internal_memmove(dst, src, size); \
+ } \
+ COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size); \
+ if (common_flags()->intercept_intrin) { \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \
+ } \
+ return REAL(memcpy)(dst, src, size); \
+ }
+#endif
+
+#ifndef COMMON_INTERCEPTOR_MMAP_IMPL
+#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, \
+ off) \
+ { return REAL(mmap)(addr, sz, prot, flags, fd, off); }
+#endif
+
+#ifndef COMMON_INTERCEPTOR_COPY_STRING
+#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {}
+#endif
+
+#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL
+#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size) \
+ COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size); \
+ uptr copy_length = internal_strnlen(s, size); \
+ char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \
+ if (common_flags()->intercept_strndup) { \
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1)); \
+ } \
+ if (new_mem) { \
+ COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \
+ internal_memcpy(new_mem, s, copy_length); \
+ new_mem[copy_length] = '\0'; \
+ } \
+ return new_mem;
+#endif
+
+#ifndef COMMON_INTERCEPTOR_STRERROR
+#define COMMON_INTERCEPTOR_STRERROR() {}
+#endif
+
+struct FileMetadata {
+ // For open_memstream().
+ char **addr;
+ SIZE_T *size;
+};
+
+struct CommonInterceptorMetadata {
+ enum {
+ CIMT_INVALID = 0,
+ CIMT_FILE
+ } type;
+ union {
+ FileMetadata file;
+ };
+};
+
+#if SI_POSIX
+typedef AddrHashMap<CommonInterceptorMetadata, 31051> MetadataHashMap;
+
+static MetadataHashMap *interceptor_metadata_map;
+
+UNUSED static void SetInterceptorMetadata(__sanitizer_FILE *addr,
+ const FileMetadata &file) {
+ MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr);
+ CHECK(h.created());
+ h->type = CommonInterceptorMetadata::CIMT_FILE;
+ h->file = file;
+}
+
+UNUSED static const FileMetadata *GetInterceptorMetadata(
+ __sanitizer_FILE *addr) {
+ MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr,
+ /* remove */ false,
+ /* create */ false);
+ if (addr && h.exists()) {
+ CHECK(!h.created());
+ CHECK(h->type == CommonInterceptorMetadata::CIMT_FILE);
+ return &h->file;
+ } else {
+ return 0;
+ }
+}
+
+UNUSED static void DeleteInterceptorMetadata(void *addr) {
+ MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr, true);
+ CHECK(h.exists());
+}
+#endif // SI_POSIX
+
+#if SANITIZER_INTERCEPT_STRLEN
+INTERCEPTOR(SIZE_T, strlen, const char *s) {
+ // Sometimes strlen is called prior to InitializeCommonInterceptors,
+ // in which case the REAL(strlen) typically used in
+ // COMMON_INTERCEPTOR_ENTER will fail. We use internal_strlen here
+ // to handle that.
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return internal_strlen(s);
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strlen, s);
+ SIZE_T result = REAL(strlen)(s);
+ if (common_flags()->intercept_strlen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, result + 1);
+ return result;
+}
+#define INIT_STRLEN COMMON_INTERCEPT_FUNCTION(strlen)
+#else
+#define INIT_STRLEN
+#endif
+
+#if SANITIZER_INTERCEPT_STRNLEN
+INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strnlen, s, maxlen);
+ SIZE_T length = REAL(strnlen)(s, maxlen);
+ if (common_flags()->intercept_strlen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, Min(length + 1, maxlen));
+ return length;
+}
+#define INIT_STRNLEN COMMON_INTERCEPT_FUNCTION(strnlen)
+#else
+#define INIT_STRNLEN
+#endif
+
+#if SANITIZER_INTERCEPT_STRNDUP
+INTERCEPTOR(char*, strndup, const char *s, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
+}
+#define INIT_STRNDUP COMMON_INTERCEPT_FUNCTION(strndup)
+#else
+#define INIT_STRNDUP
+#endif // SANITIZER_INTERCEPT_STRNDUP
+
+#if SANITIZER_INTERCEPT___STRNDUP
+INTERCEPTOR(char*, __strndup, const char *s, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
+}
+#define INIT___STRNDUP COMMON_INTERCEPT_FUNCTION(__strndup)
+#else
+#define INIT___STRNDUP
+#endif // SANITIZER_INTERCEPT___STRNDUP
+
+#if SANITIZER_INTERCEPT_TEXTDOMAIN
+INTERCEPTOR(char*, textdomain, const char *domainname) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, textdomain, domainname);
+ if (domainname) COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
+ char *domain = REAL(textdomain)(domainname);
+ if (domain) {
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, internal_strlen(domain) + 1);
+ }
+ return domain;
+}
+#define INIT_TEXTDOMAIN COMMON_INTERCEPT_FUNCTION(textdomain)
+#else
+#define INIT_TEXTDOMAIN
+#endif
+
+#if SANITIZER_INTERCEPT_STRCMP
+static inline int CharCmpX(unsigned char c1, unsigned char c2) {
+ return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
+}
+
+DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, uptr called_pc,
+ const char *s1, const char *s2, int result)
+
+INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strcmp, s1, s2);
+ unsigned char c1, c2;
+ uptr i;
+ for (i = 0;; i++) {
+ c1 = (unsigned char)s1[i];
+ c2 = (unsigned char)s2[i];
+ if (c1 != c2 || c1 == '\0') break;
+ }
+ if (common_flags()->intercept_strcmp) {
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
+ }
+ int result = CharCmpX(c1, c2);
+ CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1,
+ s2, result);
+ return result;
+}
+
+DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, uptr called_pc,
+ const char *s1, const char *s2, uptr n,
+ int result)
+
+INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return internal_strncmp(s1, s2, size);
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);
+ unsigned char c1 = 0, c2 = 0;
+ uptr i;
+ for (i = 0; i < size; i++) {
+ c1 = (unsigned char)s1[i];
+ c2 = (unsigned char)s2[i];
+ if (c1 != c2 || c1 == '\0') break;
+ }
+ uptr i1 = i;
+ uptr i2 = i;
+ if (common_flags()->strict_string_checks) {
+ for (; i1 < size && s1[i1]; i1++) {}
+ for (; i2 < size && s2[i2]; i2++) {}
+ }
+ COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
+ COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
+ int result = CharCmpX(c1, c2);
+ CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1,
+ s2, size, result);
+ return result;
+}
+
+#define INIT_STRCMP COMMON_INTERCEPT_FUNCTION(strcmp)
+#define INIT_STRNCMP COMMON_INTERCEPT_FUNCTION(strncmp)
+#else
+#define INIT_STRCMP
+#define INIT_STRNCMP
+#endif
+
+#if SANITIZER_INTERCEPT_STRCASECMP
+static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
+ int c1_low = ToLower(c1);
+ int c2_low = ToLower(c2);
+ return c1_low - c2_low;
+}
+
+DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, uptr called_pc,
+ const char *s1, const char *s2, int result)
+
+INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strcasecmp, s1, s2);
+ unsigned char c1 = 0, c2 = 0;
+ uptr i;
+ for (i = 0;; i++) {
+ c1 = (unsigned char)s1[i];
+ c2 = (unsigned char)s2[i];
+ if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
+ }
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
+ int result = CharCaseCmp(c1, c2);
+ CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, GET_CALLER_PC(),
+ s1, s2, result);
+ return result;
+}
+
+DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, uptr called_pc,
+ const char *s1, const char *s2, uptr size,
+ int result)
+
+INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, size);
+ unsigned char c1 = 0, c2 = 0;
+ uptr i;
+ for (i = 0; i < size; i++) {
+ c1 = (unsigned char)s1[i];
+ c2 = (unsigned char)s2[i];
+ if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
+ }
+ uptr i1 = i;
+ uptr i2 = i;
+ if (common_flags()->strict_string_checks) {
+ for (; i1 < size && s1[i1]; i1++) {}
+ for (; i2 < size && s2[i2]; i2++) {}
+ }
+ COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
+ COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
+ int result = CharCaseCmp(c1, c2);
+ CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, GET_CALLER_PC(),
+ s1, s2, size, result);
+ return result;
+}
+
+#define INIT_STRCASECMP COMMON_INTERCEPT_FUNCTION(strcasecmp)
+#define INIT_STRNCASECMP COMMON_INTERCEPT_FUNCTION(strncasecmp)
+#else
+#define INIT_STRCASECMP
+#define INIT_STRNCASECMP
+#endif
+
+#if SANITIZER_INTERCEPT_STRSTR || SANITIZER_INTERCEPT_STRCASESTR
+static inline void StrstrCheck(void *ctx, char *r, const char *s1,
+ const char *s2) {
+ uptr len1 = internal_strlen(s1);
+ uptr len2 = internal_strlen(s2);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2 + 1);
+}
+#endif
+
+#if SANITIZER_INTERCEPT_STRSTR
+
+DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, uptr called_pc,
+ const char *s1, const char *s2, char *result)
+
+INTERCEPTOR(char*, strstr, const char *s1, const char *s2) {
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return internal_strstr(s1, s2);
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strstr, s1, s2);
+ char *r = REAL(strstr)(s1, s2);
+ if (common_flags()->intercept_strstr)
+ StrstrCheck(ctx, r, s1, s2);
+ CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, GET_CALLER_PC(), s1,
+ s2, r);
+ return r;
+}
+
+#define INIT_STRSTR COMMON_INTERCEPT_FUNCTION(strstr);
+#else
+#define INIT_STRSTR
+#endif
+
+#if SANITIZER_INTERCEPT_STRCASESTR
+
+DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, uptr called_pc,
+ const char *s1, const char *s2, char *result)
+
+INTERCEPTOR(char*, strcasestr, const char *s1, const char *s2) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strcasestr, s1, s2);
+ char *r = REAL(strcasestr)(s1, s2);
+ if (common_flags()->intercept_strstr)
+ StrstrCheck(ctx, r, s1, s2);
+ CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, GET_CALLER_PC(),
+ s1, s2, r);
+ return r;
+}
+
+#define INIT_STRCASESTR COMMON_INTERCEPT_FUNCTION(strcasestr);
+#else
+#define INIT_STRCASESTR
+#endif
+
+#if SANITIZER_INTERCEPT_STRTOK
+
+INTERCEPTOR(char*, strtok, char *str, const char *delimiters) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strtok, str, delimiters);
+ if (!common_flags()->intercept_strtok) {
+ return REAL(strtok)(str, delimiters);
+ }
+ if (common_flags()->strict_string_checks) {
+ // If strict_string_checks is enabled, we check the whole first argument
+ // string on the first call (strtok saves this string in a static buffer
+ // for subsequent calls). We do not need to check strtok's result.
+ // As the delimiters can change, we check them every call.
+ if (str != nullptr) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
+ }
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters,
+ internal_strlen(delimiters) + 1);
+ return REAL(strtok)(str, delimiters);
+ } else {
+ // However, when strict_string_checks is disabled we cannot check the
+ // whole string on the first call. Instead, we check the result string
+ // which is guaranteed to be a NULL-terminated substring of the first
+ // argument. We also conservatively check one character of str and the
+ // delimiters.
+ if (str != nullptr) {
+ COMMON_INTERCEPTOR_READ_STRING(ctx, str, 1);
+ }
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters, 1);
+ char *result = REAL(strtok)(str, delimiters);
+ if (result != nullptr) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, result, internal_strlen(result) + 1);
+ } else if (str != nullptr) {
+ // No delimiter were found, it's safe to assume that the entire str was
+ // scanned.
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
+ }
+ return result;
+ }
+}
+
+#define INIT_STRTOK COMMON_INTERCEPT_FUNCTION(strtok)
+#else
+#define INIT_STRTOK
+#endif
+
+#if SANITIZER_INTERCEPT_MEMMEM
+DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, uptr called_pc,
+ const void *s1, SIZE_T len1, const void *s2,
+ SIZE_T len2, void *result)
+
+INTERCEPTOR(void*, memmem, const void *s1, SIZE_T len1, const void *s2,
+ SIZE_T len2) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, memmem, s1, len1, s2, len2);
+ void *r = REAL(memmem)(s1, len1, s2, len2);
+ if (common_flags()->intercept_memmem) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, len1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2);
+ }
+ CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, GET_CALLER_PC(),
+ s1, len1, s2, len2, r);
+ return r;
+}
+
+#define INIT_MEMMEM COMMON_INTERCEPT_FUNCTION(memmem);
+#else
+#define INIT_MEMMEM
+#endif // SANITIZER_INTERCEPT_MEMMEM
+
+#if SANITIZER_INTERCEPT_STRCHR
+INTERCEPTOR(char*, strchr, const char *s, int c) {
+ void *ctx;
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return internal_strchr(s, c);
+ COMMON_INTERCEPTOR_ENTER(ctx, strchr, s, c);
+ char *result = REAL(strchr)(s, c);
+ if (common_flags()->intercept_strchr) {
+ // Keep strlen as macro argument, as macro may ignore it.
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s,
+ (result ? result - s : internal_strlen(s)) + 1);
+ }
+ return result;
+}
+#define INIT_STRCHR COMMON_INTERCEPT_FUNCTION(strchr)
+#else
+#define INIT_STRCHR
+#endif
+
+#if SANITIZER_INTERCEPT_STRCHRNUL
+INTERCEPTOR(char*, strchrnul, const char *s, int c) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strchrnul, s, c);
+ char *result = REAL(strchrnul)(s, c);
+ uptr len = result - s + 1;
+ if (common_flags()->intercept_strchr)
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s, len);
+ return result;
+}
+#define INIT_STRCHRNUL COMMON_INTERCEPT_FUNCTION(strchrnul)
+#else
+#define INIT_STRCHRNUL
+#endif
+
+#if SANITIZER_INTERCEPT_STRRCHR
+INTERCEPTOR(char*, strrchr, const char *s, int c) {
+ void *ctx;
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return internal_strrchr(s, c);
+ COMMON_INTERCEPTOR_ENTER(ctx, strrchr, s, c);
+ if (common_flags()->intercept_strchr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
+ return REAL(strrchr)(s, c);
+}
+#define INIT_STRRCHR COMMON_INTERCEPT_FUNCTION(strrchr)
+#else
+#define INIT_STRRCHR
+#endif
+
+#if SANITIZER_INTERCEPT_STRSPN
+INTERCEPTOR(SIZE_T, strspn, const char *s1, const char *s2) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strspn, s1, s2);
+ SIZE_T r = REAL(strspn)(s1, s2);
+ if (common_flags()->intercept_strspn) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
+ }
+ return r;
+}
+
+INTERCEPTOR(SIZE_T, strcspn, const char *s1, const char *s2) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strcspn, s1, s2);
+ SIZE_T r = REAL(strcspn)(s1, s2);
+ if (common_flags()->intercept_strspn) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
+ }
+ return r;
+}
+
+#define INIT_STRSPN \
+ COMMON_INTERCEPT_FUNCTION(strspn); \
+ COMMON_INTERCEPT_FUNCTION(strcspn);
+#else
+#define INIT_STRSPN
+#endif
+
+#if SANITIZER_INTERCEPT_STRPBRK
+INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strpbrk, s1, s2);
+ char *r = REAL(strpbrk)(s1, s2);
+ if (common_flags()->intercept_strpbrk) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, internal_strlen(s2) + 1);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s1,
+ r ? r - s1 + 1 : internal_strlen(s1) + 1);
+ }
+ return r;
+}
+
+#define INIT_STRPBRK COMMON_INTERCEPT_FUNCTION(strpbrk);
+#else
+#define INIT_STRPBRK
+#endif
+
+#if SANITIZER_INTERCEPT_MEMSET
+INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size);
+}
+
+#define INIT_MEMSET COMMON_INTERCEPT_FUNCTION(memset)
+#else
+#define INIT_MEMSET
+#endif
+
+#if SANITIZER_INTERCEPT_MEMMOVE
+INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
+}
+
+#define INIT_MEMMOVE COMMON_INTERCEPT_FUNCTION(memmove)
+#else
+#define INIT_MEMMOVE
+#endif
+
+#if SANITIZER_INTERCEPT_MEMCPY
+INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
+ // On OS X, calling internal_memcpy here will cause memory corruptions,
+ // because memcpy and memmove are actually aliases of the same
+ // implementation. We need to use internal_memmove here.
+ // N.B.: If we switch this to internal_ we'll have to use internal_memmove
+ // due to memcpy being an alias of memmove on OS X.
+ void *ctx;
+#if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
+ COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size);
+#else
+ COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
+#endif
+}
+
+#define INIT_MEMCPY \
+ do { \
+ if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { \
+ COMMON_INTERCEPT_FUNCTION(memcpy); \
+ } else { \
+ ASSIGN_REAL(memcpy, memmove); \
+ } \
+ CHECK(REAL(memcpy)); \
+ } while (false)
+
+#else
+#define INIT_MEMCPY
+#endif
+
+#if SANITIZER_INTERCEPT_MEMCMP
+DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, uptr called_pc,
+ const void *s1, const void *s2, uptr n,
+ int result)
+
+// Common code for `memcmp` and `bcmp`.
+int MemcmpInterceptorCommon(void *ctx,
+ int (*real_fn)(const void *, const void *, uptr),
+ const void *a1, const void *a2, uptr size) {
+ if (common_flags()->intercept_memcmp) {
+ if (common_flags()->strict_memcmp) {
+ // Check the entire regions even if the first bytes of the buffers are
+ // different.
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, a1, size);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, a2, size);
+ // Fallthrough to REAL(memcmp) below.
+ } else {
+ unsigned char c1 = 0, c2 = 0;
+ const unsigned char *s1 = (const unsigned char*)a1;
+ const unsigned char *s2 = (const unsigned char*)a2;
+ uptr i;
+ for (i = 0; i < size; i++) {
+ c1 = s1[i];
+ c2 = s2[i];
+ if (c1 != c2) break;
+ }
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
+ int r = CharCmpX(c1, c2);
+ CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(),
+ a1, a2, size, r);
+ return r;
+ }
+ }
+ int result = real_fn(a1, a2, size);
+ CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1,
+ a2, size, result);
+ return result;
+}
+
+INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return internal_memcmp(a1, a2, size);
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
+ return MemcmpInterceptorCommon(ctx, REAL(memcmp), a1, a2, size);
+}
+
+#define INIT_MEMCMP COMMON_INTERCEPT_FUNCTION(memcmp)
+#else
+#define INIT_MEMCMP
+#endif
+
+#if SANITIZER_INTERCEPT_BCMP
+INTERCEPTOR(int, bcmp, const void *a1, const void *a2, uptr size) {
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return internal_memcmp(a1, a2, size);
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, bcmp, a1, a2, size);
+ return MemcmpInterceptorCommon(ctx, REAL(bcmp), a1, a2, size);
+}
+
+#define INIT_BCMP COMMON_INTERCEPT_FUNCTION(bcmp)
+#else
+#define INIT_BCMP
+#endif
+
+#if SANITIZER_INTERCEPT_MEMCHR
+INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) {
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return internal_memchr(s, c, n);
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, memchr, s, c, n);
+#if SANITIZER_WINDOWS
+ void *res;
+ if (REAL(memchr)) {
+ res = REAL(memchr)(s, c, n);
+ } else {
+ res = internal_memchr(s, c, n);
+ }
+#else
+ void *res = REAL(memchr)(s, c, n);
+#endif
+ uptr len = res ? (char *)res - (const char *)s + 1 : n;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, len);
+ return res;
+}
+
+#define INIT_MEMCHR COMMON_INTERCEPT_FUNCTION(memchr)
+#else
+#define INIT_MEMCHR
+#endif
+
+#if SANITIZER_INTERCEPT_MEMRCHR
+INTERCEPTOR(void*, memrchr, const void *s, int c, SIZE_T n) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, memrchr, s, c, n);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, n);
+ return REAL(memrchr)(s, c, n);
+}
+
+#define INIT_MEMRCHR COMMON_INTERCEPT_FUNCTION(memrchr)
+#else
+#define INIT_MEMRCHR
+#endif
+
+#if SANITIZER_INTERCEPT_FREXP
+INTERCEPTOR(double, frexp, double x, int *exp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, frexp, x, exp);
+ // Assuming frexp() always writes to |exp|.
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
+ double res = REAL(frexp)(x, exp);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp));
+ return res;
+}
+
+#define INIT_FREXP COMMON_INTERCEPT_FUNCTION(frexp);
+#else
+#define INIT_FREXP
+#endif // SANITIZER_INTERCEPT_FREXP
+
+#if SANITIZER_INTERCEPT_FREXPF_FREXPL
+INTERCEPTOR(float, frexpf, float x, int *exp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
+ float res = REAL(frexpf)(x, exp);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp));
+ return res;
+}
+
+INTERCEPTOR(long double, frexpl, long double x, int *exp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
+ long double res = REAL(frexpl)(x, exp);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp));
+ return res;
+}
+
+#define INIT_FREXPF_FREXPL \
+ COMMON_INTERCEPT_FUNCTION(frexpf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(frexpl)
+#else
+#define INIT_FREXPF_FREXPL
+#endif // SANITIZER_INTERCEPT_FREXPF_FREXPL
+
+#if SI_POSIX
+static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec,
+ SIZE_T iovlen, SIZE_T maxlen) {
+ for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
+ SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec[i].iov_base, sz);
+ maxlen -= sz;
+ }
+}
+
+static void read_iovec(void *ctx, struct __sanitizer_iovec *iovec,
+ SIZE_T iovlen, SIZE_T maxlen) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec) * iovlen);
+ for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
+ SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec[i].iov_base, sz);
+ maxlen -= sz;
+ }
+}
+#endif
+
+#if SANITIZER_INTERCEPT_READ
+INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SSIZE_T res = REAL(read)(fd, ptr, count);
+ if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
+ if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ return res;
+}
+#define INIT_READ COMMON_INTERCEPT_FUNCTION(read)
+#else
+#define INIT_READ
+#endif
+
+#if SANITIZER_INTERCEPT_FREAD
+INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
+ // libc file streams can call user-supplied functions, see fopencookie.
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, file);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
+ if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res * size);
+ return res;
+}
+#define INIT_FREAD COMMON_INTERCEPT_FUNCTION(fread)
+#else
+#define INIT_FREAD
+#endif
+
+#if SANITIZER_INTERCEPT_PREAD
+INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
+ if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
+ if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ return res;
+}
+#define INIT_PREAD COMMON_INTERCEPT_FUNCTION(pread)
+#else
+#define INIT_PREAD
+#endif
+
+#if SANITIZER_INTERCEPT_PREAD64
+INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
+ if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
+ if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ return res;
+}
+#define INIT_PREAD64 COMMON_INTERCEPT_FUNCTION(pread64)
+#else
+#define INIT_PREAD64
+#endif
+
+#if SANITIZER_INTERCEPT_READV
+INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
+ int iovcnt) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ SSIZE_T res = REAL(readv)(fd, iov, iovcnt);
+ if (res > 0) write_iovec(ctx, iov, iovcnt, res);
+ if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ return res;
+}
+#define INIT_READV COMMON_INTERCEPT_FUNCTION(readv)
+#else
+#define INIT_READV
+#endif
+
+#if SANITIZER_INTERCEPT_PREADV
+INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
+ OFF_T offset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset);
+ if (res > 0) write_iovec(ctx, iov, iovcnt, res);
+ if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ return res;
+}
+#define INIT_PREADV COMMON_INTERCEPT_FUNCTION(preadv)
+#else
+#define INIT_PREADV
+#endif
+
+#if SANITIZER_INTERCEPT_PREADV64
+INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
+ OFF64_T offset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset);
+ if (res > 0) write_iovec(ctx, iov, iovcnt, res);
+ if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ return res;
+}
+#define INIT_PREADV64 COMMON_INTERCEPT_FUNCTION(preadv64)
+#else
+#define INIT_PREADV64
+#endif
+
+#if SANITIZER_INTERCEPT_WRITE
+INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ SSIZE_T res = REAL(write)(fd, ptr, count);
+ // FIXME: this check should be _before_ the call to REAL(write), not after
+ if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
+ return res;
+}
+#define INIT_WRITE COMMON_INTERCEPT_FUNCTION(write)
+#else
+#define INIT_WRITE
+#endif
+
+#if SANITIZER_INTERCEPT_FWRITE
+INTERCEPTOR(SIZE_T, fwrite, const void *p, uptr size, uptr nmemb, void *file) {
+ // libc file streams can call user-supplied functions, see fopencookie.
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, file);
+ SIZE_T res = REAL(fwrite)(p, size, nmemb, file);
+ if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, p, res * size);
+ return res;
+}
+#define INIT_FWRITE COMMON_INTERCEPT_FUNCTION(fwrite)
+#else
+#define INIT_FWRITE
+#endif
+
+#if SANITIZER_INTERCEPT_PWRITE
+INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
+ if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
+ return res;
+}
+#define INIT_PWRITE COMMON_INTERCEPT_FUNCTION(pwrite)
+#else
+#define INIT_PWRITE
+#endif
+
+#if SANITIZER_INTERCEPT_PWRITE64
+INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
+ OFF64_T offset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
+ if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
+ return res;
+}
+#define INIT_PWRITE64 COMMON_INTERCEPT_FUNCTION(pwrite64)
+#else
+#define INIT_PWRITE64
+#endif
+
+#if SANITIZER_INTERCEPT_WRITEV
+INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
+ int iovcnt) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ SSIZE_T res = REAL(writev)(fd, iov, iovcnt);
+ if (res > 0) read_iovec(ctx, iov, iovcnt, res);
+ return res;
+}
+#define INIT_WRITEV COMMON_INTERCEPT_FUNCTION(writev)
+#else
+#define INIT_WRITEV
+#endif
+
+#if SANITIZER_INTERCEPT_PWRITEV
+INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
+ OFF_T offset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset);
+ if (res > 0) read_iovec(ctx, iov, iovcnt, res);
+ return res;
+}
+#define INIT_PWRITEV COMMON_INTERCEPT_FUNCTION(pwritev)
+#else
+#define INIT_PWRITEV
+#endif
+
+#if SANITIZER_INTERCEPT_PWRITEV64
+INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt,
+ OFF64_T offset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset);
+ if (res > 0) read_iovec(ctx, iov, iovcnt, res);
+ return res;
+}
+#define INIT_PWRITEV64 COMMON_INTERCEPT_FUNCTION(pwritev64)
+#else
+#define INIT_PWRITEV64
+#endif
+
+#if SANITIZER_INTERCEPT_FGETS
+INTERCEPTOR(char *, fgets, char *s, SIZE_T size, void *file) {
+ // libc file streams can call user-supplied functions, see fopencookie.
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fgets, s, size, file);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *res = REAL(fgets)(s, size, file);
+ if (res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
+ return res;
+}
+#define INIT_FGETS COMMON_INTERCEPT_FUNCTION(fgets)
+#else
+#define INIT_FGETS
+#endif
+
+#if SANITIZER_INTERCEPT_FPUTS
+INTERCEPTOR_WITH_SUFFIX(int, fputs, char *s, void *file) {
+ // libc file streams can call user-supplied functions, see fopencookie.
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fputs, s, file);
+ if (!SANITIZER_APPLE || s) { // `fputs(NULL, file)` is supported on Darwin.
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
+ }
+ return REAL(fputs)(s, file);
+}
+#define INIT_FPUTS COMMON_INTERCEPT_FUNCTION(fputs)
+#else
+#define INIT_FPUTS
+#endif
+
+#if SANITIZER_INTERCEPT_PUTS
+INTERCEPTOR(int, puts, char *s) {
+ // libc file streams can call user-supplied functions, see fopencookie.
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, puts, s);
+ if (!SANITIZER_APPLE || s) { // `puts(NULL)` is supported on Darwin.
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
+ }
+ return REAL(puts)(s);
+}
+#define INIT_PUTS COMMON_INTERCEPT_FUNCTION(puts)
+#else
+#define INIT_PUTS
+#endif
+
+#if SANITIZER_INTERCEPT_PRCTL
+INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
+ static const int PR_SET_NAME = 15;
+ static const int PR_SET_VMA = 0x53564d41;
+ static const int PR_SCHED_CORE = 62;
+ static const int PR_SCHED_CORE_GET = 0;
+ if (option == PR_SET_VMA && arg2 == 0UL) {
+ char *name = (char *)arg5;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ }
+ int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
+ if (option == PR_SET_NAME) {
+ char buff[16];
+ internal_strncpy(buff, (char *)arg2, 15);
+ buff[15] = 0;
+ COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
+ } else if (res != -1 && option == PR_SCHED_CORE && arg2 == PR_SCHED_CORE_GET) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (u64*)(arg5), sizeof(u64));
+ }
+ return res;
+}
+#define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)
+#else
+#define INIT_PRCTL
+#endif // SANITIZER_INTERCEPT_PRCTL
+
+#if SANITIZER_INTERCEPT_TIME
+INTERCEPTOR(unsigned long, time, unsigned long *t) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, time, t);
+ unsigned long local_t;
+ unsigned long res = REAL(time)(&local_t);
+ if (t && res != (unsigned long)-1) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, t, sizeof(*t));
+ *t = local_t;
+ }
+ return res;
+}
+#define INIT_TIME COMMON_INTERCEPT_FUNCTION(time);
+#else
+#define INIT_TIME
+#endif // SANITIZER_INTERCEPT_TIME
+
+#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
+static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
+#if !SANITIZER_SOLARIS
+ if (tm->tm_zone) {
+ // Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone
+ // can point to shared memory and tsan would report a data race.
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(tm->tm_zone,
+ internal_strlen(tm->tm_zone) + 1);
+ }
+#endif
+}
+INTERCEPTOR(__sanitizer_tm *, localtime, unsigned long *timep) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
+ __sanitizer_tm *res = REAL(localtime)(timep);
+ if (res) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
+ unpoison_tm(ctx, res);
+ }
+ return res;
+}
+INTERCEPTOR(__sanitizer_tm *, localtime_r, unsigned long *timep, void *result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
+ __sanitizer_tm *res = REAL(localtime_r)(timep, result);
+ if (res) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
+ unpoison_tm(ctx, res);
+ }
+ return res;
+}
+INTERCEPTOR(__sanitizer_tm *, gmtime, unsigned long *timep) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
+ __sanitizer_tm *res = REAL(gmtime)(timep);
+ if (res) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
+ unpoison_tm(ctx, res);
+ }
+ return res;
+}
+INTERCEPTOR(__sanitizer_tm *, gmtime_r, unsigned long *timep, void *result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
+ __sanitizer_tm *res = REAL(gmtime_r)(timep, result);
+ if (res) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
+ unpoison_tm(ctx, res);
+ }
+ return res;
+}
+INTERCEPTOR(char *, ctime, unsigned long *timep) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *res = REAL(ctime)(timep);
+ if (res) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
+ }
+ return res;
+}
+INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *res = REAL(ctime_r)(timep, result);
+ if (res) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
+ }
+ return res;
+}
+INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *res = REAL(asctime)(tm);
+ if (res) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
+ }
+ return res;
+}
+INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *res = REAL(asctime_r)(tm, result);
+ if (res) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
+ }
+ return res;
+}
+INTERCEPTOR(long, mktime, __sanitizer_tm *tm) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, mktime, tm);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_sec, sizeof(tm->tm_sec));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_min, sizeof(tm->tm_min));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_hour, sizeof(tm->tm_hour));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mday, sizeof(tm->tm_mday));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mon, sizeof(tm->tm_mon));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_year, sizeof(tm->tm_year));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_isdst, sizeof(tm->tm_isdst));
+ long res = REAL(mktime)(tm);
+ if (res != -1) unpoison_tm(ctx, tm);
+ return res;
+}
+#define INIT_LOCALTIME_AND_FRIENDS \
+ COMMON_INTERCEPT_FUNCTION(localtime); \
+ COMMON_INTERCEPT_FUNCTION(localtime_r); \
+ COMMON_INTERCEPT_FUNCTION(gmtime); \
+ COMMON_INTERCEPT_FUNCTION(gmtime_r); \
+ COMMON_INTERCEPT_FUNCTION(ctime); \
+ COMMON_INTERCEPT_FUNCTION(ctime_r); \
+ COMMON_INTERCEPT_FUNCTION(asctime); \
+ COMMON_INTERCEPT_FUNCTION(asctime_r); \
+ COMMON_INTERCEPT_FUNCTION(mktime);
+#else
+#define INIT_LOCALTIME_AND_FRIENDS
+#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
+
+#if SANITIZER_INTERCEPT_STRPTIME
+INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strptime, s, format, tm);
+ if (format)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *res = REAL(strptime)(s, format, tm);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, s, res ? res - s : 0);
+ if (res && tm) {
+ // Do not call unpoison_tm here, because strptime does not, in fact,
+ // initialize the entire struct tm. For example, tm_zone pointer is left
+ // uninitialized.
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
+ }
+ return res;
+}
+#define INIT_STRPTIME COMMON_INTERCEPT_FUNCTION(strptime);
+#else
+#define INIT_STRPTIME
+#endif
+
+#if SANITIZER_INTERCEPT_SCANF || SANITIZER_INTERCEPT_PRINTF
+#include "sanitizer_common_interceptors_format.inc"
+
+#define FORMAT_INTERCEPTOR_IMPL(name, vname, ...) \
+ { \
+ void *ctx; \
+ va_list ap; \
+ va_start(ap, format); \
+ COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__, ap); \
+ int res = WRAP(vname)(__VA_ARGS__, ap); \
+ va_end(ap); \
+ return res; \
+ }
+
+#endif
+
+#if SANITIZER_INTERCEPT_SCANF
+
+#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...) \
+ { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__); \
+ va_list aq; \
+ va_copy(aq, ap); \
+ int res = REAL(vname)(__VA_ARGS__); \
+ if (res > 0) \
+ scanf_common(ctx, res, allowGnuMalloc, format, aq); \
+ va_end(aq); \
+ return res; \
+ }
+
+INTERCEPTOR(int, vscanf, const char *format, va_list ap)
+VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)
+
+INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
+VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)
+
+INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
+VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)
+
+#if SANITIZER_INTERCEPT_ISOC99_SCANF
+INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
+VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)
+
+INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
+ va_list ap)
+VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)
+
+INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
+VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
+#endif // SANITIZER_INTERCEPT_ISOC99_SCANF
+
+INTERCEPTOR(int, scanf, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(scanf, vscanf, format)
+
+INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
+
+INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
+
+#if SANITIZER_INTERCEPT_ISOC99_SCANF
+INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
+
+INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
+
+INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
+#endif
+
+#endif
+
+#if SANITIZER_INTERCEPT_SCANF
+#define INIT_SCANF \
+ COMMON_INTERCEPT_FUNCTION_LDBL(scanf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(sscanf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(fscanf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(vscanf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(vsscanf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(vfscanf);
+#else
+#define INIT_SCANF
+#endif
+
+#if SANITIZER_INTERCEPT_ISOC99_SCANF
+#define INIT_ISOC99_SCANF \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_scanf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_sscanf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_fscanf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_vscanf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_vsscanf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf);
+#else
+#define INIT_ISOC99_SCANF
+#endif
+
+#if SANITIZER_INTERCEPT_PRINTF
+
+#define VPRINTF_INTERCEPTOR_ENTER(vname, ...) \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__); \
+ va_list aq; \
+ va_copy(aq, ap);
+
+#define VPRINTF_INTERCEPTOR_RETURN() \
+ va_end(aq);
+
+#define VPRINTF_INTERCEPTOR_IMPL(vname, ...) \
+ { \
+ VPRINTF_INTERCEPTOR_ENTER(vname, __VA_ARGS__); \
+ if (common_flags()->check_printf) \
+ printf_common(ctx, format, aq); \
+ int res = REAL(vname)(__VA_ARGS__); \
+ VPRINTF_INTERCEPTOR_RETURN(); \
+ return res; \
+ }
+
+// FIXME: under ASan the REAL() call below may write to freed memory and
+// corrupt its metadata. See
+// https://github.com/google/sanitizers/issues/321.
+#define VSPRINTF_INTERCEPTOR_IMPL(vname, str, ...) \
+ { \
+ VPRINTF_INTERCEPTOR_ENTER(vname, str, __VA_ARGS__) \
+ if (common_flags()->check_printf) { \
+ printf_common(ctx, format, aq); \
+ } \
+ int res = REAL(vname)(str, __VA_ARGS__); \
+ if (res >= 0) { \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, res + 1); \
+ } \
+ VPRINTF_INTERCEPTOR_RETURN(); \
+ return res; \
+ }
+
+// FIXME: under ASan the REAL() call below may write to freed memory and
+// corrupt its metadata. See
+// https://github.com/google/sanitizers/issues/321.
+#define VSNPRINTF_INTERCEPTOR_IMPL(vname, str, size, ...) \
+ { \
+ VPRINTF_INTERCEPTOR_ENTER(vname, str, size, __VA_ARGS__) \
+ if (common_flags()->check_printf) { \
+ printf_common(ctx, format, aq); \
+ } \
+ int res = REAL(vname)(str, size, __VA_ARGS__); \
+ if (res >= 0) { \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, Min(size, (SIZE_T)(res + 1))); \
+ } \
+ VPRINTF_INTERCEPTOR_RETURN(); \
+ return res; \
+ }
+
+// FIXME: under ASan the REAL() call below may write to freed memory and
+// corrupt its metadata. See
+// https://github.com/google/sanitizers/issues/321.
+#define VASPRINTF_INTERCEPTOR_IMPL(vname, strp, ...) \
+ { \
+ VPRINTF_INTERCEPTOR_ENTER(vname, strp, __VA_ARGS__) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, strp, sizeof(char *)); \
+ if (common_flags()->check_printf) { \
+ printf_common(ctx, format, aq); \
+ } \
+ int res = REAL(vname)(strp, __VA_ARGS__); \
+ if (res >= 0) { \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *strp, res + 1); \
+ } \
+ VPRINTF_INTERCEPTOR_RETURN(); \
+ return res; \
+ }
+
+INTERCEPTOR(int, vprintf, const char *format, va_list ap)
+VPRINTF_INTERCEPTOR_IMPL(vprintf, format, ap)
+
+INTERCEPTOR(int, vfprintf, __sanitizer_FILE *stream, const char *format,
+ va_list ap)
+VPRINTF_INTERCEPTOR_IMPL(vfprintf, stream, format, ap)
+
+INTERCEPTOR(int, vsnprintf, char *str, SIZE_T size, const char *format,
+ va_list ap)
+VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)
+
+#if SANITIZER_INTERCEPT___PRINTF_CHK
+INTERCEPTOR(int, __vsnprintf_chk, char *str, SIZE_T size, int flag,
+ SIZE_T size_to, const char *format, va_list ap)
+VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)
+#endif
+
+#if SANITIZER_INTERCEPT_PRINTF_L
+INTERCEPTOR(int, vsnprintf_l, char *str, SIZE_T size, void *loc,
+ const char *format, va_list ap)
+VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf_l, str, size, loc, format, ap)
+
+INTERCEPTOR(int, snprintf_l, char *str, SIZE_T size, void *loc,
+ const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(snprintf_l, vsnprintf_l, str, size, loc, format)
+#endif // SANITIZER_INTERCEPT_PRINTF_L
+
+INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap)
+VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
+
+#if SANITIZER_INTERCEPT___PRINTF_CHK
+INTERCEPTOR(int, __vsprintf_chk, char *str, int flag, SIZE_T size_to,
+ const char *format, va_list ap)
+VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
+#endif
+
+INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap)
+VASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, ap)
+
+#if SANITIZER_INTERCEPT_ISOC99_PRINTF
+INTERCEPTOR(int, __isoc99_vprintf, const char *format, va_list ap)
+VPRINTF_INTERCEPTOR_IMPL(__isoc99_vprintf, format, ap)
+
+INTERCEPTOR(int, __isoc99_vfprintf, __sanitizer_FILE *stream,
+ const char *format, va_list ap)
+VPRINTF_INTERCEPTOR_IMPL(__isoc99_vfprintf, stream, format, ap)
+
+INTERCEPTOR(int, __isoc99_vsnprintf, char *str, SIZE_T size, const char *format,
+ va_list ap)
+VSNPRINTF_INTERCEPTOR_IMPL(__isoc99_vsnprintf, str, size, format, ap)
+
+INTERCEPTOR(int, __isoc99_vsprintf, char *str, const char *format,
+ va_list ap)
+VSPRINTF_INTERCEPTOR_IMPL(__isoc99_vsprintf, str, format,
+ ap)
+
+#endif // SANITIZER_INTERCEPT_ISOC99_PRINTF
+
+INTERCEPTOR(int, printf, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(printf, vprintf, format)
+
+INTERCEPTOR(int, fprintf, __sanitizer_FILE *stream, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(fprintf, vfprintf, stream, format)
+
+#if SANITIZER_INTERCEPT___PRINTF_CHK
+INTERCEPTOR(int, __fprintf_chk, __sanitizer_FILE *stream, SIZE_T size,
+ const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__fprintf_chk, vfprintf, stream, format)
+#endif
+
+INTERCEPTOR(int, sprintf, char *str, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format)
+
+#if SANITIZER_INTERCEPT___PRINTF_CHK
+INTERCEPTOR(int, __sprintf_chk, char *str, int flag, SIZE_T size_to,
+ const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format)
+#endif
+
+INTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(snprintf, vsnprintf, str, size, format)
+
+#if SANITIZER_INTERCEPT___PRINTF_CHK
+INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag,
+ SIZE_T size_to, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format)
+#endif
+
+INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, format)
+
+#if SANITIZER_INTERCEPT_ISOC99_PRINTF
+INTERCEPTOR(int, __isoc99_printf, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_printf, __isoc99_vprintf, format)
+
+INTERCEPTOR(int, __isoc99_fprintf, __sanitizer_FILE *stream, const char *format,
+ ...)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_fprintf, __isoc99_vfprintf, stream, format)
+
+INTERCEPTOR(int, __isoc99_sprintf, char *str, const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_sprintf, __isoc99_vsprintf, str, format)
+
+INTERCEPTOR(int, __isoc99_snprintf, char *str, SIZE_T size,
+ const char *format, ...)
+FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size,
+ format)
+
+#endif // SANITIZER_INTERCEPT_ISOC99_PRINTF
+
+#endif // SANITIZER_INTERCEPT_PRINTF
+
+#if SANITIZER_INTERCEPT_PRINTF
+#define INIT_PRINTF \
+ COMMON_INTERCEPT_FUNCTION_LDBL(printf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(sprintf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(snprintf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(asprintf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(fprintf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(vprintf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf);
+#else
+#define INIT_PRINTF
+#endif
+
+#if SANITIZER_INTERCEPT___PRINTF_CHK
+#define INIT___PRINTF_CHK \
+ COMMON_INTERCEPT_FUNCTION(__sprintf_chk); \
+ COMMON_INTERCEPT_FUNCTION(__snprintf_chk); \
+ COMMON_INTERCEPT_FUNCTION(__vsprintf_chk); \
+ COMMON_INTERCEPT_FUNCTION(__vsnprintf_chk); \
+ COMMON_INTERCEPT_FUNCTION(__fprintf_chk);
+#else
+#define INIT___PRINTF_CHK
+#endif
+
+#if SANITIZER_INTERCEPT_PRINTF_L
+#define INIT_PRINTF_L \
+ COMMON_INTERCEPT_FUNCTION(snprintf_l); \
+ COMMON_INTERCEPT_FUNCTION(vsnprintf_l);
+#else
+#define INIT_PRINTF_L
+#endif
+
+#if SANITIZER_INTERCEPT_ISOC99_PRINTF
+#define INIT_ISOC99_PRINTF \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_printf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_sprintf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_snprintf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_fprintf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_vprintf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_vsprintf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_vsnprintf); \
+ COMMON_INTERCEPT_FUNCTION(__isoc99_vfprintf);
+#else
+#define INIT_ISOC99_PRINTF
+#endif
+
+#if SANITIZER_INTERCEPT_IOCTL
+#include "sanitizer_common_interceptors_ioctl.inc"
+#include "sanitizer_interceptors_ioctl_netbsd.inc"
+INTERCEPTOR(int, ioctl, int d, unsigned long request, ...) {
+ // We need a frame pointer, because we call into ioctl_common_[pre|post] which
+ // can trigger a report and we need to be able to unwind through this
+ // function. On Mac in debug mode we might not have a frame pointer, because
+ // ioctl_common_[pre|post] doesn't get inlined here.
+ ENABLE_FRAME_POINTER;
+
+ void *ctx;
+ va_list ap;
+ va_start(ap, request);
+ void *arg = va_arg(ap, void *);
+ va_end(ap);
+ COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg);
+
+ CHECK(ioctl_initialized);
+
+ // Note: TSan does not use common flags, and they are zero-initialized.
+ // This effectively disables ioctl handling in TSan.
+ if (!common_flags()->handle_ioctl) return REAL(ioctl)(d, request, arg);
+
+ // Although request is unsigned long, the rest of the interceptor uses it
+ // as just "unsigned" to save space, because we know that all values fit in
+ // "unsigned" - they are compile-time constants.
+
+ const ioctl_desc *desc = ioctl_lookup(request);
+ ioctl_desc decoded_desc;
+ if (!desc) {
+ VPrintf(2, "Decoding unknown ioctl 0x%lx\n", request);
+ if (!ioctl_decode(request, &decoded_desc))
+ Printf("WARNING: failed decoding unknown ioctl 0x%lx\n", request);
+ else
+ desc = &decoded_desc;
+ }
+
+ if (desc) ioctl_common_pre(ctx, desc, d, request, arg);
+ int res = REAL(ioctl)(d, request, arg);
+ // FIXME: some ioctls have different return values for success and failure.
+ if (desc && res != -1) ioctl_common_post(ctx, desc, res, d, request, arg);
+ return res;
+}
+#define INIT_IOCTL \
+ ioctl_init(); \
+ COMMON_INTERCEPT_FUNCTION(ioctl);
+#else
+#define INIT_IOCTL
+#endif
+
+#if SANITIZER_POSIX
+UNUSED static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) {
+ if (pwd) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, sizeof(*pwd));
+ if (pwd->pw_name)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_name,
+ internal_strlen(pwd->pw_name) + 1);
+ if (pwd->pw_passwd)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_passwd,
+ internal_strlen(pwd->pw_passwd) + 1);
+#if !SANITIZER_ANDROID
+ if (pwd->pw_gecos)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_gecos,
+ internal_strlen(pwd->pw_gecos) + 1);
+#endif
+#if SANITIZER_APPLE || SANITIZER_FREEBSD || SANITIZER_NETBSD
+ if (pwd->pw_class)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_class,
+ internal_strlen(pwd->pw_class) + 1);
+#endif
+ if (pwd->pw_dir)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_dir,
+ internal_strlen(pwd->pw_dir) + 1);
+ if (pwd->pw_shell)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd->pw_shell,
+ internal_strlen(pwd->pw_shell) + 1);
+ }
+}
+
+UNUSED static void unpoison_group(void *ctx, __sanitizer_group *grp) {
+ if (grp) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, sizeof(*grp));
+ if (grp->gr_name)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_name,
+ internal_strlen(grp->gr_name) + 1);
+ if (grp->gr_passwd)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_passwd,
+ internal_strlen(grp->gr_passwd) + 1);
+ char **p = grp->gr_mem;
+ for (; *p; ++p) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
+ }
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp->gr_mem,
+ (p - grp->gr_mem + 1) * sizeof(*p));
+ }
+}
+#endif // SANITIZER_POSIX
+
+#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
+INTERCEPTOR(__sanitizer_passwd *, getpwnam, const char *name) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
+ if (name)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ __sanitizer_passwd *res = REAL(getpwnam)(name);
+ unpoison_passwd(ctx, res);
+ return res;
+}
+INTERCEPTOR(__sanitizer_passwd *, getpwuid, u32 uid) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
+ __sanitizer_passwd *res = REAL(getpwuid)(uid);
+ unpoison_passwd(ctx, res);
+ return res;
+}
+INTERCEPTOR(__sanitizer_group *, getgrnam, const char *name) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ __sanitizer_group *res = REAL(getgrnam)(name);
+ unpoison_group(ctx, res);
+ return res;
+}
+INTERCEPTOR(__sanitizer_group *, getgrgid, u32 gid) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
+ __sanitizer_group *res = REAL(getgrgid)(gid);
+ unpoison_group(ctx, res);
+ return res;
+}
+#define INIT_GETPWNAM_AND_FRIENDS \
+ COMMON_INTERCEPT_FUNCTION(getpwnam); \
+ COMMON_INTERCEPT_FUNCTION(getpwuid); \
+ COMMON_INTERCEPT_FUNCTION(getgrnam); \
+ COMMON_INTERCEPT_FUNCTION(getgrgid);
+#else
+#define INIT_GETPWNAM_AND_FRIENDS
+#endif
+
+#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
+INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd,
+ char *buf, SIZE_T buflen, __sanitizer_passwd **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
+ if (!res && result)
+ unpoison_passwd(ctx, *result);
+ if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ return res;
+}
+INTERCEPTOR(int, getpwuid_r, u32 uid, __sanitizer_passwd *pwd, char *buf,
+ SIZE_T buflen, __sanitizer_passwd **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
+ if (!res && result)
+ unpoison_passwd(ctx, *result);
+ if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ return res;
+}
+INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp,
+ char *buf, SIZE_T buflen, __sanitizer_group **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
+ if (!res && result)
+ unpoison_group(ctx, *result);
+ if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ return res;
+}
+INTERCEPTOR(int, getgrgid_r, u32 gid, __sanitizer_group *grp, char *buf,
+ SIZE_T buflen, __sanitizer_group **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
+ if (!res && result)
+ unpoison_group(ctx, *result);
+ if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ return res;
+}
+#define INIT_GETPWNAM_R_AND_FRIENDS \
+ COMMON_INTERCEPT_FUNCTION(getpwnam_r); \
+ COMMON_INTERCEPT_FUNCTION(getpwuid_r); \
+ COMMON_INTERCEPT_FUNCTION(getgrnam_r); \
+ COMMON_INTERCEPT_FUNCTION(getgrgid_r);
+#else
+#define INIT_GETPWNAM_R_AND_FRIENDS
+#endif
+
+#if SANITIZER_INTERCEPT_GETPWENT
+INTERCEPTOR(__sanitizer_passwd *, getpwent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpwent, dummy);
+ __sanitizer_passwd *res = REAL(getpwent)(dummy);
+ unpoison_passwd(ctx, res);
+ return res;
+}
+INTERCEPTOR(__sanitizer_group *, getgrent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgrent, dummy);
+ __sanitizer_group *res = REAL(getgrent)(dummy);
+ unpoison_group(ctx, res);
+ return res;
+}
+#define INIT_GETPWENT \
+ COMMON_INTERCEPT_FUNCTION(getpwent); \
+ COMMON_INTERCEPT_FUNCTION(getgrent);
+#else
+#define INIT_GETPWENT
+#endif
+
+#if SANITIZER_INTERCEPT_FGETPWENT
+INTERCEPTOR(__sanitizer_passwd *, fgetpwent, void *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent, fp);
+ __sanitizer_passwd *res = REAL(fgetpwent)(fp);
+ unpoison_passwd(ctx, res);
+ return res;
+}
+INTERCEPTOR(__sanitizer_group *, fgetgrent, void *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent, fp);
+ __sanitizer_group *res = REAL(fgetgrent)(fp);
+ unpoison_group(ctx, res);
+ return res;
+}
+#define INIT_FGETPWENT \
+ COMMON_INTERCEPT_FUNCTION(fgetpwent); \
+ COMMON_INTERCEPT_FUNCTION(fgetgrent);
+#else
+#define INIT_FGETPWENT
+#endif
+
+#if SANITIZER_INTERCEPT_GETPWENT_R
+INTERCEPTOR(int, getpwent_r, __sanitizer_passwd *pwbuf, char *buf,
+ SIZE_T buflen, __sanitizer_passwd **pwbufp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpwent_r, pwbuf, buf, buflen, pwbufp);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getpwent_r)(pwbuf, buf, buflen, pwbufp);
+ if (!res && pwbufp)
+ unpoison_passwd(ctx, *pwbufp);
+ if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
+ return res;
+}
+INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen,
+ __sanitizer_group **pwbufp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp);
+ if (!res && pwbufp)
+ unpoison_group(ctx, *pwbufp);
+ if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
+ return res;
+}
+#define INIT_GETPWENT_R \
+ COMMON_INTERCEPT_FUNCTION(getpwent_r); \
+ COMMON_INTERCEPT_FUNCTION(getgrent_r);
+#else
+#define INIT_GETPWENT_R
+#endif
+
+#if SANITIZER_INTERCEPT_FGETPWENT_R
+INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf,
+ SIZE_T buflen, __sanitizer_passwd **pwbufp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp);
+ if (!res && pwbufp)
+ unpoison_passwd(ctx, *pwbufp);
+ if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
+ return res;
+}
+#define INIT_FGETPWENT_R \
+ COMMON_INTERCEPT_FUNCTION(fgetpwent_r);
+#else
+#define INIT_FGETPWENT_R
+#endif
+
+#if SANITIZER_INTERCEPT_FGETGRENT_R
+INTERCEPTOR(int, fgetgrent_r, void *fp, __sanitizer_group *pwbuf, char *buf,
+ SIZE_T buflen, __sanitizer_group **pwbufp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(fgetgrent_r)(fp, pwbuf, buf, buflen, pwbufp);
+ if (!res && pwbufp)
+ unpoison_group(ctx, *pwbufp);
+ if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
+ return res;
+}
+#define INIT_FGETGRENT_R \
+ COMMON_INTERCEPT_FUNCTION(fgetgrent_r);
+#else
+#define INIT_FGETGRENT_R
+#endif
+
+#if SANITIZER_INTERCEPT_SETPWENT
+// The only thing these interceptors do is disable any nested interceptors.
+// These functions may open nss modules and call uninstrumented functions from
+// them, and we don't want things like strlen() to trigger.
+INTERCEPTOR(void, setpwent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, setpwent, dummy);
+ REAL(setpwent)(dummy);
+}
+INTERCEPTOR(void, endpwent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, endpwent, dummy);
+ REAL(endpwent)(dummy);
+}
+INTERCEPTOR(void, setgrent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, setgrent, dummy);
+ REAL(setgrent)(dummy);
+}
+INTERCEPTOR(void, endgrent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, endgrent, dummy);
+ REAL(endgrent)(dummy);
+}
+#define INIT_SETPWENT \
+ COMMON_INTERCEPT_FUNCTION(setpwent); \
+ COMMON_INTERCEPT_FUNCTION(endpwent); \
+ COMMON_INTERCEPT_FUNCTION(setgrent); \
+ COMMON_INTERCEPT_FUNCTION(endgrent);
+#else
+#define INIT_SETPWENT
+#endif
+
+#if SANITIZER_INTERCEPT_CLOCK_GETTIME
+INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(clock_getres)(clk_id, tp);
+ if (!res && tp) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
+ }
+ return res;
+}
+INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(clock_gettime)(clk_id, tp);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
+ }
+ return res;
+}
+#if SANITIZER_GLIBC
+namespace __sanitizer {
+extern "C" {
+int real_clock_gettime(u32 clk_id, void *tp) {
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return internal_clock_gettime(clk_id, tp);
+ return REAL(clock_gettime)(clk_id, tp);
+}
+} // extern "C"
+} // namespace __sanitizer
+#endif
+INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
+ return REAL(clock_settime)(clk_id, tp);
+}
+#define INIT_CLOCK_GETTIME \
+ COMMON_INTERCEPT_FUNCTION(clock_getres); \
+ COMMON_INTERCEPT_FUNCTION(clock_gettime); \
+ COMMON_INTERCEPT_FUNCTION(clock_settime);
+#else
+#define INIT_CLOCK_GETTIME
+#endif
+
+#if SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID
+INTERCEPTOR(int, clock_getcpuclockid, pid_t pid,
+ __sanitizer_clockid_t *clockid) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, clock_getcpuclockid, pid, clockid);
+ int res = REAL(clock_getcpuclockid)(pid, clockid);
+ if (!res && clockid) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, clockid, sizeof *clockid);
+ }
+ return res;
+}
+
+INTERCEPTOR(int, pthread_getcpuclockid, uptr thread,
+ __sanitizer_clockid_t *clockid) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_getcpuclockid, thread, clockid);
+ int res = REAL(pthread_getcpuclockid)(thread, clockid);
+ if (!res && clockid) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, clockid, sizeof *clockid);
+ }
+ return res;
+}
+
+#define INIT_CLOCK_GETCPUCLOCKID \
+ COMMON_INTERCEPT_FUNCTION(clock_getcpuclockid); \
+ COMMON_INTERCEPT_FUNCTION(pthread_getcpuclockid);
+#else
+#define INIT_CLOCK_GETCPUCLOCKID
+#endif
+
+#if SANITIZER_INTERCEPT_GETITIMER
+INTERCEPTOR(int, getitimer, int which, void *curr_value) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getitimer)(which, curr_value);
+ if (!res && curr_value) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
+ }
+ return res;
+}
+INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
+ if (new_value) {
+ // itimerval can contain padding that may be legitimately uninitialized
+ const struct __sanitizer_itimerval *nv =
+ (const struct __sanitizer_itimerval *)new_value;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_sec,
+ sizeof(__sanitizer_time_t));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_usec,
+ sizeof(__sanitizer_suseconds_t));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_sec,
+ sizeof(__sanitizer_time_t));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_usec,
+ sizeof(__sanitizer_suseconds_t));
+ }
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(setitimer)(which, new_value, old_value);
+ if (!res && old_value) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
+ }
+ return res;
+}
+#define INIT_GETITIMER \
+ COMMON_INTERCEPT_FUNCTION(getitimer); \
+ COMMON_INTERCEPT_FUNCTION(setitimer);
+#else
+#define INIT_GETITIMER
+#endif
+
+#if SANITIZER_INTERCEPT_GLOB
+static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
+ // +1 for NULL pointer at the end.
+ if (pglob->gl_pathv)
+ COMMON_INTERCEPTOR_WRITE_RANGE(
+ ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
+ for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
+ char *p = pglob->gl_pathv[i];
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, internal_strlen(p) + 1);
+ }
+}
+
+#if SANITIZER_SOLARIS
+INTERCEPTOR(int, glob, const char *pattern, int flags,
+ int (*errfunc)(const char *epath, int eerrno),
+ __sanitizer_glob_t *pglob) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
+ int res = REAL(glob)(pattern, flags, errfunc, pglob);
+ if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
+ return res;
+}
+#else
+static THREADLOCAL __sanitizer_glob_t *pglob_copy;
+
+static void wrapped_gl_closedir(void *dir) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ pglob_copy->gl_closedir(dir);
+}
+
+static void *wrapped_gl_readdir(void *dir) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ return pglob_copy->gl_readdir(dir);
+}
+
+static void *wrapped_gl_opendir(const char *s) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
+ return pglob_copy->gl_opendir(s);
+}
+
+static int wrapped_gl_lstat(const char *s, void *st) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
+ return pglob_copy->gl_lstat(s, st);
+}
+
+static int wrapped_gl_stat(const char *s, void *st) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, internal_strlen(s) + 1);
+ return pglob_copy->gl_stat(s, st);
+}
+
+static const __sanitizer_glob_t kGlobCopy = {
+ 0, 0, 0,
+ 0, wrapped_gl_closedir, wrapped_gl_readdir,
+ wrapped_gl_opendir, wrapped_gl_lstat, wrapped_gl_stat};
+
+INTERCEPTOR(int, glob, const char *pattern, int flags,
+ int (*errfunc)(const char *epath, int eerrno),
+ __sanitizer_glob_t *pglob) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
+ __sanitizer_glob_t glob_copy;
+ internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
+ if (flags & glob_altdirfunc) {
+ Swap(pglob->gl_closedir, glob_copy.gl_closedir);
+ Swap(pglob->gl_readdir, glob_copy.gl_readdir);
+ Swap(pglob->gl_opendir, glob_copy.gl_opendir);
+ Swap(pglob->gl_lstat, glob_copy.gl_lstat);
+ Swap(pglob->gl_stat, glob_copy.gl_stat);
+ pglob_copy = &glob_copy;
+ }
+ int res = REAL(glob)(pattern, flags, errfunc, pglob);
+ if (flags & glob_altdirfunc) {
+ Swap(pglob->gl_closedir, glob_copy.gl_closedir);
+ Swap(pglob->gl_readdir, glob_copy.gl_readdir);
+ Swap(pglob->gl_opendir, glob_copy.gl_opendir);
+ Swap(pglob->gl_lstat, glob_copy.gl_lstat);
+ Swap(pglob->gl_stat, glob_copy.gl_stat);
+ }
+ pglob_copy = 0;
+ if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
+ return res;
+}
+#endif // SANITIZER_SOLARIS
+#define INIT_GLOB \
+ COMMON_INTERCEPT_FUNCTION(glob);
+#else // SANITIZER_INTERCEPT_GLOB
+#define INIT_GLOB
+#endif // SANITIZER_INTERCEPT_GLOB
+
+#if SANITIZER_INTERCEPT_GLOB64
+INTERCEPTOR(int, glob64, const char *pattern, int flags,
+ int (*errfunc)(const char *epath, int eerrno),
+ __sanitizer_glob_t *pglob) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
+ __sanitizer_glob_t glob_copy;
+ internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
+ if (flags & glob_altdirfunc) {
+ Swap(pglob->gl_closedir, glob_copy.gl_closedir);
+ Swap(pglob->gl_readdir, glob_copy.gl_readdir);
+ Swap(pglob->gl_opendir, glob_copy.gl_opendir);
+ Swap(pglob->gl_lstat, glob_copy.gl_lstat);
+ Swap(pglob->gl_stat, glob_copy.gl_stat);
+ pglob_copy = &glob_copy;
+ }
+ int res = REAL(glob64)(pattern, flags, errfunc, pglob);
+ if (flags & glob_altdirfunc) {
+ Swap(pglob->gl_closedir, glob_copy.gl_closedir);
+ Swap(pglob->gl_readdir, glob_copy.gl_readdir);
+ Swap(pglob->gl_opendir, glob_copy.gl_opendir);
+ Swap(pglob->gl_lstat, glob_copy.gl_lstat);
+ Swap(pglob->gl_stat, glob_copy.gl_stat);
+ }
+ pglob_copy = 0;
+ if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
+ return res;
+}
+#define INIT_GLOB64 \
+ COMMON_INTERCEPT_FUNCTION(glob64);
+#else // SANITIZER_INTERCEPT_GLOB64
+#define INIT_GLOB64
+#endif // SANITIZER_INTERCEPT_GLOB64
+
+#if SANITIZER_INTERCEPT___B64_TO
+INTERCEPTOR(int, __b64_ntop, unsigned char const *src, SIZE_T srclength,
+ char *target, SIZE_T targsize) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __b64_ntop, src, srclength, target, targsize);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, srclength);
+ int res = REAL(__b64_ntop)(src, srclength, target, targsize);
+ if (res >= 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, target, res + 1);
+ return res;
+}
+INTERCEPTOR(int, __b64_pton, char const *src, char *target, SIZE_T targsize) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __b64_pton, src, target, targsize);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
+ int res = REAL(__b64_pton)(src, target, targsize);
+ if (res >= 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, target, res);
+ return res;
+}
+#define INIT___B64_TO \
+ COMMON_INTERCEPT_FUNCTION(__b64_ntop); \
+ COMMON_INTERCEPT_FUNCTION(__b64_pton);
+#else // SANITIZER_INTERCEPT___B64_TO
+#define INIT___B64_TO
+#endif // SANITIZER_INTERCEPT___B64_TO
+
+#if SANITIZER_INTERCEPT_DN_COMP_EXPAND
+# if __GLIBC_PREREQ(2, 34)
+// Changed with https://sourceware.org/git/?p=glibc.git;h=640bbdf
+# define DN_COMP_INTERCEPTOR_NAME dn_comp
+# define DN_EXPAND_INTERCEPTOR_NAME dn_expand
+# else
+# define DN_COMP_INTERCEPTOR_NAME __dn_comp
+# define DN_EXPAND_INTERCEPTOR_NAME __dn_expand
+# endif
+INTERCEPTOR(int, DN_COMP_INTERCEPTOR_NAME, unsigned char *exp_dn,
+ unsigned char *comp_dn, int length, unsigned char **dnptrs,
+ unsigned char **lastdnptr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, DN_COMP_INTERCEPTOR_NAME, exp_dn, comp_dn,
+ length, dnptrs, lastdnptr);
+ int res = REAL(DN_COMP_INTERCEPTOR_NAME)(exp_dn, comp_dn, length, dnptrs,
+ lastdnptr);
+ if (res >= 0) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, comp_dn, res);
+ if (dnptrs && lastdnptr) {
+ unsigned char **p = dnptrs;
+ for (; p != lastdnptr && *p; ++p)
+ ;
+ if (p != lastdnptr)
+ ++p;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dnptrs, (p - dnptrs) * sizeof(*p));
+ }
+ }
+ return res;
+}
+INTERCEPTOR(int, DN_EXPAND_INTERCEPTOR_NAME, unsigned char const *base,
+ unsigned char const *end, unsigned char const *src, char *dest,
+ int space) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, DN_EXPAND_INTERCEPTOR_NAME, base, end, src,
+ dest, space);
+ // TODO: add read check if __dn_comp intercept added
+ int res = REAL(DN_EXPAND_INTERCEPTOR_NAME)(base, end, src, dest, space);
+ if (res >= 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, internal_strlen(dest) + 1);
+ return res;
+}
+# define INIT_DN_COMP_EXPAND \
+ COMMON_INTERCEPT_FUNCTION(DN_COMP_INTERCEPTOR_NAME); \
+ COMMON_INTERCEPT_FUNCTION(DN_EXPAND_INTERCEPTOR_NAME);
+#else // SANITIZER_INTERCEPT_DN_COMP_EXPAND
+# define INIT_DN_COMP_EXPAND
+#endif // SANITIZER_INTERCEPT_DN_COMP_EXPAND
+
+#if SANITIZER_INTERCEPT_POSIX_SPAWN
+
+template <class RealSpawnPtr>
+static int PosixSpawnImpl(void *ctx, RealSpawnPtr *real_posix_spawn, pid_t *pid,
+ const char *file_or_path, const void *file_actions,
+ const void *attrp, char *const argv[],
+ char *const envp[]) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, file_or_path,
+ internal_strlen(file_or_path) + 1);
+ if (argv) {
+ for (char *const *s = argv; ; ++s) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(*s));
+ if (!*s) break;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *s, internal_strlen(*s) + 1);
+ }
+ }
+ if (envp) {
+ for (char *const *s = envp; ; ++s) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(*s));
+ if (!*s) break;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *s, internal_strlen(*s) + 1);
+ }
+ }
+ int res =
+ real_posix_spawn(pid, file_or_path, file_actions, attrp, argv, envp);
+ if (res == 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pid, sizeof(*pid));
+ return res;
+}
+INTERCEPTOR(int, posix_spawn, pid_t *pid, const char *path,
+ const void *file_actions, const void *attrp, char *const argv[],
+ char *const envp[]) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, posix_spawn, pid, path, file_actions, attrp,
+ argv, envp);
+ return PosixSpawnImpl(ctx, REAL(posix_spawn), pid, path, file_actions, attrp,
+ argv, envp);
+}
+INTERCEPTOR(int, posix_spawnp, pid_t *pid, const char *file,
+ const void *file_actions, const void *attrp, char *const argv[],
+ char *const envp[]) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, posix_spawnp, pid, file, file_actions, attrp,
+ argv, envp);
+ return PosixSpawnImpl(ctx, REAL(posix_spawnp), pid, file, file_actions, attrp,
+ argv, envp);
+}
+# define INIT_POSIX_SPAWN \
+ COMMON_INTERCEPT_FUNCTION(posix_spawn); \
+ COMMON_INTERCEPT_FUNCTION(posix_spawnp);
+#else // SANITIZER_INTERCEPT_POSIX_SPAWN
+# define INIT_POSIX_SPAWN
+#endif // SANITIZER_INTERCEPT_POSIX_SPAWN
+
+#if SANITIZER_INTERCEPT_WAIT
+// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
+// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
+// details.
+INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(wait)(status);
+ if (res != -1 && status)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
+ return res;
+}
+// On FreeBSD id_t is always 64-bit wide.
+#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
+INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, long long id, void *infop,
+ int options) {
+#else
+INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
+ int options) {
+#endif
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(waitid)(idtype, id, infop, options);
+ if (res != -1 && infop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
+ return res;
+}
+INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(waitpid)(pid, status, options);
+ if (res != -1 && status)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
+ return res;
+}
+INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(wait3)(status, options, rusage);
+ if (res != -1) {
+ if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
+ if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
+ }
+ return res;
+}
+#if SANITIZER_ANDROID
+INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __wait4, pid, status, options, rusage);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(__wait4)(pid, status, options, rusage);
+ if (res != -1) {
+ if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
+ if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
+ }
+ return res;
+}
+#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(__wait4);
+#else
+INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(wait4)(pid, status, options, rusage);
+ if (res != -1) {
+ if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
+ if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
+ }
+ return res;
+}
+#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(wait4);
+#endif // SANITIZER_ANDROID
+#define INIT_WAIT \
+ COMMON_INTERCEPT_FUNCTION(wait); \
+ COMMON_INTERCEPT_FUNCTION(waitid); \
+ COMMON_INTERCEPT_FUNCTION(waitpid); \
+ COMMON_INTERCEPT_FUNCTION(wait3);
+#else
+#define INIT_WAIT
+#define INIT_WAIT4
+#endif
+
+#if SANITIZER_INTERCEPT_INET
+INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
+ uptr sz = __sanitizer_in_addr_sz(af);
+ if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
+ // FIXME: figure out read size based on the address family.
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *res = REAL(inet_ntop)(af, src, dst, size);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
+ return res;
+}
+INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, src, 0);
+ // FIXME: figure out read size based on the address family.
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(inet_pton)(af, src, dst);
+ if (res == 1) {
+ uptr sz = __sanitizer_in_addr_sz(af);
+ if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
+ }
+ return res;
+}
+#define INIT_INET \
+ COMMON_INTERCEPT_FUNCTION(inet_ntop); \
+ COMMON_INTERCEPT_FUNCTION(inet_pton);
+#else
+#define INIT_INET
+#endif
+
+#if SANITIZER_INTERCEPT_INET
+INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
+ if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, internal_strlen(cp) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(inet_aton)(cp, dst);
+ if (res != 0) {
+ uptr sz = __sanitizer_in_addr_sz(af_inet);
+ if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
+ }
+ return res;
+}
+#define INIT_INET_ATON COMMON_INTERCEPT_FUNCTION(inet_aton);
+#else
+#define INIT_INET_ATON
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
+INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(pthread_getschedparam)(thread, policy, param);
+ if (res == 0) {
+ if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
+ if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
+ }
+ return res;
+}
+#define INIT_PTHREAD_GETSCHEDPARAM \
+ COMMON_INTERCEPT_FUNCTION(pthread_getschedparam);
+#else
+#define INIT_PTHREAD_GETSCHEDPARAM
+#endif
+
+#if SANITIZER_INTERCEPT_GETADDRINFO
+INTERCEPTOR(int, getaddrinfo, char *node, char *service,
+ struct __sanitizer_addrinfo *hints,
+ struct __sanitizer_addrinfo **out) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
+ if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, internal_strlen(node) + 1);
+ if (service)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, service, internal_strlen(service) + 1);
+ if (hints)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getaddrinfo)(node, service, hints, out);
+ if (res == 0 && out) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
+ struct __sanitizer_addrinfo *p = *out;
+ while (p) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
+ if (p->ai_addr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
+ if (p->ai_canonname)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
+ internal_strlen(p->ai_canonname) + 1);
+ p = p->ai_next;
+ }
+ }
+ return res;
+}
+#define INIT_GETADDRINFO COMMON_INTERCEPT_FUNCTION(getaddrinfo);
+#else
+#define INIT_GETADDRINFO
+#endif
+
+#if SANITIZER_INTERCEPT_GETNAMEINFO
+INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
+ unsigned hostlen, char *serv, unsigned servlen, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
+ serv, servlen, flags);
+ // FIXME: consider adding READ_RANGE(sockaddr, salen)
+ // There is padding in in_addr that may make this too noisy
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res =
+ REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
+ if (res == 0) {
+ if (host && hostlen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, internal_strlen(host) + 1);
+ if (serv && servlen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, internal_strlen(serv) + 1);
+ }
+ return res;
+}
+#define INIT_GETNAMEINFO COMMON_INTERCEPT_FUNCTION(getnameinfo);
+#else
+#define INIT_GETNAMEINFO
+#endif
+
+#if SANITIZER_INTERCEPT_GETSOCKNAME
+INTERCEPTOR(int, getsockname, int sock_fd, void *addr, unsigned *addrlen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
+ unsigned addr_sz;
+ if (addrlen) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
+ addr_sz = *addrlen;
+ }
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getsockname)(sock_fd, addr, addrlen);
+ if (!res && addr && addrlen) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
+ }
+ return res;
+}
+#define INIT_GETSOCKNAME COMMON_INTERCEPT_FUNCTION(getsockname);
+#else
+#define INIT_GETSOCKNAME
+#endif
+
+#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
+static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
+ if (h->h_name)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, internal_strlen(h->h_name) + 1);
+ char **p = h->h_aliases;
+ while (*p) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
+ ++p;
+ }
+ COMMON_INTERCEPTOR_WRITE_RANGE(
+ ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
+ p = h->h_addr_list;
+ while (*p) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
+ ++p;
+ }
+ COMMON_INTERCEPTOR_WRITE_RANGE(
+ ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
+}
+#endif
+
+#if SANITIZER_INTERCEPT_GETHOSTBYNAME
+INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
+ struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
+ if (res) write_hostent(ctx, res);
+ return res;
+}
+
+INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
+ int type) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
+ struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
+ if (res) write_hostent(ctx, res);
+ return res;
+}
+
+INTERCEPTOR(struct __sanitizer_hostent *, gethostent, int fake) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostent, fake);
+ struct __sanitizer_hostent *res = REAL(gethostent)(fake);
+ if (res) write_hostent(ctx, res);
+ return res;
+}
+#define INIT_GETHOSTBYNAME \
+ COMMON_INTERCEPT_FUNCTION(gethostent); \
+ COMMON_INTERCEPT_FUNCTION(gethostbyaddr); \
+ COMMON_INTERCEPT_FUNCTION(gethostbyname);
+#else
+#define INIT_GETHOSTBYNAME
+#endif // SANITIZER_INTERCEPT_GETHOSTBYNAME
+
+#if SANITIZER_INTERCEPT_GETHOSTBYNAME2
+INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
+ struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
+ if (res) write_hostent(ctx, res);
+ return res;
+}
+#define INIT_GETHOSTBYNAME2 COMMON_INTERCEPT_FUNCTION(gethostbyname2);
+#else
+#define INIT_GETHOSTBYNAME2
+#endif // SANITIZER_INTERCEPT_GETHOSTBYNAME2
+
+#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
+INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
+ char *buf, SIZE_T buflen, __sanitizer_hostent **result,
+ int *h_errnop) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
+ h_errnop);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
+ if (result) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (res == 0 && *result) write_hostent(ctx, *result);
+ }
+ if (h_errnop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
+ return res;
+}
+#define INIT_GETHOSTBYNAME_R COMMON_INTERCEPT_FUNCTION(gethostbyname_r);
+#else
+#define INIT_GETHOSTBYNAME_R
+#endif
+
+#if SANITIZER_INTERCEPT_GETHOSTENT_R
+INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
+ SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
+ h_errnop);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
+ if (result) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (res == 0 && *result) write_hostent(ctx, *result);
+ }
+ if (h_errnop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
+ return res;
+}
+#define INIT_GETHOSTENT_R \
+ COMMON_INTERCEPT_FUNCTION(gethostent_r);
+#else
+#define INIT_GETHOSTENT_R
+#endif
+
+#if SANITIZER_INTERCEPT_GETHOSTBYADDR_R
+INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
+ struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
+ __sanitizer_hostent **result, int *h_errnop) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
+ buflen, result, h_errnop);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
+ h_errnop);
+ if (result) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (res == 0 && *result) write_hostent(ctx, *result);
+ }
+ if (h_errnop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
+ return res;
+}
+#define INIT_GETHOSTBYADDR_R \
+ COMMON_INTERCEPT_FUNCTION(gethostbyaddr_r);
+#else
+#define INIT_GETHOSTBYADDR_R
+#endif
+
+#if SANITIZER_INTERCEPT_GETHOSTBYNAME2_R
+INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
+ struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
+ __sanitizer_hostent **result, int *h_errnop) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
+ result, h_errnop);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res =
+ REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
+ if (result) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (res == 0 && *result) write_hostent(ctx, *result);
+ }
+ if (h_errnop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
+ return res;
+}
+#define INIT_GETHOSTBYNAME2_R \
+ COMMON_INTERCEPT_FUNCTION(gethostbyname2_r);
+#else
+#define INIT_GETHOSTBYNAME2_R
+#endif
+
+#if SANITIZER_INTERCEPT_GETSOCKOPT
+INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
+ int *optlen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
+ optlen);
+ if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
+ if (res == 0)
+ if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
+ return res;
+}
+#define INIT_GETSOCKOPT COMMON_INTERCEPT_FUNCTION(getsockopt);
+#else
+#define INIT_GETSOCKOPT
+#endif
+
+#if SANITIZER_INTERCEPT_ACCEPT
+INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
+ unsigned addrlen0 = 0;
+ if (addrlen) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
+ addrlen0 = *addrlen;
+ }
+ int fd2 = REAL(accept)(fd, addr, addrlen);
+ if (fd2 >= 0) {
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
+ if (addr && addrlen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
+ }
+ return fd2;
+}
+#define INIT_ACCEPT COMMON_INTERCEPT_FUNCTION(accept);
+#else
+#define INIT_ACCEPT
+#endif
+
+#if SANITIZER_INTERCEPT_ACCEPT4
+INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
+ unsigned addrlen0 = 0;
+ if (addrlen) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
+ addrlen0 = *addrlen;
+ }
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int fd2 = REAL(accept4)(fd, addr, addrlen, f);
+ if (fd2 >= 0) {
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
+ if (addr && addrlen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
+ }
+ return fd2;
+}
+#define INIT_ACCEPT4 COMMON_INTERCEPT_FUNCTION(accept4);
+#else
+#define INIT_ACCEPT4
+#endif
+
+#if SANITIZER_INTERCEPT_PACCEPT
+INTERCEPTOR(int, paccept, int fd, void *addr, unsigned *addrlen,
+ __sanitizer_sigset_t *set, int f) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, paccept, fd, addr, addrlen, set, f);
+ unsigned addrlen0 = 0;
+ if (addrlen) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
+ addrlen0 = *addrlen;
+ }
+ if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
+ int fd2 = REAL(paccept)(fd, addr, addrlen, set, f);
+ if (fd2 >= 0) {
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
+ if (addr && addrlen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
+ }
+ return fd2;
+}
+#define INIT_PACCEPT COMMON_INTERCEPT_FUNCTION(paccept);
+#else
+#define INIT_PACCEPT
+#endif
+
+#if SANITIZER_INTERCEPT_MODF
+INTERCEPTOR(double, modf, double x, double *iptr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ double res = REAL(modf)(x, iptr);
+ if (iptr) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
+ }
+ return res;
+}
+INTERCEPTOR(float, modff, float x, float *iptr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ float res = REAL(modff)(x, iptr);
+ if (iptr) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
+ }
+ return res;
+}
+INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ long double res = REAL(modfl)(x, iptr);
+ if (iptr) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
+ }
+ return res;
+}
+#define INIT_MODF \
+ COMMON_INTERCEPT_FUNCTION(modf); \
+ COMMON_INTERCEPT_FUNCTION(modff); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(modfl);
+#else
+#define INIT_MODF
+#endif
+
+#if SANITIZER_INTERCEPT_RECVMSG || SANITIZER_INTERCEPT_RECVMMSG
+static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
+ SSIZE_T maxlen) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
+ if (msg->msg_name && msg->msg_namelen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name, msg->msg_namelen);
+ if (msg->msg_iov && msg->msg_iovlen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
+ sizeof(*msg->msg_iov) * msg->msg_iovlen);
+ write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
+ if (msg->msg_control && msg->msg_controllen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
+}
+#endif
+
+#if SANITIZER_INTERCEPT_RECVMSG
+INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
+ int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
+ if (res >= 0) {
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ if (msg) {
+ write_msghdr(ctx, msg, res);
+ COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg);
+ }
+ }
+ return res;
+}
+#define INIT_RECVMSG COMMON_INTERCEPT_FUNCTION(recvmsg);
+#else
+#define INIT_RECVMSG
+#endif
+
+#if SANITIZER_INTERCEPT_RECVMMSG
+INTERCEPTOR(int, recvmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
+ unsigned int vlen, int flags, void *timeout) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, recvmmsg, fd, msgvec, vlen, flags, timeout);
+ if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
+ int res = REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout);
+ if (res >= 0) {
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ for (int i = 0; i < res; ++i) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
+ sizeof(msgvec[i].msg_len));
+ write_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
+ COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, &msgvec[i].msg_hdr);
+ }
+ }
+ return res;
+}
+#define INIT_RECVMMSG COMMON_INTERCEPT_FUNCTION(recvmmsg);
+#else
+#define INIT_RECVMMSG
+#endif
+
+#if SANITIZER_INTERCEPT_SENDMSG || SANITIZER_INTERCEPT_SENDMMSG
+static void read_msghdr_control(void *ctx, void *control, uptr controllen) {
+ const unsigned kCmsgDataOffset =
+ RoundUpTo(sizeof(__sanitizer_cmsghdr), sizeof(uptr));
+
+ char *p = (char *)control;
+ char *const control_end = p + controllen;
+ while (true) {
+ if (p + sizeof(__sanitizer_cmsghdr) > control_end) break;
+ __sanitizer_cmsghdr *cmsg = (__sanitizer_cmsghdr *)p;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_len, sizeof(cmsg->cmsg_len));
+
+ if (p + RoundUpTo(cmsg->cmsg_len, sizeof(uptr)) > control_end) break;
+
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_level,
+ sizeof(cmsg->cmsg_level));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_type,
+ sizeof(cmsg->cmsg_type));
+
+ if (cmsg->cmsg_len > kCmsgDataOffset) {
+ char *data = p + kCmsgDataOffset;
+ unsigned data_len = cmsg->cmsg_len - kCmsgDataOffset;
+ if (data_len > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, data_len);
+ }
+
+ p += RoundUpTo(cmsg->cmsg_len, sizeof(uptr));
+ }
+}
+
+static void read_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
+ SSIZE_T maxlen) {
+#define R(f) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &msg->msg_##f, sizeof(msg->msg_##f))
+ R(name);
+ R(namelen);
+ R(iov);
+ R(iovlen);
+ R(control);
+ R(controllen);
+ R(flags);
+#undef R
+ if (msg->msg_name && msg->msg_namelen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_name, msg->msg_namelen);
+ if (msg->msg_iov && msg->msg_iovlen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_iov,
+ sizeof(*msg->msg_iov) * msg->msg_iovlen);
+ read_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
+ if (msg->msg_control && msg->msg_controllen)
+ read_msghdr_control(ctx, msg->msg_control, msg->msg_controllen);
+}
+#endif
+
+#if SANITIZER_INTERCEPT_SENDMSG
+INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
+ int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sendmsg, fd, msg, flags);
+ if (fd >= 0) {
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ }
+ SSIZE_T res = REAL(sendmsg)(fd, msg, flags);
+ if (common_flags()->intercept_send && res >= 0 && msg)
+ read_msghdr(ctx, msg, res);
+ return res;
+}
+#define INIT_SENDMSG COMMON_INTERCEPT_FUNCTION(sendmsg);
+#else
+#define INIT_SENDMSG
+#endif
+
+#if SANITIZER_INTERCEPT_SENDMMSG
+INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
+ unsigned vlen, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sendmmsg, fd, msgvec, vlen, flags);
+ if (fd >= 0) {
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ }
+ int res = REAL(sendmmsg)(fd, msgvec, vlen, flags);
+ if (res >= 0 && msgvec) {
+ for (int i = 0; i < res; ++i) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
+ sizeof(msgvec[i].msg_len));
+ if (common_flags()->intercept_send)
+ read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
+ }
+ }
+ return res;
+}
+#define INIT_SENDMMSG COMMON_INTERCEPT_FUNCTION(sendmmsg);
+#else
+#define INIT_SENDMMSG
+#endif
+
+#if SANITIZER_INTERCEPT_SYSMSG
+INTERCEPTOR(int, msgsnd, int msqid, const void *msgp, SIZE_T msgsz,
+ int msgflg) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, msgsnd, msqid, msgp, msgsz, msgflg);
+ if (msgp)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, msgp, sizeof(long) + msgsz);
+ int res = REAL(msgsnd)(msqid, msgp, msgsz, msgflg);
+ return res;
+}
+
+INTERCEPTOR(SSIZE_T, msgrcv, int msqid, void *msgp, SIZE_T msgsz,
+ long msgtyp, int msgflg) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, msgrcv, msqid, msgp, msgsz, msgtyp, msgflg);
+ SSIZE_T len = REAL(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg);
+ if (len != -1)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msgp, sizeof(long) + len);
+ return len;
+}
+
+#define INIT_SYSMSG \
+ COMMON_INTERCEPT_FUNCTION(msgsnd); \
+ COMMON_INTERCEPT_FUNCTION(msgrcv);
+#else
+#define INIT_SYSMSG
+#endif
+
+#if SANITIZER_INTERCEPT_GETPEERNAME
+INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
+ unsigned addr_sz;
+ if (addrlen) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
+ addr_sz = *addrlen;
+ }
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getpeername)(sockfd, addr, addrlen);
+ if (!res && addr && addrlen) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
+ }
+ return res;
+}
+#define INIT_GETPEERNAME COMMON_INTERCEPT_FUNCTION(getpeername);
+#else
+#define INIT_GETPEERNAME
+#endif
+
+#if SANITIZER_INTERCEPT_SYSINFO
+INTERCEPTOR(int, sysinfo, void *info) {
+ void *ctx;
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
+ int res = REAL(sysinfo)(info);
+ if (!res && info)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
+ return res;
+}
+#define INIT_SYSINFO COMMON_INTERCEPT_FUNCTION(sysinfo);
+#else
+#define INIT_SYSINFO
+#endif
+
+#if SANITIZER_INTERCEPT_READDIR
+INTERCEPTOR(__sanitizer_dirent *, opendir, const char *path) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, opendir, path);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ __sanitizer_dirent *res = REAL(opendir)(path);
+ if (res)
+ COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path);
+ return res;
+}
+
+INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ __sanitizer_dirent *res = REAL(readdir)(dirp);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
+ return res;
+}
+
+INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
+ __sanitizer_dirent **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(readdir_r)(dirp, entry, result);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (*result)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
+ }
+ return res;
+}
+
+#define INIT_READDIR \
+ COMMON_INTERCEPT_FUNCTION(opendir); \
+ COMMON_INTERCEPT_FUNCTION(readdir); \
+ COMMON_INTERCEPT_FUNCTION(readdir_r);
+#else
+#define INIT_READDIR
+#endif
+
+#if SANITIZER_INTERCEPT_READDIR64
+INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
+ return res;
+}
+
+INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
+ __sanitizer_dirent64 **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(readdir64_r)(dirp, entry, result);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (*result)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
+ }
+ return res;
+}
+#define INIT_READDIR64 \
+ COMMON_INTERCEPT_FUNCTION(readdir64); \
+ COMMON_INTERCEPT_FUNCTION(readdir64_r);
+#else
+#define INIT_READDIR64
+#endif
+
+#if SANITIZER_INTERCEPT_PTRACE
+INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
+ __sanitizer_iovec local_iovec;
+
+ if (data) {
+ if (request == ptrace_setregs) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
+ } else if (request == ptrace_setfpregs) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
+ } else if (request == ptrace_setfpxregs) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
+ } else if (request == ptrace_setvfpregs) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
+ } else if (request == ptrace_setsiginfo) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
+
+ // Some kernel might zero the iovec::iov_base in case of invalid
+ // write access. In this case copy the invalid address for further
+ // inspection.
+ } else if (request == ptrace_setregset || request == ptrace_getregset) {
+ __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));
+ local_iovec = *iovec;
+ if (request == ptrace_setregset)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec->iov_base, iovec->iov_len);
+ }
+ }
+
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ uptr res = REAL(ptrace)(request, pid, addr, data);
+
+ if (!res && data) {
+ // Note that PEEK* requests assign different meaning to the return value.
+ // This function does not handle them (nor does it need to).
+ if (request == ptrace_getregs) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
+ } else if (request == ptrace_getfpregs) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
+ } else if (request == ptrace_getfpxregs) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
+ } else if (request == ptrace_getvfpregs) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
+ } else if (request == ptrace_getsiginfo) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
+ } else if (request == ptrace_geteventmsg) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long));
+ } else if (request == ptrace_getregset) {
+ __sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base,
+ local_iovec.iov_len);
+ }
+ }
+ return res;
+}
+
+#define INIT_PTRACE COMMON_INTERCEPT_FUNCTION(ptrace);
+#else
+#define INIT_PTRACE
+#endif
+
+#if SANITIZER_INTERCEPT_SETLOCALE
+static void unpoison_ctype_arrays(void *ctx) {
+#if SANITIZER_NETBSD
+ // These arrays contain 256 regular elements in unsigned char range + 1 EOF
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _ctype_tab_, 257 * sizeof(short));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _toupper_tab_, 257 * sizeof(short));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, _tolower_tab_, 257 * sizeof(short));
+#endif
+}
+
+INTERCEPTOR(char *, setlocale, int category, char *locale) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
+ if (locale)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, internal_strlen(locale) + 1);
+ char *res = REAL(setlocale)(category, locale);
+ if (res) {
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+ unpoison_ctype_arrays(ctx);
+ }
+ return res;
+}
+
+#define INIT_SETLOCALE COMMON_INTERCEPT_FUNCTION(setlocale);
+#else
+#define INIT_SETLOCALE
+#endif
+
+#if SANITIZER_INTERCEPT_GETCWD
+INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *res = REAL(getcwd)(buf, size);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
+ return res;
+}
+#define INIT_GETCWD COMMON_INTERCEPT_FUNCTION(getcwd);
+#else
+#define INIT_GETCWD
+#endif
+
+#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
+INTERCEPTOR(char *, get_current_dir_name, int fake) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name, fake);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *res = REAL(get_current_dir_name)(fake);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
+ return res;
+}
+
+#define INIT_GET_CURRENT_DIR_NAME \
+ COMMON_INTERCEPT_FUNCTION(get_current_dir_name);
+#else
+#define INIT_GET_CURRENT_DIR_NAME
+#endif
+
+UNUSED static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
+ CHECK(endptr);
+ if (nptr == *endptr) {
+ // No digits were found at strtol call, we need to find out the last
+ // symbol accessed by strtoll on our own.
+ // We get this symbol by skipping leading blanks and optional +/- sign.
+ while (IsSpace(*nptr)) nptr++;
+ if (*nptr == '+' || *nptr == '-') nptr++;
+ *endptr = const_cast<char *>(nptr);
+ }
+ CHECK(*endptr >= nptr);
+}
+
+UNUSED static inline void StrtolFixAndCheck(void *ctx, const char *nptr,
+ char **endptr, char *real_endptr, int base) {
+ if (endptr) {
+ *endptr = real_endptr;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
+ }
+ // If base has unsupported value, strtol can exit with EINVAL
+ // without reading any characters. So do additional checks only
+ // if base is valid.
+ bool is_valid_base = (base == 0) || (2 <= base && base <= 36);
+ if (is_valid_base) {
+ FixRealStrtolEndptr(nptr, &real_endptr);
+ }
+ COMMON_INTERCEPTOR_READ_STRING(ctx, nptr, is_valid_base ?
+ (real_endptr - nptr) + 1 : 0);
+}
+
+
+#if SANITIZER_INTERCEPT_STRTOIMAX
+INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *real_endptr;
+ INTMAX_T res = REAL(strtoimax)(nptr, &real_endptr, base);
+ StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
+ return res;
+}
+
+INTERCEPTOR(UINTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *real_endptr;
+ UINTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base);
+ StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
+ return res;
+}
+
+#define INIT_STRTOIMAX \
+ COMMON_INTERCEPT_FUNCTION(strtoimax); \
+ COMMON_INTERCEPT_FUNCTION(strtoumax);
+#else
+#define INIT_STRTOIMAX
+#endif
+
+#if SANITIZER_INTERCEPT_MBSTOWCS
+INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SIZE_T res = REAL(mbstowcs)(dest, src, len);
+ if (res != (SIZE_T) - 1 && dest) {
+ SIZE_T write_cnt = res + (res < len);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
+ }
+ return res;
+}
+
+INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
+ void *ps) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
+ if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
+ if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps);
+ if (res != (SIZE_T)(-1) && dest && src) {
+ // This function, and several others, may or may not write the terminating
+ // \0 character. They write it iff they clear *src.
+ SIZE_T write_cnt = res + !*src;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
+ }
+ return res;
+}
+
+#define INIT_MBSTOWCS \
+ COMMON_INTERCEPT_FUNCTION(mbstowcs); \
+ COMMON_INTERCEPT_FUNCTION(mbsrtowcs);
+#else
+#define INIT_MBSTOWCS
+#endif
+
+#if SANITIZER_INTERCEPT_MBSNRTOWCS
+INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
+ SIZE_T len, void *ps) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
+ if (src) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
+ if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
+ }
+ if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps);
+ if (res != (SIZE_T)(-1) && dest && src) {
+ SIZE_T write_cnt = res + !*src;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
+ }
+ return res;
+}
+
+#define INIT_MBSNRTOWCS COMMON_INTERCEPT_FUNCTION(mbsnrtowcs);
+#else
+#define INIT_MBSNRTOWCS
+#endif
+
+#if SANITIZER_INTERCEPT_WCSTOMBS
+INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SIZE_T res = REAL(wcstombs)(dest, src, len);
+ if (res != (SIZE_T) - 1 && dest) {
+ SIZE_T write_cnt = res + (res < len);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
+ }
+ return res;
+}
+
+INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
+ void *ps) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
+ if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
+ if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps);
+ if (res != (SIZE_T) - 1 && dest && src) {
+ SIZE_T write_cnt = res + !*src;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
+ }
+ return res;
+}
+
+#define INIT_WCSTOMBS \
+ COMMON_INTERCEPT_FUNCTION(wcstombs); \
+ COMMON_INTERCEPT_FUNCTION(wcsrtombs);
+#else
+#define INIT_WCSTOMBS
+#endif
+
+#if SANITIZER_INTERCEPT_WCSNRTOMBS
+INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
+ SIZE_T len, void *ps) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
+ if (src) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
+ if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
+ }
+ if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps);
+ if (res != ((SIZE_T)-1) && dest && src) {
+ SIZE_T write_cnt = res + !*src;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
+ }
+ return res;
+}
+
+#define INIT_WCSNRTOMBS COMMON_INTERCEPT_FUNCTION(wcsnrtombs);
+#else
+#define INIT_WCSNRTOMBS
+#endif
+
+
+#if SANITIZER_INTERCEPT_WCRTOMB
+INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wcrtomb, dest, src, ps);
+ if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
+
+ if (!dest)
+ return REAL(wcrtomb)(dest, src, ps);
+
+ char local_dest[32];
+ SIZE_T res = REAL(wcrtomb)(local_dest, src, ps);
+ if (res != ((SIZE_T)-1)) {
+ CHECK_LE(res, sizeof(local_dest));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
+ REAL(memcpy)(dest, local_dest, res);
+ }
+ return res;
+}
+
+#define INIT_WCRTOMB COMMON_INTERCEPT_FUNCTION(wcrtomb);
+#else
+#define INIT_WCRTOMB
+#endif
+
+#if SANITIZER_INTERCEPT_WCTOMB
+INTERCEPTOR(int, wctomb, char *dest, wchar_t src) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wctomb, dest, src);
+ if (!dest)
+ return REAL(wctomb)(dest, src);
+
+ char local_dest[32];
+ int res = REAL(wctomb)(local_dest, src);
+ if (res != -1) {
+ CHECK_LE(res, sizeof(local_dest));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res);
+ REAL(memcpy)(dest, local_dest, res);
+ }
+ return res;
+}
+
+#define INIT_WCTOMB COMMON_INTERCEPT_FUNCTION(wctomb);
+#else
+#define INIT_WCTOMB
+#endif
+
+#if SANITIZER_INTERCEPT_TCGETATTR
+INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(tcgetattr)(fd, termios_p);
+ if (!res && termios_p)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz);
+ return res;
+}
+
+#define INIT_TCGETATTR COMMON_INTERCEPT_FUNCTION(tcgetattr);
+#else
+#define INIT_TCGETATTR
+#endif
+
+#if SANITIZER_INTERCEPT_REALPATH
+INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+
+ // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
+ // version of a versioned symbol. For realpath(), this gives us something
+ // (called __old_realpath) that does not handle NULL in the second argument.
+ // Handle it as part of the interceptor.
+ char *allocated_path = nullptr;
+ if (!resolved_path)
+ allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
+
+ char *res = REAL(realpath)(path, resolved_path);
+ if (allocated_path && !res)
+ WRAP(free)(allocated_path);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
+ return res;
+}
+# define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath);
+#else
+#define INIT_REALPATH
+#endif
+
+#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
+INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ char *res = REAL(canonicalize_file_name)(path);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
+ return res;
+}
+#define INIT_CANONICALIZE_FILE_NAME \
+ COMMON_INTERCEPT_FUNCTION(canonicalize_file_name);
+#else
+#define INIT_CANONICALIZE_FILE_NAME
+#endif
+
+#if SANITIZER_INTERCEPT_CONFSTR
+INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SIZE_T res = REAL(confstr)(name, buf, len);
+ if (buf && res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len);
+ return res;
+}
+#define INIT_CONFSTR COMMON_INTERCEPT_FUNCTION(confstr);
+#else
+#define INIT_CONFSTR
+#endif
+
+#if SANITIZER_INTERCEPT_SCHED_GETAFFINITY
+INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(sched_getaffinity)(pid, cpusetsize, mask);
+ if (mask && !res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
+ return res;
+}
+#define INIT_SCHED_GETAFFINITY COMMON_INTERCEPT_FUNCTION(sched_getaffinity);
+#else
+#define INIT_SCHED_GETAFFINITY
+#endif
+
+#if SANITIZER_INTERCEPT_SCHED_GETPARAM
+INTERCEPTOR(int, sched_getparam, int pid, void *param) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sched_getparam, pid, param);
+ int res = REAL(sched_getparam)(pid, param);
+ if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, struct_sched_param_sz);
+ return res;
+}
+#define INIT_SCHED_GETPARAM COMMON_INTERCEPT_FUNCTION(sched_getparam);
+#else
+#define INIT_SCHED_GETPARAM
+#endif
+
+#if SANITIZER_INTERCEPT_STRERROR
+INTERCEPTOR(char *, strerror, int errnum) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
+ COMMON_INTERCEPTOR_STRERROR();
+ char *res = REAL(strerror)(errnum);
+ if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+ return res;
+}
+#define INIT_STRERROR COMMON_INTERCEPT_FUNCTION(strerror);
+#else
+#define INIT_STRERROR
+#endif
+
+#if SANITIZER_INTERCEPT_STRERROR_R
+// There are 2 versions of strerror_r:
+// * POSIX version returns 0 on success, negative error code on failure,
+// writes message to buf.
+// * GNU version returns message pointer, which points to either buf or some
+// static storage.
+#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || \
+ SANITIZER_APPLE || SANITIZER_ANDROID || SANITIZER_NETBSD || \
+ SANITIZER_FREEBSD
+// POSIX version. Spec is not clear on whether buf is NULL-terminated.
+// At least on OSX, buf contents are valid even when the call fails.
+INTERCEPTOR(int, strerror_r, int errnum, char *buf, SIZE_T buflen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(strerror_r)(errnum, buf, buflen);
+
+ SIZE_T sz = internal_strnlen(buf, buflen);
+ if (sz < buflen) ++sz;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
+ return res;
+}
+#else
+// GNU version.
+INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *res = REAL(strerror_r)(errnum, buf, buflen);
+ if (res == buf)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
+ else
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+ return res;
+}
+#endif //(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE ||
+ //SANITIZER_APPLE
+#define INIT_STRERROR_R COMMON_INTERCEPT_FUNCTION(strerror_r);
+#else
+#define INIT_STRERROR_R
+#endif
+
+#if SANITIZER_INTERCEPT_XPG_STRERROR_R
+INTERCEPTOR(int, __xpg_strerror_r, int errnum, char *buf, SIZE_T buflen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __xpg_strerror_r, errnum, buf, buflen);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(__xpg_strerror_r)(errnum, buf, buflen);
+ // This version always returns a null-terminated string.
+ if (buf && buflen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
+ return res;
+}
+#define INIT_XPG_STRERROR_R COMMON_INTERCEPT_FUNCTION(__xpg_strerror_r);
+#else
+#define INIT_XPG_STRERROR_R
+#endif
+
+#if SANITIZER_INTERCEPT_SCANDIR
+typedef int (*scandir_filter_f)(const struct __sanitizer_dirent *);
+typedef int (*scandir_compar_f)(const struct __sanitizer_dirent **,
+ const struct __sanitizer_dirent **);
+
+static THREADLOCAL scandir_filter_f scandir_filter;
+static THREADLOCAL scandir_compar_f scandir_compar;
+
+static int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
+ return scandir_filter(dir);
+}
+
+static int wrapped_scandir_compar(const struct __sanitizer_dirent **a,
+ const struct __sanitizer_dirent **b) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
+ return scandir_compar(a, b);
+}
+
+INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
+ scandir_filter_f filter, scandir_compar_f compar) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
+ if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, internal_strlen(dirp) + 1);
+ scandir_filter = filter;
+ scandir_compar = compar;
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(scandir)(dirp, namelist,
+ filter ? wrapped_scandir_filter : nullptr,
+ compar ? wrapped_scandir_compar : nullptr);
+ scandir_filter = nullptr;
+ scandir_compar = nullptr;
+ if (namelist && res > 0) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
+ for (int i = 0; i < res; ++i)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
+ (*namelist)[i]->d_reclen);
+ }
+ return res;
+}
+#define INIT_SCANDIR COMMON_INTERCEPT_FUNCTION(scandir);
+#else
+#define INIT_SCANDIR
+#endif
+
+#if SANITIZER_INTERCEPT_SCANDIR64
+typedef int (*scandir64_filter_f)(const struct __sanitizer_dirent64 *);
+typedef int (*scandir64_compar_f)(const struct __sanitizer_dirent64 **,
+ const struct __sanitizer_dirent64 **);
+
+static THREADLOCAL scandir64_filter_f scandir64_filter;
+static THREADLOCAL scandir64_compar_f scandir64_compar;
+
+static int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
+ return scandir64_filter(dir);
+}
+
+static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a,
+ const struct __sanitizer_dirent64 **b) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
+ return scandir64_compar(a, b);
+}
+
+INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
+ scandir64_filter_f filter, scandir64_compar_f compar) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
+ if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, internal_strlen(dirp) + 1);
+ scandir64_filter = filter;
+ scandir64_compar = compar;
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res =
+ REAL(scandir64)(dirp, namelist,
+ filter ? wrapped_scandir64_filter : nullptr,
+ compar ? wrapped_scandir64_compar : nullptr);
+ scandir64_filter = nullptr;
+ scandir64_compar = nullptr;
+ if (namelist && res > 0) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
+ for (int i = 0; i < res; ++i)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
+ (*namelist)[i]->d_reclen);
+ }
+ return res;
+}
+#define INIT_SCANDIR64 COMMON_INTERCEPT_FUNCTION(scandir64);
+#else
+#define INIT_SCANDIR64
+#endif
+
+#if SANITIZER_INTERCEPT_GETGROUPS
+INTERCEPTOR(int, getgroups, int size, u32 *lst) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgroups, size, lst);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getgroups)(size, lst);
+ if (res >= 0 && lst && size > 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst));
+ return res;
+}
+#define INIT_GETGROUPS COMMON_INTERCEPT_FUNCTION(getgroups);
+#else
+#define INIT_GETGROUPS
+#endif
+
+#if SANITIZER_INTERCEPT_POLL
+static void read_pollfd(void *ctx, __sanitizer_pollfd *fds,
+ __sanitizer_nfds_t nfds) {
+ for (unsigned i = 0; i < nfds; ++i) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].fd, sizeof(fds[i].fd));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].events, sizeof(fds[i].events));
+ }
+}
+
+static void write_pollfd(void *ctx, __sanitizer_pollfd *fds,
+ __sanitizer_nfds_t nfds) {
+ for (unsigned i = 0; i < nfds; ++i)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &fds[i].revents,
+ sizeof(fds[i].revents));
+}
+
+INTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
+ int timeout) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, poll, fds, nfds, timeout);
+ if (fds && nfds) read_pollfd(ctx, fds, nfds);
+ int res = COMMON_INTERCEPTOR_BLOCK_REAL(poll)(fds, nfds, timeout);
+ if (fds && nfds) write_pollfd(ctx, fds, nfds);
+ return res;
+}
+#define INIT_POLL COMMON_INTERCEPT_FUNCTION(poll);
+#else
+#define INIT_POLL
+#endif
+
+#if SANITIZER_INTERCEPT_PPOLL
+INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
+ void *timeout_ts, __sanitizer_sigset_t *sigmask) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ppoll, fds, nfds, timeout_ts, sigmask);
+ if (fds && nfds) read_pollfd(ctx, fds, nfds);
+ if (timeout_ts)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, struct_timespec_sz);
+ if (sigmask) COMMON_INTERCEPTOR_READ_RANGE(ctx, sigmask, sizeof(*sigmask));
+ int res =
+ COMMON_INTERCEPTOR_BLOCK_REAL(ppoll)(fds, nfds, timeout_ts, sigmask);
+ if (fds && nfds) write_pollfd(ctx, fds, nfds);
+ return res;
+}
+#define INIT_PPOLL COMMON_INTERCEPT_FUNCTION(ppoll);
+#else
+#define INIT_PPOLL
+#endif
+
+#if SANITIZER_INTERCEPT_WORDEXP
+INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
+ if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(wordexp)(s, p, flags);
+ if (!res && p) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
+ uptr we_wordc =
+ ((flags & wordexp_wrde_dooffs) ? p->we_offs : 0) + p->we_wordc;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
+ sizeof(*p->we_wordv) * (we_wordc + 1));
+ for (uptr i = 0; i < we_wordc; ++i) {
+ char *w = p->we_wordv[i];
+ if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, internal_strlen(w) + 1);
+ }
+ }
+ return res;
+}
+#define INIT_WORDEXP COMMON_INTERCEPT_FUNCTION(wordexp);
+#else
+#define INIT_WORDEXP
+#endif
+
+#if SANITIZER_INTERCEPT_SIGWAIT
+INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigwait, set, sig);
+ if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigwait)(set, sig);
+ if (!res && sig) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sig, sizeof(*sig));
+ return res;
+}
+#define INIT_SIGWAIT COMMON_INTERCEPT_FUNCTION(sigwait);
+#else
+#define INIT_SIGWAIT
+#endif
+
+#if SANITIZER_INTERCEPT_SIGWAITINFO
+INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigwaitinfo, set, info);
+ if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigwaitinfo)(set, info);
+ if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
+ return res;
+}
+#define INIT_SIGWAITINFO COMMON_INTERCEPT_FUNCTION(sigwaitinfo);
+#else
+#define INIT_SIGWAITINFO
+#endif
+
+#if SANITIZER_INTERCEPT_SIGTIMEDWAIT
+INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info,
+ void *timeout) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigtimedwait, set, info, timeout);
+ if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
+ if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = COMMON_INTERCEPTOR_BLOCK_REAL(sigtimedwait)(set, info, timeout);
+ if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
+ return res;
+}
+#define INIT_SIGTIMEDWAIT COMMON_INTERCEPT_FUNCTION(sigtimedwait);
+#else
+#define INIT_SIGTIMEDWAIT
+#endif
+
+#if SANITIZER_INTERCEPT_SIGSETOPS
+INTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigemptyset, set);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(sigemptyset)(set);
+ if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
+ return res;
+}
+
+INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigfillset, set);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(sigfillset)(set);
+ if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
+ return res;
+}
+#define INIT_SIGSETOPS \
+ COMMON_INTERCEPT_FUNCTION(sigemptyset); \
+ COMMON_INTERCEPT_FUNCTION(sigfillset);
+#else
+#define INIT_SIGSETOPS
+#endif
+
+#if SANITIZER_INTERCEPT_SIGSET_LOGICOPS
+INTERCEPTOR(int, sigandset, __sanitizer_sigset_t *dst,
+ __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigandset, dst, src1, src2);
+ if (src1)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1));
+ if (src2)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2));
+ int res = REAL(sigandset)(dst, src1, src2);
+ if (!res && dst)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
+ return res;
+}
+
+INTERCEPTOR(int, sigorset, __sanitizer_sigset_t *dst,
+ __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigorset, dst, src1, src2);
+ if (src1)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1));
+ if (src2)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2));
+ int res = REAL(sigorset)(dst, src1, src2);
+ if (!res && dst)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
+ return res;
+}
+#define INIT_SIGSET_LOGICOPS \
+ COMMON_INTERCEPT_FUNCTION(sigandset); \
+ COMMON_INTERCEPT_FUNCTION(sigorset);
+#else
+#define INIT_SIGSET_LOGICOPS
+#endif
+
+#if SANITIZER_INTERCEPT_SIGPENDING
+INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigpending, set);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(sigpending)(set);
+ if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
+ return res;
+}
+#define INIT_SIGPENDING COMMON_INTERCEPT_FUNCTION(sigpending);
+#else
+#define INIT_SIGPENDING
+#endif
+
+#if SANITIZER_INTERCEPT_SIGPROCMASK
+INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
+ __sanitizer_sigset_t *oldset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
+ if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(sigprocmask)(how, set, oldset);
+ if (!res && oldset)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
+ return res;
+}
+#define INIT_SIGPROCMASK COMMON_INTERCEPT_FUNCTION(sigprocmask);
+#else
+#define INIT_SIGPROCMASK
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_SIGMASK
+INTERCEPTOR(int, pthread_sigmask, int how, __sanitizer_sigset_t *set,
+ __sanitizer_sigset_t *oldset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_sigmask, how, set, oldset);
+ if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(pthread_sigmask)(how, set, oldset);
+ if (!res && oldset)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
+ return res;
+}
+#define INIT_PTHREAD_SIGMASK COMMON_INTERCEPT_FUNCTION(pthread_sigmask);
+#else
+#define INIT_PTHREAD_SIGMASK
+#endif
+
+#if SANITIZER_INTERCEPT_BACKTRACE
+INTERCEPTOR(int, backtrace, void **buffer, int size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(backtrace)(buffer, size);
+ if (res && buffer)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buffer, res * sizeof(*buffer));
+ return res;
+}
+
+INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, backtrace_symbols, buffer, size);
+ if (buffer && size)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer));
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char **res = REAL(backtrace_symbols)(buffer, size);
+ if (res && size) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res));
+ for (int i = 0; i < size; ++i)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], internal_strlen(res[i]) + 1);
+ }
+ return res;
+}
+#define INIT_BACKTRACE \
+ COMMON_INTERCEPT_FUNCTION(backtrace); \
+ COMMON_INTERCEPT_FUNCTION(backtrace_symbols);
+#else
+#define INIT_BACKTRACE
+#endif
+
+#if SANITIZER_INTERCEPT__EXIT
+INTERCEPTOR(void, _exit, int status) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, _exit, status);
+ COMMON_INTERCEPTOR_USER_CALLBACK_START();
+ int status1 = COMMON_INTERCEPTOR_ON_EXIT(ctx);
+ COMMON_INTERCEPTOR_USER_CALLBACK_END();
+ if (status == 0) status = status1;
+ REAL(_exit)(status);
+}
+#define INIT__EXIT COMMON_INTERCEPT_FUNCTION(_exit);
+#else
+#define INIT__EXIT
+#endif
+
+#if SANITIZER_INTERCEPT___LIBC_MUTEX
+INTERCEPTOR(int, __libc_thr_setcancelstate, int state, int *oldstate)
+ALIAS(WRAPPER_NAME(pthread_setcancelstate));
+
+#define INIT___LIBC_THR_SETCANCELSTATE \
+ COMMON_INTERCEPT_FUNCTION(__libc_thr_setcancelstate)
+#else
+#define INIT___LIBC_THR_SETCANCELSTATE
+#endif
+
+#if SANITIZER_INTERCEPT_GETMNTENT || SANITIZER_INTERCEPT_GETMNTENT_R
+static void write_mntent(void *ctx, __sanitizer_mntent *mnt) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt, sizeof(*mnt));
+ if (mnt->mnt_fsname)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_fsname,
+ internal_strlen(mnt->mnt_fsname) + 1);
+ if (mnt->mnt_dir)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_dir,
+ internal_strlen(mnt->mnt_dir) + 1);
+ if (mnt->mnt_type)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_type,
+ internal_strlen(mnt->mnt_type) + 1);
+ if (mnt->mnt_opts)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_opts,
+ internal_strlen(mnt->mnt_opts) + 1);
+}
+#endif
+
+#if SANITIZER_INTERCEPT_GETMNTENT
+INTERCEPTOR(__sanitizer_mntent *, getmntent, void *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getmntent, fp);
+ __sanitizer_mntent *res = REAL(getmntent)(fp);
+ if (res) write_mntent(ctx, res);
+ return res;
+}
+#define INIT_GETMNTENT COMMON_INTERCEPT_FUNCTION(getmntent);
+#else
+#define INIT_GETMNTENT
+#endif
+
+#if SANITIZER_INTERCEPT_GETMNTENT_R
+INTERCEPTOR(__sanitizer_mntent *, getmntent_r, void *fp,
+ __sanitizer_mntent *mntbuf, char *buf, int buflen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getmntent_r, fp, mntbuf, buf, buflen);
+ __sanitizer_mntent *res = REAL(getmntent_r)(fp, mntbuf, buf, buflen);
+ if (res) write_mntent(ctx, res);
+ return res;
+}
+#define INIT_GETMNTENT_R COMMON_INTERCEPT_FUNCTION(getmntent_r);
+#else
+#define INIT_GETMNTENT_R
+#endif
+
+#if SANITIZER_INTERCEPT_STATFS
+INTERCEPTOR(int, statfs, char *path, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, statfs, path, buf);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(statfs)(path, buf);
+ if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
+ return res;
+}
+INTERCEPTOR(int, fstatfs, int fd, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fstatfs, fd, buf);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(fstatfs)(fd, buf);
+ if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
+ return res;
+}
+#define INIT_STATFS \
+ COMMON_INTERCEPT_FUNCTION(statfs); \
+ COMMON_INTERCEPT_FUNCTION(fstatfs);
+#else
+#define INIT_STATFS
+#endif
+
+#if SANITIZER_INTERCEPT_STATFS64
+INTERCEPTOR(int, statfs64, char *path, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, statfs64, path, buf);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(statfs64)(path, buf);
+ if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
+ return res;
+}
+INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fstatfs64, fd, buf);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(fstatfs64)(fd, buf);
+ if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
+ return res;
+}
+#define INIT_STATFS64 \
+ COMMON_INTERCEPT_FUNCTION(statfs64); \
+ COMMON_INTERCEPT_FUNCTION(fstatfs64);
+#else
+#define INIT_STATFS64
+#endif
+
+#if SANITIZER_INTERCEPT_STATVFS
+INTERCEPTOR(int, statvfs, char *path, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(statvfs)(path, buf);
+ if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
+ return res;
+}
+INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(fstatvfs)(fd, buf);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
+ if (fd >= 0)
+ COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ }
+ return res;
+}
+#define INIT_STATVFS \
+ COMMON_INTERCEPT_FUNCTION(statvfs); \
+ COMMON_INTERCEPT_FUNCTION(fstatvfs);
+#else
+#define INIT_STATVFS
+#endif
+
+#if SANITIZER_INTERCEPT_STATVFS64
+INTERCEPTOR(int, statvfs64, char *path, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, statvfs64, path, buf);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(statvfs64)(path, buf);
+ if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
+ return res;
+}
+INTERCEPTOR(int, fstatvfs64, int fd, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs64, fd, buf);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(fstatvfs64)(fd, buf);
+ if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
+ return res;
+}
+#define INIT_STATVFS64 \
+ COMMON_INTERCEPT_FUNCTION(statvfs64); \
+ COMMON_INTERCEPT_FUNCTION(fstatvfs64);
+#else
+#define INIT_STATVFS64
+#endif
+
+#if SANITIZER_INTERCEPT_INITGROUPS
+INTERCEPTOR(int, initgroups, char *user, u32 group) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, initgroups, user, group);
+ if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, internal_strlen(user) + 1);
+ int res = REAL(initgroups)(user, group);
+ return res;
+}
+#define INIT_INITGROUPS COMMON_INTERCEPT_FUNCTION(initgroups);
+#else
+#define INIT_INITGROUPS
+#endif
+
+#if SANITIZER_INTERCEPT_ETHER_NTOA_ATON
+INTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa, addr);
+ if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
+ char *res = REAL(ether_ntoa)(addr);
+ if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+ return res;
+}
+INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ether_aton, buf);
+ if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, internal_strlen(buf) + 1);
+ __sanitizer_ether_addr *res = REAL(ether_aton)(buf);
+ if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, sizeof(*res));
+ return res;
+}
+#define INIT_ETHER_NTOA_ATON \
+ COMMON_INTERCEPT_FUNCTION(ether_ntoa); \
+ COMMON_INTERCEPT_FUNCTION(ether_aton);
+#else
+#define INIT_ETHER_NTOA_ATON
+#endif
+
+#if SANITIZER_INTERCEPT_ETHER_HOST
+INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ether_ntohost, hostname, addr);
+ if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(ether_ntohost)(hostname, addr);
+ if (!res && hostname)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
+ return res;
+}
+INTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ether_hostton, hostname, addr);
+ if (hostname)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(ether_hostton)(hostname, addr);
+ if (!res && addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
+ return res;
+}
+INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
+ char *hostname) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ether_line, line, addr, hostname);
+ if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, internal_strlen(line) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(ether_line)(line, addr, hostname);
+ if (!res) {
+ if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
+ if (hostname)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, internal_strlen(hostname) + 1);
+ }
+ return res;
+}
+#define INIT_ETHER_HOST \
+ COMMON_INTERCEPT_FUNCTION(ether_ntohost); \
+ COMMON_INTERCEPT_FUNCTION(ether_hostton); \
+ COMMON_INTERCEPT_FUNCTION(ether_line);
+#else
+#define INIT_ETHER_HOST
+#endif
+
+#if SANITIZER_INTERCEPT_ETHER_R
+INTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa_r, addr, buf);
+ if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *res = REAL(ether_ntoa_r)(addr, buf);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
+ return res;
+}
+INTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf,
+ __sanitizer_ether_addr *addr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ether_aton_r, buf, addr);
+ if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, internal_strlen(buf) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ __sanitizer_ether_addr *res = REAL(ether_aton_r)(buf, addr);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(*res));
+ return res;
+}
+#define INIT_ETHER_R \
+ COMMON_INTERCEPT_FUNCTION(ether_ntoa_r); \
+ COMMON_INTERCEPT_FUNCTION(ether_aton_r);
+#else
+#define INIT_ETHER_R
+#endif
+
+#if SANITIZER_INTERCEPT_SHMCTL
+INTERCEPTOR(int, shmctl, int shmid, int cmd, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, shmctl, shmid, cmd, buf);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(shmctl)(shmid, cmd, buf);
+ if (res >= 0) {
+ unsigned sz = 0;
+ if (cmd == shmctl_ipc_stat || cmd == shmctl_shm_stat)
+ sz = sizeof(__sanitizer_shmid_ds);
+ else if (cmd == shmctl_ipc_info)
+ sz = struct_shminfo_sz;
+ else if (cmd == shmctl_shm_info)
+ sz = struct_shm_info_sz;
+ if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
+ }
+ return res;
+}
+#define INIT_SHMCTL COMMON_INTERCEPT_FUNCTION(shmctl);
+#else
+#define INIT_SHMCTL
+#endif
+
+#if SANITIZER_INTERCEPT_RANDOM_R
+INTERCEPTOR(int, random_r, void *buf, u32 *result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, random_r, buf, result);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(random_r)(buf, result);
+ if (!res && result)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ return res;
+}
+#define INIT_RANDOM_R COMMON_INTERCEPT_FUNCTION(random_r);
+#else
+#define INIT_RANDOM_R
+#endif
+
+// FIXME: under ASan the REAL() call below may write to freed memory and corrupt
+// its metadata. See
+// https://github.com/google/sanitizers/issues/321.
+#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET || \
+ SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED || \
+ SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSSCHED || \
+ SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GET || \
+ SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GET || \
+ SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GET || \
+ SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GET
+#define INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(fn, sz) \
+ INTERCEPTOR(int, fn, void *attr, void *r) { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, fn, attr, r); \
+ int res = REAL(fn)(attr, r); \
+ if (!res && r) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, r, sz); \
+ return res; \
+ }
+#define INTERCEPTOR_PTHREAD_ATTR_GET(what, sz) \
+ INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_attr_get##what, sz)
+#define INTERCEPTOR_PTHREAD_MUTEXATTR_GET(what, sz) \
+ INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_mutexattr_get##what, sz)
+#define INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(what, sz) \
+ INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_rwlockattr_get##what, sz)
+#define INTERCEPTOR_PTHREAD_CONDATTR_GET(what, sz) \
+ INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_condattr_get##what, sz)
+#define INTERCEPTOR_PTHREAD_BARRIERATTR_GET(what, sz) \
+ INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_barrierattr_get##what, sz)
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET
+INTERCEPTOR_PTHREAD_ATTR_GET(detachstate, sizeof(int))
+INTERCEPTOR_PTHREAD_ATTR_GET(guardsize, sizeof(SIZE_T))
+INTERCEPTOR_PTHREAD_ATTR_GET(scope, sizeof(int))
+INTERCEPTOR_PTHREAD_ATTR_GET(stacksize, sizeof(SIZE_T))
+INTERCEPTOR(int, pthread_attr_getstack, void *attr, void **addr, SIZE_T *size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getstack, attr, addr, size);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(pthread_attr_getstack)(attr, addr, size);
+ if (!res) {
+ if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
+ if (size) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, size, sizeof(*size));
+ }
+ return res;
+}
+
+// We may need to call the real pthread_attr_getstack from the run-time
+// in sanitizer_common, but we don't want to include the interception headers
+// there. So, just define this function here.
+namespace __sanitizer {
+extern "C" {
+int real_pthread_attr_getstack(void *attr, void **addr, SIZE_T *size) {
+ return REAL(pthread_attr_getstack)(attr, addr, size);
+}
+} // extern "C"
+} // namespace __sanitizer
+
+#define INIT_PTHREAD_ATTR_GET \
+ COMMON_INTERCEPT_FUNCTION(pthread_attr_getdetachstate); \
+ COMMON_INTERCEPT_FUNCTION(pthread_attr_getguardsize); \
+ COMMON_INTERCEPT_FUNCTION(pthread_attr_getscope); \
+ COMMON_INTERCEPT_FUNCTION(pthread_attr_getstacksize); \
+ COMMON_INTERCEPT_FUNCTION(pthread_attr_getstack);
+#else
+#define INIT_PTHREAD_ATTR_GET
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED
+INTERCEPTOR_PTHREAD_ATTR_GET(schedparam, struct_sched_param_sz)
+INTERCEPTOR_PTHREAD_ATTR_GET(schedpolicy, sizeof(int))
+
+#define INIT_PTHREAD_ATTR_GET_SCHED \
+ COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedparam); \
+ COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedpolicy);
+#else
+#define INIT_PTHREAD_ATTR_GET_SCHED
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED
+INTERCEPTOR_PTHREAD_ATTR_GET(inheritsched, sizeof(int))
+
+#define INIT_PTHREAD_ATTR_GETINHERITSCHED \
+ COMMON_INTERCEPT_FUNCTION(pthread_attr_getinheritsched);
+#else
+#define INIT_PTHREAD_ATTR_GETINHERITSCHED
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP
+INTERCEPTOR(int, pthread_attr_getaffinity_np, void *attr, SIZE_T cpusetsize,
+ void *cpuset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getaffinity_np, attr, cpusetsize,
+ cpuset);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(pthread_attr_getaffinity_np)(attr, cpusetsize, cpuset);
+ if (!res && cpusetsize && cpuset)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize);
+ return res;
+}
+
+#define INIT_PTHREAD_ATTR_GETAFFINITY_NP \
+ COMMON_INTERCEPT_FUNCTION(pthread_attr_getaffinity_np);
+#else
+#define INIT_PTHREAD_ATTR_GETAFFINITY_NP
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_GETAFFINITY_NP
+INTERCEPTOR(int, pthread_getaffinity_np, void *attr, SIZE_T cpusetsize,
+ void *cpuset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_getaffinity_np, attr, cpusetsize,
+ cpuset);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(pthread_getaffinity_np)(attr, cpusetsize, cpuset);
+ if (!res && cpusetsize && cpuset)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize);
+ return res;
+}
+
+#define INIT_PTHREAD_GETAFFINITY_NP \
+ COMMON_INTERCEPT_FUNCTION(pthread_getaffinity_np);
+#else
+#define INIT_PTHREAD_GETAFFINITY_NP
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED
+INTERCEPTOR_PTHREAD_MUTEXATTR_GET(pshared, sizeof(int))
+#define INIT_PTHREAD_MUTEXATTR_GETPSHARED \
+ COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getpshared);
+#else
+#define INIT_PTHREAD_MUTEXATTR_GETPSHARED
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETTYPE
+INTERCEPTOR_PTHREAD_MUTEXATTR_GET(type, sizeof(int))
+#define INIT_PTHREAD_MUTEXATTR_GETTYPE \
+ COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_gettype);
+#else
+#define INIT_PTHREAD_MUTEXATTR_GETTYPE
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPROTOCOL
+INTERCEPTOR_PTHREAD_MUTEXATTR_GET(protocol, sizeof(int))
+#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL \
+ COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprotocol);
+#else
+#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPRIOCEILING
+INTERCEPTOR_PTHREAD_MUTEXATTR_GET(prioceiling, sizeof(int))
+#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING \
+ COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprioceiling);
+#else
+#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST
+INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust, sizeof(int))
+#define INIT_PTHREAD_MUTEXATTR_GETROBUST \
+ COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust);
+#else
+#define INIT_PTHREAD_MUTEXATTR_GETROBUST
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST_NP
+INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust_np, sizeof(int))
+#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP \
+ COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust_np);
+#else
+#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETPSHARED
+INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(pshared, sizeof(int))
+#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED \
+ COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getpshared);
+#else
+#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETKIND_NP
+INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(kind_np, sizeof(int))
+#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP \
+ COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getkind_np);
+#else
+#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETPSHARED
+INTERCEPTOR_PTHREAD_CONDATTR_GET(pshared, sizeof(int))
+#define INIT_PTHREAD_CONDATTR_GETPSHARED \
+ COMMON_INTERCEPT_FUNCTION(pthread_condattr_getpshared);
+#else
+#define INIT_PTHREAD_CONDATTR_GETPSHARED
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETCLOCK
+INTERCEPTOR_PTHREAD_CONDATTR_GET(clock, sizeof(int))
+#define INIT_PTHREAD_CONDATTR_GETCLOCK \
+ COMMON_INTERCEPT_FUNCTION(pthread_condattr_getclock);
+#else
+#define INIT_PTHREAD_CONDATTR_GETCLOCK
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GETPSHARED
+INTERCEPTOR_PTHREAD_BARRIERATTR_GET(pshared, sizeof(int)) // !mac !android
+#define INIT_PTHREAD_BARRIERATTR_GETPSHARED \
+ COMMON_INTERCEPT_FUNCTION(pthread_barrierattr_getpshared);
+#else
+#define INIT_PTHREAD_BARRIERATTR_GETPSHARED
+#endif
+
+#if SANITIZER_INTERCEPT_TMPNAM
+INTERCEPTOR(char *, tmpnam, char *s) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, tmpnam, s);
+ char *res = REAL(tmpnam)(s);
+ if (res) {
+ if (s)
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
+ else
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+ }
+ return res;
+}
+#define INIT_TMPNAM COMMON_INTERCEPT_FUNCTION(tmpnam);
+#else
+#define INIT_TMPNAM
+#endif
+
+#if SANITIZER_INTERCEPT_TMPNAM_R
+INTERCEPTOR(char *, tmpnam_r, char *s) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, tmpnam_r, s);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *res = REAL(tmpnam_r)(s);
+ if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, internal_strlen(s) + 1);
+ return res;
+}
+#define INIT_TMPNAM_R COMMON_INTERCEPT_FUNCTION(tmpnam_r);
+#else
+#define INIT_TMPNAM_R
+#endif
+
+#if SANITIZER_INTERCEPT_PTSNAME
+INTERCEPTOR(char *, ptsname, int fd) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ptsname, fd);
+ char *res = REAL(ptsname)(fd);
+ if (res != nullptr)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+ return res;
+}
+#define INIT_PTSNAME COMMON_INTERCEPT_FUNCTION(ptsname);
+#else
+#define INIT_PTSNAME
+#endif
+
+#if SANITIZER_INTERCEPT_PTSNAME_R
+INTERCEPTOR(int, ptsname_r, int fd, char *name, SIZE_T namesize) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ptsname_r, fd, name, namesize);
+ int res = REAL(ptsname_r)(fd, name, namesize);
+ if (res == 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
+ return res;
+}
+#define INIT_PTSNAME_R COMMON_INTERCEPT_FUNCTION(ptsname_r);
+#else
+#define INIT_PTSNAME_R
+#endif
+
+#if SANITIZER_INTERCEPT_TTYNAME
+INTERCEPTOR(char *, ttyname, int fd) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ttyname, fd);
+ char *res = REAL(ttyname)(fd);
+ if (res != nullptr)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+ return res;
+}
+#define INIT_TTYNAME COMMON_INTERCEPT_FUNCTION(ttyname);
+#else
+#define INIT_TTYNAME
+#endif
+
+#if SANITIZER_INTERCEPT_TTYNAME_R
+INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ttyname_r, fd, name, namesize);
+ int res = REAL(ttyname_r)(fd, name, namesize);
+ if (res == 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
+ return res;
+}
+#define INIT_TTYNAME_R COMMON_INTERCEPT_FUNCTION(ttyname_r);
+#else
+#define INIT_TTYNAME_R
+#endif
+
+#if SANITIZER_INTERCEPT_TEMPNAM
+INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, tempnam, dir, pfx);
+ if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, internal_strlen(dir) + 1);
+ if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, internal_strlen(pfx) + 1);
+ char *res = REAL(tempnam)(dir, pfx);
+ if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+ return res;
+}
+#define INIT_TEMPNAM COMMON_INTERCEPT_FUNCTION(tempnam);
+#else
+#define INIT_TEMPNAM
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && !SANITIZER_NETBSD
+INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
+ COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name);
+ return REAL(pthread_setname_np)(thread, name);
+}
+#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
+#elif SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && SANITIZER_NETBSD
+INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name, void *arg) {
+ void *ctx;
+ char newname[32]; // PTHREAD_MAX_NAMELEN_NP=32
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name, arg);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
+ internal_snprintf(newname, sizeof(newname), name, arg);
+ COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, newname);
+ return REAL(pthread_setname_np)(thread, name, arg);
+}
+#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
+#else
+#define INIT_PTHREAD_SETNAME_NP
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_GETNAME_NP
+INTERCEPTOR(int, pthread_getname_np, uptr thread, char *name, SIZE_T len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_getname_np, thread, name, len);
+ int res = REAL(pthread_getname_np)(thread, name, len);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strnlen(name, len) + 1);
+ return res;
+}
+#define INIT_PTHREAD_GETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_getname_np);
+#else
+#define INIT_PTHREAD_GETNAME_NP
+#endif
+
+#if SANITIZER_INTERCEPT_SINCOS
+INTERCEPTOR(void, sincos, double x, double *sin, double *cos) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sincos, x, sin, cos);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ REAL(sincos)(x, sin, cos);
+ if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
+ if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
+}
+INTERCEPTOR(void, sincosf, float x, float *sin, float *cos) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sincosf, x, sin, cos);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ REAL(sincosf)(x, sin, cos);
+ if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
+ if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
+}
+INTERCEPTOR(void, sincosl, long double x, long double *sin, long double *cos) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sincosl, x, sin, cos);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ REAL(sincosl)(x, sin, cos);
+ if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
+ if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
+}
+#define INIT_SINCOS \
+ COMMON_INTERCEPT_FUNCTION(sincos); \
+ COMMON_INTERCEPT_FUNCTION(sincosf); \
+ COMMON_INTERCEPT_FUNCTION_LDBL(sincosl);
+#else
+#define INIT_SINCOS
+#endif
+
+#if SANITIZER_INTERCEPT_REMQUO
+INTERCEPTOR(double, remquo, double x, double y, int *quo) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, remquo, x, y, quo);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ double res = REAL(remquo)(x, y, quo);
+ if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
+ return res;
+}
+INTERCEPTOR(float, remquof, float x, float y, int *quo) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, remquof, x, y, quo);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ float res = REAL(remquof)(x, y, quo);
+ if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
+ return res;
+}
+#define INIT_REMQUO \
+ COMMON_INTERCEPT_FUNCTION(remquo); \
+ COMMON_INTERCEPT_FUNCTION(remquof);
+#else
+#define INIT_REMQUO
+#endif
+
+#if SANITIZER_INTERCEPT_REMQUOL
+INTERCEPTOR(long double, remquol, long double x, long double y, int *quo) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, remquol, x, y, quo);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ long double res = REAL(remquol)(x, y, quo);
+ if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
+ return res;
+}
+#define INIT_REMQUOL \
+ COMMON_INTERCEPT_FUNCTION_LDBL(remquol);
+#else
+#define INIT_REMQUOL
+#endif
+
+#if SANITIZER_INTERCEPT_LGAMMA
+extern int signgam;
+INTERCEPTOR(double, lgamma, double x) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, lgamma, x);
+ double res = REAL(lgamma)(x);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
+ return res;
+}
+INTERCEPTOR(float, lgammaf, float x) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, lgammaf, x);
+ float res = REAL(lgammaf)(x);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
+ return res;
+}
+#define INIT_LGAMMA \
+ COMMON_INTERCEPT_FUNCTION(lgamma); \
+ COMMON_INTERCEPT_FUNCTION(lgammaf);
+#else
+#define INIT_LGAMMA
+#endif
+
+#if SANITIZER_INTERCEPT_LGAMMAL
+INTERCEPTOR(long double, lgammal, long double x) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, lgammal, x);
+ long double res = REAL(lgammal)(x);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
+ return res;
+}
+#define INIT_LGAMMAL \
+ COMMON_INTERCEPT_FUNCTION_LDBL(lgammal);
+#else
+#define INIT_LGAMMAL
+#endif
+
+#if SANITIZER_INTERCEPT_LGAMMA_R
+INTERCEPTOR(double, lgamma_r, double x, int *signp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, lgamma_r, x, signp);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ double res = REAL(lgamma_r)(x, signp);
+ if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
+ return res;
+}
+INTERCEPTOR(float, lgammaf_r, float x, int *signp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, lgammaf_r, x, signp);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ float res = REAL(lgammaf_r)(x, signp);
+ if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
+ return res;
+}
+#define INIT_LGAMMA_R \
+ COMMON_INTERCEPT_FUNCTION(lgamma_r); \
+ COMMON_INTERCEPT_FUNCTION(lgammaf_r);
+#else
+#define INIT_LGAMMA_R
+#endif
+
+#if SANITIZER_INTERCEPT_LGAMMAL_R
+INTERCEPTOR(long double, lgammal_r, long double x, int *signp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, lgammal_r, x, signp);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ long double res = REAL(lgammal_r)(x, signp);
+ if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
+ return res;
+}
+#define INIT_LGAMMAL_R COMMON_INTERCEPT_FUNCTION_LDBL(lgammal_r);
+#else
+#define INIT_LGAMMAL_R
+#endif
+
+#if SANITIZER_INTERCEPT_DRAND48_R
+INTERCEPTOR(int, drand48_r, void *buffer, double *result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, drand48_r, buffer, result);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(drand48_r)(buffer, result);
+ if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ return res;
+}
+INTERCEPTOR(int, lrand48_r, void *buffer, long *result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, lrand48_r, buffer, result);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(lrand48_r)(buffer, result);
+ if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ return res;
+}
+#define INIT_DRAND48_R \
+ COMMON_INTERCEPT_FUNCTION(drand48_r); \
+ COMMON_INTERCEPT_FUNCTION(lrand48_r);
+#else
+#define INIT_DRAND48_R
+#endif
+
+#if SANITIZER_INTERCEPT_RAND_R
+INTERCEPTOR(int, rand_r, unsigned *seedp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, rand_r, seedp);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, seedp, sizeof(*seedp));
+ return REAL(rand_r)(seedp);
+}
+#define INIT_RAND_R COMMON_INTERCEPT_FUNCTION(rand_r);
+#else
+#define INIT_RAND_R
+#endif
+
+#if SANITIZER_INTERCEPT_GETLINE
+INTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getline, lineptr, n, stream);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SSIZE_T res = REAL(getline)(lineptr, n, stream);
+ if (res > 0) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);
+ }
+ return res;
+}
+
+// FIXME: under ASan the call below may write to freed memory and corrupt its
+// metadata. See
+// https://github.com/google/sanitizers/issues/321.
+#define GETDELIM_INTERCEPTOR_IMPL(vname) \
+ { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, vname, lineptr, n, delim, stream); \
+ SSIZE_T res = REAL(vname)(lineptr, n, delim, stream); \
+ if (res > 0) { \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr)); \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n)); \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1); \
+ } \
+ return res; \
+ }
+
+INTERCEPTOR(SSIZE_T, __getdelim, char **lineptr, SIZE_T *n, int delim,
+ void *stream)
+GETDELIM_INTERCEPTOR_IMPL(__getdelim)
+
+// There's no __getdelim() on FreeBSD so we supply the getdelim() interceptor
+// with its own body.
+INTERCEPTOR(SSIZE_T, getdelim, char **lineptr, SIZE_T *n, int delim,
+ void *stream)
+GETDELIM_INTERCEPTOR_IMPL(getdelim)
+
+#define INIT_GETLINE \
+ COMMON_INTERCEPT_FUNCTION(getline); \
+ COMMON_INTERCEPT_FUNCTION(__getdelim); \
+ COMMON_INTERCEPT_FUNCTION(getdelim);
+#else
+#define INIT_GETLINE
+#endif
+
+#if SANITIZER_INTERCEPT_ICONV
+INTERCEPTOR(SIZE_T, iconv, void *cd, char **inbuf, SIZE_T *inbytesleft,
+ char **outbuf, SIZE_T *outbytesleft) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, iconv, cd, inbuf, inbytesleft, outbuf,
+ outbytesleft);
+ if (inbytesleft)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, inbytesleft, sizeof(*inbytesleft));
+ if (inbuf && inbytesleft)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *inbuf, *inbytesleft);
+ if (outbytesleft)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, outbytesleft, sizeof(*outbytesleft));
+ void *outbuf_orig = outbuf ? *outbuf : nullptr;
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SIZE_T res = REAL(iconv)(cd, inbuf, inbytesleft, outbuf, outbytesleft);
+ if (outbuf && *outbuf > outbuf_orig) {
+ SIZE_T sz = (char *)*outbuf - (char *)outbuf_orig;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, outbuf_orig, sz);
+ }
+ return res;
+}
+#define INIT_ICONV COMMON_INTERCEPT_FUNCTION(iconv);
+#else
+#define INIT_ICONV
+#endif
+
+#if SANITIZER_INTERCEPT_TIMES
+INTERCEPTOR(__sanitizer_clock_t, times, void *tms) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, times, tms);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ __sanitizer_clock_t res = REAL(times)(tms);
+ if (res != (__sanitizer_clock_t)-1 && tms)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tms, struct_tms_sz);
+ return res;
+}
+#define INIT_TIMES COMMON_INTERCEPT_FUNCTION(times);
+#else
+#define INIT_TIMES
+#endif
+
+#if SANITIZER_S390 && \
+ (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET)
+extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
+DEFINE_REAL(uptr, __tls_get_offset, void *arg)
+#endif
+
+#if SANITIZER_INTERCEPT_TLS_GET_ADDR
+#if !SANITIZER_S390
+#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr)
+// If you see any crashes around this functions, there are 2 known issues with
+// it: 1. __tls_get_addr can be called with mis-aligned stack due to:
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
+// 2. It can be called recursively if sanitizer code uses __tls_get_addr
+// to access thread local variables (it should not happen normally,
+// because sanitizers use initial-exec tls model).
+INTERCEPTOR(void *, __tls_get_addr, void *arg) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg);
+ void *res = REAL(__tls_get_addr)(arg);
+ uptr tls_begin, tls_end;
+ COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
+ DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, tls_begin, tls_end);
+ if (dtv) {
+ // New DTLS block has been allocated.
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
+ }
+ return res;
+}
+#if SANITIZER_PPC
+// On PowerPC, we also need to intercept __tls_get_addr_opt, which has
+// mostly the same semantics as __tls_get_addr, but its presence enables
+// some optimizations in linker (which are safe to ignore here).
+extern "C" __attribute__((alias("__interceptor___tls_get_addr"),
+ visibility("default")))
+void *__tls_get_addr_opt(void *arg);
+#endif
+#else // SANITIZER_S390
+// On s390, we have to intercept two functions here:
+// - __tls_get_addr_internal, which is a glibc-internal function that is like
+// the usual __tls_get_addr, but returns a TP-relative offset instead of
+// a proper pointer. It is used by dlsym for TLS symbols.
+// - __tls_get_offset, which is like the above, but also takes a GOT-relative
+// descriptor offset as an argument instead of a pointer. GOT address
+// is passed in r12, so it's necessary to write it in assembly. This is
+// the function used by the compiler.
+#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset)
+INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg);
+ uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset));
+ uptr tp = reinterpret_cast<uptr>(__builtin_thread_pointer());
+ void *ptr = reinterpret_cast<void *>(res + tp);
+ uptr tls_begin, tls_end;
+ COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
+ DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, ptr, tls_begin, tls_end);
+ if (dtv) {
+ // New DTLS block has been allocated.
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
+ }
+ return res;
+}
+#endif // SANITIZER_S390
+#else
+#define INIT_TLS_GET_ADDR
+#endif
+
+#if SANITIZER_S390 && \
+ (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET)
+extern "C" uptr __tls_get_offset(void *arg);
+extern "C" uptr __interceptor___tls_get_offset(void *arg);
+// We need a hidden symbol aliasing the above, so that we can jump
+// directly to it from the assembly below.
+extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"),
+ visibility("hidden")))
+uptr __tls_get_addr_hidden(void *arg);
+// Now carefully intercept __tls_get_offset.
+asm(
+ ".text\n"
+// The __intercept_ version has to exist, so that gen_dynamic_list.py
+// exports our symbol.
+ ".weak __tls_get_offset\n"
+ ".type __tls_get_offset, @function\n"
+ "__tls_get_offset:\n"
+ ".global __interceptor___tls_get_offset\n"
+ ".type __interceptor___tls_get_offset, @function\n"
+ "__interceptor___tls_get_offset:\n"
+#ifdef __s390x__
+ "la %r2, 0(%r2,%r12)\n"
+ "jg __tls_get_addr_hidden\n"
+#else
+ "basr %r3,0\n"
+ "0: la %r2,0(%r2,%r12)\n"
+ "l %r4,1f-0b(%r3)\n"
+ "b 0(%r4,%r3)\n"
+ "1: .long __tls_get_addr_hidden - 0b\n"
+#endif
+ ".size __interceptor___tls_get_offset, .-__interceptor___tls_get_offset\n"
+// Assembly wrapper to call REAL(__tls_get_offset)(arg)
+ ".type __tls_get_offset_wrapper, @function\n"
+ "__tls_get_offset_wrapper:\n"
+#ifdef __s390x__
+ "sgr %r2,%r12\n"
+#else
+ "sr %r2,%r12\n"
+#endif
+ "br %r3\n"
+ ".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n"
+);
+#endif
+
+#if SANITIZER_INTERCEPT_LISTXATTR
+INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, listxattr, path, list, size);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SSIZE_T res = REAL(listxattr)(path, list, size);
+ // Here and below, size == 0 is a special case where nothing is written to the
+ // buffer, and res contains the desired buffer size.
+ if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
+ return res;
+}
+INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, llistxattr, path, list, size);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SSIZE_T res = REAL(llistxattr)(path, list, size);
+ if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
+ return res;
+}
+INTERCEPTOR(SSIZE_T, flistxattr, int fd, char *list, SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, flistxattr, fd, list, size);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SSIZE_T res = REAL(flistxattr)(fd, list, size);
+ if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
+ return res;
+}
+#define INIT_LISTXATTR \
+ COMMON_INTERCEPT_FUNCTION(listxattr); \
+ COMMON_INTERCEPT_FUNCTION(llistxattr); \
+ COMMON_INTERCEPT_FUNCTION(flistxattr);
+#else
+#define INIT_LISTXATTR
+#endif
+
+#if SANITIZER_INTERCEPT_GETXATTR
+INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value,
+ SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getxattr, path, name, value, size);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SSIZE_T res = REAL(getxattr)(path, name, value, size);
+ if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
+ return res;
+}
+INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value,
+ SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, lgetxattr, path, name, value, size);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SSIZE_T res = REAL(lgetxattr)(path, name, value, size);
+ if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
+ return res;
+}
+INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value,
+ SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fgetxattr, fd, name, value, size);
+ if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ SSIZE_T res = REAL(fgetxattr)(fd, name, value, size);
+ if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
+ return res;
+}
+#define INIT_GETXATTR \
+ COMMON_INTERCEPT_FUNCTION(getxattr); \
+ COMMON_INTERCEPT_FUNCTION(lgetxattr); \
+ COMMON_INTERCEPT_FUNCTION(fgetxattr);
+#else
+#define INIT_GETXATTR
+#endif
+
+#if SANITIZER_INTERCEPT_GETRESID
+INTERCEPTOR(int, getresuid, void *ruid, void *euid, void *suid) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getresuid, ruid, euid, suid);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getresuid)(ruid, euid, suid);
+ if (res >= 0) {
+ if (ruid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ruid, uid_t_sz);
+ if (euid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, euid, uid_t_sz);
+ if (suid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, suid, uid_t_sz);
+ }
+ return res;
+}
+INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getresgid, rgid, egid, sgid);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getresgid)(rgid, egid, sgid);
+ if (res >= 0) {
+ if (rgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rgid, gid_t_sz);
+ if (egid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, egid, gid_t_sz);
+ if (sgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sgid, gid_t_sz);
+ }
+ return res;
+}
+#define INIT_GETRESID \
+ COMMON_INTERCEPT_FUNCTION(getresuid); \
+ COMMON_INTERCEPT_FUNCTION(getresgid);
+#else
+#define INIT_GETRESID
+#endif
+
+#if SANITIZER_INTERCEPT_GETIFADDRS
+// As long as getifaddrs()/freeifaddrs() use calloc()/free(), we don't need to
+// intercept freeifaddrs(). If that ceases to be the case, we might need to
+// intercept it to poison the memory again.
+INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getifaddrs, ifap);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(getifaddrs)(ifap);
+ if (res == 0 && ifap) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifap, sizeof(void *));
+ __sanitizer_ifaddrs *p = *ifap;
+ while (p) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(__sanitizer_ifaddrs));
+ if (p->ifa_name)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_name,
+ internal_strlen(p->ifa_name) + 1);
+ if (p->ifa_addr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_addr, struct_sockaddr_sz);
+ if (p->ifa_netmask)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_netmask, struct_sockaddr_sz);
+ // On Linux this is a union, but the other member also points to a
+ // struct sockaddr, so the following is sufficient.
+ if (p->ifa_dstaddr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_dstaddr, struct_sockaddr_sz);
+ // FIXME(smatveev): Unpoison p->ifa_data as well.
+ p = p->ifa_next;
+ }
+ }
+ return res;
+}
+#define INIT_GETIFADDRS \
+ COMMON_INTERCEPT_FUNCTION(getifaddrs);
+#else
+#define INIT_GETIFADDRS
+#endif
+
+#if SANITIZER_INTERCEPT_IF_INDEXTONAME
+INTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, if_indextoname, ifindex, ifname);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ char *res = REAL(if_indextoname)(ifindex, ifname);
+ if (res && ifname)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, internal_strlen(ifname) + 1);
+ return res;
+}
+INTERCEPTOR(unsigned int, if_nametoindex, const char* ifname) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, if_nametoindex, ifname);
+ if (ifname)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, internal_strlen(ifname) + 1);
+ return REAL(if_nametoindex)(ifname);
+}
+#define INIT_IF_INDEXTONAME \
+ COMMON_INTERCEPT_FUNCTION(if_indextoname); \
+ COMMON_INTERCEPT_FUNCTION(if_nametoindex);
+#else
+#define INIT_IF_INDEXTONAME
+#endif
+
+#if SANITIZER_INTERCEPT_CAPGET
+INTERCEPTOR(int, capget, void *hdrp, void *datap) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, capget, hdrp, datap);
+ if (hdrp)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(capget)(hdrp, datap);
+ if (res == 0 && datap)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, __user_cap_data_struct_sz);
+ // We can also return -1 and write to hdrp->version if the version passed in
+ // hdrp->version is unsupported. But that's not a trivial condition to check,
+ // and anyway COMMON_INTERCEPTOR_READ_RANGE protects us to some extent.
+ return res;
+}
+INTERCEPTOR(int, capset, void *hdrp, const void *datap) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, capset, hdrp, datap);
+ if (hdrp)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
+ if (datap)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, datap, __user_cap_data_struct_sz);
+ return REAL(capset)(hdrp, datap);
+}
+#define INIT_CAPGET \
+ COMMON_INTERCEPT_FUNCTION(capget); \
+ COMMON_INTERCEPT_FUNCTION(capset);
+#else
+#define INIT_CAPGET
+#endif
+
+#if SANITIZER_INTERCEPT_AEABI_MEM
+INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
+}
+
+INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
+}
+
+INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
+}
+
+INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
+}
+
+INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
+}
+
+INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
+}
+
+// Note the argument order.
+INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
+}
+
+INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
+}
+
+INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
+}
+
+INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
+}
+
+INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
+}
+
+INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
+}
+
+#define INIT_AEABI_MEM \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memmove); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memmove4); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memmove8); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy4); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy8); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memset); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memset4); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memset8); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memclr); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memclr4); \
+ COMMON_INTERCEPT_FUNCTION(__aeabi_memclr8);
+#else
+#define INIT_AEABI_MEM
+#endif // SANITIZER_INTERCEPT_AEABI_MEM
+
+#if SANITIZER_INTERCEPT___BZERO
+INTERCEPTOR(void *, __bzero, void *block, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
+}
+#define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero);
+#else
+#define INIT___BZERO
+#endif // SANITIZER_INTERCEPT___BZERO
+
+#if SANITIZER_INTERCEPT_BZERO
+INTERCEPTOR(void *, bzero, void *block, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
+}
+#define INIT_BZERO COMMON_INTERCEPT_FUNCTION(bzero);
+#else
+#define INIT_BZERO
+#endif // SANITIZER_INTERCEPT_BZERO
+
+#if SANITIZER_INTERCEPT_FTIME
+INTERCEPTOR(int, ftime, __sanitizer_timeb *tp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ftime, tp);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(ftime)(tp);
+ if (tp)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, sizeof(*tp));
+ return res;
+}
+#define INIT_FTIME COMMON_INTERCEPT_FUNCTION(ftime);
+#else
+#define INIT_FTIME
+#endif // SANITIZER_INTERCEPT_FTIME
+
+#if SANITIZER_INTERCEPT_XDR
+INTERCEPTOR(void, xdrmem_create, __sanitizer_XDR *xdrs, uptr addr,
+ unsigned size, int op) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, xdrmem_create, xdrs, addr, size, op);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ REAL(xdrmem_create)(xdrs, addr, size, op);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
+ if (op == __sanitizer_XDR_ENCODE) {
+ // It's not obvious how much data individual xdr_ routines write.
+ // Simply unpoison the entire target buffer in advance.
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (void *)addr, size);
+ }
+}
+
+INTERCEPTOR(void, xdrstdio_create, __sanitizer_XDR *xdrs, void *file, int op) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, xdrstdio_create, xdrs, file, op);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ REAL(xdrstdio_create)(xdrs, file, op);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
+}
+
+// FIXME: under ASan the call below may write to freed memory and corrupt
+// its metadata. See
+// https://github.com/google/sanitizers/issues/321.
+#define XDR_INTERCEPTOR(F, T) \
+ INTERCEPTOR(int, F, __sanitizer_XDR *xdrs, T *p) { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, F, xdrs, p); \
+ if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p)); \
+ int res = REAL(F)(xdrs, p); \
+ if (res && p && xdrs->x_op == __sanitizer_XDR_DECODE) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); \
+ return res; \
+ }
+
+XDR_INTERCEPTOR(xdr_short, short)
+XDR_INTERCEPTOR(xdr_u_short, unsigned short)
+XDR_INTERCEPTOR(xdr_int, int)
+XDR_INTERCEPTOR(xdr_u_int, unsigned)
+XDR_INTERCEPTOR(xdr_long, long)
+XDR_INTERCEPTOR(xdr_u_long, unsigned long)
+XDR_INTERCEPTOR(xdr_hyper, long long)
+XDR_INTERCEPTOR(xdr_u_hyper, unsigned long long)
+XDR_INTERCEPTOR(xdr_longlong_t, long long)
+XDR_INTERCEPTOR(xdr_u_longlong_t, unsigned long long)
+XDR_INTERCEPTOR(xdr_int8_t, u8)
+XDR_INTERCEPTOR(xdr_uint8_t, u8)
+XDR_INTERCEPTOR(xdr_int16_t, u16)
+XDR_INTERCEPTOR(xdr_uint16_t, u16)
+XDR_INTERCEPTOR(xdr_int32_t, u32)
+XDR_INTERCEPTOR(xdr_uint32_t, u32)
+XDR_INTERCEPTOR(xdr_int64_t, u64)
+XDR_INTERCEPTOR(xdr_uint64_t, u64)
+XDR_INTERCEPTOR(xdr_quad_t, long long)
+XDR_INTERCEPTOR(xdr_u_quad_t, unsigned long long)
+XDR_INTERCEPTOR(xdr_bool, bool)
+XDR_INTERCEPTOR(xdr_enum, int)
+XDR_INTERCEPTOR(xdr_char, char)
+XDR_INTERCEPTOR(xdr_u_char, unsigned char)
+XDR_INTERCEPTOR(xdr_float, float)
+XDR_INTERCEPTOR(xdr_double, double)
+
+// FIXME: intercept xdr_array, opaque, union, vector, reference, pointer,
+// wrapstring, sizeof
+
+INTERCEPTOR(int, xdr_bytes, __sanitizer_XDR *xdrs, char **p, unsigned *sizep,
+ unsigned maxsize) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, xdr_bytes, xdrs, p, sizep, maxsize);
+ if (p && sizep && xdrs->x_op == __sanitizer_XDR_ENCODE) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sizep, sizeof(*sizep));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, *sizep);
+ }
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(xdr_bytes)(xdrs, p, sizep, maxsize);
+ if (p && sizep && xdrs->x_op == __sanitizer_XDR_DECODE) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizep, sizeof(*sizep));
+ if (res && *p && *sizep) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, *sizep);
+ }
+ return res;
+}
+
+INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
+ unsigned maxsize) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, xdr_string, xdrs, p, maxsize);
+ if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, internal_strlen(*p) + 1);
+ }
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(xdr_string)(xdrs, p, maxsize);
+ if (p && xdrs->x_op == __sanitizer_XDR_DECODE) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
+ if (res && *p)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, internal_strlen(*p) + 1);
+ }
+ return res;
+}
+
+#define INIT_XDR \
+ COMMON_INTERCEPT_FUNCTION(xdrmem_create); \
+ COMMON_INTERCEPT_FUNCTION(xdrstdio_create); \
+ COMMON_INTERCEPT_FUNCTION(xdr_short); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_short); \
+ COMMON_INTERCEPT_FUNCTION(xdr_int); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_int); \
+ COMMON_INTERCEPT_FUNCTION(xdr_long); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_long); \
+ COMMON_INTERCEPT_FUNCTION(xdr_hyper); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_hyper); \
+ COMMON_INTERCEPT_FUNCTION(xdr_longlong_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_longlong_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_int8_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_uint8_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_int16_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_uint16_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_int32_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_uint32_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_int64_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_uint64_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_quad_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_quad_t); \
+ COMMON_INTERCEPT_FUNCTION(xdr_bool); \
+ COMMON_INTERCEPT_FUNCTION(xdr_enum); \
+ COMMON_INTERCEPT_FUNCTION(xdr_char); \
+ COMMON_INTERCEPT_FUNCTION(xdr_u_char); \
+ COMMON_INTERCEPT_FUNCTION(xdr_float); \
+ COMMON_INTERCEPT_FUNCTION(xdr_double); \
+ COMMON_INTERCEPT_FUNCTION(xdr_bytes); \
+ COMMON_INTERCEPT_FUNCTION(xdr_string);
+#else
+#define INIT_XDR
+#endif // SANITIZER_INTERCEPT_XDR
+
+#if SANITIZER_INTERCEPT_XDRREC
+typedef int (*xdrrec_cb)(char*, char*, int);
+struct XdrRecWrapper {
+ char *handle;
+ xdrrec_cb rd, wr;
+};
+typedef AddrHashMap<XdrRecWrapper *, 11> XdrRecWrapMap;
+static XdrRecWrapMap *xdrrec_wrap_map;
+
+static int xdrrec_wr_wrap(char *handle, char *buf, int count) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(buf, count);
+ XdrRecWrapper *wrap = (XdrRecWrapper *)handle;
+ return wrap->wr(wrap->handle, buf, count);
+}
+
+static int xdrrec_rd_wrap(char *handle, char *buf, int count) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ XdrRecWrapper *wrap = (XdrRecWrapper *)handle;
+ return wrap->rd(wrap->handle, buf, count);
+}
+
+// This doesn't apply to the solaris version as it has a different function
+// signature.
+INTERCEPTOR(void, xdrrec_create, __sanitizer_XDR *xdr, unsigned sndsize,
+ unsigned rcvsize, char *handle, int (*rd)(char*, char*, int),
+ int (*wr)(char*, char*, int)) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, xdrrec_create, xdr, sndsize, rcvsize,
+ handle, rd, wr);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &xdr->x_op, sizeof xdr->x_op);
+
+ // We can't allocate a wrapper on the stack, as the handle is used outside
+ // this stack frame. So we put it on the heap, and keep track of it with
+ // the HashMap (keyed by x_private). When we later need to xdr_destroy,
+ // we can index the map, free the wrapper, and then clean the map entry.
+ XdrRecWrapper *wrap_data =
+ (XdrRecWrapper *)InternalAlloc(sizeof(XdrRecWrapper));
+ wrap_data->handle = handle;
+ wrap_data->rd = rd;
+ wrap_data->wr = wr;
+ if (wr)
+ wr = xdrrec_wr_wrap;
+ if (rd)
+ rd = xdrrec_rd_wrap;
+ handle = (char *)wrap_data;
+
+ REAL(xdrrec_create)(xdr, sndsize, rcvsize, handle, rd, wr);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdr, sizeof *xdr);
+
+ XdrRecWrapMap::Handle wrap(xdrrec_wrap_map, xdr->x_private, false, true);
+ *wrap = wrap_data;
+}
+
+// We have to intercept this to be able to free wrapper memory;
+// otherwise it's not necessary.
+INTERCEPTOR(void, xdr_destroy, __sanitizer_XDR *xdr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, xdr_destroy, xdr);
+
+ XdrRecWrapMap::Handle wrap(xdrrec_wrap_map, xdr->x_private, true);
+ InternalFree(*wrap);
+ REAL(xdr_destroy)(xdr);
+}
+#define INIT_XDRREC_LINUX \
+ static u64 xdrrec_wrap_mem[sizeof(XdrRecWrapMap) / sizeof(u64) + 1]; \
+ xdrrec_wrap_map = new ((void *)&xdrrec_wrap_mem) XdrRecWrapMap(); \
+ COMMON_INTERCEPT_FUNCTION(xdrrec_create); \
+ COMMON_INTERCEPT_FUNCTION(xdr_destroy);
+#else
+#define INIT_XDRREC_LINUX
+#endif
+
+#if SANITIZER_INTERCEPT_TSEARCH
+INTERCEPTOR(void *, tsearch, void *key, void **rootp,
+ int (*compar)(const void *, const void *)) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, tsearch, key, rootp, compar);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ void *res = REAL(tsearch)(key, rootp, compar);
+ if (res && *(void **)res == key)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(void *));
+ return res;
+}
+#define INIT_TSEARCH COMMON_INTERCEPT_FUNCTION(tsearch);
+#else
+#define INIT_TSEARCH
+#endif
+
+#if SANITIZER_INTERCEPT_LIBIO_INTERNALS || SANITIZER_INTERCEPT_FOPEN || \
+ SANITIZER_INTERCEPT_OPEN_MEMSTREAM
+void unpoison_file(__sanitizer_FILE *fp) {
+#if SANITIZER_HAS_STRUCT_FILE
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp, sizeof(*fp));
+#if SANITIZER_NETBSD
+ if (fp->_bf._base && fp->_bf._size > 0)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_bf._base,
+ fp->_bf._size);
+#else
+ if (fp->_IO_read_base && fp->_IO_read_base < fp->_IO_read_end)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_read_base,
+ fp->_IO_read_end - fp->_IO_read_base);
+ if (fp->_IO_write_base && fp->_IO_write_base < fp->_IO_write_end)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_write_base,
+ fp->_IO_write_end - fp->_IO_write_base);
+#endif
+#endif // SANITIZER_HAS_STRUCT_FILE
+}
+#endif
+
+#if SANITIZER_INTERCEPT_LIBIO_INTERNALS
+// These guys are called when a .c source is built with -O2.
+INTERCEPTOR(int, __uflow, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __uflow, fp);
+ int res = REAL(__uflow)(fp);
+ unpoison_file(fp);
+ return res;
+}
+INTERCEPTOR(int, __underflow, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __underflow, fp);
+ int res = REAL(__underflow)(fp);
+ unpoison_file(fp);
+ return res;
+}
+INTERCEPTOR(int, __overflow, __sanitizer_FILE *fp, int ch) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __overflow, fp, ch);
+ int res = REAL(__overflow)(fp, ch);
+ unpoison_file(fp);
+ return res;
+}
+INTERCEPTOR(int, __wuflow, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __wuflow, fp);
+ int res = REAL(__wuflow)(fp);
+ unpoison_file(fp);
+ return res;
+}
+INTERCEPTOR(int, __wunderflow, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __wunderflow, fp);
+ int res = REAL(__wunderflow)(fp);
+ unpoison_file(fp);
+ return res;
+}
+INTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __woverflow, fp, ch);
+ int res = REAL(__woverflow)(fp, ch);
+ unpoison_file(fp);
+ return res;
+}
+#define INIT_LIBIO_INTERNALS \
+ COMMON_INTERCEPT_FUNCTION(__uflow); \
+ COMMON_INTERCEPT_FUNCTION(__underflow); \
+ COMMON_INTERCEPT_FUNCTION(__overflow); \
+ COMMON_INTERCEPT_FUNCTION(__wuflow); \
+ COMMON_INTERCEPT_FUNCTION(__wunderflow); \
+ COMMON_INTERCEPT_FUNCTION(__woverflow);
+#else
+#define INIT_LIBIO_INTERNALS
+#endif
+
+#if SANITIZER_INTERCEPT_FOPEN
+INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fopen, path, mode);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
+ __sanitizer_FILE *res = REAL(fopen)(path, mode);
+ COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
+ if (res) unpoison_file(res);
+ return res;
+}
+INTERCEPTOR(__sanitizer_FILE *, fdopen, int fd, const char *mode) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fdopen, fd, mode);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
+ __sanitizer_FILE *res = REAL(fdopen)(fd, mode);
+ if (res) unpoison_file(res);
+ return res;
+}
+INTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode,
+ __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, freopen, path, mode, fp);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
+ COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
+ __sanitizer_FILE *res = REAL(freopen)(path, mode, fp);
+ COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
+ if (res) unpoison_file(res);
+ return res;
+}
+#define INIT_FOPEN \
+ COMMON_INTERCEPT_FUNCTION(fopen); \
+ COMMON_INTERCEPT_FUNCTION(fdopen); \
+ COMMON_INTERCEPT_FUNCTION(freopen);
+#else
+#define INIT_FOPEN
+#endif
+
+#if SANITIZER_INTERCEPT_FLOPEN
+INTERCEPTOR(int, flopen, const char *path, int flags, ...) {
+ void *ctx;
+ va_list ap;
+ va_start(ap, flags);
+ u16 mode = static_cast<u16>(va_arg(ap, u32));
+ va_end(ap);
+ COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode);
+ if (path) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ }
+ return REAL(flopen)(path, flags, mode);
+}
+
+INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) {
+ void *ctx;
+ va_list ap;
+ va_start(ap, flags);
+ u16 mode = static_cast<u16>(va_arg(ap, u32));
+ va_end(ap);
+ COMMON_INTERCEPTOR_ENTER(ctx, flopen, path, flags, mode);
+ if (path) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ }
+ return REAL(flopenat)(dirfd, path, flags, mode);
+}
+
+#define INIT_FLOPEN \
+ COMMON_INTERCEPT_FUNCTION(flopen); \
+ COMMON_INTERCEPT_FUNCTION(flopenat);
+#else
+#define INIT_FLOPEN
+#endif
+
+#if SANITIZER_INTERCEPT_FOPEN64
+INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fopen64, path, mode);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
+ __sanitizer_FILE *res = REAL(fopen64)(path, mode);
+ COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
+ if (res) unpoison_file(res);
+ return res;
+}
+INTERCEPTOR(__sanitizer_FILE *, freopen64, const char *path, const char *mode,
+ __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, freopen64, path, mode, fp);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, internal_strlen(mode) + 1);
+ COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
+ __sanitizer_FILE *res = REAL(freopen64)(path, mode, fp);
+ COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
+ if (res) unpoison_file(res);
+ return res;
+}
+#define INIT_FOPEN64 \
+ COMMON_INTERCEPT_FUNCTION(fopen64); \
+ COMMON_INTERCEPT_FUNCTION(freopen64);
+#else
+#define INIT_FOPEN64
+#endif
+
+#if SANITIZER_INTERCEPT_OPEN_MEMSTREAM
+INTERCEPTOR(__sanitizer_FILE *, open_memstream, char **ptr, SIZE_T *sizeloc) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, open_memstream, ptr, sizeloc);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ __sanitizer_FILE *res = REAL(open_memstream)(ptr, sizeloc);
+ if (res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
+ unpoison_file(res);
+ FileMetadata file = {ptr, sizeloc};
+ SetInterceptorMetadata(res, file);
+ }
+ return res;
+}
+INTERCEPTOR(__sanitizer_FILE *, open_wmemstream, wchar_t **ptr,
+ SIZE_T *sizeloc) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, open_wmemstream, ptr, sizeloc);
+ __sanitizer_FILE *res = REAL(open_wmemstream)(ptr, sizeloc);
+ if (res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
+ unpoison_file(res);
+ FileMetadata file = {(char **)ptr, sizeloc};
+ SetInterceptorMetadata(res, file);
+ }
+ return res;
+}
+INTERCEPTOR(__sanitizer_FILE *, fmemopen, void *buf, SIZE_T size,
+ const char *mode) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fmemopen, buf, size, mode);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ __sanitizer_FILE *res = REAL(fmemopen)(buf, size, mode);
+ if (res) unpoison_file(res);
+ return res;
+}
+#define INIT_OPEN_MEMSTREAM \
+ COMMON_INTERCEPT_FUNCTION(open_memstream); \
+ COMMON_INTERCEPT_FUNCTION(open_wmemstream); \
+ COMMON_INTERCEPT_FUNCTION(fmemopen);
+#else
+#define INIT_OPEN_MEMSTREAM
+#endif
+
+#if SANITIZER_INTERCEPT_OBSTACK
+static void initialize_obstack(__sanitizer_obstack *obstack) {
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack, sizeof(*obstack));
+ if (obstack->chunk)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack->chunk,
+ sizeof(*obstack->chunk));
+}
+
+INTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack, int sz,
+ int align, void *(*alloc_fn)(uptr arg, uptr sz),
+ void (*free_fn)(uptr arg, void *p)) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin_1, obstack, sz, align, alloc_fn,
+ free_fn);
+ int res = REAL(_obstack_begin_1)(obstack, sz, align, alloc_fn, free_fn);
+ if (res) initialize_obstack(obstack);
+ return res;
+}
+INTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack, int sz,
+ int align, void *(*alloc_fn)(uptr sz), void (*free_fn)(void *p)) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin, obstack, sz, align, alloc_fn,
+ free_fn);
+ int res = REAL(_obstack_begin)(obstack, sz, align, alloc_fn, free_fn);
+ if (res) initialize_obstack(obstack);
+ return res;
+}
+INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, _obstack_newchunk, obstack, length);
+ REAL(_obstack_newchunk)(obstack, length);
+ if (obstack->chunk)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(
+ obstack->chunk, obstack->next_free - (char *)obstack->chunk);
+}
+#define INIT_OBSTACK \
+ COMMON_INTERCEPT_FUNCTION(_obstack_begin_1); \
+ COMMON_INTERCEPT_FUNCTION(_obstack_begin); \
+ COMMON_INTERCEPT_FUNCTION(_obstack_newchunk);
+#else
+#define INIT_OBSTACK
+#endif
+
+#if SANITIZER_INTERCEPT_FFLUSH
+INTERCEPTOR(int, fflush, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fflush, fp);
+ if (fp)
+ unpoison_file(fp);
+ int res = REAL(fflush)(fp);
+ // FIXME: handle fp == NULL
+ if (fp) {
+ const FileMetadata *m = GetInterceptorMetadata(fp);
+ if (m) COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
+ }
+ return res;
+}
+#define INIT_FFLUSH COMMON_INTERCEPT_FUNCTION(fflush);
+#else
+#define INIT_FFLUSH
+#endif
+
+#if SANITIZER_INTERCEPT_FCLOSE
+INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fclose, fp);
+ COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
+ const FileMetadata *m = GetInterceptorMetadata(fp);
+ if (fp)
+ unpoison_file(fp);
+ int res = REAL(fclose)(fp);
+ if (m) {
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
+ DeleteInterceptorMetadata(fp);
+ }
+ return res;
+}
+#define INIT_FCLOSE COMMON_INTERCEPT_FUNCTION(fclose);
+#else
+#define INIT_FCLOSE
+#endif
+
+#if SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
+INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag);
+ if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);
+ void *res = COMMON_INTERCEPTOR_DLOPEN(filename, flag);
+ Symbolizer::GetOrInit()->InvalidateModuleList();
+ COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res);
+ return res;
+}
+
+INTERCEPTOR(int, dlclose, void *handle) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlclose, handle);
+ int res = REAL(dlclose)(handle);
+ Symbolizer::GetOrInit()->InvalidateModuleList();
+ COMMON_INTERCEPTOR_LIBRARY_UNLOADED();
+ return res;
+}
+#define INIT_DLOPEN_DLCLOSE \
+ COMMON_INTERCEPT_FUNCTION(dlopen); \
+ COMMON_INTERCEPT_FUNCTION(dlclose);
+#else
+#define INIT_DLOPEN_DLCLOSE
+#endif
+
+#if SANITIZER_INTERCEPT_GETPASS
+INTERCEPTOR(char *, getpass, const char *prompt) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpass, prompt);
+ if (prompt)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, internal_strlen(prompt)+1);
+ char *res = REAL(getpass)(prompt);
+ if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res)+1);
+ return res;
+}
+
+#define INIT_GETPASS COMMON_INTERCEPT_FUNCTION(getpass);
+#else
+#define INIT_GETPASS
+#endif
+
+#if SANITIZER_INTERCEPT_TIMERFD
+INTERCEPTOR(int, timerfd_settime, int fd, int flags, void *new_value,
+ void *old_value) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, timerfd_settime, fd, flags, new_value,
+ old_value);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerspec_sz);
+ int res = REAL(timerfd_settime)(fd, flags, new_value, old_value);
+ if (res != -1 && old_value)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerspec_sz);
+ return res;
+}
+
+INTERCEPTOR(int, timerfd_gettime, int fd, void *curr_value) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, timerfd_gettime, fd, curr_value);
+ int res = REAL(timerfd_gettime)(fd, curr_value);
+ if (res != -1 && curr_value)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerspec_sz);
+ return res;
+}
+#define INIT_TIMERFD \
+ COMMON_INTERCEPT_FUNCTION(timerfd_settime); \
+ COMMON_INTERCEPT_FUNCTION(timerfd_gettime);
+#else
+#define INIT_TIMERFD
+#endif
+
+#if SANITIZER_INTERCEPT_MLOCKX
+// Linux kernel has a bug that leads to kernel deadlock if a process
+// maps TBs of memory and then calls mlock().
+static void MlockIsUnsupported() {
+ static atomic_uint8_t printed;
+ if (atomic_exchange(&printed, 1, memory_order_relaxed))
+ return;
+ VPrintf(1, "%s ignores mlock/mlockall/munlock/munlockall\n",
+ SanitizerToolName);
+}
+
+INTERCEPTOR(int, mlock, const void *addr, uptr len) {
+ MlockIsUnsupported();
+ return 0;
+}
+
+INTERCEPTOR(int, munlock, const void *addr, uptr len) {
+ MlockIsUnsupported();
+ return 0;
+}
+
+INTERCEPTOR(int, mlockall, int flags) {
+ MlockIsUnsupported();
+ return 0;
+}
+
+INTERCEPTOR(int, munlockall, void) {
+ MlockIsUnsupported();
+ return 0;
+}
+
+#define INIT_MLOCKX \
+ COMMON_INTERCEPT_FUNCTION(mlock); \
+ COMMON_INTERCEPT_FUNCTION(munlock); \
+ COMMON_INTERCEPT_FUNCTION(mlockall); \
+ COMMON_INTERCEPT_FUNCTION(munlockall);
+
+#else
+#define INIT_MLOCKX
+#endif // SANITIZER_INTERCEPT_MLOCKX
+
+#if SANITIZER_INTERCEPT_FOPENCOOKIE
+struct WrappedCookie {
+ void *real_cookie;
+ __sanitizer_cookie_io_functions_t real_io_funcs;
+};
+
+static uptr wrapped_read(void *cookie, char *buf, uptr size) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
+ __sanitizer_cookie_io_read real_read = wrapped_cookie->real_io_funcs.read;
+ return real_read ? real_read(wrapped_cookie->real_cookie, buf, size) : 0;
+}
+
+static uptr wrapped_write(void *cookie, const char *buf, uptr size) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
+ __sanitizer_cookie_io_write real_write = wrapped_cookie->real_io_funcs.write;
+ return real_write ? real_write(wrapped_cookie->real_cookie, buf, size) : size;
+}
+
+static int wrapped_seek(void *cookie, u64 *offset, int whence) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(offset, sizeof(*offset));
+ WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
+ __sanitizer_cookie_io_seek real_seek = wrapped_cookie->real_io_funcs.seek;
+ return real_seek ? real_seek(wrapped_cookie->real_cookie, offset, whence)
+ : -1;
+}
+
+static int wrapped_close(void *cookie) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
+ __sanitizer_cookie_io_close real_close = wrapped_cookie->real_io_funcs.close;
+ int res = real_close ? real_close(wrapped_cookie->real_cookie) : 0;
+ InternalFree(wrapped_cookie);
+ return res;
+}
+
+INTERCEPTOR(__sanitizer_FILE *, fopencookie, void *cookie, const char *mode,
+ __sanitizer_cookie_io_functions_t io_funcs) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fopencookie, cookie, mode, io_funcs);
+ WrappedCookie *wrapped_cookie =
+ (WrappedCookie *)InternalAlloc(sizeof(WrappedCookie));
+ wrapped_cookie->real_cookie = cookie;
+ wrapped_cookie->real_io_funcs = io_funcs;
+ __sanitizer_FILE *res =
+ REAL(fopencookie)(wrapped_cookie, mode, {wrapped_read, wrapped_write,
+ wrapped_seek, wrapped_close});
+ return res;
+}
+
+#define INIT_FOPENCOOKIE COMMON_INTERCEPT_FUNCTION(fopencookie);
+#else
+#define INIT_FOPENCOOKIE
+#endif // SANITIZER_INTERCEPT_FOPENCOOKIE
+
+#if SANITIZER_INTERCEPT_SEM
+INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value);
+ // Workaround a bug in glibc's "old" semaphore implementation by
+ // zero-initializing the sem_t contents. This has to be done here because
+ // interceptors bind to the lowest version before glibc 2.36, hitting the
+ // buggy code path while the non-sanitized build of the same code works fine.
+ REAL(memset)(s, 0, sizeof(*s));
+ int res = REAL(sem_init)(s, pshared, value);
+ return res;
+}
+
+INTERCEPTOR(int, sem_destroy, __sanitizer_sem_t *s) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sem_destroy, s);
+ int res = REAL(sem_destroy)(s);
+ return res;
+}
+
+INTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sem_wait, s);
+ int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_wait)(s);
+ if (res == 0) {
+ COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
+ }
+ return res;
+}
+
+INTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sem_trywait, s);
+ int res = REAL(sem_trywait)(s);
+ if (res == 0) {
+ COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
+ }
+ return res;
+}
+
+INTERCEPTOR(int, sem_timedwait, __sanitizer_sem_t *s, void *abstime) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sem_timedwait, s, abstime);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, abstime, struct_timespec_sz);
+ int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_timedwait)(s, abstime);
+ if (res == 0) {
+ COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
+ }
+ return res;
+}
+
+INTERCEPTOR(int, sem_post, __sanitizer_sem_t *s) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sem_post, s);
+ COMMON_INTERCEPTOR_RELEASE(ctx, (uptr)s);
+ int res = REAL(sem_post)(s);
+ return res;
+}
+
+INTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sem_getvalue, s, sval);
+ int res = REAL(sem_getvalue)(s, sval);
+ if (res == 0) {
+ COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sval, sizeof(*sval));
+ }
+ return res;
+}
+
+INTERCEPTOR(__sanitizer_sem_t *, sem_open, const char *name, int oflag, ...) {
+ void *ctx;
+ va_list ap;
+ va_start(ap, oflag);
+ u32 mode = va_arg(ap, u32);
+ u32 value = va_arg(ap, u32);
+ COMMON_INTERCEPTOR_ENTER(ctx, sem_open, name, oflag, mode, value);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ __sanitizer_sem_t *s = REAL(sem_open)(name, oflag, mode, value);
+ if (s)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, sizeof(*s));
+ va_end(ap);
+ return s;
+}
+
+INTERCEPTOR(int, sem_unlink, const char *name) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sem_unlink, name);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ return REAL(sem_unlink)(name);
+}
+
+# define INIT_SEM \
+ COMMON_INTERCEPT_FUNCTION(sem_init); \
+ COMMON_INTERCEPT_FUNCTION(sem_destroy); \
+ COMMON_INTERCEPT_FUNCTION(sem_wait); \
+ COMMON_INTERCEPT_FUNCTION(sem_trywait); \
+ COMMON_INTERCEPT_FUNCTION(sem_timedwait); \
+ COMMON_INTERCEPT_FUNCTION(sem_post); \
+ COMMON_INTERCEPT_FUNCTION(sem_getvalue); \
+ COMMON_INTERCEPT_FUNCTION(sem_open); \
+ COMMON_INTERCEPT_FUNCTION(sem_unlink);
+#else
+# define INIT_SEM
+#endif // SANITIZER_INTERCEPT_SEM
+
+#if SANITIZER_INTERCEPT_PTHREAD_SETCANCEL
+INTERCEPTOR(int, pthread_setcancelstate, int state, int *oldstate) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcancelstate, state, oldstate);
+ int res = REAL(pthread_setcancelstate)(state, oldstate);
+ if (res == 0 && oldstate != nullptr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldstate, sizeof(*oldstate));
+ return res;
+}
+
+INTERCEPTOR(int, pthread_setcanceltype, int type, int *oldtype) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcanceltype, type, oldtype);
+ int res = REAL(pthread_setcanceltype)(type, oldtype);
+ if (res == 0 && oldtype != nullptr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldtype, sizeof(*oldtype));
+ return res;
+}
+#define INIT_PTHREAD_SETCANCEL \
+ COMMON_INTERCEPT_FUNCTION(pthread_setcancelstate); \
+ COMMON_INTERCEPT_FUNCTION(pthread_setcanceltype);
+#else
+#define INIT_PTHREAD_SETCANCEL
+#endif
+
+#if SANITIZER_INTERCEPT_MINCORE
+INTERCEPTOR(int, mincore, void *addr, uptr length, unsigned char *vec) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, mincore, addr, length, vec);
+ int res = REAL(mincore)(addr, length, vec);
+ if (res == 0) {
+ uptr page_size = GetPageSizeCached();
+ uptr vec_size = ((length + page_size - 1) & (~(page_size - 1))) / page_size;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, vec, vec_size);
+ }
+ return res;
+}
+#define INIT_MINCORE COMMON_INTERCEPT_FUNCTION(mincore);
+#else
+#define INIT_MINCORE
+#endif
+
+#if SANITIZER_INTERCEPT_PROCESS_VM_READV
+INTERCEPTOR(SSIZE_T, process_vm_readv, int pid, __sanitizer_iovec *local_iov,
+ uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
+ uptr flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, process_vm_readv, pid, local_iov, liovcnt,
+ remote_iov, riovcnt, flags);
+ SSIZE_T res = REAL(process_vm_readv)(pid, local_iov, liovcnt, remote_iov,
+ riovcnt, flags);
+ if (res > 0)
+ write_iovec(ctx, local_iov, liovcnt, res);
+ return res;
+}
+
+INTERCEPTOR(SSIZE_T, process_vm_writev, int pid, __sanitizer_iovec *local_iov,
+ uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
+ uptr flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, process_vm_writev, pid, local_iov, liovcnt,
+ remote_iov, riovcnt, flags);
+ SSIZE_T res = REAL(process_vm_writev)(pid, local_iov, liovcnt, remote_iov,
+ riovcnt, flags);
+ if (res > 0)
+ read_iovec(ctx, local_iov, liovcnt, res);
+ return res;
+}
+#define INIT_PROCESS_VM_READV \
+ COMMON_INTERCEPT_FUNCTION(process_vm_readv); \
+ COMMON_INTERCEPT_FUNCTION(process_vm_writev);
+#else
+#define INIT_PROCESS_VM_READV
+#endif
+
+#if SANITIZER_INTERCEPT_CTERMID
+INTERCEPTOR(char *, ctermid, char *s) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s);
+ char *res = REAL(ctermid)(s);
+ if (res) {
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+ }
+ return res;
+}
+#define INIT_CTERMID COMMON_INTERCEPT_FUNCTION(ctermid);
+#else
+#define INIT_CTERMID
+#endif
+
+#if SANITIZER_INTERCEPT_CTERMID_R
+INTERCEPTOR(char *, ctermid_r, char *s) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s);
+ char *res = REAL(ctermid_r)(s);
+ if (res) {
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+ }
+ return res;
+}
+#define INIT_CTERMID_R COMMON_INTERCEPT_FUNCTION(ctermid_r);
+#else
+#define INIT_CTERMID_R
+#endif
+
+#if SANITIZER_INTERCEPT_RECV_RECVFROM
+INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ SSIZE_T res = REAL(recv)(fd, buf, len, flags);
+ if (res > 0) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
+ }
+ if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ return res;
+}
+
+INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
+ void *srcaddr, int *addrlen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, recvfrom, fd, buf, len, flags, srcaddr,
+ addrlen);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ SIZE_T srcaddr_sz;
+ if (srcaddr) srcaddr_sz = *addrlen;
+ (void)srcaddr_sz; // prevent "set but not used" warning
+ SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
+ if (res > 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
+ if (res >= 0 && srcaddr)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr,
+ Min((SIZE_T)*addrlen, srcaddr_sz));
+ return res;
+}
+#define INIT_RECV_RECVFROM \
+ COMMON_INTERCEPT_FUNCTION(recv); \
+ COMMON_INTERCEPT_FUNCTION(recvfrom);
+#else
+#define INIT_RECV_RECVFROM
+#endif
+
+#if SANITIZER_INTERCEPT_SEND_SENDTO
+INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, send, fd, buf, len, flags);
+ if (fd >= 0) {
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ }
+ SSIZE_T res = REAL(send)(fd, buf, len, flags);
+ if (common_flags()->intercept_send && res > 0)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
+ return res;
+}
+
+INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags,
+ void *dstaddr, int addrlen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sendto, fd, buf, len, flags, dstaddr, addrlen);
+ if (fd >= 0) {
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ }
+ // Can't check dstaddr as it may have uninitialized padding at the end.
+ SSIZE_T res = REAL(sendto)(fd, buf, len, flags, dstaddr, addrlen);
+ if (common_flags()->intercept_send && res > 0)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
+ return res;
+}
+#define INIT_SEND_SENDTO \
+ COMMON_INTERCEPT_FUNCTION(send); \
+ COMMON_INTERCEPT_FUNCTION(sendto);
+#else
+#define INIT_SEND_SENDTO
+#endif
+
+#if SANITIZER_INTERCEPT_EVENTFD_READ_WRITE
+INTERCEPTOR(int, eventfd_read, int fd, u64 *value) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, eventfd_read, fd, value);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ int res = REAL(eventfd_read)(fd, value);
+ if (res == 0) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, sizeof(*value));
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ }
+ return res;
+}
+INTERCEPTOR(int, eventfd_write, int fd, u64 value) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, eventfd_write, fd, value);
+ if (fd >= 0) {
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ }
+ int res = REAL(eventfd_write)(fd, value);
+ return res;
+}
+#define INIT_EVENTFD_READ_WRITE \
+ COMMON_INTERCEPT_FUNCTION(eventfd_read); \
+ COMMON_INTERCEPT_FUNCTION(eventfd_write)
+#else
+#define INIT_EVENTFD_READ_WRITE
+#endif
+
+#if SANITIZER_INTERCEPT_STAT
+INTERCEPTOR(int, stat, const char *path, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, stat, path, buf);
+ if (common_flags()->intercept_stat)
+ COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
+ int res = REAL(stat)(path, buf);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
+ return res;
+}
+#define INIT_STAT COMMON_INTERCEPT_FUNCTION(stat)
+#else
+#define INIT_STAT
+#endif
+
+#if SANITIZER_INTERCEPT_STAT64
+INTERCEPTOR(int, stat64, const char *path, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, stat64, path, buf);
+ if (common_flags()->intercept_stat)
+ COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
+ int res = REAL(stat64)(path, buf);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
+ return res;
+}
+#define INIT_STAT64 COMMON_INTERCEPT_FUNCTION(stat64)
+#else
+#define INIT_STAT64
+#endif
+
+
+#if SANITIZER_INTERCEPT_LSTAT
+INTERCEPTOR(int, lstat, const char *path, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, lstat, path, buf);
+ if (common_flags()->intercept_stat)
+ COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
+ int res = REAL(lstat)(path, buf);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
+ return res;
+}
+#define INIT_LSTAT COMMON_INTERCEPT_FUNCTION(lstat)
+#else
+#define INIT_LSTAT
+#endif
+
+#if SANITIZER_INTERCEPT_STAT64
+INTERCEPTOR(int, lstat64, const char *path, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, lstat64, path, buf);
+ if (common_flags()->intercept_stat)
+ COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
+ int res = REAL(lstat64)(path, buf);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
+ return res;
+}
+#define INIT_LSTAT64 COMMON_INTERCEPT_FUNCTION(lstat64)
+#else
+#define INIT_LSTAT64
+#endif
+
+#if SANITIZER_INTERCEPT___XSTAT
+INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __xstat, version, path, buf);
+ if (common_flags()->intercept_stat)
+ COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
+ int res = REAL(__xstat)(version, path, buf);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
+ return res;
+}
+#define INIT___XSTAT COMMON_INTERCEPT_FUNCTION(__xstat)
+#else
+#define INIT___XSTAT
+#endif
+
+#if SANITIZER_INTERCEPT___XSTAT64
+INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __xstat64, version, path, buf);
+ if (common_flags()->intercept_stat)
+ COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
+ int res = REAL(__xstat64)(version, path, buf);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
+ return res;
+}
+#define INIT___XSTAT64 COMMON_INTERCEPT_FUNCTION(__xstat64)
+#else
+#define INIT___XSTAT64
+#endif
+
+#if SANITIZER_INTERCEPT___LXSTAT
+INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __lxstat, version, path, buf);
+ if (common_flags()->intercept_stat)
+ COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
+ int res = REAL(__lxstat)(version, path, buf);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
+ return res;
+}
+#define INIT___LXSTAT COMMON_INTERCEPT_FUNCTION(__lxstat)
+#else
+#define INIT___LXSTAT
+#endif
+
+#if SANITIZER_INTERCEPT___LXSTAT64
+INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __lxstat64, version, path, buf);
+ if (common_flags()->intercept_stat)
+ COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
+ int res = REAL(__lxstat64)(version, path, buf);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
+ return res;
+}
+#define INIT___LXSTAT64 COMMON_INTERCEPT_FUNCTION(__lxstat64)
+#else
+#define INIT___LXSTAT64
+#endif
+
+// FIXME: add other *stat interceptor
+
+#if SANITIZER_INTERCEPT_UTMP
+INTERCEPTOR(void *, getutent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getutent, dummy);
+ void *res = REAL(getutent)(dummy);
+ if (res)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
+ return res;
+}
+INTERCEPTOR(void *, getutid, void *ut) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getutid, ut);
+ void *res = REAL(getutid)(ut);
+ if (res)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
+ return res;
+}
+INTERCEPTOR(void *, getutline, void *ut) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getutline, ut);
+ void *res = REAL(getutline)(ut);
+ if (res)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
+ return res;
+}
+#define INIT_UTMP \
+ COMMON_INTERCEPT_FUNCTION(getutent); \
+ COMMON_INTERCEPT_FUNCTION(getutid); \
+ COMMON_INTERCEPT_FUNCTION(getutline);
+#else
+#define INIT_UTMP
+#endif
+
+#if SANITIZER_INTERCEPT_UTMPX
+INTERCEPTOR(void *, getutxent, int dummy) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getutxent, dummy);
+ void *res = REAL(getutxent)(dummy);
+ if (res)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
+ return res;
+}
+INTERCEPTOR(void *, getutxid, void *ut) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getutxid, ut);
+ void *res = REAL(getutxid)(ut);
+ if (res)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
+ return res;
+}
+INTERCEPTOR(void *, getutxline, void *ut) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getutxline, ut);
+ void *res = REAL(getutxline)(ut);
+ if (res)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
+ return res;
+}
+INTERCEPTOR(void *, pututxline, const void *ut) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pututxline, ut);
+ if (ut)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, ut, __sanitizer::struct_utmpx_sz);
+ void *res = REAL(pututxline)(ut);
+ if (res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_utmpx_sz);
+ return res;
+}
+#define INIT_UTMPX \
+ COMMON_INTERCEPT_FUNCTION(getutxent); \
+ COMMON_INTERCEPT_FUNCTION(getutxid); \
+ COMMON_INTERCEPT_FUNCTION(getutxline); \
+ COMMON_INTERCEPT_FUNCTION(pututxline);
+#else
+#define INIT_UTMPX
+#endif
+
+#if SANITIZER_INTERCEPT_GETLOADAVG
+INTERCEPTOR(int, getloadavg, double *loadavg, int nelem) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getloadavg, loadavg, nelem);
+ int res = REAL(getloadavg)(loadavg, nelem);
+ if (res > 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, loadavg, res * sizeof(*loadavg));
+ return res;
+}
+#define INIT_GETLOADAVG \
+ COMMON_INTERCEPT_FUNCTION(getloadavg);
+#else
+#define INIT_GETLOADAVG
+#endif
+
+#if SANITIZER_INTERCEPT_MCHECK_MPROBE
+INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
+ return 0;
+}
+
+INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
+ return 0;
+}
+
+INTERCEPTOR(int, mprobe, void *ptr) {
+ return 0;
+}
+#endif
+
+INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wcslen, s);
+ SIZE_T res = REAL(wcslen)(s);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (res + 1));
+ return res;
+}
+
+INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wcsnlen, s, n);
+ SIZE_T res = REAL(wcsnlen)(s, n);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * Min(res + 1, n));
+ return res;
+}
+#define INIT_WCSLEN \
+ COMMON_INTERCEPT_FUNCTION(wcslen); \
+ COMMON_INTERCEPT_FUNCTION(wcsnlen);
+
+#if SANITIZER_INTERCEPT_WCSCAT
+INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wcscat, dst, src);
+ SIZE_T src_size = internal_wcslen(src);
+ SIZE_T dst_size = internal_wcslen(dst);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, (src_size + 1) * sizeof(wchar_t));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
+ (src_size + 1) * sizeof(wchar_t));
+ return REAL(wcscat)(dst, src);
+}
+
+INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wcsncat, dst, src, n);
+ SIZE_T src_size = internal_wcsnlen(src, n);
+ SIZE_T dst_size = internal_wcslen(dst);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src,
+ Min(src_size + 1, n) * sizeof(wchar_t));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
+ (src_size + 1) * sizeof(wchar_t));
+ return REAL(wcsncat)(dst, src, n);
+}
+#define INIT_WCSCAT \
+ COMMON_INTERCEPT_FUNCTION(wcscat); \
+ COMMON_INTERCEPT_FUNCTION(wcsncat);
+#else
+#define INIT_WCSCAT
+#endif
+
+#if SANITIZER_INTERCEPT_WCSDUP
+INTERCEPTOR(wchar_t *, wcsdup, wchar_t *s) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wcsdup, s);
+ SIZE_T len = internal_wcslen(s);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (len + 1));
+ wchar_t *result = REAL(wcsdup)(s);
+ if (result)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(wchar_t) * (len + 1));
+ return result;
+}
+
+#define INIT_WCSDUP COMMON_INTERCEPT_FUNCTION(wcsdup);
+#else
+#define INIT_WCSDUP
+#endif
+
+#if SANITIZER_INTERCEPT_STRXFRM
+static SIZE_T RealStrLen(const char *str) { return internal_strlen(str); }
+
+static SIZE_T RealStrLen(const wchar_t *str) { return internal_wcslen(str); }
+
+#define STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len, ...) \
+ { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, strxfrm, dest, src, len, ##__VA_ARGS__); \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, \
+ sizeof(*src) * (RealStrLen(src) + 1)); \
+ SIZE_T res = REAL(strxfrm)(dest, src, len, ##__VA_ARGS__); \
+ if (res < len) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, sizeof(*src) * (res + 1)); \
+ return res; \
+ }
+
+INTERCEPTOR(SIZE_T, strxfrm, char *dest, const char *src, SIZE_T len) {
+ STRXFRM_INTERCEPTOR_IMPL(strxfrm, dest, src, len);
+}
+
+INTERCEPTOR(SIZE_T, strxfrm_l, char *dest, const char *src, SIZE_T len,
+ void *locale) {
+ STRXFRM_INTERCEPTOR_IMPL(strxfrm_l, dest, src, len, locale);
+}
+
+#define INIT_STRXFRM \
+ COMMON_INTERCEPT_FUNCTION(strxfrm); \
+ COMMON_INTERCEPT_FUNCTION(strxfrm_l);
+#else
+#define INIT_STRXFRM
+#endif
+
+#if SANITIZER_INTERCEPT___STRXFRM_L
+INTERCEPTOR(SIZE_T, __strxfrm_l, char *dest, const char *src, SIZE_T len,
+ void *locale) {
+ STRXFRM_INTERCEPTOR_IMPL(__strxfrm_l, dest, src, len, locale);
+}
+
+#define INIT___STRXFRM_L COMMON_INTERCEPT_FUNCTION(__strxfrm_l);
+#else
+#define INIT___STRXFRM_L
+#endif
+
+#if SANITIZER_INTERCEPT_WCSXFRM
+INTERCEPTOR(SIZE_T, wcsxfrm, wchar_t *dest, const wchar_t *src, SIZE_T len) {
+ STRXFRM_INTERCEPTOR_IMPL(wcsxfrm, dest, src, len);
+}
+
+INTERCEPTOR(SIZE_T, wcsxfrm_l, wchar_t *dest, const wchar_t *src, SIZE_T len,
+ void *locale) {
+ STRXFRM_INTERCEPTOR_IMPL(wcsxfrm_l, dest, src, len, locale);
+}
+
+#define INIT_WCSXFRM \
+ COMMON_INTERCEPT_FUNCTION(wcsxfrm); \
+ COMMON_INTERCEPT_FUNCTION(wcsxfrm_l);
+#else
+#define INIT_WCSXFRM
+#endif
+
+#if SANITIZER_INTERCEPT___WCSXFRM_L
+INTERCEPTOR(SIZE_T, __wcsxfrm_l, wchar_t *dest, const wchar_t *src, SIZE_T len,
+ void *locale) {
+ STRXFRM_INTERCEPTOR_IMPL(__wcsxfrm_l, dest, src, len, locale);
+}
+
+#define INIT___WCSXFRM_L COMMON_INTERCEPT_FUNCTION(__wcsxfrm_l);
+#else
+#define INIT___WCSXFRM_L
+#endif
+
+#if SANITIZER_INTERCEPT_ACCT
+INTERCEPTOR(int, acct, const char *file) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, acct, file);
+ if (file)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, file, internal_strlen(file) + 1);
+ return REAL(acct)(file);
+}
+#define INIT_ACCT COMMON_INTERCEPT_FUNCTION(acct)
+#else
+#define INIT_ACCT
+#endif
+
+#if SANITIZER_INTERCEPT_USER_FROM_UID
+INTERCEPTOR(const char *, user_from_uid, u32 uid, int nouser) {
+ void *ctx;
+ const char *user;
+ COMMON_INTERCEPTOR_ENTER(ctx, user_from_uid, uid, nouser);
+ user = REAL(user_from_uid)(uid, nouser);
+ if (user)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, user, internal_strlen(user) + 1);
+ return user;
+}
+#define INIT_USER_FROM_UID COMMON_INTERCEPT_FUNCTION(user_from_uid)
+#else
+#define INIT_USER_FROM_UID
+#endif
+
+#if SANITIZER_INTERCEPT_UID_FROM_USER
+INTERCEPTOR(int, uid_from_user, const char *name, u32 *uid) {
+ void *ctx;
+ int res;
+ COMMON_INTERCEPTOR_ENTER(ctx, uid_from_user, name, uid);
+ if (name)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ res = REAL(uid_from_user)(name, uid);
+ if (uid)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, uid, sizeof(*uid));
+ return res;
+}
+#define INIT_UID_FROM_USER COMMON_INTERCEPT_FUNCTION(uid_from_user)
+#else
+#define INIT_UID_FROM_USER
+#endif
+
+#if SANITIZER_INTERCEPT_GROUP_FROM_GID
+INTERCEPTOR(const char *, group_from_gid, u32 gid, int nogroup) {
+ void *ctx;
+ const char *group;
+ COMMON_INTERCEPTOR_ENTER(ctx, group_from_gid, gid, nogroup);
+ group = REAL(group_from_gid)(gid, nogroup);
+ if (group)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, group, internal_strlen(group) + 1);
+ return group;
+}
+#define INIT_GROUP_FROM_GID COMMON_INTERCEPT_FUNCTION(group_from_gid)
+#else
+#define INIT_GROUP_FROM_GID
+#endif
+
+#if SANITIZER_INTERCEPT_GID_FROM_GROUP
+INTERCEPTOR(int, gid_from_group, const char *group, u32 *gid) {
+ void *ctx;
+ int res;
+ COMMON_INTERCEPTOR_ENTER(ctx, gid_from_group, group, gid);
+ if (group)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, group, internal_strlen(group) + 1);
+ res = REAL(gid_from_group)(group, gid);
+ if (gid)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, gid, sizeof(*gid));
+ return res;
+}
+#define INIT_GID_FROM_GROUP COMMON_INTERCEPT_FUNCTION(gid_from_group)
+#else
+#define INIT_GID_FROM_GROUP
+#endif
+
+#if SANITIZER_INTERCEPT_ACCESS
+INTERCEPTOR(int, access, const char *path, int mode) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, access, path, mode);
+ if (path)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ return REAL(access)(path, mode);
+}
+#define INIT_ACCESS COMMON_INTERCEPT_FUNCTION(access)
+#else
+#define INIT_ACCESS
+#endif
+
+#if SANITIZER_INTERCEPT_FACCESSAT
+INTERCEPTOR(int, faccessat, int fd, const char *path, int mode, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, faccessat, fd, path, mode, flags);
+ if (path)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ return REAL(faccessat)(fd, path, mode, flags);
+}
+#define INIT_FACCESSAT COMMON_INTERCEPT_FUNCTION(faccessat)
+#else
+#define INIT_FACCESSAT
+#endif
+
+#if SANITIZER_INTERCEPT_GETGROUPLIST
+INTERCEPTOR(int, getgrouplist, const char *name, u32 basegid, u32 *groups,
+ int *ngroups) {
+ void *ctx;
+ int res;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgrouplist, name, basegid, groups, ngroups);
+ if (name)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ if (ngroups)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, ngroups, sizeof(*ngroups));
+ res = REAL(getgrouplist)(name, basegid, groups, ngroups);
+ if (!res && groups && ngroups) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ngroups, sizeof(*ngroups));
+ }
+ return res;
+}
+
+#define INIT_GETGROUPLIST COMMON_INTERCEPT_FUNCTION(getgrouplist);
+#else
+#define INIT_GETGROUPLIST
+#endif
+
+#if SANITIZER_INTERCEPT_GETGROUPMEMBERSHIP
+INTERCEPTOR(int, getgroupmembership, const char *name, u32 basegid, u32 *groups,
+ int maxgrp, int *ngroups) {
+ void *ctx;
+ int res;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgroupmembership, name, basegid, groups,
+ maxgrp, ngroups);
+ if (name)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ res = REAL(getgroupmembership)(name, basegid, groups, maxgrp, ngroups);
+ if (!res && groups && ngroups) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, groups, sizeof(*groups) * (*ngroups));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ngroups, sizeof(*ngroups));
+ }
+ return res;
+}
+
+#define INIT_GETGROUPMEMBERSHIP COMMON_INTERCEPT_FUNCTION(getgroupmembership);
+#else
+#define INIT_GETGROUPMEMBERSHIP
+#endif
+
+#if SANITIZER_INTERCEPT_READLINK
+INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
+ void* ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readlink, path, buf, bufsiz);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
+ if (res > 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
+ return res;
+}
+
+#define INIT_READLINK COMMON_INTERCEPT_FUNCTION(readlink)
+#else
+#define INIT_READLINK
+#endif
+
+#if SANITIZER_INTERCEPT_READLINKAT
+INTERCEPTOR(SSIZE_T, readlinkat, int dirfd, const char *path, char *buf,
+ SIZE_T bufsiz) {
+ void* ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readlinkat, dirfd, path, buf, bufsiz);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ SSIZE_T res = REAL(readlinkat)(dirfd, path, buf, bufsiz);
+ if (res > 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
+ return res;
+}
+
+#define INIT_READLINKAT COMMON_INTERCEPT_FUNCTION(readlinkat)
+#else
+#define INIT_READLINKAT
+#endif
+
+#if SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT
+INTERCEPTOR(int, name_to_handle_at, int dirfd, const char *pathname,
+ struct file_handle *handle, int *mount_id, int flags) {
+ void* ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, name_to_handle_at, dirfd, pathname, handle,
+ mount_id, flags);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, pathname, internal_strlen(pathname) + 1);
+
+ __sanitizer_file_handle *sanitizer_handle =
+ reinterpret_cast<__sanitizer_file_handle*>(handle);
+ COMMON_INTERCEPTOR_READ_RANGE(
+ ctx, &sanitizer_handle->handle_bytes,
+ sizeof(sanitizer_handle->handle_bytes));
+
+ int res = REAL(name_to_handle_at)(dirfd, pathname, handle, mount_id, flags);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(
+ ctx, &sanitizer_handle->handle_bytes,
+ sizeof(sanitizer_handle->handle_bytes));
+ COMMON_INTERCEPTOR_WRITE_RANGE(
+ ctx, &sanitizer_handle->handle_type,
+ sizeof(sanitizer_handle->handle_type));
+ COMMON_INTERCEPTOR_WRITE_RANGE(
+ ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mount_id, sizeof(*mount_id));
+ }
+ return res;
+}
+
+#define INIT_NAME_TO_HANDLE_AT COMMON_INTERCEPT_FUNCTION(name_to_handle_at)
+#else
+#define INIT_NAME_TO_HANDLE_AT
+#endif
+
+#if SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT
+INTERCEPTOR(int, open_by_handle_at, int mount_fd, struct file_handle* handle,
+ int flags) {
+ void* ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, open_by_handle_at, mount_fd, handle, flags);
+
+ __sanitizer_file_handle *sanitizer_handle =
+ reinterpret_cast<__sanitizer_file_handle*>(handle);
+ COMMON_INTERCEPTOR_READ_RANGE(
+ ctx, &sanitizer_handle->handle_bytes,
+ sizeof(sanitizer_handle->handle_bytes));
+ COMMON_INTERCEPTOR_READ_RANGE(
+ ctx, &sanitizer_handle->handle_type,
+ sizeof(sanitizer_handle->handle_type));
+ COMMON_INTERCEPTOR_READ_RANGE(
+ ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes);
+
+ return REAL(open_by_handle_at)(mount_fd, handle, flags);
+}
+
+#define INIT_OPEN_BY_HANDLE_AT COMMON_INTERCEPT_FUNCTION(open_by_handle_at)
+#else
+#define INIT_OPEN_BY_HANDLE_AT
+#endif
+
+#if SANITIZER_INTERCEPT_STRLCPY
+INTERCEPTOR(SIZE_T, strlcpy, char *dst, char *src, SIZE_T size) {
+ void *ctx;
+ SIZE_T res;
+ COMMON_INTERCEPTOR_ENTER(ctx, strlcpy, dst, src, size);
+ if (src) {
+ // Keep strnlen as macro argument, as macro may ignore it.
+ COMMON_INTERCEPTOR_READ_STRING(
+ ctx, src, Min(internal_strnlen(src, size), size - 1) + 1);
+ }
+ res = REAL(strlcpy)(dst, src, size);
+ COMMON_INTERCEPTOR_COPY_STRING(ctx, dst, src, internal_strlen(dst) + 1);
+ return res;
+}
+
+INTERCEPTOR(SIZE_T, strlcat, char *dst, char *src, SIZE_T size) {
+ void *ctx;
+ SIZE_T len = 0;
+ COMMON_INTERCEPTOR_ENTER(ctx, strlcat, dst, src, size);
+ // src is checked in the strlcpy() interceptor
+ if (dst) {
+ len = internal_strnlen(dst, size);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, dst, Min(len, size - 1) + 1);
+ }
+ // Reuse the rest of the code in the strlcpy() interceptor
+ return WRAP(strlcpy)(dst + len, src, size - len) + len;
+}
+#define INIT_STRLCPY \
+ COMMON_INTERCEPT_FUNCTION(strlcpy); \
+ COMMON_INTERCEPT_FUNCTION(strlcat);
+#else
+#define INIT_STRLCPY
+#endif
+
+#if SANITIZER_INTERCEPT_MMAP
+INTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags, int fd,
+ OFF_T off) {
+ void *ctx;
+ if (common_flags()->detect_write_exec)
+ ReportMmapWriteExec(prot, flags);
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
+ COMMON_INTERCEPTOR_ENTER(ctx, mmap, addr, sz, prot, flags, fd, off);
+ COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, off);
+}
+
+INTERCEPTOR(int, mprotect, void *addr, SIZE_T sz, int prot) {
+ void *ctx;
+ if (common_flags()->detect_write_exec)
+ ReportMmapWriteExec(prot, 0);
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return (int)internal_mprotect(addr, sz, prot);
+ COMMON_INTERCEPTOR_ENTER(ctx, mprotect, addr, sz, prot);
+ MprotectMallocZones(addr, prot);
+ return REAL(mprotect)(addr, sz, prot);
+}
+#define INIT_MMAP \
+ COMMON_INTERCEPT_FUNCTION(mmap); \
+ COMMON_INTERCEPT_FUNCTION(mprotect);
+#else
+#define INIT_MMAP
+#endif
+
+#if SANITIZER_INTERCEPT_MMAP64
+INTERCEPTOR(void *, mmap64, void *addr, SIZE_T sz, int prot, int flags, int fd,
+ OFF64_T off) {
+ void *ctx;
+ if (common_flags()->detect_write_exec)
+ ReportMmapWriteExec(prot, flags);
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
+ COMMON_INTERCEPTOR_ENTER(ctx, mmap64, addr, sz, prot, flags, fd, off);
+ COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap64, addr, sz, prot, flags, fd, off);
+}
+#define INIT_MMAP64 COMMON_INTERCEPT_FUNCTION(mmap64);
+#else
+#define INIT_MMAP64
+#endif
+
+#if SANITIZER_INTERCEPT_DEVNAME
+INTERCEPTOR(char *, devname, u64 dev, u32 type) {
+ void *ctx;
+ char *name;
+ COMMON_INTERCEPTOR_ENTER(ctx, devname, dev, type);
+ name = REAL(devname)(dev, type);
+ if (name)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
+ return name;
+}
+#define INIT_DEVNAME COMMON_INTERCEPT_FUNCTION(devname);
+#else
+#define INIT_DEVNAME
+#endif
+
+#if SANITIZER_INTERCEPT_DEVNAME_R
+#if SANITIZER_NETBSD
+#define DEVNAME_R_RETTYPE int
+#define DEVNAME_R_SUCCESS(x) (!(x))
+#else
+#define DEVNAME_R_RETTYPE char*
+#define DEVNAME_R_SUCCESS(x) (x)
+#endif
+INTERCEPTOR(DEVNAME_R_RETTYPE, devname_r, u64 dev, u32 type, char *path,
+ uptr len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, devname_r, dev, type, path, len);
+ DEVNAME_R_RETTYPE res = REAL(devname_r)(dev, type, path, len);
+ if (DEVNAME_R_SUCCESS(res))
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, path, internal_strlen(path) + 1);
+ return res;
+}
+#define INIT_DEVNAME_R COMMON_INTERCEPT_FUNCTION(devname_r);
+#else
+#define INIT_DEVNAME_R
+#endif
+
+#if SANITIZER_INTERCEPT_FGETLN
+INTERCEPTOR(char *, fgetln, __sanitizer_FILE *stream, SIZE_T *len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fgetln, stream, len);
+ char *str = REAL(fgetln)(stream, len);
+ if (str && len) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, *len);
+ }
+ return str;
+}
+#define INIT_FGETLN COMMON_INTERCEPT_FUNCTION(fgetln)
+#else
+#define INIT_FGETLN
+#endif
+
+#if SANITIZER_INTERCEPT_STRMODE
+INTERCEPTOR(void, strmode, u32 mode, char *bp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strmode, mode, bp);
+ REAL(strmode)(mode, bp);
+ if (bp)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, bp, internal_strlen(bp) + 1);
+}
+#define INIT_STRMODE COMMON_INTERCEPT_FUNCTION(strmode)
+#else
+#define INIT_STRMODE
+#endif
+
+#if SANITIZER_INTERCEPT_TTYENT
+INTERCEPTOR(struct __sanitizer_ttyent *, getttyent, void) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getttyent);
+ struct __sanitizer_ttyent *ttyent = REAL(getttyent)();
+ if (ttyent)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz);
+ return ttyent;
+}
+INTERCEPTOR(struct __sanitizer_ttyent *, getttynam, char *name) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getttynam, name);
+ if (name)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ struct __sanitizer_ttyent *ttyent = REAL(getttynam)(name);
+ if (ttyent)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ttyent, struct_ttyent_sz);
+ return ttyent;
+}
+#define INIT_TTYENT \
+ COMMON_INTERCEPT_FUNCTION(getttyent); \
+ COMMON_INTERCEPT_FUNCTION(getttynam);
+#else
+#define INIT_TTYENT
+#endif
+
+#if SANITIZER_INTERCEPT_TTYENTPATH
+INTERCEPTOR(int, setttyentpath, char *path) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, setttyentpath, path);
+ if (path)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ return REAL(setttyentpath)(path);
+}
+#define INIT_TTYENTPATH COMMON_INTERCEPT_FUNCTION(setttyentpath);
+#else
+#define INIT_TTYENTPATH
+#endif
+
+#if SANITIZER_INTERCEPT_PROTOENT
+static void write_protoent(void *ctx, struct __sanitizer_protoent *p) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
+
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_name, internal_strlen(p->p_name) + 1);
+
+ SIZE_T pp_size = 1; // One handles the trailing \0
+
+ for (char **pp = p->p_aliases; *pp; ++pp, ++pp_size)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *pp, internal_strlen(*pp) + 1);
+
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases,
+ pp_size * sizeof(char **));
+}
+
+INTERCEPTOR(struct __sanitizer_protoent *, getprotoent) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getprotoent);
+ struct __sanitizer_protoent *p = REAL(getprotoent)();
+ if (p)
+ write_protoent(ctx, p);
+ return p;
+}
+
+INTERCEPTOR(struct __sanitizer_protoent *, getprotobyname, const char *name) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname, name);
+ if (name)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ struct __sanitizer_protoent *p = REAL(getprotobyname)(name);
+ if (p)
+ write_protoent(ctx, p);
+ return p;
+}
+
+INTERCEPTOR(struct __sanitizer_protoent *, getprotobynumber, int proto) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getprotobynumber, proto);
+ struct __sanitizer_protoent *p = REAL(getprotobynumber)(proto);
+ if (p)
+ write_protoent(ctx, p);
+ return p;
+}
+#define INIT_PROTOENT \
+ COMMON_INTERCEPT_FUNCTION(getprotoent); \
+ COMMON_INTERCEPT_FUNCTION(getprotobyname); \
+ COMMON_INTERCEPT_FUNCTION(getprotobynumber)
+#else
+#define INIT_PROTOENT
+#endif
+
+#if SANITIZER_INTERCEPT_PROTOENT_R
+INTERCEPTOR(int, getprotoent_r, struct __sanitizer_protoent *result_buf,
+ char *buf, SIZE_T buflen, struct __sanitizer_protoent **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getprotoent_r, result_buf, buf, buflen,
+ result);
+ int res = REAL(getprotoent_r)(result_buf, buf, buflen, result);
+
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
+ if (!res && *result)
+ write_protoent(ctx, *result);
+ return res;
+}
+
+INTERCEPTOR(int, getprotobyname_r, const char *name,
+ struct __sanitizer_protoent *result_buf, char *buf, SIZE_T buflen,
+ struct __sanitizer_protoent **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getprotobyname_r, name, result_buf, buf,
+ buflen, result);
+ if (name)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ int res = REAL(getprotobyname_r)(name, result_buf, buf, buflen, result);
+
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
+ if (!res && *result)
+ write_protoent(ctx, *result);
+ return res;
+}
+
+INTERCEPTOR(int, getprotobynumber_r, int num,
+ struct __sanitizer_protoent *result_buf, char *buf,
+ SIZE_T buflen, struct __sanitizer_protoent **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getprotobynumber_r, num, result_buf, buf,
+ buflen, result);
+ int res = REAL(getprotobynumber_r)(num, result_buf, buf, buflen, result);
+
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof *result);
+ if (!res && *result)
+ write_protoent(ctx, *result);
+ return res;
+}
+
+#define INIT_PROTOENT_R \
+ COMMON_INTERCEPT_FUNCTION(getprotoent_r); \
+ COMMON_INTERCEPT_FUNCTION(getprotobyname_r); \
+ COMMON_INTERCEPT_FUNCTION(getprotobynumber_r);
+#else
+#define INIT_PROTOENT_R
+#endif
+
+#if SANITIZER_INTERCEPT_NETENT
+INTERCEPTOR(struct __sanitizer_netent *, getnetent) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getnetent);
+ struct __sanitizer_netent *n = REAL(getnetent)();
+ if (n) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
+
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
+
+ SIZE_T nn_size = 1; // One handles the trailing \0
+
+ for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
+
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
+ nn_size * sizeof(char **));
+ }
+ return n;
+}
+
+INTERCEPTOR(struct __sanitizer_netent *, getnetbyname, const char *name) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getnetbyname, name);
+ if (name)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ struct __sanitizer_netent *n = REAL(getnetbyname)(name);
+ if (n) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
+
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
+
+ SIZE_T nn_size = 1; // One handles the trailing \0
+
+ for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
+
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
+ nn_size * sizeof(char **));
+ }
+ return n;
+}
+
+INTERCEPTOR(struct __sanitizer_netent *, getnetbyaddr, u32 net, int type) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getnetbyaddr, net, type);
+ struct __sanitizer_netent *n = REAL(getnetbyaddr)(net, type);
+ if (n) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
+
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, internal_strlen(n->n_name) + 1);
+
+ SIZE_T nn_size = 1; // One handles the trailing \0
+
+ for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, internal_strlen(*nn) + 1);
+
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases,
+ nn_size * sizeof(char **));
+ }
+ return n;
+}
+#define INIT_NETENT \
+ COMMON_INTERCEPT_FUNCTION(getnetent); \
+ COMMON_INTERCEPT_FUNCTION(getnetbyname); \
+ COMMON_INTERCEPT_FUNCTION(getnetbyaddr)
+#else
+#define INIT_NETENT
+#endif
+
+#if SANITIZER_INTERCEPT_GETMNTINFO
+INTERCEPTOR(int, getmntinfo, void **mntbufp, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getmntinfo, mntbufp, flags);
+ int cnt = REAL(getmntinfo)(mntbufp, flags);
+ if (cnt > 0 && mntbufp) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mntbufp, sizeof(void *));
+ if (*mntbufp)
+#if SANITIZER_NETBSD
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statvfs_sz);
+#else
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statfs_sz);
+#endif
+ }
+ return cnt;
+}
+#define INIT_GETMNTINFO COMMON_INTERCEPT_FUNCTION(getmntinfo)
+#else
+#define INIT_GETMNTINFO
+#endif
+
+#if SANITIZER_INTERCEPT_MI_VECTOR_HASH
+INTERCEPTOR(void, mi_vector_hash, const void *key, SIZE_T len, u32 seed,
+ u32 hashes[3]) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, mi_vector_hash, key, len, seed, hashes);
+ if (key)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, key, len);
+ REAL(mi_vector_hash)(key, len, seed, hashes);
+ if (hashes)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hashes, sizeof(hashes[0]) * 3);
+}
+#define INIT_MI_VECTOR_HASH COMMON_INTERCEPT_FUNCTION(mi_vector_hash)
+#else
+#define INIT_MI_VECTOR_HASH
+#endif
+
+#if SANITIZER_INTERCEPT_SETVBUF
+INTERCEPTOR(int, setvbuf, __sanitizer_FILE *stream, char *buf, int mode,
+ SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, setvbuf, stream, buf, mode, size);
+ int ret = REAL(setvbuf)(stream, buf, mode, size);
+ if (buf)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, size);
+ if (stream)
+ unpoison_file(stream);
+ return ret;
+}
+
+INTERCEPTOR(void, setbuf, __sanitizer_FILE *stream, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, setbuf, stream, buf);
+ REAL(setbuf)(stream, buf);
+ if (buf) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer_bufsiz);
+ }
+ if (stream)
+ unpoison_file(stream);
+}
+
+INTERCEPTOR(void, setbuffer, __sanitizer_FILE *stream, char *buf, SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, setbuffer, stream, buf, size);
+ REAL(setbuffer)(stream, buf, size);
+ if (buf) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, size);
+ }
+ if (stream)
+ unpoison_file(stream);
+}
+
+INTERCEPTOR(void, setlinebuf, __sanitizer_FILE *stream) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, setlinebuf, stream);
+ REAL(setlinebuf)(stream);
+ if (stream)
+ unpoison_file(stream);
+}
+#define INIT_SETVBUF COMMON_INTERCEPT_FUNCTION(setvbuf); \
+ COMMON_INTERCEPT_FUNCTION(setbuf); \
+ COMMON_INTERCEPT_FUNCTION(setbuffer); \
+ COMMON_INTERCEPT_FUNCTION(setlinebuf)
+#else
+#define INIT_SETVBUF
+#endif
+
+#if SANITIZER_INTERCEPT_GETVFSSTAT
+INTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getvfsstat, buf, bufsize, flags);
+ int ret = REAL(getvfsstat)(buf, bufsize, flags);
+ if (buf && ret > 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, ret * struct_statvfs_sz);
+ return ret;
+}
+#define INIT_GETVFSSTAT COMMON_INTERCEPT_FUNCTION(getvfsstat)
+#else
+#define INIT_GETVFSSTAT
+#endif
+
+#if SANITIZER_INTERCEPT_REGEX
+INTERCEPTOR(int, regcomp, void *preg, const char *pattern, int cflags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, regcomp, preg, pattern, cflags);
+ if (pattern)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, pattern, internal_strlen(pattern) + 1);
+ int res = REAL(regcomp)(preg, pattern, cflags);
+ if (preg)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, preg, struct_regex_sz);
+ return res;
+}
+INTERCEPTOR(int, regexec, const void *preg, const char *string, SIZE_T nmatch,
+ struct __sanitizer_regmatch *pmatch[], int eflags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, regexec, preg, string, nmatch, pmatch, eflags);
+ if (preg)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
+ if (string)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, string, internal_strlen(string) + 1);
+ int res = REAL(regexec)(preg, string, nmatch, pmatch, eflags);
+ if (!res && pmatch)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pmatch, nmatch * struct_regmatch_sz);
+ return res;
+}
+INTERCEPTOR(SIZE_T, regerror, int errcode, const void *preg, char *errbuf,
+ SIZE_T errbuf_size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, regerror, errcode, preg, errbuf, errbuf_size);
+ if (preg)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
+ SIZE_T res = REAL(regerror)(errcode, preg, errbuf, errbuf_size);
+ if (errbuf)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errbuf, internal_strlen(errbuf) + 1);
+ return res;
+}
+INTERCEPTOR(void, regfree, const void *preg) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, regfree, preg);
+ if (preg)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, preg, struct_regex_sz);
+ REAL(regfree)(preg);
+}
+#define INIT_REGEX \
+ COMMON_INTERCEPT_FUNCTION(regcomp); \
+ COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(regexec, "GLIBC_2.3.4"); \
+ COMMON_INTERCEPT_FUNCTION(regerror); \
+ COMMON_INTERCEPT_FUNCTION(regfree);
+#else
+#define INIT_REGEX
+#endif
+
+#if SANITIZER_INTERCEPT_REGEXSUB
+INTERCEPTOR(SSIZE_T, regnsub, char *buf, SIZE_T bufsiz, const char *sub,
+ const struct __sanitizer_regmatch *rm, const char *str) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, regnsub, buf, bufsiz, sub, rm, str);
+ if (sub)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, internal_strlen(sub) + 1);
+ // The implementation demands and hardcodes 10 elements
+ if (rm)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
+ if (str)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, str, internal_strlen(str) + 1);
+ SSIZE_T res = REAL(regnsub)(buf, bufsiz, sub, rm, str);
+ if (res > 0 && buf)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
+ return res;
+}
+INTERCEPTOR(SSIZE_T, regasub, char **buf, const char *sub,
+ const struct __sanitizer_regmatch *rm, const char *sstr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, regasub, buf, sub, rm, sstr);
+ if (sub)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sub, internal_strlen(sub) + 1);
+ // Hardcode 10 elements as this is hardcoded size
+ if (rm)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, rm, 10 * struct_regmatch_sz);
+ if (sstr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sstr, internal_strlen(sstr) + 1);
+ SSIZE_T res = REAL(regasub)(buf, sub, rm, sstr);
+ if (res > 0 && buf) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sizeof(char *));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *buf, internal_strlen(*buf) + 1);
+ }
+ return res;
+}
+
+#define INIT_REGEXSUB \
+ COMMON_INTERCEPT_FUNCTION(regnsub); \
+ COMMON_INTERCEPT_FUNCTION(regasub);
+#else
+#define INIT_REGEXSUB
+#endif
+
+#if SANITIZER_INTERCEPT_FTS
+INTERCEPTOR(void *, fts_open, char *const *path_argv, int options,
+ int (*compar)(void **, void **)) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fts_open, path_argv, options, compar);
+ if (path_argv) {
+ for (char *const *pa = path_argv; ; ++pa) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
+ if (!*pa)
+ break;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
+ }
+ }
+ // TODO(kamil): handle compar callback
+ void *fts = REAL(fts_open)(path_argv, options, compar);
+ if (fts)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, fts, struct_FTS_sz);
+ return fts;
+}
+
+INTERCEPTOR(void *, fts_read, void *ftsp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fts_read, ftsp);
+ if (ftsp)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
+ void *ftsent = REAL(fts_read)(ftsp);
+ if (ftsent)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz);
+ return ftsent;
+}
+
+INTERCEPTOR(void *, fts_children, void *ftsp, int options) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fts_children, ftsp, options);
+ if (ftsp)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
+ void *ftsent = REAL(fts_children)(ftsp, options);
+ if (ftsent)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ftsent, struct_FTSENT_sz);
+ return ftsent;
+}
+
+INTERCEPTOR(int, fts_set, void *ftsp, void *f, int options) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fts_set, ftsp, f, options);
+ if (ftsp)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
+ if (f)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, f, struct_FTSENT_sz);
+ return REAL(fts_set)(ftsp, f, options);
+}
+
+INTERCEPTOR(int, fts_close, void *ftsp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fts_close, ftsp);
+ if (ftsp)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, ftsp, struct_FTS_sz);
+ return REAL(fts_close)(ftsp);
+}
+#define INIT_FTS \
+ COMMON_INTERCEPT_FUNCTION(fts_open); \
+ COMMON_INTERCEPT_FUNCTION(fts_read); \
+ COMMON_INTERCEPT_FUNCTION(fts_children); \
+ COMMON_INTERCEPT_FUNCTION(fts_set); \
+ COMMON_INTERCEPT_FUNCTION(fts_close);
+#else
+#define INIT_FTS
+#endif
+
+#if SANITIZER_INTERCEPT_SYSCTL
+INTERCEPTOR(int, sysctl, int *name, unsigned int namelen, void *oldp,
+ SIZE_T *oldlenp, void *newp, SIZE_T newlen) {
+ void *ctx;
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return internal_sysctl(name, namelen, oldp, oldlenp, newp, newlen);
+ COMMON_INTERCEPTOR_ENTER(ctx, sysctl, name, namelen, oldp, oldlenp, newp,
+ newlen);
+ if (name)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, namelen * sizeof(*name));
+ if (oldlenp)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
+ if (newp && newlen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
+ int res = REAL(sysctl)(name, namelen, oldp, oldlenp, newp, newlen);
+ if (!res) {
+ if (oldlenp) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
+ if (oldp)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
+ }
+ }
+ return res;
+}
+
+INTERCEPTOR(int, sysctlbyname, char *sname, void *oldp, SIZE_T *oldlenp,
+ void *newp, SIZE_T newlen) {
+ void *ctx;
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return internal_sysctlbyname(sname, oldp, oldlenp, newp, newlen);
+ COMMON_INTERCEPTOR_ENTER(ctx, sysctlbyname, sname, oldp, oldlenp, newp,
+ newlen);
+ if (sname)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
+ if (oldlenp)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, oldlenp, sizeof(*oldlenp));
+ if (newp && newlen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, newp, newlen);
+ int res = REAL(sysctlbyname)(sname, oldp, oldlenp, newp, newlen);
+ if (!res) {
+ if (oldlenp) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldlenp, sizeof(*oldlenp));
+ if (oldp)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldp, *oldlenp);
+ }
+ }
+ return res;
+}
+
+INTERCEPTOR(int, sysctlnametomib, const char *sname, int *name,
+ SIZE_T *namelenp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sysctlnametomib, sname, name, namelenp);
+ if (sname)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
+ if (namelenp)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
+ int res = REAL(sysctlnametomib)(sname, name, namelenp);
+ if (!res) {
+ if (namelenp) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
+ if (name)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
+ }
+ }
+ return res;
+}
+
+#define INIT_SYSCTL \
+ COMMON_INTERCEPT_FUNCTION(sysctl); \
+ COMMON_INTERCEPT_FUNCTION(sysctlbyname); \
+ COMMON_INTERCEPT_FUNCTION(sysctlnametomib);
+#else
+#define INIT_SYSCTL
+#endif
+
+#if SANITIZER_INTERCEPT_ASYSCTL
+INTERCEPTOR(void *, asysctl, const int *name, SIZE_T namelen, SIZE_T *len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, asysctl, name, namelen, len);
+ if (name)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, sizeof(*name) * namelen);
+ void *res = REAL(asysctl)(name, namelen, len);
+ if (res && len) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
+ }
+ return res;
+}
+
+INTERCEPTOR(void *, asysctlbyname, const char *sname, SIZE_T *len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, asysctlbyname, sname, len);
+ if (sname)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
+ void *res = REAL(asysctlbyname)(sname, len);
+ if (res && len) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, *len);
+ }
+ return res;
+}
+#define INIT_ASYSCTL \
+ COMMON_INTERCEPT_FUNCTION(asysctl); \
+ COMMON_INTERCEPT_FUNCTION(asysctlbyname);
+#else
+#define INIT_ASYSCTL
+#endif
+
+#if SANITIZER_INTERCEPT_SYSCTLGETMIBINFO
+INTERCEPTOR(int, sysctlgetmibinfo, char *sname, int *name,
+ unsigned int *namelenp, char *cname, SIZE_T *csz, void **rnode,
+ int v) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sysctlgetmibinfo, sname, name, namelenp, cname,
+ csz, rnode, v);
+ if (sname)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, internal_strlen(sname) + 1);
+ if (namelenp)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
+ if (csz)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, csz, sizeof(*csz));
+ // Skip rnode, it's rarely used and not trivial to sanitize
+ // It's also used mostly internally
+ int res = REAL(sysctlgetmibinfo)(sname, name, namelenp, cname, csz, rnode, v);
+ if (!res) {
+ if (namelenp) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
+ if (name)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
+ }
+ if (csz) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, csz, sizeof(*csz));
+ if (cname)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cname, *csz);
+ }
+ }
+ return res;
+}
+#define INIT_SYSCTLGETMIBINFO \
+ COMMON_INTERCEPT_FUNCTION(sysctlgetmibinfo);
+#else
+#define INIT_SYSCTLGETMIBINFO
+#endif
+
+#if SANITIZER_INTERCEPT_NL_LANGINFO
+INTERCEPTOR(char *, nl_langinfo, long item) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, nl_langinfo, item);
+ char *ret = REAL(nl_langinfo)(item);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, internal_strlen(ret) + 1);
+ return ret;
+}
+#define INIT_NL_LANGINFO COMMON_INTERCEPT_FUNCTION(nl_langinfo)
+#else
+#define INIT_NL_LANGINFO
+#endif
+
+#if SANITIZER_INTERCEPT_MODCTL
+INTERCEPTOR(int, modctl, int operation, void *argp) {
+ void *ctx;
+ int ret;
+ COMMON_INTERCEPTOR_ENTER(ctx, modctl, operation, argp);
+
+ if (operation == modctl_load) {
+ if (argp) {
+ __sanitizer_modctl_load_t *ml = (__sanitizer_modctl_load_t *)argp;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, ml, sizeof(*ml));
+ if (ml->ml_filename)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_filename,
+ internal_strlen(ml->ml_filename) + 1);
+ if (ml->ml_props)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, ml->ml_props, ml->ml_propslen);
+ }
+ ret = REAL(modctl)(operation, argp);
+ } else if (operation == modctl_unload) {
+ if (argp) {
+ const char *name = (const char *)argp;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
+ }
+ ret = REAL(modctl)(operation, argp);
+ } else if (operation == modctl_stat) {
+ uptr iov_len;
+ struct __sanitizer_iovec *iov = (struct __sanitizer_iovec *)argp;
+ if (iov) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, iov, sizeof(*iov));
+ iov_len = iov->iov_len;
+ }
+ ret = REAL(modctl)(operation, argp);
+ if (iov)
+ COMMON_INTERCEPTOR_WRITE_RANGE(
+ ctx, iov->iov_base, Min(iov_len, iov->iov_len));
+ } else if (operation == modctl_exists) {
+ ret = REAL(modctl)(operation, argp);
+ } else {
+ ret = REAL(modctl)(operation, argp);
+ }
+
+ return ret;
+}
+#define INIT_MODCTL COMMON_INTERCEPT_FUNCTION(modctl)
+#else
+#define INIT_MODCTL
+#endif
+
+#if SANITIZER_INTERCEPT_STRTONUM
+INTERCEPTOR(long long, strtonum, const char *nptr, long long minval,
+ long long maxval, const char **errstr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strtonum, nptr, minval, maxval, errstr);
+
+ // TODO(kamil): Implement strtoll as a common inteceptor
+ char *real_endptr;
+ long long ret = (long long)REAL(strtoimax)(nptr, &real_endptr, 10);
+ StrtolFixAndCheck(ctx, nptr, nullptr, real_endptr, 10);
+
+ ret = REAL(strtonum)(nptr, minval, maxval, errstr);
+ if (errstr) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, errstr, sizeof(const char *));
+ if (*errstr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *errstr, internal_strlen(*errstr) + 1);
+ }
+ return ret;
+}
+#define INIT_STRTONUM COMMON_INTERCEPT_FUNCTION(strtonum)
+#else
+#define INIT_STRTONUM
+#endif
+
+#if SANITIZER_INTERCEPT_FPARSELN
+INTERCEPTOR(char *, fparseln, __sanitizer_FILE *stream, SIZE_T *len,
+ SIZE_T *lineno, const char delim[3], int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fparseln, stream, len, lineno, delim, flags);
+ if (lineno)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, lineno, sizeof(*lineno));
+ if (delim)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, delim, sizeof(delim[0]) * 3);
+ char *ret = REAL(fparseln)(stream, len, lineno, delim, flags);
+ if (ret) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, internal_strlen(ret) + 1);
+ if (len)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, len, sizeof(*len));
+ if (lineno)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineno, sizeof(*lineno));
+ }
+ return ret;
+}
+#define INIT_FPARSELN COMMON_INTERCEPT_FUNCTION(fparseln)
+#else
+#define INIT_FPARSELN
+#endif
+
+#if SANITIZER_INTERCEPT_STATVFS1
+INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ int res = REAL(statvfs1)(path, buf, flags);
+ if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
+ return res;
+}
+INTERCEPTOR(int, fstatvfs1, int fd, void *buf, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs1, fd, buf, flags);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ int res = REAL(fstatvfs1)(fd, buf, flags);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
+ if (fd >= 0)
+ COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ }
+ return res;
+}
+#define INIT_STATVFS1 \
+ COMMON_INTERCEPT_FUNCTION(statvfs1); \
+ COMMON_INTERCEPT_FUNCTION(fstatvfs1);
+#else
+#define INIT_STATVFS1
+#endif
+
+#if SANITIZER_INTERCEPT_STRTOI
+INTERCEPTOR(INTMAX_T, strtoi, const char *nptr, char **endptr, int base,
+ INTMAX_T low, INTMAX_T high, int *rstatus) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strtoi, nptr, endptr, base, low, high, rstatus);
+ char *real_endptr;
+ INTMAX_T ret = REAL(strtoi)(nptr, &real_endptr, base, low, high, rstatus);
+ StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
+ if (rstatus)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus));
+ return ret;
+}
+
+INTERCEPTOR(UINTMAX_T, strtou, const char *nptr, char **endptr, int base,
+ UINTMAX_T low, UINTMAX_T high, int *rstatus) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strtou, nptr, endptr, base, low, high, rstatus);
+ char *real_endptr;
+ UINTMAX_T ret = REAL(strtou)(nptr, &real_endptr, base, low, high, rstatus);
+ StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
+ if (rstatus)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rstatus, sizeof(*rstatus));
+ return ret;
+}
+#define INIT_STRTOI \
+ COMMON_INTERCEPT_FUNCTION(strtoi); \
+ COMMON_INTERCEPT_FUNCTION(strtou)
+#else
+#define INIT_STRTOI
+#endif
+
+#if SANITIZER_INTERCEPT_CAPSICUM
+#define CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights, ...) \
+ { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_init, rights, ##__VA_ARGS__); \
+ if (rights) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \
+ __sanitizer_cap_rights_t *ret = \
+ REAL(cap_rights_init)(rights, ##__VA_ARGS__); \
+ if (ret) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret)); \
+ return ret; \
+ }
+
+#define CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights, ...) \
+ { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_set, rights, ##__VA_ARGS__); \
+ if (rights) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \
+ __sanitizer_cap_rights_t *ret = \
+ REAL(cap_rights_set)(rights, ##__VA_ARGS__); \
+ if (ret) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret)); \
+ return ret; \
+ }
+
+#define CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights, ...) \
+ { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_clear, rights, ##__VA_ARGS__); \
+ if (rights) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \
+ __sanitizer_cap_rights_t *ret = \
+ REAL(cap_rights_clear)(rights, ##__VA_ARGS__); \
+ if (ret) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret)); \
+ return ret; \
+ }
+
+#define CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights, ...) \
+ { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_set, rights, ##__VA_ARGS__); \
+ if (rights) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights)); \
+ return REAL(cap_rights_is_set)(rights, ##__VA_ARGS__); \
+ }
+
+INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_init,
+ __sanitizer_cap_rights_t *rights) {
+ CAP_RIGHTS_INIT_INTERCEPTOR(cap_rights_init, rights);
+}
+
+INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_set,
+ __sanitizer_cap_rights_t *rights) {
+ CAP_RIGHTS_SET_INTERCEPTOR(cap_rights_set, rights);
+}
+
+INTERCEPTOR(__sanitizer_cap_rights_t *, cap_rights_clear,
+ __sanitizer_cap_rights_t *rights) {
+ CAP_RIGHTS_CLEAR_INTERCEPTOR(cap_rights_clear, rights);
+}
+
+INTERCEPTOR(bool, cap_rights_is_set,
+ __sanitizer_cap_rights_t *rights) {
+ CAP_RIGHTS_IS_SET_INTERCEPTOR(cap_rights_is_set, rights);
+}
+
+INTERCEPTOR(int, cap_rights_limit, int fd,
+ const __sanitizer_cap_rights_t *rights) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_limit, fd, rights);
+ if (rights)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));
+
+ return REAL(cap_rights_limit)(fd, rights);
+}
+
+INTERCEPTOR(int, cap_rights_get, int fd, __sanitizer_cap_rights_t *rights) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_get, fd, rights);
+ int ret = REAL(cap_rights_get)(fd, rights);
+ if (!ret && rights)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rights, sizeof(*rights));
+
+ return ret;
+}
+
+INTERCEPTOR(bool, cap_rights_is_valid, const __sanitizer_cap_rights_t *rights) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_is_valid, rights);
+ if (rights)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, rights, sizeof(*rights));
+
+ return REAL(cap_rights_is_valid(rights));
+}
+
+INTERCEPTOR(__sanitizer_cap_rights *, cap_rights_merge,
+ __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_merge, dst, src);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
+
+ __sanitizer_cap_rights *ret = REAL(cap_rights_merge)(dst, src);
+ if (dst)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
+
+ return ret;
+}
+
+INTERCEPTOR(__sanitizer_cap_rights *, cap_rights_remove,
+ __sanitizer_cap_rights *dst, const __sanitizer_cap_rights *src) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_remove, dst, src);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
+
+ __sanitizer_cap_rights *ret = REAL(cap_rights_remove)(dst, src);
+ if (dst)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst));
+
+ return ret;
+}
+
+INTERCEPTOR(bool, cap_rights_contains, const __sanitizer_cap_rights *big,
+ const __sanitizer_cap_rights *little) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cap_rights_contains, big, little);
+ if (little)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, little, sizeof(*little));
+ if (big)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, big, sizeof(*big));
+
+ return REAL(cap_rights_contains)(big, little);
+}
+
+INTERCEPTOR(int, cap_ioctls_limit, int fd, const uptr *cmds, SIZE_T ncmds) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_limit, fd, cmds, ncmds);
+ if (cmds)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cmds, sizeof(*cmds) * ncmds);
+
+ return REAL(cap_ioctls_limit)(fd, cmds, ncmds);
+}
+
+INTERCEPTOR(int, cap_ioctls_get, int fd, uptr *cmds, SIZE_T maxcmds) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cap_ioctls_get, fd, cmds, maxcmds);
+ int ret = REAL(cap_ioctls_get)(fd, cmds, maxcmds);
+ if (!ret && cmds)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cmds, sizeof(*cmds) * maxcmds);
+
+ return ret;
+}
+#define INIT_CAPSICUM \
+ COMMON_INTERCEPT_FUNCTION(cap_rights_init); \
+ COMMON_INTERCEPT_FUNCTION(cap_rights_set); \
+ COMMON_INTERCEPT_FUNCTION(cap_rights_clear); \
+ COMMON_INTERCEPT_FUNCTION(cap_rights_is_set); \
+ COMMON_INTERCEPT_FUNCTION(cap_rights_get); \
+ COMMON_INTERCEPT_FUNCTION(cap_rights_limit); \
+ COMMON_INTERCEPT_FUNCTION(cap_rights_contains); \
+ COMMON_INTERCEPT_FUNCTION(cap_rights_remove); \
+ COMMON_INTERCEPT_FUNCTION(cap_rights_merge); \
+ COMMON_INTERCEPT_FUNCTION(cap_rights_is_valid); \
+ COMMON_INTERCEPT_FUNCTION(cap_ioctls_get); \
+ COMMON_INTERCEPT_FUNCTION(cap_ioctls_limit)
+#else
+#define INIT_CAPSICUM
+#endif
+
+#if SANITIZER_INTERCEPT_SHA1
+INTERCEPTOR(void, SHA1Init, void *context) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA1Init, context);
+ REAL(SHA1Init)(context);
+ if (context)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz);
+}
+INTERCEPTOR(void, SHA1Update, void *context, const u8 *data, unsigned len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA1Update, context, data, len);
+ if (data && len > 0)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
+ REAL(SHA1Update)(context, data, len);
+ if (context)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA1_CTX_sz);
+}
+INTERCEPTOR(void, SHA1Final, u8 digest[20], void *context) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA1Final, digest, context);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
+ REAL(SHA1Final)(digest, context);
+ if (digest)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20);
+}
+INTERCEPTOR(void, SHA1Transform, u32 state[5], u8 buffer[64]) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA1Transform, state, buffer);
+ if (state)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5);
+ if (buffer)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u8) * 64);
+ REAL(SHA1Transform)(state, buffer);
+ if (state)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5);
+}
+INTERCEPTOR(char *, SHA1End, void *context, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA1End, context, buf);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA1_CTX_sz);
+ char *ret = REAL(SHA1End)(context, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
+ return ret;
+}
+INTERCEPTOR(char *, SHA1File, char *filename, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA1File, filename, buf);
+ if (filename)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
+ char *ret = REAL(SHA1File)(filename, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
+ return ret;
+}
+INTERCEPTOR(char *, SHA1FileChunk, char *filename, char *buf, OFF_T offset,
+ OFF_T length) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA1FileChunk, filename, buf, offset, length);
+ if (filename)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
+ char *ret = REAL(SHA1FileChunk)(filename, buf, offset, length);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
+ return ret;
+}
+INTERCEPTOR(char *, SHA1Data, u8 *data, SIZE_T len, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA1Data, data, len, buf);
+ if (data)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
+ char *ret = REAL(SHA1Data)(data, len, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA1_return_length);
+ return ret;
+}
+#define INIT_SHA1 \
+ COMMON_INTERCEPT_FUNCTION(SHA1Init); \
+ COMMON_INTERCEPT_FUNCTION(SHA1Update); \
+ COMMON_INTERCEPT_FUNCTION(SHA1Final); \
+ COMMON_INTERCEPT_FUNCTION(SHA1Transform); \
+ COMMON_INTERCEPT_FUNCTION(SHA1End); \
+ COMMON_INTERCEPT_FUNCTION(SHA1File); \
+ COMMON_INTERCEPT_FUNCTION(SHA1FileChunk); \
+ COMMON_INTERCEPT_FUNCTION(SHA1Data)
+#else
+#define INIT_SHA1
+#endif
+
+#if SANITIZER_INTERCEPT_MD4
+INTERCEPTOR(void, MD4Init, void *context) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD4Init, context);
+ REAL(MD4Init)(context);
+ if (context)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz);
+}
+
+INTERCEPTOR(void, MD4Update, void *context, const unsigned char *data,
+ unsigned int len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD4Update, context, data, len);
+ if (data && len > 0)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
+ REAL(MD4Update)(context, data, len);
+ if (context)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD4_CTX_sz);
+}
+
+INTERCEPTOR(void, MD4Final, unsigned char digest[16], void *context) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD4Final, digest, context);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
+ REAL(MD4Final)(digest, context);
+ if (digest)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
+}
+
+INTERCEPTOR(char *, MD4End, void *context, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD4End, context, buf);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD4_CTX_sz);
+ char *ret = REAL(MD4End)(context, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
+ return ret;
+}
+
+INTERCEPTOR(char *, MD4File, const char *filename, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD4File, filename, buf);
+ if (filename)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
+ char *ret = REAL(MD4File)(filename, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
+ return ret;
+}
+
+INTERCEPTOR(char *, MD4Data, const unsigned char *data, unsigned int len,
+ char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD4Data, data, len, buf);
+ if (data && len > 0)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
+ char *ret = REAL(MD4Data)(data, len, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD4_return_length);
+ return ret;
+}
+
+#define INIT_MD4 \
+ COMMON_INTERCEPT_FUNCTION(MD4Init); \
+ COMMON_INTERCEPT_FUNCTION(MD4Update); \
+ COMMON_INTERCEPT_FUNCTION(MD4Final); \
+ COMMON_INTERCEPT_FUNCTION(MD4End); \
+ COMMON_INTERCEPT_FUNCTION(MD4File); \
+ COMMON_INTERCEPT_FUNCTION(MD4Data)
+#else
+#define INIT_MD4
+#endif
+
+#if SANITIZER_INTERCEPT_RMD160
+INTERCEPTOR(void, RMD160Init, void *context) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, RMD160Init, context);
+ REAL(RMD160Init)(context);
+ if (context)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz);
+}
+INTERCEPTOR(void, RMD160Update, void *context, const u8 *data, unsigned len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, RMD160Update, context, data, len);
+ if (data && len > 0)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
+ REAL(RMD160Update)(context, data, len);
+ if (context)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, RMD160_CTX_sz);
+}
+INTERCEPTOR(void, RMD160Final, u8 digest[20], void *context) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, RMD160Final, digest, context);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
+ REAL(RMD160Final)(digest, context);
+ if (digest)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(u8) * 20);
+}
+INTERCEPTOR(void, RMD160Transform, u32 state[5], u16 buffer[16]) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, RMD160Transform, state, buffer);
+ if (state)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, state, sizeof(u32) * 5);
+ if (buffer)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, sizeof(u32) * 16);
+ REAL(RMD160Transform)(state, buffer);
+ if (state)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, state, sizeof(u32) * 5);
+}
+INTERCEPTOR(char *, RMD160End, void *context, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, RMD160End, context, buf);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, RMD160_CTX_sz);
+ char *ret = REAL(RMD160End)(context, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
+ return ret;
+}
+INTERCEPTOR(char *, RMD160File, char *filename, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, RMD160File, filename, buf);
+ if (filename)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
+ char *ret = REAL(RMD160File)(filename, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
+ return ret;
+}
+INTERCEPTOR(char *, RMD160FileChunk, char *filename, char *buf, OFF_T offset,
+ OFF_T length) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, RMD160FileChunk, filename, buf, offset, length);
+ if (filename)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
+ char *ret = REAL(RMD160FileChunk)(filename, buf, offset, length);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
+ return ret;
+}
+INTERCEPTOR(char *, RMD160Data, u8 *data, SIZE_T len, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, RMD160Data, data, len, buf);
+ if (data && len > 0)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
+ char *ret = REAL(RMD160Data)(data, len, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, RMD160_return_length);
+ return ret;
+}
+#define INIT_RMD160 \
+ COMMON_INTERCEPT_FUNCTION(RMD160Init); \
+ COMMON_INTERCEPT_FUNCTION(RMD160Update); \
+ COMMON_INTERCEPT_FUNCTION(RMD160Final); \
+ COMMON_INTERCEPT_FUNCTION(RMD160Transform); \
+ COMMON_INTERCEPT_FUNCTION(RMD160End); \
+ COMMON_INTERCEPT_FUNCTION(RMD160File); \
+ COMMON_INTERCEPT_FUNCTION(RMD160FileChunk); \
+ COMMON_INTERCEPT_FUNCTION(RMD160Data)
+#else
+#define INIT_RMD160
+#endif
+
+#if SANITIZER_INTERCEPT_MD5
+INTERCEPTOR(void, MD5Init, void *context) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD5Init, context);
+ REAL(MD5Init)(context);
+ if (context)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
+}
+
+INTERCEPTOR(void, MD5Update, void *context, const unsigned char *data,
+ unsigned int len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD5Update, context, data, len);
+ if (data && len > 0)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
+ REAL(MD5Update)(context, data, len);
+ if (context)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD5_CTX_sz);
+}
+
+INTERCEPTOR(void, MD5Final, unsigned char digest[16], void *context) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD5Final, digest, context);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
+ REAL(MD5Final)(digest, context);
+ if (digest)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
+}
+
+INTERCEPTOR(char *, MD5End, void *context, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD5End, context, buf);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD5_CTX_sz);
+ char *ret = REAL(MD5End)(context, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
+ return ret;
+}
+
+INTERCEPTOR(char *, MD5File, const char *filename, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD5File, filename, buf);
+ if (filename)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
+ char *ret = REAL(MD5File)(filename, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
+ return ret;
+}
+
+INTERCEPTOR(char *, MD5Data, const unsigned char *data, unsigned int len,
+ char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD5Data, data, len, buf);
+ if (data && len > 0)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
+ char *ret = REAL(MD5Data)(data, len, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD5_return_length);
+ return ret;
+}
+
+#define INIT_MD5 \
+ COMMON_INTERCEPT_FUNCTION(MD5Init); \
+ COMMON_INTERCEPT_FUNCTION(MD5Update); \
+ COMMON_INTERCEPT_FUNCTION(MD5Final); \
+ COMMON_INTERCEPT_FUNCTION(MD5End); \
+ COMMON_INTERCEPT_FUNCTION(MD5File); \
+ COMMON_INTERCEPT_FUNCTION(MD5Data)
+#else
+#define INIT_MD5
+#endif
+
+#if SANITIZER_INTERCEPT_FSEEK
+INTERCEPTOR(int, fseek, __sanitizer_FILE *stream, long int offset, int whence) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fseek, stream, offset, whence);
+ return REAL(fseek)(stream, offset, whence);
+}
+INTERCEPTOR(int, fseeko, __sanitizer_FILE *stream, OFF_T offset, int whence) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fseeko, stream, offset, whence);
+ return REAL(fseeko)(stream, offset, whence);
+}
+INTERCEPTOR(long int, ftell, __sanitizer_FILE *stream) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ftell, stream);
+ return REAL(ftell)(stream);
+}
+INTERCEPTOR(OFF_T, ftello, __sanitizer_FILE *stream) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ftello, stream);
+ return REAL(ftello)(stream);
+}
+INTERCEPTOR(void, rewind, __sanitizer_FILE *stream) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, rewind, stream);
+ return REAL(rewind)(stream);
+}
+INTERCEPTOR(int, fgetpos, __sanitizer_FILE *stream, void *pos) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fgetpos, stream, pos);
+ int ret = REAL(fgetpos)(stream, pos);
+ if (pos && !ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pos, fpos_t_sz);
+ return ret;
+}
+INTERCEPTOR(int, fsetpos, __sanitizer_FILE *stream, const void *pos) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fsetpos, stream, pos);
+ if (pos)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, pos, fpos_t_sz);
+ return REAL(fsetpos)(stream, pos);
+}
+#define INIT_FSEEK \
+ COMMON_INTERCEPT_FUNCTION(fseek); \
+ COMMON_INTERCEPT_FUNCTION(fseeko); \
+ COMMON_INTERCEPT_FUNCTION(ftell); \
+ COMMON_INTERCEPT_FUNCTION(ftello); \
+ COMMON_INTERCEPT_FUNCTION(rewind); \
+ COMMON_INTERCEPT_FUNCTION(fgetpos); \
+ COMMON_INTERCEPT_FUNCTION(fsetpos)
+#else
+#define INIT_FSEEK
+#endif
+
+#if SANITIZER_INTERCEPT_MD2
+INTERCEPTOR(void, MD2Init, void *context) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD2Init, context);
+ REAL(MD2Init)(context);
+ if (context)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz);
+}
+
+INTERCEPTOR(void, MD2Update, void *context, const unsigned char *data,
+ unsigned int len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD2Update, context, data, len);
+ if (data && len > 0)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
+ REAL(MD2Update)(context, data, len);
+ if (context)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, MD2_CTX_sz);
+}
+
+INTERCEPTOR(void, MD2Final, unsigned char digest[16], void *context) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD2Final, digest, context);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
+ REAL(MD2Final)(digest, context);
+ if (digest)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, sizeof(unsigned char) * 16);
+}
+
+INTERCEPTOR(char *, MD2End, void *context, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD2End, context, buf);
+ if (context)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, MD2_CTX_sz);
+ char *ret = REAL(MD2End)(context, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
+ return ret;
+}
+
+INTERCEPTOR(char *, MD2File, const char *filename, char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD2File, filename, buf);
+ if (filename)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);
+ char *ret = REAL(MD2File)(filename, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
+ return ret;
+}
+
+INTERCEPTOR(char *, MD2Data, const unsigned char *data, unsigned int len,
+ char *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, MD2Data, data, len, buf);
+ if (data && len > 0)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len);
+ char *ret = REAL(MD2Data)(data, len, buf);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, MD2_return_length);
+ return ret;
+}
+
+#define INIT_MD2 \
+ COMMON_INTERCEPT_FUNCTION(MD2Init); \
+ COMMON_INTERCEPT_FUNCTION(MD2Update); \
+ COMMON_INTERCEPT_FUNCTION(MD2Final); \
+ COMMON_INTERCEPT_FUNCTION(MD2End); \
+ COMMON_INTERCEPT_FUNCTION(MD2File); \
+ COMMON_INTERCEPT_FUNCTION(MD2Data)
+#else
+#define INIT_MD2
+#endif
+
+#if SANITIZER_INTERCEPT_SHA2
+#define SHA2_INTERCEPTORS(LEN, SHA2_STATE_T) \
+ INTERCEPTOR(void, SHA##LEN##_Init, void *context) { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Init, context); \
+ REAL(SHA##LEN##_Init)(context); \
+ if (context) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
+ } \
+ INTERCEPTOR(void, SHA##LEN##_Update, void *context, \
+ const u8 *data, SIZE_T len) { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Update, context, data, len); \
+ if (data && len > 0) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
+ if (context) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
+ REAL(SHA##LEN##_Update)(context, data, len); \
+ if (context) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
+ } \
+ INTERCEPTOR(void, SHA##LEN##_Final, u8 digest[LEN/8], \
+ void *context) { \
+ void *ctx; \
+ CHECK_EQ(SHA##LEN##_digest_length, LEN/8); \
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Final, digest, context); \
+ if (context) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
+ REAL(SHA##LEN##_Final)(digest, context); \
+ if (digest) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, digest, \
+ sizeof(digest[0]) * \
+ SHA##LEN##_digest_length); \
+ } \
+ INTERCEPTOR(char *, SHA##LEN##_End, void *context, char *buf) { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_End, context, buf); \
+ if (context) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, context, SHA##LEN##_CTX_sz); \
+ char *ret = REAL(SHA##LEN##_End)(context, buf); \
+ if (ret) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
+ return ret; \
+ } \
+ INTERCEPTOR(char *, SHA##LEN##_File, const char *filename, char *buf) { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_File, filename, buf); \
+ if (filename) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
+ char *ret = REAL(SHA##LEN##_File)(filename, buf); \
+ if (ret) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
+ return ret; \
+ } \
+ INTERCEPTOR(char *, SHA##LEN##_FileChunk, const char *filename, char *buf, \
+ OFF_T offset, OFF_T length) { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_FileChunk, filename, buf, offset, \
+ length); \
+ if (filename) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, filename, internal_strlen(filename) + 1);\
+ char *ret = REAL(SHA##LEN##_FileChunk)(filename, buf, offset, length); \
+ if (ret) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
+ return ret; \
+ } \
+ INTERCEPTOR(char *, SHA##LEN##_Data, u8 *data, SIZE_T len, char *buf) { \
+ void *ctx; \
+ COMMON_INTERCEPTOR_ENTER(ctx, SHA##LEN##_Data, data, len, buf); \
+ if (data && len > 0) \
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, len); \
+ char *ret = REAL(SHA##LEN##_Data)(data, len, buf); \
+ if (ret) \
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, SHA##LEN##_return_length); \
+ return ret; \
+ }
+
+SHA2_INTERCEPTORS(224, u32)
+SHA2_INTERCEPTORS(256, u32)
+SHA2_INTERCEPTORS(384, u64)
+SHA2_INTERCEPTORS(512, u64)
+
+#define INIT_SHA2_INTECEPTORS(LEN) \
+ COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Init); \
+ COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Update); \
+ COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Final); \
+ COMMON_INTERCEPT_FUNCTION(SHA##LEN##_End); \
+ COMMON_INTERCEPT_FUNCTION(SHA##LEN##_File); \
+ COMMON_INTERCEPT_FUNCTION(SHA##LEN##_FileChunk); \
+ COMMON_INTERCEPT_FUNCTION(SHA##LEN##_Data)
+
+#define INIT_SHA2 \
+ INIT_SHA2_INTECEPTORS(224); \
+ INIT_SHA2_INTECEPTORS(256); \
+ INIT_SHA2_INTECEPTORS(384); \
+ INIT_SHA2_INTECEPTORS(512)
+#undef SHA2_INTERCEPTORS
+#else
+#define INIT_SHA2
+#endif
+
+#if SANITIZER_INTERCEPT_VIS
+INTERCEPTOR(char *, vis, char *dst, int c, int flag, int nextc) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, vis, dst, c, flag, nextc);
+ char *end = REAL(vis)(dst, c, flag, nextc);
+ // dst is NULL terminated and end points to the NULL char
+ if (dst && end)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
+ return end;
+}
+INTERCEPTOR(char *, nvis, char *dst, SIZE_T dlen, int c, int flag, int nextc) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, nvis, dst, dlen, c, flag, nextc);
+ char *end = REAL(nvis)(dst, dlen, c, flag, nextc);
+ // nvis cannot make sure the dst is NULL terminated
+ if (dst && end)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
+ return end;
+}
+INTERCEPTOR(int, strvis, char *dst, const char *src, int flag) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strvis, dst, src, flag);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
+ int len = REAL(strvis)(dst, src, flag);
+ if (dst)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
+ return len;
+}
+INTERCEPTOR(int, stravis, char **dst, const char *src, int flag) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, stravis, dst, src, flag);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
+ int len = REAL(stravis)(dst, src, flag);
+ if (dst) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(char *));
+ if (*dst)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *dst, len + 1);
+ }
+ return len;
+}
+INTERCEPTOR(int, strnvis, char *dst, SIZE_T dlen, const char *src, int flag) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strnvis, dst, dlen, src, flag);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
+ int len = REAL(strnvis)(dst, dlen, src, flag);
+ // The interface will be valid even if there is no space for NULL char
+ if (dst && len > 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
+ return len;
+}
+INTERCEPTOR(int, strvisx, char *dst, const char *src, SIZE_T len, int flag) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strvisx, dst, src, len, flag);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
+ int ret = REAL(strvisx)(dst, src, len, flag);
+ if (dst)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+ return ret;
+}
+INTERCEPTOR(int, strnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
+ int flag) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strnvisx, dst, dlen, src, len, flag);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
+ int ret = REAL(strnvisx)(dst, dlen, src, len, flag);
+ if (dst && ret >= 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+ return ret;
+}
+INTERCEPTOR(int, strenvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
+ int flag, int *cerr_ptr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strenvisx, dst, dlen, src, len, flag, cerr_ptr);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
+ // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
+ // according to the implementation
+ if (cerr_ptr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
+ int ret = REAL(strenvisx)(dst, dlen, src, len, flag, cerr_ptr);
+ if (dst && ret >= 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+ if (cerr_ptr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
+ return ret;
+}
+INTERCEPTOR(char *, svis, char *dst, int c, int flag, int nextc,
+ const char *extra) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, svis, dst, c, flag, nextc, extra);
+ if (extra)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
+ char *end = REAL(svis)(dst, c, flag, nextc, extra);
+ if (dst && end)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, end - dst + 1);
+ return end;
+}
+INTERCEPTOR(char *, snvis, char *dst, SIZE_T dlen, int c, int flag, int nextc,
+ const char *extra) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, snvis, dst, dlen, c, flag, nextc, extra);
+ if (extra)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
+ char *end = REAL(snvis)(dst, dlen, c, flag, nextc, extra);
+ if (dst && end)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst,
+ Min((SIZE_T)(end - dst + 1), dlen));
+ return end;
+}
+INTERCEPTOR(int, strsvis, char *dst, const char *src, int flag,
+ const char *extra) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strsvis, dst, src, flag, extra);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
+ if (extra)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
+ int len = REAL(strsvis)(dst, src, flag, extra);
+ if (dst)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
+ return len;
+}
+INTERCEPTOR(int, strsnvis, char *dst, SIZE_T dlen, const char *src, int flag,
+ const char *extra) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strsnvis, dst, dlen, src, flag, extra);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
+ if (extra)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
+ int len = REAL(strsnvis)(dst, dlen, src, flag, extra);
+ // The interface will be valid even if there is no space for NULL char
+ if (dst && len >= 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, len + 1);
+ return len;
+}
+INTERCEPTOR(int, strsvisx, char *dst, const char *src, SIZE_T len, int flag,
+ const char *extra) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strsvisx, dst, src, len, flag, extra);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
+ if (extra)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
+ int ret = REAL(strsvisx)(dst, src, len, flag, extra);
+ if (dst)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+ return ret;
+}
+INTERCEPTOR(int, strsnvisx, char *dst, SIZE_T dlen, const char *src, SIZE_T len,
+ int flag, const char *extra) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strsnvisx, dst, dlen, src, len, flag, extra);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
+ if (extra)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
+ int ret = REAL(strsnvisx)(dst, dlen, src, len, flag, extra);
+ if (dst && ret >= 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+ return ret;
+}
+INTERCEPTOR(int, strsenvisx, char *dst, SIZE_T dlen, const char *src,
+ SIZE_T len, int flag, const char *extra, int *cerr_ptr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strsenvisx, dst, dlen, src, len, flag, extra,
+ cerr_ptr);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, len);
+ if (extra)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, extra, internal_strlen(extra) + 1);
+ // FIXME: only need to be checked when "flag | VIS_NOLOCALE" doesn't hold
+ // according to the implementation
+ if (cerr_ptr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cerr_ptr, sizeof(int));
+ int ret = REAL(strsenvisx)(dst, dlen, src, len, flag, extra, cerr_ptr);
+ if (dst && ret >= 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+ if (cerr_ptr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cerr_ptr, sizeof(int));
+ return ret;
+}
+INTERCEPTOR(int, unvis, char *cp, int c, int *astate, int flag) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, unvis, cp, c, astate, flag);
+ if (astate)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, astate, sizeof(*astate));
+ int ret = REAL(unvis)(cp, c, astate, flag);
+ if (ret == unvis_valid || ret == unvis_validpush) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cp, sizeof(*cp));
+ }
+ return ret;
+}
+INTERCEPTOR(int, strunvis, char *dst, const char *src) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strunvis, dst, src);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
+ int ret = REAL(strunvis)(dst, src);
+ if (ret != -1)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+ return ret;
+}
+INTERCEPTOR(int, strnunvis, char *dst, SIZE_T dlen, const char *src) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strnunvis, dst, dlen, src);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
+ int ret = REAL(strnunvis)(dst, dlen, src);
+ if (ret != -1)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+ return ret;
+}
+INTERCEPTOR(int, strunvisx, char *dst, const char *src, int flag) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strunvisx, dst, src, flag);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
+ int ret = REAL(strunvisx)(dst, src, flag);
+ if (ret != -1)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+ return ret;
+}
+INTERCEPTOR(int, strnunvisx, char *dst, SIZE_T dlen, const char *src,
+ int flag) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strnunvisx, dst, dlen, src, flag);
+ if (src)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, internal_strlen(src) + 1);
+ int ret = REAL(strnunvisx)(dst, dlen, src, flag);
+ if (ret != -1)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, ret + 1);
+ return ret;
+}
+#define INIT_VIS \
+ COMMON_INTERCEPT_FUNCTION(vis); \
+ COMMON_INTERCEPT_FUNCTION(nvis); \
+ COMMON_INTERCEPT_FUNCTION(strvis); \
+ COMMON_INTERCEPT_FUNCTION(stravis); \
+ COMMON_INTERCEPT_FUNCTION(strnvis); \
+ COMMON_INTERCEPT_FUNCTION(strvisx); \
+ COMMON_INTERCEPT_FUNCTION(strnvisx); \
+ COMMON_INTERCEPT_FUNCTION(strenvisx); \
+ COMMON_INTERCEPT_FUNCTION(svis); \
+ COMMON_INTERCEPT_FUNCTION(snvis); \
+ COMMON_INTERCEPT_FUNCTION(strsvis); \
+ COMMON_INTERCEPT_FUNCTION(strsnvis); \
+ COMMON_INTERCEPT_FUNCTION(strsvisx); \
+ COMMON_INTERCEPT_FUNCTION(strsnvisx); \
+ COMMON_INTERCEPT_FUNCTION(strsenvisx); \
+ COMMON_INTERCEPT_FUNCTION(unvis); \
+ COMMON_INTERCEPT_FUNCTION(strunvis); \
+ COMMON_INTERCEPT_FUNCTION(strnunvis); \
+ COMMON_INTERCEPT_FUNCTION(strunvisx); \
+ COMMON_INTERCEPT_FUNCTION(strnunvisx)
+#else
+#define INIT_VIS
+#endif
+
+#if SANITIZER_INTERCEPT_CDB
+INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open, const char *path, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open, path, flags);
+ if (path)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ struct __sanitizer_cdbr *cdbr = REAL(cdbr_open)(path, flags);
+ if (cdbr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
+ return cdbr;
+}
+
+INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open_mem, void *base, SIZE_T size,
+ int flags, void (*unmap)(void *, void *, SIZE_T), void *cookie) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open_mem, base, size, flags, unmap,
+ cookie);
+ if (base && size)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, base, size);
+ struct __sanitizer_cdbr *cdbr =
+ REAL(cdbr_open_mem)(base, size, flags, unmap, cookie);
+ if (cdbr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
+ return cdbr;
+}
+
+INTERCEPTOR(u32, cdbr_entries, struct __sanitizer_cdbr *cdbr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbr_entries, cdbr);
+ if (cdbr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
+ return REAL(cdbr_entries)(cdbr);
+}
+
+INTERCEPTOR(int, cdbr_get, struct __sanitizer_cdbr *cdbr, u32 index,
+ const void **data, SIZE_T *datalen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbr_get, cdbr, index, data, datalen);
+ if (cdbr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
+ int ret = REAL(cdbr_get)(cdbr, index, data, datalen);
+ if (!ret) {
+ if (data)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
+ if (datalen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
+ if (data && datalen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
+ }
+ return ret;
+}
+
+INTERCEPTOR(int, cdbr_find, struct __sanitizer_cdbr *cdbr, const void *key,
+ SIZE_T keylen, const void **data, SIZE_T *datalen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbr_find, cdbr, key, keylen, data, datalen);
+ if (cdbr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
+ if (key)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
+ int ret = REAL(cdbr_find)(cdbr, key, keylen, data, datalen);
+ if (!ret) {
+ if (data)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
+ if (datalen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
+ if (data && datalen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
+ }
+ return ret;
+}
+
+INTERCEPTOR(void, cdbr_close, struct __sanitizer_cdbr *cdbr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbr_close, cdbr);
+ if (cdbr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
+ REAL(cdbr_close)(cdbr);
+}
+
+INTERCEPTOR(struct __sanitizer_cdbw *, cdbw_open) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbw_open);
+ struct __sanitizer_cdbw *ret = REAL(cdbw_open)();
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));
+ return ret;
+}
+
+INTERCEPTOR(int, cdbw_put, struct __sanitizer_cdbw *cdbw, const void *key,
+ SIZE_T keylen, const void *data, SIZE_T datalen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put, cdbw, key, keylen, data, datalen);
+ if (cdbw)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
+ if (data && datalen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
+ if (key && keylen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
+ int ret = REAL(cdbw_put)(cdbw, key, keylen, data, datalen);
+ if (!ret && cdbw)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
+ return ret;
+}
+
+INTERCEPTOR(int, cdbw_put_data, struct __sanitizer_cdbw *cdbw, const void *data,
+ SIZE_T datalen, u32 *index) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_data, cdbw, data, datalen, index);
+ if (cdbw)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
+ if (data && datalen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
+ int ret = REAL(cdbw_put_data)(cdbw, data, datalen, index);
+ if (!ret) {
+ if (index)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, index, sizeof(*index));
+ if (cdbw)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
+ }
+ return ret;
+}
+
+INTERCEPTOR(int, cdbw_put_key, struct __sanitizer_cdbw *cdbw, const void *key,
+ SIZE_T keylen, u32 index) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_key, cdbw, key, keylen, index);
+ if (cdbw)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
+ if (key && keylen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
+ int ret = REAL(cdbw_put_key)(cdbw, key, keylen, index);
+ if (!ret && cdbw)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
+ return ret;
+}
+
+INTERCEPTOR(int, cdbw_output, struct __sanitizer_cdbw *cdbw, int output,
+ const char descr[16], u32 (*seedgen)(void)) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbw_output, cdbw, output, descr, seedgen);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, output);
+ if (cdbw)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
+ if (descr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, descr, internal_strnlen(descr, 16));
+ if (seedgen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)seedgen, sizeof(seedgen));
+ int ret = REAL(cdbw_output)(cdbw, output, descr, seedgen);
+ if (!ret) {
+ if (cdbw)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
+ if (output >= 0)
+ COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, output);
+ }
+ return ret;
+}
+
+INTERCEPTOR(void, cdbw_close, struct __sanitizer_cdbw *cdbw) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbw_close, cdbw);
+ if (cdbw)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
+ REAL(cdbw_close)(cdbw);
+}
+
+#define INIT_CDB \
+ COMMON_INTERCEPT_FUNCTION(cdbr_open); \
+ COMMON_INTERCEPT_FUNCTION(cdbr_open_mem); \
+ COMMON_INTERCEPT_FUNCTION(cdbr_entries); \
+ COMMON_INTERCEPT_FUNCTION(cdbr_get); \
+ COMMON_INTERCEPT_FUNCTION(cdbr_find); \
+ COMMON_INTERCEPT_FUNCTION(cdbr_close); \
+ COMMON_INTERCEPT_FUNCTION(cdbw_open); \
+ COMMON_INTERCEPT_FUNCTION(cdbw_put); \
+ COMMON_INTERCEPT_FUNCTION(cdbw_put_data); \
+ COMMON_INTERCEPT_FUNCTION(cdbw_put_key); \
+ COMMON_INTERCEPT_FUNCTION(cdbw_output); \
+ COMMON_INTERCEPT_FUNCTION(cdbw_close)
+#else
+#define INIT_CDB
+#endif
+
+#if SANITIZER_INTERCEPT_GETFSENT
+INTERCEPTOR(void *, getfsent) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getfsent);
+ void *ret = REAL(getfsent)();
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
+ return ret;
+}
+
+INTERCEPTOR(void *, getfsspec, const char *spec) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getfsspec, spec);
+ if (spec)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, spec, internal_strlen(spec) + 1);
+ void *ret = REAL(getfsspec)(spec);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
+ return ret;
+}
+
+INTERCEPTOR(void *, getfsfile, const char *file) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getfsfile, file);
+ if (file)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, file, internal_strlen(file) + 1);
+ void *ret = REAL(getfsfile)(file);
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, struct_fstab_sz);
+ return ret;
+}
+
+#define INIT_GETFSENT \
+ COMMON_INTERCEPT_FUNCTION(getfsent); \
+ COMMON_INTERCEPT_FUNCTION(getfsspec); \
+ COMMON_INTERCEPT_FUNCTION(getfsfile);
+#else
+#define INIT_GETFSENT
+#endif
+
+#if SANITIZER_INTERCEPT_ARC4RANDOM
+INTERCEPTOR(void, arc4random_buf, void *buf, SIZE_T len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, arc4random_buf, buf, len);
+ REAL(arc4random_buf)(buf, len);
+ if (buf && len)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, len);
+}
+
+INTERCEPTOR(void, arc4random_addrandom, u8 *dat, int datlen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, arc4random_addrandom, dat, datlen);
+ if (dat && datlen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, dat, datlen);
+ REAL(arc4random_addrandom)(dat, datlen);
+}
+
+#define INIT_ARC4RANDOM \
+ COMMON_INTERCEPT_FUNCTION(arc4random_buf); \
+ COMMON_INTERCEPT_FUNCTION(arc4random_addrandom);
+#else
+#define INIT_ARC4RANDOM
+#endif
+
+#if SANITIZER_INTERCEPT_POPEN
+INTERCEPTOR(__sanitizer_FILE *, popen, const char *command, const char *type) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, popen, command, type);
+ if (command)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, command, internal_strlen(command) + 1);
+ if (type)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, type, internal_strlen(type) + 1);
+ __sanitizer_FILE *res = REAL(popen)(command, type);
+ COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
+ if (res) unpoison_file(res);
+ return res;
+}
+#define INIT_POPEN COMMON_INTERCEPT_FUNCTION(popen)
+#else
+#define INIT_POPEN
+#endif
+
+#if SANITIZER_INTERCEPT_POPENVE
+INTERCEPTOR(__sanitizer_FILE *, popenve, const char *path,
+ char *const *argv, char *const *envp, const char *type) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, popenve, path, argv, envp, type);
+ if (path)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ if (argv) {
+ for (char *const *pa = argv; ; ++pa) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
+ if (!*pa)
+ break;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
+ }
+ }
+ if (envp) {
+ for (char *const *pa = envp; ; ++pa) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
+ if (!*pa)
+ break;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, internal_strlen(*pa) + 1);
+ }
+ }
+ if (type)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, type, internal_strlen(type) + 1);
+ __sanitizer_FILE *res = REAL(popenve)(path, argv, envp, type);
+ COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
+ if (res) unpoison_file(res);
+ return res;
+}
+#define INIT_POPENVE COMMON_INTERCEPT_FUNCTION(popenve)
+#else
+#define INIT_POPENVE
+#endif
+
+#if SANITIZER_INTERCEPT_PCLOSE
+INTERCEPTOR(int, pclose, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pclose, fp);
+ COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
+ const FileMetadata *m = GetInterceptorMetadata(fp);
+ int res = REAL(pclose)(fp);
+ if (m) {
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
+ DeleteInterceptorMetadata(fp);
+ }
+ return res;
+}
+#define INIT_PCLOSE COMMON_INTERCEPT_FUNCTION(pclose);
+#else
+#define INIT_PCLOSE
+#endif
+
+#if SANITIZER_INTERCEPT_FUNOPEN
+typedef int (*funopen_readfn)(void *cookie, char *buf, int len);
+typedef int (*funopen_writefn)(void *cookie, const char *buf, int len);
+typedef OFF_T (*funopen_seekfn)(void *cookie, OFF_T offset, int whence);
+typedef int (*funopen_closefn)(void *cookie);
+
+struct WrappedFunopenCookie {
+ void *real_cookie;
+ funopen_readfn real_read;
+ funopen_writefn real_write;
+ funopen_seekfn real_seek;
+ funopen_closefn real_close;
+};
+
+static int wrapped_funopen_read(void *cookie, char *buf, int len) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
+ funopen_readfn real_read = wrapped_cookie->real_read;
+ return real_read(wrapped_cookie->real_cookie, buf, len);
+}
+
+static int wrapped_funopen_write(void *cookie, const char *buf, int len) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
+ funopen_writefn real_write = wrapped_cookie->real_write;
+ return real_write(wrapped_cookie->real_cookie, buf, len);
+}
+
+static OFF_T wrapped_funopen_seek(void *cookie, OFF_T offset, int whence) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
+ funopen_seekfn real_seek = wrapped_cookie->real_seek;
+ return real_seek(wrapped_cookie->real_cookie, offset, whence);
+}
+
+static int wrapped_funopen_close(void *cookie) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ WrappedFunopenCookie *wrapped_cookie = (WrappedFunopenCookie *)cookie;
+ funopen_closefn real_close = wrapped_cookie->real_close;
+ int res = real_close(wrapped_cookie->real_cookie);
+ InternalFree(wrapped_cookie);
+ return res;
+}
+
+INTERCEPTOR(__sanitizer_FILE *, funopen, void *cookie, funopen_readfn readfn,
+ funopen_writefn writefn, funopen_seekfn seekfn,
+ funopen_closefn closefn) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, funopen, cookie, readfn, writefn, seekfn,
+ closefn);
+
+ WrappedFunopenCookie *wrapped_cookie =
+ (WrappedFunopenCookie *)InternalAlloc(sizeof(WrappedFunopenCookie));
+ wrapped_cookie->real_cookie = cookie;
+ wrapped_cookie->real_read = readfn;
+ wrapped_cookie->real_write = writefn;
+ wrapped_cookie->real_seek = seekfn;
+ wrapped_cookie->real_close = closefn;
+
+ __sanitizer_FILE *res =
+ REAL(funopen)(wrapped_cookie,
+ readfn ? wrapped_funopen_read : nullptr,
+ writefn ? wrapped_funopen_write : nullptr,
+ seekfn ? wrapped_funopen_seek : nullptr,
+ closefn ? wrapped_funopen_close : nullptr);
+ if (res)
+ unpoison_file(res);
+ return res;
+}
+#define INIT_FUNOPEN COMMON_INTERCEPT_FUNCTION(funopen)
+#else
+#define INIT_FUNOPEN
+#endif
+
+#if SANITIZER_INTERCEPT_FUNOPEN2
+typedef SSIZE_T (*funopen2_readfn)(void *cookie, void *buf, SIZE_T len);
+typedef SSIZE_T (*funopen2_writefn)(void *cookie, const void *buf, SIZE_T len);
+typedef OFF_T (*funopen2_seekfn)(void *cookie, OFF_T offset, int whence);
+typedef int (*funopen2_flushfn)(void *cookie);
+typedef int (*funopen2_closefn)(void *cookie);
+
+struct WrappedFunopen2Cookie {
+ void *real_cookie;
+ funopen2_readfn real_read;
+ funopen2_writefn real_write;
+ funopen2_seekfn real_seek;
+ funopen2_flushfn real_flush;
+ funopen2_closefn real_close;
+};
+
+static SSIZE_T wrapped_funopen2_read(void *cookie, void *buf, SIZE_T len) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
+ funopen2_readfn real_read = wrapped_cookie->real_read;
+ return real_read(wrapped_cookie->real_cookie, buf, len);
+}
+
+static SSIZE_T wrapped_funopen2_write(void *cookie, const void *buf,
+ SIZE_T len) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
+ funopen2_writefn real_write = wrapped_cookie->real_write;
+ return real_write(wrapped_cookie->real_cookie, buf, len);
+}
+
+static OFF_T wrapped_funopen2_seek(void *cookie, OFF_T offset, int whence) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
+ funopen2_seekfn real_seek = wrapped_cookie->real_seek;
+ return real_seek(wrapped_cookie->real_cookie, offset, whence);
+}
+
+static int wrapped_funopen2_flush(void *cookie) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
+ funopen2_flushfn real_flush = wrapped_cookie->real_flush;
+ return real_flush(wrapped_cookie->real_cookie);
+}
+
+static int wrapped_funopen2_close(void *cookie) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
+ WrappedFunopen2Cookie *wrapped_cookie = (WrappedFunopen2Cookie *)cookie;
+ funopen2_closefn real_close = wrapped_cookie->real_close;
+ int res = real_close(wrapped_cookie->real_cookie);
+ InternalFree(wrapped_cookie);
+ return res;
+}
+
+INTERCEPTOR(__sanitizer_FILE *, funopen2, void *cookie, funopen2_readfn readfn,
+ funopen2_writefn writefn, funopen2_seekfn seekfn,
+ funopen2_flushfn flushfn, funopen2_closefn closefn) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, funopen2, cookie, readfn, writefn, seekfn,
+ flushfn, closefn);
+
+ WrappedFunopen2Cookie *wrapped_cookie =
+ (WrappedFunopen2Cookie *)InternalAlloc(sizeof(WrappedFunopen2Cookie));
+ wrapped_cookie->real_cookie = cookie;
+ wrapped_cookie->real_read = readfn;
+ wrapped_cookie->real_write = writefn;
+ wrapped_cookie->real_seek = seekfn;
+ wrapped_cookie->real_flush = flushfn;
+ wrapped_cookie->real_close = closefn;
+
+ __sanitizer_FILE *res =
+ REAL(funopen2)(wrapped_cookie,
+ readfn ? wrapped_funopen2_read : nullptr,
+ writefn ? wrapped_funopen2_write : nullptr,
+ seekfn ? wrapped_funopen2_seek : nullptr,
+ flushfn ? wrapped_funopen2_flush : nullptr,
+ closefn ? wrapped_funopen2_close : nullptr);
+ if (res)
+ unpoison_file(res);
+ return res;
+}
+#define INIT_FUNOPEN2 COMMON_INTERCEPT_FUNCTION(funopen2)
+#else
+#define INIT_FUNOPEN2
+#endif
+
+#if SANITIZER_INTERCEPT_FDEVNAME
+INTERCEPTOR(char *, fdevname, int fd) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fdevname, fd);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ char *name = REAL(fdevname)(fd);
+ if (name) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strlen(name) + 1);
+ if (fd > 0)
+ COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ }
+ return name;
+}
+
+INTERCEPTOR(char *, fdevname_r, int fd, char *buf, SIZE_T len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fdevname_r, fd, buf, len);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ char *name = REAL(fdevname_r)(fd, buf, len);
+ if (name && buf && len > 0) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
+ if (fd > 0)
+ COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ }
+ return name;
+}
+
+#define INIT_FDEVNAME \
+ COMMON_INTERCEPT_FUNCTION(fdevname); \
+ COMMON_INTERCEPT_FUNCTION(fdevname_r);
+#else
+#define INIT_FDEVNAME
+#endif
+
+#if SANITIZER_INTERCEPT_GETUSERSHELL
+INTERCEPTOR(char *, getusershell) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getusershell);
+ char *res = REAL(getusershell)();
+ if (res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
+ return res;
+}
+
+#define INIT_GETUSERSHELL COMMON_INTERCEPT_FUNCTION(getusershell);
+#else
+#define INIT_GETUSERSHELL
+#endif
+
+#if SANITIZER_INTERCEPT_SL_INIT
+INTERCEPTOR(void *, sl_init) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sl_init);
+ void *res = REAL(sl_init)();
+ if (res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, __sanitizer::struct_StringList_sz);
+ return res;
+}
+
+INTERCEPTOR(int, sl_add, void *sl, char *item) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sl_add, sl, item);
+ if (sl)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
+ if (item)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, item, internal_strlen(item) + 1);
+ int res = REAL(sl_add)(sl, item);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
+ return res;
+}
+
+INTERCEPTOR(char *, sl_find, void *sl, const char *item) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sl_find, sl, item);
+ if (sl)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
+ if (item)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, item, internal_strlen(item) + 1);
+ char *res = REAL(sl_find)(sl, item);
+ if (res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1);
+ return res;
+}
+
+INTERCEPTOR(void, sl_free, void *sl, int freeall) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sl_free, sl, freeall);
+ if (sl)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, sl, __sanitizer::struct_StringList_sz);
+ REAL(sl_free)(sl, freeall);
+}
+
+#define INIT_SL_INIT \
+ COMMON_INTERCEPT_FUNCTION(sl_init); \
+ COMMON_INTERCEPT_FUNCTION(sl_add); \
+ COMMON_INTERCEPT_FUNCTION(sl_find); \
+ COMMON_INTERCEPT_FUNCTION(sl_free);
+#else
+#define INIT_SL_INIT
+#endif
+
+#if SANITIZER_INTERCEPT_GETRANDOM
+INTERCEPTOR(SSIZE_T, getrandom, void *buf, SIZE_T buflen, unsigned int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getrandom, buf, buflen, flags);
+ SSIZE_T n = REAL(getrandom)(buf, buflen, flags);
+ if (n > 0) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, n);
+ }
+ return n;
+}
+#define INIT_GETRANDOM COMMON_INTERCEPT_FUNCTION(getrandom)
+#else
+#define INIT_GETRANDOM
+#endif
+
+#if SANITIZER_INTERCEPT_CRYPT
+INTERCEPTOR(char *, crypt, char *key, char *salt) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, crypt, key, salt);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
+ char *res = REAL(crypt)(key, salt);
+ if (res != nullptr)
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+ return res;
+}
+#define INIT_CRYPT COMMON_INTERCEPT_FUNCTION(crypt);
+#else
+#define INIT_CRYPT
+#endif
+
+#if SANITIZER_INTERCEPT_CRYPT_R
+INTERCEPTOR(char *, crypt_r, char *key, char *salt, void *data) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, crypt_r, key, salt, data);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, key, internal_strlen(key) + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, salt, internal_strlen(salt) + 1);
+ char *res = REAL(crypt_r)(key, salt, data);
+ if (res != nullptr) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data,
+ __sanitizer::struct_crypt_data_sz);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, internal_strlen(res) + 1);
+ }
+ return res;
+}
+#define INIT_CRYPT_R COMMON_INTERCEPT_FUNCTION(crypt_r);
+#else
+#define INIT_CRYPT_R
+#endif
+
+#if SANITIZER_INTERCEPT_GETENTROPY
+INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getentropy, buf, buflen);
+ int r = REAL(getentropy)(buf, buflen);
+ if (r == 0) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
+ }
+ return r;
+}
+#define INIT_GETENTROPY COMMON_INTERCEPT_FUNCTION(getentropy)
+#else
+#define INIT_GETENTROPY
+#endif
+
+#if SANITIZER_INTERCEPT_QSORT_R
+typedef int (*qsort_r_compar_f)(const void *, const void *, void *);
+struct qsort_r_compar_params {
+ SIZE_T size;
+ qsort_r_compar_f compar;
+ void *arg;
+};
+static int wrapped_qsort_r_compar(const void *a, const void *b, void *arg) {
+ qsort_r_compar_params *params = (qsort_r_compar_params *)arg;
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, params->size);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, params->size);
+ return params->compar(a, b, params->arg);
+}
+
+INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
+ qsort_r_compar_f compar, void *arg) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, qsort_r, base, nmemb, size, compar, arg);
+ // Run the comparator over all array elements to detect any memory issues.
+ if (nmemb > 1) {
+ for (SIZE_T i = 0; i < nmemb - 1; ++i) {
+ void *p = (void *)((char *)base + i * size);
+ void *q = (void *)((char *)base + (i + 1) * size);
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
+ compar(p, q, arg);
+ }
+ }
+ qsort_r_compar_params params = {size, compar, arg};
+ REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, &params);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
+}
+# define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r)
+#else
+# define INIT_QSORT_R
+#endif
+
+#if SANITIZER_INTERCEPT_QSORT && SANITIZER_INTERCEPT_QSORT_R
+INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
+ qsort_r_compar_f compar) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar);
+ WRAP(qsort_r)(base, nmemb, size, compar, nullptr);
+}
+# define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
+#elif SANITIZER_INTERCEPT_QSORT && !SANITIZER_INTERCEPT_QSORT_R
+// Glibc qsort uses a temporary buffer allocated either on stack or on heap.
+// Poisoned memory from there may get copied into the comparator arguments,
+// where it needs to be dealt with. But even that is not enough - the results of
+// the sort may be copied into the input/output array based on the results of
+// the comparator calls, but directly from the temp memory, bypassing the
+// unpoisoning done in wrapped_qsort_compar. We deal with this by, again,
+// unpoisoning the entire array after the sort is done.
+//
+// We can not check that the entire array is initialized at the beginning. IMHO,
+// it's fine for parts of the sorted objects to contain uninitialized memory,
+// ex. as padding in structs.
+typedef int (*qsort_compar_f)(const void *, const void *);
+static THREADLOCAL qsort_compar_f qsort_compar;
+static THREADLOCAL SIZE_T qsort_size;
+static int wrapped_qsort_compar(const void *a, const void *b) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_size);
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_size);
+ return qsort_compar(a, b);
+}
+
+INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
+ qsort_compar_f compar) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar);
+ // Run the comparator over all array elements to detect any memory issues.
+ if (nmemb > 1) {
+ for (SIZE_T i = 0; i < nmemb - 1; ++i) {
+ void *p = (void *)((char *)base + i * size);
+ void *q = (void *)((char *)base + (i + 1) * size);
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
+ compar(p, q);
+ }
+ }
+ qsort_compar_f old_compar = qsort_compar;
+ SIZE_T old_size = qsort_size;
+ // Handle qsort() implementations that recurse using an
+ // interposable function call:
+ bool already_wrapped = compar == wrapped_qsort_compar;
+ if (already_wrapped) {
+ // This case should only happen if the qsort() implementation calls itself
+ // using a preemptible function call (e.g. the FreeBSD libc version).
+ // Check that the size and comparator arguments are as expected.
+ CHECK_NE(compar, qsort_compar);
+ CHECK_EQ(qsort_size, size);
+ } else {
+ qsort_compar = compar;
+ qsort_size = size;
+ }
+ REAL(qsort)(base, nmemb, size, wrapped_qsort_compar);
+ if (!already_wrapped) {
+ qsort_compar = old_compar;
+ qsort_size = old_size;
+ }
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
+}
+# define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
+#else
+# define INIT_QSORT
+#endif
+
+#if SANITIZER_INTERCEPT_BSEARCH
+typedef int (*bsearch_compar_f)(const void *, const void *);
+struct bsearch_compar_params {
+ const void *key;
+ bsearch_compar_f compar;
+};
+
+static int wrapped_bsearch_compar(const void *key, const void *b) {
+ const bsearch_compar_params *params = (const bsearch_compar_params *)key;
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
+ return params->compar(params->key, b);
+}
+
+INTERCEPTOR(void *, bsearch, const void *key, const void *base, SIZE_T nmemb,
+ SIZE_T size, bsearch_compar_f compar) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, bsearch, key, base, nmemb, size, compar);
+ bsearch_compar_params params = {key, compar};
+ return REAL(bsearch)(&params, base, nmemb, size, wrapped_bsearch_compar);
+}
+# define INIT_BSEARCH COMMON_INTERCEPT_FUNCTION(bsearch)
+#else
+# define INIT_BSEARCH
+#endif
+
+#if SANITIZER_INTERCEPT_SIGALTSTACK
+INTERCEPTOR(int, sigaltstack, void *ss, void *oss) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigaltstack, ss, oss);
+ int r = REAL(sigaltstack)(ss, oss);
+ if (r == 0 && oss != nullptr) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oss, struct_stack_t_sz);
+ }
+ return r;
+}
+#define INIT_SIGALTSTACK COMMON_INTERCEPT_FUNCTION(sigaltstack)
+#else
+#define INIT_SIGALTSTACK
+#endif
+
+#if SANITIZER_INTERCEPT_PROCCTL
+INTERCEPTOR(int, procctl, int idtype, u64 id, int cmd, uptr data) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, procctl, idtype, id, cmd, data);
+ static const int PROC_REAP_ACQUIRE = 2;
+ static const int PROC_REAP_RELEASE = 3;
+ static const int PROC_REAP_STATUS = 4;
+ static const int PROC_REAP_GETPIDS = 5;
+ static const int PROC_REAP_KILL = 6;
+ if (cmd < PROC_REAP_ACQUIRE || cmd > PROC_REAP_KILL) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, sizeof(int));
+ } else {
+ // reap_acquire/reap_release bears no arguments.
+ if (cmd > PROC_REAP_RELEASE) {
+ unsigned int reapsz;
+ switch (cmd) {
+ case PROC_REAP_STATUS:
+ reapsz = struct_procctl_reaper_status_sz;
+ break;
+ case PROC_REAP_GETPIDS:
+ reapsz = struct_procctl_reaper_pids_sz;
+ break;
+ case PROC_REAP_KILL:
+ reapsz = struct_procctl_reaper_kill_sz;
+ break;
+ }
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)data, reapsz);
+ }
+ }
+ return REAL(procctl)(idtype, id, cmd, data);
+}
+#define INIT_PROCCTL COMMON_INTERCEPT_FUNCTION(procctl)
+#else
+#define INIT_PROCCTL
+#endif
+
+#if SANITIZER_INTERCEPT_UNAME
+INTERCEPTOR(int, uname, struct utsname *utsname) {
+#if SANITIZER_LINUX
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return internal_uname(utsname);
+#endif
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, uname, utsname);
+ int res = REAL(uname)(utsname);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, utsname,
+ __sanitizer::struct_utsname_sz);
+ return res;
+}
+#define INIT_UNAME COMMON_INTERCEPT_FUNCTION(uname)
+#else
+#define INIT_UNAME
+#endif
+
+#if SANITIZER_INTERCEPT___XUNAME
+// FreeBSD's <sys/utsname.h> define uname() as
+// static __inline int uname(struct utsname *name) {
+// return __xuname(SYS_NMLN, (void*)name);
+// }
+INTERCEPTOR(int, __xuname, int size, void *utsname) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __xuname, size, utsname);
+ int res = REAL(__xuname)(size, utsname);
+ if (!res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, utsname,
+ __sanitizer::struct_utsname_sz);
+ return res;
+}
+#define INIT___XUNAME COMMON_INTERCEPT_FUNCTION(__xuname)
+#else
+#define INIT___XUNAME
+#endif
+
+#if SANITIZER_INTERCEPT_HEXDUMP
+INTERCEPTOR(void, hexdump, const void *ptr, int length, const char *header, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, hexdump, ptr, length, header, flags);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, length);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, header, internal_strlen(header) + 1);
+ REAL(hexdump)(ptr, length, header, flags);
+}
+
+#define INIT_HEXDUMP COMMON_INTERCEPT_FUNCTION(hexdump);
+#else
+#define INIT_HEXDUMP
+#endif
+
+#include "sanitizer_common_interceptors_netbsd_compat.inc"
+
+static void InitializeCommonInterceptors() {
+#if SI_POSIX
+ static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
+ interceptor_metadata_map = new ((void *)&metadata_mem) MetadataHashMap();
+#endif
+
+ INIT_MMAP;
+ INIT_MMAP64;
+ INIT_TEXTDOMAIN;
+ INIT_STRLEN;
+ INIT_STRNLEN;
+ INIT_STRNDUP;
+ INIT___STRNDUP;
+ INIT_STRCMP;
+ INIT_STRNCMP;
+ INIT_STRCASECMP;
+ INIT_STRNCASECMP;
+ INIT_STRSTR;
+ INIT_STRCASESTR;
+ INIT_STRCHR;
+ INIT_STRCHRNUL;
+ INIT_STRRCHR;
+ INIT_STRSPN;
+ INIT_STRTOK;
+ INIT_STRPBRK;
+ INIT_STRXFRM;
+ INIT___STRXFRM_L;
+ INIT_MEMSET;
+ INIT_MEMMOVE;
+ INIT_MEMCPY;
+ INIT_MEMCHR;
+ INIT_MEMCMP;
+ INIT_BCMP;
+ INIT_MEMRCHR;
+ INIT_MEMMEM;
+ INIT_READ;
+ INIT_FREAD;
+ INIT_PREAD;
+ INIT_PREAD64;
+ INIT_READV;
+ INIT_PREADV;
+ INIT_PREADV64;
+ INIT_WRITE;
+ INIT_FWRITE;
+ INIT_PWRITE;
+ INIT_PWRITE64;
+ INIT_WRITEV;
+ INIT_PWRITEV;
+ INIT_PWRITEV64;
+ INIT_FGETS;
+ INIT_FPUTS;
+ INIT_PUTS;
+ INIT_PRCTL;
+ INIT_LOCALTIME_AND_FRIENDS;
+ INIT_STRPTIME;
+ INIT_SCANF;
+ INIT_ISOC99_SCANF;
+ INIT_PRINTF;
+ INIT_PRINTF_L;
+ INIT_ISOC99_PRINTF;
+ INIT_FREXP;
+ INIT_FREXPF_FREXPL;
+ INIT_GETPWNAM_AND_FRIENDS;
+ INIT_GETPWNAM_R_AND_FRIENDS;
+ INIT_GETPWENT;
+ INIT_FGETPWENT;
+ INIT_GETPWENT_R;
+ INIT_FGETPWENT_R;
+ INIT_FGETGRENT_R;
+ INIT_SETPWENT;
+ INIT_CLOCK_GETTIME;
+ INIT_CLOCK_GETCPUCLOCKID;
+ INIT_GETITIMER;
+ INIT_TIME;
+ INIT_GLOB;
+ INIT_GLOB64;
+ INIT___B64_TO;
+ INIT_DN_COMP_EXPAND;
+ INIT_POSIX_SPAWN;
+ INIT_WAIT;
+ INIT_WAIT4;
+ INIT_INET;
+ INIT_PTHREAD_GETSCHEDPARAM;
+ INIT_GETADDRINFO;
+ INIT_GETNAMEINFO;
+ INIT_GETSOCKNAME;
+ INIT_GETHOSTBYNAME;
+ INIT_GETHOSTBYNAME2;
+ INIT_GETHOSTBYNAME_R;
+ INIT_GETHOSTBYNAME2_R;
+ INIT_GETHOSTBYADDR_R;
+ INIT_GETHOSTENT_R;
+ INIT_GETSOCKOPT;
+ INIT_ACCEPT;
+ INIT_ACCEPT4;
+ INIT_PACCEPT;
+ INIT_MODF;
+ INIT_RECVMSG;
+ INIT_SENDMSG;
+ INIT_RECVMMSG;
+ INIT_SENDMMSG;
+ INIT_SYSMSG;
+ INIT_GETPEERNAME;
+ INIT_IOCTL;
+ INIT_INET_ATON;
+ INIT_SYSINFO;
+ INIT_READDIR;
+ INIT_READDIR64;
+ INIT_PTRACE;
+ INIT_SETLOCALE;
+ INIT_GETCWD;
+ INIT_GET_CURRENT_DIR_NAME;
+ INIT_STRTOIMAX;
+ INIT_MBSTOWCS;
+ INIT_MBSNRTOWCS;
+ INIT_WCSTOMBS;
+ INIT_WCSNRTOMBS;
+ INIT_WCRTOMB;
+ INIT_WCTOMB;
+ INIT_TCGETATTR;
+ INIT_REALPATH;
+ INIT_CANONICALIZE_FILE_NAME;
+ INIT_CONFSTR;
+ INIT_SCHED_GETAFFINITY;
+ INIT_SCHED_GETPARAM;
+ INIT_STRERROR;
+ INIT_STRERROR_R;
+ INIT_XPG_STRERROR_R;
+ INIT_SCANDIR;
+ INIT_SCANDIR64;
+ INIT_GETGROUPS;
+ INIT_POLL;
+ INIT_PPOLL;
+ INIT_WORDEXP;
+ INIT_SIGWAIT;
+ INIT_SIGWAITINFO;
+ INIT_SIGTIMEDWAIT;
+ INIT_SIGSETOPS;
+ INIT_SIGSET_LOGICOPS;
+ INIT_SIGPENDING;
+ INIT_SIGPROCMASK;
+ INIT_PTHREAD_SIGMASK;
+ INIT_BACKTRACE;
+ INIT__EXIT;
+ INIT___LIBC_THR_SETCANCELSTATE;
+ INIT_GETMNTENT;
+ INIT_GETMNTENT_R;
+ INIT_STATFS;
+ INIT_STATFS64;
+ INIT_STATVFS;
+ INIT_STATVFS64;
+ INIT_INITGROUPS;
+ INIT_ETHER_NTOA_ATON;
+ INIT_ETHER_HOST;
+ INIT_ETHER_R;
+ INIT_SHMCTL;
+ INIT_RANDOM_R;
+ INIT_PTHREAD_ATTR_GET;
+ INIT_PTHREAD_ATTR_GET_SCHED;
+ INIT_PTHREAD_ATTR_GETINHERITSCHED;
+ INIT_PTHREAD_ATTR_GETAFFINITY_NP;
+ INIT_PTHREAD_GETAFFINITY_NP;
+ INIT_PTHREAD_MUTEXATTR_GETPSHARED;
+ INIT_PTHREAD_MUTEXATTR_GETTYPE;
+ INIT_PTHREAD_MUTEXATTR_GETPROTOCOL;
+ INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING;
+ INIT_PTHREAD_MUTEXATTR_GETROBUST;
+ INIT_PTHREAD_MUTEXATTR_GETROBUST_NP;
+ INIT_PTHREAD_RWLOCKATTR_GETPSHARED;
+ INIT_PTHREAD_RWLOCKATTR_GETKIND_NP;
+ INIT_PTHREAD_CONDATTR_GETPSHARED;
+ INIT_PTHREAD_CONDATTR_GETCLOCK;
+ INIT_PTHREAD_BARRIERATTR_GETPSHARED;
+ INIT_TMPNAM;
+ INIT_TMPNAM_R;
+ INIT_PTSNAME;
+ INIT_PTSNAME_R;
+ INIT_TTYNAME;
+ INIT_TTYNAME_R;
+ INIT_TEMPNAM;
+ INIT_PTHREAD_SETNAME_NP;
+ INIT_PTHREAD_GETNAME_NP;
+ INIT_SINCOS;
+ INIT_REMQUO;
+ INIT_REMQUOL;
+ INIT_LGAMMA;
+ INIT_LGAMMAL;
+ INIT_LGAMMA_R;
+ INIT_LGAMMAL_R;
+ INIT_DRAND48_R;
+ INIT_RAND_R;
+ INIT_GETLINE;
+ INIT_ICONV;
+ INIT_TIMES;
+ INIT_TLS_GET_ADDR;
+ INIT_LISTXATTR;
+ INIT_GETXATTR;
+ INIT_GETRESID;
+ INIT_GETIFADDRS;
+ INIT_IF_INDEXTONAME;
+ INIT_CAPGET;
+ INIT_AEABI_MEM;
+ INIT___BZERO;
+ INIT_BZERO;
+ INIT_FTIME;
+ INIT_XDR;
+ INIT_XDRREC_LINUX;
+ INIT_TSEARCH;
+ INIT_LIBIO_INTERNALS;
+ INIT_FOPEN;
+ INIT_FOPEN64;
+ INIT_FLOPEN;
+ INIT_OPEN_MEMSTREAM;
+ INIT_OBSTACK;
+ INIT_FFLUSH;
+ INIT_FCLOSE;
+ INIT_DLOPEN_DLCLOSE;
+ INIT_GETPASS;
+ INIT_TIMERFD;
+ INIT_MLOCKX;
+ INIT_FOPENCOOKIE;
+ INIT_SEM;
+ INIT_PTHREAD_SETCANCEL;
+ INIT_MINCORE;
+ INIT_PROCESS_VM_READV;
+ INIT_CTERMID;
+ INIT_CTERMID_R;
+ INIT_RECV_RECVFROM;
+ INIT_SEND_SENDTO;
+ INIT_STAT;
+ INIT_STAT64;
+ INIT_EVENTFD_READ_WRITE;
+ INIT_LSTAT;
+ INIT_LSTAT64;
+ INIT___XSTAT;
+ INIT___XSTAT64;
+ INIT___LXSTAT;
+ INIT___LXSTAT64;
+ // FIXME: add other *stat interceptors.
+ INIT_UTMP;
+ INIT_UTMPX;
+ INIT_GETLOADAVG;
+ INIT_WCSLEN;
+ INIT_WCSCAT;
+ INIT_WCSDUP;
+ INIT_WCSXFRM;
+ INIT___WCSXFRM_L;
+ INIT_ACCT;
+ INIT_USER_FROM_UID;
+ INIT_UID_FROM_USER;
+ INIT_GROUP_FROM_GID;
+ INIT_GID_FROM_GROUP;
+ INIT_ACCESS;
+ INIT_FACCESSAT;
+ INIT_GETGROUPLIST;
+ INIT_GETGROUPMEMBERSHIP;
+ INIT_READLINK;
+ INIT_READLINKAT;
+ INIT_NAME_TO_HANDLE_AT;
+ INIT_OPEN_BY_HANDLE_AT;
+ INIT_STRLCPY;
+ INIT_DEVNAME;
+ INIT_DEVNAME_R;
+ INIT_FGETLN;
+ INIT_STRMODE;
+ INIT_TTYENT;
+ INIT_PROTOENT;
+ INIT_PROTOENT_R;
+ INIT_NETENT;
+ INIT_GETMNTINFO;
+ INIT_MI_VECTOR_HASH;
+ INIT_SETVBUF;
+ INIT_GETVFSSTAT;
+ INIT_REGEX;
+ INIT_REGEXSUB;
+ INIT_FTS;
+ INIT_SYSCTL;
+ INIT_ASYSCTL;
+ INIT_SYSCTLGETMIBINFO;
+ INIT_NL_LANGINFO;
+ INIT_MODCTL;
+ INIT_STRTONUM;
+ INIT_FPARSELN;
+ INIT_STATVFS1;
+ INIT_STRTOI;
+ INIT_CAPSICUM;
+ INIT_SHA1;
+ INIT_MD4;
+ INIT_RMD160;
+ INIT_MD5;
+ INIT_FSEEK;
+ INIT_MD2;
+ INIT_SHA2;
+ INIT_VIS;
+ INIT_CDB;
+ INIT_GETFSENT;
+ INIT_ARC4RANDOM;
+ INIT_POPEN;
+ INIT_POPENVE;
+ INIT_PCLOSE;
+ INIT_FUNOPEN;
+ INIT_FUNOPEN2;
+ INIT_FDEVNAME;
+ INIT_GETUSERSHELL;
+ INIT_SL_INIT;
+ INIT_GETRANDOM;
+ INIT_CRYPT;
+ INIT_CRYPT_R;
+ INIT_GETENTROPY;
+ INIT_QSORT;
+ INIT_QSORT_R;
+ INIT_BSEARCH;
+ INIT_SIGALTSTACK;
+ INIT_PROCCTL
+ INIT_UNAME;
+ INIT___XUNAME;
+ INIT_HEXDUMP;
+
+ INIT___PRINTF_CHK;
+}
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc
new file mode 100644
index 00000000000..220abb89c3b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc
@@ -0,0 +1,568 @@
+//===-- sanitizer_common_interceptors_format.inc ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Scanf/printf implementation for use in *Sanitizer interceptors.
+// Follows http://pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html
+// and http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
+// with a few common GNU extensions.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdarg.h>
+
+static const char *parse_number(const char *p, int *out) {
+ *out = internal_atoll(p);
+ while (*p >= '0' && *p <= '9')
+ ++p;
+ return p;
+}
+
+static const char *maybe_parse_param_index(const char *p, int *out) {
+ // n$
+ if (*p >= '0' && *p <= '9') {
+ int number;
+ const char *q = parse_number(p, &number);
+ CHECK(q);
+ if (*q == '$') {
+ *out = number;
+ p = q + 1;
+ }
+ }
+
+ // Otherwise, do not change p. This will be re-parsed later as the field
+ // width.
+ return p;
+}
+
+static bool char_is_one_of(char c, const char *s) {
+ return !!internal_strchr(s, c);
+}
+
+static const char *maybe_parse_length_modifier(const char *p, char ll[2]) {
+ if (char_is_one_of(*p, "jztLq")) {
+ ll[0] = *p;
+ ++p;
+ } else if (*p == 'h') {
+ ll[0] = 'h';
+ ++p;
+ if (*p == 'h') {
+ ll[1] = 'h';
+ ++p;
+ }
+ } else if (*p == 'l') {
+ ll[0] = 'l';
+ ++p;
+ if (*p == 'l') {
+ ll[1] = 'l';
+ ++p;
+ }
+ }
+ return p;
+}
+
+// Returns true if the character is an integer conversion specifier.
+static bool format_is_integer_conv(char c) {
+ return char_is_one_of(c, "diouxXn");
+}
+
+// Returns true if the character is an floating point conversion specifier.
+static bool format_is_float_conv(char c) {
+ return char_is_one_of(c, "aAeEfFgG");
+}
+
+// Returns string output character size for string-like conversions,
+// or 0 if the conversion is invalid.
+static int format_get_char_size(char convSpecifier,
+ const char lengthModifier[2]) {
+ if (char_is_one_of(convSpecifier, "CS")) {
+ return sizeof(wchar_t);
+ }
+
+ if (char_is_one_of(convSpecifier, "cs[")) {
+ if (lengthModifier[0] == 'l' && lengthModifier[1] == '\0')
+ return sizeof(wchar_t);
+ else if (lengthModifier[0] == '\0')
+ return sizeof(char);
+ }
+
+ return 0;
+}
+
+enum FormatStoreSize {
+ // Store size not known in advance; can be calculated as wcslen() of the
+ // destination buffer.
+ FSS_WCSLEN = -2,
+ // Store size not known in advance; can be calculated as strlen() of the
+ // destination buffer.
+ FSS_STRLEN = -1,
+ // Invalid conversion specifier.
+ FSS_INVALID = 0
+};
+
+// Returns the memory size of a format directive (if >0), or a value of
+// FormatStoreSize.
+static int format_get_value_size(char convSpecifier,
+ const char lengthModifier[2],
+ bool promote_float) {
+ if (format_is_integer_conv(convSpecifier)) {
+ switch (lengthModifier[0]) {
+ case 'h':
+ return lengthModifier[1] == 'h' ? sizeof(char) : sizeof(short);
+ case 'l':
+ return lengthModifier[1] == 'l' ? sizeof(long long) : sizeof(long);
+ case 'q':
+ return sizeof(long long);
+ case 'L':
+ return sizeof(long long);
+ case 'j':
+ return sizeof(INTMAX_T);
+ case 'z':
+ return sizeof(SIZE_T);
+ case 't':
+ return sizeof(PTRDIFF_T);
+ case 0:
+ return sizeof(int);
+ default:
+ return FSS_INVALID;
+ }
+ }
+
+ if (format_is_float_conv(convSpecifier)) {
+ switch (lengthModifier[0]) {
+ case 'L':
+ case 'q':
+ return sizeof(long double);
+ case 'l':
+ return lengthModifier[1] == 'l' ? sizeof(long double)
+ : sizeof(double);
+ case 0:
+ // Printf promotes floats to doubles but scanf does not
+ return promote_float ? sizeof(double) : sizeof(float);
+ default:
+ return FSS_INVALID;
+ }
+ }
+
+ if (convSpecifier == 'p') {
+ if (lengthModifier[0] != 0)
+ return FSS_INVALID;
+ return sizeof(void *);
+ }
+
+ return FSS_INVALID;
+}
+
+struct ScanfDirective {
+ int argIdx; // argument index, or -1 if not specified ("%n$")
+ int fieldWidth;
+ const char *begin;
+ const char *end;
+ bool suppressed; // suppress assignment ("*")
+ bool allocate; // allocate space ("m")
+ char lengthModifier[2];
+ char convSpecifier;
+ bool maybeGnuMalloc;
+};
+
+// Parse scanf format string. If a valid directive in encountered, it is
+// returned in dir. This function returns the pointer to the first
+// unprocessed character, or 0 in case of error.
+// In case of the end-of-string, a pointer to the closing \0 is returned.
+static const char *scanf_parse_next(const char *p, bool allowGnuMalloc,
+ ScanfDirective *dir) {
+ internal_memset(dir, 0, sizeof(*dir));
+ dir->argIdx = -1;
+
+ while (*p) {
+ if (*p != '%') {
+ ++p;
+ continue;
+ }
+ dir->begin = p;
+ ++p;
+ // %%
+ if (*p == '%') {
+ ++p;
+ continue;
+ }
+ if (*p == '\0') {
+ return nullptr;
+ }
+ // %n$
+ p = maybe_parse_param_index(p, &dir->argIdx);
+ CHECK(p);
+ // *
+ if (*p == '*') {
+ dir->suppressed = true;
+ ++p;
+ }
+ // Field width
+ if (*p >= '0' && *p <= '9') {
+ p = parse_number(p, &dir->fieldWidth);
+ CHECK(p);
+ if (dir->fieldWidth <= 0) // Width if at all must be non-zero
+ return nullptr;
+ }
+ // m
+ if (*p == 'm') {
+ dir->allocate = true;
+ ++p;
+ }
+ // Length modifier.
+ p = maybe_parse_length_modifier(p, dir->lengthModifier);
+ // Conversion specifier.
+ dir->convSpecifier = *p++;
+ // Consume %[...] expression.
+ if (dir->convSpecifier == '[') {
+ if (*p == '^')
+ ++p;
+ if (*p == ']')
+ ++p;
+ while (*p && *p != ']')
+ ++p;
+ if (*p == 0)
+ return nullptr; // unexpected end of string
+ // Consume the closing ']'.
+ ++p;
+ }
+ // This is unfortunately ambiguous between old GNU extension
+ // of %as, %aS and %a[...] and newer POSIX %a followed by
+ // letters s, S or [.
+ if (allowGnuMalloc && dir->convSpecifier == 'a' &&
+ !dir->lengthModifier[0]) {
+ if (*p == 's' || *p == 'S') {
+ dir->maybeGnuMalloc = true;
+ ++p;
+ } else if (*p == '[') {
+ // Watch for %a[h-j%d], if % appears in the
+ // [...] range, then we need to give up, we don't know
+ // if scanf will parse it as POSIX %a [h-j %d ] or
+ // GNU allocation of string with range dh-j plus %.
+ const char *q = p + 1;
+ if (*q == '^')
+ ++q;
+ if (*q == ']')
+ ++q;
+ while (*q && *q != ']' && *q != '%')
+ ++q;
+ if (*q == 0 || *q == '%')
+ return nullptr;
+ p = q + 1; // Consume the closing ']'.
+ dir->maybeGnuMalloc = true;
+ }
+ }
+ dir->end = p;
+ break;
+ }
+ return p;
+}
+
+static int scanf_get_value_size(ScanfDirective *dir) {
+ if (dir->allocate) {
+ if (!char_is_one_of(dir->convSpecifier, "cCsS["))
+ return FSS_INVALID;
+ return sizeof(char *);
+ }
+
+ if (dir->maybeGnuMalloc) {
+ if (dir->convSpecifier != 'a' || dir->lengthModifier[0])
+ return FSS_INVALID;
+ // This is ambiguous, so check the smaller size of char * (if it is
+ // a GNU extension of %as, %aS or %a[...]) and float (if it is
+ // POSIX %a followed by s, S or [ letters).
+ return sizeof(char *) < sizeof(float) ? sizeof(char *) : sizeof(float);
+ }
+
+ if (char_is_one_of(dir->convSpecifier, "cCsS[")) {
+ bool needsTerminator = char_is_one_of(dir->convSpecifier, "sS[");
+ unsigned charSize =
+ format_get_char_size(dir->convSpecifier, dir->lengthModifier);
+ if (charSize == 0)
+ return FSS_INVALID;
+ if (dir->fieldWidth == 0) {
+ if (!needsTerminator)
+ return charSize;
+ return (charSize == sizeof(char)) ? FSS_STRLEN : FSS_WCSLEN;
+ }
+ return (dir->fieldWidth + needsTerminator) * charSize;
+ }
+
+ return format_get_value_size(dir->convSpecifier, dir->lengthModifier, false);
+}
+
+// Common part of *scanf interceptors.
+// Process format string and va_list, and report all store ranges.
+// Stops when "consuming" n_inputs input items.
+static void scanf_common(void *ctx, int n_inputs, bool allowGnuMalloc,
+ const char *format, va_list aq) {
+ CHECK_GT(n_inputs, 0);
+ const char *p = format;
+
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
+
+ while (*p) {
+ ScanfDirective dir;
+ p = scanf_parse_next(p, allowGnuMalloc, &dir);
+ if (!p)
+ break;
+ if (dir.convSpecifier == 0) {
+ // This can only happen at the end of the format string.
+ CHECK_EQ(*p, 0);
+ break;
+ }
+ // Here the directive is valid. Do what it says.
+ if (dir.argIdx != -1) {
+ // Unsupported.
+ break;
+ }
+ if (dir.suppressed)
+ continue;
+ int size = scanf_get_value_size(&dir);
+ if (size == FSS_INVALID) {
+ Report("%s: WARNING: unexpected format specifier in scanf interceptor: %.*s\n",
+ SanitizerToolName, static_cast<int>(dir.end - dir.begin), dir.begin);
+ break;
+ }
+ void *argp = va_arg(aq, void *);
+ if (dir.convSpecifier != 'n')
+ --n_inputs;
+ if (n_inputs < 0)
+ break;
+ if (size == FSS_STRLEN) {
+ size = internal_strlen((const char *)argp) + 1;
+ } else if (size == FSS_WCSLEN) {
+ // FIXME: actually use wcslen() to calculate it.
+ size = 0;
+ }
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, argp, size);
+ // For %ms/%mc, write the allocated output buffer as well.
+ if (dir.allocate) {
+ char *buf = *(char **)argp;
+ if (buf)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, internal_strlen(buf) + 1);
+ }
+ }
+}
+
+#if SANITIZER_INTERCEPT_PRINTF
+
+struct PrintfDirective {
+ int fieldWidth;
+ int fieldPrecision;
+ int argIdx; // width argument index, or -1 if not specified ("%*n$")
+ int precisionIdx; // precision argument index, or -1 if not specified (".*n$")
+ const char *begin;
+ const char *end;
+ bool starredWidth;
+ bool starredPrecision;
+ char lengthModifier[2];
+ char convSpecifier;
+};
+
+static const char *maybe_parse_number(const char *p, int *out) {
+ if (*p >= '0' && *p <= '9')
+ p = parse_number(p, out);
+ return p;
+}
+
+static const char *maybe_parse_number_or_star(const char *p, int *out,
+ bool *star) {
+ if (*p == '*') {
+ *star = true;
+ ++p;
+ } else {
+ *star = false;
+ p = maybe_parse_number(p, out);
+ }
+ return p;
+}
+
+// Parse printf format string. Same as scanf_parse_next.
+static const char *printf_parse_next(const char *p, PrintfDirective *dir) {
+ internal_memset(dir, 0, sizeof(*dir));
+ dir->argIdx = -1;
+ dir->precisionIdx = -1;
+
+ while (*p) {
+ if (*p != '%') {
+ ++p;
+ continue;
+ }
+ dir->begin = p;
+ ++p;
+ // %%
+ if (*p == '%') {
+ ++p;
+ continue;
+ }
+ if (*p == '\0') {
+ return nullptr;
+ }
+ // %n$
+ p = maybe_parse_param_index(p, &dir->precisionIdx);
+ CHECK(p);
+ // Flags
+ while (char_is_one_of(*p, "'-+ #0")) {
+ ++p;
+ }
+ // Field width
+ p = maybe_parse_number_or_star(p, &dir->fieldWidth,
+ &dir->starredWidth);
+ if (!p)
+ return nullptr;
+ // Precision
+ if (*p == '.') {
+ ++p;
+ // Actual precision is optional (surprise!)
+ p = maybe_parse_number_or_star(p, &dir->fieldPrecision,
+ &dir->starredPrecision);
+ if (!p)
+ return nullptr;
+ // m$
+ if (dir->starredPrecision) {
+ p = maybe_parse_param_index(p, &dir->precisionIdx);
+ CHECK(p);
+ }
+ }
+ // Length modifier.
+ p = maybe_parse_length_modifier(p, dir->lengthModifier);
+ // Conversion specifier.
+ dir->convSpecifier = *p++;
+ dir->end = p;
+ break;
+ }
+ return p;
+}
+
+static int printf_get_value_size(PrintfDirective *dir) {
+ if (char_is_one_of(dir->convSpecifier, "cCsS")) {
+ unsigned charSize =
+ format_get_char_size(dir->convSpecifier, dir->lengthModifier);
+ if (charSize == 0)
+ return FSS_INVALID;
+ if (char_is_one_of(dir->convSpecifier, "sS")) {
+ return (charSize == sizeof(char)) ? FSS_STRLEN : FSS_WCSLEN;
+ }
+ return charSize;
+ }
+
+ return format_get_value_size(dir->convSpecifier, dir->lengthModifier, true);
+}
+
+#define SKIP_SCALAR_ARG(aq, convSpecifier, size) \
+ do { \
+ if (format_is_float_conv(convSpecifier)) { \
+ switch (size) { \
+ case 8: \
+ va_arg(*aq, double); \
+ break; \
+ case 12: \
+ va_arg(*aq, long double); \
+ break; \
+ case 16: \
+ va_arg(*aq, long double); \
+ break; \
+ default: \
+ Report("WARNING: unexpected floating-point arg size" \
+ " in printf interceptor: %zu\n", static_cast<uptr>(size)); \
+ return; \
+ } \
+ } else { \
+ switch (size) { \
+ case 1: \
+ case 2: \
+ case 4: \
+ va_arg(*aq, u32); \
+ break; \
+ case 8: \
+ va_arg(*aq, u64); \
+ break; \
+ default: \
+ Report("WARNING: unexpected arg size" \
+ " in printf interceptor: %zu\n", static_cast<uptr>(size)); \
+ return; \
+ } \
+ } \
+ } while (0)
+
+// Common part of *printf interceptors.
+// Process format string and va_list, and report all load ranges.
+static void printf_common(void *ctx, const char *format, va_list aq) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, format, internal_strlen(format) + 1);
+
+ const char *p = format;
+
+ while (*p) {
+ PrintfDirective dir;
+ p = printf_parse_next(p, &dir);
+ if (!p)
+ break;
+ if (dir.convSpecifier == 0) {
+ // This can only happen at the end of the format string.
+ CHECK_EQ(*p, 0);
+ break;
+ }
+ // Here the directive is valid. Do what it says.
+ if (dir.argIdx != -1 || dir.precisionIdx != -1) {
+ // Unsupported.
+ break;
+ }
+ if (dir.starredWidth) {
+ // Dynamic width
+ SKIP_SCALAR_ARG(&aq, 'd', sizeof(int));
+ }
+ if (dir.starredPrecision) {
+ // Dynamic precision
+ SKIP_SCALAR_ARG(&aq, 'd', sizeof(int));
+ }
+ // %m does not require an argument: strlen(errno).
+ if (dir.convSpecifier == 'm')
+ continue;
+ int size = printf_get_value_size(&dir);
+ if (size == FSS_INVALID) {
+ static int ReportedOnce;
+ if (!ReportedOnce++)
+ Report(
+ "%s: WARNING: unexpected format specifier in printf "
+ "interceptor: %.*s (reported once per process)\n",
+ SanitizerToolName, static_cast<int>(dir.end - dir.begin), dir.begin);
+ break;
+ }
+ if (dir.convSpecifier == 'n') {
+ void *argp = va_arg(aq, void *);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, argp, size);
+ continue;
+ } else if (size == FSS_STRLEN) {
+ if (void *argp = va_arg(aq, void *)) {
+ if (dir.starredPrecision) {
+ // FIXME: properly support starred precision for strings.
+ size = 0;
+ } else if (dir.fieldPrecision > 0) {
+ // Won't read more than "precision" symbols.
+ size = internal_strnlen((const char *)argp, dir.fieldPrecision);
+ if (size < dir.fieldPrecision) size++;
+ } else {
+ // Whole string will be accessed.
+ size = internal_strlen((const char *)argp) + 1;
+ }
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, size);
+ }
+ } else if (size == FSS_WCSLEN) {
+ if (void *argp = va_arg(aq, void *)) {
+ // FIXME: Properly support wide-character strings (via wcsrtombs).
+ size = 0;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, argp, size);
+ }
+ } else {
+ // Skip non-pointer args
+ SKIP_SCALAR_ARG(&aq, dir.convSpecifier, size);
+ }
+ }
+}
+
+#endif // SANITIZER_INTERCEPT_PRINTF
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
new file mode 100644
index 00000000000..49ec4097c90
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
@@ -0,0 +1,612 @@
+//===-- sanitizer_common_interceptors_ioctl.inc -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Ioctl handling in common sanitizer interceptors.
+//===----------------------------------------------------------------------===//
+
+#if !SANITIZER_NETBSD
+
+#include "sanitizer_flags.h"
+
+struct ioctl_desc {
+ unsigned req;
+ // FIXME: support read+write arguments. Currently READWRITE and WRITE do the
+ // same thing.
+ // XXX: The declarations below may use WRITE instead of READWRITE, unless
+ // explicitly noted.
+ enum {
+ NONE,
+ READ,
+ WRITE,
+ READWRITE,
+ CUSTOM
+ } type : 3;
+ unsigned size : 29;
+ const char* name;
+};
+
+const unsigned ioctl_table_max = 500;
+static ioctl_desc ioctl_table[ioctl_table_max];
+static unsigned ioctl_table_size = 0;
+
+// This can not be declared as a global, because references to struct_*_sz
+// require a global initializer. And this table must be available before global
+// initializers are run.
+static void ioctl_table_fill() {
+#define _(rq, tp, sz) \
+ if (IOCTL_##rq != IOCTL_NOT_PRESENT) { \
+ CHECK(ioctl_table_size < ioctl_table_max); \
+ ioctl_table[ioctl_table_size].req = IOCTL_##rq; \
+ ioctl_table[ioctl_table_size].type = ioctl_desc::tp; \
+ ioctl_table[ioctl_table_size].size = sz; \
+ ioctl_table[ioctl_table_size].name = #rq; \
+ ++ioctl_table_size; \
+ }
+
+ _(FIOASYNC, READ, sizeof(int));
+ _(FIOCLEX, NONE, 0);
+ _(FIOGETOWN, WRITE, sizeof(int));
+ _(FIONBIO, READ, sizeof(int));
+ _(FIONCLEX, NONE, 0);
+ _(FIOSETOWN, READ, sizeof(int));
+ _(SIOCATMARK, WRITE, sizeof(int));
+ _(SIOCGIFCONF, CUSTOM, 0);
+ _(SIOCGPGRP, WRITE, sizeof(int));
+ _(SIOCSPGRP, READ, sizeof(int));
+#if !SANITIZER_SOLARIS
+ _(TIOCCONS, NONE, 0);
+#endif
+ _(TIOCEXCL, NONE, 0);
+ _(TIOCGETD, WRITE, sizeof(int));
+ _(TIOCGPGRP, WRITE, pid_t_sz);
+ _(TIOCGWINSZ, WRITE, struct_winsize_sz);
+ _(TIOCMBIC, READ, sizeof(int));
+ _(TIOCMBIS, READ, sizeof(int));
+ _(TIOCMGET, WRITE, sizeof(int));
+ _(TIOCMSET, READ, sizeof(int));
+ _(TIOCNOTTY, NONE, 0);
+ _(TIOCNXCL, NONE, 0);
+ _(TIOCOUTQ, WRITE, sizeof(int));
+ _(TIOCPKT, READ, sizeof(int));
+ _(TIOCSCTTY, NONE, 0);
+ _(TIOCSETD, READ, sizeof(int));
+ _(TIOCSPGRP, READ, pid_t_sz);
+ _(TIOCSTI, READ, sizeof(char));
+ _(TIOCSWINSZ, READ, struct_winsize_sz);
+
+#if !SANITIZER_IOS
+ _(SIOCADDMULTI, READ, struct_ifreq_sz);
+ _(SIOCDELMULTI, READ, struct_ifreq_sz);
+ _(SIOCGIFADDR, WRITE, struct_ifreq_sz);
+ _(SIOCGIFBRDADDR, WRITE, struct_ifreq_sz);
+ _(SIOCGIFDSTADDR, WRITE, struct_ifreq_sz);
+ _(SIOCGIFFLAGS, WRITE, struct_ifreq_sz);
+ _(SIOCGIFMETRIC, WRITE, struct_ifreq_sz);
+ _(SIOCGIFMTU, WRITE, struct_ifreq_sz);
+ _(SIOCGIFNETMASK, WRITE, struct_ifreq_sz);
+ _(SIOCSIFADDR, READ, struct_ifreq_sz);
+ _(SIOCSIFBRDADDR, READ, struct_ifreq_sz);
+ _(SIOCSIFDSTADDR, READ, struct_ifreq_sz);
+ _(SIOCSIFFLAGS, READ, struct_ifreq_sz);
+ _(SIOCSIFMETRIC, READ, struct_ifreq_sz);
+ _(SIOCSIFMTU, READ, struct_ifreq_sz);
+ _(SIOCSIFNETMASK, READ, struct_ifreq_sz);
+#endif
+
+#if (SANITIZER_LINUX && !SANITIZER_ANDROID)
+ _(SIOCGETSGCNT, WRITE, struct_sioc_sg_req_sz);
+ _(SIOCGETVIFCNT, WRITE, struct_sioc_vif_req_sz);
+#endif
+
+#if SANITIZER_LINUX
+ // Conflicting request ids.
+ // _(CDROMAUDIOBUFSIZ, NONE, 0);
+ // _(SNDCTL_TMR_CONTINUE, NONE, 0);
+ // _(SNDCTL_TMR_START, NONE, 0);
+ // _(SNDCTL_TMR_STOP, NONE, 0);
+ // _(SOUND_MIXER_READ_LOUD, WRITE, sizeof(int)); // same as ...READ_ENHANCE
+ // _(SOUND_MIXER_READ_MUTE, WRITE, sizeof(int)); // same as ...READ_ENHANCE
+ // _(SOUND_MIXER_WRITE_LOUD, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE
+ // _(SOUND_MIXER_WRITE_MUTE, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE
+ _(BLKFLSBUF, NONE, 0);
+ _(BLKGETSIZE, WRITE, sizeof(uptr));
+ _(BLKRAGET, WRITE, sizeof(uptr));
+ _(BLKRASET, NONE, 0);
+ _(BLKROGET, WRITE, sizeof(int));
+ _(BLKROSET, READ, sizeof(int));
+ _(BLKRRPART, NONE, 0);
+ _(BLKFRASET, NONE, 0);
+ _(BLKFRAGET, WRITE, sizeof(uptr));
+ _(BLKSECTSET, READ, sizeof(short));
+ _(BLKSECTGET, WRITE, sizeof(short));
+ _(BLKSSZGET, WRITE, sizeof(int));
+ _(BLKBSZGET, WRITE, sizeof(int));
+ _(BLKBSZSET, READ, sizeof(uptr));
+ _(BLKGETSIZE64, WRITE, sizeof(u64));
+ _(CDROMEJECT, NONE, 0);
+ _(CDROMEJECT_SW, NONE, 0);
+ _(CDROMMULTISESSION, WRITE, struct_cdrom_multisession_sz);
+ _(CDROMPAUSE, NONE, 0);
+ _(CDROMPLAYMSF, READ, struct_cdrom_msf_sz);
+ _(CDROMPLAYTRKIND, READ, struct_cdrom_ti_sz);
+ _(CDROMREADAUDIO, READ, struct_cdrom_read_audio_sz);
+ _(CDROMREADCOOKED, READ, struct_cdrom_msf_sz);
+ _(CDROMREADMODE1, READ, struct_cdrom_msf_sz);
+ _(CDROMREADMODE2, READ, struct_cdrom_msf_sz);
+ _(CDROMREADRAW, READ, struct_cdrom_msf_sz);
+ _(CDROMREADTOCENTRY, WRITE, struct_cdrom_tocentry_sz);
+ _(CDROMREADTOCHDR, WRITE, struct_cdrom_tochdr_sz);
+ _(CDROMRESET, NONE, 0);
+ _(CDROMRESUME, NONE, 0);
+ _(CDROMSEEK, READ, struct_cdrom_msf_sz);
+ _(CDROMSTART, NONE, 0);
+ _(CDROMSTOP, NONE, 0);
+ _(CDROMSUBCHNL, WRITE, struct_cdrom_subchnl_sz);
+ _(CDROMVOLCTRL, READ, struct_cdrom_volctrl_sz);
+ _(CDROMVOLREAD, WRITE, struct_cdrom_volctrl_sz);
+ _(CDROM_GET_UPC, WRITE, 8);
+ _(EVIOCGABS, WRITE, struct_input_absinfo_sz); // fixup
+ _(EVIOCGBIT, WRITE, struct_input_id_sz); // fixup
+ _(EVIOCGEFFECTS, WRITE, sizeof(int));
+ _(EVIOCGID, WRITE, struct_input_id_sz);
+ _(EVIOCGKEY, WRITE, 0);
+ _(EVIOCGKEYCODE, WRITE, sizeof(int) * 2);
+ _(EVIOCGLED, WRITE, 0);
+ _(EVIOCGNAME, WRITE, 0);
+ _(EVIOCGPHYS, WRITE, 0);
+ _(EVIOCGRAB, READ, sizeof(int));
+ _(EVIOCGREP, WRITE, sizeof(int) * 2);
+ _(EVIOCGSND, WRITE, 0);
+ _(EVIOCGSW, WRITE, 0);
+ _(EVIOCGUNIQ, WRITE, 0);
+ _(EVIOCGVERSION, WRITE, sizeof(int));
+ _(EVIOCRMFF, READ, sizeof(int));
+ _(EVIOCSABS, READ, struct_input_absinfo_sz); // fixup
+ _(EVIOCSFF, READ, struct_ff_effect_sz);
+ _(EVIOCSKEYCODE, READ, sizeof(int) * 2);
+ _(EVIOCSREP, READ, sizeof(int) * 2);
+ _(FDCLRPRM, NONE, 0);
+ _(FDDEFPRM, READ, struct_floppy_struct_sz);
+ _(FDFLUSH, NONE, 0);
+ _(FDFMTBEG, NONE, 0);
+ _(FDFMTEND, NONE, 0);
+ _(FDFMTTRK, READ, struct_format_descr_sz);
+ _(FDGETDRVPRM, WRITE, struct_floppy_drive_params_sz);
+ _(FDGETDRVSTAT, WRITE, struct_floppy_drive_struct_sz);
+ _(FDGETDRVTYP, WRITE, 16);
+ _(FDGETFDCSTAT, WRITE, struct_floppy_fdc_state_sz);
+ _(FDGETMAXERRS, WRITE, struct_floppy_max_errors_sz);
+ _(FDGETPRM, WRITE, struct_floppy_struct_sz);
+ _(FDMSGOFF, NONE, 0);
+ _(FDMSGON, NONE, 0);
+ _(FDPOLLDRVSTAT, WRITE, struct_floppy_drive_struct_sz);
+ _(FDRAWCMD, WRITE, struct_floppy_raw_cmd_sz);
+ _(FDRESET, NONE, 0);
+ _(FDSETDRVPRM, READ, struct_floppy_drive_params_sz);
+ _(FDSETEMSGTRESH, NONE, 0);
+ _(FDSETMAXERRS, READ, struct_floppy_max_errors_sz);
+ _(FDSETPRM, READ, struct_floppy_struct_sz);
+ _(FDTWADDLE, NONE, 0);
+ _(FDWERRORCLR, NONE, 0);
+ _(FDWERRORGET, WRITE, struct_floppy_write_errors_sz);
+ _(HDIO_DRIVE_CMD, WRITE, sizeof(int));
+ _(HDIO_GETGEO, WRITE, struct_hd_geometry_sz);
+ _(HDIO_GET_32BIT, WRITE, sizeof(int));
+ _(HDIO_GET_DMA, WRITE, sizeof(int));
+ _(HDIO_GET_IDENTITY, WRITE, struct_hd_driveid_sz);
+ _(HDIO_GET_KEEPSETTINGS, WRITE, sizeof(int));
+ _(HDIO_GET_MULTCOUNT, WRITE, sizeof(int));
+ _(HDIO_GET_NOWERR, WRITE, sizeof(int));
+ _(HDIO_GET_UNMASKINTR, WRITE, sizeof(int));
+ _(HDIO_SET_32BIT, NONE, 0);
+ _(HDIO_SET_DMA, NONE, 0);
+ _(HDIO_SET_KEEPSETTINGS, NONE, 0);
+ _(HDIO_SET_MULTCOUNT, NONE, 0);
+ _(HDIO_SET_NOWERR, NONE, 0);
+ _(HDIO_SET_UNMASKINTR, NONE, 0);
+ _(MTIOCGET, WRITE, struct_mtget_sz);
+ _(MTIOCPOS, WRITE, struct_mtpos_sz);
+ _(MTIOCTOP, READ, struct_mtop_sz);
+ _(PPPIOCGASYNCMAP, WRITE, sizeof(int));
+ _(PPPIOCGDEBUG, WRITE, sizeof(int));
+ _(PPPIOCGFLAGS, WRITE, sizeof(int));
+ _(PPPIOCGUNIT, WRITE, sizeof(int));
+ _(PPPIOCGXASYNCMAP, WRITE, sizeof(int) * 8);
+ _(PPPIOCSASYNCMAP, READ, sizeof(int));
+ _(PPPIOCSDEBUG, READ, sizeof(int));
+ _(PPPIOCSFLAGS, READ, sizeof(int));
+ _(PPPIOCSMAXCID, READ, sizeof(int));
+ _(PPPIOCSMRU, READ, sizeof(int));
+ _(PPPIOCSXASYNCMAP, READ, sizeof(int) * 8);
+ _(SIOCADDRT, READ, struct_rtentry_sz);
+ _(SIOCDARP, READ, struct_arpreq_sz);
+ _(SIOCDELRT, READ, struct_rtentry_sz);
+ _(SIOCDRARP, READ, struct_arpreq_sz);
+ _(SIOCGARP, WRITE, struct_arpreq_sz);
+ _(SIOCGIFENCAP, WRITE, sizeof(int));
+ _(SIOCGIFHWADDR, WRITE, struct_ifreq_sz);
+ _(SIOCGIFMAP, WRITE, struct_ifreq_sz);
+ _(SIOCGIFMEM, WRITE, struct_ifreq_sz);
+ _(SIOCGIFNAME, NONE, 0);
+ _(SIOCGIFSLAVE, NONE, 0);
+ _(SIOCGRARP, WRITE, struct_arpreq_sz);
+ _(SIOCGSTAMP, WRITE, timeval_sz);
+ _(SIOCSARP, READ, struct_arpreq_sz);
+ _(SIOCSIFENCAP, READ, sizeof(int));
+ _(SIOCSIFHWADDR, READ, struct_ifreq_sz);
+ _(SIOCSIFLINK, NONE, 0);
+ _(SIOCSIFMAP, READ, struct_ifreq_sz);
+ _(SIOCSIFMEM, READ, struct_ifreq_sz);
+ _(SIOCSIFSLAVE, NONE, 0);
+ _(SIOCSRARP, READ, struct_arpreq_sz);
+ _(SNDCTL_COPR_HALT, WRITE, struct_copr_debug_buf_sz);
+ _(SNDCTL_COPR_LOAD, READ, struct_copr_buffer_sz);
+ _(SNDCTL_COPR_RCODE, WRITE, struct_copr_debug_buf_sz);
+ _(SNDCTL_COPR_RCVMSG, WRITE, struct_copr_msg_sz);
+ _(SNDCTL_COPR_RDATA, WRITE, struct_copr_debug_buf_sz);
+ _(SNDCTL_COPR_RESET, NONE, 0);
+ _(SNDCTL_COPR_RUN, WRITE, struct_copr_debug_buf_sz);
+ _(SNDCTL_COPR_SENDMSG, READ, struct_copr_msg_sz);
+ _(SNDCTL_COPR_WCODE, READ, struct_copr_debug_buf_sz);
+ _(SNDCTL_COPR_WDATA, READ, struct_copr_debug_buf_sz);
+ _(SNDCTL_DSP_GETBLKSIZE, WRITE, sizeof(int));
+ _(SNDCTL_DSP_GETFMTS, WRITE, sizeof(int));
+ _(SNDCTL_DSP_NONBLOCK, NONE, 0);
+ _(SNDCTL_DSP_POST, NONE, 0);
+ _(SNDCTL_DSP_RESET, NONE, 0);
+ _(SNDCTL_DSP_SETFMT, WRITE, sizeof(int));
+ _(SNDCTL_DSP_SETFRAGMENT, WRITE, sizeof(int));
+ _(SNDCTL_DSP_SPEED, WRITE, sizeof(int));
+ _(SNDCTL_DSP_STEREO, WRITE, sizeof(int));
+ _(SNDCTL_DSP_SUBDIVIDE, WRITE, sizeof(int));
+ _(SNDCTL_DSP_SYNC, NONE, 0);
+ _(SNDCTL_FM_4OP_ENABLE, READ, sizeof(int));
+ _(SNDCTL_FM_LOAD_INSTR, READ, struct_sbi_instrument_sz);
+ _(SNDCTL_MIDI_INFO, WRITE, struct_midi_info_sz);
+ _(SNDCTL_MIDI_PRETIME, WRITE, sizeof(int));
+ _(SNDCTL_SEQ_CTRLRATE, WRITE, sizeof(int));
+ _(SNDCTL_SEQ_GETINCOUNT, WRITE, sizeof(int));
+ _(SNDCTL_SEQ_GETOUTCOUNT, WRITE, sizeof(int));
+ _(SNDCTL_SEQ_NRMIDIS, WRITE, sizeof(int));
+ _(SNDCTL_SEQ_NRSYNTHS, WRITE, sizeof(int));
+ _(SNDCTL_SEQ_OUTOFBAND, READ, struct_seq_event_rec_sz);
+ _(SNDCTL_SEQ_PANIC, NONE, 0);
+ _(SNDCTL_SEQ_PERCMODE, NONE, 0);
+ _(SNDCTL_SEQ_RESET, NONE, 0);
+ _(SNDCTL_SEQ_RESETSAMPLES, READ, sizeof(int));
+ _(SNDCTL_SEQ_SYNC, NONE, 0);
+ _(SNDCTL_SEQ_TESTMIDI, READ, sizeof(int));
+ _(SNDCTL_SEQ_THRESHOLD, READ, sizeof(int));
+ _(SNDCTL_SYNTH_INFO, WRITE, struct_synth_info_sz);
+ _(SNDCTL_SYNTH_MEMAVL, WRITE, sizeof(int));
+ _(SNDCTL_TMR_METRONOME, READ, sizeof(int));
+ _(SNDCTL_TMR_SELECT, WRITE, sizeof(int));
+ _(SNDCTL_TMR_SOURCE, WRITE, sizeof(int));
+ _(SNDCTL_TMR_TEMPO, WRITE, sizeof(int));
+ _(SNDCTL_TMR_TIMEBASE, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_ALTPCM, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_BASS, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_CAPS, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_CD, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_DEVMASK, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_ENHANCE, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_IGAIN, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_IMIX, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_LINE, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_LINE1, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_LINE2, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_LINE3, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_MIC, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_OGAIN, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_PCM, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_RECLEV, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_RECMASK, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_RECSRC, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_SPEAKER, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_STEREODEVS, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_SYNTH, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_TREBLE, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_VOLUME, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_ALTPCM, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_BASS, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_CD, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_ENHANCE, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_IGAIN, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_IMIX, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_LINE, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_LINE1, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_LINE2, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_LINE3, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_MIC, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_OGAIN, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_PCM, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_RECLEV, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_RECSRC, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_SPEAKER, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_SYNTH, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_TREBLE, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_VOLUME, WRITE, sizeof(int));
+ _(SOUND_PCM_READ_BITS, WRITE, sizeof(int));
+ _(SOUND_PCM_READ_CHANNELS, WRITE, sizeof(int));
+ _(SOUND_PCM_READ_FILTER, WRITE, sizeof(int));
+ _(SOUND_PCM_READ_RATE, WRITE, sizeof(int));
+ _(SOUND_PCM_WRITE_CHANNELS, WRITE, sizeof(int));
+ _(SOUND_PCM_WRITE_FILTER, WRITE, sizeof(int));
+ _(TCFLSH, NONE, 0);
+#if SANITIZER_GLIBC
+ _(TCGETA, WRITE, struct_termio_sz);
+#endif
+ _(TCGETS, WRITE, struct_termios_sz);
+ _(TCSBRK, NONE, 0);
+ _(TCSBRKP, NONE, 0);
+#if SANITIZER_GLIBC
+ _(TCSETA, READ, struct_termio_sz);
+ _(TCSETAF, READ, struct_termio_sz);
+ _(TCSETAW, READ, struct_termio_sz);
+#endif
+ _(TCSETS, READ, struct_termios_sz);
+ _(TCSETSF, READ, struct_termios_sz);
+ _(TCSETSW, READ, struct_termios_sz);
+ _(TCXONC, NONE, 0);
+ _(TIOCGLCKTRMIOS, WRITE, struct_termios_sz);
+ _(TIOCGSOFTCAR, WRITE, sizeof(int));
+ _(TIOCINQ, WRITE, sizeof(int));
+ _(TIOCLINUX, READ, sizeof(char));
+ _(TIOCSERCONFIG, NONE, 0);
+ _(TIOCSERGETLSR, WRITE, sizeof(int));
+ _(TIOCSERGWILD, WRITE, sizeof(int));
+ _(TIOCSERSWILD, READ, sizeof(int));
+ _(TIOCSLCKTRMIOS, READ, struct_termios_sz);
+ _(TIOCSSOFTCAR, READ, sizeof(int));
+ _(VT_ACTIVATE, NONE, 0);
+ _(VT_DISALLOCATE, NONE, 0);
+ _(VT_GETMODE, WRITE, struct_vt_mode_sz);
+ _(VT_GETSTATE, WRITE, struct_vt_stat_sz);
+ _(VT_OPENQRY, WRITE, sizeof(int));
+ _(VT_RELDISP, NONE, 0);
+ _(VT_RESIZE, READ, struct_vt_sizes_sz);
+ _(VT_RESIZEX, READ, struct_vt_consize_sz);
+ _(VT_SENDSIG, NONE, 0);
+ _(VT_SETMODE, READ, struct_vt_mode_sz);
+ _(VT_WAITACTIVE, NONE, 0);
+#endif
+
+#if SANITIZER_GLIBC
+ // _(SIOCDEVPLIP, WRITE, struct_ifreq_sz); // the same as EQL_ENSLAVE
+ _(EQL_EMANCIPATE, WRITE, struct_ifreq_sz);
+ _(EQL_ENSLAVE, WRITE, struct_ifreq_sz);
+ _(EQL_GETMASTRCFG, WRITE, struct_ifreq_sz);
+ _(EQL_GETSLAVECFG, WRITE, struct_ifreq_sz);
+ _(EQL_SETMASTRCFG, WRITE, struct_ifreq_sz);
+ _(EQL_SETSLAVECFG, WRITE, struct_ifreq_sz);
+ _(EVIOCGKEYCODE_V2, WRITE, struct_input_keymap_entry_sz);
+ _(EVIOCGPROP, WRITE, 0);
+ _(EVIOCSKEYCODE_V2, READ, struct_input_keymap_entry_sz);
+ _(FS_IOC_GETFLAGS, WRITE, sizeof(int));
+ _(FS_IOC_GETVERSION, WRITE, sizeof(int));
+ _(FS_IOC_SETFLAGS, READ, sizeof(int));
+ _(FS_IOC_SETVERSION, READ, sizeof(int));
+ _(GIO_CMAP, WRITE, 48);
+ _(GIO_FONT, WRITE, 8192);
+ _(GIO_SCRNMAP, WRITE, e_tabsz);
+ _(GIO_UNIMAP, WRITE, struct_unimapdesc_sz);
+ _(GIO_UNISCRNMAP, WRITE, sizeof(short) * e_tabsz);
+ _(KDADDIO, NONE, 0);
+ _(KDDELIO, NONE, 0);
+ _(KDDISABIO, NONE, 0);
+ _(KDENABIO, NONE, 0);
+ _(KDGETKEYCODE, WRITE, struct_kbkeycode_sz);
+ _(KDGETLED, WRITE, 1);
+ _(KDGETMODE, WRITE, sizeof(int));
+ _(KDGKBDIACR, WRITE, struct_kbdiacrs_sz);
+ _(KDGKBENT, WRITE, struct_kbentry_sz);
+ _(KDGKBLED, WRITE, sizeof(int));
+ _(KDGKBMETA, WRITE, sizeof(int));
+ _(KDGKBMODE, WRITE, sizeof(int));
+ _(KDGKBSENT, WRITE, struct_kbsentry_sz);
+ _(KDGKBTYPE, WRITE, 1);
+ _(KDMAPDISP, NONE, 0);
+ _(KDMKTONE, NONE, 0);
+ _(KDSETKEYCODE, READ, struct_kbkeycode_sz);
+ _(KDSETLED, NONE, 0);
+ _(KDSETMODE, NONE, 0);
+ _(KDSIGACCEPT, NONE, 0);
+ _(KDSKBDIACR, READ, struct_kbdiacrs_sz);
+ _(KDSKBENT, READ, struct_kbentry_sz);
+ _(KDSKBLED, NONE, 0);
+ _(KDSKBMETA, NONE, 0);
+ _(KDSKBMODE, NONE, 0);
+ _(KDSKBSENT, READ, struct_kbsentry_sz);
+ _(KDUNMAPDISP, NONE, 0);
+ _(KIOCSOUND, NONE, 0);
+ _(LPABORT, NONE, 0);
+ _(LPABORTOPEN, NONE, 0);
+ _(LPCAREFUL, NONE, 0);
+ _(LPCHAR, NONE, 0);
+ _(LPGETIRQ, WRITE, sizeof(int));
+ _(LPGETSTATUS, WRITE, sizeof(int));
+ _(LPRESET, NONE, 0);
+ _(LPSETIRQ, NONE, 0);
+ _(LPTIME, NONE, 0);
+ _(LPWAIT, NONE, 0);
+ _(MTIOCGETCONFIG, WRITE, struct_mtconfiginfo_sz);
+ _(MTIOCSETCONFIG, READ, struct_mtconfiginfo_sz);
+ _(PIO_CMAP, NONE, 0);
+ _(PIO_FONT, READ, 8192);
+ _(PIO_SCRNMAP, READ, e_tabsz);
+ _(PIO_UNIMAP, READ, struct_unimapdesc_sz);
+ _(PIO_UNIMAPCLR, READ, struct_unimapinit_sz);
+ _(PIO_UNISCRNMAP, READ, sizeof(short) * e_tabsz);
+ _(SCSI_IOCTL_PROBE_HOST, READ, sizeof(int));
+ _(SCSI_IOCTL_TAGGED_DISABLE, NONE, 0);
+ _(SCSI_IOCTL_TAGGED_ENABLE, NONE, 0);
+ _(SNDCTL_DSP_GETISPACE, WRITE, struct_audio_buf_info_sz);
+ _(SNDCTL_DSP_GETOSPACE, WRITE, struct_audio_buf_info_sz);
+ _(TIOCGSERIAL, WRITE, struct_serial_struct_sz);
+ _(TIOCSERGETMULTI, WRITE, struct_serial_multiport_struct_sz);
+ _(TIOCSERSETMULTI, READ, struct_serial_multiport_struct_sz);
+ _(TIOCSSERIAL, READ, struct_serial_struct_sz);
+
+ // The following ioctl requests are shared between AX25, IPX, netrom and
+ // mrouted.
+ // _(SIOCAIPXITFCRT, READ, sizeof(char));
+ // _(SIOCAX25GETUID, READ, struct_sockaddr_ax25_sz);
+ // _(SIOCNRGETPARMS, WRITE, struct_nr_parms_struct_sz);
+ // _(SIOCAIPXPRISLT, READ, sizeof(char));
+ // _(SIOCNRSETPARMS, READ, struct_nr_parms_struct_sz);
+ // _(SIOCAX25ADDUID, READ, struct_sockaddr_ax25_sz);
+ // _(SIOCNRDECOBS, NONE, 0);
+ // _(SIOCAX25DELUID, READ, struct_sockaddr_ax25_sz);
+ // _(SIOCIPXCFGDATA, WRITE, struct_ipx_config_data_sz);
+ // _(SIOCAX25NOUID, READ, sizeof(int));
+ // _(SIOCNRRTCTL, READ, sizeof(int));
+ // _(SIOCAX25DIGCTL, READ, sizeof(int));
+ // _(SIOCAX25GETPARMS, WRITE, struct_ax25_parms_struct_sz);
+ // _(SIOCAX25SETPARMS, READ, struct_ax25_parms_struct_sz);
+#endif
+#undef _
+}
+
+static bool ioctl_initialized = false;
+
+struct ioctl_desc_compare {
+ bool operator()(const ioctl_desc& left, const ioctl_desc& right) const {
+ return left.req < right.req;
+ }
+};
+
+static void ioctl_init() {
+ ioctl_table_fill();
+ Sort(ioctl_table, ioctl_table_size, ioctl_desc_compare());
+
+ bool bad = false;
+ for (unsigned i = 0; i < ioctl_table_size - 1; ++i) {
+ if (ioctl_table[i].req >= ioctl_table[i + 1].req) {
+ Printf("Duplicate or unsorted ioctl request id %x >= %x (%s vs %s)\n",
+ ioctl_table[i].req, ioctl_table[i + 1].req, ioctl_table[i].name,
+ ioctl_table[i + 1].name);
+ bad = true;
+ }
+ }
+
+ if (bad) Die();
+
+ ioctl_initialized = true;
+}
+
+// Handle the most evil ioctls that encode argument value as part of request id.
+static unsigned ioctl_request_fixup(unsigned req) {
+#if SANITIZER_LINUX
+ // Strip size and event number.
+ const unsigned kEviocgbitMask =
+ (IOC_SIZEMASK << IOC_SIZESHIFT) | EVIOC_EV_MAX;
+ if ((req & ~kEviocgbitMask) == IOCTL_EVIOCGBIT)
+ return IOCTL_EVIOCGBIT;
+ // Strip absolute axis number.
+ if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCGABS)
+ return IOCTL_EVIOCGABS;
+ if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCSABS)
+ return IOCTL_EVIOCSABS;
+#endif
+ return req;
+}
+
+static const ioctl_desc *ioctl_table_lookup(unsigned req) {
+ int left = 0;
+ int right = ioctl_table_size;
+ while (left < right) {
+ int mid = (left + right) / 2;
+ if (ioctl_table[mid].req < req)
+ left = mid + 1;
+ else
+ right = mid;
+ }
+ if (left == right && ioctl_table[left].req == req)
+ return ioctl_table + left;
+ else
+ return nullptr;
+}
+
+static bool ioctl_decode(unsigned req, ioctl_desc *desc) {
+ CHECK(desc);
+ desc->req = req;
+ desc->name = "<DECODED_IOCTL>";
+ desc->size = IOC_SIZE(req);
+ // Sanity check.
+ if (desc->size > 0xFFFF) return false;
+ unsigned dir = IOC_DIR(req);
+ switch (dir) {
+ case IOC_NONE:
+ desc->type = ioctl_desc::NONE;
+ break;
+ case IOC_READ | IOC_WRITE:
+ desc->type = ioctl_desc::READWRITE;
+ break;
+ case IOC_READ:
+ desc->type = ioctl_desc::WRITE;
+ break;
+ case IOC_WRITE:
+ desc->type = ioctl_desc::READ;
+ break;
+ default:
+ return false;
+ }
+ // Size can be 0 iff type is NONE.
+ if ((desc->type == IOC_NONE) != (desc->size == 0)) return false;
+ // Sanity check.
+ if (IOC_TYPE(req) == 0) return false;
+ return true;
+}
+
+static const ioctl_desc *ioctl_lookup(unsigned req) {
+ req = ioctl_request_fixup(req);
+ const ioctl_desc *desc = ioctl_table_lookup(req);
+ if (desc) return desc;
+
+ // Try stripping access size from the request id.
+ desc = ioctl_table_lookup(req & ~(IOC_SIZEMASK << IOC_SIZESHIFT));
+ // Sanity check: requests that encode access size are either read or write and
+ // have size of 0 in the table.
+ if (desc && desc->size == 0 &&
+ (desc->type == ioctl_desc::READWRITE || desc->type == ioctl_desc::WRITE ||
+ desc->type == ioctl_desc::READ))
+ return desc;
+ return nullptr;
+}
+
+static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,
+ unsigned request, void *arg) {
+ if (desc->type == ioctl_desc::READ || desc->type == ioctl_desc::READWRITE) {
+ unsigned size = desc->size ? desc->size : IOC_SIZE(request);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size);
+ }
+ if (desc->type != ioctl_desc::CUSTOM)
+ return;
+ if (request == IOCTL_SIOCGIFCONF) {
+ struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, (char*)&ifc->ifc_len,
+ sizeof(ifc->ifc_len));
+ }
+}
+
+static void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d,
+ unsigned request, void *arg) {
+ if (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READWRITE) {
+ // FIXME: add verbose output
+ unsigned size = desc->size ? desc->size : IOC_SIZE(request);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size);
+ }
+ if (desc->type != ioctl_desc::CUSTOM)
+ return;
+ if (request == IOCTL_SIOCGIFCONF) {
+ struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifc->ifc_ifcu.ifcu_req, ifc->ifc_len);
+ }
+}
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc
new file mode 100644
index 00000000000..f6ac3fa5af1
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_netbsd_compat.inc
@@ -0,0 +1,128 @@
+//===-- sanitizer_common_interceptors_netbsd_compat.inc ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Common function interceptors for tools like AddressSanitizer,
+// ThreadSanitizer, MemorySanitizer, etc.
+//
+// Interceptors for NetBSD old function calls that have been versioned.
+//
+// NetBSD minimal version supported 9.0.
+// NetBSD current version supported 9.99.26.
+//
+//===----------------------------------------------------------------------===//
+
+#if SANITIZER_NETBSD
+
+// First undef all mangled symbols.
+// Next, define compat interceptors.
+// Finally, undef INIT_ and redefine it.
+// This allows to avoid preprocessor issues.
+
+#undef fstatvfs
+#undef fstatvfs1
+#undef getmntinfo
+#undef getvfsstat
+#undef statvfs
+#undef statvfs1
+
+INTERCEPTOR(int, statvfs, char *path, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(statvfs)(path, buf);
+ if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
+ return res;
+}
+
+INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ // FIXME: under ASan the call below may write to freed memory and corrupt
+ // its metadata. See
+ // https://github.com/google/sanitizers/issues/321.
+ int res = REAL(fstatvfs)(fd, buf);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
+ if (fd >= 0)
+ COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ }
+ return res;
+}
+
+#undef INIT_STATVFS
+#define INIT_STATVFS \
+ COMMON_INTERCEPT_FUNCTION(statvfs); \
+ COMMON_INTERCEPT_FUNCTION(fstatvfs); \
+ COMMON_INTERCEPT_FUNCTION(__statvfs90); \
+ COMMON_INTERCEPT_FUNCTION(__fstatvfs90)
+
+INTERCEPTOR(int, __getmntinfo13, void **mntbufp, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __getmntinfo13, mntbufp, flags);
+ int cnt = REAL(__getmntinfo13)(mntbufp, flags);
+ if (cnt > 0 && mntbufp) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mntbufp, sizeof(void *));
+ if (*mntbufp)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * struct_statvfs90_sz);
+ }
+ return cnt;
+}
+
+#undef INIT_GETMNTINFO
+#define INIT_GETMNTINFO \
+ COMMON_INTERCEPT_FUNCTION(__getmntinfo13); \
+ COMMON_INTERCEPT_FUNCTION(__getmntinfo90)
+
+INTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getvfsstat, buf, bufsize, flags);
+ int ret = REAL(getvfsstat)(buf, bufsize, flags);
+ if (buf && ret > 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, ret * struct_statvfs90_sz);
+ return ret;
+}
+
+#undef INIT_GETVFSSTAT
+#define INIT_GETVFSSTAT \
+ COMMON_INTERCEPT_FUNCTION(getvfsstat); \
+ COMMON_INTERCEPT_FUNCTION(__getvfsstat90)
+
+INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1);
+ int res = REAL(statvfs1)(path, buf, flags);
+ if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
+ return res;
+}
+
+INTERCEPTOR(int, fstatvfs1, int fd, void *buf, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs1, fd, buf, flags);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ int res = REAL(fstatvfs1)(fd, buf, flags);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz);
+ if (fd >= 0)
+ COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ }
+ return res;
+}
+
+#undef INIT_STATVFS1
+#define INIT_STATVFS1 \
+ COMMON_INTERCEPT_FUNCTION(statvfs1); \
+ COMMON_INTERCEPT_FUNCTION(fstatvfs1); \
+ COMMON_INTERCEPT_FUNCTION(__statvfs190); \
+ COMMON_INTERCEPT_FUNCTION(__fstatvfs190)
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S
new file mode 100644
index 00000000000..72e482754b6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S
@@ -0,0 +1,48 @@
+#if defined(__aarch64__) && defined(__linux__)
+
+#include "sanitizer_common/sanitizer_asm.h"
+#include "builtins/assembly.h"
+
+ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
+
+.comm _ZN14__interception10real_vforkE,8,8
+.globl ASM_WRAPPER_NAME(vfork)
+ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
+ASM_WRAPPER_NAME(vfork):
+ // Save x30 in the off-stack spill area.
+ hint #25 // paciasp
+ stp xzr, x30, [sp, #-16]!
+ bl COMMON_INTERCEPTOR_SPILL_AREA
+ ldp xzr, x30, [sp], 16
+ str x30, [x0]
+
+ // Call real vfork. This may return twice. User code that runs between the first and the second return
+ // may clobber the stack frame of the interceptor; that's why it does not have a frame.
+ adrp x0, _ZN14__interception10real_vforkE
+ ldr x0, [x0, :lo12:_ZN14__interception10real_vforkE]
+ blr x0
+
+ stp x0, xzr, [sp, #-16]!
+ cmp x0, #0
+ b.eq .L_exit
+
+ // x0 != 0 => parent process. Clear stack shadow.
+ add x0, sp, #16
+ bl COMMON_INTERCEPTOR_HANDLE_VFORK
+
+.L_exit:
+ // Restore x30.
+ bl COMMON_INTERCEPTOR_SPILL_AREA
+ ldr x30, [x0]
+ ldp x0, xzr, [sp], 16
+ hint #29 // autiasp
+
+ ret
+ASM_SIZE(vfork)
+
+.weak vfork
+.set vfork, ASM_WRAPPER_NAME(vfork)
+
+GNU_PROPERTY_BTI_PAC
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S
new file mode 100644
index 00000000000..780a9d46e26
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S
@@ -0,0 +1,49 @@
+#if defined(__arm__) && defined(__linux__)
+
+#include "sanitizer_common/sanitizer_asm.h"
+
+ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
+
+.comm _ZN14__interception10real_vforkE,4,4
+.globl ASM_WRAPPER_NAME(vfork)
+ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
+ASM_WRAPPER_NAME(vfork):
+ // Save LR in the off-stack spill area.
+ push {r4, lr}
+ bl COMMON_INTERCEPTOR_SPILL_AREA
+ pop {r4, lr}
+ str lr, [r0]
+
+ // Call real vfork. This may return twice. User code that runs between the first and the second return
+ // may clobber the stack frame of the interceptor; that's why it does not have a frame.
+ ldr r0, .LCPI0_0
+.LPC0_0:
+ ldr r0, [pc, r0]
+ mov lr, pc
+ bx r0
+
+ push {r0, r4}
+ cmp r0, #0
+ beq .L_exit
+
+ // r0 != 0 => parent process. Clear stack shadow.
+ add r0, sp, #8
+ bl COMMON_INTERCEPTOR_HANDLE_VFORK
+
+.L_exit:
+ // Restore LR.
+ bl COMMON_INTERCEPTOR_SPILL_AREA
+ ldr lr, [r0]
+ pop {r0, r4}
+
+ mov pc, lr
+
+.LCPI0_0:
+ .long _ZN14__interception10real_vforkE - (.LPC0_0+8)
+
+ASM_SIZE(vfork)
+
+.weak vfork
+.set vfork, ASM_WRAPPER_NAME(vfork)
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S
new file mode 100644
index 00000000000..f60b05d157b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S
@@ -0,0 +1,64 @@
+#if defined(__i386__) && defined(__linux__)
+
+#include "sanitizer_common/sanitizer_asm.h"
+
+.comm _ZN14__interception10real_vforkE,4,4
+.globl ASM_WRAPPER_NAME(vfork)
+ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
+ASM_WRAPPER_NAME(vfork):
+ _CET_ENDBR
+ // Store return address in the spill area and tear down the stack frame.
+ sub $12, %esp
+ call COMMON_INTERCEPTOR_SPILL_AREA
+ mov 12(%esp), %ecx
+ mov %ecx, (%eax)
+ add $16, %esp
+
+ call .L0$pb
+.L0$pb:
+ pop %eax
+.Ltmp0:
+ add $_GLOBAL_OFFSET_TABLE_+(.Ltmp0-.L0$pb), %eax
+ call *_ZN14__interception10real_vforkE@GOTOFF(%eax)
+
+ // Restore the stack frame.
+ // 12(%esp) return address
+ // 8(%esp) spill %ebx
+ // 4(%esp) spill REAL(vfork) return value
+ // (%esp) call frame (arg0) for __*_handle_vfork
+ sub $16, %esp
+ mov %ebx, 8(%esp)
+ mov %eax, 4(%esp)
+
+ // Form GOT address in %ebx.
+ call .L1$pb
+.L1$pb:
+ pop %ebx
+.Ltmp1:
+ add $_GLOBAL_OFFSET_TABLE_+(.Ltmp1-.L1$pb), %ebx
+
+ // Restore original return address.
+ call COMMON_INTERCEPTOR_SPILL_AREA
+ mov (%eax), %ecx
+ mov %ecx, 12(%esp)
+ mov 4(%esp), %eax
+
+ // Call handle_vfork in the parent process (%rax != 0).
+ test %eax, %eax
+ je .L_exit
+
+ lea 16(%esp), %ecx
+ mov %ecx, (%esp)
+ call COMMON_INTERCEPTOR_HANDLE_VFORK@PLT
+
+.L_exit:
+ mov 4(%esp), %eax
+ mov 8(%esp), %ebx
+ add $12, %esp
+ ret
+ASM_SIZE(vfork)
+
+.weak vfork
+.set vfork, ASM_WRAPPER_NAME(vfork)
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_loongarch64.inc.S b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_loongarch64.inc.S
new file mode 100644
index 00000000000..68782acb379
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_loongarch64.inc.S
@@ -0,0 +1,57 @@
+#if defined(__loongarch_lp64) && defined(__linux__)
+
+#include "sanitizer_common/sanitizer_asm.h"
+
+ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
+ASM_HIDDEN(_ZN14__interception10real_vforkE)
+
+.text
+.globl ASM_WRAPPER_NAME(vfork)
+ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
+ASM_WRAPPER_NAME(vfork):
+ // Save ra in the off-stack spill area.
+ // allocate space on stack
+ addi.d $sp, $sp, -16
+ // store $ra value
+ st.d $ra, $sp, 8
+ bl COMMON_INTERCEPTOR_SPILL_AREA
+ // restore previous values from stack
+ ld.d $ra, $sp, 8
+ // adjust stack
+ addi.d $sp, $sp, 16
+ // store $ra by $a0
+ st.d $ra, $a0, 0
+
+ // Call real vfork. This may return twice. User code that runs between the first and the second return
+ // may clobber the stack frame of the interceptor; that's why it does not have a frame.
+ la.local $a0, _ZN14__interception10real_vforkE
+ ld.d $a0, $a0, 0
+ jirl $ra, $a0, 0
+
+ // adjust stack
+ addi.d $sp, $sp, -16
+ // store $a0 by adjusted stack
+ st.d $a0, $sp, 8
+ // jump to exit label if $a0 is 0
+ beqz $a0, .L_exit
+
+ // $a0 != 0 => parent process. Clear stack shadow.
+ // put old $sp to $a0
+ addi.d $a0, $sp, 16
+ bl %plt(COMMON_INTERCEPTOR_HANDLE_VFORK)
+
+.L_exit:
+ // Restore $ra
+ bl COMMON_INTERCEPTOR_SPILL_AREA
+ ld.d $ra, $a0, 0
+ // load value by stack
+ ld.d $a0, $sp, 8
+ // adjust stack
+ addi.d $sp, $sp, 16
+ jr $ra
+ASM_SIZE(vfork)
+
+.weak vfork
+.set vfork, ASM_WRAPPER_NAME(vfork)
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_riscv64.inc.S b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_riscv64.inc.S
new file mode 100644
index 00000000000..b7ec27859b8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_riscv64.inc.S
@@ -0,0 +1,56 @@
+#if (defined(__riscv) && (__riscv_xlen == 64)) && defined(__linux__)
+
+#include "sanitizer_common/sanitizer_asm.h"
+
+ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
+
+.comm _ZN14__interception10real_vforkE,8,8
+.globl ASM_WRAPPER_NAME(vfork)
+ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
+ASM_WRAPPER_NAME(vfork):
+ // Save ra in the off-stack spill area.
+ // allocate space on stack
+ addi sp, sp, -16
+ // store ra value
+ sd ra, 8(sp)
+ call COMMON_INTERCEPTOR_SPILL_AREA
+ // restore previous values from stack
+ ld ra, 8(sp)
+ // adjust stack
+ addi sp, sp, 16
+ // store ra by x10
+ sd ra, 0(x10)
+
+ // Call real vfork. This may return twice. User code that runs between the first and the second return
+ // may clobber the stack frame of the interceptor; that's why it does not have a frame.
+ la x10, _ZN14__interception10real_vforkE
+ ld x10, 0(x10)
+ jalr x10
+
+ // adjust stack
+ addi sp, sp, -16
+ // store x10 by adjusted stack
+ sd x10, 8(sp)
+ // jump to exit label if x10 is 0
+ beqz x10, .L_exit
+
+ // x0 != 0 => parent process. Clear stack shadow.
+ // put old sp to x10
+ addi x10, sp, 16
+ call COMMON_INTERCEPTOR_HANDLE_VFORK
+
+.L_exit:
+ // Restore ra
+ call COMMON_INTERCEPTOR_SPILL_AREA
+ ld ra, 0(x10)
+ // load value by stack
+ ld x10, 8(sp)
+ // adjust stack
+ addi sp, sp, 16
+ ret
+ASM_SIZE(vfork)
+
+.weak vfork
+.set vfork, ASM_WRAPPER_NAME(vfork)
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S
new file mode 100644
index 00000000000..8fd18ea67ff
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S
@@ -0,0 +1,42 @@
+#if defined(__x86_64__) && defined(__linux__)
+
+#include "sanitizer_common/sanitizer_asm.h"
+
+.comm _ZN14__interception10real_vforkE,8,8
+.globl ASM_WRAPPER_NAME(vfork)
+ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
+ASM_WRAPPER_NAME(vfork):
+ _CET_ENDBR
+ // Store return address in the spill area and tear down the stack frame.
+ push %rcx
+ call COMMON_INTERCEPTOR_SPILL_AREA
+ pop %rcx
+ pop %rdi
+ mov %rdi, (%rax)
+
+ call *_ZN14__interception10real_vforkE(%rip)
+
+ // Restore return address from the spill area.
+ push %rcx
+ push %rax
+ call COMMON_INTERCEPTOR_SPILL_AREA
+ mov (%rax), %rdx
+ mov %rdx, 8(%rsp)
+ mov (%rsp), %rax
+
+ // Call handle_vfork in the parent process (%rax != 0).
+ test %rax, %rax
+ je .L_exit
+
+ lea 16(%rsp), %rdi
+ call COMMON_INTERCEPTOR_HANDLE_VFORK@PLT
+
+.L_exit:
+ pop %rax
+ ret
+ASM_SIZE(vfork)
+
+.weak vfork
+.set vfork, ASM_WRAPPER_NAME(vfork)
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interface.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interface.inc
new file mode 100644
index 00000000000..958f071e7b5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interface.inc
@@ -0,0 +1,46 @@
+//===-- sanitizer_common_interface.inc ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Sanitizer Common interface list.
+//===----------------------------------------------------------------------===//
+INTERFACE_FUNCTION(__sanitizer_acquire_crash_state)
+INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container)
+INTERFACE_FUNCTION(__sanitizer_annotate_double_ended_contiguous_container)
+INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address)
+INTERFACE_FUNCTION(
+ __sanitizer_double_ended_contiguous_container_find_bad_address)
+INTERFACE_FUNCTION(__sanitizer_set_death_callback)
+INTERFACE_FUNCTION(__sanitizer_set_report_path)
+INTERFACE_FUNCTION(__sanitizer_set_report_fd)
+INTERFACE_FUNCTION(__sanitizer_get_report_path)
+INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container)
+INTERFACE_FUNCTION(__sanitizer_verify_double_ended_contiguous_container)
+INTERFACE_WEAK_FUNCTION(__sanitizer_on_print)
+INTERFACE_WEAK_FUNCTION(__sanitizer_report_error_summary)
+INTERFACE_WEAK_FUNCTION(__sanitizer_sandbox_on_notify)
+// Sanitizer weak hooks
+INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_memcmp)
+INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_strcmp)
+INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_strncmp)
+INTERFACE_WEAK_FUNCTION(__sanitizer_weak_hook_strstr)
+// Stacktrace interface.
+INTERFACE_FUNCTION(__sanitizer_get_module_and_offset_for_pc)
+INTERFACE_FUNCTION(__sanitizer_symbolize_global)
+INTERFACE_FUNCTION(__sanitizer_symbolize_pc)
+// Allocator interface.
+INTERFACE_FUNCTION(__sanitizer_get_allocated_size)
+INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes)
+INTERFACE_FUNCTION(__sanitizer_get_estimated_allocated_size)
+INTERFACE_FUNCTION(__sanitizer_get_free_bytes)
+INTERFACE_FUNCTION(__sanitizer_get_heap_size)
+INTERFACE_FUNCTION(__sanitizer_get_ownership)
+INTERFACE_FUNCTION(__sanitizer_get_unmapped_bytes)
+INTERFACE_FUNCTION(__sanitizer_install_malloc_and_free_hooks)
+INTERFACE_FUNCTION(__sanitizer_purge_allocator)
+INTERFACE_FUNCTION(__sanitizer_print_memory_profile)
+INTERFACE_WEAK_FUNCTION(__sanitizer_free_hook)
+INTERFACE_WEAK_FUNCTION(__sanitizer_malloc_hook)
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interface_posix.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interface_posix.inc
new file mode 100644
index 00000000000..a5259be9335
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_interface_posix.inc
@@ -0,0 +1,15 @@
+//===-- sanitizer_common_interface_posix.inc ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Sanitizer Common interface list only available for Posix systems.
+//===----------------------------------------------------------------------===//
+INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_code)
+INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_data)
+INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_demangle)
+INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_flush)
+INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_set_demangle)
+INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_set_inline_frames)
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp
new file mode 100644
index 00000000000..8fd39856428
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp
@@ -0,0 +1,226 @@
+//===-- sanitizer_common_libcdep.cpp --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_allocator.h"
+#include "sanitizer_allocator_interface.h"
+#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_interface_internal.h"
+#include "sanitizer_procmaps.h"
+#include "sanitizer_stackdepot.h"
+
+namespace __sanitizer {
+
+#if (SANITIZER_LINUX || SANITIZER_NETBSD) && !SANITIZER_GO
+// Weak default implementation for when sanitizer_stackdepot is not linked in.
+SANITIZER_WEAK_ATTRIBUTE StackDepotStats StackDepotGetStats() { return {}; }
+
+void *BackgroundThread(void *arg) {
+ VPrintf(1, "%s: Started BackgroundThread\n", SanitizerToolName);
+ const uptr hard_rss_limit_mb = common_flags()->hard_rss_limit_mb;
+ const uptr soft_rss_limit_mb = common_flags()->soft_rss_limit_mb;
+ const bool heap_profile = common_flags()->heap_profile;
+ uptr prev_reported_rss = 0;
+ uptr prev_reported_stack_depot_size = 0;
+ bool reached_soft_rss_limit = false;
+ uptr rss_during_last_reported_profile = 0;
+ while (true) {
+ SleepForMillis(100);
+ const uptr current_rss_mb = GetRSS() >> 20;
+ if (Verbosity()) {
+ // If RSS has grown 10% since last time, print some information.
+ if (prev_reported_rss * 11 / 10 < current_rss_mb) {
+ Printf("%s: RSS: %zdMb\n", SanitizerToolName, current_rss_mb);
+ prev_reported_rss = current_rss_mb;
+ }
+ // If stack depot has grown 10% since last time, print it too.
+ StackDepotStats stack_depot_stats = StackDepotGetStats();
+ if (prev_reported_stack_depot_size * 11 / 10 <
+ stack_depot_stats.allocated) {
+ Printf("%s: StackDepot: %zd ids; %zdM allocated\n", SanitizerToolName,
+ stack_depot_stats.n_uniq_ids, stack_depot_stats.allocated >> 20);
+ prev_reported_stack_depot_size = stack_depot_stats.allocated;
+ }
+ }
+ // Check RSS against the limit.
+ if (hard_rss_limit_mb && hard_rss_limit_mb < current_rss_mb) {
+ Report("%s: hard rss limit exhausted (%zdMb vs %zdMb)\n",
+ SanitizerToolName, hard_rss_limit_mb, current_rss_mb);
+ DumpProcessMap();
+ Die();
+ }
+ if (soft_rss_limit_mb) {
+ if (soft_rss_limit_mb < current_rss_mb && !reached_soft_rss_limit) {
+ reached_soft_rss_limit = true;
+ Report("%s: soft rss limit exhausted (%zdMb vs %zdMb)\n",
+ SanitizerToolName, soft_rss_limit_mb, current_rss_mb);
+ SetRssLimitExceeded(true);
+ } else if (soft_rss_limit_mb >= current_rss_mb &&
+ reached_soft_rss_limit) {
+ reached_soft_rss_limit = false;
+ SetRssLimitExceeded(false);
+ }
+ }
+ if (heap_profile &&
+ current_rss_mb > rss_during_last_reported_profile * 1.1) {
+ Printf("\n\nHEAP PROFILE at RSS %zdMb\n", current_rss_mb);
+ __sanitizer_print_memory_profile(90, 20);
+ rss_during_last_reported_profile = current_rss_mb;
+ }
+ }
+}
+
+void MaybeStartBackgroudThread() {
+ // Need to implement/test on other platforms.
+ // Start the background thread if one of the rss limits is given.
+ if (!common_flags()->hard_rss_limit_mb &&
+ !common_flags()->soft_rss_limit_mb &&
+ !common_flags()->heap_profile) return;
+ if (!&real_pthread_create) {
+ VPrintf(1, "%s: real_pthread_create undefined\n", SanitizerToolName);
+ return; // Can't spawn the thread anyway.
+ }
+
+ static bool started = false;
+ if (!started) {
+ started = true;
+ internal_start_thread(BackgroundThread, nullptr);
+ }
+}
+
+# if !SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL
+# ifdef __clang__
+# pragma clang diagnostic push
+// We avoid global-constructors to be sure that globals are ready when
+// sanitizers need them. This can happend before global constructors executed.
+// Here we don't mind if thread is started on later stages.
+# pragma clang diagnostic ignored "-Wglobal-constructors"
+# endif
+static struct BackgroudThreadStarted {
+ BackgroudThreadStarted() { MaybeStartBackgroudThread(); }
+} background_thread_strarter UNUSED;
+# ifdef __clang__
+# pragma clang diagnostic pop
+# endif
+# endif
+#else
+void MaybeStartBackgroudThread() {}
+#endif
+
+void WriteToSyslog(const char *msg) {
+ InternalScopedString msg_copy;
+ msg_copy.append("%s", msg);
+ const char *p = msg_copy.data();
+
+ // Print one line at a time.
+ // syslog, at least on Android, has an implicit message length limit.
+ while (char* q = internal_strchr(p, '\n')) {
+ *q = '\0';
+ WriteOneLineToSyslog(p);
+ p = q + 1;
+ }
+ // Print remaining characters, if there are any.
+ // Note that this will add an extra newline at the end.
+ // FIXME: buffer extra output. This would need a thread-local buffer, which
+ // on Android requires plugging into the tools (ex. ASan's) Thread class.
+ if (*p)
+ WriteOneLineToSyslog(p);
+}
+
+static void (*sandboxing_callback)();
+void SetSandboxingCallback(void (*f)()) {
+ sandboxing_callback = f;
+}
+
+uptr ReservedAddressRange::InitAligned(uptr size, uptr align,
+ const char *name) {
+ CHECK(IsPowerOfTwo(align));
+ if (align <= GetPageSizeCached())
+ return Init(size, name);
+ uptr start = Init(size + align, name);
+ start += align - (start & (align - 1));
+ return start;
+}
+
+#if !SANITIZER_FUCHSIA
+
+// Reserve memory range [beg, end].
+// We need to use inclusive range because end+1 may not be representable.
+void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name,
+ bool madvise_shadow) {
+ CHECK_EQ((beg % GetMmapGranularity()), 0);
+ CHECK_EQ(((end + 1) % GetMmapGranularity()), 0);
+ uptr size = end - beg + 1;
+ DecreaseTotalMmap(size); // Don't count the shadow against mmap_limit_mb.
+ if (madvise_shadow ? !MmapFixedSuperNoReserve(beg, size, name)
+ : !MmapFixedNoReserve(beg, size, name)) {
+ Report(
+ "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
+ "Perhaps you're using ulimit -v\n",
+ size);
+ Abort();
+ }
+ if (madvise_shadow && common_flags()->use_madv_dontdump)
+ DontDumpShadowMemory(beg, size);
+}
+
+void ProtectGap(uptr addr, uptr size, uptr zero_base_shadow_start,
+ uptr zero_base_max_shadow_start) {
+ if (!size)
+ return;
+ void *res = MmapFixedNoAccess(addr, size, "shadow gap");
+ if (addr == (uptr)res)
+ return;
+ // A few pages at the start of the address space can not be protected.
+ // But we really want to protect as much as possible, to prevent this memory
+ // being returned as a result of a non-FIXED mmap().
+ if (addr == zero_base_shadow_start) {
+ uptr step = GetMmapGranularity();
+ while (size > step && addr < zero_base_max_shadow_start) {
+ addr += step;
+ size -= step;
+ void *res = MmapFixedNoAccess(addr, size, "shadow gap");
+ if (addr == (uptr)res)
+ return;
+ }
+ }
+
+ Report(
+ "ERROR: Failed to protect the shadow gap. "
+ "%s cannot proceed correctly. ABORTING.\n",
+ SanitizerToolName);
+ DumpProcessMap();
+ Die();
+}
+
+#endif // !SANITIZER_FUCHSIA
+
+#if !SANITIZER_WINDOWS && !SANITIZER_GO
+// Weak default implementation for when sanitizer_stackdepot is not linked in.
+SANITIZER_WEAK_ATTRIBUTE void StackDepotStopBackgroundThread() {}
+static void StopStackDepotBackgroundThread() {
+ StackDepotStopBackgroundThread();
+}
+#else
+// SANITIZER_WEAK_ATTRIBUTE is unsupported.
+static void StopStackDepotBackgroundThread() {}
+#endif
+
+} // namespace __sanitizer
+
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_sandbox_on_notify,
+ __sanitizer_sandbox_arguments *args) {
+ __sanitizer::StopStackDepotBackgroundThread();
+ __sanitizer::PlatformPrepareForSandboxing(args);
+ if (__sanitizer::sandboxing_callback)
+ __sanitizer::sandboxing_callback();
+}
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc
new file mode 100644
index 00000000000..9d7518ac947
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc
@@ -0,0 +1,3180 @@
+//===-- sanitizer_common_syscalls.inc ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Common syscalls handlers for tools like AddressSanitizer,
+// ThreadSanitizer, MemorySanitizer, etc.
+//
+// This file should be included into the tool's interceptor file,
+// which has to define it's own macros:
+// COMMON_SYSCALL_PRE_READ_RANGE
+// Called in prehook for regions that will be read by the kernel and
+// must be initialized.
+// COMMON_SYSCALL_PRE_WRITE_RANGE
+// Called in prehook for regions that will be written to by the kernel
+// and must be addressable. The actual write range may be smaller than
+// reported in the prehook. See POST_WRITE_RANGE.
+// COMMON_SYSCALL_POST_READ_RANGE
+// Called in posthook for regions that were read by the kernel. Does
+// not make much sense.
+// COMMON_SYSCALL_POST_WRITE_RANGE
+// Called in posthook for regions that were written to by the kernel
+// and are now initialized.
+// COMMON_SYSCALL_ACQUIRE(addr)
+// Acquire memory visibility from addr.
+// COMMON_SYSCALL_RELEASE(addr)
+// Release memory visibility to addr.
+// COMMON_SYSCALL_FD_CLOSE(fd)
+// Called before closing file descriptor fd.
+// COMMON_SYSCALL_FD_ACQUIRE(fd)
+// Acquire memory visibility from fd.
+// COMMON_SYSCALL_FD_RELEASE(fd)
+// Release memory visibility to fd.
+// COMMON_SYSCALL_PRE_FORK()
+// Called before fork syscall.
+// COMMON_SYSCALL_POST_FORK(long res)
+// Called after fork syscall.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_LINUX
+
+# include "sanitizer_libc.h"
+
+# define PRE_SYSCALL(name) \
+ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_impl_##name
+# define PRE_READ(p, s) COMMON_SYSCALL_PRE_READ_RANGE(p, s)
+# define PRE_WRITE(p, s) COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
+
+# define POST_SYSCALL(name) \
+ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_post_impl_##name
+# define POST_READ(p, s) COMMON_SYSCALL_POST_READ_RANGE(p, s)
+# define POST_WRITE(p, s) COMMON_SYSCALL_POST_WRITE_RANGE(p, s)
+
+# ifndef COMMON_SYSCALL_ACQUIRE
+# define COMMON_SYSCALL_ACQUIRE(addr) ((void)(addr))
+# endif
+
+# ifndef COMMON_SYSCALL_RELEASE
+# define COMMON_SYSCALL_RELEASE(addr) ((void)(addr))
+# endif
+
+# ifndef COMMON_SYSCALL_FD_CLOSE
+# define COMMON_SYSCALL_FD_CLOSE(fd) ((void)(fd))
+# endif
+
+# ifndef COMMON_SYSCALL_FD_ACQUIRE
+# define COMMON_SYSCALL_FD_ACQUIRE(fd) ((void)(fd))
+# endif
+
+# ifndef COMMON_SYSCALL_FD_RELEASE
+# define COMMON_SYSCALL_FD_RELEASE(fd) ((void)(fd))
+# endif
+
+# ifndef COMMON_SYSCALL_PRE_FORK
+# define COMMON_SYSCALL_PRE_FORK() \
+ {}
+# endif
+
+# ifndef COMMON_SYSCALL_POST_FORK
+# define COMMON_SYSCALL_POST_FORK(res) \
+ {}
+# endif
+
+// FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such).
+
+extern "C" {
+struct sanitizer_kernel_iovec {
+ void *iov_base;
+ unsigned long iov_len;
+};
+
+struct sanitizer_kernel_msghdr {
+ void *msg_name;
+ int msg_namelen;
+ struct sanitizer_kernel_iovec *msg_iov;
+ unsigned long msg_iovlen;
+ void *msg_control;
+ unsigned long msg_controllen;
+ unsigned msg_flags;
+};
+
+struct sanitizer_kernel_mmsghdr {
+ struct sanitizer_kernel_msghdr msg_hdr;
+ unsigned msg_len;
+};
+
+struct sanitizer_kernel_timespec {
+ long tv_sec;
+ long tv_nsec;
+};
+
+struct sanitizer_kernel_timeval {
+ long tv_sec;
+ long tv_usec;
+};
+
+struct sanitizer_kernel_rusage {
+ struct sanitizer_kernel_timeval ru_timeval[2];
+ long ru_long[14];
+};
+
+struct sanitizer_kernel_sockaddr {
+ unsigned short sa_family;
+ char sa_data[14];
+};
+
+// Real sigset size is always passed as a syscall argument.
+// Declare it "void" to catch sizeof(kernel_sigset_t).
+typedef void kernel_sigset_t;
+
+static void kernel_write_iovec(const __sanitizer_iovec *iovec, SIZE_T iovlen,
+ SIZE_T maxlen) {
+ for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
+ SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
+ POST_WRITE(iovec[i].iov_base, sz);
+ maxlen -= sz;
+ }
+}
+
+// This functions uses POST_READ, because it needs to run after syscall to know
+// the real read range.
+static void kernel_read_iovec(const __sanitizer_iovec *iovec, SIZE_T iovlen,
+ SIZE_T maxlen) {
+ POST_READ(iovec, sizeof(*iovec) * iovlen);
+ for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
+ SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
+ POST_READ(iovec[i].iov_base, sz);
+ maxlen -= sz;
+ }
+}
+
+PRE_SYSCALL(recvmsg)(long sockfd, sanitizer_kernel_msghdr *msg, long flags) {
+ PRE_READ(msg, sizeof(*msg));
+}
+
+POST_SYSCALL(recvmsg)
+(long res, long sockfd, sanitizer_kernel_msghdr *msg, long flags) {
+ if (res >= 0) {
+ if (msg) {
+ for (unsigned long i = 0; i < msg->msg_iovlen; ++i) {
+ POST_WRITE(msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
+ }
+ POST_WRITE(msg->msg_control, msg->msg_controllen);
+ }
+ }
+}
+
+PRE_SYSCALL(recvmmsg)
+(long fd, sanitizer_kernel_mmsghdr *msg, long vlen, long flags, void *timeout) {
+ PRE_READ(msg, vlen * sizeof(*msg));
+}
+
+POST_SYSCALL(recvmmsg)
+(long res, long fd, sanitizer_kernel_mmsghdr *msg, long vlen, long flags,
+ void *timeout) {
+ if (res >= 0) {
+ if (msg) {
+ for (unsigned long i = 0; i < msg->msg_hdr.msg_iovlen; ++i) {
+ POST_WRITE(msg->msg_hdr.msg_iov[i].iov_base,
+ msg->msg_hdr.msg_iov[i].iov_len);
+ }
+ POST_WRITE(msg->msg_hdr.msg_control, msg->msg_hdr.msg_controllen);
+ POST_WRITE(&msg->msg_len, sizeof(msg->msg_len));
+ }
+ if (timeout)
+ POST_WRITE(timeout, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(read)(long fd, void *buf, uptr count) {
+ if (buf) {
+ PRE_WRITE(buf, count);
+ }
+}
+
+POST_SYSCALL(read)(long res, long fd, void *buf, uptr count) {
+ if (res > 0 && buf) {
+ POST_WRITE(buf, res);
+ }
+}
+
+PRE_SYSCALL(time)(void *tloc) {}
+
+POST_SYSCALL(time)(long res, void *tloc) {
+ if (res >= 0) {
+ if (tloc)
+ POST_WRITE(tloc, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(stime)(void *tptr) {}
+
+POST_SYSCALL(stime)(long res, void *tptr) {
+ if (res >= 0) {
+ if (tptr)
+ POST_WRITE(tptr, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(gettimeofday)(void *tv, void *tz) {}
+
+POST_SYSCALL(gettimeofday)(long res, void *tv, void *tz) {
+ if (res >= 0) {
+ if (tv)
+ POST_WRITE(tv, timeval_sz);
+ if (tz)
+ POST_WRITE(tz, struct_timezone_sz);
+ }
+}
+
+PRE_SYSCALL(settimeofday)(void *tv, void *tz) {}
+
+POST_SYSCALL(settimeofday)(long res, void *tv, void *tz) {
+ if (res >= 0) {
+ if (tv)
+ POST_WRITE(tv, timeval_sz);
+ if (tz)
+ POST_WRITE(tz, struct_timezone_sz);
+ }
+}
+
+# if !SANITIZER_ANDROID
+PRE_SYSCALL(adjtimex)(void *txc_p) {}
+
+POST_SYSCALL(adjtimex)(long res, void *txc_p) {
+ if (res >= 0) {
+ if (txc_p)
+ POST_WRITE(txc_p, struct_timex_sz);
+ }
+}
+# endif
+
+PRE_SYSCALL(times)(void *tbuf) {}
+
+POST_SYSCALL(times)(long res, void *tbuf) {
+ if (res >= 0) {
+ if (tbuf)
+ POST_WRITE(tbuf, struct_tms_sz);
+ }
+}
+
+PRE_SYSCALL(gettid)() {}
+
+POST_SYSCALL(gettid)(long res) {}
+
+PRE_SYSCALL(nanosleep)(void *rqtp, void *rmtp) {}
+
+POST_SYSCALL(nanosleep)(long res, void *rqtp, void *rmtp) {
+ if (res >= 0) {
+ if (rqtp)
+ POST_WRITE(rqtp, struct_timespec_sz);
+ if (rmtp)
+ POST_WRITE(rmtp, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(alarm)(long seconds) {}
+
+POST_SYSCALL(alarm)(long res, long seconds) {}
+
+PRE_SYSCALL(getpid)() {}
+
+POST_SYSCALL(getpid)(long res) {}
+
+PRE_SYSCALL(getppid)() {}
+
+POST_SYSCALL(getppid)(long res) {}
+
+PRE_SYSCALL(getuid)() {}
+
+POST_SYSCALL(getuid)(long res) {}
+
+PRE_SYSCALL(geteuid)() {}
+
+POST_SYSCALL(geteuid)(long res) {}
+
+PRE_SYSCALL(getgid)() {}
+
+POST_SYSCALL(getgid)(long res) {}
+
+PRE_SYSCALL(getegid)() {}
+
+POST_SYSCALL(getegid)(long res) {}
+
+PRE_SYSCALL(getresuid)(void *ruid, void *euid, void *suid) {}
+
+POST_SYSCALL(getresuid)(long res, void *ruid, void *euid, void *suid) {
+ if (res >= 0) {
+ if (ruid)
+ POST_WRITE(ruid, sizeof(unsigned));
+ if (euid)
+ POST_WRITE(euid, sizeof(unsigned));
+ if (suid)
+ POST_WRITE(suid, sizeof(unsigned));
+ }
+}
+
+PRE_SYSCALL(getresgid)(void *rgid, void *egid, void *sgid) {}
+
+POST_SYSCALL(getresgid)(long res, void *rgid, void *egid, void *sgid) {
+ if (res >= 0) {
+ if (rgid)
+ POST_WRITE(rgid, sizeof(unsigned));
+ if (egid)
+ POST_WRITE(egid, sizeof(unsigned));
+ if (sgid)
+ POST_WRITE(sgid, sizeof(unsigned));
+ }
+}
+
+PRE_SYSCALL(getpgid)(long pid) {}
+
+POST_SYSCALL(getpgid)(long res, long pid) {}
+
+PRE_SYSCALL(getpgrp)() {}
+
+POST_SYSCALL(getpgrp)(long res) {}
+
+PRE_SYSCALL(getsid)(long pid) {}
+
+POST_SYSCALL(getsid)(long res, long pid) {}
+
+PRE_SYSCALL(getgroups)(long gidsetsize, void *grouplist) {}
+
+POST_SYSCALL(getgroups)
+(long res, long gidsetsize, __sanitizer___kernel_gid_t *grouplist) {
+ if (res >= 0) {
+ if (grouplist)
+ POST_WRITE(grouplist, res * sizeof(*grouplist));
+ }
+}
+
+PRE_SYSCALL(setregid)(long rgid, long egid) {}
+
+POST_SYSCALL(setregid)(long res, long rgid, long egid) {}
+
+PRE_SYSCALL(setgid)(long gid) {}
+
+POST_SYSCALL(setgid)(long res, long gid) {}
+
+PRE_SYSCALL(setreuid)(long ruid, long euid) {}
+
+POST_SYSCALL(setreuid)(long res, long ruid, long euid) {}
+
+PRE_SYSCALL(setuid)(long uid) {}
+
+POST_SYSCALL(setuid)(long res, long uid) {}
+
+PRE_SYSCALL(setresuid)(long ruid, long euid, long suid) {}
+
+POST_SYSCALL(setresuid)(long res, long ruid, long euid, long suid) {}
+
+PRE_SYSCALL(setresgid)(long rgid, long egid, long sgid) {}
+
+POST_SYSCALL(setresgid)(long res, long rgid, long egid, long sgid) {}
+
+PRE_SYSCALL(setfsuid)(long uid) {}
+
+POST_SYSCALL(setfsuid)(long res, long uid) {}
+
+PRE_SYSCALL(setfsgid)(long gid) {}
+
+POST_SYSCALL(setfsgid)(long res, long gid) {}
+
+PRE_SYSCALL(setpgid)(long pid, long pgid) {}
+
+POST_SYSCALL(setpgid)(long res, long pid, long pgid) {}
+
+PRE_SYSCALL(setsid)() {}
+
+POST_SYSCALL(setsid)(long res) {}
+
+PRE_SYSCALL(setgroups)(long gidsetsize, __sanitizer___kernel_gid_t *grouplist) {
+ if (grouplist)
+ POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
+}
+
+POST_SYSCALL(setgroups)
+(long res, long gidsetsize, __sanitizer___kernel_gid_t *grouplist) {}
+
+PRE_SYSCALL(acct)(const void *name) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(acct)(long res, const void *name) {}
+
+PRE_SYSCALL(capget)(void *header, void *dataptr) {
+ if (header)
+ PRE_READ(header, __user_cap_header_struct_sz);
+}
+
+POST_SYSCALL(capget)(long res, void *header, void *dataptr) {
+ if (res >= 0)
+ if (dataptr)
+ POST_WRITE(dataptr, __user_cap_data_struct_sz);
+}
+
+PRE_SYSCALL(capset)(void *header, const void *data) {
+ if (header)
+ PRE_READ(header, __user_cap_header_struct_sz);
+ if (data)
+ PRE_READ(data, __user_cap_data_struct_sz);
+}
+
+POST_SYSCALL(capset)(long res, void *header, const void *data) {}
+
+PRE_SYSCALL(personality)(long personality) {}
+
+POST_SYSCALL(personality)(long res, long personality) {}
+
+PRE_SYSCALL(sigpending)(void *set) {}
+
+POST_SYSCALL(sigpending)(long res, void *set) {
+ if (res >= 0) {
+ if (set)
+ POST_WRITE(set, old_sigset_t_sz);
+ }
+}
+
+PRE_SYSCALL(sigprocmask)(long how, void *set, void *oset) {}
+
+POST_SYSCALL(sigprocmask)(long res, long how, void *set, void *oset) {
+ if (res >= 0) {
+ if (set)
+ POST_WRITE(set, old_sigset_t_sz);
+ if (oset)
+ POST_WRITE(oset, old_sigset_t_sz);
+ }
+}
+
+PRE_SYSCALL(getitimer)(long which, void *value) {}
+
+POST_SYSCALL(getitimer)(long res, long which, void *value) {
+ if (res >= 0) {
+ if (value)
+ POST_WRITE(value, struct_itimerval_sz);
+ }
+}
+
+PRE_SYSCALL(setitimer)(long which, void *value, void *ovalue) {}
+
+POST_SYSCALL(setitimer)(long res, long which, void *value, void *ovalue) {
+ if (res >= 0) {
+ if (value)
+ POST_WRITE(value, struct_itimerval_sz);
+ if (ovalue)
+ POST_WRITE(ovalue, struct_itimerval_sz);
+ }
+}
+
+PRE_SYSCALL(timer_create)
+(long which_clock, void *timer_event_spec, void *created_timer_id) {}
+
+POST_SYSCALL(timer_create)
+(long res, long which_clock, void *timer_event_spec, void *created_timer_id) {
+ if (res >= 0) {
+ if (timer_event_spec)
+ POST_WRITE(timer_event_spec, struct_sigevent_sz);
+ if (created_timer_id)
+ POST_WRITE(created_timer_id, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(timer_gettime)(long timer_id, void *setting) {}
+
+POST_SYSCALL(timer_gettime)(long res, long timer_id, void *setting) {
+ if (res >= 0) {
+ if (setting)
+ POST_WRITE(setting, struct_itimerspec_sz);
+ }
+}
+
+PRE_SYSCALL(timer_getoverrun)(long timer_id) {}
+
+POST_SYSCALL(timer_getoverrun)(long res, long timer_id) {}
+
+PRE_SYSCALL(timer_settime)
+(long timer_id, long flags, const void *new_setting, void *old_setting) {
+ if (new_setting)
+ PRE_READ(new_setting, struct_itimerspec_sz);
+}
+
+POST_SYSCALL(timer_settime)
+(long res, long timer_id, long flags, const void *new_setting,
+ void *old_setting) {
+ if (res >= 0) {
+ if (old_setting)
+ POST_WRITE(old_setting, struct_itimerspec_sz);
+ }
+}
+
+PRE_SYSCALL(timer_delete)(long timer_id) {}
+
+POST_SYSCALL(timer_delete)(long res, long timer_id) {}
+
+PRE_SYSCALL(clock_settime)(long which_clock, const void *tp) {
+ if (tp)
+ PRE_READ(tp, struct_timespec_sz);
+}
+
+POST_SYSCALL(clock_settime)(long res, long which_clock, const void *tp) {}
+
+PRE_SYSCALL(clock_gettime)(long which_clock, void *tp) {}
+
+POST_SYSCALL(clock_gettime)(long res, long which_clock, void *tp) {
+ if (res >= 0) {
+ if (tp)
+ POST_WRITE(tp, struct_timespec_sz);
+ }
+}
+
+# if !SANITIZER_ANDROID
+PRE_SYSCALL(clock_adjtime)(long which_clock, void *tx) {}
+
+POST_SYSCALL(clock_adjtime)(long res, long which_clock, void *tx) {
+ if (res >= 0) {
+ if (tx)
+ POST_WRITE(tx, struct_timex_sz);
+ }
+}
+# endif
+
+PRE_SYSCALL(clock_getres)(long which_clock, void *tp) {}
+
+POST_SYSCALL(clock_getres)(long res, long which_clock, void *tp) {
+ if (res >= 0) {
+ if (tp)
+ POST_WRITE(tp, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(clock_nanosleep)
+(long which_clock, long flags, const void *rqtp, void *rmtp) {
+ if (rqtp)
+ PRE_READ(rqtp, struct_timespec_sz);
+}
+
+POST_SYSCALL(clock_nanosleep)
+(long res, long which_clock, long flags, const void *rqtp, void *rmtp) {
+ if (res >= 0) {
+ if (rmtp)
+ POST_WRITE(rmtp, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(nice)(long increment) {}
+
+POST_SYSCALL(nice)(long res, long increment) {}
+
+PRE_SYSCALL(sched_setscheduler)(long pid, long policy, void *param) {}
+
+POST_SYSCALL(sched_setscheduler)(long res, long pid, long policy, void *param) {
+ if (res >= 0) {
+ if (param)
+ POST_WRITE(param, struct_sched_param_sz);
+ }
+}
+
+PRE_SYSCALL(sched_setparam)(long pid, void *param) {
+ if (param)
+ PRE_READ(param, struct_sched_param_sz);
+}
+
+POST_SYSCALL(sched_setparam)(long res, long pid, void *param) {}
+
+PRE_SYSCALL(sched_getscheduler)(long pid) {}
+
+POST_SYSCALL(sched_getscheduler)(long res, long pid) {}
+
+PRE_SYSCALL(sched_getparam)(long pid, void *param) {}
+
+POST_SYSCALL(sched_getparam)(long res, long pid, void *param) {
+ if (res >= 0) {
+ if (param)
+ POST_WRITE(param, struct_sched_param_sz);
+ }
+}
+
+PRE_SYSCALL(sched_setaffinity)(long pid, long len, void *user_mask_ptr) {
+ if (user_mask_ptr)
+ PRE_READ(user_mask_ptr, len);
+}
+
+POST_SYSCALL(sched_setaffinity)
+(long res, long pid, long len, void *user_mask_ptr) {}
+
+PRE_SYSCALL(sched_getaffinity)(long pid, long len, void *user_mask_ptr) {}
+
+POST_SYSCALL(sched_getaffinity)
+(long res, long pid, long len, void *user_mask_ptr) {
+ if (res >= 0) {
+ if (user_mask_ptr)
+ POST_WRITE(user_mask_ptr, len);
+ }
+}
+
+PRE_SYSCALL(sched_yield)() {}
+
+POST_SYSCALL(sched_yield)(long res) {}
+
+PRE_SYSCALL(sched_get_priority_max)(long policy) {}
+
+POST_SYSCALL(sched_get_priority_max)(long res, long policy) {}
+
+PRE_SYSCALL(sched_get_priority_min)(long policy) {}
+
+POST_SYSCALL(sched_get_priority_min)(long res, long policy) {}
+
+PRE_SYSCALL(sched_rr_get_interval)(long pid, void *interval) {}
+
+POST_SYSCALL(sched_rr_get_interval)(long res, long pid, void *interval) {
+ if (res >= 0) {
+ if (interval)
+ POST_WRITE(interval, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(setpriority)(long which, long who, long niceval) {}
+
+POST_SYSCALL(setpriority)(long res, long which, long who, long niceval) {}
+
+PRE_SYSCALL(getpriority)(long which, long who) {}
+
+POST_SYSCALL(getpriority)(long res, long which, long who) {}
+
+PRE_SYSCALL(shutdown)(long arg0, long arg1) {}
+
+POST_SYSCALL(shutdown)(long res, long arg0, long arg1) {}
+
+PRE_SYSCALL(reboot)(long magic1, long magic2, long cmd, void *arg) {}
+
+POST_SYSCALL(reboot)(long res, long magic1, long magic2, long cmd, void *arg) {}
+
+PRE_SYSCALL(restart_syscall)() {}
+
+POST_SYSCALL(restart_syscall)(long res) {}
+
+PRE_SYSCALL(kexec_load)
+(long entry, long nr_segments, void *segments, long flags) {}
+
+POST_SYSCALL(kexec_load)
+(long res, long entry, long nr_segments, void *segments, long flags) {
+ if (res >= 0) {
+ if (segments)
+ POST_WRITE(segments, struct_kexec_segment_sz);
+ }
+}
+
+PRE_SYSCALL(exit)(long error_code) {}
+
+POST_SYSCALL(exit)(long res, long error_code) {}
+
+PRE_SYSCALL(exit_group)(long error_code) {}
+
+POST_SYSCALL(exit_group)(long res, long error_code) {}
+
+PRE_SYSCALL(wait4)(long pid, void *stat_addr, long options, void *ru) {}
+
+POST_SYSCALL(wait4)
+(long res, long pid, void *stat_addr, long options, void *ru) {
+ if (res >= 0) {
+ if (stat_addr)
+ POST_WRITE(stat_addr, sizeof(int));
+ if (ru)
+ POST_WRITE(ru, struct_rusage_sz);
+ }
+}
+
+PRE_SYSCALL(waitid)
+(long which, long pid, void *infop, long options, void *ru) {}
+
+POST_SYSCALL(waitid)
+(long res, long which, long pid, void *infop, long options, void *ru) {
+ if (res >= 0) {
+ if (infop)
+ POST_WRITE(infop, siginfo_t_sz);
+ if (ru)
+ POST_WRITE(ru, struct_rusage_sz);
+ }
+}
+
+PRE_SYSCALL(waitpid)(long pid, void *stat_addr, long options) {}
+
+POST_SYSCALL(waitpid)(long res, long pid, void *stat_addr, long options) {
+ if (res >= 0) {
+ if (stat_addr)
+ POST_WRITE(stat_addr, sizeof(int));
+ }
+}
+
+PRE_SYSCALL(set_tid_address)(void *tidptr) {}
+
+POST_SYSCALL(set_tid_address)(long res, void *tidptr) {
+ if (res >= 0) {
+ if (tidptr)
+ POST_WRITE(tidptr, sizeof(int));
+ }
+}
+
+PRE_SYSCALL(init_module)(void *umod, long len, const void *uargs) {
+ if (uargs)
+ PRE_READ(uargs, __sanitizer::internal_strlen((const char *)uargs) + 1);
+}
+
+POST_SYSCALL(init_module)(long res, void *umod, long len, const void *uargs) {}
+
+PRE_SYSCALL(delete_module)(const void *name_user, long flags) {
+ if (name_user)
+ PRE_READ(name_user,
+ __sanitizer::internal_strlen((const char *)name_user) + 1);
+}
+
+POST_SYSCALL(delete_module)(long res, const void *name_user, long flags) {}
+
+PRE_SYSCALL(rt_sigprocmask)(long how, void *set, void *oset, long sigsetsize) {}
+
+POST_SYSCALL(rt_sigprocmask)
+(long res, long how, kernel_sigset_t *set, kernel_sigset_t *oset,
+ long sigsetsize) {
+ if (res >= 0) {
+ if (set)
+ POST_WRITE(set, sigsetsize);
+ if (oset)
+ POST_WRITE(oset, sigsetsize);
+ }
+}
+
+PRE_SYSCALL(rt_sigpending)(void *set, long sigsetsize) {}
+
+POST_SYSCALL(rt_sigpending)(long res, kernel_sigset_t *set, long sigsetsize) {
+ if (res >= 0) {
+ if (set)
+ POST_WRITE(set, sigsetsize);
+ }
+}
+
+PRE_SYSCALL(rt_sigtimedwait)
+(const kernel_sigset_t *uthese, void *uinfo, const void *uts, long sigsetsize) {
+ if (uthese)
+ PRE_READ(uthese, sigsetsize);
+ if (uts)
+ PRE_READ(uts, struct_timespec_sz);
+}
+
+POST_SYSCALL(rt_sigtimedwait)
+(long res, const void *uthese, void *uinfo, const void *uts, long sigsetsize) {
+ if (res >= 0) {
+ if (uinfo)
+ POST_WRITE(uinfo, siginfo_t_sz);
+ }
+}
+
+PRE_SYSCALL(rt_tgsigqueueinfo)(long tgid, long pid, long sig, void *uinfo) {}
+
+POST_SYSCALL(rt_tgsigqueueinfo)
+(long res, long tgid, long pid, long sig, void *uinfo) {
+ if (res >= 0) {
+ if (uinfo)
+ POST_WRITE(uinfo, siginfo_t_sz);
+ }
+}
+
+PRE_SYSCALL(kill)(long pid, long sig) {}
+
+POST_SYSCALL(kill)(long res, long pid, long sig) {}
+
+PRE_SYSCALL(tgkill)(long tgid, long pid, long sig) {}
+
+POST_SYSCALL(tgkill)(long res, long tgid, long pid, long sig) {}
+
+PRE_SYSCALL(tkill)(long pid, long sig) {}
+
+POST_SYSCALL(tkill)(long res, long pid, long sig) {}
+
+PRE_SYSCALL(rt_sigqueueinfo)(long pid, long sig, void *uinfo) {}
+
+POST_SYSCALL(rt_sigqueueinfo)(long res, long pid, long sig, void *uinfo) {
+ if (res >= 0) {
+ if (uinfo)
+ POST_WRITE(uinfo, siginfo_t_sz);
+ }
+}
+
+PRE_SYSCALL(sgetmask)() {}
+
+POST_SYSCALL(sgetmask)(long res) {}
+
+PRE_SYSCALL(ssetmask)(long newmask) {}
+
+POST_SYSCALL(ssetmask)(long res, long newmask) {}
+
+PRE_SYSCALL(signal)(long sig, long handler) {}
+
+POST_SYSCALL(signal)(long res, long sig, long handler) {}
+
+PRE_SYSCALL(pause)() {}
+
+POST_SYSCALL(pause)(long res) {}
+
+PRE_SYSCALL(sync)() {}
+
+POST_SYSCALL(sync)(long res) {}
+
+PRE_SYSCALL(fsync)(long fd) {}
+
+POST_SYSCALL(fsync)(long res, long fd) {}
+
+PRE_SYSCALL(fdatasync)(long fd) {}
+
+POST_SYSCALL(fdatasync)(long res, long fd) {}
+
+PRE_SYSCALL(bdflush)(long func, long data) {}
+
+POST_SYSCALL(bdflush)(long res, long func, long data) {}
+
+PRE_SYSCALL(mount)
+(void *dev_name, void *dir_name, void *type, long flags, void *data) {}
+
+POST_SYSCALL(mount)
+(long res, void *dev_name, void *dir_name, void *type, long flags, void *data) {
+ if (res >= 0) {
+ if (dev_name)
+ POST_WRITE(dev_name,
+ __sanitizer::internal_strlen((const char *)dev_name) + 1);
+ if (dir_name)
+ POST_WRITE(dir_name,
+ __sanitizer::internal_strlen((const char *)dir_name) + 1);
+ if (type)
+ POST_WRITE(type, __sanitizer::internal_strlen((const char *)type) + 1);
+ }
+}
+
+PRE_SYSCALL(umount)(void *name, long flags) {}
+
+POST_SYSCALL(umount)(long res, void *name, long flags) {
+ if (res >= 0) {
+ if (name)
+ POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ }
+}
+
+PRE_SYSCALL(oldumount)(void *name) {}
+
+POST_SYSCALL(oldumount)(long res, void *name) {
+ if (res >= 0) {
+ if (name)
+ POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ }
+}
+
+PRE_SYSCALL(truncate)(const void *path, long length) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(truncate)(long res, const void *path, long length) {}
+
+PRE_SYSCALL(ftruncate)(long fd, long length) {}
+
+POST_SYSCALL(ftruncate)(long res, long fd, long length) {}
+
+PRE_SYSCALL(stat)(const void *filename, void *statbuf) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(stat)(long res, const void *filename, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf)
+ POST_WRITE(statbuf, struct___old_kernel_stat_sz);
+ }
+}
+
+# if !SANITIZER_ANDROID
+PRE_SYSCALL(statfs)(const void *path, void *buf) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(statfs)(long res, const void *path, void *buf) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, struct_statfs_sz);
+ }
+}
+
+PRE_SYSCALL(fstatfs)(long fd, void *buf) {}
+
+POST_SYSCALL(fstatfs)(long res, long fd, void *buf) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, struct_statfs_sz);
+ }
+}
+# endif // !SANITIZER_ANDROID
+
+# if SANITIZER_GLIBC
+PRE_SYSCALL(statfs64)(const void *path, long sz, void *buf) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(statfs64)(long res, const void *path, long sz, void *buf) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, struct_statfs64_sz);
+ }
+}
+
+PRE_SYSCALL(fstatfs64)(long fd, long sz, void *buf) {}
+
+POST_SYSCALL(fstatfs64)(long res, long fd, long sz, void *buf) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, struct_statfs64_sz);
+ }
+}
+# endif // SANITIZER_GLIBC
+
+PRE_SYSCALL(lstat)(const void *filename, void *statbuf) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(lstat)(long res, const void *filename, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf)
+ POST_WRITE(statbuf, struct___old_kernel_stat_sz);
+ }
+}
+
+PRE_SYSCALL(fstat)(long fd, void *statbuf) {}
+
+POST_SYSCALL(fstat)(long res, long fd, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf)
+ POST_WRITE(statbuf, struct___old_kernel_stat_sz);
+ }
+}
+
+PRE_SYSCALL(newstat)(const void *filename, void *statbuf) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(newstat)(long res, const void *filename, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat_sz);
+ }
+}
+
+PRE_SYSCALL(newlstat)(const void *filename, void *statbuf) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(newlstat)(long res, const void *filename, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat_sz);
+ }
+}
+
+PRE_SYSCALL(newfstat)(long fd, void *statbuf) {}
+
+POST_SYSCALL(newfstat)(long res, long fd, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat_sz);
+ }
+}
+
+# if SANITIZER_GLIBC
+PRE_SYSCALL(ustat)(long dev, void *ubuf) {}
+
+POST_SYSCALL(ustat)(long res, long dev, void *ubuf) {
+ if (res >= 0) {
+ if (ubuf)
+ POST_WRITE(ubuf, struct_ustat_sz);
+ }
+}
+# endif // SANITIZER_GLIBC
+
+PRE_SYSCALL(stat64)(const void *filename, void *statbuf) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(stat64)(long res, const void *filename, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat64_sz);
+ }
+}
+
+PRE_SYSCALL(fstat64)(long fd, void *statbuf) {}
+
+POST_SYSCALL(fstat64)(long res, long fd, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat64_sz);
+ }
+}
+
+PRE_SYSCALL(lstat64)(const void *filename, void *statbuf) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(lstat64)(long res, const void *filename, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat64_sz);
+ }
+}
+
+PRE_SYSCALL(setxattr)
+(const void *path, const void *name, const void *value, long size, long flags) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ if (value)
+ PRE_READ(value, size);
+}
+
+POST_SYSCALL(setxattr)
+(long res, const void *path, const void *name, const void *value, long size,
+ long flags) {}
+
+PRE_SYSCALL(lsetxattr)
+(const void *path, const void *name, const void *value, long size, long flags) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ if (value)
+ PRE_READ(value, size);
+}
+
+POST_SYSCALL(lsetxattr)
+(long res, const void *path, const void *name, const void *value, long size,
+ long flags) {}
+
+PRE_SYSCALL(fsetxattr)
+(long fd, const void *name, const void *value, long size, long flags) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ if (value)
+ PRE_READ(value, size);
+}
+
+POST_SYSCALL(fsetxattr)
+(long res, long fd, const void *name, const void *value, long size,
+ long flags) {}
+
+PRE_SYSCALL(getxattr)
+(const void *path, const void *name, void *value, long size) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(getxattr)
+(long res, const void *path, const void *name, void *value, long size) {
+ if (size && res > 0) {
+ if (value)
+ POST_WRITE(value, res);
+ }
+}
+
+PRE_SYSCALL(lgetxattr)
+(const void *path, const void *name, void *value, long size) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(lgetxattr)
+(long res, const void *path, const void *name, void *value, long size) {
+ if (size && res > 0) {
+ if (value)
+ POST_WRITE(value, res);
+ }
+}
+
+PRE_SYSCALL(fgetxattr)(long fd, const void *name, void *value, long size) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(fgetxattr)
+(long res, long fd, const void *name, void *value, long size) {
+ if (size && res > 0) {
+ if (value)
+ POST_WRITE(value, res);
+ }
+}
+
+PRE_SYSCALL(listxattr)(const void *path, void *list, long size) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(listxattr)(long res, const void *path, void *list, long size) {
+ if (size && res > 0) {
+ if (list)
+ POST_WRITE(list, res);
+ }
+}
+
+PRE_SYSCALL(llistxattr)(const void *path, void *list, long size) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(llistxattr)(long res, const void *path, void *list, long size) {
+ if (size && res > 0) {
+ if (list)
+ POST_WRITE(list, res);
+ }
+}
+
+PRE_SYSCALL(flistxattr)(long fd, void *list, long size) {}
+
+POST_SYSCALL(flistxattr)(long res, long fd, void *list, long size) {
+ if (size && res > 0) {
+ if (list)
+ POST_WRITE(list, res);
+ }
+}
+
+PRE_SYSCALL(removexattr)(const void *path, const void *name) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(removexattr)(long res, const void *path, const void *name) {}
+
+PRE_SYSCALL(lremovexattr)(const void *path, const void *name) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(lremovexattr)(long res, const void *path, const void *name) {}
+
+PRE_SYSCALL(fremovexattr)(long fd, const void *name) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(fremovexattr)(long res, long fd, const void *name) {}
+
+PRE_SYSCALL(brk)(long brk) {}
+
+POST_SYSCALL(brk)(long res, long brk) {}
+
+PRE_SYSCALL(mprotect)(long start, long len, long prot) {}
+
+POST_SYSCALL(mprotect)(long res, long start, long len, long prot) {}
+
+PRE_SYSCALL(mremap)
+(long addr, long old_len, long new_len, long flags, long new_addr) {}
+
+POST_SYSCALL(mremap)
+(long res, long addr, long old_len, long new_len, long flags, long new_addr) {}
+
+PRE_SYSCALL(remap_file_pages)
+(long start, long size, long prot, long pgoff, long flags) {}
+
+POST_SYSCALL(remap_file_pages)
+(long res, long start, long size, long prot, long pgoff, long flags) {}
+
+PRE_SYSCALL(msync)(long start, long len, long flags) {}
+
+POST_SYSCALL(msync)(long res, long start, long len, long flags) {}
+
+PRE_SYSCALL(munmap)(long addr, long len) {}
+
+POST_SYSCALL(munmap)(long res, long addr, long len) {}
+
+PRE_SYSCALL(mlock)(long start, long len) {}
+
+POST_SYSCALL(mlock)(long res, long start, long len) {}
+
+PRE_SYSCALL(munlock)(long start, long len) {}
+
+POST_SYSCALL(munlock)(long res, long start, long len) {}
+
+PRE_SYSCALL(mlockall)(long flags) {}
+
+POST_SYSCALL(mlockall)(long res, long flags) {}
+
+PRE_SYSCALL(munlockall)() {}
+
+POST_SYSCALL(munlockall)(long res) {}
+
+PRE_SYSCALL(madvise)(long start, long len, long behavior) {}
+
+POST_SYSCALL(madvise)(long res, long start, long len, long behavior) {}
+
+PRE_SYSCALL(mincore)(long start, long len, void *vec) {}
+
+POST_SYSCALL(mincore)(long res, long start, long len, void *vec) {
+ if (res >= 0) {
+ if (vec) {
+ POST_WRITE(vec, (len + GetPageSizeCached() - 1) / GetPageSizeCached());
+ }
+ }
+}
+
+PRE_SYSCALL(pivot_root)(const void *new_root, const void *put_old) {
+ if (new_root)
+ PRE_READ(new_root,
+ __sanitizer::internal_strlen((const char *)new_root) + 1);
+ if (put_old)
+ PRE_READ(put_old, __sanitizer::internal_strlen((const char *)put_old) + 1);
+}
+
+POST_SYSCALL(pivot_root)(long res, const void *new_root, const void *put_old) {}
+
+PRE_SYSCALL(chroot)(const void *filename) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(chroot)(long res, const void *filename) {}
+
+PRE_SYSCALL(mknod)(const void *filename, long mode, long dev) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(mknod)(long res, const void *filename, long mode, long dev) {}
+
+PRE_SYSCALL(link)(const void *oldname, const void *newname) {
+ if (oldname)
+ PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
+ if (newname)
+ PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
+}
+
+POST_SYSCALL(link)(long res, const void *oldname, const void *newname) {}
+
+PRE_SYSCALL(symlink)(const void *old, const void *new_) {
+ if (old)
+ PRE_READ(old, __sanitizer::internal_strlen((const char *)old) + 1);
+ if (new_)
+ PRE_READ(new_, __sanitizer::internal_strlen((const char *)new_) + 1);
+}
+
+POST_SYSCALL(symlink)(long res, const void *old, const void *new_) {}
+
+PRE_SYSCALL(unlink)(const void *pathname) {
+ if (pathname)
+ PRE_READ(pathname,
+ __sanitizer::internal_strlen((const char *)pathname) + 1);
+}
+
+POST_SYSCALL(unlink)(long res, const void *pathname) {}
+
+PRE_SYSCALL(rename)(const void *oldname, const void *newname) {
+ if (oldname)
+ PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
+ if (newname)
+ PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
+}
+
+POST_SYSCALL(rename)(long res, const void *oldname, const void *newname) {}
+
+PRE_SYSCALL(chmod)(const void *filename, long mode) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(chmod)(long res, const void *filename, long mode) {}
+
+PRE_SYSCALL(fchmod)(long fd, long mode) {}
+
+POST_SYSCALL(fchmod)(long res, long fd, long mode) {}
+
+PRE_SYSCALL(fcntl)(long fd, long cmd, long arg) {}
+
+POST_SYSCALL(fcntl)(long res, long fd, long cmd, long arg) {}
+
+PRE_SYSCALL(fcntl64)(long fd, long cmd, long arg) {}
+
+POST_SYSCALL(fcntl64)(long res, long fd, long cmd, long arg) {}
+
+PRE_SYSCALL(pipe)(void *fildes) {}
+
+POST_SYSCALL(pipe)(long res, void *fildes) {
+ if (res >= 0)
+ if (fildes)
+ POST_WRITE(fildes, sizeof(int) * 2);
+}
+
+PRE_SYSCALL(pipe2)(void *fildes, long flags) {}
+
+POST_SYSCALL(pipe2)(long res, void *fildes, long flags) {
+ if (res >= 0)
+ if (fildes)
+ POST_WRITE(fildes, sizeof(int) * 2);
+}
+
+PRE_SYSCALL(dup)(long fildes) {}
+
+POST_SYSCALL(dup)(long res, long fildes) {}
+
+PRE_SYSCALL(dup2)(long oldfd, long newfd) {}
+
+POST_SYSCALL(dup2)(long res, long oldfd, long newfd) {}
+
+PRE_SYSCALL(dup3)(long oldfd, long newfd, long flags) {}
+
+POST_SYSCALL(dup3)(long res, long oldfd, long newfd, long flags) {}
+
+PRE_SYSCALL(ioperm)(long from, long num, long on) {}
+
+POST_SYSCALL(ioperm)(long res, long from, long num, long on) {}
+
+PRE_SYSCALL(ioctl)(long fd, long cmd, long arg) {}
+
+POST_SYSCALL(ioctl)(long res, long fd, long cmd, long arg) {}
+
+PRE_SYSCALL(flock)(long fd, long cmd) {}
+
+POST_SYSCALL(flock)(long res, long fd, long cmd) {}
+
+PRE_SYSCALL(io_setup)(long nr_reqs, void **ctx) {
+ if (ctx)
+ PRE_WRITE(ctx, sizeof(*ctx));
+}
+
+POST_SYSCALL(io_setup)(long res, long nr_reqs, void **ctx) {
+ if (res >= 0) {
+ if (ctx)
+ POST_WRITE(ctx, sizeof(*ctx));
+ // (*ctx) is actually a pointer to a kernel mapped page, and there are
+ // people out there who are crazy enough to peek into that page's 32-byte
+ // header.
+ if (*ctx)
+ POST_WRITE(*ctx, 32);
+ }
+}
+
+PRE_SYSCALL(io_destroy)(long ctx) {}
+
+POST_SYSCALL(io_destroy)(long res, long ctx) {}
+
+PRE_SYSCALL(io_getevents)
+(long ctx_id, long min_nr, long nr, __sanitizer_io_event *ioevpp,
+ void *timeout) {
+ if (timeout)
+ PRE_READ(timeout, struct_timespec_sz);
+}
+
+POST_SYSCALL(io_getevents)
+(long res, long ctx_id, long min_nr, long nr, __sanitizer_io_event *ioevpp,
+ void *timeout) {
+ if (res >= 0) {
+ if (ioevpp)
+ POST_WRITE(ioevpp, res * sizeof(*ioevpp));
+ if (timeout)
+ POST_WRITE(timeout, struct_timespec_sz);
+ }
+ for (long i = 0; i < res; i++) {
+ // We synchronize io_submit -> io_getevents/io_cancel using the
+ // user-provided data context. Data is not necessary a pointer, it can be
+ // an int, 0 or whatever; acquire/release will correctly handle this.
+ // This scheme can lead to false negatives, e.g. when all operations
+ // synchronize on 0. But there does not seem to be a better solution
+ // (except wrapping all operations in own context, which is unreliable).
+ // We can not reliably extract fildes in io_getevents.
+ COMMON_SYSCALL_ACQUIRE((void *)ioevpp[i].data);
+ }
+}
+
+PRE_SYSCALL(io_submit)(long ctx_id, long nr, __sanitizer_iocb **iocbpp) {
+ for (long i = 0; i < nr; ++i) {
+ uptr op = iocbpp[i]->aio_lio_opcode;
+ void *data = (void *)iocbpp[i]->aio_data;
+ void *buf = (void *)iocbpp[i]->aio_buf;
+ uptr len = (uptr)iocbpp[i]->aio_nbytes;
+ if (op == iocb_cmd_pwrite && buf && len) {
+ PRE_READ(buf, len);
+ } else if (op == iocb_cmd_pread && buf && len) {
+ POST_WRITE(buf, len);
+ } else if (op == iocb_cmd_pwritev) {
+ __sanitizer_iovec *iovec = (__sanitizer_iovec *)buf;
+ for (uptr v = 0; v < len; v++)
+ PRE_READ(iovec[v].iov_base, iovec[v].iov_len);
+ } else if (op == iocb_cmd_preadv) {
+ __sanitizer_iovec *iovec = (__sanitizer_iovec *)buf;
+ for (uptr v = 0; v < len; v++)
+ POST_WRITE(iovec[v].iov_base, iovec[v].iov_len);
+ }
+ // See comment in io_getevents.
+ COMMON_SYSCALL_RELEASE(data);
+ }
+}
+
+POST_SYSCALL(io_submit)
+(long res, long ctx_id, long nr, __sanitizer_iocb **iocbpp) {}
+
+PRE_SYSCALL(io_cancel)
+(long ctx_id, __sanitizer_iocb *iocb, __sanitizer_io_event *result) {}
+
+POST_SYSCALL(io_cancel)
+(long res, long ctx_id, __sanitizer_iocb *iocb, __sanitizer_io_event *result) {
+ if (res == 0) {
+ if (result) {
+ // See comment in io_getevents.
+ COMMON_SYSCALL_ACQUIRE((void *)result->data);
+ POST_WRITE(result, sizeof(*result));
+ }
+ if (iocb)
+ POST_WRITE(iocb, sizeof(*iocb));
+ }
+}
+
+PRE_SYSCALL(sendfile)(long out_fd, long in_fd, void *offset, long count) {}
+
+POST_SYSCALL(sendfile)
+(long res, long out_fd, long in_fd, __sanitizer___kernel_off_t *offset,
+ long count) {
+ if (res >= 0) {
+ if (offset)
+ POST_WRITE(offset, sizeof(*offset));
+ }
+}
+
+PRE_SYSCALL(sendfile64)(long out_fd, long in_fd, void *offset, long count) {}
+
+POST_SYSCALL(sendfile64)
+(long res, long out_fd, long in_fd, __sanitizer___kernel_loff_t *offset,
+ long count) {
+ if (res >= 0) {
+ if (offset)
+ POST_WRITE(offset, sizeof(*offset));
+ }
+}
+
+PRE_SYSCALL(readlink)(const void *path, void *buf, long bufsiz) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(readlink)(long res, const void *path, void *buf, long bufsiz) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
+ }
+}
+
+PRE_SYSCALL(creat)(const void *pathname, long mode) {
+ if (pathname)
+ PRE_READ(pathname,
+ __sanitizer::internal_strlen((const char *)pathname) + 1);
+}
+
+POST_SYSCALL(creat)(long res, const void *pathname, long mode) {}
+
+PRE_SYSCALL(open)(const void *filename, long flags, long mode) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(open)(long res, const void *filename, long flags, long mode) {}
+
+PRE_SYSCALL(close)(long fd) { COMMON_SYSCALL_FD_CLOSE((int)fd); }
+
+POST_SYSCALL(close)(long res, long fd) {}
+
+PRE_SYSCALL(access)(const void *filename, long mode) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(access)(long res, const void *filename, long mode) {}
+
+PRE_SYSCALL(vhangup)() {}
+
+POST_SYSCALL(vhangup)(long res) {}
+
+PRE_SYSCALL(chown)(const void *filename, long user, long group) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(chown)(long res, const void *filename, long user, long group) {}
+
+PRE_SYSCALL(lchown)(const void *filename, long user, long group) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(lchown)(long res, const void *filename, long user, long group) {}
+
+PRE_SYSCALL(fchown)(long fd, long user, long group) {}
+
+POST_SYSCALL(fchown)(long res, long fd, long user, long group) {}
+
+# if SANITIZER_USES_UID16_SYSCALLS
+PRE_SYSCALL(chown16)(const void *filename, long user, long group) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(chown16)(long res, const void *filename, long user, long group) {}
+
+PRE_SYSCALL(lchown16)(const void *filename, long user, long group) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(lchown16)(long res, const void *filename, long user, long group) {}
+
+PRE_SYSCALL(fchown16)(long fd, long user, long group) {}
+
+POST_SYSCALL(fchown16)(long res, long fd, long user, long group) {}
+
+PRE_SYSCALL(setregid16)(long rgid, long egid) {}
+
+POST_SYSCALL(setregid16)(long res, long rgid, long egid) {}
+
+PRE_SYSCALL(setgid16)(long gid) {}
+
+POST_SYSCALL(setgid16)(long res, long gid) {}
+
+PRE_SYSCALL(setreuid16)(long ruid, long euid) {}
+
+POST_SYSCALL(setreuid16)(long res, long ruid, long euid) {}
+
+PRE_SYSCALL(setuid16)(long uid) {}
+
+POST_SYSCALL(setuid16)(long res, long uid) {}
+
+PRE_SYSCALL(setresuid16)(long ruid, long euid, long suid) {}
+
+POST_SYSCALL(setresuid16)(long res, long ruid, long euid, long suid) {}
+
+PRE_SYSCALL(getresuid16)(void *ruid, void *euid, void *suid) {}
+
+POST_SYSCALL(getresuid16)
+(long res, __sanitizer___kernel_old_uid_t *ruid,
+ __sanitizer___kernel_old_uid_t *euid, __sanitizer___kernel_old_uid_t *suid) {
+ if (res >= 0) {
+ if (ruid)
+ POST_WRITE(ruid, sizeof(*ruid));
+ if (euid)
+ POST_WRITE(euid, sizeof(*euid));
+ if (suid)
+ POST_WRITE(suid, sizeof(*suid));
+ }
+}
+
+PRE_SYSCALL(setresgid16)(long rgid, long egid, long sgid) {}
+
+POST_SYSCALL(setresgid16)(long res, long rgid, long egid, long sgid) {}
+
+PRE_SYSCALL(getresgid16)(void *rgid, void *egid, void *sgid) {}
+
+POST_SYSCALL(getresgid16)
+(long res, __sanitizer___kernel_old_gid_t *rgid,
+ __sanitizer___kernel_old_gid_t *egid, __sanitizer___kernel_old_gid_t *sgid) {
+ if (res >= 0) {
+ if (rgid)
+ POST_WRITE(rgid, sizeof(*rgid));
+ if (egid)
+ POST_WRITE(egid, sizeof(*egid));
+ if (sgid)
+ POST_WRITE(sgid, sizeof(*sgid));
+ }
+}
+
+PRE_SYSCALL(setfsuid16)(long uid) {}
+
+POST_SYSCALL(setfsuid16)(long res, long uid) {}
+
+PRE_SYSCALL(setfsgid16)(long gid) {}
+
+POST_SYSCALL(setfsgid16)(long res, long gid) {}
+
+PRE_SYSCALL(getgroups16)
+(long gidsetsize, __sanitizer___kernel_old_gid_t *grouplist) {}
+
+POST_SYSCALL(getgroups16)
+(long res, long gidsetsize, __sanitizer___kernel_old_gid_t *grouplist) {
+ if (res >= 0) {
+ if (grouplist)
+ POST_WRITE(grouplist, res * sizeof(*grouplist));
+ }
+}
+
+PRE_SYSCALL(setgroups16)
+(long gidsetsize, __sanitizer___kernel_old_gid_t *grouplist) {
+ if (grouplist)
+ POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
+}
+
+POST_SYSCALL(setgroups16)
+(long res, long gidsetsize, __sanitizer___kernel_old_gid_t *grouplist) {}
+
+PRE_SYSCALL(getuid16)() {}
+
+POST_SYSCALL(getuid16)(long res) {}
+
+PRE_SYSCALL(geteuid16)() {}
+
+POST_SYSCALL(geteuid16)(long res) {}
+
+PRE_SYSCALL(getgid16)() {}
+
+POST_SYSCALL(getgid16)(long res) {}
+
+PRE_SYSCALL(getegid16)() {}
+
+POST_SYSCALL(getegid16)(long res) {}
+# endif // SANITIZER_USES_UID16_SYSCALLS
+
+PRE_SYSCALL(utime)(void *filename, void *times) {}
+
+POST_SYSCALL(utime)(long res, void *filename, void *times) {
+ if (res >= 0) {
+ if (filename)
+ POST_WRITE(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+ if (times)
+ POST_WRITE(times, struct_utimbuf_sz);
+ }
+}
+
+PRE_SYSCALL(utimes)(void *filename, void *utimes) {}
+
+POST_SYSCALL(utimes)(long res, void *filename, void *utimes) {
+ if (res >= 0) {
+ if (filename)
+ POST_WRITE(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+ if (utimes)
+ POST_WRITE(utimes, timeval_sz);
+ }
+}
+
+PRE_SYSCALL(lseek)(long fd, long offset, long origin) {}
+
+POST_SYSCALL(lseek)(long res, long fd, long offset, long origin) {}
+
+PRE_SYSCALL(llseek)
+(long fd, long offset_high, long offset_low, void *result, long origin) {}
+
+POST_SYSCALL(llseek)
+(long res, long fd, long offset_high, long offset_low, void *result,
+ long origin) {
+ if (res >= 0) {
+ if (result)
+ POST_WRITE(result, sizeof(long long));
+ }
+}
+
+PRE_SYSCALL(readv)(long fd, const __sanitizer_iovec *vec, long vlen) {}
+
+POST_SYSCALL(readv)
+(long res, long fd, const __sanitizer_iovec *vec, long vlen) {
+ if (res >= 0) {
+ if (vec)
+ kernel_write_iovec(vec, vlen, res);
+ }
+}
+
+PRE_SYSCALL(write)(long fd, const void *buf, long count) {
+ if (buf)
+ PRE_READ(buf, count);
+}
+
+POST_SYSCALL(write)(long res, long fd, const void *buf, long count) {}
+
+PRE_SYSCALL(writev)(long fd, const __sanitizer_iovec *vec, long vlen) {}
+
+POST_SYSCALL(writev)
+(long res, long fd, const __sanitizer_iovec *vec, long vlen) {
+ if (res >= 0) {
+ if (vec)
+ kernel_read_iovec(vec, vlen, res);
+ }
+}
+
+# ifdef _LP64
+PRE_SYSCALL(pread64)(long fd, void *buf, long count, long pos) {}
+
+POST_SYSCALL(pread64)(long res, long fd, void *buf, long count, long pos) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, res);
+ }
+}
+
+PRE_SYSCALL(pwrite64)(long fd, const void *buf, long count, long pos) {
+ if (buf)
+ PRE_READ(buf, count);
+}
+
+POST_SYSCALL(pwrite64)
+(long res, long fd, const void *buf, long count, long pos) {}
+# else
+PRE_SYSCALL(pread64)(long fd, void *buf, long count, long pos0, long pos1) {}
+
+POST_SYSCALL(pread64)
+(long res, long fd, void *buf, long count, long pos0, long pos1) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, res);
+ }
+}
+
+PRE_SYSCALL(pwrite64)
+(long fd, const void *buf, long count, long pos0, long pos1) {
+ if (buf)
+ PRE_READ(buf, count);
+}
+
+POST_SYSCALL(pwrite64)
+(long res, long fd, const void *buf, long count, long pos0, long pos1) {}
+# endif
+
+PRE_SYSCALL(preadv)
+(long fd, const __sanitizer_iovec *vec, long vlen, long pos_l, long pos_h) {}
+
+POST_SYSCALL(preadv)
+(long res, long fd, const __sanitizer_iovec *vec, long vlen, long pos_l,
+ long pos_h) {
+ if (res >= 0) {
+ if (vec)
+ kernel_write_iovec(vec, vlen, res);
+ }
+}
+
+PRE_SYSCALL(pwritev)
+(long fd, const __sanitizer_iovec *vec, long vlen, long pos_l, long pos_h) {}
+
+POST_SYSCALL(pwritev)
+(long res, long fd, const __sanitizer_iovec *vec, long vlen, long pos_l,
+ long pos_h) {
+ if (res >= 0) {
+ if (vec)
+ kernel_read_iovec(vec, vlen, res);
+ }
+}
+
+PRE_SYSCALL(getcwd)(void *buf, long size) {}
+
+POST_SYSCALL(getcwd)(long res, void *buf, long size) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
+ }
+}
+
+PRE_SYSCALL(mkdir)(const void *pathname, long mode) {
+ if (pathname)
+ PRE_READ(pathname,
+ __sanitizer::internal_strlen((const char *)pathname) + 1);
+}
+
+POST_SYSCALL(mkdir)(long res, const void *pathname, long mode) {}
+
+PRE_SYSCALL(chdir)(const void *filename) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(chdir)(long res, const void *filename) {}
+
+PRE_SYSCALL(fchdir)(long fd) {}
+
+POST_SYSCALL(fchdir)(long res, long fd) {}
+
+PRE_SYSCALL(rmdir)(const void *pathname) {
+ if (pathname)
+ PRE_READ(pathname,
+ __sanitizer::internal_strlen((const char *)pathname) + 1);
+}
+
+POST_SYSCALL(rmdir)(long res, const void *pathname) {}
+
+PRE_SYSCALL(lookup_dcookie)(u64 cookie64, void *buf, long len) {}
+
+POST_SYSCALL(lookup_dcookie)(long res, u64 cookie64, void *buf, long len) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
+ }
+}
+
+PRE_SYSCALL(quotactl)(long cmd, const void *special, long id, void *addr) {
+ if (special)
+ PRE_READ(special, __sanitizer::internal_strlen((const char *)special) + 1);
+}
+
+POST_SYSCALL(quotactl)
+(long res, long cmd, const void *special, long id, void *addr) {}
+
+PRE_SYSCALL(getdents)(long fd, void *dirent, long count) {}
+
+POST_SYSCALL(getdents)(long res, long fd, void *dirent, long count) {
+ if (res >= 0) {
+ if (dirent)
+ POST_WRITE(dirent, res);
+ }
+}
+
+PRE_SYSCALL(getdents64)(long fd, void *dirent, long count) {}
+
+POST_SYSCALL(getdents64)(long res, long fd, void *dirent, long count) {
+ if (res >= 0) {
+ if (dirent)
+ POST_WRITE(dirent, res);
+ }
+}
+
+PRE_SYSCALL(setsockopt)
+(long fd, long level, long optname, void *optval, long optlen) {}
+
+POST_SYSCALL(setsockopt)
+(long res, long fd, long level, long optname, void *optval, long optlen) {
+ if (res >= 0) {
+ if (optval)
+ POST_WRITE(optval,
+ __sanitizer::internal_strlen((const char *)optval) + 1);
+ }
+}
+
+PRE_SYSCALL(getsockopt)
+(long fd, long level, long optname, void *optval, void *optlen) {}
+
+POST_SYSCALL(getsockopt)
+(long res, long fd, long level, long optname, void *optval, void *optlen) {
+ if (res >= 0) {
+ if (optval)
+ POST_WRITE(optval,
+ __sanitizer::internal_strlen((const char *)optval) + 1);
+ if (optlen)
+ POST_WRITE(optlen, sizeof(int));
+ }
+}
+
+PRE_SYSCALL(bind)(long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {}
+
+POST_SYSCALL(bind)
+(long res, long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {
+ if (res >= 0) {
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
+ }
+}
+
+PRE_SYSCALL(connect)(long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {}
+
+POST_SYSCALL(connect)
+(long res, long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {
+ if (res >= 0) {
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
+ }
+}
+
+PRE_SYSCALL(accept)(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {}
+
+POST_SYSCALL(accept)
+(long res, long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {
+ if (res >= 0) {
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2)
+ POST_WRITE(arg2, sizeof(unsigned));
+ }
+}
+
+PRE_SYSCALL(accept4)
+(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2, long arg3) {}
+
+POST_SYSCALL(accept4)
+(long res, long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2, long arg3) {
+ if (res >= 0) {
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2)
+ POST_WRITE(arg2, sizeof(unsigned));
+ }
+}
+
+PRE_SYSCALL(getsockname)
+(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {}
+
+POST_SYSCALL(getsockname)
+(long res, long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {
+ if (res >= 0) {
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2)
+ POST_WRITE(arg2, sizeof(unsigned));
+ }
+}
+
+PRE_SYSCALL(getpeername)
+(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {}
+
+POST_SYSCALL(getpeername)
+(long res, long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {
+ if (res >= 0) {
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2)
+ POST_WRITE(arg2, sizeof(unsigned));
+ }
+}
+
+PRE_SYSCALL(send)(long arg0, void *arg1, long arg2, long arg3) {}
+
+POST_SYSCALL(send)(long res, long arg0, void *arg1, long arg2, long arg3) {
+ if (res) {
+ if (arg1)
+ POST_READ(arg1, res);
+ }
+}
+
+PRE_SYSCALL(sendto)
+(long arg0, void *arg1, long arg2, long arg3, sanitizer_kernel_sockaddr *arg4,
+ long arg5) {}
+
+POST_SYSCALL(sendto)
+(long res, long arg0, void *arg1, long arg2, long arg3,
+ sanitizer_kernel_sockaddr *arg4, long arg5) {
+ if (res >= 0) {
+ if (arg1)
+ POST_READ(arg1, res);
+ if (arg4)
+ POST_WRITE(arg4, sizeof(*arg4));
+ }
+}
+
+PRE_SYSCALL(sendmsg)(long fd, void *msg, long flags) {}
+
+POST_SYSCALL(sendmsg)(long res, long fd, void *msg, long flags) {
+ // FIXME: POST_READ
+}
+
+PRE_SYSCALL(sendmmsg)(long fd, void *msg, long vlen, long flags) {}
+
+POST_SYSCALL(sendmmsg)(long res, long fd, void *msg, long vlen, long flags) {
+ // FIXME: POST_READ
+}
+
+PRE_SYSCALL(recv)(long arg0, void *buf, long len, long flags) {}
+
+POST_SYSCALL(recv)(long res, void *buf, long len, long flags) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, res);
+ }
+}
+
+PRE_SYSCALL(recvfrom)
+(long arg0, void *buf, long len, long flags, sanitizer_kernel_sockaddr *arg4,
+ void *arg5) {}
+
+POST_SYSCALL(recvfrom)
+(long res, long arg0, void *buf, long len, long flags,
+ sanitizer_kernel_sockaddr *arg4, void *arg5) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, res);
+ if (arg4)
+ POST_WRITE(arg4, sizeof(*arg4));
+ if (arg5)
+ POST_WRITE(arg5, sizeof(int));
+ }
+}
+
+PRE_SYSCALL(socket)(long arg0, long arg1, long arg2) {}
+
+POST_SYSCALL(socket)(long res, long arg0, long arg1, long arg2) {}
+
+PRE_SYSCALL(socketpair)(long arg0, long arg1, long arg2, int *sv) {}
+
+POST_SYSCALL(socketpair)(long res, long arg0, long arg1, long arg2, int *sv) {
+ if (res >= 0)
+ if (sv)
+ POST_WRITE(sv, sizeof(int) * 2);
+}
+
+PRE_SYSCALL(socketcall)(long call, void *args) {}
+
+POST_SYSCALL(socketcall)(long res, long call, void *args) {
+ if (res >= 0) {
+ if (args)
+ POST_WRITE(args, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(listen)(long arg0, long arg1) {}
+
+POST_SYSCALL(listen)(long res, long arg0, long arg1) {}
+
+PRE_SYSCALL(poll)(void *ufds, long nfds, long timeout) {}
+
+POST_SYSCALL(poll)
+(long res, __sanitizer_pollfd *ufds, long nfds, long timeout) {
+ if (res >= 0) {
+ if (ufds)
+ POST_WRITE(ufds, nfds * sizeof(*ufds));
+ }
+}
+
+PRE_SYSCALL(select)
+(long n, __sanitizer___kernel_fd_set *inp, __sanitizer___kernel_fd_set *outp,
+ __sanitizer___kernel_fd_set *exp, void *tvp) {}
+
+POST_SYSCALL(select)
+(long res, long n, __sanitizer___kernel_fd_set *inp,
+ __sanitizer___kernel_fd_set *outp, __sanitizer___kernel_fd_set *exp,
+ void *tvp) {
+ if (res >= 0) {
+ if (inp)
+ POST_WRITE(inp, sizeof(*inp));
+ if (outp)
+ POST_WRITE(outp, sizeof(*outp));
+ if (exp)
+ POST_WRITE(exp, sizeof(*exp));
+ if (tvp)
+ POST_WRITE(tvp, timeval_sz);
+ }
+}
+
+PRE_SYSCALL(old_select)(void *arg) {}
+
+POST_SYSCALL(old_select)(long res, void *arg) {}
+
+PRE_SYSCALL(epoll_create)(long size) {}
+
+POST_SYSCALL(epoll_create)(long res, long size) {}
+
+PRE_SYSCALL(epoll_create1)(long flags) {}
+
+POST_SYSCALL(epoll_create1)(long res, long flags) {}
+
+PRE_SYSCALL(epoll_ctl)(long epfd, long op, long fd, void *event) {}
+
+POST_SYSCALL(epoll_ctl)(long res, long epfd, long op, long fd, void *event) {
+ if (res >= 0) {
+ if (event)
+ POST_WRITE(event, struct_epoll_event_sz);
+ }
+}
+
+PRE_SYSCALL(epoll_wait)
+(long epfd, void *events, long maxevents, long timeout) {}
+
+POST_SYSCALL(epoll_wait)
+(long res, long epfd, void *events, long maxevents, long timeout) {
+ if (res >= 0) {
+ COMMON_SYSCALL_FD_ACQUIRE(epfd);
+ if (events)
+ POST_WRITE(events, res * struct_epoll_event_sz);
+ }
+}
+
+PRE_SYSCALL(epoll_pwait)
+(long epfd, void *events, long maxevents, long timeout,
+ const kernel_sigset_t *sigmask, long sigsetsize) {
+ if (sigmask)
+ PRE_READ(sigmask, sigsetsize);
+}
+
+POST_SYSCALL(epoll_pwait)
+(long res, long epfd, void *events, long maxevents, long timeout,
+ const void *sigmask, long sigsetsize) {
+ if (res >= 0) {
+ COMMON_SYSCALL_FD_ACQUIRE(epfd);
+ if (events)
+ POST_WRITE(events, res * struct_epoll_event_sz);
+ }
+}
+
+PRE_SYSCALL(epoll_pwait2)
+(long epfd, void *events, long maxevents,
+ const sanitizer_kernel_timespec *timeout, const kernel_sigset_t *sigmask,
+ long sigsetsize) {
+ if (timeout)
+ PRE_READ(timeout, sizeof(timeout));
+ if (sigmask)
+ PRE_READ(sigmask, sigsetsize);
+}
+
+POST_SYSCALL(epoll_pwait2)
+(long res, long epfd, void *events, long maxevents,
+ const sanitizer_kernel_timespec *timeout, const void *sigmask,
+ long sigsetsize) {
+ if (res >= 0) {
+ COMMON_SYSCALL_FD_ACQUIRE(epfd);
+ if (events)
+ POST_WRITE(events, res * struct_epoll_event_sz);
+ }
+}
+
+PRE_SYSCALL(gethostname)(void *name, long len) {}
+
+POST_SYSCALL(gethostname)(long res, void *name, long len) {
+ if (res >= 0) {
+ if (name)
+ POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ }
+}
+
+PRE_SYSCALL(sethostname)(void *name, long len) {}
+
+POST_SYSCALL(sethostname)(long res, void *name, long len) {
+ if (res >= 0) {
+ if (name)
+ POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ }
+}
+
+PRE_SYSCALL(setdomainname)(void *name, long len) {}
+
+POST_SYSCALL(setdomainname)(long res, void *name, long len) {
+ if (res >= 0) {
+ if (name)
+ POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ }
+}
+
+PRE_SYSCALL(newuname)(void *name) {}
+
+POST_SYSCALL(newuname)(long res, void *name) {
+ if (res >= 0) {
+ if (name)
+ POST_WRITE(name, struct_new_utsname_sz);
+ }
+}
+
+PRE_SYSCALL(uname)(void *arg0) {}
+
+POST_SYSCALL(uname)(long res, void *arg0) {
+ if (res >= 0) {
+ if (arg0)
+ POST_WRITE(arg0, struct_old_utsname_sz);
+ }
+}
+
+PRE_SYSCALL(olduname)(void *arg0) {}
+
+POST_SYSCALL(olduname)(long res, void *arg0) {
+ if (res >= 0) {
+ if (arg0)
+ POST_WRITE(arg0, struct_oldold_utsname_sz);
+ }
+}
+
+PRE_SYSCALL(getrlimit)(long resource, void *rlim) {}
+
+POST_SYSCALL(getrlimit)(long res, long resource, void *rlim) {
+ if (res >= 0) {
+ if (rlim)
+ POST_WRITE(rlim, struct_rlimit_sz);
+ }
+}
+
+PRE_SYSCALL(old_getrlimit)(long resource, void *rlim) {}
+
+POST_SYSCALL(old_getrlimit)(long res, long resource, void *rlim) {
+ if (res >= 0) {
+ if (rlim)
+ POST_WRITE(rlim, struct_rlimit_sz);
+ }
+}
+
+PRE_SYSCALL(setrlimit)(long resource, void *rlim) {}
+
+POST_SYSCALL(setrlimit)(long res, long resource, void *rlim) {
+ if (res >= 0) {
+ if (rlim)
+ POST_WRITE(rlim, struct_rlimit_sz);
+ }
+}
+
+# if SANITIZER_GLIBC
+PRE_SYSCALL(prlimit64)
+(long pid, long resource, const void *new_rlim, void *old_rlim) {
+ if (new_rlim)
+ PRE_READ(new_rlim, struct_rlimit64_sz);
+}
+
+POST_SYSCALL(prlimit64)
+(long res, long pid, long resource, const void *new_rlim, void *old_rlim) {
+ if (res >= 0) {
+ if (old_rlim)
+ POST_WRITE(old_rlim, struct_rlimit64_sz);
+ }
+}
+# endif
+
+PRE_SYSCALL(getrusage)(long who, void *ru) {}
+
+POST_SYSCALL(getrusage)(long res, long who, void *ru) {
+ if (res >= 0) {
+ if (ru)
+ POST_WRITE(ru, struct_rusage_sz);
+ }
+}
+
+PRE_SYSCALL(umask)(long mask) {}
+
+POST_SYSCALL(umask)(long res, long mask) {}
+
+PRE_SYSCALL(msgget)(long key, long msgflg) {}
+
+POST_SYSCALL(msgget)(long res, long key, long msgflg) {}
+
+PRE_SYSCALL(msgsnd)(long msqid, void *msgp, long msgsz, long msgflg) {
+ if (msgp)
+ PRE_READ(msgp, msgsz);
+}
+
+POST_SYSCALL(msgsnd)
+(long res, long msqid, void *msgp, long msgsz, long msgflg) {}
+
+PRE_SYSCALL(msgrcv)
+(long msqid, void *msgp, long msgsz, long msgtyp, long msgflg) {}
+
+POST_SYSCALL(msgrcv)
+(long res, long msqid, void *msgp, long msgsz, long msgtyp, long msgflg) {
+ if (res >= 0) {
+ if (msgp)
+ POST_WRITE(msgp, res);
+ }
+}
+
+# if !SANITIZER_ANDROID
+PRE_SYSCALL(msgctl)(long msqid, long cmd, void *buf) {}
+
+POST_SYSCALL(msgctl)(long res, long msqid, long cmd, void *buf) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, struct_msqid_ds_sz);
+ }
+}
+# endif
+
+PRE_SYSCALL(semget)(long key, long nsems, long semflg) {}
+
+POST_SYSCALL(semget)(long res, long key, long nsems, long semflg) {}
+
+PRE_SYSCALL(semop)(long semid, void *sops, long nsops) {}
+
+POST_SYSCALL(semop)(long res, long semid, void *sops, long nsops) {}
+
+PRE_SYSCALL(semctl)(long semid, long semnum, long cmd, void *arg) {}
+
+POST_SYSCALL(semctl)(long res, long semid, long semnum, long cmd, void *arg) {}
+
+PRE_SYSCALL(semtimedop)
+(long semid, void *sops, long nsops, const void *timeout) {
+ if (timeout)
+ PRE_READ(timeout, struct_timespec_sz);
+}
+
+POST_SYSCALL(semtimedop)
+(long res, long semid, void *sops, long nsops, const void *timeout) {}
+
+PRE_SYSCALL(shmat)(long shmid, void *shmaddr, long shmflg) {}
+
+POST_SYSCALL(shmat)(long res, long shmid, void *shmaddr, long shmflg) {
+ if (res >= 0) {
+ if (shmaddr)
+ POST_WRITE(shmaddr,
+ __sanitizer::internal_strlen((const char *)shmaddr) + 1);
+ }
+}
+
+PRE_SYSCALL(shmget)(long key, long size, long flag) {}
+
+POST_SYSCALL(shmget)(long res, long key, long size, long flag) {}
+
+PRE_SYSCALL(shmdt)(void *shmaddr) {}
+
+POST_SYSCALL(shmdt)(long res, void *shmaddr) {
+ if (res >= 0) {
+ if (shmaddr)
+ POST_WRITE(shmaddr,
+ __sanitizer::internal_strlen((const char *)shmaddr) + 1);
+ }
+}
+
+PRE_SYSCALL(ipc)
+(long call, long first, long second, long third, void *ptr, long fifth) {}
+
+POST_SYSCALL(ipc)
+(long res, long call, long first, long second, long third, void *ptr,
+ long fifth) {}
+
+# if !SANITIZER_ANDROID
+PRE_SYSCALL(shmctl)(long shmid, long cmd, void *buf) {}
+
+POST_SYSCALL(shmctl)(long res, long shmid, long cmd, void *buf) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, sizeof(__sanitizer_shmid_ds));
+ }
+}
+
+PRE_SYSCALL(mq_open)(const void *name, long oflag, long mode, void *attr) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(mq_open)
+(long res, const void *name, long oflag, long mode, void *attr) {
+ if (res >= 0) {
+ if (attr)
+ POST_WRITE(attr, struct_mq_attr_sz);
+ }
+}
+
+PRE_SYSCALL(mq_unlink)(const void *name) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(mq_unlink)(long res, const void *name) {}
+
+PRE_SYSCALL(mq_timedsend)
+(long mqdes, const void *msg_ptr, long msg_len, long msg_prio,
+ const void *abs_timeout) {
+ if (msg_ptr)
+ PRE_READ(msg_ptr, msg_len);
+ if (abs_timeout)
+ PRE_READ(abs_timeout, struct_timespec_sz);
+}
+
+POST_SYSCALL(mq_timedsend)
+(long res, long mqdes, const void *msg_ptr, long msg_len, long msg_prio,
+ const void *abs_timeout) {}
+
+PRE_SYSCALL(mq_timedreceive)
+(long mqdes, void *msg_ptr, long msg_len, void *msg_prio,
+ const void *abs_timeout) {
+ if (abs_timeout)
+ PRE_READ(abs_timeout, struct_timespec_sz);
+}
+
+POST_SYSCALL(mq_timedreceive)
+(long res, long mqdes, void *msg_ptr, long msg_len, int *msg_prio,
+ const void *abs_timeout) {
+ if (res >= 0) {
+ if (msg_ptr)
+ POST_WRITE(msg_ptr, res);
+ if (msg_prio)
+ POST_WRITE(msg_prio, sizeof(*msg_prio));
+ }
+}
+
+PRE_SYSCALL(mq_notify)(long mqdes, const void *notification) {
+ if (notification)
+ PRE_READ(notification, struct_sigevent_sz);
+}
+
+POST_SYSCALL(mq_notify)(long res, long mqdes, const void *notification) {}
+
+PRE_SYSCALL(mq_getsetattr)(long mqdes, const void *mqstat, void *omqstat) {
+ if (mqstat)
+ PRE_READ(mqstat, struct_mq_attr_sz);
+}
+
+POST_SYSCALL(mq_getsetattr)
+(long res, long mqdes, const void *mqstat, void *omqstat) {
+ if (res >= 0) {
+ if (omqstat)
+ POST_WRITE(omqstat, struct_mq_attr_sz);
+ }
+}
+# endif // SANITIZER_ANDROID
+
+PRE_SYSCALL(pciconfig_iobase)(long which, long bus, long devfn) {}
+
+POST_SYSCALL(pciconfig_iobase)(long res, long which, long bus, long devfn) {}
+
+PRE_SYSCALL(pciconfig_read)
+(long bus, long dfn, long off, long len, void *buf) {}
+
+POST_SYSCALL(pciconfig_read)
+(long res, long bus, long dfn, long off, long len, void *buf) {}
+
+PRE_SYSCALL(pciconfig_write)
+(long bus, long dfn, long off, long len, void *buf) {}
+
+POST_SYSCALL(pciconfig_write)
+(long res, long bus, long dfn, long off, long len, void *buf) {}
+
+PRE_SYSCALL(swapon)(const void *specialfile, long swap_flags) {
+ if (specialfile)
+ PRE_READ(specialfile,
+ __sanitizer::internal_strlen((const char *)specialfile) + 1);
+}
+
+POST_SYSCALL(swapon)(long res, const void *specialfile, long swap_flags) {}
+
+PRE_SYSCALL(swapoff)(const void *specialfile) {
+ if (specialfile)
+ PRE_READ(specialfile,
+ __sanitizer::internal_strlen((const char *)specialfile) + 1);
+}
+
+POST_SYSCALL(swapoff)(long res, const void *specialfile) {}
+
+PRE_SYSCALL(sysctl)(__sanitizer___sysctl_args *args) {
+ if (args) {
+ if (args->name)
+ PRE_READ(args->name, args->nlen * sizeof(*args->name));
+ if (args->newval)
+ PRE_READ(args->name, args->newlen);
+ }
+}
+
+POST_SYSCALL(sysctl)(long res, __sanitizer___sysctl_args *args) {
+ if (res >= 0) {
+ if (args && args->oldval && args->oldlenp) {
+ POST_WRITE(args->oldlenp, sizeof(*args->oldlenp));
+ POST_WRITE(args->oldval, *args->oldlenp);
+ }
+ }
+}
+
+PRE_SYSCALL(sysinfo)(void *info) {}
+
+POST_SYSCALL(sysinfo)(long res, void *info) {
+ if (res >= 0) {
+ if (info)
+ POST_WRITE(info, struct_sysinfo_sz);
+ }
+}
+
+PRE_SYSCALL(sysfs)(long option, long arg1, long arg2) {}
+
+POST_SYSCALL(sysfs)(long res, long option, long arg1, long arg2) {}
+
+PRE_SYSCALL(syslog)(long type, void *buf, long len) {}
+
+POST_SYSCALL(syslog)(long res, long type, void *buf, long len) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
+ }
+}
+
+PRE_SYSCALL(uselib)(const void *library) {
+ if (library)
+ PRE_READ(library, __sanitizer::internal_strlen((const char *)library) + 1);
+}
+
+POST_SYSCALL(uselib)(long res, const void *library) {}
+
+PRE_SYSCALL(ni_syscall)() {}
+
+POST_SYSCALL(ni_syscall)(long res) {}
+
+PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) {
+# if !SANITIZER_ANDROID && \
+ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
+ defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
+ defined(__loongarch__) || SANITIZER_RISCV64)
+ if (data) {
+ if (request == ptrace_setregs) {
+ PRE_READ((void *)data, struct_user_regs_struct_sz);
+ } else if (request == ptrace_setfpregs) {
+ PRE_READ((void *)data, struct_user_fpregs_struct_sz);
+ } else if (request == ptrace_setfpxregs) {
+ PRE_READ((void *)data, struct_user_fpxregs_struct_sz);
+ } else if (request == ptrace_setsiginfo) {
+ PRE_READ((void *)data, siginfo_t_sz);
+ } else if (request == ptrace_setregset) {
+ __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
+ PRE_READ(iov->iov_base, iov->iov_len);
+ }
+ }
+# endif
+}
+
+POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) {
+# if !SANITIZER_ANDROID && \
+ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
+ defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
+ defined(__loongarch__) || SANITIZER_RISCV64)
+ if (res >= 0 && data) {
+ // Note that this is different from the interceptor in
+ // sanitizer_common_interceptors.inc.
+ // PEEK* requests return resulting values through data pointer.
+ if (request == ptrace_getregs) {
+ POST_WRITE((void *)data, struct_user_regs_struct_sz);
+ } else if (request == ptrace_getfpregs) {
+ POST_WRITE((void *)data, struct_user_fpregs_struct_sz);
+ } else if (request == ptrace_getfpxregs) {
+ POST_WRITE((void *)data, struct_user_fpxregs_struct_sz);
+ } else if (request == ptrace_getsiginfo) {
+ POST_WRITE((void *)data, siginfo_t_sz);
+ } else if (request == ptrace_getregset) {
+ __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
+ POST_WRITE(iov->iov_base, iov->iov_len);
+ } else if (request == ptrace_peekdata || request == ptrace_peektext ||
+ request == ptrace_peekuser) {
+ POST_WRITE((void *)data, sizeof(void *));
+ }
+ }
+# endif
+}
+
+PRE_SYSCALL(add_key)
+(const void *_type, const void *_description, const void *_payload, long plen,
+ long destringid) {
+ if (_type)
+ PRE_READ(_type, __sanitizer::internal_strlen((const char *)_type) + 1);
+ if (_description)
+ PRE_READ(_description,
+ __sanitizer::internal_strlen((const char *)_description) + 1);
+}
+
+POST_SYSCALL(add_key)
+(long res, const void *_type, const void *_description, const void *_payload,
+ long plen, long destringid) {}
+
+PRE_SYSCALL(request_key)
+(const void *_type, const void *_description, const void *_callout_info,
+ long destringid) {
+ if (_type)
+ PRE_READ(_type, __sanitizer::internal_strlen((const char *)_type) + 1);
+ if (_description)
+ PRE_READ(_description,
+ __sanitizer::internal_strlen((const char *)_description) + 1);
+ if (_callout_info)
+ PRE_READ(_callout_info,
+ __sanitizer::internal_strlen((const char *)_callout_info) + 1);
+}
+
+POST_SYSCALL(request_key)
+(long res, const void *_type, const void *_description,
+ const void *_callout_info, long destringid) {}
+
+PRE_SYSCALL(keyctl)(long cmd, long arg2, long arg3, long arg4, long arg5) {}
+
+POST_SYSCALL(keyctl)
+(long res, long cmd, long arg2, long arg3, long arg4, long arg5) {}
+
+PRE_SYSCALL(ioprio_set)(long which, long who, long ioprio) {}
+
+POST_SYSCALL(ioprio_set)(long res, long which, long who, long ioprio) {}
+
+PRE_SYSCALL(ioprio_get)(long which, long who) {}
+
+POST_SYSCALL(ioprio_get)(long res, long which, long who) {}
+
+PRE_SYSCALL(set_mempolicy)(long mode, void *nmask, long maxnode) {}
+
+POST_SYSCALL(set_mempolicy)(long res, long mode, void *nmask, long maxnode) {
+ if (res >= 0) {
+ if (nmask)
+ POST_WRITE(nmask, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(migrate_pages)
+(long pid, long maxnode, const void *from, const void *to) {
+ if (from)
+ PRE_READ(from, sizeof(long));
+ if (to)
+ PRE_READ(to, sizeof(long));
+}
+
+POST_SYSCALL(migrate_pages)
+(long res, long pid, long maxnode, const void *from, const void *to) {}
+
+PRE_SYSCALL(move_pages)
+(long pid, long nr_pages, const void **pages, const int *nodes, int *status,
+ long flags) {
+ if (pages)
+ PRE_READ(pages, nr_pages * sizeof(*pages));
+ if (nodes)
+ PRE_READ(nodes, nr_pages * sizeof(*nodes));
+}
+
+POST_SYSCALL(move_pages)
+(long res, long pid, long nr_pages, const void **pages, const int *nodes,
+ int *status, long flags) {
+ if (res >= 0) {
+ if (status)
+ POST_WRITE(status, nr_pages * sizeof(*status));
+ }
+}
+
+PRE_SYSCALL(mbind)
+(long start, long len, long mode, void *nmask, long maxnode, long flags) {}
+
+POST_SYSCALL(mbind)
+(long res, long start, long len, long mode, void *nmask, long maxnode,
+ long flags) {
+ if (res >= 0) {
+ if (nmask)
+ POST_WRITE(nmask, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(get_mempolicy)
+(void *policy, void *nmask, long maxnode, long addr, long flags) {}
+
+POST_SYSCALL(get_mempolicy)
+(long res, void *policy, void *nmask, long maxnode, long addr, long flags) {
+ if (res >= 0) {
+ if (policy)
+ POST_WRITE(policy, sizeof(int));
+ if (nmask)
+ POST_WRITE(nmask, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(inotify_init)() {}
+
+POST_SYSCALL(inotify_init)(long res) {}
+
+PRE_SYSCALL(inotify_init1)(long flags) {}
+
+POST_SYSCALL(inotify_init1)(long res, long flags) {}
+
+PRE_SYSCALL(inotify_add_watch)(long fd, const void *path, long mask) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(inotify_add_watch)
+(long res, long fd, const void *path, long mask) {}
+
+PRE_SYSCALL(inotify_rm_watch)(long fd, long wd) {}
+
+POST_SYSCALL(inotify_rm_watch)(long res, long fd, long wd) {}
+
+PRE_SYSCALL(spu_run)(long fd, void *unpc, void *ustatus) {}
+
+POST_SYSCALL(spu_run)(long res, long fd, unsigned *unpc, unsigned *ustatus) {
+ if (res >= 0) {
+ if (unpc)
+ POST_WRITE(unpc, sizeof(*unpc));
+ if (ustatus)
+ POST_WRITE(ustatus, sizeof(*ustatus));
+ }
+}
+
+PRE_SYSCALL(spu_create)(const void *name, long flags, long mode, long fd) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(spu_create)
+(long res, const void *name, long flags, long mode, long fd) {}
+
+PRE_SYSCALL(mknodat)(long dfd, const void *filename, long mode, long dev) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(mknodat)
+(long res, long dfd, const void *filename, long mode, long dev) {}
+
+PRE_SYSCALL(mkdirat)(long dfd, const void *pathname, long mode) {
+ if (pathname)
+ PRE_READ(pathname,
+ __sanitizer::internal_strlen((const char *)pathname) + 1);
+}
+
+POST_SYSCALL(mkdirat)(long res, long dfd, const void *pathname, long mode) {}
+
+PRE_SYSCALL(unlinkat)(long dfd, const void *pathname, long flag) {
+ if (pathname)
+ PRE_READ(pathname,
+ __sanitizer::internal_strlen((const char *)pathname) + 1);
+}
+
+POST_SYSCALL(unlinkat)(long res, long dfd, const void *pathname, long flag) {}
+
+PRE_SYSCALL(symlinkat)(const void *oldname, long newdfd, const void *newname) {
+ if (oldname)
+ PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
+ if (newname)
+ PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
+}
+
+POST_SYSCALL(symlinkat)
+(long res, const void *oldname, long newdfd, const void *newname) {}
+
+PRE_SYSCALL(linkat)
+(long olddfd, const void *oldname, long newdfd, const void *newname,
+ long flags) {
+ if (oldname)
+ PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
+ if (newname)
+ PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
+}
+
+POST_SYSCALL(linkat)
+(long res, long olddfd, const void *oldname, long newdfd, const void *newname,
+ long flags) {}
+
+PRE_SYSCALL(renameat)
+(long olddfd, const void *oldname, long newdfd, const void *newname) {
+ if (oldname)
+ PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
+ if (newname)
+ PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
+}
+
+POST_SYSCALL(renameat)
+(long res, long olddfd, const void *oldname, long newdfd, const void *newname) {
+}
+
+PRE_SYSCALL(futimesat)(long dfd, const void *filename, void *utimes) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(futimesat)
+(long res, long dfd, const void *filename, void *utimes) {
+ if (res >= 0) {
+ if (utimes)
+ POST_WRITE(utimes, timeval_sz);
+ }
+}
+
+PRE_SYSCALL(faccessat)(long dfd, const void *filename, long mode) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(faccessat)(long res, long dfd, const void *filename, long mode) {}
+
+PRE_SYSCALL(fchmodat)(long dfd, const void *filename, long mode) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(fchmodat)(long res, long dfd, const void *filename, long mode) {}
+
+PRE_SYSCALL(fchownat)
+(long dfd, const void *filename, long user, long group, long flag) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(fchownat)
+(long res, long dfd, const void *filename, long user, long group, long flag) {}
+
+PRE_SYSCALL(openat)(long dfd, const void *filename, long flags, long mode) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(openat)
+(long res, long dfd, const void *filename, long flags, long mode) {}
+
+PRE_SYSCALL(newfstatat)
+(long dfd, const void *filename, void *statbuf, long flag) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(newfstatat)
+(long res, long dfd, const void *filename, void *statbuf, long flag) {
+ if (res >= 0) {
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat_sz);
+ }
+}
+
+PRE_SYSCALL(fstatat64)
+(long dfd, const void *filename, void *statbuf, long flag) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(fstatat64)
+(long res, long dfd, const void *filename, void *statbuf, long flag) {
+ if (res >= 0) {
+ if (statbuf)
+ POST_WRITE(statbuf, struct_kernel_stat64_sz);
+ }
+}
+
+PRE_SYSCALL(readlinkat)(long dfd, const void *path, void *buf, long bufsiz) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(readlinkat)
+(long res, long dfd, const void *path, void *buf, long bufsiz) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
+ }
+}
+
+PRE_SYSCALL(utimensat)
+(long dfd, const void *filename, void *utimes, long flags) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(utimensat)
+(long res, long dfd, const void *filename, void *utimes, long flags) {
+ if (res >= 0) {
+ if (utimes)
+ POST_WRITE(utimes, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(unshare)(long unshare_flags) {}
+
+POST_SYSCALL(unshare)(long res, long unshare_flags) {}
+
+PRE_SYSCALL(splice)
+(long fd_in, void *off_in, long fd_out, void *off_out, long len, long flags) {}
+
+POST_SYSCALL(splice)
+(long res, long fd_in, void *off_in, long fd_out, void *off_out, long len,
+ long flags) {
+ if (res >= 0) {
+ if (off_in)
+ POST_WRITE(off_in, sizeof(long long));
+ if (off_out)
+ POST_WRITE(off_out, sizeof(long long));
+ }
+}
+
+PRE_SYSCALL(vmsplice)
+(long fd, const __sanitizer_iovec *iov, long nr_segs, long flags) {}
+
+POST_SYSCALL(vmsplice)
+(long res, long fd, const __sanitizer_iovec *iov, long nr_segs, long flags) {
+ if (res >= 0) {
+ if (iov)
+ kernel_read_iovec(iov, nr_segs, res);
+ }
+}
+
+PRE_SYSCALL(tee)(long fdin, long fdout, long len, long flags) {}
+
+POST_SYSCALL(tee)(long res, long fdin, long fdout, long len, long flags) {}
+
+PRE_SYSCALL(get_robust_list)(long pid, void *head_ptr, void *len_ptr) {}
+
+POST_SYSCALL(get_robust_list)
+(long res, long pid, void *head_ptr, void *len_ptr) {}
+
+PRE_SYSCALL(set_robust_list)(void *head, long len) {}
+
+POST_SYSCALL(set_robust_list)(long res, void *head, long len) {}
+
+PRE_SYSCALL(getcpu)(void *cpu, void *node, void *cache) {}
+
+POST_SYSCALL(getcpu)(long res, void *cpu, void *node, void *cache) {
+ if (res >= 0) {
+ if (cpu)
+ POST_WRITE(cpu, sizeof(unsigned));
+ if (node)
+ POST_WRITE(node, sizeof(unsigned));
+ // The third argument to this system call is nowadays unused.
+ }
+}
+
+PRE_SYSCALL(signalfd)(long ufd, void *user_mask, long sizemask) {}
+
+POST_SYSCALL(signalfd)
+(long res, long ufd, kernel_sigset_t *user_mask, long sizemask) {
+ if (res >= 0) {
+ if (user_mask)
+ POST_WRITE(user_mask, sizemask);
+ }
+}
+
+PRE_SYSCALL(signalfd4)(long ufd, void *user_mask, long sizemask, long flags) {}
+
+POST_SYSCALL(signalfd4)
+(long res, long ufd, kernel_sigset_t *user_mask, long sizemask, long flags) {
+ if (res >= 0) {
+ if (user_mask)
+ POST_WRITE(user_mask, sizemask);
+ }
+}
+
+PRE_SYSCALL(timerfd_create)(long clockid, long flags) {}
+
+POST_SYSCALL(timerfd_create)(long res, long clockid, long flags) {}
+
+PRE_SYSCALL(timerfd_settime)
+(long ufd, long flags, const void *utmr, void *otmr) {
+ if (utmr)
+ PRE_READ(utmr, struct_itimerspec_sz);
+}
+
+POST_SYSCALL(timerfd_settime)
+(long res, long ufd, long flags, const void *utmr, void *otmr) {
+ if (res >= 0) {
+ if (otmr)
+ POST_WRITE(otmr, struct_itimerspec_sz);
+ }
+}
+
+PRE_SYSCALL(timerfd_gettime)(long ufd, void *otmr) {}
+
+POST_SYSCALL(timerfd_gettime)(long res, long ufd, void *otmr) {
+ if (res >= 0) {
+ if (otmr)
+ POST_WRITE(otmr, struct_itimerspec_sz);
+ }
+}
+
+PRE_SYSCALL(eventfd)(long count) {}
+
+POST_SYSCALL(eventfd)(long res, long count) {}
+
+PRE_SYSCALL(eventfd2)(long count, long flags) {}
+
+POST_SYSCALL(eventfd2)(long res, long count, long flags) {}
+
+PRE_SYSCALL(old_readdir)(long arg0, void *arg1, long arg2) {}
+
+POST_SYSCALL(old_readdir)(long res, long arg0, void *arg1, long arg2) {
+ // Missing definition of 'struct old_linux_dirent'.
+}
+
+PRE_SYSCALL(pselect6)
+(long arg0, __sanitizer___kernel_fd_set *arg1,
+ __sanitizer___kernel_fd_set *arg2, __sanitizer___kernel_fd_set *arg3,
+ void *arg4, void *arg5) {}
+
+POST_SYSCALL(pselect6)
+(long res, long arg0, __sanitizer___kernel_fd_set *arg1,
+ __sanitizer___kernel_fd_set *arg2, __sanitizer___kernel_fd_set *arg3,
+ void *arg4, void *arg5) {
+ if (res >= 0) {
+ if (arg1)
+ POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2)
+ POST_WRITE(arg2, sizeof(*arg2));
+ if (arg3)
+ POST_WRITE(arg3, sizeof(*arg3));
+ if (arg4)
+ POST_WRITE(arg4, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(ppoll)
+(__sanitizer_pollfd *arg0, long arg1, void *arg2, const kernel_sigset_t *arg3,
+ long arg4) {
+ if (arg3)
+ PRE_READ(arg3, arg4);
+}
+
+POST_SYSCALL(ppoll)
+(long res, __sanitizer_pollfd *arg0, long arg1, void *arg2, const void *arg3,
+ long arg4) {
+ if (res >= 0) {
+ if (arg0)
+ POST_WRITE(arg0, sizeof(*arg0));
+ if (arg2)
+ POST_WRITE(arg2, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(syncfs)(long fd) {}
+
+POST_SYSCALL(syncfs)(long res, long fd) {}
+
+PRE_SYSCALL(perf_event_open)
+(__sanitizer_perf_event_attr *attr_uptr, long pid, long cpu, long group_fd,
+ long flags) {
+ if (attr_uptr)
+ PRE_READ(attr_uptr, attr_uptr->size);
+}
+
+POST_SYSCALL(perf_event_open)
+(long res, __sanitizer_perf_event_attr *attr_uptr, long pid, long cpu,
+ long group_fd, long flags) {}
+
+PRE_SYSCALL(mmap_pgoff)
+(long addr, long len, long prot, long flags, long fd, long pgoff) {}
+
+POST_SYSCALL(mmap_pgoff)
+(long res, long addr, long len, long prot, long flags, long fd, long pgoff) {}
+
+PRE_SYSCALL(old_mmap)(void *arg) {}
+
+POST_SYSCALL(old_mmap)(long res, void *arg) {}
+
+PRE_SYSCALL(name_to_handle_at)
+(long dfd, const void *name, void *handle, void *mnt_id, long flag) {}
+
+POST_SYSCALL(name_to_handle_at)
+(long res, long dfd, const void *name, void *handle, void *mnt_id, long flag) {}
+
+PRE_SYSCALL(open_by_handle_at)(long mountdirfd, void *handle, long flags) {}
+
+POST_SYSCALL(open_by_handle_at)
+(long res, long mountdirfd, void *handle, long flags) {}
+
+PRE_SYSCALL(setns)(long fd, long nstype) {}
+
+POST_SYSCALL(setns)(long res, long fd, long nstype) {}
+
+PRE_SYSCALL(process_vm_readv)
+(long pid, const __sanitizer_iovec *lvec, long liovcnt, const void *rvec,
+ long riovcnt, long flags) {}
+
+POST_SYSCALL(process_vm_readv)
+(long res, long pid, const __sanitizer_iovec *lvec, long liovcnt,
+ const void *rvec, long riovcnt, long flags) {
+ if (res >= 0) {
+ if (lvec)
+ kernel_write_iovec(lvec, liovcnt, res);
+ }
+}
+
+PRE_SYSCALL(process_vm_writev)
+(long pid, const __sanitizer_iovec *lvec, long liovcnt, const void *rvec,
+ long riovcnt, long flags) {}
+
+POST_SYSCALL(process_vm_writev)
+(long res, long pid, const __sanitizer_iovec *lvec, long liovcnt,
+ const void *rvec, long riovcnt, long flags) {
+ if (res >= 0) {
+ if (lvec)
+ kernel_read_iovec(lvec, liovcnt, res);
+ }
+}
+
+PRE_SYSCALL(fork)() { COMMON_SYSCALL_PRE_FORK(); }
+
+POST_SYSCALL(fork)(long res) { COMMON_SYSCALL_POST_FORK(res); }
+
+PRE_SYSCALL(vfork)() { COMMON_SYSCALL_PRE_FORK(); }
+
+POST_SYSCALL(vfork)(long res) { COMMON_SYSCALL_POST_FORK(res); }
+
+PRE_SYSCALL(sigaction)
+(long signum, const __sanitizer_kernel_sigaction_t *act,
+ __sanitizer_kernel_sigaction_t *oldact) {
+ if (act) {
+ PRE_READ(&act->sigaction, sizeof(act->sigaction));
+ PRE_READ(&act->sa_flags, sizeof(act->sa_flags));
+ PRE_READ(&act->sa_mask, sizeof(act->sa_mask));
+ }
+}
+
+POST_SYSCALL(sigaction)
+(long res, long signum, const __sanitizer_kernel_sigaction_t *act,
+ __sanitizer_kernel_sigaction_t *oldact) {
+ if (res >= 0 && oldact)
+ POST_WRITE(oldact, sizeof(*oldact));
+}
+
+PRE_SYSCALL(rt_sigaction)
+(long signum, const __sanitizer_kernel_sigaction_t *act,
+ __sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
+ if (act) {
+ PRE_READ(&act->sigaction, sizeof(act->sigaction));
+ PRE_READ(&act->sa_flags, sizeof(act->sa_flags));
+ PRE_READ(&act->sa_mask, sz);
+ }
+}
+
+POST_SYSCALL(rt_sigaction)
+(long res, long signum, const __sanitizer_kernel_sigaction_t *act,
+ __sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
+ if (res >= 0 && oldact) {
+ SIZE_T oldact_sz = ((char *)&oldact->sa_mask) - ((char *)oldact) + sz;
+ POST_WRITE(oldact, oldact_sz);
+ }
+}
+
+PRE_SYSCALL(getrandom)(void *buf, uptr count, long flags) {
+ if (buf) {
+ PRE_WRITE(buf, count);
+ }
+}
+
+POST_SYSCALL(getrandom)(long res, void *buf, uptr count, long flags) {
+ if (res > 0 && buf) {
+ POST_WRITE(buf, res);
+ }
+}
+
+PRE_SYSCALL(sigaltstack)(const void *ss, void *oss) {
+ if (ss != nullptr) {
+ PRE_READ(ss, struct_stack_t_sz);
+ }
+ if (oss != nullptr) {
+ PRE_WRITE(oss, struct_stack_t_sz);
+ }
+}
+
+POST_SYSCALL(sigaltstack)(long res, void *ss, void *oss) {
+ if (res == 0) {
+ if (oss != nullptr) {
+ POST_WRITE(oss, struct_stack_t_sz);
+ }
+ }
+}
+} // extern "C"
+
+# undef PRE_SYSCALL
+# undef PRE_READ
+# undef PRE_WRITE
+# undef POST_SYSCALL
+# undef POST_READ
+# undef POST_WRITE
+
+#endif // SANITIZER_LINUX
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_fuchsia.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_fuchsia.cpp
new file mode 100644
index 00000000000..0171fb09d2d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_fuchsia.cpp
@@ -0,0 +1,254 @@
+//===-- sanitizer_coverage_fuchsia.cpp ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Sanitizer Coverage Controller for Trace PC Guard, Fuchsia-specific version.
+//
+// This Fuchsia-specific implementation uses the same basic scheme and the
+// same simple '.sancov' file format as the generic implementation. The
+// difference is that we just produce a single blob of output for the whole
+// program, not a separate one per DSO. We do not sort the PC table and do
+// not prune the zeros, so the resulting file is always as large as it
+// would be to report 100% coverage. Implicit tracing information about
+// the address ranges of DSOs allows offline tools to split the one big
+// blob into separate files that the 'sancov' tool can understand.
+//
+// Unlike the traditional implementation that uses an atexit hook to write
+// out data files at the end, the results on Fuchsia do not go into a file
+// per se. The 'coverage_dir' option is ignored. Instead, they are stored
+// directly into a shared memory object (a Zircon VMO). At exit, that VMO
+// is handed over to a system service that's responsible for getting the
+// data out to somewhere that it can be fed into the sancov tool (where and
+// how is not our problem).
+
+#include "sanitizer_platform.h"
+#if SANITIZER_FUCHSIA
+#error #include <zircon/process.h>
+#error #include <zircon/sanitizer.h>
+#error #include <zircon/syscalls.h>
+
+#include "sanitizer_atomic.h"
+#include "sanitizer_common.h"
+#include "sanitizer_interface_internal.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_symbolizer_fuchsia.h"
+
+using namespace __sanitizer;
+
+namespace __sancov {
+namespace {
+
+// TODO(mcgrathr): Move the constant into a header shared with other impls.
+constexpr u64 Magic64 = 0xC0BFFFFFFFFFFF64ULL;
+static_assert(SANITIZER_WORDSIZE == 64, "Fuchsia is always LP64");
+
+constexpr const char kSancovSinkName[] = "sancov";
+
+// Collects trace-pc guard coverage.
+// This class relies on zero-initialization.
+class TracePcGuardController final {
+ public:
+ constexpr TracePcGuardController() {}
+
+ // For each PC location being tracked, there is a u32 reserved in global
+ // data called the "guard". At startup, we assign each guard slot a
+ // unique index into the big results array. Later during runtime, the
+ // first call to TracePcGuard (below) will store the corresponding PC at
+ // that index in the array. (Each later call with the same guard slot is
+ // presumed to be from the same PC.) Then it clears the guard slot back
+ // to zero, which tells the compiler not to bother calling in again. At
+ // the end of the run, we have a big array where each element is either
+ // zero or is a tracked PC location that was hit in the trace.
+
+ // This is called from global constructors. Each translation unit has a
+ // contiguous array of guard slots, and a constructor that calls here
+ // with the bounds of its array. Those constructors are allowed to call
+ // here more than once for the same array. Usually all of these
+ // constructors run in the initial thread, but it's possible that a
+ // dlopen call on a secondary thread will run constructors that get here.
+ void InitTracePcGuard(u32 *start, u32 *end) {
+ if (end > start && *start == 0 && common_flags()->coverage) {
+ // Complete the setup before filling in any guards with indices.
+ // This avoids the possibility of code called from Setup reentering
+ // TracePcGuard.
+ u32 idx = Setup(end - start);
+ for (u32 *p = start; p < end; ++p) {
+ *p = idx++;
+ }
+ }
+ }
+
+ void TracePcGuard(u32 *guard, uptr pc) {
+ atomic_uint32_t *guard_ptr = reinterpret_cast<atomic_uint32_t *>(guard);
+ u32 idx = atomic_exchange(guard_ptr, 0, memory_order_relaxed);
+ if (idx > 0)
+ array_[idx] = pc;
+ }
+
+ void Dump() {
+ Lock locked(&setup_lock_);
+ if (array_) {
+ CHECK_NE(vmo_, ZX_HANDLE_INVALID);
+
+ // Publish the VMO to the system, where it can be collected and
+ // analyzed after this process exits. This always consumes the VMO
+ // handle. Any failure is just logged and not indicated to us.
+ __sanitizer_publish_data(kSancovSinkName, vmo_);
+ vmo_ = ZX_HANDLE_INVALID;
+
+ // This will route to __sanitizer_log_write, which will ensure that
+ // information about shared libraries is written out. This message
+ // uses the `dumpfile` symbolizer markup element to highlight the
+ // dump. See the explanation for this in:
+ // https://fuchsia.googlesource.com/zircon/+/master/docs/symbolizer_markup.md
+ Printf("SanitizerCoverage: " FORMAT_DUMPFILE " with up to %u PCs\n",
+ kSancovSinkName, vmo_name_, next_index_ - 1);
+ }
+ }
+
+ private:
+ // We map in the largest possible view into the VMO: one word
+ // for every possible 32-bit index value. This avoids the need
+ // to change the mapping when increasing the size of the VMO.
+ // We can always spare the 32G of address space.
+ static constexpr size_t MappingSize = sizeof(uptr) << 32;
+
+ Mutex setup_lock_;
+ uptr *array_ = nullptr;
+ u32 next_index_ = 0;
+ zx_handle_t vmo_ = {};
+ char vmo_name_[ZX_MAX_NAME_LEN] = {};
+
+ size_t DataSize() const { return next_index_ * sizeof(uintptr_t); }
+
+ u32 Setup(u32 num_guards) {
+ Lock locked(&setup_lock_);
+ DCHECK(common_flags()->coverage);
+
+ if (next_index_ == 0) {
+ CHECK_EQ(vmo_, ZX_HANDLE_INVALID);
+ CHECK_EQ(array_, nullptr);
+
+ // The first sample goes at [1] to reserve [0] for the magic number.
+ next_index_ = 1 + num_guards;
+
+ zx_status_t status = _zx_vmo_create(DataSize(), ZX_VMO_RESIZABLE, &vmo_);
+ CHECK_EQ(status, ZX_OK);
+
+ // Give the VMO a name including our process KOID so it's easy to spot.
+ internal_snprintf(vmo_name_, sizeof(vmo_name_), "%s.%zu", kSancovSinkName,
+ internal_getpid());
+ _zx_object_set_property(vmo_, ZX_PROP_NAME, vmo_name_,
+ internal_strlen(vmo_name_));
+ uint64_t size = DataSize();
+ status = _zx_object_set_property(vmo_, ZX_PROP_VMO_CONTENT_SIZE, &size,
+ sizeof(size));
+ CHECK_EQ(status, ZX_OK);
+
+ // Map the largest possible view we might need into the VMO. Later
+ // we might need to increase the VMO's size before we can use larger
+ // indices, but we'll never move the mapping address so we don't have
+ // any multi-thread synchronization issues with that.
+ uintptr_t mapping;
+ status =
+ _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
+ 0, vmo_, 0, MappingSize, &mapping);
+ CHECK_EQ(status, ZX_OK);
+
+ // Hereafter other threads are free to start storing into
+ // elements [1, next_index_) of the big array.
+ array_ = reinterpret_cast<uptr *>(mapping);
+
+ // Store the magic number.
+ // Hereafter, the VMO serves as the contents of the '.sancov' file.
+ array_[0] = Magic64;
+
+ return 1;
+ } else {
+ // The VMO is already mapped in, but it's not big enough to use the
+ // new indices. So increase the size to cover the new maximum index.
+
+ CHECK_NE(vmo_, ZX_HANDLE_INVALID);
+ CHECK_NE(array_, nullptr);
+
+ uint32_t first_index = next_index_;
+ next_index_ += num_guards;
+
+ zx_status_t status = _zx_vmo_set_size(vmo_, DataSize());
+ CHECK_EQ(status, ZX_OK);
+ uint64_t size = DataSize();
+ status = _zx_object_set_property(vmo_, ZX_PROP_VMO_CONTENT_SIZE, &size,
+ sizeof(size));
+ CHECK_EQ(status, ZX_OK);
+
+ return first_index;
+ }
+ }
+};
+
+static TracePcGuardController pc_guard_controller;
+
+} // namespace
+} // namespace __sancov
+
+namespace __sanitizer {
+void InitializeCoverage(bool enabled, const char *dir) {
+ CHECK_EQ(enabled, common_flags()->coverage);
+ CHECK_EQ(dir, common_flags()->coverage_dir);
+
+ static bool coverage_enabled = false;
+ if (!coverage_enabled) {
+ coverage_enabled = enabled;
+ Atexit(__sanitizer_cov_dump);
+ AddDieCallback(__sanitizer_cov_dump);
+ }
+}
+} // namespace __sanitizer
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(const uptr *pcs,
+ uptr len) {
+ UNIMPLEMENTED();
+}
+
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *guard) {
+ if (!*guard)
+ return;
+ __sancov::pc_guard_controller.TracePcGuard(guard, GET_CALLER_PC() - 1);
+}
+
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init,
+ u32 *start, u32 *end) {
+ if (start == end || *start)
+ return;
+ __sancov::pc_guard_controller.InitTracePcGuard(start, end);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_trace_pc_guard_coverage() {
+ __sancov::pc_guard_controller.Dump();
+}
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() {
+ __sanitizer_dump_trace_pc_guard_coverage();
+}
+// Default empty implementations (weak). Users should redefine them.
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp1, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp2, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp4, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp8, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp1, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp2, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp4, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp8, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_switch, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div4, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div8, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_gep, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {}
+} // extern "C"
+
+#endif // !SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc
new file mode 100644
index 00000000000..9d36a40270d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_interface.inc
@@ -0,0 +1,43 @@
+//===-- sanitizer_coverage_interface.inc ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Sanitizer Coverage interface list.
+//===----------------------------------------------------------------------===//
+INTERFACE_FUNCTION(__sanitizer_cov_dump)
+INTERFACE_FUNCTION(__sanitizer_cov_reset)
+INTERFACE_FUNCTION(__sanitizer_dump_coverage)
+INTERFACE_FUNCTION(__sanitizer_dump_trace_pc_guard_coverage)
+INTERFACE_WEAK_FUNCTION(__sancov_default_options)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp1)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp2)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp4)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp8)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp1)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp2)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp4)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp8)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_div4)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_div8)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_gep)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard_init)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_indir)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load1)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load2)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load4)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load8)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load16)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store1)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store2)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store4)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store8)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store16)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_switch)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_8bit_counters_init)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_bool_flag_init)
+INTERFACE_WEAK_FUNCTION(__sanitizer_cov_pcs_init)
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp
new file mode 100644
index 00000000000..956b48e0b43
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp
@@ -0,0 +1,288 @@
+//===-- sanitizer_coverage_libcdep_new.cpp --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Sanitizer Coverage Controller for Trace PC Guard.
+
+#include "sanitizer_platform.h"
+
+#if !SANITIZER_FUCHSIA
+# include "sancov_flags.h"
+# include "sanitizer_allocator_internal.h"
+# include "sanitizer_atomic.h"
+# include "sanitizer_common.h"
+# include "sanitizer_common/sanitizer_stacktrace.h"
+# include "sanitizer_file.h"
+# include "sanitizer_interface_internal.h"
+
+using namespace __sanitizer;
+
+using AddressRange = LoadedModule::AddressRange;
+
+namespace __sancov {
+namespace {
+
+static const u64 Magic64 = 0xC0BFFFFFFFFFFF64ULL;
+static const u64 Magic32 = 0xC0BFFFFFFFFFFF32ULL;
+static const u64 Magic = SANITIZER_WORDSIZE == 64 ? Magic64 : Magic32;
+
+static fd_t OpenFile(const char* path) {
+ error_t err;
+ fd_t fd = OpenFile(path, WrOnly, &err);
+ if (fd == kInvalidFd)
+ Report("SanitizerCoverage: failed to open %s for writing (reason: %d)\n",
+ path, err);
+ return fd;
+}
+
+static void GetCoverageFilename(char* path, const char* name,
+ const char* extension) {
+ CHECK(name);
+ internal_snprintf(path, kMaxPathLength, "%s/%s.%zd.%s",
+ common_flags()->coverage_dir, name, internal_getpid(),
+ extension);
+}
+
+static void WriteModuleCoverage(char* file_path, const char* module_name,
+ const uptr* pcs, uptr len) {
+ GetCoverageFilename(file_path, StripModuleName(module_name), "sancov");
+ fd_t fd = OpenFile(file_path);
+ WriteToFile(fd, &Magic, sizeof(Magic));
+ WriteToFile(fd, pcs, len * sizeof(*pcs));
+ CloseFile(fd);
+ Printf("SanitizerCoverage: %s: %zd PCs written\n", file_path, len);
+}
+
+static void SanitizerDumpCoverage(const uptr* unsorted_pcs, uptr len) {
+ if (!len) return;
+
+ char* file_path = static_cast<char*>(InternalAlloc(kMaxPathLength));
+ char* module_name = static_cast<char*>(InternalAlloc(kMaxPathLength));
+ uptr* pcs = static_cast<uptr*>(InternalAlloc(len * sizeof(uptr)));
+
+ internal_memcpy(pcs, unsorted_pcs, len * sizeof(uptr));
+ Sort(pcs, len);
+
+ bool module_found = false;
+ uptr last_base = 0;
+ uptr module_start_idx = 0;
+
+ for (uptr i = 0; i < len; ++i) {
+ const uptr pc = pcs[i];
+ if (!pc) continue;
+
+ if (!GetModuleAndOffsetForPc(pc, nullptr, 0, &pcs[i])) {
+ Printf("ERROR: unknown pc 0x%zx (may happen if dlclose is used)\n", pc);
+ continue;
+ }
+ uptr module_base = pc - pcs[i];
+
+ if (module_base != last_base || !module_found) {
+ if (module_found) {
+ WriteModuleCoverage(file_path, module_name, &pcs[module_start_idx],
+ i - module_start_idx);
+ }
+
+ last_base = module_base;
+ module_start_idx = i;
+ module_found = true;
+ GetModuleAndOffsetForPc(pc, module_name, kMaxPathLength, &pcs[i]);
+ }
+ }
+
+ if (module_found) {
+ WriteModuleCoverage(file_path, module_name, &pcs[module_start_idx],
+ len - module_start_idx);
+ }
+
+ InternalFree(file_path);
+ InternalFree(module_name);
+ InternalFree(pcs);
+}
+
+// Collects trace-pc guard coverage.
+// This class relies on zero-initialization.
+class TracePcGuardController {
+ public:
+ void Initialize() {
+ CHECK(!initialized);
+
+ initialized = true;
+ InitializeSancovFlags();
+
+ pc_vector.Initialize(0);
+ }
+
+ void InitTracePcGuard(u32* start, u32* end) {
+ if (!initialized) Initialize();
+ CHECK(!*start);
+ CHECK_NE(start, end);
+
+ u32 i = pc_vector.size();
+ for (u32* p = start; p < end; p++) *p = ++i;
+ pc_vector.resize(i);
+ }
+
+ void TracePcGuard(u32* guard, uptr pc) {
+ u32 idx = *guard;
+ if (!idx) return;
+ // we start indices from 1.
+ atomic_uintptr_t* pc_ptr =
+ reinterpret_cast<atomic_uintptr_t*>(&pc_vector[idx - 1]);
+ if (atomic_load(pc_ptr, memory_order_relaxed) == 0)
+ atomic_store(pc_ptr, pc, memory_order_relaxed);
+ }
+
+ void Reset() {
+ internal_memset(&pc_vector[0], 0, sizeof(pc_vector[0]) * pc_vector.size());
+ }
+
+ void Dump() {
+ if (!initialized || !common_flags()->coverage) return;
+ __sanitizer_dump_coverage(pc_vector.data(), pc_vector.size());
+ }
+
+ private:
+ bool initialized;
+ InternalMmapVectorNoCtor<uptr> pc_vector;
+};
+
+static TracePcGuardController pc_guard_controller;
+
+// A basic default implementation of callbacks for
+// -fsanitize-coverage=inline-8bit-counters,pc-table.
+// Use TOOL_OPTIONS (UBSAN_OPTIONS, etc) to dump the coverage data:
+// * cov_8bit_counters_out=PATH to dump the 8bit counters.
+// * cov_pcs_out=PATH to dump the pc table.
+//
+// Most users will still need to define their own callbacks for greater
+// flexibility.
+namespace SingletonCounterCoverage {
+
+static char *counters_beg, *counters_end;
+static const uptr *pcs_beg, *pcs_end;
+
+static void DumpCoverage() {
+ const char* file_path = common_flags()->cov_8bit_counters_out;
+ if (file_path && internal_strlen(file_path)) {
+ fd_t fd = OpenFile(file_path);
+ FileCloser file_closer(fd);
+ uptr size = counters_end - counters_beg;
+ WriteToFile(fd, counters_beg, size);
+ if (common_flags()->verbosity)
+ __sanitizer::Printf("cov_8bit_counters_out: written %zd bytes to %s\n",
+ size, file_path);
+ }
+ file_path = common_flags()->cov_pcs_out;
+ if (file_path && internal_strlen(file_path)) {
+ fd_t fd = OpenFile(file_path);
+ FileCloser file_closer(fd);
+ uptr size = (pcs_end - pcs_beg) * sizeof(uptr);
+ WriteToFile(fd, pcs_beg, size);
+ if (common_flags()->verbosity)
+ __sanitizer::Printf("cov_pcs_out: written %zd bytes to %s\n", size,
+ file_path);
+ }
+}
+
+static void Cov8bitCountersInit(char* beg, char* end) {
+ counters_beg = beg;
+ counters_end = end;
+ Atexit(DumpCoverage);
+}
+
+static void CovPcsInit(const uptr* beg, const uptr* end) {
+ pcs_beg = beg;
+ pcs_end = end;
+}
+
+} // namespace SingletonCounterCoverage
+
+} // namespace
+} // namespace __sancov
+
+namespace __sanitizer {
+void InitializeCoverage(bool enabled, const char *dir) {
+ static bool coverage_enabled = false;
+ if (coverage_enabled)
+ return; // May happen if two sanitizer enable coverage in the same process.
+ coverage_enabled = enabled;
+ Atexit(__sanitizer_cov_dump);
+ AddDieCallback(__sanitizer_cov_dump);
+}
+} // namespace __sanitizer
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(const uptr* pcs,
+ uptr len) {
+ return __sancov::SanitizerDumpCoverage(pcs, len);
+}
+
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32* guard) {
+ if (!*guard) return;
+ __sancov::pc_guard_controller.TracePcGuard(
+ guard, StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()));
+}
+
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init,
+ u32* start, u32* end) {
+ if (start == end || *start) return;
+ __sancov::pc_guard_controller.InitTracePcGuard(start, end);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_trace_pc_guard_coverage() {
+ __sancov::pc_guard_controller.Dump();
+}
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() {
+ __sanitizer_dump_trace_pc_guard_coverage();
+}
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_reset() {
+ __sancov::pc_guard_controller.Reset();
+}
+// Default implementations (weak).
+// Either empty or very simple.
+// Most users should redefine them.
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp1, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp2, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp4, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_cmp8, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp1, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp2, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp4, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_const_cmp8, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_switch, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div4, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_div8, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_gep, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_load1, void){}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_load2, void){}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_load4, void){}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_load8, void){}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_load16, void){}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_store1, void){}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_store2, void){}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_store4, void){}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_store8, void){}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_store16, void){}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_8bit_counters_init,
+ char* start, char* end) {
+ __sancov::SingletonCounterCoverage::Cov8bitCountersInit(start, end);
+}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_bool_flag_init, void) {}
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, const uptr* beg,
+ const uptr* end) {
+ __sancov::SingletonCounterCoverage::CovPcsInit(beg, end);
+}
+} // extern "C"
+// Weak definition for code instrumented with -fsanitize-coverage=stack-depth
+// and later linked with code containing a strong definition.
+// E.g., -fsanitize=fuzzer-no-link
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+SANITIZER_TLS_INITIAL_EXEC_ATTRIBUTE uptr __sancov_lowest_stack;
+
+#endif // !SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_win_sections.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_win_sections.cpp
new file mode 100644
index 00000000000..e7d6563393c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_coverage_win_sections.cpp
@@ -0,0 +1,67 @@
+//===-- sanitizer_coverage_win_sections.cpp -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines delimiters for Sanitizer Coverage's section. It contains
+// Windows specific tricks to coax the linker into giving us the start and stop
+// addresses of a section, as ELF linkers can do, to get the size of certain
+// arrays. According to https://msdn.microsoft.com/en-us/library/7977wcck.aspx
+// sections with the same name before "$" are sorted alphabetically by the
+// string that comes after "$" and merged into one section. We take advantage
+// of this by putting data we want the size of into the middle (M) of a section,
+// by using the letter "M" after "$". We get the start of this data (ie:
+// __start_section_name) by making the start variable come at the start of the
+// section (using the letter A after "$"). We do the same to get the end of the
+// data by using the letter "Z" after "$" to make the end variable come after
+// the data. Note that because of our technique the address of the start
+// variable is actually the address of data that comes before our middle
+// section. We also need to prevent the linker from adding any padding. Each
+// technique we use for this is explained in the comments below.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_WINDOWS
+#include <stdint.h>
+
+extern "C" {
+// Use uint64_t so the linker won't need to add any padding if it tries to word
+// align the start of the 8-bit counters array. The array will always start 8
+// bytes after __start_sancov_cntrs.
+#pragma section(".SCOV$CA", read, write)
+__declspec(allocate(".SCOV$CA")) uint64_t __start___sancov_cntrs = 0;
+
+// Even though we said not to align __stop__sancov_cntrs (using the "align"
+// declspec), MSVC's linker may try to align the section, .SCOV$CZ, containing
+// it. This can cause a mismatch between the number of PCs and counters since
+// each PCTable element is 8 bytes (unlike counters which are 1 byte) so no
+// padding would be added to align .SCOVP$Z, However, if .SCOV$CZ section is 1
+// byte, the linker won't try to align it on an 8-byte boundary, so use a
+// uint8_t for __stop_sancov_cntrs.
+#pragma section(".SCOV$CZ", read, write)
+__declspec(allocate(".SCOV$CZ")) __declspec(align(1)) uint8_t
+ __stop___sancov_cntrs = 0;
+
+#pragma section(".SCOV$GA", read, write)
+__declspec(allocate(".SCOV$GA")) uint64_t __start___sancov_guards = 0;
+#pragma section(".SCOV$GZ", read, write)
+__declspec(allocate(".SCOV$GZ")) __declspec(align(1)) uint8_t
+ __stop___sancov_guards = 0;
+
+// The guard array and counter array should both be merged into the .data
+// section to reduce the number of PE sections. However, because PCTable is
+// constant it should be merged with the .rdata section.
+#pragma comment(linker, "/MERGE:.SCOV=.data")
+
+#pragma section(".SCOVP$A", read)
+__declspec(allocate(".SCOVP$A")) uint64_t __start___sancov_pcs = 0;
+#pragma section(".SCOVP$Z", read)
+__declspec(allocate(".SCOVP$Z")) __declspec(align(1)) uint8_t
+ __stop___sancov_pcs = 0;
+
+#pragma comment(linker, "/MERGE:.SCOVP=.rdata")
+}
+#endif // SANITIZER_WINDOWS
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_dbghelp.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_dbghelp.h
new file mode 100644
index 00000000000..00a53998006
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_dbghelp.h
@@ -0,0 +1,41 @@
+//===-- sanitizer_dbghelp.h ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Wrappers for lazy loaded dbghelp.dll. Provides function pointers and a
+// callback to initialize them.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_SYMBOLIZER_WIN_H
+#define SANITIZER_SYMBOLIZER_WIN_H
+
+#if !SANITIZER_WINDOWS
+#error "sanitizer_dbghelp.h is a Windows-only header"
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <dbghelp.h>
+
+namespace __sanitizer {
+
+extern decltype(::StackWalk64) *StackWalk64;
+extern decltype(::SymCleanup) *SymCleanup;
+extern decltype(::SymFromAddr) *SymFromAddr;
+extern decltype(::SymFunctionTableAccess64) *SymFunctionTableAccess64;
+extern decltype(::SymGetLineFromAddr64) *SymGetLineFromAddr64;
+extern decltype(::SymGetModuleBase64) *SymGetModuleBase64;
+extern decltype(::SymGetSearchPathW) *SymGetSearchPathW;
+extern decltype(::SymInitialize) *SymInitialize;
+extern decltype(::SymSetOptions) *SymSetOptions;
+extern decltype(::SymSetSearchPathW) *SymSetSearchPathW;
+extern decltype(::UnDecorateSymbolName) *UnDecorateSymbolName;
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SYMBOLIZER_WIN_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h
new file mode 100644
index 00000000000..0749f633b4b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector.h
@@ -0,0 +1,410 @@
+//===-- sanitizer_deadlock_detector.h ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer runtime.
+// The deadlock detector maintains a directed graph of lock acquisitions.
+// When a lock event happens, the detector checks if the locks already held by
+// the current thread are reachable from the newly acquired lock.
+//
+// The detector can handle only a fixed amount of simultaneously live locks
+// (a lock is alive if it has been locked at least once and has not been
+// destroyed). When the maximal number of locks is reached the entire graph
+// is flushed and the new lock epoch is started. The node ids from the old
+// epochs can not be used with any of the detector methods except for
+// nodeBelongsToCurrentEpoch().
+//
+// FIXME: this is work in progress, nothing really works yet.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_DEADLOCK_DETECTOR_H
+#define SANITIZER_DEADLOCK_DETECTOR_H
+
+#include "sanitizer_bvgraph.h"
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+
+// Thread-local state for DeadlockDetector.
+// It contains the locks currently held by the owning thread.
+template <class BV>
+class DeadlockDetectorTLS {
+ public:
+ // No CTOR.
+ void clear() {
+ bv_.clear();
+ epoch_ = 0;
+ n_recursive_locks = 0;
+ n_all_locks_ = 0;
+ }
+
+ bool empty() const { return bv_.empty(); }
+
+ void ensureCurrentEpoch(uptr current_epoch) {
+ if (epoch_ == current_epoch) return;
+ bv_.clear();
+ epoch_ = current_epoch;
+ n_recursive_locks = 0;
+ n_all_locks_ = 0;
+ }
+
+ uptr getEpoch() const { return epoch_; }
+
+ // Returns true if this is the first (non-recursive) acquisition of this lock.
+ bool addLock(uptr lock_id, uptr current_epoch, u32 stk) {
+ CHECK_EQ(epoch_, current_epoch);
+ if (!bv_.setBit(lock_id)) {
+ // The lock is already held by this thread, it must be recursive.
+ CHECK_LT(n_recursive_locks, ARRAY_SIZE(recursive_locks));
+ recursive_locks[n_recursive_locks++] = lock_id;
+ return false;
+ }
+ CHECK_LT(n_all_locks_, ARRAY_SIZE(all_locks_with_contexts_));
+ // lock_id < BV::kSize, can cast to a smaller int.
+ u32 lock_id_short = static_cast<u32>(lock_id);
+ LockWithContext l = {lock_id_short, stk};
+ all_locks_with_contexts_[n_all_locks_++] = l;
+ return true;
+ }
+
+ void removeLock(uptr lock_id) {
+ if (n_recursive_locks) {
+ for (sptr i = n_recursive_locks - 1; i >= 0; i--) {
+ if (recursive_locks[i] == lock_id) {
+ n_recursive_locks--;
+ Swap(recursive_locks[i], recursive_locks[n_recursive_locks]);
+ return;
+ }
+ }
+ }
+ if (!bv_.clearBit(lock_id))
+ return; // probably addLock happened before flush
+ if (n_all_locks_) {
+ for (sptr i = n_all_locks_ - 1; i >= 0; i--) {
+ if (all_locks_with_contexts_[i].lock == static_cast<u32>(lock_id)) {
+ Swap(all_locks_with_contexts_[i],
+ all_locks_with_contexts_[n_all_locks_ - 1]);
+ n_all_locks_--;
+ break;
+ }
+ }
+ }
+ }
+
+ u32 findLockContext(uptr lock_id) {
+ for (uptr i = 0; i < n_all_locks_; i++)
+ if (all_locks_with_contexts_[i].lock == static_cast<u32>(lock_id))
+ return all_locks_with_contexts_[i].stk;
+ return 0;
+ }
+
+ const BV &getLocks(uptr current_epoch) const {
+ CHECK_EQ(epoch_, current_epoch);
+ return bv_;
+ }
+
+ uptr getNumLocks() const { return n_all_locks_; }
+ uptr getLock(uptr idx) const { return all_locks_with_contexts_[idx].lock; }
+
+ private:
+ BV bv_;
+ uptr epoch_;
+ uptr recursive_locks[64];
+ uptr n_recursive_locks;
+ struct LockWithContext {
+ u32 lock;
+ u32 stk;
+ };
+ LockWithContext all_locks_with_contexts_[64];
+ uptr n_all_locks_;
+};
+
+// DeadlockDetector.
+// For deadlock detection to work we need one global DeadlockDetector object
+// and one DeadlockDetectorTLS object per evey thread.
+// This class is not thread safe, all concurrent accesses should be guarded
+// by an external lock.
+// Most of the methods of this class are not thread-safe (i.e. should
+// be protected by an external lock) unless explicitly told otherwise.
+template <class BV>
+class DeadlockDetector {
+ public:
+ typedef BV BitVector;
+
+ uptr size() const { return g_.size(); }
+
+ // No CTOR.
+ void clear() {
+ current_epoch_ = 0;
+ available_nodes_.clear();
+ recycled_nodes_.clear();
+ g_.clear();
+ n_edges_ = 0;
+ }
+
+ // Allocate new deadlock detector node.
+ // If we are out of available nodes first try to recycle some.
+ // If there is nothing to recycle, flush the graph and increment the epoch.
+ // Associate 'data' (opaque user's object) with the new node.
+ uptr newNode(uptr data) {
+ if (!available_nodes_.empty())
+ return getAvailableNode(data);
+ if (!recycled_nodes_.empty()) {
+ for (sptr i = n_edges_ - 1; i >= 0; i--) {
+ if (recycled_nodes_.getBit(edges_[i].from) ||
+ recycled_nodes_.getBit(edges_[i].to)) {
+ Swap(edges_[i], edges_[n_edges_ - 1]);
+ n_edges_--;
+ }
+ }
+ CHECK(available_nodes_.empty());
+ // removeEdgesFrom was called in removeNode.
+ g_.removeEdgesTo(recycled_nodes_);
+ available_nodes_.setUnion(recycled_nodes_);
+ recycled_nodes_.clear();
+ return getAvailableNode(data);
+ }
+ // We are out of vacant nodes. Flush and increment the current_epoch_.
+ current_epoch_ += size();
+ recycled_nodes_.clear();
+ available_nodes_.setAll();
+ g_.clear();
+ n_edges_ = 0;
+ return getAvailableNode(data);
+ }
+
+ // Get data associated with the node created by newNode().
+ uptr getData(uptr node) const { return data_[nodeToIndex(node)]; }
+
+ bool nodeBelongsToCurrentEpoch(uptr node) {
+ return node && (node / size() * size()) == current_epoch_;
+ }
+
+ void removeNode(uptr node) {
+ uptr idx = nodeToIndex(node);
+ CHECK(!available_nodes_.getBit(idx));
+ CHECK(recycled_nodes_.setBit(idx));
+ g_.removeEdgesFrom(idx);
+ }
+
+ void ensureCurrentEpoch(DeadlockDetectorTLS<BV> *dtls) {
+ dtls->ensureCurrentEpoch(current_epoch_);
+ }
+
+ // Returns true if there is a cycle in the graph after this lock event.
+ // Ideally should be called before the lock is acquired so that we can
+ // report a deadlock before a real deadlock happens.
+ bool onLockBefore(DeadlockDetectorTLS<BV> *dtls, uptr cur_node) {
+ ensureCurrentEpoch(dtls);
+ uptr cur_idx = nodeToIndex(cur_node);
+ return g_.isReachable(cur_idx, dtls->getLocks(current_epoch_));
+ }
+
+ u32 findLockContext(DeadlockDetectorTLS<BV> *dtls, uptr node) {
+ return dtls->findLockContext(nodeToIndex(node));
+ }
+
+ // Add cur_node to the set of locks held currently by dtls.
+ void onLockAfter(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk = 0) {
+ ensureCurrentEpoch(dtls);
+ uptr cur_idx = nodeToIndex(cur_node);
+ dtls->addLock(cur_idx, current_epoch_, stk);
+ }
+
+ // Experimental *racy* fast path function.
+ // Returns true if all edges from the currently held locks to cur_node exist.
+ bool hasAllEdges(DeadlockDetectorTLS<BV> *dtls, uptr cur_node) {
+ uptr local_epoch = dtls->getEpoch();
+ // Read from current_epoch_ is racy.
+ if (cur_node && local_epoch == current_epoch_ &&
+ local_epoch == nodeToEpoch(cur_node)) {
+ uptr cur_idx = nodeToIndexUnchecked(cur_node);
+ for (uptr i = 0, n = dtls->getNumLocks(); i < n; i++) {
+ if (!g_.hasEdge(dtls->getLock(i), cur_idx))
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ // Adds edges from currently held locks to cur_node,
+ // returns the number of added edges, and puts the sources of added edges
+ // into added_edges[].
+ // Should be called before onLockAfter.
+ uptr addEdges(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk,
+ int unique_tid) {
+ ensureCurrentEpoch(dtls);
+ uptr cur_idx = nodeToIndex(cur_node);
+ uptr added_edges[40];
+ uptr n_added_edges = g_.addEdges(dtls->getLocks(current_epoch_), cur_idx,
+ added_edges, ARRAY_SIZE(added_edges));
+ for (uptr i = 0; i < n_added_edges; i++) {
+ if (n_edges_ < ARRAY_SIZE(edges_)) {
+ Edge e = {(u16)added_edges[i], (u16)cur_idx,
+ dtls->findLockContext(added_edges[i]), stk,
+ unique_tid};
+ edges_[n_edges_++] = e;
+ }
+ }
+ return n_added_edges;
+ }
+
+ bool findEdge(uptr from_node, uptr to_node, u32 *stk_from, u32 *stk_to,
+ int *unique_tid) {
+ uptr from_idx = nodeToIndex(from_node);
+ uptr to_idx = nodeToIndex(to_node);
+ for (uptr i = 0; i < n_edges_; i++) {
+ if (edges_[i].from == from_idx && edges_[i].to == to_idx) {
+ *stk_from = edges_[i].stk_from;
+ *stk_to = edges_[i].stk_to;
+ *unique_tid = edges_[i].unique_tid;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Test-only function. Handles the before/after lock events,
+ // returns true if there is a cycle.
+ bool onLock(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk = 0) {
+ ensureCurrentEpoch(dtls);
+ bool is_reachable = !isHeld(dtls, cur_node) && onLockBefore(dtls, cur_node);
+ addEdges(dtls, cur_node, stk, 0);
+ onLockAfter(dtls, cur_node, stk);
+ return is_reachable;
+ }
+
+ // Handles the try_lock event, returns false.
+ // When a try_lock event happens (i.e. a try_lock call succeeds) we need
+ // to add this lock to the currently held locks, but we should not try to
+ // change the lock graph or to detect a cycle. We may want to investigate
+ // whether a more aggressive strategy is possible for try_lock.
+ bool onTryLock(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, u32 stk = 0) {
+ ensureCurrentEpoch(dtls);
+ uptr cur_idx = nodeToIndex(cur_node);
+ dtls->addLock(cur_idx, current_epoch_, stk);
+ return false;
+ }
+
+ // Returns true iff dtls is empty (no locks are currently held) and we can
+ // add the node to the currently held locks w/o changing the global state.
+ // This operation is thread-safe as it only touches the dtls.
+ bool onFirstLock(DeadlockDetectorTLS<BV> *dtls, uptr node, u32 stk = 0) {
+ if (!dtls->empty()) return false;
+ if (dtls->getEpoch() && dtls->getEpoch() == nodeToEpoch(node)) {
+ dtls->addLock(nodeToIndexUnchecked(node), nodeToEpoch(node), stk);
+ return true;
+ }
+ return false;
+ }
+
+ // Finds a path between the lock 'cur_node' (currently not held in dtls)
+ // and some currently held lock, returns the length of the path
+ // or 0 on failure.
+ uptr findPathToLock(DeadlockDetectorTLS<BV> *dtls, uptr cur_node, uptr *path,
+ uptr path_size) {
+ tmp_bv_.copyFrom(dtls->getLocks(current_epoch_));
+ uptr idx = nodeToIndex(cur_node);
+ CHECK(!tmp_bv_.getBit(idx));
+ uptr res = g_.findShortestPath(idx, tmp_bv_, path, path_size);
+ for (uptr i = 0; i < res; i++)
+ path[i] = indexToNode(path[i]);
+ if (res)
+ CHECK_EQ(path[0], cur_node);
+ return res;
+ }
+
+ // Handle the unlock event.
+ // This operation is thread-safe as it only touches the dtls.
+ void onUnlock(DeadlockDetectorTLS<BV> *dtls, uptr node) {
+ if (dtls->getEpoch() == nodeToEpoch(node))
+ dtls->removeLock(nodeToIndexUnchecked(node));
+ }
+
+ // Tries to handle the lock event w/o writing to global state.
+ // Returns true on success.
+ // This operation is thread-safe as it only touches the dtls
+ // (modulo racy nature of hasAllEdges).
+ bool onLockFast(DeadlockDetectorTLS<BV> *dtls, uptr node, u32 stk = 0) {
+ if (hasAllEdges(dtls, node)) {
+ dtls->addLock(nodeToIndexUnchecked(node), nodeToEpoch(node), stk);
+ return true;
+ }
+ return false;
+ }
+
+ bool isHeld(DeadlockDetectorTLS<BV> *dtls, uptr node) const {
+ return dtls->getLocks(current_epoch_).getBit(nodeToIndex(node));
+ }
+
+ uptr testOnlyGetEpoch() const { return current_epoch_; }
+ bool testOnlyHasEdge(uptr l1, uptr l2) {
+ return g_.hasEdge(nodeToIndex(l1), nodeToIndex(l2));
+ }
+ // idx1 and idx2 are raw indices to g_, not lock IDs.
+ bool testOnlyHasEdgeRaw(uptr idx1, uptr idx2) {
+ return g_.hasEdge(idx1, idx2);
+ }
+
+ void Print() {
+ for (uptr from = 0; from < size(); from++)
+ for (uptr to = 0; to < size(); to++)
+ if (g_.hasEdge(from, to))
+ Printf(" %zx => %zx\n", from, to);
+ }
+
+ private:
+ void check_idx(uptr idx) const { CHECK_LT(idx, size()); }
+
+ void check_node(uptr node) const {
+ CHECK_GE(node, size());
+ CHECK_EQ(current_epoch_, nodeToEpoch(node));
+ }
+
+ uptr indexToNode(uptr idx) const {
+ check_idx(idx);
+ return idx + current_epoch_;
+ }
+
+ uptr nodeToIndexUnchecked(uptr node) const { return node % size(); }
+
+ uptr nodeToIndex(uptr node) const {
+ check_node(node);
+ return nodeToIndexUnchecked(node);
+ }
+
+ uptr nodeToEpoch(uptr node) const { return node / size() * size(); }
+
+ uptr getAvailableNode(uptr data) {
+ uptr idx = available_nodes_.getAndClearFirstOne();
+ data_[idx] = data;
+ return indexToNode(idx);
+ }
+
+ struct Edge {
+ u16 from;
+ u16 to;
+ u32 stk_from;
+ u32 stk_to;
+ int unique_tid;
+ };
+
+ uptr current_epoch_;
+ BV available_nodes_;
+ BV recycled_nodes_;
+ BV tmp_bv_;
+ BVGraph<BV> g_;
+ uptr data_[BV::kSize];
+ Edge edges_[BV::kSize * 32];
+ uptr n_edges_;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_DEADLOCK_DETECTOR_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cpp
new file mode 100644
index 00000000000..ccb7065b07a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector1.cpp
@@ -0,0 +1,194 @@
+//===-- sanitizer_deadlock_detector1.cpp ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Deadlock detector implementation based on NxN adjacency bit matrix.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_deadlock_detector_interface.h"
+#include "sanitizer_deadlock_detector.h"
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_mutex.h"
+
+#if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1
+
+namespace __sanitizer {
+
+typedef TwoLevelBitVector<> DDBV; // DeadlockDetector's bit vector.
+
+struct DDPhysicalThread {
+};
+
+struct DDLogicalThread {
+ u64 ctx;
+ DeadlockDetectorTLS<DDBV> dd;
+ DDReport rep;
+ bool report_pending;
+};
+
+struct DD final : public DDetector {
+ SpinMutex mtx;
+ DeadlockDetector<DDBV> dd;
+ DDFlags flags;
+
+ explicit DD(const DDFlags *flags);
+
+ DDPhysicalThread *CreatePhysicalThread() override;
+ void DestroyPhysicalThread(DDPhysicalThread *pt) override;
+
+ DDLogicalThread *CreateLogicalThread(u64 ctx) override;
+ void DestroyLogicalThread(DDLogicalThread *lt) override;
+
+ void MutexInit(DDCallback *cb, DDMutex *m) override;
+ void MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) override;
+ void MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock,
+ bool trylock) override;
+ void MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) override;
+ void MutexDestroy(DDCallback *cb, DDMutex *m) override;
+
+ DDReport *GetReport(DDCallback *cb) override;
+
+ void MutexEnsureID(DDLogicalThread *lt, DDMutex *m);
+ void ReportDeadlock(DDCallback *cb, DDMutex *m);
+};
+
+DDetector *DDetector::Create(const DDFlags *flags) {
+ (void)flags;
+ void *mem = MmapOrDie(sizeof(DD), "deadlock detector");
+ return new(mem) DD(flags);
+}
+
+DD::DD(const DDFlags *flags)
+ : flags(*flags) {
+ dd.clear();
+}
+
+DDPhysicalThread* DD::CreatePhysicalThread() {
+ return nullptr;
+}
+
+void DD::DestroyPhysicalThread(DDPhysicalThread *pt) {
+}
+
+DDLogicalThread* DD::CreateLogicalThread(u64 ctx) {
+ DDLogicalThread *lt = (DDLogicalThread*)InternalAlloc(sizeof(*lt));
+ lt->ctx = ctx;
+ lt->dd.clear();
+ lt->report_pending = false;
+ return lt;
+}
+
+void DD::DestroyLogicalThread(DDLogicalThread *lt) {
+ lt->~DDLogicalThread();
+ InternalFree(lt);
+}
+
+void DD::MutexInit(DDCallback *cb, DDMutex *m) {
+ m->id = 0;
+ m->stk = cb->Unwind();
+}
+
+void DD::MutexEnsureID(DDLogicalThread *lt, DDMutex *m) {
+ if (!dd.nodeBelongsToCurrentEpoch(m->id))
+ m->id = dd.newNode(reinterpret_cast<uptr>(m));
+ dd.ensureCurrentEpoch(&lt->dd);
+}
+
+void DD::MutexBeforeLock(DDCallback *cb,
+ DDMutex *m, bool wlock) {
+ DDLogicalThread *lt = cb->lt;
+ if (lt->dd.empty()) return; // This will be the first lock held by lt.
+ if (dd.hasAllEdges(&lt->dd, m->id)) return; // We already have all edges.
+ SpinMutexLock lk(&mtx);
+ MutexEnsureID(lt, m);
+ if (dd.isHeld(&lt->dd, m->id))
+ return; // FIXME: allow this only for recursive locks.
+ if (dd.onLockBefore(&lt->dd, m->id)) {
+ // Actually add this edge now so that we have all the stack traces.
+ dd.addEdges(&lt->dd, m->id, cb->Unwind(), cb->UniqueTid());
+ ReportDeadlock(cb, m);
+ }
+}
+
+void DD::ReportDeadlock(DDCallback *cb, DDMutex *m) {
+ DDLogicalThread *lt = cb->lt;
+ uptr path[20];
+ uptr len = dd.findPathToLock(&lt->dd, m->id, path, ARRAY_SIZE(path));
+ if (len == 0U) {
+ // A cycle of 20+ locks? Well, that's a bit odd...
+ Printf("WARNING: too long mutex cycle found\n");
+ return;
+ }
+ CHECK_EQ(m->id, path[0]);
+ lt->report_pending = true;
+ len = Min<uptr>(len, DDReport::kMaxLoopSize);
+ DDReport *rep = &lt->rep;
+ rep->n = len;
+ for (uptr i = 0; i < len; i++) {
+ uptr from = path[i];
+ uptr to = path[(i + 1) % len];
+ DDMutex *m0 = (DDMutex*)dd.getData(from);
+ DDMutex *m1 = (DDMutex*)dd.getData(to);
+
+ u32 stk_from = 0, stk_to = 0;
+ int unique_tid = 0;
+ dd.findEdge(from, to, &stk_from, &stk_to, &unique_tid);
+ // Printf("Edge: %zd=>%zd: %u/%u T%d\n", from, to, stk_from, stk_to,
+ // unique_tid);
+ rep->loop[i].thr_ctx = unique_tid;
+ rep->loop[i].mtx_ctx0 = m0->ctx;
+ rep->loop[i].mtx_ctx1 = m1->ctx;
+ rep->loop[i].stk[0] = stk_to;
+ rep->loop[i].stk[1] = stk_from;
+ }
+}
+
+void DD::MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock, bool trylock) {
+ DDLogicalThread *lt = cb->lt;
+ u32 stk = 0;
+ if (flags.second_deadlock_stack)
+ stk = cb->Unwind();
+ // Printf("T%p MutexLock: %zx stk %u\n", lt, m->id, stk);
+ if (dd.onFirstLock(&lt->dd, m->id, stk))
+ return;
+ if (dd.onLockFast(&lt->dd, m->id, stk))
+ return;
+
+ SpinMutexLock lk(&mtx);
+ MutexEnsureID(lt, m);
+ if (wlock) // Only a recursive rlock may be held.
+ CHECK(!dd.isHeld(&lt->dd, m->id));
+ if (!trylock)
+ dd.addEdges(&lt->dd, m->id, stk ? stk : cb->Unwind(), cb->UniqueTid());
+ dd.onLockAfter(&lt->dd, m->id, stk);
+}
+
+void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {
+ // Printf("T%p MutexUnLock: %zx\n", cb->lt, m->id);
+ dd.onUnlock(&cb->lt->dd, m->id);
+}
+
+void DD::MutexDestroy(DDCallback *cb,
+ DDMutex *m) {
+ if (!m->id) return;
+ SpinMutexLock lk(&mtx);
+ if (dd.nodeBelongsToCurrentEpoch(m->id))
+ dd.removeNode(m->id);
+ m->id = 0;
+}
+
+DDReport *DD::GetReport(DDCallback *cb) {
+ if (!cb->lt->report_pending)
+ return nullptr;
+ cb->lt->report_pending = false;
+ return &cb->lt->rep;
+}
+
+} // namespace __sanitizer
+#endif // #if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector2.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector2.cpp
new file mode 100644
index 00000000000..1fbbbcccfa9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector2.cpp
@@ -0,0 +1,421 @@
+//===-- sanitizer_deadlock_detector2.cpp ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Deadlock detector implementation based on adjacency lists.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_deadlock_detector_interface.h"
+#include "sanitizer_common.h"
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_mutex.h"
+
+#if SANITIZER_DEADLOCK_DETECTOR_VERSION == 2
+
+namespace __sanitizer {
+
+const int kMaxNesting = 64;
+const u32 kNoId = -1;
+const u32 kEndId = -2;
+const int kMaxLink = 8;
+const int kL1Size = 1024;
+const int kL2Size = 1024;
+const int kMaxMutex = kL1Size * kL2Size;
+
+struct Id {
+ u32 id;
+ u32 seq;
+
+ explicit Id(u32 id = 0, u32 seq = 0)
+ : id(id)
+ , seq(seq) {
+ }
+};
+
+struct Link {
+ u32 id;
+ u32 seq;
+ u32 tid;
+ u32 stk0;
+ u32 stk1;
+
+ explicit Link(u32 id = 0, u32 seq = 0, u32 tid = 0, u32 s0 = 0, u32 s1 = 0)
+ : id(id)
+ , seq(seq)
+ , tid(tid)
+ , stk0(s0)
+ , stk1(s1) {
+ }
+};
+
+struct DDPhysicalThread {
+ DDReport rep;
+ bool report_pending;
+ bool visited[kMaxMutex];
+ Link pending[kMaxMutex];
+ Link path[kMaxMutex];
+};
+
+struct ThreadMutex {
+ u32 id;
+ u32 stk;
+};
+
+struct DDLogicalThread {
+ u64 ctx;
+ ThreadMutex locked[kMaxNesting];
+ int nlocked;
+};
+
+struct MutexState {
+ StaticSpinMutex mtx;
+ u32 seq;
+ int nlink;
+ Link link[kMaxLink];
+};
+
+struct DD final : public DDetector {
+ explicit DD(const DDFlags *flags);
+
+ DDPhysicalThread* CreatePhysicalThread();
+ void DestroyPhysicalThread(DDPhysicalThread *pt);
+
+ DDLogicalThread* CreateLogicalThread(u64 ctx);
+ void DestroyLogicalThread(DDLogicalThread *lt);
+
+ void MutexInit(DDCallback *cb, DDMutex *m);
+ void MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock);
+ void MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock,
+ bool trylock);
+ void MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock);
+ void MutexDestroy(DDCallback *cb, DDMutex *m);
+
+ DDReport *GetReport(DDCallback *cb);
+
+ void CycleCheck(DDPhysicalThread *pt, DDLogicalThread *lt, DDMutex *mtx);
+ void Report(DDPhysicalThread *pt, DDLogicalThread *lt, int npath);
+ u32 allocateId(DDCallback *cb);
+ MutexState *getMutex(u32 id);
+ u32 getMutexId(MutexState *m);
+
+ DDFlags flags;
+
+ MutexState *mutex[kL1Size];
+
+ SpinMutex mtx;
+ InternalMmapVector<u32> free_id;
+ int id_gen = 0;
+};
+
+DDetector *DDetector::Create(const DDFlags *flags) {
+ (void)flags;
+ void *mem = MmapOrDie(sizeof(DD), "deadlock detector");
+ return new(mem) DD(flags);
+}
+
+DD::DD(const DDFlags *flags) : flags(*flags) { free_id.reserve(1024); }
+
+DDPhysicalThread* DD::CreatePhysicalThread() {
+ DDPhysicalThread *pt = (DDPhysicalThread*)MmapOrDie(sizeof(DDPhysicalThread),
+ "deadlock detector (physical thread)");
+ return pt;
+}
+
+void DD::DestroyPhysicalThread(DDPhysicalThread *pt) {
+ pt->~DDPhysicalThread();
+ UnmapOrDie(pt, sizeof(DDPhysicalThread));
+}
+
+DDLogicalThread* DD::CreateLogicalThread(u64 ctx) {
+ DDLogicalThread *lt = (DDLogicalThread*)InternalAlloc(
+ sizeof(DDLogicalThread));
+ lt->ctx = ctx;
+ lt->nlocked = 0;
+ return lt;
+}
+
+void DD::DestroyLogicalThread(DDLogicalThread *lt) {
+ lt->~DDLogicalThread();
+ InternalFree(lt);
+}
+
+void DD::MutexInit(DDCallback *cb, DDMutex *m) {
+ VPrintf(2, "#%llu: DD::MutexInit(%p)\n", cb->lt->ctx, m);
+ m->id = kNoId;
+ m->recursion = 0;
+ atomic_store(&m->owner, 0, memory_order_relaxed);
+}
+
+MutexState *DD::getMutex(u32 id) { return &mutex[id / kL2Size][id % kL2Size]; }
+
+u32 DD::getMutexId(MutexState *m) {
+ for (int i = 0; i < kL1Size; i++) {
+ MutexState *tab = mutex[i];
+ if (tab == 0)
+ break;
+ if (m >= tab && m < tab + kL2Size)
+ return i * kL2Size + (m - tab);
+ }
+ return -1;
+}
+
+u32 DD::allocateId(DDCallback *cb) {
+ u32 id = -1;
+ SpinMutexLock l(&mtx);
+ if (free_id.size() > 0) {
+ id = free_id.back();
+ free_id.pop_back();
+ } else {
+ CHECK_LT(id_gen, kMaxMutex);
+ if ((id_gen % kL2Size) == 0) {
+ mutex[id_gen / kL2Size] = (MutexState *)MmapOrDie(
+ kL2Size * sizeof(MutexState), "deadlock detector (mutex table)");
+ }
+ id = id_gen++;
+ }
+ CHECK_LE(id, kMaxMutex);
+ VPrintf(3, "#%llu: DD::allocateId assign id %d\n", cb->lt->ctx, id);
+ return id;
+}
+
+void DD::MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) {
+ VPrintf(2, "#%llu: DD::MutexBeforeLock(%p, wlock=%d) nlocked=%d\n",
+ cb->lt->ctx, m, wlock, cb->lt->nlocked);
+ DDPhysicalThread *pt = cb->pt;
+ DDLogicalThread *lt = cb->lt;
+
+ uptr owner = atomic_load(&m->owner, memory_order_relaxed);
+ if (owner == (uptr)cb->lt) {
+ VPrintf(3, "#%llu: DD::MutexBeforeLock recursive\n",
+ cb->lt->ctx);
+ return;
+ }
+
+ CHECK_LE(lt->nlocked, kMaxNesting);
+
+ // FIXME(dvyukov): don't allocate id if lt->nlocked == 0?
+ if (m->id == kNoId)
+ m->id = allocateId(cb);
+
+ ThreadMutex *tm = &lt->locked[lt->nlocked++];
+ tm->id = m->id;
+ if (flags.second_deadlock_stack)
+ tm->stk = cb->Unwind();
+ if (lt->nlocked == 1) {
+ VPrintf(3, "#%llu: DD::MutexBeforeLock first mutex\n",
+ cb->lt->ctx);
+ return;
+ }
+
+ bool added = false;
+ MutexState *mtx = getMutex(m->id);
+ for (int i = 0; i < lt->nlocked - 1; i++) {
+ u32 id1 = lt->locked[i].id;
+ u32 stk1 = lt->locked[i].stk;
+ MutexState *mtx1 = getMutex(id1);
+ SpinMutexLock l(&mtx1->mtx);
+ if (mtx1->nlink == kMaxLink) {
+ // FIXME(dvyukov): check stale links
+ continue;
+ }
+ int li = 0;
+ for (; li < mtx1->nlink; li++) {
+ Link *link = &mtx1->link[li];
+ if (link->id == m->id) {
+ if (link->seq != mtx->seq) {
+ link->seq = mtx->seq;
+ link->tid = lt->ctx;
+ link->stk0 = stk1;
+ link->stk1 = cb->Unwind();
+ added = true;
+ VPrintf(3, "#%llu: DD::MutexBeforeLock added %d->%d link\n",
+ cb->lt->ctx, getMutexId(mtx1), m->id);
+ }
+ break;
+ }
+ }
+ if (li == mtx1->nlink) {
+ // FIXME(dvyukov): check stale links
+ Link *link = &mtx1->link[mtx1->nlink++];
+ link->id = m->id;
+ link->seq = mtx->seq;
+ link->tid = lt->ctx;
+ link->stk0 = stk1;
+ link->stk1 = cb->Unwind();
+ added = true;
+ VPrintf(3, "#%llu: DD::MutexBeforeLock added %d->%d link\n",
+ cb->lt->ctx, getMutexId(mtx1), m->id);
+ }
+ }
+
+ if (!added || mtx->nlink == 0) {
+ VPrintf(3, "#%llu: DD::MutexBeforeLock don't check\n",
+ cb->lt->ctx);
+ return;
+ }
+
+ CycleCheck(pt, lt, m);
+}
+
+void DD::MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock,
+ bool trylock) {
+ VPrintf(2, "#%llu: DD::MutexAfterLock(%p, wlock=%d, try=%d) nlocked=%d\n",
+ cb->lt->ctx, m, wlock, trylock, cb->lt->nlocked);
+ DDLogicalThread *lt = cb->lt;
+
+ uptr owner = atomic_load(&m->owner, memory_order_relaxed);
+ if (owner == (uptr)cb->lt) {
+ VPrintf(3, "#%llu: DD::MutexAfterLock recursive\n", cb->lt->ctx);
+ CHECK(wlock);
+ m->recursion++;
+ return;
+ }
+ CHECK_EQ(owner, 0);
+ if (wlock) {
+ VPrintf(3, "#%llu: DD::MutexAfterLock set owner\n", cb->lt->ctx);
+ CHECK_EQ(m->recursion, 0);
+ m->recursion = 1;
+ atomic_store(&m->owner, (uptr)cb->lt, memory_order_relaxed);
+ }
+
+ if (!trylock)
+ return;
+
+ CHECK_LE(lt->nlocked, kMaxNesting);
+ if (m->id == kNoId)
+ m->id = allocateId(cb);
+ ThreadMutex *tm = &lt->locked[lt->nlocked++];
+ tm->id = m->id;
+ if (flags.second_deadlock_stack)
+ tm->stk = cb->Unwind();
+}
+
+void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {
+ VPrintf(2, "#%llu: DD::MutexBeforeUnlock(%p, wlock=%d) nlocked=%d\n",
+ cb->lt->ctx, m, wlock, cb->lt->nlocked);
+ DDLogicalThread *lt = cb->lt;
+
+ uptr owner = atomic_load(&m->owner, memory_order_relaxed);
+ if (owner == (uptr)cb->lt) {
+ VPrintf(3, "#%llu: DD::MutexBeforeUnlock recursive\n", cb->lt->ctx);
+ if (--m->recursion > 0)
+ return;
+ VPrintf(3, "#%llu: DD::MutexBeforeUnlock reset owner\n", cb->lt->ctx);
+ atomic_store(&m->owner, 0, memory_order_relaxed);
+ }
+ CHECK_NE(m->id, kNoId);
+ int last = lt->nlocked - 1;
+ for (int i = last; i >= 0; i--) {
+ if (cb->lt->locked[i].id == m->id) {
+ lt->locked[i] = lt->locked[last];
+ lt->nlocked--;
+ break;
+ }
+ }
+}
+
+void DD::MutexDestroy(DDCallback *cb, DDMutex *m) {
+ VPrintf(2, "#%llu: DD::MutexDestroy(%p)\n",
+ cb->lt->ctx, m);
+ DDLogicalThread *lt = cb->lt;
+
+ if (m->id == kNoId)
+ return;
+
+ // Remove the mutex from lt->locked if there.
+ int last = lt->nlocked - 1;
+ for (int i = last; i >= 0; i--) {
+ if (lt->locked[i].id == m->id) {
+ lt->locked[i] = lt->locked[last];
+ lt->nlocked--;
+ break;
+ }
+ }
+
+ // Clear and invalidate the mutex descriptor.
+ {
+ MutexState *mtx = getMutex(m->id);
+ SpinMutexLock l(&mtx->mtx);
+ mtx->seq++;
+ mtx->nlink = 0;
+ }
+
+ // Return id to cache.
+ {
+ SpinMutexLock l(&mtx);
+ free_id.push_back(m->id);
+ }
+}
+
+void DD::CycleCheck(DDPhysicalThread *pt, DDLogicalThread *lt,
+ DDMutex *m) {
+ internal_memset(pt->visited, 0, sizeof(pt->visited));
+ int npath = 0;
+ int npending = 0;
+ {
+ MutexState *mtx = getMutex(m->id);
+ SpinMutexLock l(&mtx->mtx);
+ for (int li = 0; li < mtx->nlink; li++)
+ pt->pending[npending++] = mtx->link[li];
+ }
+ while (npending > 0) {
+ Link link = pt->pending[--npending];
+ if (link.id == kEndId) {
+ npath--;
+ continue;
+ }
+ if (pt->visited[link.id])
+ continue;
+ MutexState *mtx1 = getMutex(link.id);
+ SpinMutexLock l(&mtx1->mtx);
+ if (mtx1->seq != link.seq)
+ continue;
+ pt->visited[link.id] = true;
+ if (mtx1->nlink == 0)
+ continue;
+ pt->path[npath++] = link;
+ pt->pending[npending++] = Link(kEndId);
+ if (link.id == m->id)
+ return Report(pt, lt, npath); // Bingo!
+ for (int li = 0; li < mtx1->nlink; li++) {
+ Link *link1 = &mtx1->link[li];
+ // MutexState *mtx2 = getMutex(link->id);
+ // FIXME(dvyukov): fast seq check
+ // FIXME(dvyukov): fast nlink != 0 check
+ // FIXME(dvyukov): fast pending check?
+ // FIXME(dvyukov): npending can be larger than kMaxMutex
+ pt->pending[npending++] = *link1;
+ }
+ }
+}
+
+void DD::Report(DDPhysicalThread *pt, DDLogicalThread *lt, int npath) {
+ DDReport *rep = &pt->rep;
+ rep->n = npath;
+ for (int i = 0; i < npath; i++) {
+ Link *link = &pt->path[i];
+ Link *link0 = &pt->path[i ? i - 1 : npath - 1];
+ rep->loop[i].thr_ctx = link->tid;
+ rep->loop[i].mtx_ctx0 = link0->id;
+ rep->loop[i].mtx_ctx1 = link->id;
+ rep->loop[i].stk[0] = flags.second_deadlock_stack ? link->stk0 : 0;
+ rep->loop[i].stk[1] = link->stk1;
+ }
+ pt->report_pending = true;
+}
+
+DDReport *DD::GetReport(DDCallback *cb) {
+ if (!cb->pt->report_pending)
+ return 0;
+ cb->pt->report_pending = false;
+ return &cb->pt->rep;
+}
+
+} // namespace __sanitizer
+#endif // #if SANITIZER_DEADLOCK_DETECTOR_VERSION == 2
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h
new file mode 100644
index 00000000000..7f461c98bad
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_deadlock_detector_interface.h
@@ -0,0 +1,98 @@
+//===-- sanitizer_deadlock_detector_interface.h -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer runtime.
+// Abstract deadlock detector interface.
+// FIXME: this is work in progress, nothing really works yet.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_DEADLOCK_DETECTOR_INTERFACE_H
+#define SANITIZER_DEADLOCK_DETECTOR_INTERFACE_H
+
+#ifndef SANITIZER_DEADLOCK_DETECTOR_VERSION
+# define SANITIZER_DEADLOCK_DETECTOR_VERSION 1
+#endif
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_atomic.h"
+
+namespace __sanitizer {
+
+// dd - deadlock detector.
+// lt - logical (user) thread.
+// pt - physical (OS) thread.
+
+struct DDPhysicalThread;
+struct DDLogicalThread;
+
+struct DDMutex {
+#if SANITIZER_DEADLOCK_DETECTOR_VERSION == 1
+ uptr id;
+ u32 stk; // creation stack
+#elif SANITIZER_DEADLOCK_DETECTOR_VERSION == 2
+ u32 id;
+ u32 recursion;
+ atomic_uintptr_t owner;
+#else
+# error "BAD SANITIZER_DEADLOCK_DETECTOR_VERSION"
+#endif
+ u64 ctx;
+};
+
+struct DDFlags {
+ bool second_deadlock_stack;
+};
+
+struct DDReport {
+ enum { kMaxLoopSize = 20 };
+ int n; // number of entries in loop
+ struct {
+ u64 thr_ctx; // user thread context
+ u64 mtx_ctx0; // user mutex context, start of the edge
+ u64 mtx_ctx1; // user mutex context, end of the edge
+ u32 stk[2]; // stack ids for the edge
+ } loop[kMaxLoopSize];
+};
+
+struct DDCallback {
+ DDPhysicalThread *pt;
+ DDLogicalThread *lt;
+
+ virtual u32 Unwind() { return 0; }
+ virtual int UniqueTid() { return 0; }
+
+ protected:
+ ~DDCallback() {}
+};
+
+struct DDetector {
+ static DDetector *Create(const DDFlags *flags);
+
+ virtual DDPhysicalThread* CreatePhysicalThread() { return nullptr; }
+ virtual void DestroyPhysicalThread(DDPhysicalThread *pt) {}
+
+ virtual DDLogicalThread* CreateLogicalThread(u64 ctx) { return nullptr; }
+ virtual void DestroyLogicalThread(DDLogicalThread *lt) {}
+
+ virtual void MutexInit(DDCallback *cb, DDMutex *m) {}
+ virtual void MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) {}
+ virtual void MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock,
+ bool trylock) {}
+ virtual void MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {}
+ virtual void MutexDestroy(DDCallback *cb, DDMutex *m) {}
+
+ virtual DDReport *GetReport(DDCallback *cb) { return nullptr; }
+
+ protected:
+ ~DDetector() {}
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_DEADLOCK_DETECTOR_INTERFACE_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_dense_map.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_dense_map.h
new file mode 100644
index 00000000000..046d77dddc9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_dense_map.h
@@ -0,0 +1,705 @@
+//===- sanitizer_dense_map.h - Dense probed hash table ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is fork of llvm/ADT/DenseMap.h class with the following changes:
+// * Use mmap to allocate.
+// * No iterators.
+// * Does not shrink.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_DENSE_MAP_H
+#define SANITIZER_DENSE_MAP_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_dense_map_info.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_type_traits.h"
+
+namespace __sanitizer {
+
+template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
+ typename BucketT>
+class DenseMapBase {
+ public:
+ using size_type = unsigned;
+ using key_type = KeyT;
+ using mapped_type = ValueT;
+ using value_type = BucketT;
+
+ WARN_UNUSED_RESULT bool empty() const { return getNumEntries() == 0; }
+ unsigned size() const { return getNumEntries(); }
+
+ /// Grow the densemap so that it can contain at least \p NumEntries items
+ /// before resizing again.
+ void reserve(size_type NumEntries) {
+ auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
+ if (NumBuckets > getNumBuckets())
+ grow(NumBuckets);
+ }
+
+ void clear() {
+ if (getNumEntries() == 0 && getNumTombstones() == 0)
+ return;
+
+ const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
+ if (__sanitizer::is_trivially_destructible<ValueT>::value) {
+ // Use a simpler loop when values don't need destruction.
+ for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P)
+ P->getFirst() = EmptyKey;
+ } else {
+ unsigned NumEntries = getNumEntries();
+ for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
+ if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) {
+ if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
+ P->getSecond().~ValueT();
+ --NumEntries;
+ }
+ P->getFirst() = EmptyKey;
+ }
+ }
+ CHECK_EQ(NumEntries, 0);
+ }
+ setNumEntries(0);
+ setNumTombstones(0);
+ }
+
+ /// Return 1 if the specified key is in the map, 0 otherwise.
+ size_type count(const KeyT &Key) const {
+ const BucketT *TheBucket;
+ return LookupBucketFor(Key, TheBucket) ? 1 : 0;
+ }
+
+ value_type *find(const KeyT &Key) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Key, TheBucket))
+ return TheBucket;
+ return nullptr;
+ }
+ const value_type *find(const KeyT &Key) const {
+ const BucketT *TheBucket;
+ if (LookupBucketFor(Key, TheBucket))
+ return TheBucket;
+ return nullptr;
+ }
+
+ /// Alternate version of find() which allows a different, and possibly
+ /// less expensive, key type.
+ /// The DenseMapInfo is responsible for supplying methods
+ /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
+ /// type used.
+ template <class LookupKeyT>
+ value_type *find_as(const LookupKeyT &Key) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Key, TheBucket))
+ return TheBucket;
+ return nullptr;
+ }
+ template <class LookupKeyT>
+ const value_type *find_as(const LookupKeyT &Key) const {
+ const BucketT *TheBucket;
+ if (LookupBucketFor(Key, TheBucket))
+ return TheBucket;
+ return nullptr;
+ }
+
+ /// lookup - Return the entry for the specified key, or a default
+ /// constructed value if no such entry exists.
+ ValueT lookup(const KeyT &Key) const {
+ const BucketT *TheBucket;
+ if (LookupBucketFor(Key, TheBucket))
+ return TheBucket->getSecond();
+ return ValueT();
+ }
+
+ // Inserts key,value pair into the map if the key isn't already in the map.
+ // If the key is already in the map, it returns false and doesn't update the
+ // value.
+ detail::DenseMapPair<value_type *, bool> insert(const value_type &KV) {
+ return try_emplace(KV.first, KV.second);
+ }
+
+ // Inserts key,value pair into the map if the key isn't already in the map.
+ // If the key is already in the map, it returns false and doesn't update the
+ // value.
+ detail::DenseMapPair<value_type *, bool> insert(value_type &&KV) {
+ return try_emplace(__sanitizer::move(KV.first),
+ __sanitizer::move(KV.second));
+ }
+
+ // Inserts key,value pair into the map if the key isn't already in the map.
+ // The value is constructed in-place if the key is not in the map, otherwise
+ // it is not moved.
+ template <typename... Ts>
+ detail::DenseMapPair<value_type *, bool> try_emplace(KeyT &&Key,
+ Ts &&...Args) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Key, TheBucket))
+ return {TheBucket, false}; // Already in map.
+
+ // Otherwise, insert the new element.
+ TheBucket = InsertIntoBucket(TheBucket, __sanitizer::move(Key),
+ __sanitizer::forward<Ts>(Args)...);
+ return {TheBucket, true};
+ }
+
+ // Inserts key,value pair into the map if the key isn't already in the map.
+ // The value is constructed in-place if the key is not in the map, otherwise
+ // it is not moved.
+ template <typename... Ts>
+ detail::DenseMapPair<value_type *, bool> try_emplace(const KeyT &Key,
+ Ts &&...Args) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Key, TheBucket))
+ return {TheBucket, false}; // Already in map.
+
+ // Otherwise, insert the new element.
+ TheBucket =
+ InsertIntoBucket(TheBucket, Key, __sanitizer::forward<Ts>(Args)...);
+ return {TheBucket, true};
+ }
+
+ /// Alternate version of insert() which allows a different, and possibly
+ /// less expensive, key type.
+ /// The DenseMapInfo is responsible for supplying methods
+ /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
+ /// type used.
+ template <typename LookupKeyT>
+ detail::DenseMapPair<value_type *, bool> insert_as(value_type &&KV,
+ const LookupKeyT &Val) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Val, TheBucket))
+ return {TheBucket, false}; // Already in map.
+
+ // Otherwise, insert the new element.
+ TheBucket =
+ InsertIntoBucketWithLookup(TheBucket, __sanitizer::move(KV.first),
+ __sanitizer::move(KV.second), Val);
+ return {TheBucket, true};
+ }
+
+ bool erase(const KeyT &Val) {
+ BucketT *TheBucket;
+ if (!LookupBucketFor(Val, TheBucket))
+ return false; // not in map.
+
+ TheBucket->getSecond().~ValueT();
+ TheBucket->getFirst() = getTombstoneKey();
+ decrementNumEntries();
+ incrementNumTombstones();
+ return true;
+ }
+
+ void erase(value_type *I) {
+ CHECK_NE(I, nullptr);
+ BucketT *TheBucket = &*I;
+ TheBucket->getSecond().~ValueT();
+ TheBucket->getFirst() = getTombstoneKey();
+ decrementNumEntries();
+ incrementNumTombstones();
+ }
+
+ value_type &FindAndConstruct(const KeyT &Key) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Key, TheBucket))
+ return *TheBucket;
+
+ return *InsertIntoBucket(TheBucket, Key);
+ }
+
+ ValueT &operator[](const KeyT &Key) { return FindAndConstruct(Key).second; }
+
+ value_type &FindAndConstruct(KeyT &&Key) {
+ BucketT *TheBucket;
+ if (LookupBucketFor(Key, TheBucket))
+ return *TheBucket;
+
+ return *InsertIntoBucket(TheBucket, __sanitizer::move(Key));
+ }
+
+ ValueT &operator[](KeyT &&Key) {
+ return FindAndConstruct(__sanitizer::move(Key)).second;
+ }
+
+ /// Iterate over active entries of the container.
+ ///
+ /// Function can return fast to stop the process.
+ template <class Fn>
+ void forEach(Fn fn) {
+ const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
+ for (auto *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
+ const KeyT K = P->getFirst();
+ if (!KeyInfoT::isEqual(K, EmptyKey) &&
+ !KeyInfoT::isEqual(K, TombstoneKey)) {
+ if (!fn(*P))
+ return;
+ }
+ }
+ }
+
+ template <class Fn>
+ void forEach(Fn fn) const {
+ const_cast<DenseMapBase *>(this)->forEach(
+ [&](const value_type &KV) { return fn(KV); });
+ }
+
+ protected:
+ DenseMapBase() = default;
+
+ void destroyAll() {
+ if (getNumBuckets() == 0) // Nothing to do.
+ return;
+
+ const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
+ for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
+ if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(P->getFirst(), TombstoneKey))
+ P->getSecond().~ValueT();
+ P->getFirst().~KeyT();
+ }
+ }
+
+ void initEmpty() {
+ setNumEntries(0);
+ setNumTombstones(0);
+
+ CHECK_EQ((getNumBuckets() & (getNumBuckets() - 1)), 0);
+ const KeyT EmptyKey = getEmptyKey();
+ for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B)
+ ::new (&B->getFirst()) KeyT(EmptyKey);
+ }
+
+ /// Returns the number of buckets to allocate to ensure that the DenseMap can
+ /// accommodate \p NumEntries without need to grow().
+ unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
+ // Ensure that "NumEntries * 4 < NumBuckets * 3"
+ if (NumEntries == 0)
+ return 0;
+ // +1 is required because of the strict equality.
+ // For example if NumEntries is 48, we need to return 401.
+ return RoundUpToPowerOfTwo((NumEntries * 4 / 3 + 1) + /* NextPowerOf2 */ 1);
+ }
+
+ void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) {
+ initEmpty();
+
+ // Insert all the old elements.
+ const KeyT EmptyKey = getEmptyKey();
+ const KeyT TombstoneKey = getTombstoneKey();
+ for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) {
+ if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) &&
+ !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) {
+ // Insert the key/value into the new table.
+ BucketT *DestBucket;
+ bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket);
+ (void)FoundVal; // silence warning.
+ CHECK(!FoundVal);
+ DestBucket->getFirst() = __sanitizer::move(B->getFirst());
+ ::new (&DestBucket->getSecond())
+ ValueT(__sanitizer::move(B->getSecond()));
+ incrementNumEntries();
+
+ // Free the value.
+ B->getSecond().~ValueT();
+ }
+ B->getFirst().~KeyT();
+ }
+ }
+
+ template <typename OtherBaseT>
+ void copyFrom(
+ const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) {
+ CHECK_NE(&other, this);
+ CHECK_EQ(getNumBuckets(), other.getNumBuckets());
+
+ setNumEntries(other.getNumEntries());
+ setNumTombstones(other.getNumTombstones());
+
+ if (__sanitizer::is_trivially_copyable<KeyT>::value &&
+ __sanitizer::is_trivially_copyable<ValueT>::value)
+ internal_memcpy(reinterpret_cast<void *>(getBuckets()),
+ other.getBuckets(), getNumBuckets() * sizeof(BucketT));
+ else
+ for (uptr i = 0; i < getNumBuckets(); ++i) {
+ ::new (&getBuckets()[i].getFirst())
+ KeyT(other.getBuckets()[i].getFirst());
+ if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) &&
+ !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey()))
+ ::new (&getBuckets()[i].getSecond())
+ ValueT(other.getBuckets()[i].getSecond());
+ }
+ }
+
+ static unsigned getHashValue(const KeyT &Val) {
+ return KeyInfoT::getHashValue(Val);
+ }
+
+ template <typename LookupKeyT>
+ static unsigned getHashValue(const LookupKeyT &Val) {
+ return KeyInfoT::getHashValue(Val);
+ }
+
+ static const KeyT getEmptyKey() { return KeyInfoT::getEmptyKey(); }
+
+ static const KeyT getTombstoneKey() { return KeyInfoT::getTombstoneKey(); }
+
+ private:
+ unsigned getNumEntries() const {
+ return static_cast<const DerivedT *>(this)->getNumEntries();
+ }
+
+ void setNumEntries(unsigned Num) {
+ static_cast<DerivedT *>(this)->setNumEntries(Num);
+ }
+
+ void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
+
+ void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
+
+ unsigned getNumTombstones() const {
+ return static_cast<const DerivedT *>(this)->getNumTombstones();
+ }
+
+ void setNumTombstones(unsigned Num) {
+ static_cast<DerivedT *>(this)->setNumTombstones(Num);
+ }
+
+ void incrementNumTombstones() { setNumTombstones(getNumTombstones() + 1); }
+
+ void decrementNumTombstones() { setNumTombstones(getNumTombstones() - 1); }
+
+ const BucketT *getBuckets() const {
+ return static_cast<const DerivedT *>(this)->getBuckets();
+ }
+
+ BucketT *getBuckets() { return static_cast<DerivedT *>(this)->getBuckets(); }
+
+ unsigned getNumBuckets() const {
+ return static_cast<const DerivedT *>(this)->getNumBuckets();
+ }
+
+ BucketT *getBucketsEnd() { return getBuckets() + getNumBuckets(); }
+
+ const BucketT *getBucketsEnd() const {
+ return getBuckets() + getNumBuckets();
+ }
+
+ void grow(unsigned AtLeast) { static_cast<DerivedT *>(this)->grow(AtLeast); }
+
+ template <typename KeyArg, typename... ValueArgs>
+ BucketT *InsertIntoBucket(BucketT *TheBucket, KeyArg &&Key,
+ ValueArgs &&...Values) {
+ TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
+
+ TheBucket->getFirst() = __sanitizer::forward<KeyArg>(Key);
+ ::new (&TheBucket->getSecond())
+ ValueT(__sanitizer::forward<ValueArgs>(Values)...);
+ return TheBucket;
+ }
+
+ template <typename LookupKeyT>
+ BucketT *InsertIntoBucketWithLookup(BucketT *TheBucket, KeyT &&Key,
+ ValueT &&Value, LookupKeyT &Lookup) {
+ TheBucket = InsertIntoBucketImpl(Key, Lookup, TheBucket);
+
+ TheBucket->getFirst() = __sanitizer::move(Key);
+ ::new (&TheBucket->getSecond()) ValueT(__sanitizer::move(Value));
+ return TheBucket;
+ }
+
+ template <typename LookupKeyT>
+ BucketT *InsertIntoBucketImpl(const KeyT &Key, const LookupKeyT &Lookup,
+ BucketT *TheBucket) {
+ // If the load of the hash table is more than 3/4, or if fewer than 1/8 of
+ // the buckets are empty (meaning that many are filled with tombstones),
+ // grow the table.
+ //
+ // The later case is tricky. For example, if we had one empty bucket with
+ // tons of tombstones, failing lookups (e.g. for insertion) would have to
+ // probe almost the entire table until it found the empty bucket. If the
+ // table completely filled with tombstones, no lookup would ever succeed,
+ // causing infinite loops in lookup.
+ unsigned NewNumEntries = getNumEntries() + 1;
+ unsigned NumBuckets = getNumBuckets();
+ if (UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
+ this->grow(NumBuckets * 2);
+ LookupBucketFor(Lookup, TheBucket);
+ NumBuckets = getNumBuckets();
+ } else if (UNLIKELY(NumBuckets - (NewNumEntries + getNumTombstones()) <=
+ NumBuckets / 8)) {
+ this->grow(NumBuckets);
+ LookupBucketFor(Lookup, TheBucket);
+ }
+ CHECK(TheBucket);
+
+ // Only update the state after we've grown our bucket space appropriately
+ // so that when growing buckets we have self-consistent entry count.
+ incrementNumEntries();
+
+ // If we are writing over a tombstone, remember this.
+ const KeyT EmptyKey = getEmptyKey();
+ if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey))
+ decrementNumTombstones();
+
+ return TheBucket;
+ }
+
+ /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in
+ /// FoundBucket. If the bucket contains the key and a value, this returns
+ /// true, otherwise it returns a bucket with an empty marker or tombstone and
+ /// returns false.
+ template <typename LookupKeyT>
+ bool LookupBucketFor(const LookupKeyT &Val,
+ const BucketT *&FoundBucket) const {
+ const BucketT *BucketsPtr = getBuckets();
+ const unsigned NumBuckets = getNumBuckets();
+
+ if (NumBuckets == 0) {
+ FoundBucket = nullptr;
+ return false;
+ }
+
+ // FoundTombstone - Keep track of whether we find a tombstone while probing.
+ const BucketT *FoundTombstone = nullptr;
+ const KeyT EmptyKey = getEmptyKey();
+ const KeyT TombstoneKey = getTombstoneKey();
+ CHECK(!KeyInfoT::isEqual(Val, EmptyKey));
+ CHECK(!KeyInfoT::isEqual(Val, TombstoneKey));
+
+ unsigned BucketNo = getHashValue(Val) & (NumBuckets - 1);
+ unsigned ProbeAmt = 1;
+ while (true) {
+ const BucketT *ThisBucket = BucketsPtr + BucketNo;
+ // Found Val's bucket? If so, return it.
+ if (LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
+ FoundBucket = ThisBucket;
+ return true;
+ }
+
+ // If we found an empty bucket, the key doesn't exist in the set.
+ // Insert it and return the default value.
+ if (LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) {
+ // If we've already seen a tombstone while probing, fill it in instead
+ // of the empty bucket we eventually probed to.
+ FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
+ return false;
+ }
+
+ // If this is a tombstone, remember it. If Val ends up not in the map, we
+ // prefer to return it than something that would require more probing.
+ if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) &&
+ !FoundTombstone)
+ FoundTombstone = ThisBucket; // Remember the first tombstone found.
+
+ // Otherwise, it's a hash collision or a tombstone, continue quadratic
+ // probing.
+ BucketNo += ProbeAmt++;
+ BucketNo &= (NumBuckets - 1);
+ }
+ }
+
+ template <typename LookupKeyT>
+ bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) {
+ const BucketT *ConstFoundBucket;
+ bool Result = const_cast<const DenseMapBase *>(this)->LookupBucketFor(
+ Val, ConstFoundBucket);
+ FoundBucket = const_cast<BucketT *>(ConstFoundBucket);
+ return Result;
+ }
+
+ public:
+ /// Return the approximate size (in bytes) of the actual map.
+ /// This is just the raw memory used by DenseMap.
+ /// If entries are pointers to objects, the size of the referenced objects
+ /// are not included.
+ uptr getMemorySize() const {
+ return RoundUpTo(getNumBuckets() * sizeof(BucketT), GetPageSizeCached());
+ }
+};
+
+/// Equality comparison for DenseMap.
+///
+/// Iterates over elements of LHS confirming that each (key, value) pair in LHS
+/// is also in RHS, and that no additional pairs are in RHS.
+/// Equivalent to N calls to RHS.find and N value comparisons. Amortized
+/// complexity is linear, worst case is O(N^2) (if every hash collides).
+template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
+ typename BucketT>
+bool operator==(
+ const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
+ const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
+ if (LHS.size() != RHS.size())
+ return false;
+
+ bool R = true;
+ LHS.forEach(
+ [&](const typename DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT,
+ BucketT>::value_type &KV) -> bool {
+ const auto *I = RHS.find(KV.first);
+ if (!I || I->second != KV.second) {
+ R = false;
+ return false;
+ }
+ return true;
+ });
+
+ return R;
+}
+
+/// Inequality comparison for DenseMap.
+///
+/// Equivalent to !(LHS == RHS). See operator== for performance notes.
+template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
+ typename BucketT>
+bool operator!=(
+ const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
+ const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
+ return !(LHS == RHS);
+}
+
+template <typename KeyT, typename ValueT,
+ typename KeyInfoT = DenseMapInfo<KeyT>,
+ typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
+class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
+ KeyT, ValueT, KeyInfoT, BucketT> {
+ friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
+
+ // Lift some types from the dependent base class into this class for
+ // simplicity of referring to them.
+ using BaseT = DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
+
+ BucketT *Buckets = nullptr;
+ unsigned NumEntries = 0;
+ unsigned NumTombstones = 0;
+ unsigned NumBuckets = 0;
+
+ public:
+ /// Create a DenseMap with an optional \p InitialReserve that guarantee that
+ /// this number of elements can be inserted in the map without grow()
+ explicit DenseMap(unsigned InitialReserve) { init(InitialReserve); }
+ constexpr DenseMap() = default;
+
+ DenseMap(const DenseMap &other) : BaseT() {
+ init(0);
+ copyFrom(other);
+ }
+
+ DenseMap(DenseMap &&other) : BaseT() {
+ init(0);
+ swap(other);
+ }
+
+ ~DenseMap() {
+ this->destroyAll();
+ deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets);
+ }
+
+ void swap(DenseMap &RHS) {
+ Swap(Buckets, RHS.Buckets);
+ Swap(NumEntries, RHS.NumEntries);
+ Swap(NumTombstones, RHS.NumTombstones);
+ Swap(NumBuckets, RHS.NumBuckets);
+ }
+
+ DenseMap &operator=(const DenseMap &other) {
+ if (&other != this)
+ copyFrom(other);
+ return *this;
+ }
+
+ DenseMap &operator=(DenseMap &&other) {
+ this->destroyAll();
+ deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT));
+ init(0);
+ swap(other);
+ return *this;
+ }
+
+ void copyFrom(const DenseMap &other) {
+ this->destroyAll();
+ deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets);
+ if (allocateBuckets(other.NumBuckets)) {
+ this->BaseT::copyFrom(other);
+ } else {
+ NumEntries = 0;
+ NumTombstones = 0;
+ }
+ }
+
+ void init(unsigned InitNumEntries) {
+ auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
+ if (allocateBuckets(InitBuckets)) {
+ this->BaseT::initEmpty();
+ } else {
+ NumEntries = 0;
+ NumTombstones = 0;
+ }
+ }
+
+ void grow(unsigned AtLeast) {
+ unsigned OldNumBuckets = NumBuckets;
+ BucketT *OldBuckets = Buckets;
+
+ allocateBuckets(RoundUpToPowerOfTwo(Max<unsigned>(64, AtLeast)));
+ CHECK(Buckets);
+ if (!OldBuckets) {
+ this->BaseT::initEmpty();
+ return;
+ }
+
+ this->moveFromOldBuckets(OldBuckets, OldBuckets + OldNumBuckets);
+
+ // Free the old table.
+ deallocate_buffer(OldBuckets, sizeof(BucketT) * OldNumBuckets);
+ }
+
+ private:
+ unsigned getNumEntries() const { return NumEntries; }
+
+ void setNumEntries(unsigned Num) { NumEntries = Num; }
+
+ unsigned getNumTombstones() const { return NumTombstones; }
+
+ void setNumTombstones(unsigned Num) { NumTombstones = Num; }
+
+ BucketT *getBuckets() const { return Buckets; }
+
+ unsigned getNumBuckets() const { return NumBuckets; }
+
+ bool allocateBuckets(unsigned Num) {
+ NumBuckets = Num;
+ if (NumBuckets == 0) {
+ Buckets = nullptr;
+ return false;
+ }
+
+ uptr Size = sizeof(BucketT) * NumBuckets;
+ if (Size * 2 <= GetPageSizeCached()) {
+ // We always allocate at least a page, so use entire space.
+ unsigned Log2 = MostSignificantSetBitIndex(GetPageSizeCached() / Size);
+ Size <<= Log2;
+ NumBuckets <<= Log2;
+ CHECK_EQ(Size, sizeof(BucketT) * NumBuckets);
+ CHECK_GT(Size * 2, GetPageSizeCached());
+ }
+ Buckets = static_cast<BucketT *>(allocate_buffer(Size));
+ return true;
+ }
+
+ static void *allocate_buffer(uptr Size) {
+ return MmapOrDie(RoundUpTo(Size, GetPageSizeCached()), "DenseMap");
+ }
+
+ static void deallocate_buffer(void *Ptr, uptr Size) {
+ UnmapOrDie(Ptr, RoundUpTo(Size, GetPageSizeCached()));
+ }
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_DENSE_MAP_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_dense_map_info.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_dense_map_info.h
new file mode 100644
index 00000000000..f4640369ae5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_dense_map_info.h
@@ -0,0 +1,282 @@
+//===- sanitizer_dense_map_info.h - Type traits for DenseMap ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_DENSE_MAP_INFO_H
+#define SANITIZER_DENSE_MAP_INFO_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_type_traits.h"
+
+namespace __sanitizer {
+
+namespace detail {
+
+/// Simplistic combination of 32-bit hash values into 32-bit hash values.
+static constexpr unsigned combineHashValue(unsigned a, unsigned b) {
+ u64 key = (u64)a << 32 | (u64)b;
+ key += ~(key << 32);
+ key ^= (key >> 22);
+ key += ~(key << 13);
+ key ^= (key >> 8);
+ key += (key << 3);
+ key ^= (key >> 15);
+ key += ~(key << 27);
+ key ^= (key >> 31);
+ return (unsigned)key;
+}
+
+// We extend a pair to allow users to override the bucket type with their own
+// implementation without requiring two members.
+template <typename KeyT, typename ValueT>
+struct DenseMapPair {
+ KeyT first = {};
+ ValueT second = {};
+ constexpr DenseMapPair() = default;
+ constexpr DenseMapPair(const KeyT &f, const ValueT &s)
+ : first(f), second(s) {}
+
+ template <typename KeyT2, typename ValueT2>
+ constexpr DenseMapPair(KeyT2 &&f, ValueT2 &&s)
+ : first(__sanitizer::forward<KeyT2>(f)),
+ second(__sanitizer::forward<ValueT2>(s)) {}
+
+ constexpr DenseMapPair(const DenseMapPair &other) = default;
+ constexpr DenseMapPair &operator=(const DenseMapPair &other) = default;
+ constexpr DenseMapPair(DenseMapPair &&other) = default;
+ constexpr DenseMapPair &operator=(DenseMapPair &&other) = default;
+
+ KeyT &getFirst() { return first; }
+ const KeyT &getFirst() const { return first; }
+ ValueT &getSecond() { return second; }
+ const ValueT &getSecond() const { return second; }
+};
+
+} // end namespace detail
+
+template <typename T>
+struct DenseMapInfo {
+ // static T getEmptyKey();
+ // static T getTombstoneKey();
+ // static unsigned getHashValue(const T &Val);
+ // static bool isEqual(const T &LHS, const T &RHS);
+};
+
+// Provide DenseMapInfo for all pointers. Come up with sentinel pointer values
+// that are aligned to alignof(T) bytes, but try to avoid requiring T to be
+// complete. This allows clients to instantiate DenseMap<T*, ...> with forward
+// declared key types. Assume that no pointer key type requires more than 4096
+// bytes of alignment.
+template <typename T>
+struct DenseMapInfo<T *> {
+ // The following should hold, but it would require T to be complete:
+ // static_assert(alignof(T) <= (1 << Log2MaxAlign),
+ // "DenseMap does not support pointer keys requiring more than "
+ // "Log2MaxAlign bits of alignment");
+ static constexpr uptr Log2MaxAlign = 12;
+
+ static constexpr T *getEmptyKey() {
+ uptr Val = static_cast<uptr>(-1);
+ Val <<= Log2MaxAlign;
+ return reinterpret_cast<T *>(Val);
+ }
+
+ static constexpr T *getTombstoneKey() {
+ uptr Val = static_cast<uptr>(-2);
+ Val <<= Log2MaxAlign;
+ return reinterpret_cast<T *>(Val);
+ }
+
+ static constexpr unsigned getHashValue(const T *PtrVal) {
+ return (unsigned((uptr)PtrVal) >> 4) ^ (unsigned((uptr)PtrVal) >> 9);
+ }
+
+ static constexpr bool isEqual(const T *LHS, const T *RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for chars.
+template <>
+struct DenseMapInfo<char> {
+ static constexpr char getEmptyKey() { return ~0; }
+ static constexpr char getTombstoneKey() { return ~0 - 1; }
+ static constexpr unsigned getHashValue(const char &Val) { return Val * 37U; }
+
+ static constexpr bool isEqual(const char &LHS, const char &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for unsigned chars.
+template <>
+struct DenseMapInfo<unsigned char> {
+ static constexpr unsigned char getEmptyKey() { return ~0; }
+ static constexpr unsigned char getTombstoneKey() { return ~0 - 1; }
+ static constexpr unsigned getHashValue(const unsigned char &Val) {
+ return Val * 37U;
+ }
+
+ static constexpr bool isEqual(const unsigned char &LHS,
+ const unsigned char &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for unsigned shorts.
+template <>
+struct DenseMapInfo<unsigned short> {
+ static constexpr unsigned short getEmptyKey() { return 0xFFFF; }
+ static constexpr unsigned short getTombstoneKey() { return 0xFFFF - 1; }
+ static constexpr unsigned getHashValue(const unsigned short &Val) {
+ return Val * 37U;
+ }
+
+ static constexpr bool isEqual(const unsigned short &LHS,
+ const unsigned short &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for unsigned ints.
+template <>
+struct DenseMapInfo<unsigned> {
+ static constexpr unsigned getEmptyKey() { return ~0U; }
+ static constexpr unsigned getTombstoneKey() { return ~0U - 1; }
+ static constexpr unsigned getHashValue(const unsigned &Val) {
+ return Val * 37U;
+ }
+
+ static constexpr bool isEqual(const unsigned &LHS, const unsigned &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for unsigned longs.
+template <>
+struct DenseMapInfo<unsigned long> {
+ static constexpr unsigned long getEmptyKey() { return ~0UL; }
+ static constexpr unsigned long getTombstoneKey() { return ~0UL - 1L; }
+
+ static constexpr unsigned getHashValue(const unsigned long &Val) {
+ return (unsigned)(Val * 37UL);
+ }
+
+ static constexpr bool isEqual(const unsigned long &LHS,
+ const unsigned long &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for unsigned long longs.
+template <>
+struct DenseMapInfo<unsigned long long> {
+ static constexpr unsigned long long getEmptyKey() { return ~0ULL; }
+ static constexpr unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
+
+ static constexpr unsigned getHashValue(const unsigned long long &Val) {
+ return (unsigned)(Val * 37ULL);
+ }
+
+ static constexpr bool isEqual(const unsigned long long &LHS,
+ const unsigned long long &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for shorts.
+template <>
+struct DenseMapInfo<short> {
+ static constexpr short getEmptyKey() { return 0x7FFF; }
+ static constexpr short getTombstoneKey() { return -0x7FFF - 1; }
+ static constexpr unsigned getHashValue(const short &Val) { return Val * 37U; }
+ static constexpr bool isEqual(const short &LHS, const short &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for ints.
+template <>
+struct DenseMapInfo<int> {
+ static constexpr int getEmptyKey() { return 0x7fffffff; }
+ static constexpr int getTombstoneKey() { return -0x7fffffff - 1; }
+ static constexpr unsigned getHashValue(const int &Val) {
+ return (unsigned)(Val * 37U);
+ }
+
+ static constexpr bool isEqual(const int &LHS, const int &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for longs.
+template <>
+struct DenseMapInfo<long> {
+ static constexpr long getEmptyKey() {
+ return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
+ }
+
+ static constexpr long getTombstoneKey() { return getEmptyKey() - 1L; }
+
+ static constexpr unsigned getHashValue(const long &Val) {
+ return (unsigned)(Val * 37UL);
+ }
+
+ static constexpr bool isEqual(const long &LHS, const long &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for long longs.
+template <>
+struct DenseMapInfo<long long> {
+ static constexpr long long getEmptyKey() { return 0x7fffffffffffffffLL; }
+ static constexpr long long getTombstoneKey() {
+ return -0x7fffffffffffffffLL - 1;
+ }
+
+ static constexpr unsigned getHashValue(const long long &Val) {
+ return (unsigned)(Val * 37ULL);
+ }
+
+ static constexpr bool isEqual(const long long &LHS, const long long &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Provide DenseMapInfo for all pairs whose members have info.
+template <typename T, typename U>
+struct DenseMapInfo<detail::DenseMapPair<T, U>> {
+ using Pair = detail::DenseMapPair<T, U>;
+ using FirstInfo = DenseMapInfo<T>;
+ using SecondInfo = DenseMapInfo<U>;
+
+ static constexpr Pair getEmptyKey() {
+ return detail::DenseMapPair<T, U>(FirstInfo::getEmptyKey(),
+ SecondInfo::getEmptyKey());
+ }
+
+ static constexpr Pair getTombstoneKey() {
+ return detail::DenseMapPair<T, U>(FirstInfo::getTombstoneKey(),
+ SecondInfo::getTombstoneKey());
+ }
+
+ static constexpr unsigned getHashValue(const Pair &PairVal) {
+ return detail::combineHashValue(FirstInfo::getHashValue(PairVal.first),
+ SecondInfo::getHashValue(PairVal.second));
+ }
+
+ static constexpr bool isEqual(const Pair &LHS, const Pair &RHS) {
+ return FirstInfo::isEqual(LHS.first, RHS.first) &&
+ SecondInfo::isEqual(LHS.second, RHS.second);
+ }
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_DENSE_MAP_INFO_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_errno.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_errno.cpp
new file mode 100644
index 00000000000..cbadf4d924a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_errno.cpp
@@ -0,0 +1,34 @@
+//===-- sanitizer_errno.cpp -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between sanitizers run-time libraries.
+//
+// Defines errno to avoid including errno.h and its dependencies into other
+// files (e.g. interceptors are not supposed to include any system headers).
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_errno_codes.h"
+#include "sanitizer_internal_defs.h"
+
+#include <errno.h>
+
+namespace __sanitizer {
+
+COMPILER_CHECK(errno_ENOMEM == ENOMEM);
+COMPILER_CHECK(errno_EBUSY == EBUSY);
+COMPILER_CHECK(errno_EINVAL == EINVAL);
+
+// EOWNERDEAD is not present in some older platforms.
+#if defined(EOWNERDEAD)
+extern const int errno_EOWNERDEAD = EOWNERDEAD;
+#else
+extern const int errno_EOWNERDEAD = -1;
+#endif
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_errno.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_errno.h
new file mode 100644
index 00000000000..46c85364cef
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_errno.h
@@ -0,0 +1,38 @@
+//===-- sanitizer_errno.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between sanitizers run-time libraries.
+//
+// Defines errno to avoid including errno.h and its dependencies into sensitive
+// files (e.g. interceptors are not supposed to include any system headers).
+// It's ok to use errno.h directly when your file already depend on other system
+// includes though.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ERRNO_H
+#define SANITIZER_ERRNO_H
+
+#include "sanitizer_errno_codes.h"
+#include "sanitizer_platform.h"
+
+#if SANITIZER_FREEBSD || SANITIZER_APPLE
+# define __errno_location __error
+#elif SANITIZER_ANDROID || SANITIZER_NETBSD
+# define __errno_location __errno
+#elif SANITIZER_SOLARIS
+# define __errno_location ___errno
+#elif SANITIZER_WINDOWS
+# define __errno_location _errno
+#endif
+
+extern "C" int *__errno_location();
+
+#define errno (*__errno_location())
+
+#endif // SANITIZER_ERRNO_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_errno_codes.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_errno_codes.h
new file mode 100644
index 00000000000..3917b2817f2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_errno_codes.h
@@ -0,0 +1,35 @@
+//===-- sanitizer_errno_codes.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between sanitizers run-time libraries.
+//
+// Defines errno codes to avoid including errno.h and its dependencies into
+// sensitive files (e.g. interceptors are not supposed to include any system
+// headers).
+// It's ok to use errno.h directly when your file already depend on other system
+// includes though.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ERRNO_CODES_H
+#define SANITIZER_ERRNO_CODES_H
+
+namespace __sanitizer {
+
+#define errno_ENOMEM 12
+#define errno_EBUSY 16
+#define errno_EINVAL 22
+#define errno_ENAMETOOLONG 36
+#define errno_ENOSYS 38
+
+// Those might not present or their value differ on different platforms.
+extern const int errno_EOWNERDEAD;
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_ERRNO_CODES_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_file.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_file.cpp
new file mode 100644
index 00000000000..7ef499ce07b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_file.cpp
@@ -0,0 +1,251 @@
+//===-- sanitizer_file.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries. It defines filesystem-related interfaces. This
+// is separate from sanitizer_common.cpp so that it's simpler to disable
+// all the filesystem support code for a port that doesn't use it.
+//
+//===---------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if !SANITIZER_FUCHSIA
+
+#include "sanitizer_common.h"
+#include "sanitizer_file.h"
+# include "sanitizer_interface_internal.h"
+
+namespace __sanitizer {
+
+void CatastrophicErrorWrite(const char *buffer, uptr length) {
+ WriteToFile(kStderrFd, buffer, length);
+}
+
+StaticSpinMutex report_file_mu;
+ReportFile report_file = {&report_file_mu, kStderrFd, "", "", 0};
+
+void RawWrite(const char *buffer) {
+ report_file.Write(buffer, internal_strlen(buffer));
+}
+
+void ReportFile::ReopenIfNecessary() {
+ mu->CheckLocked();
+ if (fd == kStdoutFd || fd == kStderrFd) return;
+
+ uptr pid = internal_getpid();
+ // If in tracer, use the parent's file.
+ if (pid == stoptheworld_tracer_pid)
+ pid = stoptheworld_tracer_ppid;
+ if (fd != kInvalidFd) {
+ // If the report file is already opened by the current process,
+ // do nothing. Otherwise the report file was opened by the parent
+ // process, close it now.
+ if (fd_pid == pid)
+ return;
+ else
+ CloseFile(fd);
+ }
+
+ const char *exe_name = GetProcessName();
+ if (common_flags()->log_exe_name && exe_name) {
+ internal_snprintf(full_path, kMaxPathLength, "%s.%s.%zu", path_prefix,
+ exe_name, pid);
+ } else {
+ internal_snprintf(full_path, kMaxPathLength, "%s.%zu", path_prefix, pid);
+ }
+ if (common_flags()->log_suffix) {
+ internal_strlcat(full_path, common_flags()->log_suffix, kMaxPathLength);
+ }
+ error_t err;
+ fd = OpenFile(full_path, WrOnly, &err);
+ if (fd == kInvalidFd) {
+ const char *ErrorMsgPrefix = "ERROR: Can't open file: ";
+ WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
+ WriteToFile(kStderrFd, full_path, internal_strlen(full_path));
+ char errmsg[100];
+ internal_snprintf(errmsg, sizeof(errmsg), " (reason: %d)", err);
+ WriteToFile(kStderrFd, errmsg, internal_strlen(errmsg));
+ Die();
+ }
+ fd_pid = pid;
+}
+
+static void RecursiveCreateParentDirs(char *path) {
+ if (path[0] == '\0')
+ return;
+ for (int i = 1; path[i] != '\0'; ++i) {
+ char save = path[i];
+ if (!IsPathSeparator(path[i]))
+ continue;
+ path[i] = '\0';
+ if (!DirExists(path) && !CreateDir(path)) {
+ const char *ErrorMsgPrefix = "ERROR: Can't create directory: ";
+ WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
+ WriteToFile(kStderrFd, path, internal_strlen(path));
+ Die();
+ }
+ path[i] = save;
+ }
+}
+
+void ReportFile::SetReportPath(const char *path) {
+ if (path) {
+ uptr len = internal_strlen(path);
+ if (len > sizeof(path_prefix) - 100) {
+ Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", path[0], path[1],
+ path[2], path[3], path[4], path[5], path[6], path[7]);
+ Die();
+ }
+ }
+
+ SpinMutexLock l(mu);
+ if (fd != kStdoutFd && fd != kStderrFd && fd != kInvalidFd)
+ CloseFile(fd);
+ fd = kInvalidFd;
+ if (!path || internal_strcmp(path, "stderr") == 0) {
+ fd = kStderrFd;
+ } else if (internal_strcmp(path, "stdout") == 0) {
+ fd = kStdoutFd;
+ } else {
+ internal_snprintf(path_prefix, kMaxPathLength, "%s", path);
+ RecursiveCreateParentDirs(path_prefix);
+ }
+}
+
+const char *ReportFile::GetReportPath() {
+ SpinMutexLock l(mu);
+ ReopenIfNecessary();
+ return full_path;
+}
+
+bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
+ uptr *read_len, uptr max_len, error_t *errno_p) {
+ *buff = nullptr;
+ *buff_size = 0;
+ *read_len = 0;
+ if (!max_len)
+ return true;
+ uptr PageSize = GetPageSizeCached();
+ uptr kMinFileLen = Min(PageSize, max_len);
+
+ // The files we usually open are not seekable, so try different buffer sizes.
+ for (uptr size = kMinFileLen;; size = Min(size * 2, max_len)) {
+ UnmapOrDie(*buff, *buff_size);
+ *buff = (char*)MmapOrDie(size, __func__);
+ *buff_size = size;
+ fd_t fd = OpenFile(file_name, RdOnly, errno_p);
+ if (fd == kInvalidFd) {
+ UnmapOrDie(*buff, *buff_size);
+ return false;
+ }
+ *read_len = 0;
+ // Read up to one page at a time.
+ bool reached_eof = false;
+ while (*read_len < size) {
+ uptr just_read;
+ if (!ReadFromFile(fd, *buff + *read_len, size - *read_len, &just_read,
+ errno_p)) {
+ UnmapOrDie(*buff, *buff_size);
+ CloseFile(fd);
+ return false;
+ }
+ *read_len += just_read;
+ if (just_read == 0 || *read_len == max_len) {
+ reached_eof = true;
+ break;
+ }
+ }
+ CloseFile(fd);
+ if (reached_eof) // We've read the whole file.
+ break;
+ }
+ return true;
+}
+
+bool ReadFileToVector(const char *file_name,
+ InternalMmapVectorNoCtor<char> *buff, uptr max_len,
+ error_t *errno_p) {
+ buff->clear();
+ if (!max_len)
+ return true;
+ uptr PageSize = GetPageSizeCached();
+ fd_t fd = OpenFile(file_name, RdOnly, errno_p);
+ if (fd == kInvalidFd)
+ return false;
+ uptr read_len = 0;
+ while (read_len < max_len) {
+ if (read_len >= buff->size())
+ buff->resize(Min(Max(PageSize, read_len * 2), max_len));
+ CHECK_LT(read_len, buff->size());
+ CHECK_LE(buff->size(), max_len);
+ uptr just_read;
+ if (!ReadFromFile(fd, buff->data() + read_len, buff->size() - read_len,
+ &just_read, errno_p)) {
+ CloseFile(fd);
+ return false;
+ }
+ read_len += just_read;
+ if (!just_read)
+ break;
+ }
+ CloseFile(fd);
+ buff->resize(read_len);
+ return true;
+}
+
+static const char kPathSeparator = SANITIZER_WINDOWS ? ';' : ':';
+
+char *FindPathToBinary(const char *name) {
+ if (FileExists(name)) {
+ return internal_strdup(name);
+ }
+
+ const char *path = GetEnv("PATH");
+ if (!path)
+ return nullptr;
+ uptr name_len = internal_strlen(name);
+ InternalMmapVector<char> buffer(kMaxPathLength);
+ const char *beg = path;
+ while (true) {
+ const char *end = internal_strchrnul(beg, kPathSeparator);
+ uptr prefix_len = end - beg;
+ if (prefix_len + name_len + 2 <= kMaxPathLength) {
+ internal_memcpy(buffer.data(), beg, prefix_len);
+ buffer[prefix_len] = '/';
+ internal_memcpy(&buffer[prefix_len + 1], name, name_len);
+ buffer[prefix_len + 1 + name_len] = '\0';
+ if (FileExists(buffer.data()))
+ return internal_strdup(buffer.data());
+ }
+ if (*end == '\0') break;
+ beg = end + 1;
+ }
+ return nullptr;
+}
+
+} // namespace __sanitizer
+
+using namespace __sanitizer;
+
+extern "C" {
+void __sanitizer_set_report_path(const char *path) {
+ report_file.SetReportPath(path);
+}
+
+void __sanitizer_set_report_fd(void *fd) {
+ report_file.fd = (fd_t)reinterpret_cast<uptr>(fd);
+ report_file.fd_pid = internal_getpid();
+}
+
+const char *__sanitizer_get_report_path() {
+ return report_file.GetReportPath();
+}
+} // extern "C"
+
+#endif // !SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_file.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_file.h
new file mode 100644
index 00000000000..810c1e452f6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_file.h
@@ -0,0 +1,109 @@
+//===-- sanitizer_file.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// This file is shared between run-time libraries of sanitizers.
+// It declares filesystem-related interfaces. This is separate from
+// sanitizer_common.h so that it's simpler to disable all the filesystem
+// support code for a port that doesn't use it.
+//
+//===---------------------------------------------------------------------===//
+#ifndef SANITIZER_FILE_H
+#define SANITIZER_FILE_H
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_mutex.h"
+
+namespace __sanitizer {
+
+struct ReportFile {
+ void Write(const char *buffer, uptr length);
+ bool SupportsColors();
+ void SetReportPath(const char *path);
+ const char *GetReportPath();
+
+ // Don't use fields directly. They are only declared public to allow
+ // aggregate initialization.
+
+ // Protects fields below.
+ StaticSpinMutex *mu;
+ // Opened file descriptor. Defaults to stderr. It may be equal to
+ // kInvalidFd, in which case new file will be opened when necessary.
+ fd_t fd;
+ // Path prefix of report file, set via __sanitizer_set_report_path.
+ char path_prefix[kMaxPathLength];
+ // Full path to report, obtained as <path_prefix>.PID
+ char full_path[kMaxPathLength];
+ // PID of the process that opened fd. If a fork() occurs,
+ // the PID of child will be different from fd_pid.
+ uptr fd_pid;
+
+ private:
+ void ReopenIfNecessary();
+};
+extern ReportFile report_file;
+
+enum FileAccessMode {
+ RdOnly,
+ WrOnly,
+ RdWr
+};
+
+// Returns kInvalidFd on error.
+fd_t OpenFile(const char *filename, FileAccessMode mode,
+ error_t *errno_p = nullptr);
+void CloseFile(fd_t);
+
+// Return true on success, false on error.
+bool ReadFromFile(fd_t fd, void *buff, uptr buff_size,
+ uptr *bytes_read = nullptr, error_t *error_p = nullptr);
+bool WriteToFile(fd_t fd, const void *buff, uptr buff_size,
+ uptr *bytes_written = nullptr, error_t *error_p = nullptr);
+
+// Scoped file handle closer.
+struct FileCloser {
+ explicit FileCloser(fd_t fd) : fd(fd) {}
+ ~FileCloser() { CloseFile(fd); }
+ fd_t fd;
+};
+
+bool SupportsColoredOutput(fd_t fd);
+
+// OS
+const char *GetPwd();
+bool FileExists(const char *filename);
+bool DirExists(const char *path);
+char *FindPathToBinary(const char *name);
+bool IsPathSeparator(const char c);
+bool IsAbsolutePath(const char *path);
+// Returns true on success, false on failure.
+bool CreateDir(const char *pathname);
+// Starts a subprocess and returs its pid.
+// If *_fd parameters are not kInvalidFd their corresponding input/output
+// streams will be redirect to the file. The files will always be closed
+// in parent process even in case of an error.
+// The child process will close all fds after STDERR_FILENO
+// before passing control to a program.
+pid_t StartSubprocess(const char *filename, const char *const argv[],
+ const char *const envp[], fd_t stdin_fd = kInvalidFd,
+ fd_t stdout_fd = kInvalidFd, fd_t stderr_fd = kInvalidFd);
+// Checks if specified process is still running
+bool IsProcessRunning(pid_t pid);
+// Waits for the process to finish and returns its exit code.
+// Returns -1 in case of an error.
+int WaitForProcess(pid_t pid);
+
+// Maps given file to virtual memory, and returns pointer to it
+// (or NULL if mapping fails). Stores the size of mmaped region
+// in '*buff_size'.
+void *MapFileToMemory(const char *file_name, uptr *buff_size);
+void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_FILE_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flag_parser.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flag_parser.cpp
new file mode 100644
index 00000000000..9e274268bf2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flag_parser.cpp
@@ -0,0 +1,191 @@
+//===-- sanitizer_flag_parser.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_flag_parser.h"
+
+#include "sanitizer_common.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_flag_parser.h"
+
+namespace __sanitizer {
+
+LowLevelAllocator FlagParser::Alloc;
+
+class UnknownFlags {
+ static const int kMaxUnknownFlags = 20;
+ const char *unknown_flags_[kMaxUnknownFlags];
+ int n_unknown_flags_;
+
+ public:
+ void Add(const char *name) {
+ CHECK_LT(n_unknown_flags_, kMaxUnknownFlags);
+ unknown_flags_[n_unknown_flags_++] = name;
+ }
+
+ void Report() {
+ if (!n_unknown_flags_) return;
+ Printf("WARNING: found %d unrecognized flag(s):\n", n_unknown_flags_);
+ for (int i = 0; i < n_unknown_flags_; ++i)
+ Printf(" %s\n", unknown_flags_[i]);
+ n_unknown_flags_ = 0;
+ }
+};
+
+UnknownFlags unknown_flags;
+
+void ReportUnrecognizedFlags() {
+ unknown_flags.Report();
+}
+
+char *FlagParser::ll_strndup(const char *s, uptr n) {
+ uptr len = internal_strnlen(s, n);
+ char *s2 = (char*)Alloc.Allocate(len + 1);
+ internal_memcpy(s2, s, len);
+ s2[len] = 0;
+ return s2;
+}
+
+void FlagParser::PrintFlagDescriptions() {
+ char buffer[128];
+ buffer[sizeof(buffer) - 1] = '\0';
+ Printf("Available flags for %s:\n", SanitizerToolName);
+ for (int i = 0; i < n_flags_; ++i) {
+ bool truncated = !(flags_[i].handler->Format(buffer, sizeof(buffer)));
+ CHECK_EQ(buffer[sizeof(buffer) - 1], '\0');
+ const char *truncation_str = truncated ? " Truncated" : "";
+ Printf("\t%s\n\t\t- %s (Current Value%s: %s)\n", flags_[i].name,
+ flags_[i].desc, truncation_str, buffer);
+ }
+}
+
+void FlagParser::fatal_error(const char *err) {
+ Printf("%s: ERROR: %s\n", SanitizerToolName, err);
+ Die();
+}
+
+bool FlagParser::is_space(char c) {
+ return c == ' ' || c == ',' || c == ':' || c == '\n' || c == '\t' ||
+ c == '\r';
+}
+
+void FlagParser::skip_whitespace() {
+ while (is_space(buf_[pos_])) ++pos_;
+}
+
+void FlagParser::parse_flag(const char *env_option_name) {
+ uptr name_start = pos_;
+ while (buf_[pos_] != 0 && buf_[pos_] != '=' && !is_space(buf_[pos_])) ++pos_;
+ if (buf_[pos_] != '=') {
+ if (env_option_name) {
+ Printf("%s: ERROR: expected '=' in %s\n", SanitizerToolName,
+ env_option_name);
+ Die();
+ } else {
+ fatal_error("expected '='");
+ }
+ }
+ char *name = ll_strndup(buf_ + name_start, pos_ - name_start);
+
+ uptr value_start = ++pos_;
+ char *value;
+ if (buf_[pos_] == '\'' || buf_[pos_] == '"') {
+ char quote = buf_[pos_++];
+ while (buf_[pos_] != 0 && buf_[pos_] != quote) ++pos_;
+ if (buf_[pos_] == 0) fatal_error("unterminated string");
+ value = ll_strndup(buf_ + value_start + 1, pos_ - value_start - 1);
+ ++pos_; // consume the closing quote
+ } else {
+ while (buf_[pos_] != 0 && !is_space(buf_[pos_])) ++pos_;
+ if (buf_[pos_] != 0 && !is_space(buf_[pos_]))
+ fatal_error("expected separator or eol");
+ value = ll_strndup(buf_ + value_start, pos_ - value_start);
+ }
+
+ bool res = run_handler(name, value);
+ if (!res) fatal_error("Flag parsing failed.");
+}
+
+void FlagParser::parse_flags(const char *env_option_name) {
+ while (true) {
+ skip_whitespace();
+ if (buf_[pos_] == 0) break;
+ parse_flag(env_option_name);
+ }
+
+ // Do a sanity check for certain flags.
+ if (common_flags_dont_use.malloc_context_size < 1)
+ common_flags_dont_use.malloc_context_size = 1;
+}
+
+void FlagParser::ParseStringFromEnv(const char *env_name) {
+ const char *env = GetEnv(env_name);
+ VPrintf(1, "%s: %s\n", env_name, env ? env : "<empty>");
+ ParseString(env, env_name);
+}
+
+void FlagParser::ParseString(const char *s, const char *env_option_name) {
+ if (!s) return;
+ // Backup current parser state to allow nested ParseString() calls.
+ const char *old_buf_ = buf_;
+ uptr old_pos_ = pos_;
+ buf_ = s;
+ pos_ = 0;
+
+ parse_flags(env_option_name);
+
+ buf_ = old_buf_;
+ pos_ = old_pos_;
+}
+
+bool FlagParser::ParseFile(const char *path, bool ignore_missing) {
+ static const uptr kMaxIncludeSize = 1 << 15;
+ char *data;
+ uptr data_mapped_size;
+ error_t err;
+ uptr len;
+ if (!ReadFileToBuffer(path, &data, &data_mapped_size, &len,
+ Max(kMaxIncludeSize, GetPageSizeCached()), &err)) {
+ if (ignore_missing)
+ return true;
+ Printf("Failed to read options from '%s': error %d\n", path, err);
+ return false;
+ }
+ ParseString(data, path);
+ UnmapOrDie(data, data_mapped_size);
+ return true;
+}
+
+bool FlagParser::run_handler(const char *name, const char *value) {
+ for (int i = 0; i < n_flags_; ++i) {
+ if (internal_strcmp(name, flags_[i].name) == 0)
+ return flags_[i].handler->Parse(value);
+ }
+ // Unrecognized flag. This is not a fatal error, we may print a warning later.
+ unknown_flags.Add(name);
+ return true;
+}
+
+void FlagParser::RegisterHandler(const char *name, FlagHandlerBase *handler,
+ const char *desc) {
+ CHECK_LT(n_flags_, kMaxFlags);
+ flags_[n_flags_].name = name;
+ flags_[n_flags_].desc = desc;
+ flags_[n_flags_].handler = handler;
+ ++n_flags_;
+}
+
+FlagParser::FlagParser() : n_flags_(0), buf_(nullptr), pos_(0) {
+ flags_ = (Flag *)Alloc.Allocate(sizeof(Flag) * kMaxFlags);
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flag_parser.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flag_parser.h
new file mode 100644
index 00000000000..3ccc6a6fa53
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flag_parser.h
@@ -0,0 +1,204 @@
+//===-- sanitizer_flag_parser.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_FLAG_REGISTRY_H
+#define SANITIZER_FLAG_REGISTRY_H
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+
+class FlagHandlerBase {
+ public:
+ virtual bool Parse(const char *value) { return false; }
+ // Write the C string representation of the current value (truncated to fit)
+ // into the buffer of size `size`. Returns false if truncation occurred and
+ // returns true otherwise.
+ virtual bool Format(char *buffer, uptr size) {
+ if (size > 0)
+ buffer[0] = '\0';
+ return false;
+ }
+
+ protected:
+ ~FlagHandlerBase() {}
+
+ inline bool FormatString(char *buffer, uptr size, const char *str_to_use) {
+ uptr num_symbols_should_write =
+ internal_snprintf(buffer, size, "%s", str_to_use);
+ return num_symbols_should_write < size;
+ }
+};
+
+template <typename T>
+class FlagHandler final : public FlagHandlerBase {
+ T *t_;
+
+ public:
+ explicit FlagHandler(T *t) : t_(t) {}
+ bool Parse(const char *value) final;
+ bool Format(char *buffer, uptr size) final;
+};
+
+inline bool ParseBool(const char *value, bool *b) {
+ if (internal_strcmp(value, "0") == 0 ||
+ internal_strcmp(value, "no") == 0 ||
+ internal_strcmp(value, "false") == 0) {
+ *b = false;
+ return true;
+ }
+ if (internal_strcmp(value, "1") == 0 ||
+ internal_strcmp(value, "yes") == 0 ||
+ internal_strcmp(value, "true") == 0) {
+ *b = true;
+ return true;
+ }
+ return false;
+}
+
+template <>
+inline bool FlagHandler<bool>::Parse(const char *value) {
+ if (ParseBool(value, t_)) return true;
+ Printf("ERROR: Invalid value for bool option: '%s'\n", value);
+ return false;
+}
+
+template <>
+inline bool FlagHandler<bool>::Format(char *buffer, uptr size) {
+ return FormatString(buffer, size, *t_ ? "true" : "false");
+}
+
+template <>
+inline bool FlagHandler<HandleSignalMode>::Parse(const char *value) {
+ bool b;
+ if (ParseBool(value, &b)) {
+ *t_ = b ? kHandleSignalYes : kHandleSignalNo;
+ return true;
+ }
+ if (internal_strcmp(value, "2") == 0 ||
+ internal_strcmp(value, "exclusive") == 0) {
+ *t_ = kHandleSignalExclusive;
+ return true;
+ }
+ Printf("ERROR: Invalid value for signal handler option: '%s'\n", value);
+ return false;
+}
+
+template <>
+inline bool FlagHandler<HandleSignalMode>::Format(char *buffer, uptr size) {
+ uptr num_symbols_should_write = internal_snprintf(buffer, size, "%d", *t_);
+ return num_symbols_should_write < size;
+}
+
+template <>
+inline bool FlagHandler<const char *>::Parse(const char *value) {
+ *t_ = value;
+ return true;
+}
+
+template <>
+inline bool FlagHandler<const char *>::Format(char *buffer, uptr size) {
+ return FormatString(buffer, size, *t_);
+}
+
+template <>
+inline bool FlagHandler<int>::Parse(const char *value) {
+ const char *value_end;
+ *t_ = internal_simple_strtoll(value, &value_end, 10);
+ bool ok = *value_end == 0;
+ if (!ok) Printf("ERROR: Invalid value for int option: '%s'\n", value);
+ return ok;
+}
+
+template <>
+inline bool FlagHandler<int>::Format(char *buffer, uptr size) {
+ uptr num_symbols_should_write = internal_snprintf(buffer, size, "%d", *t_);
+ return num_symbols_should_write < size;
+}
+
+template <>
+inline bool FlagHandler<uptr>::Parse(const char *value) {
+ const char *value_end;
+ *t_ = internal_simple_strtoll(value, &value_end, 10);
+ bool ok = *value_end == 0;
+ if (!ok) Printf("ERROR: Invalid value for uptr option: '%s'\n", value);
+ return ok;
+}
+
+template <>
+inline bool FlagHandler<uptr>::Format(char *buffer, uptr size) {
+ uptr num_symbols_should_write = internal_snprintf(buffer, size, "0x%zx", *t_);
+ return num_symbols_should_write < size;
+}
+
+template <>
+inline bool FlagHandler<s64>::Parse(const char *value) {
+ const char *value_end;
+ *t_ = internal_simple_strtoll(value, &value_end, 10);
+ bool ok = *value_end == 0;
+ if (!ok) Printf("ERROR: Invalid value for s64 option: '%s'\n", value);
+ return ok;
+}
+
+template <>
+inline bool FlagHandler<s64>::Format(char *buffer, uptr size) {
+ uptr num_symbols_should_write = internal_snprintf(buffer, size, "%lld", *t_);
+ return num_symbols_should_write < size;
+}
+
+class FlagParser {
+ static const int kMaxFlags = 200;
+ struct Flag {
+ const char *name;
+ const char *desc;
+ FlagHandlerBase *handler;
+ } *flags_;
+ int n_flags_;
+
+ const char *buf_;
+ uptr pos_;
+
+ public:
+ FlagParser();
+ void RegisterHandler(const char *name, FlagHandlerBase *handler,
+ const char *desc);
+ void ParseString(const char *s, const char *env_name = 0);
+ void ParseStringFromEnv(const char *env_name);
+ bool ParseFile(const char *path, bool ignore_missing);
+ void PrintFlagDescriptions();
+
+ static LowLevelAllocator Alloc;
+
+ private:
+ void fatal_error(const char *err);
+ bool is_space(char c);
+ void skip_whitespace();
+ void parse_flags(const char *env_option_name);
+ void parse_flag(const char *env_option_name);
+ bool run_handler(const char *name, const char *value);
+ char *ll_strndup(const char *s, uptr n);
+};
+
+template <typename T>
+static void RegisterFlag(FlagParser *parser, const char *name, const char *desc,
+ T *var) {
+ FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var);
+ parser->RegisterHandler(name, fh, desc);
+}
+
+void ReportUnrecognizedFlags();
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_FLAG_REGISTRY_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flags.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flags.cpp
new file mode 100644
index 00000000000..d52e96a7c38
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flags.cpp
@@ -0,0 +1,139 @@
+//===-- sanitizer_flags.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_flags.h"
+
+#include "sanitizer_common.h"
+#include "sanitizer_flag_parser.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_list.h"
+
+namespace __sanitizer {
+
+CommonFlags common_flags_dont_use;
+
+void CommonFlags::SetDefaults() {
+#define COMMON_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "sanitizer_flags.inc"
+#undef COMMON_FLAG
+}
+
+void CommonFlags::CopyFrom(const CommonFlags &other) {
+ internal_memcpy(this, &other, sizeof(*this));
+}
+
+// Copy the string from "s" to "out", making the following substitutions:
+// %b = binary basename
+// %p = pid
+// %d = binary directory
+void SubstituteForFlagValue(const char *s, char *out, uptr out_size) {
+ char *out_end = out + out_size;
+ while (*s && out < out_end - 1) {
+ if (s[0] != '%') {
+ *out++ = *s++;
+ continue;
+ }
+ switch (s[1]) {
+ case 'b': {
+ const char *base = GetProcessName();
+ CHECK(base);
+ while (*base && out < out_end - 1)
+ *out++ = *base++;
+ s += 2; // skip "%b"
+ break;
+ }
+ case 'p': {
+ int pid = internal_getpid();
+ char buf[32];
+ char *buf_pos = buf + 32;
+ do {
+ *--buf_pos = (pid % 10) + '0';
+ pid /= 10;
+ } while (pid);
+ while (buf_pos < buf + 32 && out < out_end - 1)
+ *out++ = *buf_pos++;
+ s += 2; // skip "%p"
+ break;
+ }
+ case 'd': {
+ uptr len = ReadBinaryDir(out, out_end - out);
+ out += len;
+ s += 2; // skip "%d"
+ break;
+ }
+ default:
+ *out++ = *s++;
+ break;
+ }
+ }
+ CHECK(out < out_end - 1);
+ *out = '\0';
+}
+
+class FlagHandlerInclude final : public FlagHandlerBase {
+ FlagParser *parser_;
+ bool ignore_missing_;
+ const char *original_path_;
+
+ public:
+ explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing)
+ : parser_(parser), ignore_missing_(ignore_missing), original_path_("") {}
+ bool Parse(const char *value) final {
+ original_path_ = value;
+ if (internal_strchr(value, '%')) {
+ char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude");
+ SubstituteForFlagValue(value, buf, kMaxPathLength);
+ bool res = parser_->ParseFile(buf, ignore_missing_);
+ UnmapOrDie(buf, kMaxPathLength);
+ return res;
+ }
+ return parser_->ParseFile(value, ignore_missing_);
+ }
+ bool Format(char *buffer, uptr size) override {
+ // Note `original_path_` isn't actually what's parsed due to `%`
+ // substitutions. Printing the substituted path would require holding onto
+ // mmap'ed memory.
+ return FormatString(buffer, size, original_path_);
+ }
+};
+
+void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) {
+ FlagHandlerInclude *fh_include = new (FlagParser::Alloc)
+ FlagHandlerInclude(parser, /*ignore_missing*/ false);
+ parser->RegisterHandler("include", fh_include,
+ "read more options from the given file");
+ FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc)
+ FlagHandlerInclude(parser, /*ignore_missing*/ true);
+ parser->RegisterHandler(
+ "include_if_exists", fh_include_if_exists,
+ "read more options from the given file (if it exists)");
+}
+
+void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) {
+#define COMMON_FLAG(Type, Name, DefaultValue, Description) \
+ RegisterFlag(parser, #Name, Description, &cf->Name);
+#include "sanitizer_flags.inc"
+#undef COMMON_FLAG
+
+ RegisterIncludeFlags(parser, cf);
+}
+
+void InitializeCommonFlags(CommonFlags *cf) {
+ // need to record coverage to generate coverage report.
+ cf->coverage |= cf->html_cov_report;
+ SetVerbosity(cf->verbosity);
+
+ InitializePlatformCommonFlags(cf);
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flags.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flags.h
new file mode 100644
index 00000000000..5b59e5801bf
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flags.h
@@ -0,0 +1,71 @@
+//===-- sanitizer_flags.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_FLAGS_H
+#define SANITIZER_FLAGS_H
+
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+enum HandleSignalMode {
+ kHandleSignalNo,
+ kHandleSignalYes,
+ kHandleSignalExclusive,
+};
+
+struct CommonFlags {
+#define COMMON_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "sanitizer_flags.inc"
+#undef COMMON_FLAG
+
+ void SetDefaults();
+ void CopyFrom(const CommonFlags &other);
+};
+
+// Functions to get/set global CommonFlags shared by all sanitizer runtimes:
+extern CommonFlags common_flags_dont_use;
+inline const CommonFlags *common_flags() {
+ return &common_flags_dont_use;
+}
+
+inline void SetCommonFlagsDefaults() {
+ common_flags_dont_use.SetDefaults();
+}
+
+// This function can only be used to setup tool-specific overrides for
+// CommonFlags defaults. Generally, it should only be used right after
+// SetCommonFlagsDefaults(), but before ParseCommonFlagsFromString(), and
+// only during the flags initialization (i.e. before they are used for
+// the first time).
+inline void OverrideCommonFlags(const CommonFlags &cf) {
+ common_flags_dont_use.CopyFrom(cf);
+}
+
+void SubstituteForFlagValue(const char *s, char *out, uptr out_size);
+
+class FlagParser;
+void RegisterCommonFlags(FlagParser *parser,
+ CommonFlags *cf = &common_flags_dont_use);
+void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf);
+
+// Should be called after parsing all flags. Sets up common flag values
+// and perform initializations common to all sanitizers (e.g. setting
+// verbosity).
+void InitializeCommonFlags(CommonFlags *cf = &common_flags_dont_use);
+
+// Platform specific flags initialization.
+void InitializePlatformCommonFlags(CommonFlags *cf);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_FLAGS_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flags.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flags.inc
new file mode 100644
index 00000000000..6148ae56067
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flags.inc
@@ -0,0 +1,271 @@
+//===-- sanitizer_flags.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes common flags available in all sanitizers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef COMMON_FLAG
+#error "Define COMMON_FLAG prior to including this file!"
+#endif
+
+// COMMON_FLAG(Type, Name, DefaultValue, Description)
+// Supported types: bool, const char *, int, uptr.
+// Default value must be a compile-time constant.
+// Description must be a string literal.
+
+COMMON_FLAG(
+ bool, symbolize, true,
+ "If set, use the online symbolizer from common sanitizer runtime to turn "
+ "virtual addresses to file/line locations.")
+COMMON_FLAG(
+ const char *, external_symbolizer_path, nullptr,
+ "Path to external symbolizer. If empty, the tool will search $PATH for "
+ "the symbolizer.")
+COMMON_FLAG(
+ bool, allow_addr2line, false,
+ "If set, allows online symbolizer to run addr2line binary to symbolize "
+ "stack traces (addr2line will only be used if llvm-symbolizer binary is "
+ "unavailable.")
+COMMON_FLAG(const char *, strip_path_prefix, "",
+ "Strips this prefix from file paths in error reports.")
+COMMON_FLAG(bool, fast_unwind_on_check, false,
+ "If available, use the fast frame-pointer-based unwinder on "
+ "internal CHECK failures.")
+COMMON_FLAG(bool, fast_unwind_on_fatal, false,
+ "If available, use the fast frame-pointer-based unwinder on fatal "
+ "errors.")
+// ARM thumb/thumb2 frame pointer is inconsistent on GCC and Clang [1]
+// and fast-unwider is also unreliable with mixing arm and thumb code [2].
+// [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92172
+// [2] https://bugs.llvm.org/show_bug.cgi?id=44158
+COMMON_FLAG(bool, fast_unwind_on_malloc,
+ !(SANITIZER_LINUX && !SANITIZER_ANDROID && SANITIZER_ARM),
+ "If available, use the fast frame-pointer-based unwinder on "
+ "malloc/free.")
+COMMON_FLAG(bool, handle_ioctl, false, "Intercept and handle ioctl requests.")
+COMMON_FLAG(int, malloc_context_size, 1,
+ "Max number of stack frames kept for each allocation/deallocation.")
+COMMON_FLAG(
+ const char *, log_path, nullptr,
+ "Write logs to \"log_path.pid\". The special values are \"stdout\" and "
+ "\"stderr\". If unspecified, defaults to \"stderr\".")
+COMMON_FLAG(
+ bool, log_exe_name, false,
+ "Mention name of executable when reporting error and "
+ "append executable name to logs (as in \"log_path.exe_name.pid\").")
+COMMON_FLAG(const char *, log_suffix, nullptr,
+ "String to append to log file name, e.g. \".txt\".")
+COMMON_FLAG(
+ bool, log_to_syslog, (bool)SANITIZER_ANDROID || (bool)SANITIZER_APPLE,
+ "Write all sanitizer output to syslog in addition to other means of "
+ "logging.")
+COMMON_FLAG(
+ int, verbosity, 0,
+ "Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).")
+COMMON_FLAG(bool, strip_env, true,
+ "Whether to remove the sanitizer from DYLD_INSERT_LIBRARIES to "
+ "avoid passing it to children on Apple platforms. Default is true.")
+COMMON_FLAG(bool, verify_interceptors, true,
+ "Verify that interceptors are working on Apple platforms. Default "
+ "is true.")
+COMMON_FLAG(bool, detect_leaks, !SANITIZER_APPLE, "Enable memory leak detection.")
+COMMON_FLAG(
+ bool, leak_check_at_exit, true,
+ "Invoke leak checking in an atexit handler. Has no effect if "
+ "detect_leaks=false, or if __lsan_do_leak_check() is called before the "
+ "handler has a chance to run.")
+COMMON_FLAG(bool, allocator_may_return_null, false,
+ "If false, the allocator will crash instead of returning 0 on "
+ "out-of-memory.")
+COMMON_FLAG(bool, print_summary, true,
+ "If false, disable printing error summaries in addition to error "
+ "reports.")
+COMMON_FLAG(int, print_module_map, 0,
+ "Print the process module map where supported (0 - don't print, "
+ "1 - print only once before process exits, 2 - print after each "
+ "report).")
+COMMON_FLAG(bool, check_printf, true, "Check printf arguments.")
+#define COMMON_FLAG_HANDLE_SIGNAL_HELP(signal) \
+ "Controls custom tool's " #signal " handler (0 - do not registers the " \
+ "handler, 1 - register the handler and allow user to set own, " \
+ "2 - registers the handler and block user from changing it). "
+COMMON_FLAG(HandleSignalMode, handle_segv, kHandleSignalYes,
+ COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGSEGV))
+COMMON_FLAG(HandleSignalMode, handle_sigbus, kHandleSignalYes,
+ COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGBUS))
+COMMON_FLAG(HandleSignalMode, handle_abort, kHandleSignalNo,
+ COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGABRT))
+COMMON_FLAG(HandleSignalMode, handle_sigill, kHandleSignalNo,
+ COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGILL))
+COMMON_FLAG(HandleSignalMode, handle_sigtrap, kHandleSignalNo,
+ COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGTRAP))
+COMMON_FLAG(HandleSignalMode, handle_sigfpe, kHandleSignalYes,
+ COMMON_FLAG_HANDLE_SIGNAL_HELP(SIGFPE))
+#undef COMMON_FLAG_HANDLE_SIGNAL_HELP
+COMMON_FLAG(bool, allow_user_segv_handler, true,
+ "Deprecated. True has no effect, use handle_sigbus=1. If false, "
+ "handle_*=1 will be upgraded to handle_*=2.")
+COMMON_FLAG(bool, use_sigaltstack, true,
+ "If set, uses alternate stack for signal handling.")
+COMMON_FLAG(bool, detect_deadlocks, true,
+ "If set, deadlock detection is enabled.")
+COMMON_FLAG(
+ uptr, clear_shadow_mmap_threshold, 64 * 1024,
+ "Large shadow regions are zero-filled using mmap(NORESERVE) instead of "
+ "memset(). This is the threshold size in bytes.")
+COMMON_FLAG(const char *, color, "auto",
+ "Colorize reports: (always|never|auto).")
+COMMON_FLAG(
+ bool, legacy_pthread_cond, false,
+ "Enables support for dynamic libraries linked with libpthread 2.2.5.")
+COMMON_FLAG(bool, intercept_tls_get_addr, false, "Intercept __tls_get_addr.")
+COMMON_FLAG(bool, help, false, "Print the flag descriptions.")
+COMMON_FLAG(uptr, mmap_limit_mb, 0,
+ "Limit the amount of mmap-ed memory (excluding shadow) in Mb; "
+ "not a user-facing flag, used mosly for testing the tools")
+COMMON_FLAG(uptr, hard_rss_limit_mb, 0,
+ "Hard RSS limit in Mb."
+ " If non-zero, a background thread is spawned at startup"
+ " which periodically reads RSS and aborts the process if the"
+ " limit is reached")
+COMMON_FLAG(uptr, soft_rss_limit_mb, 0,
+ "Soft RSS limit in Mb."
+ " If non-zero, a background thread is spawned at startup"
+ " which periodically reads RSS. If the limit is reached"
+ " all subsequent malloc/new calls will fail or return NULL"
+ " (depending on the value of allocator_may_return_null)"
+ " until the RSS goes below the soft limit."
+ " This limit does not affect memory allocations other than"
+ " malloc/new.")
+COMMON_FLAG(uptr, max_allocation_size_mb, 0,
+ "If non-zero, malloc/new calls larger than this size will return "
+ "nullptr (or crash if allocator_may_return_null=false).")
+COMMON_FLAG(bool, heap_profile, false, "Experimental heap profiler, asan-only")
+COMMON_FLAG(s32, allocator_release_to_os_interval_ms,
+ ((bool)SANITIZER_FUCHSIA || (bool)SANITIZER_WINDOWS) ? -1 : 5000,
+ "Only affects a 64-bit allocator. If set, tries to release unused "
+ "memory to the OS, but not more often than this interval (in "
+ "milliseconds). Negative values mean do not attempt to release "
+ "memory to the OS.\n")
+COMMON_FLAG(bool, can_use_proc_maps_statm, true,
+ "If false, do not attempt to read /proc/maps/statm."
+ " Mostly useful for testing sanitizers.")
+COMMON_FLAG(
+ bool, coverage, false,
+ "If set, coverage information will be dumped at program shutdown (if the "
+ "coverage instrumentation was enabled at compile time).")
+COMMON_FLAG(const char *, coverage_dir, ".",
+ "Target directory for coverage dumps. Defaults to the current "
+ "directory.")
+COMMON_FLAG(const char *, cov_8bit_counters_out, "",
+ "If non-empty, write 8bit counters to this file. ")
+COMMON_FLAG(const char *, cov_pcs_out, "",
+ "If non-empty, write the coverage pc table to this file. ")
+COMMON_FLAG(bool, full_address_space, false,
+ "Sanitize complete address space; "
+ "by default kernel area on 32-bit platforms will not be sanitized")
+COMMON_FLAG(bool, print_suppressions, true,
+ "Print matched suppressions at exit.")
+COMMON_FLAG(
+ bool, disable_coredump, (SANITIZER_WORDSIZE == 64) && !SANITIZER_GO,
+ "Disable core dumping. By default, disable_coredump=1 on 64-bit to avoid"
+ " dumping a 16T+ core file. Ignored on OSes that don't dump core by"
+ " default and for sanitizers that don't reserve lots of virtual memory.")
+COMMON_FLAG(bool, use_madv_dontdump, true,
+ "If set, instructs kernel to not store the (huge) shadow "
+ "in core file.")
+COMMON_FLAG(bool, symbolize_inline_frames, true,
+ "Print inlined frames in stacktraces. Defaults to true.")
+COMMON_FLAG(bool, demangle, true, "Print demangled symbols.")
+COMMON_FLAG(bool, symbolize_vs_style, false,
+ "Print file locations in Visual Studio style (e.g: "
+ " file(10,42): ...")
+COMMON_FLAG(int, dedup_token_length, 0,
+ "If positive, after printing a stack trace also print a short "
+ "string token based on this number of frames that will simplify "
+ "deduplication of the reports. "
+ "Example: 'DEDUP_TOKEN: foo-bar-main'. Default is 0.")
+COMMON_FLAG(const char *, stack_trace_format, "DEFAULT",
+ "Format string used to render stack frames. "
+ "See sanitizer_stacktrace_printer.h for the format description. "
+ "Use DEFAULT to get default format.")
+COMMON_FLAG(int, compress_stack_depot, 0,
+ "Compress stack depot to save memory.")
+COMMON_FLAG(bool, no_huge_pages_for_shadow, true,
+ "If true, the shadow is not allowed to use huge pages. ")
+COMMON_FLAG(bool, strict_string_checks, false,
+ "If set check that string arguments are properly null-terminated")
+COMMON_FLAG(bool, intercept_strstr, true,
+ "If set, uses custom wrappers for strstr and strcasestr functions "
+ "to find more errors.")
+COMMON_FLAG(bool, intercept_strspn, true,
+ "If set, uses custom wrappers for strspn and strcspn function "
+ "to find more errors.")
+COMMON_FLAG(bool, intercept_strtok, true,
+ "If set, uses a custom wrapper for the strtok function "
+ "to find more errors.")
+COMMON_FLAG(bool, intercept_strpbrk, true,
+ "If set, uses custom wrappers for strpbrk function "
+ "to find more errors.")
+COMMON_FLAG(
+ bool, intercept_strcmp, true,
+ "If set, uses custom wrappers for strcmp functions to find more errors.")
+COMMON_FLAG(bool, intercept_strlen, true,
+ "If set, uses custom wrappers for strlen and strnlen functions "
+ "to find more errors.")
+COMMON_FLAG(bool, intercept_strndup, true,
+ "If set, uses custom wrappers for strndup functions "
+ "to find more errors.")
+COMMON_FLAG(bool, intercept_strchr, true,
+ "If set, uses custom wrappers for strchr, strchrnul, and strrchr "
+ "functions to find more errors.")
+COMMON_FLAG(bool, intercept_memcmp, true,
+ "If set, uses custom wrappers for memcmp function "
+ "to find more errors.")
+COMMON_FLAG(bool, strict_memcmp, true,
+ "If true, assume that memcmp(p1, p2, n) always reads n bytes before "
+ "comparing p1 and p2.")
+COMMON_FLAG(bool, intercept_memmem, true,
+ "If set, uses a wrapper for memmem() to find more errors.")
+COMMON_FLAG(bool, intercept_intrin, true,
+ "If set, uses custom wrappers for memset/memcpy/memmove "
+ "intrinsics to find more errors.")
+COMMON_FLAG(bool, intercept_stat, true,
+ "If set, uses custom wrappers for *stat functions "
+ "to find more errors.")
+COMMON_FLAG(bool, intercept_send, true,
+ "If set, uses custom wrappers for send* functions "
+ "to find more errors.")
+COMMON_FLAG(bool, decorate_proc_maps, (bool)SANITIZER_ANDROID,
+ "If set, decorate sanitizer mappings in /proc/self/maps with "
+ "user-readable names")
+COMMON_FLAG(int, exitcode, 1, "Override the program exit status if the tool "
+ "found an error")
+COMMON_FLAG(
+ bool, abort_on_error, (bool)SANITIZER_ANDROID || (bool)SANITIZER_APPLE,
+ "If set, the tool calls abort() instead of _exit() after printing the "
+ "error report.")
+COMMON_FLAG(bool, suppress_equal_pcs, true,
+ "Deduplicate multiple reports for single source location in "
+ "halt_on_error=false mode (asan only).")
+COMMON_FLAG(bool, print_cmdline, false, "Print command line on crash "
+ "(asan only).")
+COMMON_FLAG(bool, html_cov_report, false, "Generate html coverage report.")
+COMMON_FLAG(const char *, sancov_path, "sancov", "Sancov tool location.")
+COMMON_FLAG(bool, dump_instruction_bytes, false,
+ "If true, dump 16 bytes starting at the instruction that caused SEGV")
+COMMON_FLAG(bool, dump_registers, true,
+ "If true, dump values of CPU registers when SEGV happens. Only "
+ "available on OS X for now.")
+COMMON_FLAG(bool, detect_write_exec, false,
+ "If true, triggers warning when writable-executable pages requests "
+ "are being made")
+COMMON_FLAG(bool, test_only_emulate_no_memorymap, false,
+ "TEST ONLY fail to read memory mappings to emulate sanitized "
+ "\"init\"")
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flat_map.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flat_map.h
new file mode 100644
index 00000000000..05fb554d20c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_flat_map.h
@@ -0,0 +1,173 @@
+//===-- sanitizer_flat_map.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Part of the Sanitizer Allocator.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_FLAT_MAP_H
+#define SANITIZER_FLAT_MAP_H
+
+#include "sanitizer_atomic.h"
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_local_address_space_view.h"
+#include "sanitizer_mutex.h"
+
+namespace __sanitizer {
+
+// Call these callbacks on mmap/munmap.
+struct NoOpMapUnmapCallback {
+ void OnMap(uptr p, uptr size) const {}
+ void OnUnmap(uptr p, uptr size) const {}
+};
+
+// Maps integers in rage [0, kSize) to values.
+template <typename T, u64 kSize,
+ typename AddressSpaceViewTy = LocalAddressSpaceView>
+class FlatMap {
+ public:
+ using AddressSpaceView = AddressSpaceViewTy;
+ void Init() { internal_memset(map_, 0, sizeof(map_)); }
+
+ constexpr uptr size() const { return kSize; }
+
+ bool contains(uptr idx) const {
+ CHECK_LT(idx, kSize);
+ return true;
+ }
+
+ T &operator[](uptr idx) {
+ DCHECK_LT(idx, kSize);
+ return map_[idx];
+ }
+
+ const T &operator[](uptr idx) const {
+ DCHECK_LT(idx, kSize);
+ return map_[idx];
+ }
+
+ private:
+ T map_[kSize];
+};
+
+// TwoLevelMap maps integers in range [0, kSize1*kSize2) to values.
+// It is implemented as a two-dimensional array: array of kSize1 pointers
+// to kSize2-byte arrays. The secondary arrays are mmaped on demand.
+// Each value is initially zero and can be set to something else only once.
+// Setting and getting values from multiple threads is safe w/o extra locking.
+template <typename T, u64 kSize1, u64 kSize2,
+ typename AddressSpaceViewTy = LocalAddressSpaceView,
+ class MapUnmapCallback = NoOpMapUnmapCallback>
+class TwoLevelMap {
+ static_assert(IsPowerOfTwo(kSize2), "Use a power of two for performance.");
+
+ public:
+ using AddressSpaceView = AddressSpaceViewTy;
+ void Init() {
+ mu_.Init();
+ internal_memset(map1_, 0, sizeof(map1_));
+ }
+
+ void TestOnlyUnmap() {
+ for (uptr i = 0; i < kSize1; i++) {
+ T *p = Get(i);
+ if (!p)
+ continue;
+ MapUnmapCallback().OnUnmap(reinterpret_cast<uptr>(p), MmapSize());
+ UnmapOrDie(p, kSize2);
+ }
+ Init();
+ }
+
+ uptr MemoryUsage() const {
+ uptr res = 0;
+ for (uptr i = 0; i < kSize1; i++) {
+ T *p = Get(i);
+ if (!p)
+ continue;
+ res += MmapSize();
+ }
+ return res;
+ }
+
+ constexpr uptr size() const { return kSize1 * kSize2; }
+ constexpr uptr size1() const { return kSize1; }
+ constexpr uptr size2() const { return kSize2; }
+
+ bool contains(uptr idx) const {
+ CHECK_LT(idx, kSize1 * kSize2);
+ return Get(idx / kSize2);
+ }
+
+ const T &operator[](uptr idx) const {
+ DCHECK_LT(idx, kSize1 * kSize2);
+ T *map2 = GetOrCreate(idx / kSize2);
+ return *AddressSpaceView::Load(&map2[idx % kSize2]);
+ }
+
+ T &operator[](uptr idx) {
+ DCHECK_LT(idx, kSize1 * kSize2);
+ T *map2 = GetOrCreate(idx / kSize2);
+ return *AddressSpaceView::LoadWritable(&map2[idx % kSize2]);
+ }
+
+ private:
+ constexpr uptr MmapSize() const {
+ return RoundUpTo(kSize2 * sizeof(T), GetPageSizeCached());
+ }
+
+ T *Get(uptr idx) const {
+ DCHECK_LT(idx, kSize1);
+ return reinterpret_cast<T *>(
+ atomic_load(&map1_[idx], memory_order_acquire));
+ }
+
+ T *GetOrCreate(uptr idx) const {
+ DCHECK_LT(idx, kSize1);
+ // This code needs to use memory_order_acquire/consume, but we use
+ // memory_order_relaxed for performance reasons (matters for arm64). We
+ // expect memory_order_relaxed to be effectively equivalent to
+ // memory_order_consume in this case for all relevant architectures: all
+ // dependent data is reachable only by dereferencing the resulting pointer.
+ // If relaxed load fails to see stored ptr, the code will fall back to
+ // Create() and reload the value again with locked mutex as a memory
+ // barrier.
+ T *res = reinterpret_cast<T *>(atomic_load_relaxed(&map1_[idx]));
+ if (LIKELY(res))
+ return res;
+ return Create(idx);
+ }
+
+ NOINLINE T *Create(uptr idx) const {
+ SpinMutexLock l(&mu_);
+ T *res = Get(idx);
+ if (!res) {
+ res = reinterpret_cast<T *>(MmapOrDie(MmapSize(), "TwoLevelMap"));
+ MapUnmapCallback().OnMap(reinterpret_cast<uptr>(res), kSize2);
+ atomic_store(&map1_[idx], reinterpret_cast<uptr>(res),
+ memory_order_release);
+ }
+ return res;
+ }
+
+ mutable StaticSpinMutex mu_;
+ mutable atomic_uintptr_t map1_[kSize1];
+};
+
+template <u64 kSize, typename AddressSpaceViewTy = LocalAddressSpaceView>
+using FlatByteMap = FlatMap<u8, kSize, AddressSpaceViewTy>;
+
+template <u64 kSize1, u64 kSize2,
+ typename AddressSpaceViewTy = LocalAddressSpaceView,
+ class MapUnmapCallback = NoOpMapUnmapCallback>
+using TwoLevelByteMap =
+ TwoLevelMap<u8, kSize1, kSize2, AddressSpaceViewTy, MapUnmapCallback>;
+} // namespace __sanitizer
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_freebsd.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_freebsd.h
new file mode 100644
index 00000000000..82b227eab6d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_freebsd.h
@@ -0,0 +1,137 @@
+//===-- sanitizer_freebsd.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer runtime. It contains FreeBSD-specific
+// definitions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_FREEBSD_H
+#define SANITIZER_FREEBSD_H
+
+#include "sanitizer_internal_defs.h"
+
+// x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in
+// 32-bit mode.
+#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
+#include <osreldate.h>
+#if __FreeBSD_version <= 902001 // v9.2
+#include <link.h>
+#include <sys/param.h>
+#include <ucontext.h>
+
+namespace __sanitizer {
+
+typedef unsigned long long __xuint64_t;
+
+typedef __int32_t __xregister_t;
+
+typedef struct __xmcontext {
+ __xregister_t mc_onstack;
+ __xregister_t mc_gs;
+ __xregister_t mc_fs;
+ __xregister_t mc_es;
+ __xregister_t mc_ds;
+ __xregister_t mc_edi;
+ __xregister_t mc_esi;
+ __xregister_t mc_ebp;
+ __xregister_t mc_isp;
+ __xregister_t mc_ebx;
+ __xregister_t mc_edx;
+ __xregister_t mc_ecx;
+ __xregister_t mc_eax;
+ __xregister_t mc_trapno;
+ __xregister_t mc_err;
+ __xregister_t mc_eip;
+ __xregister_t mc_cs;
+ __xregister_t mc_eflags;
+ __xregister_t mc_esp;
+ __xregister_t mc_ss;
+
+ int mc_len;
+ int mc_fpformat;
+ int mc_ownedfp;
+ __xregister_t mc_flags;
+
+ int mc_fpstate[128] __aligned(16);
+ __xregister_t mc_fsbase;
+ __xregister_t mc_gsbase;
+ __xregister_t mc_xfpustate;
+ __xregister_t mc_xfpustate_len;
+
+ int mc_spare2[4];
+} xmcontext_t;
+
+typedef struct __xucontext {
+ sigset_t uc_sigmask;
+ xmcontext_t uc_mcontext;
+
+ struct __ucontext *uc_link;
+ stack_t uc_stack;
+ int uc_flags;
+ int __spare__[4];
+} xucontext_t;
+
+struct xkinfo_vmentry {
+ int kve_structsize;
+ int kve_type;
+ __xuint64_t kve_start;
+ __xuint64_t kve_end;
+ __xuint64_t kve_offset;
+ __xuint64_t kve_vn_fileid;
+ __uint32_t kve_vn_fsid;
+ int kve_flags;
+ int kve_resident;
+ int kve_private_resident;
+ int kve_protection;
+ int kve_ref_count;
+ int kve_shadow_count;
+ int kve_vn_type;
+ __xuint64_t kve_vn_size;
+ __uint32_t kve_vn_rdev;
+ __uint16_t kve_vn_mode;
+ __uint16_t kve_status;
+ int _kve_ispare[12];
+ char kve_path[PATH_MAX];
+};
+
+typedef struct {
+ __uint32_t p_type;
+ __uint32_t p_offset;
+ __uint32_t p_vaddr;
+ __uint32_t p_paddr;
+ __uint32_t p_filesz;
+ __uint32_t p_memsz;
+ __uint32_t p_flags;
+ __uint32_t p_align;
+} XElf32_Phdr;
+
+struct xdl_phdr_info {
+ Elf_Addr dlpi_addr;
+ const char *dlpi_name;
+ const XElf32_Phdr *dlpi_phdr;
+ Elf_Half dlpi_phnum;
+ unsigned long long int dlpi_adds;
+ unsigned long long int dlpi_subs;
+ size_t dlpi_tls_modid;
+ void *dlpi_tls_data;
+};
+
+typedef int (*__xdl_iterate_hdr_callback)(struct xdl_phdr_info *, size_t,
+ void *);
+typedef int xdl_iterate_phdr_t(__xdl_iterate_hdr_callback, void *);
+
+#define xdl_iterate_phdr(callback, param) \
+ (((xdl_iterate_phdr_t *)dl_iterate_phdr)((callback), (param)))
+
+} // namespace __sanitizer
+
+#endif // __FreeBSD_version <= 902001
+#endif // SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
+
+#endif // SANITIZER_FREEBSD_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
new file mode 100644
index 00000000000..3ccc4671cb2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
@@ -0,0 +1,501 @@
+//===-- sanitizer_fuchsia.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and other sanitizer
+// run-time libraries and implements Fuchsia-specific functions from
+// sanitizer_common.h.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_fuchsia.h"
+#if SANITIZER_FUCHSIA
+
+# include <pthread.h>
+# include <stdlib.h>
+# include <unistd.h>
+# error #include <zircon/errors.h>
+# error #include <zircon/process.h>
+# error #include <zircon/syscalls.h>
+# error #include <zircon/utc.h>
+
+# include "sanitizer_common.h"
+# include "sanitizer_interface_internal.h"
+# include "sanitizer_libc.h"
+# include "sanitizer_mutex.h"
+
+namespace __sanitizer {
+
+void NORETURN internal__exit(int exitcode) { _zx_process_exit(exitcode); }
+
+uptr internal_sched_yield() {
+ zx_status_t status = _zx_thread_legacy_yield(0u);
+ CHECK_EQ(status, ZX_OK);
+ return 0; // Why doesn't this return void?
+}
+
+void internal_usleep(u64 useconds) {
+ zx_status_t status = _zx_nanosleep(_zx_deadline_after(ZX_USEC(useconds)));
+ CHECK_EQ(status, ZX_OK);
+}
+
+u64 NanoTime() {
+ zx_handle_t utc_clock = _zx_utc_reference_get();
+ CHECK_NE(utc_clock, ZX_HANDLE_INVALID);
+ zx_time_t time;
+ zx_status_t status = _zx_clock_read(utc_clock, &time);
+ CHECK_EQ(status, ZX_OK);
+ return time;
+}
+
+u64 MonotonicNanoTime() { return _zx_clock_get_monotonic(); }
+
+uptr internal_getpid() {
+ zx_info_handle_basic_t info;
+ zx_status_t status =
+ _zx_object_get_info(_zx_process_self(), ZX_INFO_HANDLE_BASIC, &info,
+ sizeof(info), NULL, NULL);
+ CHECK_EQ(status, ZX_OK);
+ uptr pid = static_cast<uptr>(info.koid);
+ CHECK_EQ(pid, info.koid);
+ return pid;
+}
+
+int internal_dlinfo(void *handle, int request, void *p) { UNIMPLEMENTED(); }
+
+uptr GetThreadSelf() { return reinterpret_cast<uptr>(thrd_current()); }
+
+tid_t GetTid() { return GetThreadSelf(); }
+
+void Abort() { abort(); }
+
+int Atexit(void (*function)(void)) { return atexit(function); }
+
+void GetThreadStackTopAndBottom(bool, uptr *stack_top, uptr *stack_bottom) {
+ pthread_attr_t attr;
+ CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
+ void *base;
+ size_t size;
+ CHECK_EQ(pthread_attr_getstack(&attr, &base, &size), 0);
+ CHECK_EQ(pthread_attr_destroy(&attr), 0);
+
+ *stack_bottom = reinterpret_cast<uptr>(base);
+ *stack_top = *stack_bottom + size;
+}
+
+void InitializePlatformEarly() {}
+void CheckASLR() {}
+void CheckMPROTECT() {}
+void PlatformPrepareForSandboxing(void *args) {}
+void DisableCoreDumperIfNecessary() {}
+void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
+void SetAlternateSignalStack() {}
+void UnsetAlternateSignalStack() {}
+void InitTlsSize() {}
+
+bool SignalContext::IsStackOverflow() const { return false; }
+void SignalContext::DumpAllRegisters(void *context) { UNIMPLEMENTED(); }
+const char *SignalContext::Describe() const { UNIMPLEMENTED(); }
+
+void FutexWait(atomic_uint32_t *p, u32 cmp) {
+ zx_status_t status = _zx_futex_wait(reinterpret_cast<zx_futex_t *>(p), cmp,
+ ZX_HANDLE_INVALID, ZX_TIME_INFINITE);
+ if (status != ZX_ERR_BAD_STATE) // Normal race.
+ CHECK_EQ(status, ZX_OK);
+}
+
+void FutexWake(atomic_uint32_t *p, u32 count) {
+ zx_status_t status = _zx_futex_wake(reinterpret_cast<zx_futex_t *>(p), count);
+ CHECK_EQ(status, ZX_OK);
+}
+
+uptr GetPageSize() { return _zx_system_get_page_size(); }
+
+uptr GetMmapGranularity() { return _zx_system_get_page_size(); }
+
+sanitizer_shadow_bounds_t ShadowBounds;
+
+void InitShadowBounds() { ShadowBounds = __sanitizer_shadow_bounds(); }
+
+uptr GetMaxUserVirtualAddress() {
+ InitShadowBounds();
+ return ShadowBounds.memory_limit - 1;
+}
+
+uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); }
+
+bool ErrorIsOOM(error_t err) { return err == ZX_ERR_NO_MEMORY; }
+
+static void *DoAnonymousMmapOrDie(uptr size, const char *mem_type,
+ bool raw_report, bool die_for_nomem) {
+ size = RoundUpTo(size, GetPageSize());
+
+ zx_handle_t vmo;
+ zx_status_t status = _zx_vmo_create(size, 0, &vmo);
+ if (status != ZX_OK) {
+ if (status != ZX_ERR_NO_MEMORY || die_for_nomem)
+ ReportMmapFailureAndDie(size, mem_type, "zx_vmo_create", status,
+ raw_report);
+ return nullptr;
+ }
+ _zx_object_set_property(vmo, ZX_PROP_NAME, mem_type,
+ internal_strlen(mem_type));
+
+ // TODO(mcgrathr): Maybe allocate a VMAR for all sanitizer heap and use that?
+ uintptr_t addr;
+ status =
+ _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0,
+ vmo, 0, size, &addr);
+ _zx_handle_close(vmo);
+
+ if (status != ZX_OK) {
+ if (status != ZX_ERR_NO_MEMORY || die_for_nomem)
+ ReportMmapFailureAndDie(size, mem_type, "zx_vmar_map", status,
+ raw_report);
+ return nullptr;
+ }
+
+ IncreaseTotalMmap(size);
+
+ return reinterpret_cast<void *>(addr);
+}
+
+void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
+ return DoAnonymousMmapOrDie(size, mem_type, raw_report, true);
+}
+
+void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
+ return MmapOrDie(size, mem_type);
+}
+
+void *MmapOrDieOnFatalError(uptr size, const char *mem_type) {
+ return DoAnonymousMmapOrDie(size, mem_type, false, false);
+}
+
+uptr ReservedAddressRange::Init(uptr init_size, const char *name,
+ uptr fixed_addr) {
+ init_size = RoundUpTo(init_size, GetPageSize());
+ DCHECK_EQ(os_handle_, ZX_HANDLE_INVALID);
+ uintptr_t base;
+ zx_handle_t vmar;
+ zx_status_t status = _zx_vmar_allocate(
+ _zx_vmar_root_self(),
+ ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE | ZX_VM_CAN_MAP_SPECIFIC, 0,
+ init_size, &vmar, &base);
+ if (status != ZX_OK)
+ ReportMmapFailureAndDie(init_size, name, "zx_vmar_allocate", status);
+ base_ = reinterpret_cast<void *>(base);
+ size_ = init_size;
+ name_ = name;
+ os_handle_ = vmar;
+
+ return reinterpret_cast<uptr>(base_);
+}
+
+static uptr DoMmapFixedOrDie(zx_handle_t vmar, uptr fixed_addr, uptr map_size,
+ void *base, const char *name, bool die_for_nomem) {
+ uptr offset = fixed_addr - reinterpret_cast<uptr>(base);
+ map_size = RoundUpTo(map_size, GetPageSize());
+ zx_handle_t vmo;
+ zx_status_t status = _zx_vmo_create(map_size, 0, &vmo);
+ if (status != ZX_OK) {
+ if (status != ZX_ERR_NO_MEMORY || die_for_nomem)
+ ReportMmapFailureAndDie(map_size, name, "zx_vmo_create", status);
+ return 0;
+ }
+ _zx_object_set_property(vmo, ZX_PROP_NAME, name, internal_strlen(name));
+ DCHECK_GE(base + size_, map_size + offset);
+ uintptr_t addr;
+
+ status =
+ _zx_vmar_map(vmar, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_SPECIFIC,
+ offset, vmo, 0, map_size, &addr);
+ _zx_handle_close(vmo);
+ if (status != ZX_OK) {
+ if (status != ZX_ERR_NO_MEMORY || die_for_nomem) {
+ ReportMmapFailureAndDie(map_size, name, "zx_vmar_map", status);
+ }
+ return 0;
+ }
+ IncreaseTotalMmap(map_size);
+ return addr;
+}
+
+uptr ReservedAddressRange::Map(uptr fixed_addr, uptr map_size,
+ const char *name) {
+ return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_, name_,
+ false);
+}
+
+uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr map_size,
+ const char *name) {
+ return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_, name_, true);
+}
+
+void UnmapOrDieVmar(void *addr, uptr size, zx_handle_t target_vmar) {
+ if (!addr || !size)
+ return;
+ size = RoundUpTo(size, GetPageSize());
+
+ zx_status_t status =
+ _zx_vmar_unmap(target_vmar, reinterpret_cast<uintptr_t>(addr), size);
+ if (status != ZX_OK) {
+ Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n",
+ SanitizerToolName, size, size, addr);
+ CHECK("unable to unmap" && 0);
+ }
+
+ DecreaseTotalMmap(size);
+}
+
+void ReservedAddressRange::Unmap(uptr addr, uptr size) {
+ CHECK_LE(size, size_);
+ const zx_handle_t vmar = static_cast<zx_handle_t>(os_handle_);
+ if (addr == reinterpret_cast<uptr>(base_)) {
+ if (size == size_) {
+ // Destroying the vmar effectively unmaps the whole mapping.
+ _zx_vmar_destroy(vmar);
+ _zx_handle_close(vmar);
+ os_handle_ = static_cast<uptr>(ZX_HANDLE_INVALID);
+ DecreaseTotalMmap(size);
+ return;
+ }
+ } else {
+ CHECK_EQ(addr + size, reinterpret_cast<uptr>(base_) + size_);
+ }
+ // Partial unmapping does not affect the fact that the initial range is still
+ // reserved, and the resulting unmapped memory can't be reused.
+ UnmapOrDieVmar(reinterpret_cast<void *>(addr), size, vmar);
+}
+
+// This should never be called.
+void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) {
+ UNIMPLEMENTED();
+}
+
+bool MprotectNoAccess(uptr addr, uptr size) {
+ return _zx_vmar_protect(_zx_vmar_root_self(), 0, addr, size) == ZX_OK;
+}
+
+bool MprotectReadOnly(uptr addr, uptr size) {
+ return _zx_vmar_protect(_zx_vmar_root_self(), ZX_VM_PERM_READ, addr, size) ==
+ ZX_OK;
+}
+
+void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
+ const char *mem_type) {
+ CHECK_GE(size, GetPageSize());
+ CHECK(IsPowerOfTwo(size));
+ CHECK(IsPowerOfTwo(alignment));
+
+ zx_handle_t vmo;
+ zx_status_t status = _zx_vmo_create(size, 0, &vmo);
+ if (status != ZX_OK) {
+ if (status != ZX_ERR_NO_MEMORY)
+ ReportMmapFailureAndDie(size, mem_type, "zx_vmo_create", status, false);
+ return nullptr;
+ }
+ _zx_object_set_property(vmo, ZX_PROP_NAME, mem_type,
+ internal_strlen(mem_type));
+
+ // TODO(mcgrathr): Maybe allocate a VMAR for all sanitizer heap and use that?
+
+ // Map a larger size to get a chunk of address space big enough that
+ // it surely contains an aligned region of the requested size. Then
+ // overwrite the aligned middle portion with a mapping from the
+ // beginning of the VMO, and unmap the excess before and after.
+ size_t map_size = size + alignment;
+ uintptr_t addr;
+ status =
+ _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0,
+ vmo, 0, map_size, &addr);
+ if (status == ZX_OK) {
+ uintptr_t map_addr = addr;
+ uintptr_t map_end = map_addr + map_size;
+ addr = RoundUpTo(map_addr, alignment);
+ uintptr_t end = addr + size;
+ if (addr != map_addr) {
+ zx_info_vmar_t info;
+ status = _zx_object_get_info(_zx_vmar_root_self(), ZX_INFO_VMAR, &info,
+ sizeof(info), NULL, NULL);
+ if (status == ZX_OK) {
+ uintptr_t new_addr;
+ status = _zx_vmar_map(
+ _zx_vmar_root_self(),
+ ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_SPECIFIC_OVERWRITE,
+ addr - info.base, vmo, 0, size, &new_addr);
+ if (status == ZX_OK)
+ CHECK_EQ(new_addr, addr);
+ }
+ }
+ if (status == ZX_OK && addr != map_addr)
+ status = _zx_vmar_unmap(_zx_vmar_root_self(), map_addr, addr - map_addr);
+ if (status == ZX_OK && end != map_end)
+ status = _zx_vmar_unmap(_zx_vmar_root_self(), end, map_end - end);
+ }
+ _zx_handle_close(vmo);
+
+ if (status != ZX_OK) {
+ if (status != ZX_ERR_NO_MEMORY)
+ ReportMmapFailureAndDie(size, mem_type, "zx_vmar_map", status, false);
+ return nullptr;
+ }
+
+ IncreaseTotalMmap(size);
+
+ return reinterpret_cast<void *>(addr);
+}
+
+void UnmapOrDie(void *addr, uptr size) {
+ UnmapOrDieVmar(addr, size, _zx_vmar_root_self());
+}
+
+void ReleaseMemoryPagesToOS(uptr beg, uptr end) {
+ uptr beg_aligned = RoundUpTo(beg, GetPageSize());
+ uptr end_aligned = RoundDownTo(end, GetPageSize());
+ if (beg_aligned < end_aligned) {
+ zx_handle_t root_vmar = _zx_vmar_root_self();
+ CHECK_NE(root_vmar, ZX_HANDLE_INVALID);
+ zx_status_t status =
+ _zx_vmar_op_range(root_vmar, ZX_VMAR_OP_DECOMMIT, beg_aligned,
+ end_aligned - beg_aligned, nullptr, 0);
+ CHECK_EQ(status, ZX_OK);
+ }
+}
+
+void DumpProcessMap() {
+ // TODO(mcgrathr): write it
+ return;
+}
+
+bool IsAccessibleMemoryRange(uptr beg, uptr size) {
+ // TODO(mcgrathr): Figure out a better way.
+ zx_handle_t vmo;
+ zx_status_t status = _zx_vmo_create(size, 0, &vmo);
+ if (status == ZX_OK) {
+ status = _zx_vmo_write(vmo, reinterpret_cast<const void *>(beg), 0, size);
+ _zx_handle_close(vmo);
+ }
+ return status == ZX_OK;
+}
+
+// FIXME implement on this platform.
+void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
+
+bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
+ uptr *read_len, uptr max_len, error_t *errno_p) {
+ *errno_p = ZX_ERR_NOT_SUPPORTED;
+ return false;
+}
+
+void RawWrite(const char *buffer) {
+ constexpr size_t size = 128;
+ static _Thread_local char line[size];
+ static _Thread_local size_t lastLineEnd = 0;
+ static _Thread_local size_t cur = 0;
+
+ while (*buffer) {
+ if (cur >= size) {
+ if (lastLineEnd == 0)
+ lastLineEnd = size;
+ __sanitizer_log_write(line, lastLineEnd);
+ internal_memmove(line, line + lastLineEnd, cur - lastLineEnd);
+ cur = cur - lastLineEnd;
+ lastLineEnd = 0;
+ }
+ if (*buffer == '\n')
+ lastLineEnd = cur + 1;
+ line[cur++] = *buffer++;
+ }
+ // Flush all complete lines before returning.
+ if (lastLineEnd != 0) {
+ __sanitizer_log_write(line, lastLineEnd);
+ internal_memmove(line, line + lastLineEnd, cur - lastLineEnd);
+ cur = cur - lastLineEnd;
+ lastLineEnd = 0;
+ }
+}
+
+void CatastrophicErrorWrite(const char *buffer, uptr length) {
+ __sanitizer_log_write(buffer, length);
+}
+
+char **StoredArgv;
+char **StoredEnviron;
+
+char **GetArgv() { return StoredArgv; }
+char **GetEnviron() { return StoredEnviron; }
+
+const char *GetEnv(const char *name) {
+ if (StoredEnviron) {
+ uptr NameLen = internal_strlen(name);
+ for (char **Env = StoredEnviron; *Env != 0; Env++) {
+ if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=')
+ return (*Env) + NameLen + 1;
+ }
+ }
+ return nullptr;
+}
+
+uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) {
+ const char *argv0 = "<UNKNOWN>";
+ if (StoredArgv && StoredArgv[0]) {
+ argv0 = StoredArgv[0];
+ }
+ internal_strncpy(buf, argv0, buf_len);
+ return internal_strlen(buf);
+}
+
+uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
+ return ReadBinaryName(buf, buf_len);
+}
+
+uptr MainThreadStackBase, MainThreadStackSize;
+
+bool GetRandom(void *buffer, uptr length, bool blocking) {
+ CHECK_LE(length, ZX_CPRNG_DRAW_MAX_LEN);
+ _zx_cprng_draw(buffer, length);
+ return true;
+}
+
+u32 GetNumberOfCPUs() { return zx_system_get_num_cpus(); }
+
+uptr GetRSS() { UNIMPLEMENTED(); }
+
+void *internal_start_thread(void *(*func)(void *arg), void *arg) { return 0; }
+void internal_join_thread(void *th) {}
+
+void InitializePlatformCommonFlags(CommonFlags *cf) {}
+
+} // namespace __sanitizer
+
+using namespace __sanitizer;
+
+extern "C" {
+void __sanitizer_startup_hook(int argc, char **argv, char **envp,
+ void *stack_base, size_t stack_size) {
+ __sanitizer::StoredArgv = argv;
+ __sanitizer::StoredEnviron = envp;
+ __sanitizer::MainThreadStackBase = reinterpret_cast<uintptr_t>(stack_base);
+ __sanitizer::MainThreadStackSize = stack_size;
+}
+
+void __sanitizer_set_report_path(const char *path) {
+ // Handle the initialization code in each sanitizer, but no other calls.
+ // This setting is never consulted on Fuchsia.
+ DCHECK_EQ(path, common_flags()->log_path);
+}
+
+void __sanitizer_set_report_fd(void *fd) {
+ UNREACHABLE("not available on Fuchsia");
+}
+
+const char *__sanitizer_get_report_path() {
+ UNREACHABLE("not available on Fuchsia");
+}
+} // extern "C"
+
+#endif // SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_fuchsia.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_fuchsia.h
new file mode 100644
index 00000000000..77c9a3f9d1e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_fuchsia.h
@@ -0,0 +1,38 @@
+//===-- sanitizer_fuchsia.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// Fuchsia-specific sanitizer support.
+//
+//===---------------------------------------------------------------------===//
+#ifndef SANITIZER_FUCHSIA_H
+#define SANITIZER_FUCHSIA_H
+
+#include "sanitizer_platform.h"
+#if SANITIZER_FUCHSIA
+
+#include "sanitizer_common.h"
+
+#error #include <zircon/sanitizer.h>
+#error #include <zircon/syscalls/object.h>
+
+namespace __sanitizer {
+
+extern uptr MainThreadStackBase, MainThreadStackSize;
+extern sanitizer_shadow_bounds_t ShadowBounds;
+
+struct MemoryMappingLayoutData {
+ InternalMmapVector<zx_info_maps_t> data;
+ size_t current; // Current index into the vector.
+};
+
+void InitShadowBounds();
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_FUCHSIA
+#endif // SANITIZER_FUCHSIA_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_getauxval.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_getauxval.h
new file mode 100644
index 00000000000..38439e44f61
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_getauxval.h
@@ -0,0 +1,60 @@
+//===-- sanitizer_getauxval.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Common getauxval() guards and definitions.
+// getauxval() is not defined until glibc version 2.16, or until API level 21
+// for Android.
+// Implement the getauxval() compat function for NetBSD.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_GETAUXVAL_H
+#define SANITIZER_GETAUXVAL_H
+
+#include "sanitizer_platform.h"
+#include "sanitizer_glibc_version.h"
+
+#if SANITIZER_LINUX || SANITIZER_FUCHSIA
+
+# if (__GLIBC_PREREQ(2, 16) || (SANITIZER_ANDROID && __ANDROID_API__ >= 21) || \
+ SANITIZER_FUCHSIA) && \
+ !SANITIZER_GO
+# define SANITIZER_USE_GETAUXVAL 1
+# else
+# define SANITIZER_USE_GETAUXVAL 0
+# endif
+
+# if SANITIZER_USE_GETAUXVAL
+# include <sys/auxv.h>
+# else
+// The weak getauxval definition allows to check for the function at runtime.
+// This is useful for Android, when compiled at a lower API level yet running
+// on a more recent platform that offers the function.
+extern "C" SANITIZER_WEAK_ATTRIBUTE unsigned long getauxval(unsigned long type);
+# endif
+
+#elif SANITIZER_NETBSD
+
+#define SANITIZER_USE_GETAUXVAL 1
+
+#include <dlfcn.h>
+#include <elf.h>
+
+static inline decltype(AuxInfo::a_v) getauxval(decltype(AuxInfo::a_type) type) {
+ for (const AuxInfo *aux = (const AuxInfo *)_dlauxinfo();
+ aux->a_type != AT_NULL; ++aux) {
+ if (type == aux->a_type)
+ return aux->a_v;
+ }
+
+ return 0;
+}
+
+#endif
+
+#endif // SANITIZER_GETAUXVAL_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_glibc_version.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_glibc_version.h
new file mode 100644
index 00000000000..47175f20aa0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_glibc_version.h
@@ -0,0 +1,26 @@
+//===-- sanitizer_glibc_version.h -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer common code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_GLIBC_VERSION_H
+#define SANITIZER_GLIBC_VERSION_H
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_LINUX || SANITIZER_FUCHSIA
+#include <features.h>
+#endif
+
+#ifndef __GLIBC_PREREQ
+#define __GLIBC_PREREQ(x, y) 0
+#endif
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_hash.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_hash.h
new file mode 100644
index 00000000000..f7cf9f234e6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_hash.h
@@ -0,0 +1,67 @@
+//===-- sanitizer_common.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a simple hash function.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_HASH_H
+#define SANITIZER_HASH_H
+
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+class MurMur2HashBuilder {
+ static const u32 m = 0x5bd1e995;
+ static const u32 seed = 0x9747b28c;
+ static const u32 r = 24;
+ u32 h;
+
+ public:
+ explicit MurMur2HashBuilder(u32 init = 0) { h = seed ^ init; }
+ void add(u32 k) {
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+ h *= m;
+ h ^= k;
+ }
+ u32 get() {
+ u32 x = h;
+ x ^= x >> 13;
+ x *= m;
+ x ^= x >> 15;
+ return x;
+ }
+};
+
+class MurMur2Hash64Builder {
+ static const u64 m = 0xc6a4a7935bd1e995ull;
+ static const u64 seed = 0x9747b28c9747b28cull;
+ static const u64 r = 47;
+ u64 h;
+
+ public:
+ explicit MurMur2Hash64Builder(u64 init = 0) { h = seed ^ (init * m); }
+ void add(u64 k) {
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+ h ^= k;
+ h *= m;
+ }
+ u64 get() {
+ u64 x = h;
+ x ^= x >> r;
+ x *= m;
+ x ^= x >> r;
+ return x;
+ }
+};
+} //namespace __sanitizer
+
+#endif // SANITIZER_HASH_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc
new file mode 100644
index 00000000000..9683b97ab91
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc
@@ -0,0 +1,1535 @@
+//===-- sanitizer_interceptors_ioctl_netbsd.inc -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Ioctl handling in common sanitizer interceptors.
+//===----------------------------------------------------------------------===//
+
+#if SANITIZER_NETBSD
+
+#include "sanitizer_flags.h"
+
+struct ioctl_desc {
+ unsigned req;
+ // FIXME: support read+write arguments. Currently READWRITE and WRITE do the
+ // same thing.
+ // XXX: The declarations below may use WRITE instead of READWRITE, unless
+ // explicitly noted.
+ enum { NONE, READ, WRITE, READWRITE, CUSTOM } type : 3;
+ unsigned size : 29;
+ const char *name;
+};
+
+const unsigned ioctl_table_max = 1238;
+static ioctl_desc ioctl_table[ioctl_table_max];
+static unsigned ioctl_table_size = 0;
+
+// This can not be declared as a global, because references to struct_*_sz
+// require a global initializer. And this table must be available before global
+// initializers are run.
+static void ioctl_table_fill() {
+#define _(rq, tp, sz) \
+ if (IOCTL_##rq != IOCTL_NOT_PRESENT) { \
+ CHECK(ioctl_table_size < ioctl_table_max); \
+ ioctl_table[ioctl_table_size].req = IOCTL_##rq; \
+ ioctl_table[ioctl_table_size].type = ioctl_desc::tp; \
+ ioctl_table[ioctl_table_size].size = sz; \
+ ioctl_table[ioctl_table_size].name = #rq; \
+ ++ioctl_table_size; \
+ }
+
+ /* Entries from file: altq/altq_afmap.h */
+ _(AFM_ADDFMAP, READWRITE, struct_atm_flowmap_sz);
+ _(AFM_DELFMAP, READWRITE, struct_atm_flowmap_sz);
+ _(AFM_CLEANFMAP, READWRITE, struct_atm_flowmap_sz);
+ _(AFM_GETFMAP, READWRITE, struct_atm_flowmap_sz);
+ /* Entries from file: altq/altq.h */
+ _(ALTQGTYPE, READWRITE, struct_altqreq_sz);
+ _(ALTQTBRSET, READ, struct_tbrreq_sz);
+ _(ALTQTBRGET, READWRITE, struct_tbrreq_sz);
+ /* Entries from file: altq/altq_blue.h */
+ _(BLUE_IF_ATTACH, READ, struct_blue_interface_sz);
+ _(BLUE_DISABLE, READ, struct_blue_interface_sz);
+ _(BLUE_CONFIG, READWRITE, struct_blue_conf_sz);
+ _(BLUE_GETSTATS, READWRITE, struct_blue_stats_sz);
+ /* Entries from file: altq/altq_cbq.h */
+ _(CBQ_ENABLE, READ, struct_cbq_interface_sz);
+ _(CBQ_ADD_CLASS, READWRITE, struct_cbq_add_class_sz);
+ _(CBQ_DEL_CLASS, READ, struct_cbq_delete_class_sz);
+ _(CBQ_MODIFY_CLASS, READWRITE, struct_cbq_modify_class_sz);
+ _(CBQ_DEL_FILTER, READ, struct_cbq_delete_filter_sz);
+ _(CBQ_GETSTATS, READWRITE, struct_cbq_getstats_sz);
+ /* Entries from file: altq/altq_cdnr.h */
+ _(CDNR_IF_DETACH, READ, struct_cdnr_interface_sz);
+ _(CDNR_ADD_FILTER, READWRITE, struct_cdnr_add_filter_sz);
+ _(CDNR_GETSTATS, READWRITE, struct_cdnr_get_stats_sz);
+ _(CDNR_ADD_ELEM, READWRITE, struct_cdnr_add_element_sz);
+ _(CDNR_DEL_ELEM, READ, struct_cdnr_delete_element_sz);
+ _(CDNR_ADD_TBM, READWRITE, struct_cdnr_add_tbmeter_sz);
+ _(CDNR_MOD_TBM, READ, struct_cdnr_modify_tbmeter_sz);
+ _(CDNR_TBM_STATS, READWRITE, struct_cdnr_tbmeter_stats_sz);
+ _(CDNR_ADD_TCM, READWRITE, struct_cdnr_add_trtcm_sz);
+ _(CDNR_MOD_TCM, READWRITE, struct_cdnr_modify_trtcm_sz);
+ _(CDNR_TCM_STATS, READWRITE, struct_cdnr_tcm_stats_sz);
+ _(CDNR_ADD_TSW, READWRITE, struct_cdnr_add_tswtcm_sz);
+ _(CDNR_MOD_TSW, READWRITE, struct_cdnr_modify_tswtcm_sz);
+ /* Entries from file: altq/altq_fifoq.h */
+ _(FIFOQ_CONFIG, READWRITE, struct_fifoq_conf_sz);
+ _(FIFOQ_GETSTATS, READWRITE, struct_fifoq_getstats_sz);
+ /* Entries from file: altq/altq_hfsc.h */
+ _(HFSC_CLEAR_HIERARCHY, READ, struct_hfsc_interface_sz);
+ _(HFSC_ADD_CLASS, READWRITE, struct_hfsc_add_class_sz);
+ _(HFSC_GETSTATS, READWRITE, struct_hfsc_class_stats_sz);
+ /* Entries from file: altq/altq_jobs.h */
+ _(JOBS_IF_ATTACH, READ, struct_jobs_attach_sz);
+ _(JOBS_IF_DETACH, READ, struct_jobs_interface_sz);
+ _(JOBS_ENABLE, READ, struct_jobs_interface_sz);
+ _(JOBS_DISABLE, READ, struct_jobs_interface_sz);
+ _(JOBS_CLEAR, READ, struct_jobs_interface_sz);
+ _(JOBS_ADD_CLASS, READWRITE, struct_jobs_add_class_sz);
+ _(JOBS_MOD_CLASS, READ, struct_jobs_modify_class_sz);
+ /* Entries from file: altq/altq_priq.h */
+ _(PRIQ_IF_ATTACH, READ, struct_priq_interface_sz);
+ _(PRIQ_CLEAR, READ, struct_priq_interface_sz);
+ _(PRIQ_ADD_CLASS, READWRITE, struct_priq_add_class_sz);
+ _(PRIQ_DEL_CLASS, READ, struct_priq_delete_class_sz);
+ _(PRIQ_MOD_CLASS, READ, struct_priq_modify_class_sz);
+ _(PRIQ_ADD_FILTER, READWRITE, struct_priq_add_filter_sz);
+ _(PRIQ_DEL_FILTER, READ, struct_priq_delete_filter_sz);
+ _(PRIQ_GETSTATS, READWRITE, struct_priq_class_stats_sz);
+ /* Entries from file: altq/altq_red.h */
+ _(RED_CONFIG, READWRITE, struct_red_conf_sz);
+ _(RED_GETSTATS, READWRITE, struct_red_stats_sz);
+ _(RED_SETDEFAULTS, READ, struct_redparams_sz);
+ /* Entries from file: altq/altq_rio.h */
+ _(RIO_CONFIG, READWRITE, struct_rio_conf_sz);
+ _(RIO_GETSTATS, READWRITE, struct_rio_stats_sz);
+ _(RIO_SETDEFAULTS, READ, struct_redparams_sz);
+ /* Entries from file: altq/altq_wfq.h */
+ _(WFQ_CONFIG, READWRITE, struct_wfq_conf_sz);
+ _(WFQ_GET_QID, READWRITE, struct_wfq_getqid_sz);
+ _(WFQ_SET_WEIGHT, READWRITE, struct_wfq_setweight_sz);
+ /* Entries from file: crypto/cryptodev.h */
+ _(CRIOGET, READWRITE, sizeof(u32));
+ _(CIOCFSESSION, READ, sizeof(u32));
+ _(CIOCKEY, READWRITE, struct_crypt_kop_sz);
+ _(CIOCNFKEYM, READWRITE, struct_crypt_mkop_sz);
+ _(CIOCNFSESSION, READ, struct_crypt_sfop_sz);
+ _(CIOCNCRYPTRETM, READWRITE, struct_cryptret_sz);
+ _(CIOCNCRYPTRET, READWRITE, struct_crypt_result_sz);
+ _(CIOCGSESSION, READWRITE, struct_session_op_sz);
+ _(CIOCNGSESSION, READWRITE, struct_crypt_sgop_sz);
+ _(CIOCCRYPT, READWRITE, struct_crypt_op_sz);
+ _(CIOCNCRYPTM, READWRITE, struct_crypt_mop_sz);
+ _(CIOCASYMFEAT, WRITE, sizeof(u32));
+ /* Entries from file: dev/apm/apmio.h */
+ _(APM_IOC_REJECT, READ, struct_apm_event_info_sz);
+ _(OAPM_IOC_GETPOWER, WRITE, struct_apm_power_info_sz);
+ _(APM_IOC_GETPOWER, READWRITE, struct_apm_power_info_sz);
+ _(APM_IOC_NEXTEVENT, WRITE, struct_apm_event_info_sz);
+ _(APM_IOC_DEV_CTL, READ, struct_apm_ctl_sz);
+ /* Entries from file: dev/dm/netbsd-dm.h */
+ _(NETBSD_DM_IOCTL, READWRITE, struct_plistref_sz);
+ /* Entries from file: dev/dmover/dmover_io.h */
+ _(DMIO_SETFUNC, READ, struct_dmio_setfunc_sz);
+ /* Entries from file: dev/dtv/dtvio_demux.h */
+ _(DMX_START, NONE, 0);
+ _(DMX_STOP, NONE, 0);
+ _(DMX_SET_FILTER, READ, struct_dmx_sct_filter_params_sz);
+ _(DMX_SET_PES_FILTER, READ, struct_dmx_pes_filter_params_sz);
+ _(DMX_SET_BUFFER_SIZE, NONE, 0);
+ _(DMX_GET_STC, READWRITE, struct_dmx_stc_sz);
+ _(DMX_ADD_PID, READ, sizeof(u16));
+ _(DMX_REMOVE_PID, READ, sizeof(u16));
+ _(DMX_GET_CAPS, WRITE, struct_dmx_caps_sz);
+ _(DMX_SET_SOURCE, READ, enum_dmx_source_sz);
+ /* Entries from file: dev/dtv/dtvio_frontend.h */
+ _(FE_READ_STATUS, WRITE, enum_fe_status_sz);
+ _(FE_READ_BER, WRITE, sizeof(u32));
+ _(FE_READ_SNR, WRITE, sizeof(u16));
+ _(FE_READ_SIGNAL_STRENGTH, WRITE, sizeof(u16));
+ _(FE_READ_UNCORRECTED_BLOCKS, WRITE, sizeof(u32));
+ _(FE_SET_FRONTEND, READWRITE, struct_dvb_frontend_parameters_sz);
+ _(FE_GET_FRONTEND, WRITE, struct_dvb_frontend_parameters_sz);
+ _(FE_GET_EVENT, WRITE, struct_dvb_frontend_event_sz);
+ _(FE_GET_INFO, WRITE, struct_dvb_frontend_info_sz);
+ _(FE_DISEQC_RESET_OVERLOAD, NONE, 0);
+ _(FE_DISEQC_SEND_MASTER_CMD, READ, struct_dvb_diseqc_master_cmd_sz);
+ _(FE_DISEQC_RECV_SLAVE_REPLY, WRITE, struct_dvb_diseqc_slave_reply_sz);
+ _(FE_DISEQC_SEND_BURST, READ, enum_fe_sec_mini_cmd_sz);
+ _(FE_SET_TONE, READ, enum_fe_sec_tone_mode_sz);
+ _(FE_SET_VOLTAGE, READ, enum_fe_sec_voltage_sz);
+ _(FE_ENABLE_HIGH_LNB_VOLTAGE, READ, sizeof(int));
+ _(FE_SET_FRONTEND_TUNE_MODE, READ, sizeof(unsigned int));
+ _(FE_DISHNETWORK_SEND_LEGACY_CMD, READ, sizeof(unsigned long));
+ /* Entries from file: dev/hdaudio/hdaudioio.h */
+ _(HDAUDIO_FGRP_INFO, READWRITE, struct_plistref_sz);
+ _(HDAUDIO_FGRP_GETCONFIG, READWRITE, struct_plistref_sz);
+ _(HDAUDIO_FGRP_SETCONFIG, READWRITE, struct_plistref_sz);
+ _(HDAUDIO_FGRP_WIDGET_INFO, READWRITE, struct_plistref_sz);
+ _(HDAUDIO_FGRP_CODEC_INFO, READWRITE, struct_plistref_sz);
+ _(HDAUDIO_AFG_WIDGET_INFO, READWRITE, struct_plistref_sz);
+ _(HDAUDIO_AFG_CODEC_INFO, READWRITE, struct_plistref_sz);
+ /* Entries from file: dev/hdmicec/hdmicecio.h */
+ _(CEC_GET_PHYS_ADDR, WRITE, sizeof(u16));
+ _(CEC_GET_LOG_ADDRS, WRITE, sizeof(u16));
+ _(CEC_SET_LOG_ADDRS, READ, sizeof(u16));
+ _(CEC_GET_VENDOR_ID, WRITE, sizeof(u32));
+ /* Entries from file: dev/hpc/hpcfbio.h */
+ _(HPCFBIO_GCONF, READWRITE, struct_hpcfb_fbconf_sz);
+ _(HPCFBIO_SCONF, READ, struct_hpcfb_fbconf_sz);
+ _(HPCFBIO_GDSPCONF, READWRITE, struct_hpcfb_dspconf_sz);
+ _(HPCFBIO_SDSPCONF, READ, struct_hpcfb_dspconf_sz);
+ _(HPCFBIO_GOP, WRITE, struct_hpcfb_dsp_op_sz);
+ _(HPCFBIO_SOP, READWRITE, struct_hpcfb_dsp_op_sz);
+ /* Entries from file: dev/i2o/iopio.h */
+ _(IOPIOCPT, READWRITE, struct_ioppt_sz);
+ _(IOPIOCGLCT, READWRITE, struct_iovec_sz);
+ _(IOPIOCGSTATUS, READWRITE, struct_iovec_sz);
+ _(IOPIOCRECONFIG, NONE, 0);
+ _(IOPIOCGTIDMAP, READWRITE, struct_iovec_sz);
+ /* Entries from file: dev/ic/athioctl.h */
+ _(SIOCGATHSTATS, READWRITE, struct_ifreq_sz);
+ _(SIOCGATHDIAG, READWRITE, struct_ath_diag_sz);
+ /* Entries from file: dev/ic/bt8xx.h */
+ _(METEORCAPTUR, READ, sizeof(int));
+ _(METEORCAPFRM, READ, struct_meteor_capframe_sz);
+ _(METEORSETGEO, READ, struct_meteor_geomet_sz);
+ _(METEORGETGEO, WRITE, struct_meteor_geomet_sz);
+ _(METEORSTATUS, WRITE, sizeof(unsigned short));
+ _(METEORSHUE, READ, sizeof(signed char));
+ _(METEORGHUE, WRITE, sizeof(signed char));
+ _(METEORSFMT, READ, sizeof(unsigned int));
+ _(METEORGFMT, WRITE, sizeof(unsigned int));
+ _(METEORSINPUT, READ, sizeof(unsigned int));
+ _(METEORGINPUT, WRITE, sizeof(unsigned int));
+ _(METEORSCHCV, READ, sizeof(unsigned char));
+ _(METEORGCHCV, WRITE, sizeof(unsigned char));
+ _(METEORSCOUNT, READ, struct_meteor_counts_sz);
+ _(METEORGCOUNT, WRITE, struct_meteor_counts_sz);
+ _(METEORSFPS, READ, sizeof(unsigned short));
+ _(METEORGFPS, WRITE, sizeof(unsigned short));
+ _(METEORSSIGNAL, READ, sizeof(unsigned int));
+ _(METEORGSIGNAL, WRITE, sizeof(unsigned int));
+ _(METEORSVIDEO, READ, struct_meteor_video_sz);
+ _(METEORGVIDEO, WRITE, struct_meteor_video_sz);
+ _(METEORSBRIG, READ, sizeof(unsigned char));
+ _(METEORGBRIG, WRITE, sizeof(unsigned char));
+ _(METEORSCSAT, READ, sizeof(unsigned char));
+ _(METEORGCSAT, WRITE, sizeof(unsigned char));
+ _(METEORSCONT, READ, sizeof(unsigned char));
+ _(METEORGCONT, WRITE, sizeof(unsigned char));
+ _(METEORSHWS, READ, sizeof(unsigned char));
+ _(METEORGHWS, WRITE, sizeof(unsigned char));
+ _(METEORSVWS, READ, sizeof(unsigned char));
+ _(METEORGVWS, WRITE, sizeof(unsigned char));
+ _(METEORSTS, READ, sizeof(unsigned char));
+ _(METEORGTS, WRITE, sizeof(unsigned char));
+ _(TVTUNER_SETCHNL, READ, sizeof(unsigned int));
+ _(TVTUNER_GETCHNL, WRITE, sizeof(unsigned int));
+ _(TVTUNER_SETTYPE, READ, sizeof(unsigned int));
+ _(TVTUNER_GETTYPE, WRITE, sizeof(unsigned int));
+ _(TVTUNER_GETSTATUS, WRITE, sizeof(unsigned int));
+ _(TVTUNER_SETFREQ, READ, sizeof(unsigned int));
+ _(TVTUNER_GETFREQ, WRITE, sizeof(unsigned int));
+ _(TVTUNER_SETAFC, READ, sizeof(int));
+ _(TVTUNER_GETAFC, WRITE, sizeof(int));
+ _(RADIO_SETMODE, READ, sizeof(unsigned int));
+ _(RADIO_GETMODE, WRITE, sizeof(unsigned char));
+ _(RADIO_SETFREQ, READ, sizeof(unsigned int));
+ _(RADIO_GETFREQ, WRITE, sizeof(unsigned int));
+ _(METEORSACTPIXFMT, READ, sizeof(int));
+ _(METEORGACTPIXFMT, WRITE, sizeof(int));
+ _(METEORGSUPPIXFMT, READWRITE, struct_meteor_pixfmt_sz);
+ _(TVTUNER_GETCHNLSET, READWRITE, struct_bktr_chnlset_sz);
+ _(REMOTE_GETKEY, WRITE, struct_bktr_remote_sz);
+ /* Entries from file: dev/ic/icp_ioctl.h */
+ _(GDT_IOCTL_GENERAL, READWRITE, struct_gdt_ucmd_sz);
+ _(GDT_IOCTL_DRVERS, WRITE, sizeof(int));
+ _(GDT_IOCTL_CTRTYPE, READWRITE, struct_gdt_ctrt_sz);
+ _(GDT_IOCTL_OSVERS, WRITE, struct_gdt_osv_sz);
+ _(GDT_IOCTL_CTRCNT, WRITE, sizeof(int));
+ _(GDT_IOCTL_EVENT, READWRITE, struct_gdt_event_sz);
+ _(GDT_IOCTL_STATIST, WRITE, struct_gdt_statist_sz);
+ _(GDT_IOCTL_RESCAN, READWRITE, struct_gdt_rescan_sz);
+ /* Entries from file: dev/ic/isp_ioctl.h */
+ _(ISP_SDBLEV, READWRITE, sizeof(int));
+ _(ISP_RESETHBA, NONE, 0);
+ _(ISP_RESCAN, NONE, 0);
+ _(ISP_SETROLE, READWRITE, sizeof(int));
+ _(ISP_GETROLE, WRITE, sizeof(int));
+ _(ISP_GET_STATS, WRITE, struct_isp_stats_sz);
+ _(ISP_CLR_STATS, NONE, 0);
+ _(ISP_FC_LIP, NONE, 0);
+ _(ISP_FC_GETDINFO, READWRITE, struct_isp_fc_device_sz);
+ _(ISP_GET_FW_CRASH_DUMP, NONE, 0);
+ _(ISP_FORCE_CRASH_DUMP, NONE, 0);
+ _(ISP_FC_GETHINFO, READWRITE, struct_isp_hba_device_sz);
+ _(ISP_TSK_MGMT, READWRITE, struct_isp_fc_tsk_mgmt_sz);
+ _(ISP_FC_GETDLIST, NONE, 0);
+ /* Entries from file: dev/ic/mlxio.h */
+ _(MLXD_STATUS, WRITE, sizeof(int));
+ _(MLXD_CHECKASYNC, WRITE, sizeof(int));
+ _(MLXD_DETACH, READ, sizeof(int));
+ _(MLX_RESCAN_DRIVES, NONE, 0);
+ _(MLX_PAUSE_CHANNEL, READ, struct_mlx_pause_sz);
+ _(MLX_COMMAND, READWRITE, struct_mlx_usercommand_sz);
+ _(MLX_REBUILDASYNC, READWRITE, struct_mlx_rebuild_request_sz);
+ _(MLX_REBUILDSTAT, WRITE, struct_mlx_rebuild_status_sz);
+ _(MLX_GET_SYSDRIVE, READWRITE, sizeof(int));
+ _(MLX_GET_CINFO, WRITE, struct_mlx_cinfo_sz);
+ /* Entries from file: dev/ic/nvmeio.h */
+ _(NVME_PASSTHROUGH_CMD, READWRITE, struct_nvme_pt_command_sz);
+ /* Entries from file: dev/ic/qemufwcfgio.h */
+ _(FWCFGIO_SET_INDEX, READ, sizeof(u16));
+ /* Entries from file: dev/ir/irdaio.h */
+ _(IRDA_RESET_PARAMS, NONE, 0);
+ _(IRDA_SET_PARAMS, READ, struct_irda_params_sz);
+ _(IRDA_GET_SPEEDMASK, WRITE, sizeof(unsigned int));
+ _(IRDA_GET_TURNAROUNDMASK, WRITE, sizeof(unsigned int));
+ _(IRFRAMETTY_GET_DEVICE, WRITE, sizeof(unsigned int));
+ _(IRFRAMETTY_GET_DONGLE, WRITE, sizeof(unsigned int));
+ _(IRFRAMETTY_SET_DONGLE, READ, sizeof(unsigned int));
+ /* Entries from file: dev/isa/isvio.h */
+ _(ISV_CMD, READWRITE, struct_isv_cmd_sz);
+ /* Entries from file: dev/isa/wtreg.h */
+ _(WTQICMD, NONE, 0);
+ /* Entries from file: dev/iscsi/iscsi_ioctl.h */
+ _(ISCSI_GET_VERSION, READWRITE, struct_iscsi_get_version_parameters_sz);
+ _(ISCSI_LOGIN, READWRITE, struct_iscsi_login_parameters_sz);
+ _(ISCSI_LOGOUT, READWRITE, struct_iscsi_logout_parameters_sz);
+ _(ISCSI_ADD_CONNECTION, READWRITE, struct_iscsi_login_parameters_sz);
+ _(ISCSI_RESTORE_CONNECTION, READWRITE, struct_iscsi_login_parameters_sz);
+ _(ISCSI_REMOVE_CONNECTION, READWRITE, struct_iscsi_remove_parameters_sz);
+ _(ISCSI_CONNECTION_STATUS, READWRITE, struct_iscsi_conn_status_parameters_sz);
+ _(ISCSI_SEND_TARGETS, READWRITE, struct_iscsi_send_targets_parameters_sz);
+ _(ISCSI_SET_NODE_NAME, READWRITE, struct_iscsi_set_node_name_parameters_sz);
+ _(ISCSI_IO_COMMAND, READWRITE, struct_iscsi_iocommand_parameters_sz);
+ _(ISCSI_REGISTER_EVENT, READWRITE, struct_iscsi_register_event_parameters_sz);
+ _(ISCSI_DEREGISTER_EVENT, READWRITE,
+ struct_iscsi_register_event_parameters_sz);
+ _(ISCSI_WAIT_EVENT, READWRITE, struct_iscsi_wait_event_parameters_sz);
+ _(ISCSI_POLL_EVENT, READWRITE, struct_iscsi_wait_event_parameters_sz);
+ /* Entries from file: dev/ofw/openfirmio.h */
+ _(OFIOCGET, READWRITE, struct_ofiocdesc_sz);
+ _(OFIOCSET, READ, struct_ofiocdesc_sz);
+ _(OFIOCNEXTPROP, READWRITE, struct_ofiocdesc_sz);
+ _(OFIOCGETOPTNODE, WRITE, sizeof(int));
+ _(OFIOCGETNEXT, READWRITE, sizeof(int));
+ _(OFIOCGETCHILD, READWRITE, sizeof(int));
+ _(OFIOCFINDDEVICE, READWRITE, struct_ofiocdesc_sz);
+ /* Entries from file: dev/pci/amrio.h */
+ _(AMR_IO_VERSION, WRITE, sizeof(int));
+ _(AMR_IO_COMMAND, READWRITE, struct_amr_user_ioctl_sz);
+ /* Entries from file: dev/pci/mlyio.h */
+ _(MLYIO_COMMAND, READWRITE, struct_mly_user_command_sz);
+ _(MLYIO_HEALTH, READ, struct_mly_user_health_sz);
+ /* Entries from file: dev/pci/pciio.h */
+ _(PCI_IOC_CFGREAD, READWRITE, struct_pciio_cfgreg_sz);
+ _(PCI_IOC_CFGWRITE, READ, struct_pciio_cfgreg_sz);
+ _(PCI_IOC_BDF_CFGREAD, READWRITE, struct_pciio_bdf_cfgreg_sz);
+ _(PCI_IOC_BDF_CFGWRITE, READ, struct_pciio_bdf_cfgreg_sz);
+ _(PCI_IOC_BUSINFO, WRITE, struct_pciio_businfo_sz);
+ _(PCI_IOC_DRVNAME, READWRITE, struct_pciio_drvname_sz);
+ _(PCI_IOC_DRVNAMEONBUS, READWRITE, struct_pciio_drvnameonbus_sz);
+ /* Entries from file: dev/pci/tweio.h */
+ _(TWEIO_COMMAND, READWRITE, struct_twe_usercommand_sz);
+ _(TWEIO_STATS, READWRITE, union_twe_statrequest_sz);
+ _(TWEIO_AEN_POLL, WRITE, sizeof(int));
+ _(TWEIO_AEN_WAIT, WRITE, sizeof(int));
+ _(TWEIO_SET_PARAM, READ, struct_twe_paramcommand_sz);
+ _(TWEIO_GET_PARAM, READ, struct_twe_paramcommand_sz);
+ _(TWEIO_RESET, NONE, 0);
+ _(TWEIO_ADD_UNIT, READ, struct_twe_drivecommand_sz);
+ _(TWEIO_DEL_UNIT, READ, struct_twe_drivecommand_sz);
+ /* Entries from file: dev/pcmcia/if_cnwioctl.h */
+ _(SIOCSCNWDOMAIN, READ, struct_ifreq_sz);
+ _(SIOCGCNWDOMAIN, READWRITE, struct_ifreq_sz);
+ _(SIOCSCNWKEY, READWRITE, struct_ifreq_sz);
+ _(SIOCGCNWSTATUS, READWRITE, struct_cnwstatus_sz);
+ _(SIOCGCNWSTATS, READWRITE, struct_cnwistats_sz);
+ _(SIOCGCNWTRAIL, READWRITE, struct_cnwitrail_sz);
+ /* Entries from file: dev/pcmcia/if_rayreg.h */
+ _(SIOCGRAYSIGLEV, READWRITE, struct_ifreq_sz);
+ /* Entries from file: dev/raidframe/raidframeio.h */
+ _(RAIDFRAME_SHUTDOWN, NONE, 0);
+ _(RAIDFRAME_TUR, READ, sizeof(u64));
+ _(RAIDFRAME_FAIL_DISK, READ, struct_rf_recon_req_sz);
+ _(RAIDFRAME_CHECK_RECON_STATUS, READWRITE, sizeof(int));
+ _(RAIDFRAME_REWRITEPARITY, NONE, 0);
+ _(RAIDFRAME_COPYBACK, NONE, 0);
+ _(RAIDFRAME_SPARET_WAIT, WRITE, struct_RF_SparetWait_sz);
+ _(RAIDFRAME_SEND_SPARET, READ, sizeof(uptr));
+ _(RAIDFRAME_ABORT_SPARET_WAIT, NONE, 0);
+ _(RAIDFRAME_START_ATRACE, NONE, 0);
+ _(RAIDFRAME_STOP_ATRACE, NONE, 0);
+ _(RAIDFRAME_GET_SIZE, WRITE, sizeof(int));
+ _(RAIDFRAME_RESET_ACCTOTALS, NONE, 0);
+ _(RAIDFRAME_KEEP_ACCTOTALS, READ, sizeof(int));
+ _(RAIDFRAME_GET_COMPONENT_LABEL, READWRITE, struct_RF_ComponentLabel_sz);
+ _(RAIDFRAME_SET_COMPONENT_LABEL, READ, struct_RF_ComponentLabel_sz);
+ _(RAIDFRAME_INIT_LABELS, READ, struct_RF_ComponentLabel_sz);
+ _(RAIDFRAME_ADD_HOT_SPARE, READ, struct_RF_SingleComponent_sz);
+ _(RAIDFRAME_REMOVE_HOT_SPARE, READ, struct_RF_SingleComponent_sz);
+ _(RAIDFRAME_REBUILD_IN_PLACE, READ, struct_RF_SingleComponent_sz);
+ _(RAIDFRAME_CHECK_PARITY, READWRITE, sizeof(int));
+ _(RAIDFRAME_CHECK_PARITYREWRITE_STATUS, READWRITE, sizeof(int));
+ _(RAIDFRAME_CHECK_COPYBACK_STATUS, READWRITE, sizeof(int));
+ _(RAIDFRAME_SET_AUTOCONFIG, READWRITE, sizeof(int));
+ _(RAIDFRAME_SET_ROOT, READWRITE, sizeof(int));
+ _(RAIDFRAME_DELETE_COMPONENT, READ, struct_RF_SingleComponent_sz);
+ _(RAIDFRAME_INCORPORATE_HOT_SPARE, READ, struct_RF_SingleComponent_sz);
+ _(RAIDFRAME_CHECK_RECON_STATUS_EXT, READWRITE, struct_RF_ProgressInfo_sz);
+ _(RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT, READWRITE,
+ struct_RF_ProgressInfo_sz);
+ _(RAIDFRAME_CHECK_COPYBACK_STATUS_EXT, READWRITE, struct_RF_ProgressInfo_sz);
+ _(RAIDFRAME_PARITYMAP_STATUS, WRITE, struct_rf_pmstat_sz);
+ _(RAIDFRAME_PARITYMAP_GET_DISABLE, WRITE, sizeof(int));
+ _(RAIDFRAME_PARITYMAP_SET_DISABLE, READ, sizeof(int));
+ _(RAIDFRAME_PARITYMAP_SET_PARAMS, READ, struct_rf_pmparams_sz);
+ _(RAIDFRAME_SET_LAST_UNIT, READ, sizeof(int));
+ _(RAIDFRAME_GET_INFO, READWRITE, sizeof(uptr));
+ _(RAIDFRAME_CONFIGURE, READ, sizeof(uptr));
+ /* Entries from file: dev/sbus/mbppio.h */
+ _(MBPPIOCSPARAM, READ, struct_mbpp_param_sz);
+ _(MBPPIOCGPARAM, WRITE, struct_mbpp_param_sz);
+ _(MBPPIOCGSTAT, WRITE, sizeof(int));
+ /* Entries from file: dev/scsipi/ses.h */
+ _(SESIOC_GETNOBJ, NONE, 0);
+ _(SESIOC_GETOBJMAP, NONE, 0);
+ _(SESIOC_GETENCSTAT, NONE, 0);
+ _(SESIOC_SETENCSTAT, NONE, 0);
+ _(SESIOC_GETOBJSTAT, NONE, 0);
+ _(SESIOC_SETOBJSTAT, NONE, 0);
+ _(SESIOC_GETTEXT, NONE, 0);
+ _(SESIOC_INIT, NONE, 0);
+ /* Entries from file: dev/sun/disklabel.h */
+ _(SUN_DKIOCGGEOM, WRITE, struct_sun_dkgeom_sz);
+ _(SUN_DKIOCINFO, WRITE, struct_sun_dkctlr_sz);
+ _(SUN_DKIOCGPART, WRITE, struct_sun_dkpart_sz);
+ /* Entries from file: dev/sun/fbio.h */
+ _(FBIOGTYPE, WRITE, struct_fbtype_sz);
+ _(FBIOPUTCMAP, READ, struct_fbcmap_sz);
+ _(FBIOGETCMAP, READ, struct_fbcmap_sz);
+ _(FBIOGATTR, WRITE, struct_fbgattr_sz);
+ _(FBIOSVIDEO, READ, sizeof(int));
+ _(FBIOGVIDEO, WRITE, sizeof(int));
+ _(FBIOSCURSOR, READ, struct_fbcursor_sz);
+ _(FBIOGCURSOR, READWRITE, struct_fbcursor_sz);
+ _(FBIOSCURPOS, READ, struct_fbcurpos_sz);
+ _(FBIOGCURPOS, READ, struct_fbcurpos_sz);
+ _(FBIOGCURMAX, WRITE, struct_fbcurpos_sz);
+ /* Entries from file: dev/sun/kbio.h */
+ _(KIOCTRANS, READ, sizeof(int));
+ _(KIOCSETKEY, READWRITE, struct_okiockey_sz);
+ _(KIOCGETKEY, READWRITE, struct_okiockey_sz);
+ _(KIOCGTRANS, WRITE, sizeof(int));
+ _(KIOCCMD, READ, sizeof(int));
+ _(KIOCTYPE, WRITE, sizeof(int));
+ _(KIOCSDIRECT, READ, sizeof(int));
+ _(KIOCSKEY, READ, struct_kiockeymap_sz);
+ _(KIOCGKEY, READWRITE, struct_kiockeymap_sz);
+ _(KIOCSLED, READ, sizeof(char));
+ _(KIOCGLED, WRITE, sizeof(char));
+ _(KIOCLAYOUT, WRITE, sizeof(int));
+ /* Entries from file: dev/sun/vuid_event.h */
+ _(VUIDSFORMAT, READ, sizeof(int));
+ _(VUIDGFORMAT, WRITE, sizeof(int));
+ /* Entries from file: dev/tc/sticio.h */
+ _(STICIO_GXINFO, WRITE, struct_stic_xinfo_sz);
+ _(STICIO_RESET, NONE, 0);
+ _(STICIO_STARTQ, NONE, 0);
+ _(STICIO_STOPQ, NONE, 0);
+ /* Entries from file: dev/usb/ukyopon.h */
+ _(UKYOPON_IDENTIFY, WRITE, struct_ukyopon_identify_sz);
+ /* Entries from file: dev/usb/usb.h */
+ _(USB_REQUEST, READWRITE, struct_usb_ctl_request_sz);
+ _(USB_SETDEBUG, READ, sizeof(int));
+ _(USB_DISCOVER, NONE, 0);
+ _(USB_DEVICEINFO, READWRITE, struct_usb_device_info_sz);
+ _(USB_DEVICEINFO_OLD, READWRITE, struct_usb_device_info_old_sz);
+ _(USB_DEVICESTATS, WRITE, struct_usb_device_stats_sz);
+ _(USB_GET_REPORT_DESC, WRITE, struct_usb_ctl_report_desc_sz);
+ _(USB_SET_IMMED, READ, sizeof(int));
+ _(USB_GET_REPORT, READWRITE, struct_usb_ctl_report_sz);
+ _(USB_SET_REPORT, READ, struct_usb_ctl_report_sz);
+ _(USB_GET_REPORT_ID, WRITE, sizeof(int));
+ _(USB_GET_CONFIG, WRITE, sizeof(int));
+ _(USB_SET_CONFIG, READ, sizeof(int));
+ _(USB_GET_ALTINTERFACE, READWRITE, struct_usb_alt_interface_sz);
+ _(USB_SET_ALTINTERFACE, READWRITE, struct_usb_alt_interface_sz);
+ _(USB_GET_NO_ALT, READWRITE, struct_usb_alt_interface_sz);
+ _(USB_GET_DEVICE_DESC, WRITE, struct_usb_device_descriptor_sz);
+ _(USB_GET_CONFIG_DESC, READWRITE, struct_usb_config_desc_sz);
+ _(USB_GET_INTERFACE_DESC, READWRITE, struct_usb_interface_desc_sz);
+ _(USB_GET_ENDPOINT_DESC, READWRITE, struct_usb_endpoint_desc_sz);
+ _(USB_GET_FULL_DESC, READWRITE, struct_usb_full_desc_sz);
+ _(USB_GET_STRING_DESC, READWRITE, struct_usb_string_desc_sz);
+ _(USB_DO_REQUEST, READWRITE, struct_usb_ctl_request_sz);
+ _(USB_GET_DEVICEINFO, WRITE, struct_usb_device_info_sz);
+ _(USB_GET_DEVICEINFO_OLD, WRITE, struct_usb_device_info_old_sz);
+ _(USB_SET_SHORT_XFER, READ, sizeof(int));
+ _(USB_SET_TIMEOUT, READ, sizeof(int));
+ _(USB_SET_BULK_RA, READ, sizeof(int));
+ _(USB_SET_BULK_WB, READ, sizeof(int));
+ _(USB_SET_BULK_RA_OPT, READ, struct_usb_bulk_ra_wb_opt_sz);
+ _(USB_SET_BULK_WB_OPT, READ, struct_usb_bulk_ra_wb_opt_sz);
+ _(USB_GET_CM_OVER_DATA, WRITE, sizeof(int));
+ _(USB_SET_CM_OVER_DATA, READ, sizeof(int));
+ /* Entries from file: dev/usb/utoppy.h */
+ _(UTOPPYIOTURBO, READ, sizeof(int));
+ _(UTOPPYIOREBOOT, NONE, 0);
+ _(UTOPPYIOSTATS, WRITE, struct_utoppy_stats_sz);
+ _(UTOPPYIORENAME, READ, struct_utoppy_rename_sz);
+ _(UTOPPYIOMKDIR, READ, sizeof(uptr));
+ _(UTOPPYIODELETE, READ, sizeof(uptr));
+ _(UTOPPYIOREADDIR, READ, sizeof(uptr));
+ _(UTOPPYIOREADFILE, READ, struct_utoppy_readfile_sz);
+ _(UTOPPYIOWRITEFILE, READ, struct_utoppy_writefile_sz);
+ /* Entries from file: dev/vme/xio.h */
+ _(DIOSXDCMD, READWRITE, struct_xd_iocmd_sz);
+ /* Entries from file: dev/wscons/wsdisplay_usl_io.h */
+ _(VT_OPENQRY, WRITE, sizeof(int));
+ _(VT_SETMODE, READ, struct_vt_mode_sz);
+ _(VT_GETMODE, WRITE, struct_vt_mode_sz);
+ _(VT_RELDISP, NONE, 0);
+ _(VT_ACTIVATE, NONE, 0);
+ _(VT_WAITACTIVE, NONE, 0);
+ _(VT_GETACTIVE, WRITE, sizeof(int));
+ _(VT_GETSTATE, WRITE, struct_vt_stat_sz);
+ _(KDGETKBENT, READWRITE, struct_kbentry_sz);
+ _(KDGKBMODE, WRITE, sizeof(int));
+ _(KDSKBMODE, NONE, 0);
+ _(KDMKTONE, NONE, 0);
+ _(KDSETMODE, NONE, 0);
+ _(KDENABIO, NONE, 0);
+ _(KDDISABIO, NONE, 0);
+ _(KDGKBTYPE, WRITE, sizeof(char));
+ _(KDGETLED, WRITE, sizeof(int));
+ _(KDSETLED, NONE, 0);
+ _(KDSETRAD, NONE, 0);
+ _(VGAPCVTID, READWRITE, struct_pcvtid_sz);
+ _(CONS_GETVERS, WRITE, sizeof(int));
+ /* Entries from file: dev/wscons/wsconsio.h */
+ _(WSKBDIO_GTYPE, WRITE, sizeof(unsigned int));
+ _(WSKBDIO_BELL, NONE, 0);
+ _(WSKBDIO_COMPLEXBELL, READ, struct_wskbd_bell_data_sz);
+ _(WSKBDIO_SETBELL, READ, struct_wskbd_bell_data_sz);
+ _(WSKBDIO_GETBELL, WRITE, struct_wskbd_bell_data_sz);
+ _(WSKBDIO_SETDEFAULTBELL, READ, struct_wskbd_bell_data_sz);
+ _(WSKBDIO_GETDEFAULTBELL, WRITE, struct_wskbd_bell_data_sz);
+ _(WSKBDIO_SETKEYREPEAT, READ, struct_wskbd_keyrepeat_data_sz);
+ _(WSKBDIO_GETKEYREPEAT, WRITE, struct_wskbd_keyrepeat_data_sz);
+ _(WSKBDIO_SETDEFAULTKEYREPEAT, READ, struct_wskbd_keyrepeat_data_sz);
+ _(WSKBDIO_GETDEFAULTKEYREPEAT, WRITE, struct_wskbd_keyrepeat_data_sz);
+ _(WSKBDIO_SETLEDS, READ, sizeof(int));
+ _(WSKBDIO_GETLEDS, WRITE, sizeof(int));
+ _(WSKBDIO_GETMAP, READWRITE, struct_wskbd_map_data_sz);
+ _(WSKBDIO_SETMAP, READ, struct_wskbd_map_data_sz);
+ _(WSKBDIO_GETENCODING, WRITE, sizeof(int));
+ _(WSKBDIO_SETENCODING, READ, sizeof(int));
+ _(WSKBDIO_SETMODE, READ, sizeof(int));
+ _(WSKBDIO_GETMODE, WRITE, sizeof(int));
+ _(WSKBDIO_SETKEYCLICK, READ, sizeof(int));
+ _(WSKBDIO_GETKEYCLICK, WRITE, sizeof(int));
+ _(WSKBDIO_GETSCROLL, WRITE, struct_wskbd_scroll_data_sz);
+ _(WSKBDIO_SETSCROLL, READ, struct_wskbd_scroll_data_sz);
+ _(WSKBDIO_SETVERSION, READ, sizeof(int));
+ _(WSMOUSEIO_GTYPE, WRITE, sizeof(unsigned int));
+ _(WSMOUSEIO_SRES, READ, sizeof(unsigned int));
+ _(WSMOUSEIO_SSCALE, READ, sizeof(unsigned int));
+ _(WSMOUSEIO_SRATE, READ, sizeof(unsigned int));
+ _(WSMOUSEIO_SCALIBCOORDS, READ, struct_wsmouse_calibcoords_sz);
+ _(WSMOUSEIO_GCALIBCOORDS, WRITE, struct_wsmouse_calibcoords_sz);
+ _(WSMOUSEIO_GETID, READWRITE, struct_wsmouse_id_sz);
+ _(WSMOUSEIO_GETREPEAT, WRITE, struct_wsmouse_repeat_sz);
+ _(WSMOUSEIO_SETREPEAT, READ, struct_wsmouse_repeat_sz);
+ _(WSMOUSEIO_SETVERSION, READ, sizeof(int));
+ _(WSDISPLAYIO_GTYPE, WRITE, sizeof(unsigned int));
+ _(WSDISPLAYIO_GINFO, WRITE, struct_wsdisplay_fbinfo_sz);
+ _(WSDISPLAYIO_GETCMAP, READ, struct_wsdisplay_cmap_sz);
+ _(WSDISPLAYIO_PUTCMAP, READ, struct_wsdisplay_cmap_sz);
+ _(WSDISPLAYIO_GVIDEO, WRITE, sizeof(unsigned int));
+ _(WSDISPLAYIO_SVIDEO, READ, sizeof(unsigned int));
+ _(WSDISPLAYIO_GCURPOS, WRITE, struct_wsdisplay_curpos_sz);
+ _(WSDISPLAYIO_SCURPOS, READ, struct_wsdisplay_curpos_sz);
+ _(WSDISPLAYIO_GCURMAX, WRITE, struct_wsdisplay_curpos_sz);
+ _(WSDISPLAYIO_GCURSOR, READWRITE, struct_wsdisplay_cursor_sz);
+ _(WSDISPLAYIO_SCURSOR, READ, struct_wsdisplay_cursor_sz);
+ _(WSDISPLAYIO_GMODE, WRITE, sizeof(unsigned int));
+ _(WSDISPLAYIO_SMODE, READ, sizeof(unsigned int));
+ _(WSDISPLAYIO_LDFONT, READ, struct_wsdisplay_font_sz);
+ _(WSDISPLAYIO_ADDSCREEN, READ, struct_wsdisplay_addscreendata_sz);
+ _(WSDISPLAYIO_DELSCREEN, READ, struct_wsdisplay_delscreendata_sz);
+ _(WSDISPLAYIO_SFONT, READ, struct_wsdisplay_usefontdata_sz);
+ _(_O_WSDISPLAYIO_SETKEYBOARD, READWRITE, struct_wsdisplay_kbddata_sz);
+ _(WSDISPLAYIO_GETPARAM, READWRITE, struct_wsdisplay_param_sz);
+ _(WSDISPLAYIO_SETPARAM, READWRITE, struct_wsdisplay_param_sz);
+ _(WSDISPLAYIO_GETACTIVESCREEN, WRITE, sizeof(int));
+ _(WSDISPLAYIO_GETWSCHAR, READWRITE, struct_wsdisplay_char_sz);
+ _(WSDISPLAYIO_PUTWSCHAR, READWRITE, struct_wsdisplay_char_sz);
+ _(WSDISPLAYIO_DGSCROLL, WRITE, struct_wsdisplay_scroll_data_sz);
+ _(WSDISPLAYIO_DSSCROLL, READ, struct_wsdisplay_scroll_data_sz);
+ _(WSDISPLAYIO_GMSGATTRS, WRITE, struct_wsdisplay_msgattrs_sz);
+ _(WSDISPLAYIO_SMSGATTRS, READ, struct_wsdisplay_msgattrs_sz);
+ _(WSDISPLAYIO_GBORDER, WRITE, sizeof(int));
+ _(WSDISPLAYIO_SBORDER, READ, sizeof(int));
+ _(WSDISPLAYIO_SSPLASH, READ, sizeof(int));
+ _(WSDISPLAYIO_SPROGRESS, READ, sizeof(int));
+ _(WSDISPLAYIO_LINEBYTES, WRITE, sizeof(unsigned int));
+ _(WSDISPLAYIO_SETVERSION, READ, sizeof(int));
+ _(WSMUXIO_ADD_DEVICE, READ, struct_wsmux_device_sz);
+ _(WSMUXIO_REMOVE_DEVICE, READ, struct_wsmux_device_sz);
+ _(WSMUXIO_LIST_DEVICES, READWRITE, struct_wsmux_device_list_sz);
+ _(WSMUXIO_INJECTEVENT, READ, struct_wscons_event_sz);
+ _(WSDISPLAYIO_GET_BUSID, WRITE, struct_wsdisplayio_bus_id_sz);
+ _(WSDISPLAYIO_GET_EDID, READWRITE, struct_wsdisplayio_edid_info_sz);
+ _(WSDISPLAYIO_SET_POLLING, READ, sizeof(int));
+ _(WSDISPLAYIO_GET_FBINFO, READWRITE, struct_wsdisplayio_fbinfo_sz);
+ _(WSDISPLAYIO_DOBLIT, READWRITE, struct_wsdisplayio_blit_sz);
+ _(WSDISPLAYIO_WAITBLIT, READWRITE, struct_wsdisplayio_blit_sz);
+ /* Entries from file: dev/biovar.h */
+ _(BIOCLOCATE, READWRITE, struct_bio_locate_sz);
+ _(BIOCINQ, READWRITE, struct_bioc_inq_sz);
+ _(BIOCDISK_NOVOL, READWRITE, struct_bioc_disk_sz);
+ _(BIOCDISK, READWRITE, struct_bioc_disk_sz);
+ _(BIOCVOL, READWRITE, struct_bioc_vol_sz);
+ _(BIOCALARM, READWRITE, struct_bioc_alarm_sz);
+ _(BIOCBLINK, READWRITE, struct_bioc_blink_sz);
+ _(BIOCSETSTATE, READWRITE, struct_bioc_setstate_sz);
+ _(BIOCVOLOPS, READWRITE, struct_bioc_volops_sz);
+ /* Entries from file: dev/md.h */
+ _(MD_GETCONF, WRITE, struct_md_conf_sz);
+ _(MD_SETCONF, READ, struct_md_conf_sz);
+ /* Entries from file: dev/ccdvar.h */
+ _(CCDIOCSET, READWRITE, struct_ccd_ioctl_sz);
+ _(CCDIOCCLR, READ, struct_ccd_ioctl_sz);
+ /* Entries from file: dev/cgdvar.h */
+ _(CGDIOCSET, READWRITE, struct_cgd_ioctl_sz);
+ _(CGDIOCCLR, READ, struct_cgd_ioctl_sz);
+ _(CGDIOCGET, READWRITE, struct_cgd_user_sz);
+ /* Entries from file: dev/fssvar.h */
+ _(FSSIOCSET, READ, struct_fss_set_sz);
+ _(FSSIOCGET, WRITE, struct_fss_get_sz);
+ _(FSSIOCCLR, NONE, 0);
+ _(FSSIOFSET, READ, sizeof(int));
+ _(FSSIOFGET, WRITE, sizeof(int));
+ /* Entries from file: dev/bluetooth/btdev.h */
+ _(BTDEV_ATTACH, READ, struct_plistref_sz);
+ _(BTDEV_DETACH, READ, struct_plistref_sz);
+ /* Entries from file: dev/bluetooth/btsco.h */
+ _(BTSCO_GETINFO, WRITE, struct_btsco_info_sz);
+ /* Entries from file: dev/kttcpio.h */
+ _(KTTCP_IO_SEND, READWRITE, struct_kttcp_io_args_sz);
+ _(KTTCP_IO_RECV, READWRITE, struct_kttcp_io_args_sz);
+ /* Entries from file: dev/lockstat.h */
+ _(IOC_LOCKSTAT_GVERSION, WRITE, sizeof(int));
+ _(IOC_LOCKSTAT_ENABLE, READ, struct_lsenable_sz);
+ _(IOC_LOCKSTAT_DISABLE, WRITE, struct_lsdisable_sz);
+ /* Entries from file: dev/vndvar.h */
+ _(VNDIOCSET, READWRITE, struct_vnd_ioctl_sz);
+ _(VNDIOCCLR, READ, struct_vnd_ioctl_sz);
+ _(VNDIOCGET, READWRITE, struct_vnd_user_sz);
+ /* Entries from file: dev/spkrio.h */
+ _(SPKRTONE, READ, struct_tone_sz);
+ _(SPKRTUNE, NONE, 0);
+ _(SPKRGETVOL, WRITE, sizeof(unsigned int));
+ _(SPKRSETVOL, READ, sizeof(unsigned int));
+#if defined(__x86_64__)
+ /* Entries from file: dev/nvmm/nvmm_ioctl.h */
+ _(NVMM_IOC_CAPABILITY, WRITE, struct_nvmm_ioc_capability_sz);
+ _(NVMM_IOC_MACHINE_CREATE, READWRITE, struct_nvmm_ioc_machine_create_sz);
+ _(NVMM_IOC_MACHINE_DESTROY, READ, struct_nvmm_ioc_machine_destroy_sz);
+ _(NVMM_IOC_MACHINE_CONFIGURE, READ, struct_nvmm_ioc_machine_configure_sz);
+ _(NVMM_IOC_VCPU_CREATE, READ, struct_nvmm_ioc_vcpu_create_sz);
+ _(NVMM_IOC_VCPU_DESTROY, READ, struct_nvmm_ioc_vcpu_destroy_sz);
+ _(NVMM_IOC_VCPU_CONFIGURE, READ, struct_nvmm_ioc_vcpu_configure_sz);
+ _(NVMM_IOC_VCPU_SETSTATE, READ, struct_nvmm_ioc_vcpu_setstate_sz);
+ _(NVMM_IOC_VCPU_GETSTATE, READ, struct_nvmm_ioc_vcpu_getstate_sz);
+ _(NVMM_IOC_VCPU_INJECT, READ, struct_nvmm_ioc_vcpu_inject_sz);
+ _(NVMM_IOC_VCPU_RUN, READWRITE, struct_nvmm_ioc_vcpu_run_sz);
+ _(NVMM_IOC_GPA_MAP, READ, struct_nvmm_ioc_gpa_map_sz);
+ _(NVMM_IOC_GPA_UNMAP, READ, struct_nvmm_ioc_gpa_unmap_sz);
+ _(NVMM_IOC_HVA_MAP, READ, struct_nvmm_ioc_hva_map_sz);
+ _(NVMM_IOC_HVA_UNMAP, READ, struct_nvmm_ioc_hva_unmap_sz);
+ _(NVMM_IOC_CTL, READ, struct_nvmm_ioc_ctl_sz);
+#endif
+ /* Entries from file: dev/spi/spi_io.h */
+ _(SPI_IOCTL_CONFIGURE, READ, struct_spi_ioctl_configure_sz);
+ _(SPI_IOCTL_TRANSFER, READ, struct_spi_ioctl_transfer_sz);
+ /* Entries from file: fs/autofs/autofs_ioctl.h */
+ _(AUTOFSREQUEST, WRITE, struct_autofs_daemon_request_sz);
+ _(AUTOFSDONE, READ, struct_autofs_daemon_done_sz);
+ /* Entries from file: net/bpf.h */
+ _(BIOCGBLEN, WRITE, sizeof(unsigned int));
+ _(BIOCSBLEN, READWRITE, sizeof(unsigned int));
+ _(BIOCSETF, READ, struct_bpf_program_sz);
+ _(BIOCFLUSH, NONE, 0);
+ _(BIOCPROMISC, NONE, 0);
+ _(BIOCGDLT, WRITE, sizeof(unsigned int));
+ _(BIOCGETIF, WRITE, struct_ifreq_sz);
+ _(BIOCSETIF, READ, struct_ifreq_sz);
+ _(BIOCGSTATS, WRITE, struct_bpf_stat_sz);
+ _(BIOCGSTATSOLD, WRITE, struct_bpf_stat_old_sz);
+ _(BIOCIMMEDIATE, READ, sizeof(unsigned int));
+ _(BIOCVERSION, WRITE, struct_bpf_version_sz);
+ _(BIOCSTCPF, READ, struct_bpf_program_sz);
+ _(BIOCSUDPF, READ, struct_bpf_program_sz);
+ _(BIOCGHDRCMPLT, WRITE, sizeof(unsigned int));
+ _(BIOCSHDRCMPLT, READ, sizeof(unsigned int));
+ _(BIOCSDLT, READ, sizeof(unsigned int));
+ _(BIOCGDLTLIST, READWRITE, struct_bpf_dltlist_sz);
+ _(BIOCGDIRECTION, WRITE, sizeof(unsigned int));
+ _(BIOCSDIRECTION, READ, sizeof(unsigned int));
+ _(BIOCSRTIMEOUT, READ, struct_timeval_sz);
+ _(BIOCGRTIMEOUT, WRITE, struct_timeval_sz);
+ _(BIOCGFEEDBACK, WRITE, sizeof(unsigned int));
+ _(BIOCSFEEDBACK, READ, sizeof(unsigned int));
+ /* Entries from file: net/if_gre.h */
+ _(GRESADDRS, READ, struct_ifreq_sz);
+ _(GRESADDRD, READ, struct_ifreq_sz);
+ _(GREGADDRS, READWRITE, struct_ifreq_sz);
+ _(GREGADDRD, READWRITE, struct_ifreq_sz);
+ _(GRESPROTO, READ, struct_ifreq_sz);
+ _(GREGPROTO, READWRITE, struct_ifreq_sz);
+ _(GRESSOCK, READ, struct_ifreq_sz);
+ _(GREDSOCK, READ, struct_ifreq_sz);
+ /* Entries from file: net/if_ppp.h */
+ _(PPPIOCGRAWIN, WRITE, struct_ppp_rawin_sz);
+ _(PPPIOCGFLAGS, WRITE, sizeof(int));
+ _(PPPIOCSFLAGS, READ, sizeof(int));
+ _(PPPIOCGASYNCMAP, WRITE, sizeof(int));
+ _(PPPIOCSASYNCMAP, READ, sizeof(int));
+ _(PPPIOCGUNIT, WRITE, sizeof(int));
+ _(PPPIOCGRASYNCMAP, WRITE, sizeof(int));
+ _(PPPIOCSRASYNCMAP, READ, sizeof(int));
+ _(PPPIOCGMRU, WRITE, sizeof(int));
+ _(PPPIOCSMRU, READ, sizeof(int));
+ _(PPPIOCSMAXCID, READ, sizeof(int));
+ _(PPPIOCGXASYNCMAP, WRITE, (8 * sizeof(u32)));
+ _(PPPIOCSXASYNCMAP, READ, (8 * sizeof(u32)));
+ _(PPPIOCXFERUNIT, NONE, 0);
+ _(PPPIOCSCOMPRESS, READ, struct_ppp_option_data_sz);
+ _(PPPIOCGNPMODE, READWRITE, struct_npioctl_sz);
+ _(PPPIOCSNPMODE, READ, struct_npioctl_sz);
+ _(PPPIOCGIDLE, WRITE, struct_ppp_idle_sz);
+ _(PPPIOCGMTU, WRITE, sizeof(int));
+ _(PPPIOCSMTU, READ, sizeof(int));
+ _(SIOCGPPPSTATS, READWRITE, struct_ifpppstatsreq_sz);
+ _(SIOCGPPPCSTATS, READWRITE, struct_ifpppcstatsreq_sz);
+ /* Entries from file: net/npf.h */
+ _(IOC_NPF_VERSION, WRITE, sizeof(int));
+ _(IOC_NPF_SWITCH, READ, sizeof(int));
+ _(IOC_NPF_LOAD, READWRITE, struct_nvlist_ref_sz);
+ _(IOC_NPF_TABLE, READ, struct_npf_ioctl_table_sz);
+ _(IOC_NPF_STATS, READ, sizeof(uptr));
+ _(IOC_NPF_SAVE, WRITE, struct_nvlist_ref_sz);
+ _(IOC_NPF_RULE, READWRITE, struct_nvlist_ref_sz);
+ _(IOC_NPF_CONN_LOOKUP, READWRITE, struct_nvlist_ref_sz);
+ _(IOC_NPF_TABLE_REPLACE, READWRITE, struct_nvlist_ref_sz);
+ /* Entries from file: net/if_pppoe.h */
+ _(PPPOESETPARMS, READ, struct_pppoediscparms_sz);
+ _(PPPOEGETPARMS, READWRITE, struct_pppoediscparms_sz);
+ _(PPPOEGETSESSION, READWRITE, struct_pppoeconnectionstate_sz);
+ /* Entries from file: net/if_sppp.h */
+ _(SPPPGETAUTHCFG, READWRITE, struct_spppauthcfg_sz);
+ _(SPPPSETAUTHCFG, READ, struct_spppauthcfg_sz);
+ _(SPPPGETLCPCFG, READWRITE, struct_sppplcpcfg_sz);
+ _(SPPPSETLCPCFG, READ, struct_sppplcpcfg_sz);
+ _(SPPPGETSTATUS, READWRITE, struct_spppstatus_sz);
+ _(SPPPGETSTATUSNCP, READWRITE, struct_spppstatusncp_sz);
+ _(SPPPGETIDLETO, READWRITE, struct_spppidletimeout_sz);
+ _(SPPPSETIDLETO, READ, struct_spppidletimeout_sz);
+ _(SPPPGETAUTHFAILURES, READWRITE, struct_spppauthfailurestats_sz);
+ _(SPPPSETAUTHFAILURE, READ, struct_spppauthfailuresettings_sz);
+ _(SPPPSETDNSOPTS, READ, struct_spppdnssettings_sz);
+ _(SPPPGETDNSOPTS, READWRITE, struct_spppdnssettings_sz);
+ _(SPPPGETDNSADDRS, READWRITE, struct_spppdnsaddrs_sz);
+ _(SPPPSETKEEPALIVE, READ, struct_spppkeepalivesettings_sz);
+ _(SPPPGETKEEPALIVE, READWRITE, struct_spppkeepalivesettings_sz);
+ /* Entries from file: net/if_srt.h */
+ _(SRT_GETNRT, WRITE, sizeof(unsigned int));
+ _(SRT_GETRT, READWRITE, struct_srt_rt_sz);
+ _(SRT_SETRT, READ, struct_srt_rt_sz);
+ _(SRT_DELRT, READ, sizeof(unsigned int));
+ _(SRT_SFLAGS, READ, sizeof(unsigned int));
+ _(SRT_GFLAGS, WRITE, sizeof(unsigned int));
+ _(SRT_SGFLAGS, READWRITE, sizeof(unsigned int));
+ _(SRT_DEBUG, READ, sizeof(uptr));
+ /* Entries from file: net/if_tap.h */
+ _(TAPGIFNAME, WRITE, struct_ifreq_sz);
+ /* Entries from file: net/if_tun.h */
+ _(TUNSDEBUG, READ, sizeof(int));
+ _(TUNGDEBUG, WRITE, sizeof(int));
+ _(TUNSIFMODE, READ, sizeof(int));
+ _(TUNSIFHEAD, READ, sizeof(int));
+ _(TUNGIFHEAD, WRITE, sizeof(int));
+ /* Entries from file: net/pfvar.h */
+ _(DIOCSTART, NONE, 0);
+ _(DIOCSTOP, NONE, 0);
+ _(DIOCADDRULE, READWRITE, struct_pfioc_rule_sz);
+ _(DIOCGETRULES, READWRITE, struct_pfioc_rule_sz);
+ _(DIOCGETRULE, READWRITE, struct_pfioc_rule_sz);
+ _(DIOCSETLCK, READWRITE, sizeof(u32));
+ _(DIOCCLRSTATES, READWRITE, struct_pfioc_state_kill_sz);
+ _(DIOCGETSTATE, READWRITE, struct_pfioc_state_sz);
+ _(DIOCSETSTATUSIF, READWRITE, struct_pfioc_if_sz);
+ _(DIOCGETSTATUS, READWRITE, struct_pf_status_sz);
+ _(DIOCCLRSTATUS, NONE, 0);
+ _(DIOCNATLOOK, READWRITE, struct_pfioc_natlook_sz);
+ _(DIOCSETDEBUG, READWRITE, sizeof(u32));
+ _(DIOCGETSTATES, READWRITE, struct_pfioc_states_sz);
+ _(DIOCCHANGERULE, READWRITE, struct_pfioc_rule_sz);
+ _(DIOCSETTIMEOUT, READWRITE, struct_pfioc_tm_sz);
+ _(DIOCGETTIMEOUT, READWRITE, struct_pfioc_tm_sz);
+ _(DIOCADDSTATE, READWRITE, struct_pfioc_state_sz);
+ _(DIOCCLRRULECTRS, NONE, 0);
+ _(DIOCGETLIMIT, READWRITE, struct_pfioc_limit_sz);
+ _(DIOCSETLIMIT, READWRITE, struct_pfioc_limit_sz);
+ _(DIOCKILLSTATES, READWRITE, struct_pfioc_state_kill_sz);
+ _(DIOCSTARTALTQ, NONE, 0);
+ _(DIOCSTOPALTQ, NONE, 0);
+ _(DIOCADDALTQ, READWRITE, struct_pfioc_altq_sz);
+ _(DIOCGETALTQS, READWRITE, struct_pfioc_altq_sz);
+ _(DIOCGETALTQ, READWRITE, struct_pfioc_altq_sz);
+ _(DIOCCHANGEALTQ, READWRITE, struct_pfioc_altq_sz);
+ _(DIOCGETQSTATS, READWRITE, struct_pfioc_qstats_sz);
+ _(DIOCBEGINADDRS, READWRITE, struct_pfioc_pooladdr_sz);
+ _(DIOCADDADDR, READWRITE, struct_pfioc_pooladdr_sz);
+ _(DIOCGETADDRS, READWRITE, struct_pfioc_pooladdr_sz);
+ _(DIOCGETADDR, READWRITE, struct_pfioc_pooladdr_sz);
+ _(DIOCCHANGEADDR, READWRITE, struct_pfioc_pooladdr_sz);
+ _(DIOCADDSTATES, READWRITE, struct_pfioc_states_sz);
+ _(DIOCGETRULESETS, READWRITE, struct_pfioc_ruleset_sz);
+ _(DIOCGETRULESET, READWRITE, struct_pfioc_ruleset_sz);
+ _(DIOCRCLRTABLES, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRADDTABLES, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRDELTABLES, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRGETTABLES, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRGETTSTATS, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRCLRTSTATS, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRCLRADDRS, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRADDADDRS, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRDELADDRS, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRSETADDRS, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRGETADDRS, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRGETASTATS, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRCLRASTATS, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRTSTADDRS, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRSETTFLAGS, READWRITE, struct_pfioc_table_sz);
+ _(DIOCRINADEFINE, READWRITE, struct_pfioc_table_sz);
+ _(DIOCOSFPFLUSH, NONE, 0);
+ _(DIOCOSFPADD, READWRITE, struct_pf_osfp_ioctl_sz);
+ _(DIOCOSFPGET, READWRITE, struct_pf_osfp_ioctl_sz);
+ _(DIOCXBEGIN, READWRITE, struct_pfioc_trans_sz);
+ _(DIOCXCOMMIT, READWRITE, struct_pfioc_trans_sz);
+ _(DIOCXROLLBACK, READWRITE, struct_pfioc_trans_sz);
+ _(DIOCGETSRCNODES, READWRITE, struct_pfioc_src_nodes_sz);
+ _(DIOCCLRSRCNODES, NONE, 0);
+ _(DIOCSETHOSTID, READWRITE, sizeof(u32));
+ _(DIOCIGETIFACES, READWRITE, struct_pfioc_iface_sz);
+ _(DIOCSETIFFLAG, READWRITE, struct_pfioc_iface_sz);
+ _(DIOCCLRIFFLAG, READWRITE, struct_pfioc_iface_sz);
+ _(DIOCKILLSRCNODES, READWRITE, struct_pfioc_src_node_kill_sz);
+ /* Entries from file: netbt/hci.h */
+ _(SIOCGBTINFO, READWRITE, struct_btreq_sz);
+ _(SIOCGBTINFOA, READWRITE, struct_btreq_sz);
+ _(SIOCNBTINFO, READWRITE, struct_btreq_sz);
+ _(SIOCSBTFLAGS, READWRITE, struct_btreq_sz);
+ _(SIOCSBTPOLICY, READWRITE, struct_btreq_sz);
+ _(SIOCSBTPTYPE, READWRITE, struct_btreq_sz);
+ _(SIOCGBTSTATS, READWRITE, struct_btreq_sz);
+ _(SIOCZBTSTATS, READWRITE, struct_btreq_sz);
+ _(SIOCBTDUMP, READ, struct_btreq_sz);
+ _(SIOCSBTSCOMTU, READWRITE, struct_btreq_sz);
+ _(SIOCGBTFEAT, READWRITE, struct_btreq_sz);
+ /* Entries from file: netinet/ip_nat.h */
+ _(SIOCADNAT, READ, struct_ipfobj_sz);
+ _(SIOCRMNAT, READ, struct_ipfobj_sz);
+ _(SIOCGNATS, READWRITE, struct_ipfobj_sz);
+ _(SIOCGNATL, READWRITE, struct_ipfobj_sz);
+ _(SIOCPURGENAT, READWRITE, struct_ipfobj_sz);
+ /* Entries from file: netinet/sctp_uio.h */
+ _(SIOCCONNECTX, READWRITE, struct_sctp_connectx_addrs_sz);
+ _(SIOCCONNECTXDEL, READWRITE, struct_sctp_connectx_addrs_sz);
+ /* Entries from file: netinet6/in6_var.h */
+ _(SIOCSIFINFO_FLAGS, READWRITE, struct_in6_ndireq_sz);
+ _(SIOCAADDRCTL_POLICY, READ, struct_in6_addrpolicy_sz);
+ _(SIOCDADDRCTL_POLICY, READ, struct_in6_addrpolicy_sz);
+ /* Entries from file: netsmb/smb_dev.h */
+ _(SMBIOC_OPENSESSION, READ, struct_smbioc_ossn_sz);
+ _(SMBIOC_OPENSHARE, READ, struct_smbioc_oshare_sz);
+ _(SMBIOC_REQUEST, READWRITE, struct_smbioc_rq_sz);
+ _(SMBIOC_SETFLAGS, READ, struct_smbioc_flags_sz);
+ _(SMBIOC_LOOKUP, READ, struct_smbioc_lookup_sz);
+ _(SMBIOC_READ, READWRITE, struct_smbioc_rw_sz);
+ _(SMBIOC_WRITE, READWRITE, struct_smbioc_rw_sz);
+ /* Entries from file: sys/agpio.h */
+ _(AGPIOC_INFO, WRITE, struct__agp_info_sz);
+ _(AGPIOC_ACQUIRE, NONE, 0);
+ _(AGPIOC_RELEASE, NONE, 0);
+ _(AGPIOC_SETUP, READ, struct__agp_setup_sz);
+ _(AGPIOC_ALLOCATE, READWRITE, struct__agp_allocate_sz);
+ _(AGPIOC_DEALLOCATE, READ, sizeof(int));
+ _(AGPIOC_BIND, READ, struct__agp_bind_sz);
+ _(AGPIOC_UNBIND, READ, struct__agp_unbind_sz);
+ /* Entries from file: sys/audioio.h */
+ _(AUDIO_GETINFO, WRITE, struct_audio_info_sz);
+ _(AUDIO_SETINFO, READWRITE, struct_audio_info_sz);
+ _(AUDIO_DRAIN, NONE, 0);
+ _(AUDIO_FLUSH, NONE, 0);
+ _(AUDIO_WSEEK, WRITE, sizeof(unsigned long));
+ _(AUDIO_RERROR, WRITE, sizeof(int));
+ _(AUDIO_GETDEV, WRITE, struct_audio_device_sz);
+ _(AUDIO_GETENC, READWRITE, struct_audio_encoding_sz);
+ _(AUDIO_GETFD, WRITE, sizeof(int));
+ _(AUDIO_SETFD, READWRITE, sizeof(int));
+ _(AUDIO_PERROR, WRITE, sizeof(int));
+ _(AUDIO_GETIOFFS, WRITE, struct_audio_offset_sz);
+ _(AUDIO_GETOOFFS, WRITE, struct_audio_offset_sz);
+ _(AUDIO_GETPROPS, WRITE, sizeof(int));
+ _(AUDIO_GETBUFINFO, WRITE, struct_audio_info_sz);
+ _(AUDIO_SETCHAN, READ, sizeof(int));
+ _(AUDIO_GETCHAN, WRITE, sizeof(int));
+ _(AUDIO_QUERYFORMAT, READWRITE, struct_audio_format_query_sz);
+ _(AUDIO_GETFORMAT, WRITE, struct_audio_info_sz);
+ _(AUDIO_SETFORMAT, READ, struct_audio_info_sz);
+ _(AUDIO_MIXER_READ, READWRITE, struct_mixer_ctrl_sz);
+ _(AUDIO_MIXER_WRITE, READWRITE, struct_mixer_ctrl_sz);
+ _(AUDIO_MIXER_DEVINFO, READWRITE, struct_mixer_devinfo_sz);
+ /* Entries from file: sys/ataio.h */
+ _(ATAIOCCOMMAND, READWRITE, struct_atareq_sz);
+ _(ATABUSIOSCAN, READ, struct_atabusioscan_args_sz);
+ _(ATABUSIORESET, NONE, 0);
+ _(ATABUSIODETACH, READ, struct_atabusiodetach_args_sz);
+ /* Entries from file: sys/cdio.h */
+ _(CDIOCPLAYTRACKS, READ, struct_ioc_play_track_sz);
+ _(CDIOCPLAYBLOCKS, READ, struct_ioc_play_blocks_sz);
+ _(CDIOCREADSUBCHANNEL, READWRITE, struct_ioc_read_subchannel_sz);
+ _(CDIOREADTOCHEADER, WRITE, struct_ioc_toc_header_sz);
+ _(CDIOREADTOCENTRIES, READWRITE, struct_ioc_read_toc_entry_sz);
+ _(CDIOREADMSADDR, READWRITE, sizeof(int));
+ _(CDIOCSETPATCH, READ, struct_ioc_patch_sz);
+ _(CDIOCGETVOL, WRITE, struct_ioc_vol_sz);
+ _(CDIOCSETVOL, READ, struct_ioc_vol_sz);
+ _(CDIOCSETMONO, NONE, 0);
+ _(CDIOCSETSTEREO, NONE, 0);
+ _(CDIOCSETMUTE, NONE, 0);
+ _(CDIOCSETLEFT, NONE, 0);
+ _(CDIOCSETRIGHT, NONE, 0);
+ _(CDIOCSETDEBUG, NONE, 0);
+ _(CDIOCCLRDEBUG, NONE, 0);
+ _(CDIOCPAUSE, NONE, 0);
+ _(CDIOCRESUME, NONE, 0);
+ _(CDIOCRESET, NONE, 0);
+ _(CDIOCSTART, NONE, 0);
+ _(CDIOCSTOP, NONE, 0);
+ _(CDIOCEJECT, NONE, 0);
+ _(CDIOCALLOW, NONE, 0);
+ _(CDIOCPREVENT, NONE, 0);
+ _(CDIOCCLOSE, NONE, 0);
+ _(CDIOCPLAYMSF, READ, struct_ioc_play_msf_sz);
+ _(CDIOCLOADUNLOAD, READ, struct_ioc_load_unload_sz);
+ /* Entries from file: sys/chio.h */
+ _(CHIOMOVE, READ, struct_changer_move_request_sz);
+ _(CHIOEXCHANGE, READ, struct_changer_exchange_request_sz);
+ _(CHIOPOSITION, READ, struct_changer_position_request_sz);
+ _(CHIOSPICKER, READ, sizeof(int));
+ _(CHIOGPARAMS, WRITE, struct_changer_params_sz);
+ _(CHIOIELEM, NONE, 0);
+ _(OCHIOGSTATUS, READ, struct_ochanger_element_status_request_sz);
+ _(CHIOGSTATUS, READ, struct_changer_element_status_request_sz);
+ _(CHIOSVOLTAG, READ, struct_changer_set_voltag_request_sz);
+ /* Entries from file: sys/clockctl.h */
+ _(CLOCKCTL_SETTIMEOFDAY, READ, struct_clockctl_settimeofday_sz);
+ _(CLOCKCTL_ADJTIME, READWRITE, struct_clockctl_adjtime_sz);
+ _(CLOCKCTL_CLOCK_SETTIME, READ, struct_clockctl_clock_settime_sz);
+ _(CLOCKCTL_NTP_ADJTIME, READWRITE, struct_clockctl_ntp_adjtime_sz);
+ /* Entries from file: sys/cpuio.h */
+ _(IOC_CPU_SETSTATE, READ, struct_cpustate_sz);
+ _(IOC_CPU_GETSTATE, READWRITE, struct_cpustate_sz);
+ _(IOC_CPU_GETCOUNT, WRITE, sizeof(int));
+ _(IOC_CPU_MAPID, READWRITE, sizeof(int));
+ _(IOC_CPU_UCODE_GET_VERSION, READWRITE, struct_cpu_ucode_version_sz);
+ _(IOC_CPU_UCODE_APPLY, READ, struct_cpu_ucode_sz);
+ /* Entries from file: sys/dkio.h */
+ _(DIOCGDINFO, WRITE, struct_disklabel_sz);
+ _(DIOCSDINFO, READ, struct_disklabel_sz);
+ _(DIOCWDINFO, READ, 0);
+ _(DIOCRFORMAT, READWRITE, struct_format_op_sz);
+ _(DIOCWFORMAT, READWRITE, struct_format_op_sz);
+ _(DIOCSSTEP, READ, sizeof(int));
+ _(DIOCSRETRIES, READ, sizeof(int));
+ _(DIOCKLABEL, READ, sizeof(int));
+ _(DIOCWLABEL, READ, sizeof(int));
+ _(DIOCSBAD, READ, struct_dkbad_sz);
+ _(DIOCEJECT, READ, sizeof(int));
+ _(ODIOCEJECT, NONE, 0);
+ _(DIOCLOCK, READ, sizeof(int));
+ _(DIOCGDEFLABEL, WRITE, struct_disklabel_sz);
+ _(DIOCCLRLABEL, NONE, 0);
+ _(DIOCGCACHE, WRITE, sizeof(int));
+ _(DIOCSCACHE, READ, sizeof(int));
+ _(DIOCCACHESYNC, READ, sizeof(int));
+ _(DIOCBSLIST, READWRITE, struct_disk_badsecinfo_sz);
+ _(DIOCBSFLUSH, NONE, 0);
+ _(DIOCAWEDGE, READWRITE, struct_dkwedge_info_sz);
+ _(DIOCGWEDGEINFO, WRITE, struct_dkwedge_info_sz);
+ _(DIOCDWEDGE, READ, struct_dkwedge_info_sz);
+ _(DIOCLWEDGES, READWRITE, struct_dkwedge_list_sz);
+ _(DIOCGSTRATEGY, WRITE, struct_disk_strategy_sz);
+ _(DIOCSSTRATEGY, READ, struct_disk_strategy_sz);
+ _(DIOCGDISKINFO, WRITE, struct_plistref_sz);
+ _(DIOCTUR, WRITE, sizeof(int));
+ _(DIOCMWEDGES, WRITE, sizeof(int));
+ _(DIOCGSECTORSIZE, WRITE, sizeof(unsigned int));
+ _(DIOCGMEDIASIZE, WRITE, sizeof(uptr));
+ _(DIOCRMWEDGES, WRITE, sizeof(int));
+ /* Entries from file: sys/drvctlio.h */
+ _(DRVDETACHDEV, READ, struct_devdetachargs_sz);
+ _(DRVRESCANBUS, READ, struct_devrescanargs_sz);
+ _(DRVCTLCOMMAND, READWRITE, struct_plistref_sz);
+ _(DRVRESUMEDEV, READ, struct_devpmargs_sz);
+ _(DRVLISTDEV, READWRITE, struct_devlistargs_sz);
+ _(DRVGETEVENT, WRITE, struct_plistref_sz);
+ _(DRVSUSPENDDEV, READ, struct_devpmargs_sz);
+ /* Entries from file: sys/dvdio.h */
+ _(DVD_READ_STRUCT, READWRITE, union_dvd_struct_sz);
+ _(DVD_WRITE_STRUCT, READWRITE, union_dvd_struct_sz);
+ _(DVD_AUTH, READWRITE, union_dvd_authinfo_sz);
+ /* Entries from file: sys/envsys.h */
+ _(ENVSYS_GETDICTIONARY, READWRITE, struct_plistref_sz);
+ _(ENVSYS_SETDICTIONARY, READWRITE, struct_plistref_sz);
+ _(ENVSYS_REMOVEPROPS, READWRITE, struct_plistref_sz);
+ _(ENVSYS_GTREDATA, READWRITE, struct_envsys_tre_data_sz);
+ _(ENVSYS_GTREINFO, READWRITE, struct_envsys_basic_info_sz);
+ /* Entries from file: sys/event.h */
+ _(KFILTER_BYFILTER, READWRITE, struct_kfilter_mapping_sz);
+ _(KFILTER_BYNAME, READWRITE, struct_kfilter_mapping_sz);
+ /* Entries from file: sys/fdio.h */
+ _(FDIOCGETOPTS, WRITE, 0);
+ _(FDIOCSETOPTS, READ, sizeof(int));
+ _(FDIOCSETFORMAT, READ, struct_fdformat_parms_sz);
+ _(FDIOCGETFORMAT, WRITE, struct_fdformat_parms_sz);
+ _(FDIOCFORMAT_TRACK, READ, struct_fdformat_cmd_sz);
+ /* Entries from file: sys/filio.h */
+ _(FIOCLEX, NONE, 0);
+ _(FIONCLEX, NONE, 0);
+ _(FIOSEEKDATA, READWRITE, sizeof(uptr));
+ _(FIOSEEKHOLE, READWRITE, sizeof(uptr));
+ _(FIONREAD, WRITE, sizeof(int));
+ _(FIONBIO, READ, sizeof(int));
+ _(FIOASYNC, READ, sizeof(int));
+ _(FIOSETOWN, READ, sizeof(int));
+ _(FIOGETOWN, WRITE, sizeof(int));
+ _(OFIOGETBMAP, READWRITE, sizeof(u32));
+ _(FIOGETBMAP, READWRITE, sizeof(u64));
+ _(FIONWRITE, WRITE, sizeof(int));
+ _(FIONSPACE, WRITE, sizeof(int));
+ /* Entries from file: sys/gpio.h */
+ _(GPIOINFO, WRITE, struct_gpio_info_sz);
+ _(GPIOSET, READWRITE, struct_gpio_set_sz);
+ _(GPIOUNSET, READWRITE, struct_gpio_set_sz);
+ _(GPIOREAD, READWRITE, struct_gpio_req_sz);
+ _(GPIOWRITE, READWRITE, struct_gpio_req_sz);
+ _(GPIOTOGGLE, READWRITE, struct_gpio_req_sz);
+ _(GPIOATTACH, READWRITE, struct_gpio_attach_sz);
+ /* Entries from file: sys/ioctl.h */
+ _(PTIOCNETBSD, READ, struct_ioctl_pt_sz);
+ _(PTIOCSUNOS, READ, struct_ioctl_pt_sz);
+ _(PTIOCLINUX, READ, struct_ioctl_pt_sz);
+ _(PTIOCFREEBSD, READ, struct_ioctl_pt_sz);
+ _(PTIOCULTRIX, READ, struct_ioctl_pt_sz);
+ /* Entries from file: sys/ioctl_compat.h */
+ _(TIOCHPCL, NONE, 0);
+ _(TIOCGETP, WRITE, struct_sgttyb_sz);
+ _(TIOCSETP, READ, struct_sgttyb_sz);
+ _(TIOCSETN, READ, 0);
+ _(TIOCSETC, READ, struct_tchars_sz);
+ _(TIOCGETC, WRITE, struct_tchars_sz);
+ _(TIOCLBIS, READ, sizeof(int));
+ _(TIOCLBIC, READ, sizeof(int));
+ _(TIOCLSET, READ, sizeof(int));
+ _(TIOCLGET, WRITE, sizeof(int));
+ _(TIOCSLTC, READ, struct_ltchars_sz);
+ _(TIOCGLTC, WRITE, struct_ltchars_sz);
+ _(OTIOCCONS, NONE, 0);
+ /* Entries from file: sys/joystick.h */
+ _(JOY_SETTIMEOUT, READ, sizeof(int));
+ _(JOY_GETTIMEOUT, WRITE, sizeof(int));
+ _(JOY_SET_X_OFFSET, READ, sizeof(int));
+ _(JOY_SET_Y_OFFSET, READ, sizeof(int));
+ _(JOY_GET_Y_OFFSET, WRITE, sizeof(int));
+ /* Entries from file: sys/ksyms.h */
+ _(OKIOCGSYMBOL, READ, struct_ksyms_ogsymbol_sz);
+ _(OKIOCGVALUE, READ, struct_ksyms_ogsymbol_sz);
+ _(KIOCGSIZE, WRITE, sizeof(int));
+ _(KIOCGVALUE, READWRITE, struct_ksyms_gvalue_sz);
+ _(KIOCGSYMBOL, READWRITE, struct_ksyms_gsymbol_sz);
+ /* Entries from file: sys/lua.h */
+ _(LUAINFO, READWRITE, struct_lua_info_sz);
+ _(LUACREATE, READWRITE, struct_lua_create_sz);
+ _(LUADESTROY, READWRITE, struct_lua_create_sz);
+ _(LUAREQUIRE, READWRITE, struct_lua_require_sz);
+ _(LUALOAD, READWRITE, struct_lua_load_sz);
+ /* Entries from file: sys/midiio.h */
+ _(MIDI_PRETIME, READWRITE, sizeof(int));
+ _(MIDI_MPUMODE, READWRITE, sizeof(int));
+ _(MIDI_MPUCMD, READWRITE, struct_mpu_command_rec_sz);
+ _(SEQUENCER_RESET, NONE, 0);
+ _(SEQUENCER_SYNC, NONE, 0);
+ _(SEQUENCER_INFO, READWRITE, struct_synth_info_sz);
+ _(SEQUENCER_CTRLRATE, READWRITE, sizeof(int));
+ _(SEQUENCER_GETOUTCOUNT, WRITE, sizeof(int));
+ _(SEQUENCER_GETINCOUNT, WRITE, sizeof(int));
+ _(SEQUENCER_RESETSAMPLES, READ, sizeof(int));
+ _(SEQUENCER_NRSYNTHS, WRITE, sizeof(int));
+ _(SEQUENCER_NRMIDIS, WRITE, sizeof(int));
+ _(SEQUENCER_THRESHOLD, READ, sizeof(int));
+ _(SEQUENCER_MEMAVL, READWRITE, sizeof(int));
+ _(SEQUENCER_PANIC, NONE, 0);
+ _(SEQUENCER_OUTOFBAND, READ, struct_seq_event_rec_sz);
+ _(SEQUENCER_GETTIME, WRITE, sizeof(int));
+ _(SEQUENCER_TMR_TIMEBASE, READWRITE, sizeof(int));
+ _(SEQUENCER_TMR_START, NONE, 0);
+ _(SEQUENCER_TMR_STOP, NONE, 0);
+ _(SEQUENCER_TMR_CONTINUE, NONE, 0);
+ _(SEQUENCER_TMR_TEMPO, READWRITE, sizeof(int));
+ _(SEQUENCER_TMR_SOURCE, READWRITE, sizeof(int));
+ _(SEQUENCER_TMR_METRONOME, READ, sizeof(int));
+ _(SEQUENCER_TMR_SELECT, READ, sizeof(int));
+ /* Entries from file: sys/mtio.h */
+ _(MTIOCTOP, READ, struct_mtop_sz);
+ _(MTIOCGET, WRITE, struct_mtget_sz);
+ _(MTIOCIEOT, NONE, 0);
+ _(MTIOCEEOT, NONE, 0);
+ _(MTIOCRDSPOS, WRITE, sizeof(u32));
+ _(MTIOCRDHPOS, WRITE, sizeof(u32));
+ _(MTIOCSLOCATE, READ, sizeof(u32));
+ _(MTIOCHLOCATE, READ, sizeof(u32));
+ /* Entries from file: sys/power.h */
+ _(POWER_EVENT_RECVDICT, READWRITE, struct_plistref_sz);
+ _(POWER_IOC_GET_TYPE, WRITE, struct_power_type_sz);
+ /* Entries from file: sys/radioio.h */
+ _(RIOCGINFO, WRITE, struct_radio_info_sz);
+ _(RIOCSINFO, READWRITE, struct_radio_info_sz);
+ _(RIOCSSRCH, READ, sizeof(int));
+ /* Entries from file: sys/rndio.h */
+ _(RNDGETENTCNT, WRITE, sizeof(u32));
+ _(RNDGETSRCNUM, READWRITE, struct_rndstat_sz);
+ _(RNDGETSRCNAME, READWRITE, struct_rndstat_name_sz);
+ _(RNDCTL, READ, struct_rndctl_sz);
+ _(RNDADDDATA, READ, struct_rnddata_sz);
+ _(RNDGETPOOLSTAT, WRITE, struct_rndpoolstat_sz);
+ _(RNDGETESTNUM, READWRITE, struct_rndstat_est_sz);
+ _(RNDGETESTNAME, READWRITE, struct_rndstat_est_name_sz);
+ /* Entries from file: sys/scanio.h */
+ _(SCIOCGET, WRITE, struct_scan_io_sz);
+ _(SCIOCSET, READ, struct_scan_io_sz);
+ _(SCIOCRESTART, NONE, 0);
+ /* Entries from file: sys/scsiio.h */
+ _(SCIOCCOMMAND, READWRITE, struct_scsireq_sz);
+ _(SCIOCDEBUG, READ, sizeof(int));
+ _(SCIOCIDENTIFY, WRITE, struct_scsi_addr_sz);
+ _(OSCIOCIDENTIFY, WRITE, struct_oscsi_addr_sz);
+ _(SCIOCDECONFIG, NONE, 0);
+ _(SCIOCRECONFIG, NONE, 0);
+ _(SCIOCRESET, NONE, 0);
+ _(SCBUSIOSCAN, READ, struct_scbusioscan_args_sz);
+ _(SCBUSIORESET, NONE, 0);
+ _(SCBUSIODETACH, READ, struct_scbusiodetach_args_sz);
+ _(SCBUSACCEL, READ, struct_scbusaccel_args_sz);
+ /* Entries from file: sys/sockio.h */
+ _(SIOCSHIWAT, READ, sizeof(int));
+ _(SIOCGHIWAT, WRITE, sizeof(int));
+ _(SIOCSLOWAT, READ, sizeof(int));
+ _(SIOCGLOWAT, WRITE, sizeof(int));
+ _(SIOCATMARK, WRITE, sizeof(int));
+ _(SIOCSPGRP, READ, sizeof(int));
+ _(SIOCGPGRP, WRITE, sizeof(int));
+ _(SIOCPEELOFF, READWRITE, sizeof(int));
+ _(SIOCADDRT, READ, struct_ortentry_sz);
+ _(SIOCDELRT, READ, struct_ortentry_sz);
+ _(SIOCSIFADDR, READ, struct_ifreq_sz);
+ _(SIOCGIFADDR, READWRITE, struct_ifreq_sz);
+ _(SIOCSIFDSTADDR, READ, struct_ifreq_sz);
+ _(SIOCGIFDSTADDR, READWRITE, struct_ifreq_sz);
+ _(SIOCSIFFLAGS, READ, struct_ifreq_sz);
+ _(SIOCGIFFLAGS, READWRITE, struct_ifreq_sz);
+ _(SIOCGIFBRDADDR, READWRITE, struct_ifreq_sz);
+ _(SIOCSIFBRDADDR, READ, struct_ifreq_sz);
+ _(SIOCGIFCONF, READWRITE, struct_ifconf_sz);
+ _(SIOCGIFNETMASK, READWRITE, struct_ifreq_sz);
+ _(SIOCSIFNETMASK, READ, struct_ifreq_sz);
+ _(SIOCGIFMETRIC, READWRITE, struct_ifreq_sz);
+ _(SIOCSIFMETRIC, READ, struct_ifreq_sz);
+ _(SIOCDIFADDR, READ, struct_ifreq_sz);
+ _(SIOCAIFADDR, READ, struct_ifaliasreq_sz);
+ _(SIOCGIFALIAS, READWRITE, struct_ifaliasreq_sz);
+ _(SIOCGIFAFLAG_IN, READWRITE, struct_ifreq_sz);
+ _(SIOCALIFADDR, READ, struct_if_laddrreq_sz);
+ _(SIOCGLIFADDR, READWRITE, struct_if_laddrreq_sz);
+ _(SIOCDLIFADDR, READ, struct_if_laddrreq_sz);
+ _(SIOCSIFADDRPREF, READ, struct_if_addrprefreq_sz);
+ _(SIOCGIFADDRPREF, READWRITE, struct_if_addrprefreq_sz);
+ _(SIOCADDMULTI, READ, struct_ifreq_sz);
+ _(SIOCDELMULTI, READ, struct_ifreq_sz);
+ _(SIOCGETVIFCNT, READWRITE, struct_sioc_vif_req_sz);
+ _(SIOCGETSGCNT, READWRITE, struct_sioc_sg_req_sz);
+ _(SIOCSIFMEDIA, READWRITE, struct_ifreq_sz);
+ _(SIOCGIFMEDIA, READWRITE, struct_ifmediareq_sz);
+ _(SIOCSIFGENERIC, READ, struct_ifreq_sz);
+ _(SIOCGIFGENERIC, READWRITE, struct_ifreq_sz);
+ _(SIOCSIFPHYADDR, READ, struct_ifaliasreq_sz);
+ _(SIOCGIFPSRCADDR, READWRITE, struct_ifreq_sz);
+ _(SIOCGIFPDSTADDR, READWRITE, struct_ifreq_sz);
+ _(SIOCDIFPHYADDR, READ, struct_ifreq_sz);
+ _(SIOCSLIFPHYADDR, READ, struct_if_laddrreq_sz);
+ _(SIOCGLIFPHYADDR, READWRITE, struct_if_laddrreq_sz);
+ _(SIOCSIFMTU, READ, struct_ifreq_sz);
+ _(SIOCGIFMTU, READWRITE, struct_ifreq_sz);
+ _(SIOCSDRVSPEC, READ, struct_ifdrv_sz);
+ _(SIOCGDRVSPEC, READWRITE, struct_ifdrv_sz);
+ _(SIOCIFCREATE, READ, struct_ifreq_sz);
+ _(SIOCIFDESTROY, READ, struct_ifreq_sz);
+ _(SIOCIFGCLONERS, READWRITE, struct_if_clonereq_sz);
+ _(SIOCGIFDLT, READWRITE, struct_ifreq_sz);
+ _(SIOCGIFCAP, READWRITE, struct_ifcapreq_sz);
+ _(SIOCSIFCAP, READ, struct_ifcapreq_sz);
+ _(SIOCSVH, READWRITE, struct_ifreq_sz);
+ _(SIOCGVH, READWRITE, struct_ifreq_sz);
+ _(SIOCINITIFADDR, READWRITE, struct_ifaddr_sz);
+ _(SIOCGIFDATA, READWRITE, struct_ifdatareq_sz);
+ _(SIOCZIFDATA, READWRITE, struct_ifdatareq_sz);
+ _(SIOCGLINKSTR, READWRITE, struct_ifdrv_sz);
+ _(SIOCSLINKSTR, READ, struct_ifdrv_sz);
+ _(SIOCGETHERCAP, READWRITE, struct_eccapreq_sz);
+ _(SIOCGIFINDEX, READWRITE, struct_ifreq_sz);
+ _(SIOCSETHERCAP, READ, struct_eccapreq_sz);
+ _(SIOCSIFDESCR, READ, struct_ifreq_sz);
+ _(SIOCGIFDESCR, READWRITE, struct_ifreq_sz);
+ _(SIOCGUMBINFO, READWRITE, struct_ifreq_sz);
+ _(SIOCSUMBPARAM, READ, struct_ifreq_sz);
+ _(SIOCGUMBPARAM, READWRITE, struct_ifreq_sz);
+ _(SIOCSETPFSYNC, READ, struct_ifreq_sz);
+ _(SIOCGETPFSYNC, READWRITE, struct_ifreq_sz);
+ /* Entries from file: sys/timepps.h */
+ _(PPS_IOC_CREATE, NONE, 0);
+ _(PPS_IOC_DESTROY, NONE, 0);
+ _(PPS_IOC_SETPARAMS, READ, struct_pps_params_sz);
+ _(PPS_IOC_GETPARAMS, WRITE, struct_pps_params_sz);
+ _(PPS_IOC_GETCAP, WRITE, sizeof(int));
+ _(PPS_IOC_FETCH, READWRITE, struct_pps_info_sz);
+ _(PPS_IOC_KCBIND, READ, sizeof(int));
+ /* Entries from file: sys/ttycom.h */
+ _(TIOCEXCL, NONE, 0);
+ _(TIOCNXCL, NONE, 0);
+ _(TIOCFLUSH, READ, sizeof(int));
+ _(TIOCGETA, WRITE, struct_termios_sz);
+ _(TIOCSETA, READ, struct_termios_sz);
+ _(TIOCSETAW, READ, 0);
+ _(TIOCSETAF, READ, 0);
+ _(TIOCGETD, WRITE, sizeof(int));
+ _(TIOCSETD, READ, sizeof(int));
+ _(TIOCGLINED, WRITE, (32 * sizeof(char)));
+ _(TIOCSLINED, READ, (32 * sizeof(char)));
+ _(TIOCSBRK, NONE, 0);
+ _(TIOCCBRK, NONE, 0);
+ _(TIOCSDTR, NONE, 0);
+ _(TIOCCDTR, NONE, 0);
+ _(TIOCGPGRP, WRITE, sizeof(int));
+ _(TIOCSPGRP, READ, sizeof(int));
+ _(TIOCOUTQ, WRITE, sizeof(int));
+ _(TIOCSTI, READ, sizeof(char));
+ _(TIOCNOTTY, NONE, 0);
+ _(TIOCPKT, READ, sizeof(int));
+ _(TIOCSTOP, NONE, 0);
+ _(TIOCSTART, NONE, 0);
+ _(TIOCMSET, READ, sizeof(int));
+ _(TIOCMBIS, READ, sizeof(int));
+ _(TIOCMBIC, READ, sizeof(int));
+ _(TIOCMGET, WRITE, sizeof(int));
+ _(TIOCREMOTE, READ, sizeof(int));
+ _(TIOCGWINSZ, WRITE, struct_winsize_sz);
+ _(TIOCSWINSZ, READ, struct_winsize_sz);
+ _(TIOCUCNTL, READ, sizeof(int));
+ _(TIOCSTAT, READ, sizeof(int));
+ _(TIOCGSID, WRITE, sizeof(int));
+ _(TIOCCONS, READ, sizeof(int));
+ _(TIOCSCTTY, NONE, 0);
+ _(TIOCEXT, READ, sizeof(int));
+ _(TIOCSIG, NONE, 0);
+ _(TIOCDRAIN, NONE, 0);
+ _(TIOCGFLAGS, WRITE, sizeof(int));
+ _(TIOCSFLAGS, READ, sizeof(int));
+ _(TIOCDCDTIMESTAMP, WRITE, struct_timeval_sz);
+ _(TIOCRCVFRAME, READ, sizeof(uptr));
+ _(TIOCXMTFRAME, READ, sizeof(uptr));
+ _(TIOCPTMGET, WRITE, struct_ptmget_sz);
+ _(TIOCGRANTPT, NONE, 0);
+ _(TIOCPTSNAME, WRITE, struct_ptmget_sz);
+ _(TIOCSQSIZE, READ, sizeof(int));
+ _(TIOCGQSIZE, WRITE, sizeof(int));
+ /* Entries from file: sys/verified_exec.h */
+ _(VERIEXEC_LOAD, READ, struct_plistref_sz);
+ _(VERIEXEC_TABLESIZE, READ, struct_plistref_sz);
+ _(VERIEXEC_DELETE, READ, struct_plistref_sz);
+ _(VERIEXEC_QUERY, READWRITE, struct_plistref_sz);
+ _(VERIEXEC_DUMP, WRITE, struct_plistref_sz);
+ _(VERIEXEC_FLUSH, NONE, 0);
+ /* Entries from file: sys/videoio.h */
+ _(VIDIOC_QUERYCAP, WRITE, struct_v4l2_capability_sz);
+ _(VIDIOC_RESERVED, NONE, 0);
+ _(VIDIOC_ENUM_FMT, READWRITE, struct_v4l2_fmtdesc_sz);
+ _(VIDIOC_G_FMT, READWRITE, struct_v4l2_format_sz);
+ _(VIDIOC_S_FMT, READWRITE, struct_v4l2_format_sz);
+ _(VIDIOC_REQBUFS, READWRITE, struct_v4l2_requestbuffers_sz);
+ _(VIDIOC_QUERYBUF, READWRITE, struct_v4l2_buffer_sz);
+ _(VIDIOC_G_FBUF, WRITE, struct_v4l2_framebuffer_sz);
+ _(VIDIOC_S_FBUF, READ, struct_v4l2_framebuffer_sz);
+ _(VIDIOC_OVERLAY, READ, sizeof(int));
+ _(VIDIOC_QBUF, READWRITE, struct_v4l2_buffer_sz);
+ _(VIDIOC_DQBUF, READWRITE, struct_v4l2_buffer_sz);
+ _(VIDIOC_STREAMON, READ, sizeof(int));
+ _(VIDIOC_STREAMOFF, READ, sizeof(int));
+ _(VIDIOC_G_PARM, READWRITE, struct_v4l2_streamparm_sz);
+ _(VIDIOC_S_PARM, READWRITE, struct_v4l2_streamparm_sz);
+ _(VIDIOC_G_STD, WRITE, sizeof(u64));
+ _(VIDIOC_S_STD, READ, sizeof(u64));
+ _(VIDIOC_ENUMSTD, READWRITE, struct_v4l2_standard_sz);
+ _(VIDIOC_ENUMINPUT, READWRITE, struct_v4l2_input_sz);
+ _(VIDIOC_G_CTRL, READWRITE, struct_v4l2_control_sz);
+ _(VIDIOC_S_CTRL, READWRITE, struct_v4l2_control_sz);
+ _(VIDIOC_G_TUNER, READWRITE, struct_v4l2_tuner_sz);
+ _(VIDIOC_S_TUNER, READ, struct_v4l2_tuner_sz);
+ _(VIDIOC_G_AUDIO, WRITE, struct_v4l2_audio_sz);
+ _(VIDIOC_S_AUDIO, READ, struct_v4l2_audio_sz);
+ _(VIDIOC_QUERYCTRL, READWRITE, struct_v4l2_queryctrl_sz);
+ _(VIDIOC_QUERYMENU, READWRITE, struct_v4l2_querymenu_sz);
+ _(VIDIOC_G_INPUT, WRITE, sizeof(int));
+ _(VIDIOC_S_INPUT, READWRITE, sizeof(int));
+ _(VIDIOC_G_OUTPUT, WRITE, sizeof(int));
+ _(VIDIOC_S_OUTPUT, READWRITE, sizeof(int));
+ _(VIDIOC_ENUMOUTPUT, READWRITE, struct_v4l2_output_sz);
+ _(VIDIOC_G_AUDOUT, WRITE, struct_v4l2_audioout_sz);
+ _(VIDIOC_S_AUDOUT, READ, struct_v4l2_audioout_sz);
+ _(VIDIOC_G_MODULATOR, READWRITE, struct_v4l2_modulator_sz);
+ _(VIDIOC_S_MODULATOR, READ, struct_v4l2_modulator_sz);
+ _(VIDIOC_G_FREQUENCY, READWRITE, struct_v4l2_frequency_sz);
+ _(VIDIOC_S_FREQUENCY, READ, struct_v4l2_frequency_sz);
+ _(VIDIOC_CROPCAP, READWRITE, struct_v4l2_cropcap_sz);
+ _(VIDIOC_G_CROP, READWRITE, struct_v4l2_crop_sz);
+ _(VIDIOC_S_CROP, READ, struct_v4l2_crop_sz);
+ _(VIDIOC_G_JPEGCOMP, WRITE, struct_v4l2_jpegcompression_sz);
+ _(VIDIOC_S_JPEGCOMP, READ, struct_v4l2_jpegcompression_sz);
+ _(VIDIOC_QUERYSTD, WRITE, sizeof(u64));
+ _(VIDIOC_TRY_FMT, READWRITE, struct_v4l2_format_sz);
+ _(VIDIOC_ENUMAUDIO, READWRITE, struct_v4l2_audio_sz);
+ _(VIDIOC_ENUMAUDOUT, READWRITE, struct_v4l2_audioout_sz);
+ _(VIDIOC_G_PRIORITY, WRITE, enum_v4l2_priority_sz);
+ _(VIDIOC_S_PRIORITY, READ, enum_v4l2_priority_sz);
+ _(VIDIOC_ENUM_FRAMESIZES, READWRITE, struct_v4l2_frmsizeenum_sz);
+ _(VIDIOC_ENUM_FRAMEINTERVALS, READWRITE, struct_v4l2_frmivalenum_sz);
+ /* Entries from file: sys/wdog.h */
+ _(WDOGIOC_GMODE, READWRITE, struct_wdog_mode_sz);
+ _(WDOGIOC_SMODE, READ, struct_wdog_mode_sz);
+ _(WDOGIOC_WHICH, WRITE, struct_wdog_mode_sz);
+ _(WDOGIOC_TICKLE, NONE, 0);
+ _(WDOGIOC_GTICKLER, WRITE, sizeof(int));
+ _(WDOGIOC_GWDOGS, READWRITE, struct_wdog_conf_sz);
+ /* Entries from file: sys/kcov.h */
+ _(KCOV_IOC_SETBUFSIZE, READ, sizeof(u64));
+ _(KCOV_IOC_ENABLE, READ, sizeof(int));
+ _(KCOV_IOC_DISABLE, NONE, 0);
+ /* Entries from file: sys/ipmi.h */
+ _(IPMICTL_RECEIVE_MSG_TRUNC, READWRITE, struct_ipmi_recv_sz);
+ _(IPMICTL_RECEIVE_MSG, READWRITE, struct_ipmi_recv_sz);
+ _(IPMICTL_SEND_COMMAND, READ, struct_ipmi_req_sz);
+ _(IPMICTL_REGISTER_FOR_CMD, READ, struct_ipmi_cmdspec_sz);
+ _(IPMICTL_UNREGISTER_FOR_CMD, READ, struct_ipmi_cmdspec_sz);
+ _(IPMICTL_SET_GETS_EVENTS_CMD, READ, sizeof(int));
+ _(IPMICTL_SET_MY_ADDRESS_CMD, READ, sizeof(unsigned int));
+ _(IPMICTL_GET_MY_ADDRESS_CMD, WRITE, sizeof(unsigned int));
+ _(IPMICTL_SET_MY_LUN_CMD, READ, sizeof(unsigned int));
+ _(IPMICTL_GET_MY_LUN_CMD, WRITE, sizeof(unsigned int));
+ /* Entries from file: soundcard.h */
+ _(SNDCTL_DSP_RESET, NONE, 0);
+ _(SNDCTL_DSP_SYNC, NONE, 0);
+ _(SNDCTL_DSP_SPEED, READWRITE, sizeof(int));
+ _(SOUND_PCM_READ_RATE, WRITE, sizeof(int));
+ _(SNDCTL_DSP_STEREO, READWRITE, sizeof(int));
+ _(SNDCTL_DSP_GETBLKSIZE, READWRITE, sizeof(int));
+ _(SNDCTL_DSP_SETFMT, READWRITE, sizeof(int));
+ _(SOUND_PCM_READ_BITS, WRITE, sizeof(int));
+ _(SNDCTL_DSP_CHANNELS, READWRITE, sizeof(int));
+ _(SOUND_PCM_READ_CHANNELS, WRITE, sizeof(int));
+ _(SOUND_PCM_WRITE_FILTER, READWRITE, sizeof(int));
+ _(SOUND_PCM_READ_FILTER, WRITE, sizeof(int));
+ _(SNDCTL_DSP_POST, NONE, 0);
+ _(SNDCTL_DSP_SUBDIVIDE, READWRITE, sizeof(int));
+ _(SNDCTL_DSP_SETFRAGMENT, READWRITE, sizeof(int));
+ _(SNDCTL_DSP_GETFMTS, WRITE, sizeof(int));
+ _(SNDCTL_DSP_GETOSPACE, WRITE, struct_audio_buf_info_sz);
+ _(SNDCTL_DSP_GETISPACE, WRITE, struct_audio_buf_info_sz);
+ _(SNDCTL_DSP_NONBLOCK, NONE, 0);
+ _(SNDCTL_DSP_GETCAPS, WRITE, sizeof(int));
+ _(SNDCTL_DSP_GETTRIGGER, WRITE, sizeof(int));
+ _(SNDCTL_DSP_SETTRIGGER, READ, sizeof(int));
+ _(SNDCTL_DSP_GETIPTR, WRITE, struct_count_info_sz);
+ _(SNDCTL_DSP_GETOPTR, WRITE, struct_count_info_sz);
+ _(SNDCTL_DSP_MAPINBUF, WRITE, struct_buffmem_desc_sz);
+ _(SNDCTL_DSP_MAPOUTBUF, WRITE, struct_buffmem_desc_sz);
+ _(SNDCTL_DSP_SETSYNCRO, NONE, 0);
+ _(SNDCTL_DSP_SETDUPLEX, NONE, 0);
+ _(SNDCTL_DSP_PROFILE, READ, sizeof(int));
+ _(SNDCTL_DSP_GETODELAY, WRITE, sizeof(int));
+ _(SOUND_MIXER_INFO, WRITE, struct_mixer_info_sz);
+ _(SOUND_OLD_MIXER_INFO, WRITE, struct__old_mixer_info_sz);
+ _(OSS_GETVERSION, WRITE, sizeof(int));
+ _(SNDCTL_SYSINFO, WRITE, struct_oss_sysinfo_sz);
+ _(SNDCTL_AUDIOINFO, READWRITE, struct_oss_audioinfo_sz);
+ _(SNDCTL_ENGINEINFO, READWRITE, struct_oss_audioinfo_sz);
+ _(SNDCTL_DSP_GETPLAYVOL, WRITE, sizeof(unsigned int));
+ _(SNDCTL_DSP_SETPLAYVOL, READ, sizeof(unsigned int));
+ _(SNDCTL_DSP_GETRECVOL, WRITE, sizeof(unsigned int));
+ _(SNDCTL_DSP_SETRECVOL, READ, sizeof(unsigned int));
+ _(SNDCTL_DSP_SKIP, NONE, 0);
+ _(SNDCTL_DSP_SILENCE, NONE, 0);
+ /* Entries from file: dev/filemon/filemon.h (compat <= 9.99.26) */
+ _(FILEMON_SET_FD, READWRITE, sizeof(int));
+ _(FILEMON_SET_PID, READWRITE, sizeof(int));
+ /* Entries from file: dev/usb/urio.h (compat <= 9.99.43) */
+ _(URIO_SEND_COMMAND, READWRITE, struct_urio_command_sz);
+ _(URIO_RECV_COMMAND, READWRITE, struct_urio_command_sz);
+#undef _
+}
+
+static bool ioctl_initialized = false;
+
+struct ioctl_desc_compare {
+ bool operator()(const ioctl_desc &left, const ioctl_desc &right) const {
+ return left.req < right.req;
+ }
+};
+
+static void ioctl_init() {
+ ioctl_table_fill();
+ Sort(ioctl_table, ioctl_table_size, ioctl_desc_compare());
+
+ bool bad = false;
+ for (unsigned i = 0; i < ioctl_table_size - 1; ++i) {
+ if (ioctl_table[i].req >= ioctl_table[i + 1].req) {
+ Printf("Duplicate or unsorted ioctl request id %x >= %x (%s vs %s)\n",
+ ioctl_table[i].req, ioctl_table[i + 1].req, ioctl_table[i].name,
+ ioctl_table[i + 1].name);
+ bad = true;
+ }
+ }
+
+ if (bad)
+ Die();
+
+ ioctl_initialized = true;
+}
+
+static const ioctl_desc *ioctl_table_lookup(unsigned req) {
+ int left = 0;
+ int right = ioctl_table_size;
+ while (left < right) {
+ int mid = (left + right) / 2;
+ if (ioctl_table[mid].req < req)
+ left = mid + 1;
+ else
+ right = mid;
+ }
+ if (left == right && ioctl_table[left].req == req)
+ return ioctl_table + left;
+ else
+ return nullptr;
+}
+
+static bool ioctl_decode(unsigned req, ioctl_desc *desc) {
+ CHECK(desc);
+ desc->req = req;
+ desc->name = "<DECODED_IOCTL>";
+ desc->size = IOC_SIZE(req);
+ // Sanity check.
+ if (desc->size > 0xFFFF)
+ return false;
+ unsigned dir = IOC_DIR(req);
+ switch (dir) {
+ case IOC_NONE:
+ desc->type = ioctl_desc::NONE;
+ break;
+ case IOC_READ | IOC_WRITE:
+ desc->type = ioctl_desc::READWRITE;
+ break;
+ case IOC_READ:
+ desc->type = ioctl_desc::WRITE;
+ break;
+ case IOC_WRITE:
+ desc->type = ioctl_desc::READ;
+ break;
+ default:
+ return false;
+ }
+ // Size can be 0 iff type is NONE.
+ if ((desc->type == IOC_NONE) != (desc->size == 0))
+ return false;
+ // Sanity check.
+ if (IOC_TYPE(req) == 0)
+ return false;
+ return true;
+}
+
+static const ioctl_desc *ioctl_lookup(unsigned req) {
+ const ioctl_desc *desc = ioctl_table_lookup(req);
+ if (desc)
+ return desc;
+
+ // Try stripping access size from the request id.
+ desc = ioctl_table_lookup(req & ~(IOC_SIZEMASK << IOC_SIZESHIFT));
+ // Sanity check: requests that encode access size are either read or write and
+ // have size of 0 in the table.
+ if (desc && desc->size == 0 &&
+ (desc->type == ioctl_desc::READWRITE || desc->type == ioctl_desc::WRITE ||
+ desc->type == ioctl_desc::READ))
+ return desc;
+ return nullptr;
+}
+
+static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,
+ unsigned request, void *arg) {
+ if (desc->type == ioctl_desc::READ || desc->type == ioctl_desc::READWRITE) {
+ unsigned size = desc->size ? desc->size : IOC_SIZE(request);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size);
+ }
+ if (desc->type != ioctl_desc::CUSTOM)
+ return;
+ if (request == IOCTL_SIOCGIFCONF) {
+ struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, (char *)&ifc->ifc_len,
+ sizeof(ifc->ifc_len));
+ }
+}
+
+static void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d,
+ unsigned request, void *arg) {
+ if (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READWRITE) {
+ // FIXME: add verbose output
+ unsigned size = desc->size ? desc->size : IOC_SIZE(request);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size);
+ }
+ if (desc->type != ioctl_desc::CUSTOM)
+ return;
+ if (request == IOCTL_SIOCGIFCONF) {
+ struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifc->ifc_ifcu.ifcu_req, ifc->ifc_len);
+ }
+}
+
+#endif // SANITIZER_NETBSD
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_interface_internal.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_interface_internal.h
new file mode 100644
index 00000000000..cd0d45e2f3f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_interface_internal.h
@@ -0,0 +1,153 @@
+//===-- sanitizer_interface_internal.h --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between run-time libraries of sanitizers.
+//
+// This header declares the sanitizer runtime interface functions.
+// The runtime library has to define these functions so the instrumented program
+// could call them.
+//
+// See also include/sanitizer/common_interface_defs.h
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_INTERFACE_INTERNAL_H
+#define SANITIZER_INTERFACE_INTERNAL_H
+
+#include "sanitizer_internal_defs.h"
+
+extern "C" {
+// Tell the tools to write their reports to "path.<pid>" instead of stderr.
+// The special values are "stdout" and "stderr".
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_set_report_path(const char *path);
+// Tell the tools to write their reports to the provided file descriptor
+// (casted to void *).
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_set_report_fd(void *fd);
+// Get the current full report file path, if a path was specified by
+// an earlier call to __sanitizer_set_report_path. Returns null otherwise.
+SANITIZER_INTERFACE_ATTRIBUTE
+const char *__sanitizer_get_report_path();
+
+typedef struct {
+ int coverage_sandboxed;
+ __sanitizer::sptr coverage_fd;
+ unsigned int coverage_max_block_size;
+} __sanitizer_sandbox_arguments;
+
+// Notify the tools that the sandbox is going to be turned on.
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args);
+
+// This function is called by the tool when it has just finished reporting
+// an error. 'error_summary' is a one-line string that summarizes
+// the error message. This function can be overridden by the client.
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_report_error_summary(const char *error_summary);
+
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump();
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(
+ const __sanitizer::uptr *pcs, const __sanitizer::uptr len);
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_trace_pc_guard_coverage();
+
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov(__sanitizer::u32 *guard);
+
+// Returns 1 on the first call, then returns 0 thereafter. Called by the tool
+// to ensure only one report is printed when multiple errors occur
+// simultaneously.
+SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_acquire_crash_state();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_annotate_contiguous_container(const void *beg, const void *end,
+ const void *old_mid,
+ const void *new_mid);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_annotate_double_ended_contiguous_container(
+ const void *storage_beg, const void *storage_end,
+ const void *old_container_beg, const void *old_container_end,
+ const void *new_container_beg, const void *new_container_end);
+SANITIZER_INTERFACE_ATTRIBUTE
+int __sanitizer_verify_contiguous_container(const void *beg, const void *mid,
+ const void *end);
+SANITIZER_INTERFACE_ATTRIBUTE
+int __sanitizer_verify_double_ended_contiguous_container(
+ const void *storage_beg, const void *container_beg,
+ const void *container_end, const void *storage_end);
+SANITIZER_INTERFACE_ATTRIBUTE
+const void *__sanitizer_contiguous_container_find_bad_address(const void *beg,
+ const void *mid,
+ const void *end);
+SANITIZER_INTERFACE_ATTRIBUTE
+const void *__sanitizer_double_ended_contiguous_container_find_bad_address(
+ const void *storage_beg, const void *container_beg,
+ const void *container_end, const void *storage_end);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __sanitizer_get_module_and_offset_for_pc(void *pc, char *module_path,
+ __sanitizer::uptr module_path_len,
+ void **pc_offset);
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_cmp();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_cmp1();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_cmp2();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_cmp4();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_cmp8();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_const_cmp1();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_const_cmp2();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_const_cmp4();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_const_cmp8();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_switch();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_div4();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_div8();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_gep();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_pc_indir();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_load1();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_load2();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_load4();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_load8();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_load16();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_store1();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_store2();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_store4();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_store8();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_store16();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_pc_guard(__sanitizer::u32 *);
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_trace_pc_guard_init(__sanitizer::u32 *, __sanitizer::u32 *);
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_8bit_counters_init(char *, char *);
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_bool_flag_init();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_cov_pcs_init(const __sanitizer::uptr *, const __sanitizer::uptr *);
+} // extern "C"
+
+#endif // SANITIZER_INTERFACE_INTERNAL_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_internal_defs.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_internal_defs.h
new file mode 100644
index 00000000000..6b800820ab8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_internal_defs.h
@@ -0,0 +1,480 @@
+//===-- sanitizer_internal_defs.h -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer.
+// It contains macro used in run-time libraries code.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_DEFS_H
+#define SANITIZER_DEFS_H
+
+#include "sanitizer_platform.h"
+
+#ifndef SANITIZER_DEBUG
+# define SANITIZER_DEBUG 0
+#endif
+
+#define SANITIZER_STRINGIFY_(S) #S
+#define SANITIZER_STRINGIFY(S) SANITIZER_STRINGIFY_(S)
+
+// Only use SANITIZER_*ATTRIBUTE* before the function return type!
+#if SANITIZER_WINDOWS
+#if SANITIZER_IMPORT_INTERFACE
+# define SANITIZER_INTERFACE_ATTRIBUTE __declspec(dllimport)
+#else
+# define SANITIZER_INTERFACE_ATTRIBUTE __declspec(dllexport)
+#endif
+# define SANITIZER_WEAK_ATTRIBUTE
+#elif SANITIZER_GO
+# define SANITIZER_INTERFACE_ATTRIBUTE
+# define SANITIZER_WEAK_ATTRIBUTE
+#else
+# define SANITIZER_INTERFACE_ATTRIBUTE __attribute__((visibility("default")))
+# define SANITIZER_WEAK_ATTRIBUTE __attribute__((weak))
+#endif
+
+// TLS is handled differently on different platforms
+#if SANITIZER_LINUX || SANITIZER_NETBSD || \
+ SANITIZER_FREEBSD
+# define SANITIZER_TLS_INITIAL_EXEC_ATTRIBUTE \
+ __attribute__((tls_model("initial-exec"))) thread_local
+#else
+# define SANITIZER_TLS_INITIAL_EXEC_ATTRIBUTE
+#endif
+
+//--------------------------- WEAK FUNCTIONS ---------------------------------//
+// When working with weak functions, to simplify the code and make it more
+// portable, when possible define a default implementation using this macro:
+//
+// SANITIZER_INTERFACE_WEAK_DEF(<return_type>, <name>, <parameter list>)
+//
+// For example:
+// SANITIZER_INTERFACE_WEAK_DEF(bool, compare, int a, int b) { return a > b; }
+//
+#if SANITIZER_WINDOWS
+#include "sanitizer_win_defs.h"
+# define SANITIZER_INTERFACE_WEAK_DEF(ReturnType, Name, ...) \
+ WIN_WEAK_EXPORT_DEF(ReturnType, Name, __VA_ARGS__)
+#else
+# define SANITIZER_INTERFACE_WEAK_DEF(ReturnType, Name, ...) \
+ extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE \
+ ReturnType Name(__VA_ARGS__)
+#endif
+
+// SANITIZER_SUPPORTS_WEAK_HOOKS means that we support real weak functions that
+// will evaluate to a null pointer when not defined.
+#ifndef SANITIZER_SUPPORTS_WEAK_HOOKS
+#if (SANITIZER_LINUX || SANITIZER_SOLARIS) && !SANITIZER_GO
+# define SANITIZER_SUPPORTS_WEAK_HOOKS 1
+// Before Xcode 4.5, the Darwin linker doesn't reliably support undefined
+// weak symbols. Mac OS X 10.9/Darwin 13 is the first release only supported
+// by Xcode >= 4.5.
+#elif SANITIZER_APPLE && \
+ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1090 && !SANITIZER_GO
+# define SANITIZER_SUPPORTS_WEAK_HOOKS 1
+#else
+# define SANITIZER_SUPPORTS_WEAK_HOOKS 0
+#endif
+#endif // SANITIZER_SUPPORTS_WEAK_HOOKS
+// For some weak hooks that will be called very often and we want to avoid the
+// overhead of executing the default implementation when it is not necessary,
+// we can use the flag SANITIZER_SUPPORTS_WEAK_HOOKS to only define the default
+// implementation for platforms that doesn't support weak symbols. For example:
+//
+// #if !SANITIZER_SUPPORT_WEAK_HOOKS
+// SANITIZER_INTERFACE_WEAK_DEF(bool, compare_hook, int a, int b) {
+// return a > b;
+// }
+// #endif
+//
+// And then use it as: if (compare_hook) compare_hook(a, b);
+//----------------------------------------------------------------------------//
+
+
+// We can use .preinit_array section on Linux to call sanitizer initialization
+// functions very early in the process startup (unless PIC macro is defined).
+//
+// On FreeBSD, .preinit_array functions are called with rtld_bind_lock writer
+// lock held. It will lead to dead lock if unresolved PLT functions (which helds
+// rtld_bind_lock reader lock) are called inside .preinit_array functions.
+//
+// FIXME: do we have anything like this on Mac?
+#ifndef SANITIZER_CAN_USE_PREINIT_ARRAY
+#if (SANITIZER_LINUX || SANITIZER_FUCHSIA || SANITIZER_NETBSD) && !defined(PIC)
+#define SANITIZER_CAN_USE_PREINIT_ARRAY 1
+// Before Solaris 11.4, .preinit_array is fully supported only with GNU ld.
+// FIXME: Check for those conditions.
+#elif SANITIZER_SOLARIS && !defined(PIC)
+# define SANITIZER_CAN_USE_PREINIT_ARRAY 1
+#else
+# define SANITIZER_CAN_USE_PREINIT_ARRAY 0
+#endif
+#endif // SANITIZER_CAN_USE_PREINIT_ARRAY
+
+// GCC does not understand __has_feature
+#if !defined(__has_feature)
+# define __has_feature(x) 0
+#endif
+
+// Older GCCs do not understand __has_attribute.
+#if !defined(__has_attribute)
+# define __has_attribute(x) 0
+#endif
+
+#if !defined(__has_cpp_attribute)
+# define __has_cpp_attribute(x) 0
+#endif
+
+// For portability reasons we do not include stddef.h, stdint.h or any other
+// system header, but we do need some basic types that are not defined
+// in a portable way by the language itself.
+namespace __sanitizer {
+
+#if defined(_WIN64)
+// 64-bit Windows uses LLP64 data model.
+typedef unsigned long long uptr;
+typedef signed long long sptr;
+#else
+# if (SANITIZER_WORDSIZE == 64) || SANITIZER_APPLE || SANITIZER_WINDOWS
+typedef unsigned long uptr;
+typedef signed long sptr;
+# else
+typedef unsigned int uptr;
+typedef signed int sptr;
+# endif
+#endif // defined(_WIN64)
+#if defined(__x86_64__)
+// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use
+// 64-bit pointer to unwind stack frame.
+typedef unsigned long long uhwptr;
+#else
+typedef uptr uhwptr;
+#endif
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+typedef signed char s8;
+typedef signed short s16;
+typedef signed int s32;
+typedef signed long long s64;
+#if SANITIZER_WINDOWS
+// On Windows, files are HANDLE, which is a synonim of void*.
+// Use void* to avoid including <windows.h> everywhere.
+typedef void* fd_t;
+typedef unsigned error_t;
+#else
+typedef int fd_t;
+typedef int error_t;
+#endif
+#if SANITIZER_SOLARIS && !defined(_LP64)
+typedef long pid_t;
+#else
+typedef int pid_t;
+#endif
+
+#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_APPLE || \
+ (SANITIZER_SOLARIS && (defined(_LP64) || _FILE_OFFSET_BITS == 64)) || \
+ (SANITIZER_LINUX && !SANITIZER_GLIBC && !SANITIZER_ANDROID) || \
+ (SANITIZER_LINUX && (defined(__x86_64__) || defined(__hexagon__)))
+typedef u64 OFF_T;
+#else
+typedef uptr OFF_T;
+#endif
+typedef u64 OFF64_T;
+
+#if (SANITIZER_WORDSIZE == 64) || SANITIZER_APPLE
+typedef uptr operator_new_size_type;
+#else
+# if defined(__s390__) && !defined(__s390x__)
+// Special case: 31-bit s390 has unsigned long as size_t.
+typedef unsigned long operator_new_size_type;
+# else
+typedef u32 operator_new_size_type;
+# endif
+#endif
+
+typedef u64 tid_t;
+
+// ----------- ATTENTION -------------
+// This header should NOT include any other headers to avoid portability issues.
+
+// Common defs.
+#define INTERFACE_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
+#define SANITIZER_WEAK_DEFAULT_IMPL \
+ extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE
+#define SANITIZER_WEAK_CXX_DEFAULT_IMPL \
+ extern "C++" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE
+
+// Platform-specific defs.
+#if defined(_MSC_VER)
+# define ALWAYS_INLINE __forceinline
+// FIXME(timurrrr): do we need this on Windows?
+# define ALIAS(x)
+# define ALIGNED(x) __declspec(align(x))
+# define FORMAT(f, a)
+# define NOINLINE __declspec(noinline)
+# define NORETURN __declspec(noreturn)
+# define THREADLOCAL __declspec(thread)
+# define LIKELY(x) (x)
+# define UNLIKELY(x) (x)
+# define PREFETCH(x) /* _mm_prefetch(x, _MM_HINT_NTA) */ (void)0
+# define WARN_UNUSED_RESULT
+#else // _MSC_VER
+# define ALWAYS_INLINE inline __attribute__((always_inline))
+# define ALIAS(x) __attribute__((alias(x)))
+// Please only use the ALIGNED macro before the type.
+// Using ALIGNED after the variable declaration is not portable!
+# define ALIGNED(x) __attribute__((aligned(x)))
+# define FORMAT(f, a) __attribute__((format(printf, f, a)))
+# define NOINLINE __attribute__((noinline))
+# define NORETURN __attribute__((noreturn))
+# define THREADLOCAL __thread
+# define LIKELY(x) __builtin_expect(!!(x), 1)
+# define UNLIKELY(x) __builtin_expect(!!(x), 0)
+# if defined(__i386__) || defined(__x86_64__)
+// __builtin_prefetch(x) generates prefetchnt0 on x86
+# define PREFETCH(x) __asm__("prefetchnta (%0)" : : "r" (x))
+# else
+# define PREFETCH(x) __builtin_prefetch(x)
+# endif
+# define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#endif // _MSC_VER
+
+#if !defined(_MSC_VER) || defined(__clang__)
+# define UNUSED __attribute__((unused))
+# define USED __attribute__((used))
+#else
+# define UNUSED
+# define USED
+#endif
+
+#if !defined(_MSC_VER) || defined(__clang__) || MSC_PREREQ(1900)
+# define NOEXCEPT noexcept
+#else
+# define NOEXCEPT throw()
+#endif
+
+#if __has_cpp_attribute(clang::fallthrough)
+# define FALLTHROUGH [[clang::fallthrough]]
+#elif __has_cpp_attribute(fallthrough)
+# define FALLTHROUGH [[fallthrough]]
+#else
+# define FALLTHROUGH
+#endif
+
+// Unaligned versions of basic types.
+typedef ALIGNED(1) u16 uu16;
+typedef ALIGNED(1) u32 uu32;
+typedef ALIGNED(1) u64 uu64;
+typedef ALIGNED(1) s16 us16;
+typedef ALIGNED(1) s32 us32;
+typedef ALIGNED(1) s64 us64;
+
+#if SANITIZER_WINDOWS
+} // namespace __sanitizer
+typedef unsigned long DWORD;
+namespace __sanitizer {
+typedef DWORD thread_return_t;
+# define THREAD_CALLING_CONV __stdcall
+#else // _WIN32
+typedef void* thread_return_t;
+# define THREAD_CALLING_CONV
+#endif // _WIN32
+typedef thread_return_t (THREAD_CALLING_CONV *thread_callback_t)(void* arg);
+
+// NOTE: Functions below must be defined in each run-time.
+void NORETURN Die();
+
+void NORETURN CheckFailed(const char *file, int line, const char *cond,
+ u64 v1, u64 v2);
+
+// Check macro
+#define RAW_CHECK_MSG(expr, msg, ...) \
+ do { \
+ if (UNLIKELY(!(expr))) { \
+ const char* msgs[] = {msg, __VA_ARGS__}; \
+ for (const char* m : msgs) RawWrite(m); \
+ Die(); \
+ } \
+ } while (0)
+
+#define RAW_CHECK(expr) RAW_CHECK_MSG(expr, #expr "\n", )
+#define RAW_CHECK_VA(expr, ...) RAW_CHECK_MSG(expr, #expr "\n", __VA_ARGS__)
+
+#define CHECK_IMPL(c1, op, c2) \
+ do { \
+ __sanitizer::u64 v1 = (__sanitizer::u64)(c1); \
+ __sanitizer::u64 v2 = (__sanitizer::u64)(c2); \
+ if (UNLIKELY(!(v1 op v2))) \
+ __sanitizer::CheckFailed(__FILE__, __LINE__, \
+ "(" #c1 ") " #op " (" #c2 ")", v1, v2); \
+ } while (false) \
+/**/
+
+#define CHECK(a) CHECK_IMPL((a), !=, 0)
+#define CHECK_EQ(a, b) CHECK_IMPL((a), ==, (b))
+#define CHECK_NE(a, b) CHECK_IMPL((a), !=, (b))
+#define CHECK_LT(a, b) CHECK_IMPL((a), <, (b))
+#define CHECK_LE(a, b) CHECK_IMPL((a), <=, (b))
+#define CHECK_GT(a, b) CHECK_IMPL((a), >, (b))
+#define CHECK_GE(a, b) CHECK_IMPL((a), >=, (b))
+
+#if SANITIZER_DEBUG
+#define DCHECK(a) CHECK(a)
+#define DCHECK_EQ(a, b) CHECK_EQ(a, b)
+#define DCHECK_NE(a, b) CHECK_NE(a, b)
+#define DCHECK_LT(a, b) CHECK_LT(a, b)
+#define DCHECK_LE(a, b) CHECK_LE(a, b)
+#define DCHECK_GT(a, b) CHECK_GT(a, b)
+#define DCHECK_GE(a, b) CHECK_GE(a, b)
+#else
+#define DCHECK(a)
+#define DCHECK_EQ(a, b)
+#define DCHECK_NE(a, b)
+#define DCHECK_LT(a, b)
+#define DCHECK_LE(a, b)
+#define DCHECK_GT(a, b)
+#define DCHECK_GE(a, b)
+#endif
+
+#define UNREACHABLE(msg) do { \
+ CHECK(0 && msg); \
+ Die(); \
+} while (0)
+
+#define UNIMPLEMENTED() UNREACHABLE("unimplemented")
+
+#define COMPILER_CHECK(pred) static_assert(pred, "")
+
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
+
+// Limits for integral types. We have to redefine it in case we don't
+// have stdint.h (like in Visual Studio 9).
+#undef __INT64_C
+#undef __UINT64_C
+#if SANITIZER_WORDSIZE == 64
+# define __INT64_C(c) c ## L
+# define __UINT64_C(c) c ## UL
+#else
+# define __INT64_C(c) c ## LL
+# define __UINT64_C(c) c ## ULL
+#endif // SANITIZER_WORDSIZE == 64
+#undef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#undef INT32_MAX
+#define INT32_MAX (2147483647)
+#undef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#undef INT64_MIN
+#define INT64_MIN (-__INT64_C(9223372036854775807)-1)
+#undef INT64_MAX
+#define INT64_MAX (__INT64_C(9223372036854775807))
+#undef UINT64_MAX
+#define UINT64_MAX (__UINT64_C(18446744073709551615))
+#undef UINTPTR_MAX
+#if SANITIZER_WORDSIZE == 64
+# define UINTPTR_MAX (18446744073709551615UL)
+#else
+# define UINTPTR_MAX (4294967295U)
+#endif // SANITIZER_WORDSIZE == 64
+
+enum LinkerInitialized { LINKER_INITIALIZED = 0 };
+
+#if !defined(_MSC_VER) || defined(__clang__)
+# define GET_CALLER_PC() \
+ ((__sanitizer::uptr)__builtin_extract_return_addr( \
+ __builtin_return_address(0)))
+# define GET_CURRENT_FRAME() ((__sanitizer::uptr)__builtin_frame_address(0))
+inline void Trap() {
+ __builtin_trap();
+}
+#else
+extern "C" void* _ReturnAddress(void);
+extern "C" void* _AddressOfReturnAddress(void);
+# pragma intrinsic(_ReturnAddress)
+# pragma intrinsic(_AddressOfReturnAddress)
+# define GET_CALLER_PC() ((__sanitizer::uptr)_ReturnAddress())
+// CaptureStackBackTrace doesn't need to know BP on Windows.
+# define GET_CURRENT_FRAME() \
+ (((__sanitizer::uptr)_AddressOfReturnAddress()) + sizeof(__sanitizer::uptr))
+
+extern "C" void __ud2(void);
+# pragma intrinsic(__ud2)
+inline void Trap() {
+ __ud2();
+}
+#endif
+
+#define HANDLE_EINTR(res, f) \
+ { \
+ int rverrno; \
+ do { \
+ res = (f); \
+ } while (internal_iserror(res, &rverrno) && rverrno == EINTR); \
+ }
+
+// Forces the compiler to generate a frame pointer in the function.
+#define ENABLE_FRAME_POINTER \
+ do { \
+ volatile __sanitizer::uptr enable_fp; \
+ enable_fp = GET_CURRENT_FRAME(); \
+ (void)enable_fp; \
+ } while (0)
+
+// Internal thread identifier allocated by ThreadRegistry.
+typedef u32 Tid;
+constexpr Tid kInvalidTid = -1;
+constexpr Tid kMainTid = 0;
+
+// Stack depot stack identifier.
+typedef u32 StackID;
+const StackID kInvalidStackID = 0;
+
+} // namespace __sanitizer
+
+namespace __asan {
+using namespace __sanitizer;
+}
+namespace __dsan {
+using namespace __sanitizer;
+}
+namespace __dfsan {
+using namespace __sanitizer;
+}
+namespace __lsan {
+using namespace __sanitizer;
+}
+namespace __msan {
+using namespace __sanitizer;
+}
+namespace __hwasan {
+using namespace __sanitizer;
+}
+namespace __tsan {
+using namespace __sanitizer;
+}
+namespace __scudo {
+using namespace __sanitizer;
+}
+namespace __ubsan {
+using namespace __sanitizer;
+}
+namespace __xray {
+using namespace __sanitizer;
+}
+namespace __interception {
+using namespace __sanitizer;
+}
+namespace __hwasan {
+using namespace __sanitizer;
+}
+namespace __memprof {
+using namespace __sanitizer;
+}
+
+#endif // SANITIZER_DEFS_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_leb128.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_leb128.h
new file mode 100644
index 00000000000..553550d2955
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_leb128.h
@@ -0,0 +1,87 @@
+//===-- sanitizer_leb128.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_LEB128_H
+#define SANITIZER_LEB128_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+template <typename T, typename It>
+It EncodeSLEB128(T value, It begin, It end) {
+ bool more;
+ do {
+ u8 byte = value & 0x7f;
+ // NOTE: this assumes that this signed shift is an arithmetic right shift.
+ value >>= 7;
+ more = !((((value == 0) && ((byte & 0x40) == 0)) ||
+ ((value == -1) && ((byte & 0x40) != 0))));
+ if (more)
+ byte |= 0x80;
+ if (UNLIKELY(begin == end))
+ break;
+ *(begin++) = byte;
+ } while (more);
+ return begin;
+}
+
+template <typename T, typename It>
+It DecodeSLEB128(It begin, It end, T* v) {
+ T value = 0;
+ unsigned shift = 0;
+ u8 byte;
+ do {
+ if (UNLIKELY(begin == end))
+ return begin;
+ byte = *(begin++);
+ T slice = byte & 0x7f;
+ value |= slice << shift;
+ shift += 7;
+ } while (byte >= 128);
+ if (shift < 64 && (byte & 0x40))
+ value |= (-1ULL) << shift;
+ *v = value;
+ return begin;
+}
+
+template <typename T, typename It>
+It EncodeULEB128(T value, It begin, It end) {
+ do {
+ u8 byte = value & 0x7f;
+ value >>= 7;
+ if (value)
+ byte |= 0x80;
+ if (UNLIKELY(begin == end))
+ break;
+ *(begin++) = byte;
+ } while (value);
+ return begin;
+}
+
+template <typename T, typename It>
+It DecodeULEB128(It begin, It end, T* v) {
+ T value = 0;
+ unsigned shift = 0;
+ u8 byte;
+ do {
+ if (UNLIKELY(begin == end))
+ return begin;
+ byte = *(begin++);
+ T slice = byte & 0x7f;
+ value += slice << shift;
+ shift += 7;
+ } while (byte >= 128);
+ *v = value;
+ return begin;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_LEB128_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_lfstack.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_lfstack.h
new file mode 100644
index 00000000000..af2ca55ec3f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_lfstack.h
@@ -0,0 +1,72 @@
+//===-- sanitizer_lfstack.h -=-----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Lock-free stack.
+// Uses 32/17 bits as ABA-counter on 32/64-bit platforms.
+// The memory passed to Push() must not be ever munmap'ed.
+// The type T must contain T *next field.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_LFSTACK_H
+#define SANITIZER_LFSTACK_H
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_common.h"
+#include "sanitizer_atomic.h"
+
+namespace __sanitizer {
+
+template<typename T>
+struct LFStack {
+ void Clear() {
+ atomic_store(&head_, 0, memory_order_relaxed);
+ }
+
+ bool Empty() const {
+ return (atomic_load(&head_, memory_order_relaxed) & kPtrMask) == 0;
+ }
+
+ void Push(T *p) {
+ u64 cmp = atomic_load(&head_, memory_order_relaxed);
+ for (;;) {
+ u64 cnt = (cmp & kCounterMask) + kCounterInc;
+ u64 xch = (u64)(uptr)p | cnt;
+ p->next = (T*)(uptr)(cmp & kPtrMask);
+ if (atomic_compare_exchange_weak(&head_, &cmp, xch,
+ memory_order_release))
+ break;
+ }
+ }
+
+ T *Pop() {
+ u64 cmp = atomic_load(&head_, memory_order_acquire);
+ for (;;) {
+ T *cur = (T*)(uptr)(cmp & kPtrMask);
+ if (!cur)
+ return nullptr;
+ T *nxt = cur->next;
+ u64 cnt = (cmp & kCounterMask);
+ u64 xch = (u64)(uptr)nxt | cnt;
+ if (atomic_compare_exchange_weak(&head_, &cmp, xch,
+ memory_order_acquire))
+ return cur;
+ }
+ }
+
+ // private:
+ static const int kCounterBits = FIRST_32_SECOND_64(32, 17);
+ static const u64 kPtrMask = ((u64)-1) >> kCounterBits;
+ static const u64 kCounterMask = ~kPtrMask;
+ static const u64 kCounterInc = kPtrMask + 1;
+
+ atomic_uint64_t head_;
+};
+} // namespace __sanitizer
+
+#endif // SANITIZER_LFSTACK_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libc.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libc.cpp
new file mode 100644
index 00000000000..d3076f0da48
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libc.cpp
@@ -0,0 +1,292 @@
+//===-- sanitizer_libc.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries. See sanitizer_libc.h for details.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_common.h"
+#include "sanitizer_libc.h"
+
+namespace __sanitizer {
+
+s64 internal_atoll(const char *nptr) {
+ return internal_simple_strtoll(nptr, nullptr, 10);
+}
+
+void *internal_memchr(const void *s, int c, uptr n) {
+ const char *t = (const char *)s;
+ for (uptr i = 0; i < n; ++i, ++t)
+ if (*t == c)
+ return reinterpret_cast<void *>(const_cast<char *>(t));
+ return nullptr;
+}
+
+void *internal_memrchr(const void *s, int c, uptr n) {
+ const char *t = (const char *)s;
+ void *res = nullptr;
+ for (uptr i = 0; i < n; ++i, ++t) {
+ if (*t == c) res = reinterpret_cast<void *>(const_cast<char *>(t));
+ }
+ return res;
+}
+
+int internal_memcmp(const void* s1, const void* s2, uptr n) {
+ const char *t1 = (const char *)s1;
+ const char *t2 = (const char *)s2;
+ for (uptr i = 0; i < n; ++i, ++t1, ++t2)
+ if (*t1 != *t2)
+ return *t1 < *t2 ? -1 : 1;
+ return 0;
+}
+
+void *internal_memcpy(void *dest, const void *src, uptr n) {
+ char *d = (char*)dest;
+ const char *s = (const char *)src;
+ for (uptr i = 0; i < n; ++i)
+ d[i] = s[i];
+ return dest;
+}
+
+void *internal_memmove(void *dest, const void *src, uptr n) {
+ char *d = (char*)dest;
+ const char *s = (const char *)src;
+ sptr i, signed_n = (sptr)n;
+ CHECK_GE(signed_n, 0);
+ if (d < s) {
+ for (i = 0; i < signed_n; ++i)
+ d[i] = s[i];
+ } else {
+ if (d > s && signed_n > 0) {
+ for (i = signed_n - 1; i >= 0; --i) {
+ d[i] = s[i];
+ }
+ }
+ }
+ return dest;
+}
+
+void *internal_memset(void* s, int c, uptr n) {
+ // Optimize for the most performance-critical case:
+ if ((reinterpret_cast<uptr>(s) % 16) == 0 && (n % 16) == 0) {
+ u64 *p = reinterpret_cast<u64*>(s);
+ u64 *e = p + n / 8;
+ u64 v = c;
+ v |= v << 8;
+ v |= v << 16;
+ v |= v << 32;
+ for (; p < e; p += 2)
+ p[0] = p[1] = v;
+ return s;
+ }
+ // The next line prevents Clang from making a call to memset() instead of the
+ // loop below.
+ // FIXME: building the runtime with -ffreestanding is a better idea. However
+ // there currently are linktime problems due to PR12396.
+ char volatile *t = (char*)s;
+ for (uptr i = 0; i < n; ++i, ++t) {
+ *t = c;
+ }
+ return s;
+}
+
+uptr internal_strcspn(const char *s, const char *reject) {
+ uptr i;
+ for (i = 0; s[i]; i++) {
+ if (internal_strchr(reject, s[i]))
+ return i;
+ }
+ return i;
+}
+
+char* internal_strdup(const char *s) {
+ uptr len = internal_strlen(s);
+ char *s2 = (char*)InternalAlloc(len + 1);
+ internal_memcpy(s2, s, len);
+ s2[len] = 0;
+ return s2;
+}
+
+int internal_strcmp(const char *s1, const char *s2) {
+ while (true) {
+ unsigned c1 = *s1;
+ unsigned c2 = *s2;
+ if (c1 != c2) return (c1 < c2) ? -1 : 1;
+ if (c1 == 0) break;
+ s1++;
+ s2++;
+ }
+ return 0;
+}
+
+int internal_strncmp(const char *s1, const char *s2, uptr n) {
+ for (uptr i = 0; i < n; i++) {
+ unsigned c1 = *s1;
+ unsigned c2 = *s2;
+ if (c1 != c2) return (c1 < c2) ? -1 : 1;
+ if (c1 == 0) break;
+ s1++;
+ s2++;
+ }
+ return 0;
+}
+
+char* internal_strchr(const char *s, int c) {
+ while (true) {
+ if (*s == (char)c)
+ return const_cast<char *>(s);
+ if (*s == 0)
+ return nullptr;
+ s++;
+ }
+}
+
+char *internal_strchrnul(const char *s, int c) {
+ char *res = internal_strchr(s, c);
+ if (!res)
+ res = const_cast<char *>(s) + internal_strlen(s);
+ return res;
+}
+
+char *internal_strrchr(const char *s, int c) {
+ const char *res = nullptr;
+ for (uptr i = 0; s[i]; i++) {
+ if (s[i] == c) res = s + i;
+ }
+ return const_cast<char *>(res);
+}
+
+uptr internal_strlen(const char *s) {
+ uptr i = 0;
+ while (s[i]) i++;
+ return i;
+}
+
+uptr internal_strlcat(char *dst, const char *src, uptr maxlen) {
+ const uptr srclen = internal_strlen(src);
+ const uptr dstlen = internal_strnlen(dst, maxlen);
+ if (dstlen == maxlen) return maxlen + srclen;
+ if (srclen < maxlen - dstlen) {
+ internal_memmove(dst + dstlen, src, srclen + 1);
+ } else {
+ internal_memmove(dst + dstlen, src, maxlen - dstlen - 1);
+ dst[maxlen - 1] = '\0';
+ }
+ return dstlen + srclen;
+}
+
+char *internal_strncat(char *dst, const char *src, uptr n) {
+ uptr len = internal_strlen(dst);
+ uptr i;
+ for (i = 0; i < n && src[i]; i++)
+ dst[len + i] = src[i];
+ dst[len + i] = 0;
+ return dst;
+}
+
+uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) {
+ const uptr srclen = internal_strlen(src);
+ if (srclen < maxlen) {
+ internal_memmove(dst, src, srclen + 1);
+ } else if (maxlen != 0) {
+ internal_memmove(dst, src, maxlen - 1);
+ dst[maxlen - 1] = '\0';
+ }
+ return srclen;
+}
+
+char *internal_strncpy(char *dst, const char *src, uptr n) {
+ uptr i;
+ for (i = 0; i < n && src[i]; i++)
+ dst[i] = src[i];
+ internal_memset(dst + i, '\0', n - i);
+ return dst;
+}
+
+uptr internal_strnlen(const char *s, uptr maxlen) {
+ uptr i = 0;
+ while (i < maxlen && s[i]) i++;
+ return i;
+}
+
+char *internal_strstr(const char *haystack, const char *needle) {
+ // This is O(N^2), but we are not using it in hot places.
+ uptr len1 = internal_strlen(haystack);
+ uptr len2 = internal_strlen(needle);
+ if (len1 < len2) return nullptr;
+ for (uptr pos = 0; pos <= len1 - len2; pos++) {
+ if (internal_memcmp(haystack + pos, needle, len2) == 0)
+ return const_cast<char *>(haystack) + pos;
+ }
+ return nullptr;
+}
+
+s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base) {
+ CHECK_EQ(base, 10);
+ while (IsSpace(*nptr)) nptr++;
+ int sgn = 1;
+ u64 res = 0;
+ bool have_digits = false;
+ char *old_nptr = const_cast<char *>(nptr);
+ if (*nptr == '+') {
+ sgn = 1;
+ nptr++;
+ } else if (*nptr == '-') {
+ sgn = -1;
+ nptr++;
+ }
+ while (IsDigit(*nptr)) {
+ res = (res <= UINT64_MAX / 10) ? res * 10 : UINT64_MAX;
+ int digit = ((*nptr) - '0');
+ res = (res <= UINT64_MAX - digit) ? res + digit : UINT64_MAX;
+ have_digits = true;
+ nptr++;
+ }
+ if (endptr) {
+ *endptr = (have_digits) ? const_cast<char *>(nptr) : old_nptr;
+ }
+ if (sgn > 0) {
+ return (s64)(Min((u64)INT64_MAX, res));
+ } else {
+ return (res > INT64_MAX) ? INT64_MIN : ((s64)res * -1);
+ }
+}
+
+uptr internal_wcslen(const wchar_t *s) {
+ uptr i = 0;
+ while (s[i]) i++;
+ return i;
+}
+
+uptr internal_wcsnlen(const wchar_t *s, uptr maxlen) {
+ uptr i = 0;
+ while (i < maxlen && s[i]) i++;
+ return i;
+}
+
+bool mem_is_zero(const char *beg, uptr size) {
+ CHECK_LE(size, 1ULL << FIRST_32_SECOND_64(30, 40)); // Sanity check.
+ const char *end = beg + size;
+ uptr *aligned_beg = (uptr *)RoundUpTo((uptr)beg, sizeof(uptr));
+ uptr *aligned_end = (uptr *)RoundDownTo((uptr)end, sizeof(uptr));
+ uptr all = 0;
+ // Prologue.
+ for (const char *mem = beg; mem < (char*)aligned_beg && mem < end; mem++)
+ all |= *mem;
+ // Aligned loop.
+ for (; aligned_beg < aligned_end; aligned_beg++)
+ all |= *aligned_beg;
+ // Epilogue.
+ if ((char *)aligned_end >= beg) {
+ for (const char *mem = (char *)aligned_end; mem < end; mem++) all |= *mem;
+ }
+ return all == 0;
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libc.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libc.h
new file mode 100644
index 00000000000..39a212665d0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libc.h
@@ -0,0 +1,89 @@
+//===-- sanitizer_libc.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+// These tools can not use some of the libc functions directly because those
+// functions are intercepted. Instead, we implement a tiny subset of libc here.
+// FIXME: Some of functions declared in this file are in fact POSIX, not libc.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_LIBC_H
+#define SANITIZER_LIBC_H
+
+// ----------- ATTENTION -------------
+// This header should NOT include any other headers from sanitizer runtime.
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+// internal_X() is a custom implementation of X() for use in RTL.
+
+// String functions
+s64 internal_atoll(const char *nptr);
+void *internal_memchr(const void *s, int c, uptr n);
+void *internal_memrchr(const void *s, int c, uptr n);
+int internal_memcmp(const void* s1, const void* s2, uptr n);
+void *internal_memcpy(void *dest, const void *src, uptr n);
+void *internal_memmove(void *dest, const void *src, uptr n);
+// Should not be used in performance-critical places.
+void *internal_memset(void *s, int c, uptr n);
+char* internal_strchr(const char *s, int c);
+char *internal_strchrnul(const char *s, int c);
+int internal_strcmp(const char *s1, const char *s2);
+uptr internal_strcspn(const char *s, const char *reject);
+char *internal_strdup(const char *s);
+uptr internal_strlen(const char *s);
+uptr internal_strlcat(char *dst, const char *src, uptr maxlen);
+char *internal_strncat(char *dst, const char *src, uptr n);
+int internal_strncmp(const char *s1, const char *s2, uptr n);
+uptr internal_strlcpy(char *dst, const char *src, uptr maxlen);
+char *internal_strncpy(char *dst, const char *src, uptr n);
+uptr internal_strnlen(const char *s, uptr maxlen);
+char *internal_strrchr(const char *s, int c);
+char *internal_strstr(const char *haystack, const char *needle);
+// Works only for base=10 and doesn't set errno.
+s64 internal_simple_strtoll(const char *nptr, const char **endptr, int base);
+int internal_snprintf(char *buffer, uptr length, const char *format, ...)
+ FORMAT(3, 4);
+uptr internal_wcslen(const wchar_t *s);
+uptr internal_wcsnlen(const wchar_t *s, uptr maxlen);
+
+// Return true if all bytes in [mem, mem+size) are zero.
+// Optimized for the case when the result is true.
+bool mem_is_zero(const char *mem, uptr size);
+
+// I/O
+// Define these as macros so we can use them in linker initialized global
+// structs without dynamic initialization.
+#define kInvalidFd ((fd_t)-1)
+#define kStdinFd ((fd_t)0)
+#define kStdoutFd ((fd_t)1)
+#define kStderrFd ((fd_t)2)
+
+uptr internal_ftruncate(fd_t fd, uptr size);
+
+// OS
+void NORETURN internal__exit(int exitcode);
+void internal_sleep(unsigned seconds);
+void internal_usleep(u64 useconds);
+
+uptr internal_getpid();
+uptr internal_getppid();
+
+int internal_dlinfo(void *handle, int request, void *p);
+
+// Threading
+uptr internal_sched_yield();
+
+// Error handling
+bool internal_iserror(uptr retval, int *rverrno = nullptr);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_LIBC_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libignore.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libignore.cpp
new file mode 100644
index 00000000000..b7fc9444cc6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libignore.cpp
@@ -0,0 +1,129 @@
+//===-- sanitizer_libignore.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \
+ SANITIZER_NETBSD
+
+#include "sanitizer_libignore.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_posix.h"
+#include "sanitizer_procmaps.h"
+
+namespace __sanitizer {
+
+LibIgnore::LibIgnore(LinkerInitialized) {
+}
+
+void LibIgnore::AddIgnoredLibrary(const char *name_templ) {
+ Lock lock(&mutex_);
+ if (count_ >= kMaxLibs) {
+ Report("%s: too many ignored libraries (max: %zu)\n", SanitizerToolName,
+ kMaxLibs);
+ Die();
+ }
+ Lib *lib = &libs_[count_++];
+ lib->templ = internal_strdup(name_templ);
+ lib->name = nullptr;
+ lib->real_name = nullptr;
+ lib->loaded = false;
+}
+
+void LibIgnore::OnLibraryLoaded(const char *name) {
+ Lock lock(&mutex_);
+ // Try to match suppressions with symlink target.
+ InternalMmapVector<char> buf(kMaxPathLength);
+ if (name && internal_readlink(name, buf.data(), buf.size() - 1) > 0 &&
+ buf[0]) {
+ for (uptr i = 0; i < count_; i++) {
+ Lib *lib = &libs_[i];
+ if (!lib->loaded && (!lib->real_name) &&
+ TemplateMatch(lib->templ, name))
+ lib->real_name = internal_strdup(buf.data());
+ }
+ }
+
+ // Scan suppressions list and find newly loaded and unloaded libraries.
+ ListOfModules modules;
+ modules.init();
+ for (uptr i = 0; i < count_; i++) {
+ Lib *lib = &libs_[i];
+ bool loaded = false;
+ for (const auto &mod : modules) {
+ for (const auto &range : mod.ranges()) {
+ if (!range.executable)
+ continue;
+ if (!TemplateMatch(lib->templ, mod.full_name()) &&
+ !(lib->real_name &&
+ internal_strcmp(lib->real_name, mod.full_name()) == 0))
+ continue;
+ if (loaded) {
+ Report("%s: called_from_lib suppression '%s' is matched against"
+ " 2 libraries: '%s' and '%s'\n",
+ SanitizerToolName, lib->templ, lib->name, mod.full_name());
+ Die();
+ }
+ loaded = true;
+ if (lib->loaded)
+ continue;
+ VReport(1,
+ "Matched called_from_lib suppression '%s' against library"
+ " '%s'\n",
+ lib->templ, mod.full_name());
+ lib->loaded = true;
+ lib->name = internal_strdup(mod.full_name());
+ const uptr idx =
+ atomic_load(&ignored_ranges_count_, memory_order_relaxed);
+ CHECK_LT(idx, ARRAY_SIZE(ignored_code_ranges_));
+ ignored_code_ranges_[idx].begin = range.beg;
+ ignored_code_ranges_[idx].end = range.end;
+ atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release);
+ break;
+ }
+ }
+ if (lib->loaded && !loaded) {
+ Report("%s: library '%s' that was matched against called_from_lib"
+ " suppression '%s' is unloaded\n",
+ SanitizerToolName, lib->name, lib->templ);
+ Die();
+ }
+ }
+
+ // Track instrumented ranges.
+ if (track_instrumented_libs_) {
+ for (const auto &mod : modules) {
+ if (!mod.instrumented())
+ continue;
+ for (const auto &range : mod.ranges()) {
+ if (!range.executable)
+ continue;
+ if (IsPcInstrumented(range.beg) && IsPcInstrumented(range.end - 1))
+ continue;
+ VReport(1, "Adding instrumented range 0x%zx-0x%zx from library '%s'\n",
+ range.beg, range.end, mod.full_name());
+ const uptr idx =
+ atomic_load(&instrumented_ranges_count_, memory_order_relaxed);
+ CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_));
+ instrumented_code_ranges_[idx].begin = range.beg;
+ instrumented_code_ranges_[idx].end = range.end;
+ atomic_store(&instrumented_ranges_count_, idx + 1,
+ memory_order_release);
+ }
+ }
+ }
+}
+
+void LibIgnore::OnLibraryUnloaded() {
+ OnLibraryLoaded(nullptr);
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE ||
+ // SANITIZER_NETBSD
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libignore.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libignore.h
new file mode 100644
index 00000000000..18e4d83ed77
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_libignore.h
@@ -0,0 +1,115 @@
+//===-- sanitizer_libignore.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// LibIgnore allows to ignore all interceptors called from a particular set
+// of dynamic libraries. LibIgnore can be initialized with several templates
+// of names of libraries to be ignored. It finds code ranges for the libraries;
+// and checks whether the provided PC value belongs to the code ranges.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_LIBIGNORE_H
+#define SANITIZER_LIBIGNORE_H
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_common.h"
+#include "sanitizer_atomic.h"
+#include "sanitizer_mutex.h"
+
+namespace __sanitizer {
+
+class LibIgnore {
+ public:
+ explicit LibIgnore(LinkerInitialized);
+
+ // Must be called during initialization.
+ void AddIgnoredLibrary(const char *name_templ);
+ void IgnoreNoninstrumentedModules(bool enable) {
+ track_instrumented_libs_ = enable;
+ }
+
+ // Must be called after a new dynamic library is loaded.
+ void OnLibraryLoaded(const char *name);
+
+ // Must be called after a dynamic library is unloaded.
+ void OnLibraryUnloaded();
+
+ // Checks whether the provided PC belongs to one of the ignored libraries or
+ // the PC should be ignored because it belongs to an non-instrumented module
+ // (when ignore_noninstrumented_modules=1). Also returns true via
+ // "pc_in_ignored_lib" if the PC is in an ignored library, false otherwise.
+ bool IsIgnored(uptr pc, bool *pc_in_ignored_lib) const;
+
+ // Checks whether the provided PC belongs to an instrumented module.
+ bool IsPcInstrumented(uptr pc) const;
+
+ private:
+ struct Lib {
+ char *templ;
+ char *name;
+ char *real_name; // target of symlink
+ bool loaded;
+ };
+
+ struct LibCodeRange {
+ uptr begin;
+ uptr end;
+ };
+
+ inline bool IsInRange(uptr pc, const LibCodeRange &range) const {
+ return (pc >= range.begin && pc < range.end);
+ }
+
+ static const uptr kMaxIgnoredRanges = 128;
+ static const uptr kMaxInstrumentedRanges = 1024;
+ static const uptr kMaxLibs = 1024;
+
+ // Hot part:
+ atomic_uintptr_t ignored_ranges_count_;
+ LibCodeRange ignored_code_ranges_[kMaxIgnoredRanges];
+
+ atomic_uintptr_t instrumented_ranges_count_;
+ LibCodeRange instrumented_code_ranges_[kMaxInstrumentedRanges];
+
+ // Cold part:
+ Mutex mutex_;
+ uptr count_;
+ Lib libs_[kMaxLibs];
+ bool track_instrumented_libs_;
+
+ // Disallow copying of LibIgnore objects.
+ LibIgnore(const LibIgnore&); // not implemented
+ void operator = (const LibIgnore&); // not implemented
+};
+
+inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {
+ const uptr n = atomic_load(&ignored_ranges_count_, memory_order_acquire);
+ for (uptr i = 0; i < n; i++) {
+ if (IsInRange(pc, ignored_code_ranges_[i])) {
+ *pc_in_ignored_lib = true;
+ return true;
+ }
+ }
+ *pc_in_ignored_lib = false;
+ if (track_instrumented_libs_ && !IsPcInstrumented(pc))
+ return true;
+ return false;
+}
+
+inline bool LibIgnore::IsPcInstrumented(uptr pc) const {
+ const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire);
+ for (uptr i = 0; i < n; i++) {
+ if (IsInRange(pc, instrumented_code_ranges_[i]))
+ return true;
+ }
+ return false;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_LIBIGNORE_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux.cpp
new file mode 100644
index 00000000000..19a5ee8926d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux.cpp
@@ -0,0 +1,2428 @@
+//===-- sanitizer_linux.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries and implements linux-specific functions from
+// sanitizer_libc.h.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
+ SANITIZER_SOLARIS
+
+#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_getauxval.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_mutex.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_procmaps.h"
+
+#if SANITIZER_LINUX && !SANITIZER_GO
+#include <asm/param.h>
+#endif
+
+// For mips64, syscall(__NR_stat) fills the buffer in the 'struct kernel_stat'
+// format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To
+// access stat from asm/stat.h, without conflicting with definition in
+// sys/stat.h, we use this trick.
+#if SANITIZER_MIPS64
+#include <asm/unistd.h>
+#include <sys/types.h>
+#define stat kernel_stat
+#if SANITIZER_GO
+#undef st_atime
+#undef st_mtime
+#undef st_ctime
+#define st_atime st_atim
+#define st_mtime st_mtim
+#define st_ctime st_ctim
+#endif
+#include <asm/stat.h>
+#undef stat
+#endif
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <link.h>
+#include <pthread.h>
+#include <sched.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#if !SANITIZER_SOLARIS
+#include <sys/ptrace.h>
+#endif
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+#if SANITIZER_LINUX
+#include <sys/utsname.h>
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#include <sys/personality.h>
+#endif
+
+#if SANITIZER_LINUX && defined(__loongarch__)
+# include <sys/sysmacros.h>
+#endif
+
+#if SANITIZER_FREEBSD
+#include <sys/exec.h>
+#error #include <sys/procctl.h>
+#include <sys/sysctl.h>
+#include <machine/atomic.h>
+extern "C" {
+// <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on
+// FreeBSD 9.2 and 10.0.
+#include <sys/umtx.h>
+}
+#include <sys/thr.h>
+#endif // SANITIZER_FREEBSD
+
+#if SANITIZER_NETBSD
+#include <limits.h> // For NAME_MAX
+#include <sys/sysctl.h>
+#include <sys/exec.h>
+extern struct ps_strings *__ps_strings;
+#endif // SANITIZER_NETBSD
+
+#if SANITIZER_SOLARIS
+#include <stdlib.h>
+#include <thread.h>
+#define environ _environ
+#endif
+
+extern char **environ;
+
+#if SANITIZER_LINUX
+// <linux/time.h>
+struct kernel_timeval {
+ long tv_sec;
+ long tv_usec;
+};
+
+// <linux/futex.h> is broken on some linux distributions.
+const int FUTEX_WAIT = 0;
+const int FUTEX_WAKE = 1;
+const int FUTEX_PRIVATE_FLAG = 128;
+const int FUTEX_WAIT_PRIVATE = FUTEX_WAIT | FUTEX_PRIVATE_FLAG;
+const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;
+#endif // SANITIZER_LINUX
+
+// Are we using 32-bit or 64-bit Linux syscalls?
+// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
+// but it still needs to use 64-bit syscalls.
+#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__powerpc64__) || \
+ SANITIZER_WORDSIZE == 64 || \
+ (defined(__mips__) && _MIPS_SIM == _ABIN32))
+# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
+#else
+# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
+#endif
+
+// Note : FreeBSD had implemented both
+// Linux apis, available from
+// future 12.x version most likely
+#if SANITIZER_LINUX && defined(__NR_getrandom)
+# if !defined(GRND_NONBLOCK)
+# define GRND_NONBLOCK 1
+# endif
+# define SANITIZER_USE_GETRANDOM 1
+#else
+# define SANITIZER_USE_GETRANDOM 0
+#endif // SANITIZER_LINUX && defined(__NR_getrandom)
+
+#if SANITIZER_FREEBSD && __FreeBSD_version >= 1200000
+# define SANITIZER_USE_GETENTROPY 1
+#else
+# define SANITIZER_USE_GETENTROPY 0
+#endif
+
+namespace __sanitizer {
+
+void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *old) {
+ CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, set, old));
+}
+
+ScopedBlockSignals::ScopedBlockSignals(__sanitizer_sigset_t *copy) {
+ __sanitizer_sigset_t set;
+ internal_sigfillset(&set);
+# if SANITIZER_LINUX && !SANITIZER_ANDROID
+ // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked
+ // on any thread, setuid call hangs.
+ // See test/sanitizer_common/TestCases/Linux/setuid.c.
+ internal_sigdelset(&set, 33);
+# endif
+# if SANITIZER_LINUX
+ // Seccomp-BPF-sandboxed processes rely on SIGSYS to handle trapped syscalls.
+ // If this signal is blocked, such calls cannot be handled and the process may
+ // hang.
+ internal_sigdelset(&set, 31);
+# endif
+ SetSigProcMask(&set, &saved_);
+ if (copy)
+ internal_memcpy(copy, &saved_, sizeof(saved_));
+}
+
+ScopedBlockSignals::~ScopedBlockSignals() { SetSigProcMask(&saved_, nullptr); }
+
+# if SANITIZER_LINUX && defined(__x86_64__)
+# include "sanitizer_syscall_linux_x86_64.inc"
+# elif SANITIZER_LINUX && SANITIZER_RISCV64
+# include "sanitizer_syscall_linux_riscv64.inc"
+# elif SANITIZER_LINUX && defined(__aarch64__)
+# include "sanitizer_syscall_linux_aarch64.inc"
+# elif SANITIZER_LINUX && defined(__arm__)
+# include "sanitizer_syscall_linux_arm.inc"
+# elif SANITIZER_LINUX && defined(__hexagon__)
+# include "sanitizer_syscall_linux_hexagon.inc"
+# elif SANITIZER_LINUX && SANITIZER_LOONGARCH64
+# include "sanitizer_syscall_linux_loongarch64.inc"
+# else
+# include "sanitizer_syscall_generic.inc"
+# endif
+
+// --------------- sanitizer_libc.h
+#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
+#if !SANITIZER_S390
+uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
+ u64 offset) {
+#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
+ return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
+ offset);
+#else
+ // mmap2 specifies file offset in 4096-byte units.
+ CHECK(IsAligned(offset, 4096));
+ return internal_syscall(SYSCALL(mmap2), addr, length, prot, flags, fd,
+ offset / 4096);
+#endif
+}
+#endif // !SANITIZER_S390
+
+uptr internal_munmap(void *addr, uptr length) {
+ return internal_syscall(SYSCALL(munmap), (uptr)addr, length);
+}
+
+#if SANITIZER_LINUX
+uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags,
+ void *new_address) {
+ return internal_syscall(SYSCALL(mremap), (uptr)old_address, old_size,
+ new_size, flags, (uptr)new_address);
+}
+#endif
+
+int internal_mprotect(void *addr, uptr length, int prot) {
+ return internal_syscall(SYSCALL(mprotect), (uptr)addr, length, prot);
+}
+
+int internal_madvise(uptr addr, uptr length, int advice) {
+ return internal_syscall(SYSCALL(madvise), addr, length, advice);
+}
+
+uptr internal_close(fd_t fd) {
+ return internal_syscall(SYSCALL(close), fd);
+}
+
+uptr internal_open(const char *filename, int flags) {
+# if SANITIZER_LINUX
+ return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags);
+#else
+ return internal_syscall(SYSCALL(open), (uptr)filename, flags);
+#endif
+}
+
+uptr internal_open(const char *filename, int flags, u32 mode) {
+# if SANITIZER_LINUX
+ return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags,
+ mode);
+#else
+ return internal_syscall(SYSCALL(open), (uptr)filename, flags, mode);
+#endif
+}
+
+uptr internal_read(fd_t fd, void *buf, uptr count) {
+ sptr res;
+ HANDLE_EINTR(res,
+ (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf, count));
+ return res;
+}
+
+uptr internal_write(fd_t fd, const void *buf, uptr count) {
+ sptr res;
+ HANDLE_EINTR(res,
+ (sptr)internal_syscall(SYSCALL(write), fd, (uptr)buf, count));
+ return res;
+}
+
+uptr internal_ftruncate(fd_t fd, uptr size) {
+ sptr res;
+ HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd,
+ (OFF_T)size));
+ return res;
+}
+
+#if (!SANITIZER_LINUX_USES_64BIT_SYSCALLS || SANITIZER_SPARC) && SANITIZER_LINUX
+static void stat64_to_stat(struct stat64 *in, struct stat *out) {
+ internal_memset(out, 0, sizeof(*out));
+ out->st_dev = in->st_dev;
+ out->st_ino = in->st_ino;
+ out->st_mode = in->st_mode;
+ out->st_nlink = in->st_nlink;
+ out->st_uid = in->st_uid;
+ out->st_gid = in->st_gid;
+ out->st_rdev = in->st_rdev;
+ out->st_size = in->st_size;
+ out->st_blksize = in->st_blksize;
+ out->st_blocks = in->st_blocks;
+ out->st_atime = in->st_atime;
+ out->st_mtime = in->st_mtime;
+ out->st_ctime = in->st_ctime;
+}
+#endif
+
+#if SANITIZER_LINUX && defined(__loongarch__)
+static void statx_to_stat(struct statx *in, struct stat *out) {
+ internal_memset(out, 0, sizeof(*out));
+ out->st_dev = makedev(in->stx_dev_major, in->stx_dev_minor);
+ out->st_ino = in->stx_ino;
+ out->st_mode = in->stx_mode;
+ out->st_nlink = in->stx_nlink;
+ out->st_uid = in->stx_uid;
+ out->st_gid = in->stx_gid;
+ out->st_rdev = makedev(in->stx_rdev_major, in->stx_rdev_minor);
+ out->st_size = in->stx_size;
+ out->st_blksize = in->stx_blksize;
+ out->st_blocks = in->stx_blocks;
+ out->st_atime = in->stx_atime.tv_sec;
+ out->st_atim.tv_nsec = in->stx_atime.tv_nsec;
+ out->st_mtime = in->stx_mtime.tv_sec;
+ out->st_mtim.tv_nsec = in->stx_mtime.tv_nsec;
+ out->st_ctime = in->stx_ctime.tv_sec;
+ out->st_ctim.tv_nsec = in->stx_ctime.tv_nsec;
+}
+#endif
+
+#if SANITIZER_MIPS64
+// Undefine compatibility macros from <sys/stat.h>
+// so that they would not clash with the kernel_stat
+// st_[a|m|c]time fields
+#if !SANITIZER_GO
+#undef st_atime
+#undef st_mtime
+#undef st_ctime
+#endif
+#if defined(SANITIZER_ANDROID)
+// Bionic sys/stat.h defines additional macros
+// for compatibility with the old NDKs and
+// they clash with the kernel_stat structure
+// st_[a|m|c]time_nsec fields.
+#undef st_atime_nsec
+#undef st_mtime_nsec
+#undef st_ctime_nsec
+#endif
+static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
+ internal_memset(out, 0, sizeof(*out));
+ out->st_dev = in->st_dev;
+ out->st_ino = in->st_ino;
+ out->st_mode = in->st_mode;
+ out->st_nlink = in->st_nlink;
+ out->st_uid = in->st_uid;
+ out->st_gid = in->st_gid;
+ out->st_rdev = in->st_rdev;
+ out->st_size = in->st_size;
+ out->st_blksize = in->st_blksize;
+ out->st_blocks = in->st_blocks;
+#if defined(__USE_MISC) || \
+ defined(__USE_XOPEN2K8) || \
+ defined(SANITIZER_ANDROID)
+ out->st_atim.tv_sec = in->st_atime;
+ out->st_atim.tv_nsec = in->st_atime_nsec;
+ out->st_mtim.tv_sec = in->st_mtime;
+ out->st_mtim.tv_nsec = in->st_mtime_nsec;
+ out->st_ctim.tv_sec = in->st_ctime;
+ out->st_ctim.tv_nsec = in->st_ctime_nsec;
+#else
+ out->st_atime = in->st_atime;
+ out->st_atimensec = in->st_atime_nsec;
+ out->st_mtime = in->st_mtime;
+ out->st_mtimensec = in->st_mtime_nsec;
+ out->st_ctime = in->st_ctime;
+ out->st_atimensec = in->st_ctime_nsec;
+#endif
+}
+#endif
+
+uptr internal_stat(const char *path, void *buf) {
+# if SANITIZER_FREEBSD
+ return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0);
+# elif SANITIZER_LINUX
+# if defined(__loongarch__)
+ struct statx bufx;
+ int res = internal_syscall(SYSCALL(statx), AT_FDCWD, (uptr)path,
+ AT_NO_AUTOMOUNT, STATX_BASIC_STATS, (uptr)&bufx);
+ statx_to_stat(&bufx, (struct stat *)buf);
+ return res;
+# elif (SANITIZER_WORDSIZE == 64 || SANITIZER_X32 || \
+ (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \
+ !SANITIZER_SPARC
+ return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
+ 0);
+# else
+ struct stat64 buf64;
+ int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
+ (uptr)&buf64, 0);
+ stat64_to_stat(&buf64, (struct stat *)buf);
+ return res;
+# endif
+# else
+ struct stat64 buf64;
+ int res = internal_syscall(SYSCALL(stat64), path, &buf64);
+ stat64_to_stat(&buf64, (struct stat *)buf);
+ return res;
+# endif
+}
+
+uptr internal_lstat(const char *path, void *buf) {
+# if SANITIZER_FREEBSD
+ return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf,
+ AT_SYMLINK_NOFOLLOW);
+# elif SANITIZER_LINUX
+# if defined(__loongarch__)
+ struct statx bufx;
+ int res = internal_syscall(SYSCALL(statx), AT_FDCWD, (uptr)path,
+ AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT,
+ STATX_BASIC_STATS, (uptr)&bufx);
+ statx_to_stat(&bufx, (struct stat *)buf);
+ return res;
+# elif (defined(_LP64) || SANITIZER_X32 || \
+ (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \
+ !SANITIZER_SPARC
+ return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
+ AT_SYMLINK_NOFOLLOW);
+# else
+ struct stat64 buf64;
+ int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
+ (uptr)&buf64, AT_SYMLINK_NOFOLLOW);
+ stat64_to_stat(&buf64, (struct stat *)buf);
+ return res;
+# endif
+# else
+ struct stat64 buf64;
+ int res = internal_syscall(SYSCALL(lstat64), path, &buf64);
+ stat64_to_stat(&buf64, (struct stat *)buf);
+ return res;
+# endif
+}
+
+uptr internal_fstat(fd_t fd, void *buf) {
+#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
+#if SANITIZER_MIPS64
+ // For mips64, fstat syscall fills buffer in the format of kernel_stat
+ struct kernel_stat kbuf;
+ int res = internal_syscall(SYSCALL(fstat), fd, &kbuf);
+ kernel_stat_to_stat(&kbuf, (struct stat *)buf);
+ return res;
+# elif SANITIZER_LINUX && defined(__loongarch__)
+ struct statx bufx;
+ int res = internal_syscall(SYSCALL(statx), fd, "", AT_EMPTY_PATH,
+ STATX_BASIC_STATS, (uptr)&bufx);
+ statx_to_stat(&bufx, (struct stat *)buf);
+ return res;
+# else
+ return internal_syscall(SYSCALL(fstat), fd, (uptr)buf);
+# endif
+#else
+ struct stat64 buf64;
+ int res = internal_syscall(SYSCALL(fstat64), fd, &buf64);
+ stat64_to_stat(&buf64, (struct stat *)buf);
+ return res;
+#endif
+}
+
+uptr internal_filesize(fd_t fd) {
+ struct stat st;
+ if (internal_fstat(fd, &st))
+ return -1;
+ return (uptr)st.st_size;
+}
+
+uptr internal_dup(int oldfd) {
+ return internal_syscall(SYSCALL(dup), oldfd);
+}
+
+uptr internal_dup2(int oldfd, int newfd) {
+# if SANITIZER_LINUX
+ return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);
+#else
+ return internal_syscall(SYSCALL(dup2), oldfd, newfd);
+#endif
+}
+
+uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
+# if SANITIZER_LINUX
+ return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, (uptr)path, (uptr)buf,
+ bufsize);
+#else
+ return internal_syscall(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize);
+#endif
+}
+
+uptr internal_unlink(const char *path) {
+# if SANITIZER_LINUX
+ return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0);
+#else
+ return internal_syscall(SYSCALL(unlink), (uptr)path);
+#endif
+}
+
+uptr internal_rename(const char *oldpath, const char *newpath) {
+# if (defined(__riscv) || defined(__loongarch__)) && defined(__linux__)
+ return internal_syscall(SYSCALL(renameat2), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
+ (uptr)newpath, 0);
+# elif SANITIZER_LINUX
+ return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
+ (uptr)newpath);
+# else
+ return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath);
+# endif
+}
+
+uptr internal_sched_yield() {
+ return internal_syscall(SYSCALL(sched_yield));
+}
+
+void internal_usleep(u64 useconds) {
+ struct timespec ts;
+ ts.tv_sec = useconds / 1000000;
+ ts.tv_nsec = (useconds % 1000000) * 1000;
+ internal_syscall(SYSCALL(nanosleep), &ts, &ts);
+}
+
+uptr internal_execve(const char *filename, char *const argv[],
+ char *const envp[]) {
+ return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv,
+ (uptr)envp);
+}
+#endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD
+
+#if !SANITIZER_NETBSD
+void internal__exit(int exitcode) {
+#if SANITIZER_FREEBSD || SANITIZER_SOLARIS
+ internal_syscall(SYSCALL(exit), exitcode);
+#else
+ internal_syscall(SYSCALL(exit_group), exitcode);
+#endif
+ Die(); // Unreachable.
+}
+#endif // !SANITIZER_NETBSD
+
+// ----------------- sanitizer_common.h
+bool FileExists(const char *filename) {
+ if (ShouldMockFailureToOpen(filename))
+ return false;
+ struct stat st;
+ if (internal_stat(filename, &st))
+ return false;
+ // Sanity check: filename is a regular file.
+ return S_ISREG(st.st_mode);
+}
+
+bool DirExists(const char *path) {
+ struct stat st;
+ if (internal_stat(path, &st))
+ return false;
+ return S_ISDIR(st.st_mode);
+}
+
+# if !SANITIZER_NETBSD
+tid_t GetTid() {
+#if SANITIZER_FREEBSD
+ long Tid;
+ thr_self(&Tid);
+ return Tid;
+#elif SANITIZER_SOLARIS
+ return thr_self();
+#else
+ return internal_syscall(SYSCALL(gettid));
+#endif
+}
+
+int TgKill(pid_t pid, tid_t tid, int sig) {
+#if SANITIZER_LINUX
+ return internal_syscall(SYSCALL(tgkill), pid, tid, sig);
+#elif SANITIZER_FREEBSD
+ return internal_syscall(SYSCALL(thr_kill2), pid, tid, sig);
+#elif SANITIZER_SOLARIS
+ (void)pid;
+ return thr_kill(tid, sig);
+#endif
+}
+#endif
+
+#if SANITIZER_GLIBC
+u64 NanoTime() {
+ kernel_timeval tv;
+ internal_memset(&tv, 0, sizeof(tv));
+ internal_syscall(SYSCALL(gettimeofday), &tv, 0);
+ return (u64)tv.tv_sec * 1000 * 1000 * 1000 + tv.tv_usec * 1000;
+}
+// Used by real_clock_gettime.
+uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
+ return internal_syscall(SYSCALL(clock_gettime), clk_id, tp);
+}
+#elif !SANITIZER_SOLARIS && !SANITIZER_NETBSD
+u64 NanoTime() {
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ return (u64)ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
+}
+#endif
+
+// Like getenv, but reads env directly from /proc (on Linux) or parses the
+// 'environ' array (on some others) and does not use libc. This function
+// should be called first inside __asan_init.
+const char *GetEnv(const char *name) {
+#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_SOLARIS
+ if (::environ != 0) {
+ uptr NameLen = internal_strlen(name);
+ for (char **Env = ::environ; *Env != 0; Env++) {
+ if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=')
+ return (*Env) + NameLen + 1;
+ }
+ }
+ return 0; // Not found.
+#elif SANITIZER_LINUX
+ static char *environ;
+ static uptr len;
+ static bool inited;
+ if (!inited) {
+ inited = true;
+ uptr environ_size;
+ if (!ReadFileToBuffer("/proc/self/environ", &environ, &environ_size, &len))
+ environ = nullptr;
+ }
+ if (!environ || len == 0) return nullptr;
+ uptr namelen = internal_strlen(name);
+ const char *p = environ;
+ while (*p != '\0') { // will happen at the \0\0 that terminates the buffer
+ // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
+ const char* endp =
+ (char*)internal_memchr(p, '\0', len - (p - environ));
+ if (!endp) // this entry isn't NUL terminated
+ return nullptr;
+ else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match.
+ return p + namelen + 1; // point after =
+ p = endp + 1;
+ }
+ return nullptr; // Not found.
+#else
+#error "Unsupported platform"
+#endif
+}
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_GO
+extern "C" {
+SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end;
+}
+#endif
+
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+static void ReadNullSepFileToArray(const char *path, char ***arr,
+ int arr_size) {
+ char *buff;
+ uptr buff_size;
+ uptr buff_len;
+ *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
+ if (!ReadFileToBuffer(path, &buff, &buff_size, &buff_len, 1024 * 1024)) {
+ (*arr)[0] = nullptr;
+ return;
+ }
+ (*arr)[0] = buff;
+ int count, i;
+ for (count = 1, i = 1; ; i++) {
+ if (buff[i] == 0) {
+ if (buff[i+1] == 0) break;
+ (*arr)[count] = &buff[i+1];
+ CHECK_LE(count, arr_size - 1); // FIXME: make this more flexible.
+ count++;
+ }
+ }
+ (*arr)[count] = nullptr;
+}
+#endif
+
+static void GetArgsAndEnv(char ***argv, char ***envp) {
+#if SANITIZER_FREEBSD
+ // On FreeBSD, retrieving the argument and environment arrays is done via the
+ // kern.ps_strings sysctl, which returns a pointer to a structure containing
+ // this information. See also <sys/exec.h>.
+ ps_strings *pss;
+ uptr sz = sizeof(pss);
+ if (internal_sysctlbyname("kern.ps_strings", &pss, &sz, NULL, 0) == -1) {
+ Printf("sysctl kern.ps_strings failed\n");
+ Die();
+ }
+ *argv = pss->ps_argvstr;
+ *envp = pss->ps_envstr;
+#elif SANITIZER_NETBSD
+ *argv = __ps_strings->ps_argvstr;
+ *envp = __ps_strings->ps_envstr;
+#else // SANITIZER_FREEBSD
+#if !SANITIZER_GO
+ if (&__libc_stack_end) {
+ uptr* stack_end = (uptr*)__libc_stack_end;
+ // Normally argc can be obtained from *stack_end, however, on ARM glibc's
+ // _start clobbers it:
+ // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/arm/start.S;hb=refs/heads/release/2.31/master#l75
+ // Do not special-case ARM and infer argc from argv everywhere.
+ int argc = 0;
+ while (stack_end[argc + 1]) argc++;
+ *argv = (char**)(stack_end + 1);
+ *envp = (char**)(stack_end + argc + 2);
+ } else {
+#endif // !SANITIZER_GO
+ static const int kMaxArgv = 2000, kMaxEnvp = 2000;
+ ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
+ ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
+#if !SANITIZER_GO
+ }
+#endif // !SANITIZER_GO
+#endif // SANITIZER_FREEBSD
+}
+
+char **GetArgv() {
+ char **argv, **envp;
+ GetArgsAndEnv(&argv, &envp);
+ return argv;
+}
+
+char **GetEnviron() {
+ char **argv, **envp;
+ GetArgsAndEnv(&argv, &envp);
+ return envp;
+}
+
+#if !SANITIZER_SOLARIS
+void FutexWait(atomic_uint32_t *p, u32 cmp) {
+# if SANITIZER_FREEBSD
+ _umtx_op(p, UMTX_OP_WAIT_UINT, cmp, 0, 0);
+# elif SANITIZER_NETBSD
+ sched_yield(); /* No userspace futex-like synchronization */
+# else
+ internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAIT_PRIVATE, cmp, 0, 0, 0);
+# endif
+}
+
+void FutexWake(atomic_uint32_t *p, u32 count) {
+# if SANITIZER_FREEBSD
+ _umtx_op(p, UMTX_OP_WAKE, count, 0, 0);
+# elif SANITIZER_NETBSD
+ /* No userspace futex-like synchronization */
+# else
+ internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAKE_PRIVATE, count, 0, 0, 0);
+# endif
+}
+
+# endif // !SANITIZER_SOLARIS
+
+// ----------------- sanitizer_linux.h
+// The actual size of this structure is specified by d_reclen.
+// Note that getdents64 uses a different structure format. We only provide the
+// 32-bit syscall here.
+#if SANITIZER_NETBSD
+// Not used
+#else
+struct linux_dirent {
+# if SANITIZER_X32 || SANITIZER_LINUX
+ u64 d_ino;
+ u64 d_off;
+# else
+ unsigned long d_ino;
+ unsigned long d_off;
+# endif
+ unsigned short d_reclen;
+# if SANITIZER_LINUX
+ unsigned char d_type;
+# endif
+ char d_name[256];
+};
+#endif
+
+#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD
+// Syscall wrappers.
+uptr internal_ptrace(int request, int pid, void *addr, void *data) {
+ return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,
+ (uptr)data);
+}
+
+uptr internal_waitpid(int pid, int *status, int options) {
+ return internal_syscall(SYSCALL(wait4), pid, (uptr)status, options,
+ 0 /* rusage */);
+}
+
+uptr internal_getpid() {
+ return internal_syscall(SYSCALL(getpid));
+}
+
+uptr internal_getppid() {
+ return internal_syscall(SYSCALL(getppid));
+}
+
+int internal_dlinfo(void *handle, int request, void *p) {
+#if SANITIZER_FREEBSD
+ return dlinfo(handle, request, p);
+#else
+ UNIMPLEMENTED();
+#endif
+}
+
+uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
+#if SANITIZER_FREEBSD
+ return internal_syscall(SYSCALL(getdirentries), fd, (uptr)dirp, count, NULL);
+# elif SANITIZER_LINUX
+ return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);
+# else
+ return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count);
+# endif
+}
+
+uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
+ return internal_syscall(SYSCALL(lseek), fd, offset, whence);
+}
+
+#if SANITIZER_LINUX
+uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
+ return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5);
+}
+# if defined(__x86_64__)
+# include <asm/unistd_64.h>
+// Currently internal_arch_prctl() is only needed on x86_64.
+uptr internal_arch_prctl(int option, uptr arg2) {
+ return internal_syscall(__NR_arch_prctl, option, arg2);
+}
+# endif
+# endif
+
+uptr internal_sigaltstack(const void *ss, void *oss) {
+ return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);
+}
+
+int internal_fork() {
+# if SANITIZER_LINUX
+# if SANITIZER_S390
+ return internal_syscall(SYSCALL(clone), 0, SIGCHLD);
+# else
+ return internal_syscall(SYSCALL(clone), SIGCHLD, 0);
+# endif
+# else
+ return internal_syscall(SYSCALL(fork));
+# endif
+}
+
+#if SANITIZER_FREEBSD
+int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
+ uptr *oldlenp, const void *newp, uptr newlen) {
+ return internal_syscall(SYSCALL(__sysctl), name, namelen, oldp,
+ (size_t *)oldlenp, newp, (size_t)newlen);
+}
+
+int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
+ const void *newp, uptr newlen) {
+ // Note: this function can be called during startup, so we need to avoid
+ // calling any interceptable functions. On FreeBSD >= 1300045 sysctlbyname()
+ // is a real syscall, but for older versions it calls sysctlnametomib()
+ // followed by sysctl(). To avoid calling the intercepted version and
+ // asserting if this happens during startup, call the real sysctlnametomib()
+ // followed by internal_sysctl() if the syscall is not available.
+#ifdef SYS___sysctlbyname
+ return internal_syscall(SYSCALL(__sysctlbyname), sname,
+ internal_strlen(sname), oldp, (size_t *)oldlenp, newp,
+ (size_t)newlen);
+#else
+ static decltype(sysctlnametomib) *real_sysctlnametomib = nullptr;
+ if (!real_sysctlnametomib)
+ real_sysctlnametomib =
+ (decltype(sysctlnametomib) *)dlsym(RTLD_NEXT, "sysctlnametomib");
+ CHECK(real_sysctlnametomib);
+
+ int oid[CTL_MAXNAME];
+ size_t len = CTL_MAXNAME;
+ if (real_sysctlnametomib(sname, oid, &len) == -1)
+ return (-1);
+ return internal_sysctl(oid, len, oldp, oldlenp, newp, newlen);
+#endif
+}
+#endif
+
+#if SANITIZER_LINUX
+#define SA_RESTORER 0x04000000
+// Doesn't set sa_restorer if the caller did not set it, so use with caution
+//(see below).
+int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
+ __sanitizer_kernel_sigaction_t k_act, k_oldact;
+ internal_memset(&k_act, 0, sizeof(__sanitizer_kernel_sigaction_t));
+ internal_memset(&k_oldact, 0, sizeof(__sanitizer_kernel_sigaction_t));
+ const __sanitizer_sigaction *u_act = (const __sanitizer_sigaction *)act;
+ __sanitizer_sigaction *u_oldact = (__sanitizer_sigaction *)oldact;
+ if (u_act) {
+ k_act.handler = u_act->handler;
+ k_act.sigaction = u_act->sigaction;
+ internal_memcpy(&k_act.sa_mask, &u_act->sa_mask,
+ sizeof(__sanitizer_kernel_sigset_t));
+ // Without SA_RESTORER kernel ignores the calls (probably returns EINVAL).
+ k_act.sa_flags = u_act->sa_flags | SA_RESTORER;
+ // FIXME: most often sa_restorer is unset, however the kernel requires it
+ // to point to a valid signal restorer that calls the rt_sigreturn syscall.
+ // If sa_restorer passed to the kernel is NULL, the program may crash upon
+ // signal delivery or fail to unwind the stack in the signal handler.
+ // libc implementation of sigaction() passes its own restorer to
+ // rt_sigaction, so we need to do the same (we'll need to reimplement the
+ // restorers; for x86_64 the restorer address can be obtained from
+ // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact).
+#if !SANITIZER_ANDROID || !SANITIZER_MIPS32
+ k_act.sa_restorer = u_act->sa_restorer;
+#endif
+ }
+
+ uptr result = internal_syscall(SYSCALL(rt_sigaction), (uptr)signum,
+ (uptr)(u_act ? &k_act : nullptr),
+ (uptr)(u_oldact ? &k_oldact : nullptr),
+ (uptr)sizeof(__sanitizer_kernel_sigset_t));
+
+ if ((result == 0) && u_oldact) {
+ u_oldact->handler = k_oldact.handler;
+ u_oldact->sigaction = k_oldact.sigaction;
+ internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask,
+ sizeof(__sanitizer_kernel_sigset_t));
+ u_oldact->sa_flags = k_oldact.sa_flags;
+#if !SANITIZER_ANDROID || !SANITIZER_MIPS32
+ u_oldact->sa_restorer = k_oldact.sa_restorer;
+#endif
+ }
+ return result;
+}
+#endif // SANITIZER_LINUX
+
+uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
+ __sanitizer_sigset_t *oldset) {
+#if SANITIZER_FREEBSD
+ return internal_syscall(SYSCALL(sigprocmask), how, set, oldset);
+#else
+ __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
+ __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset;
+ return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how, (uptr)k_set,
+ (uptr)k_oldset, sizeof(__sanitizer_kernel_sigset_t));
+#endif
+}
+
+void internal_sigfillset(__sanitizer_sigset_t *set) {
+ internal_memset(set, 0xff, sizeof(*set));
+}
+
+void internal_sigemptyset(__sanitizer_sigset_t *set) {
+ internal_memset(set, 0, sizeof(*set));
+}
+
+#if SANITIZER_LINUX
+void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
+ signum -= 1;
+ CHECK_GE(signum, 0);
+ CHECK_LT(signum, sizeof(*set) * 8);
+ __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
+ const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
+ const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
+ k_set->sig[idx] &= ~((uptr)1 << bit);
+}
+
+bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
+ signum -= 1;
+ CHECK_GE(signum, 0);
+ CHECK_LT(signum, sizeof(*set) * 8);
+ __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
+ const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
+ const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
+ return k_set->sig[idx] & ((uptr)1 << bit);
+}
+#elif SANITIZER_FREEBSD
+uptr internal_procctl(int type, int id, int cmd, void *data) {
+ return internal_syscall(SYSCALL(procctl), type, id, cmd, data);
+}
+
+void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
+ sigset_t *rset = reinterpret_cast<sigset_t *>(set);
+ sigdelset(rset, signum);
+}
+
+bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
+ sigset_t *rset = reinterpret_cast<sigset_t *>(set);
+ return sigismember(rset, signum);
+}
+#endif
+#endif // !SANITIZER_SOLARIS
+
+#if !SANITIZER_NETBSD
+// ThreadLister implementation.
+ThreadLister::ThreadLister(pid_t pid) : pid_(pid), buffer_(4096) {
+ char task_directory_path[80];
+ internal_snprintf(task_directory_path, sizeof(task_directory_path),
+ "/proc/%d/task/", pid);
+ descriptor_ = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
+ if (internal_iserror(descriptor_)) {
+ Report("Can't open /proc/%d/task for reading.\n", pid);
+ }
+}
+
+ThreadLister::Result ThreadLister::ListThreads(
+ InternalMmapVector<tid_t> *threads) {
+ if (internal_iserror(descriptor_))
+ return Error;
+ internal_lseek(descriptor_, 0, SEEK_SET);
+ threads->clear();
+
+ Result result = Ok;
+ for (bool first_read = true;; first_read = false) {
+ // Resize to max capacity if it was downsized by IsAlive.
+ buffer_.resize(buffer_.capacity());
+ CHECK_GE(buffer_.size(), 4096);
+ uptr read = internal_getdents(
+ descriptor_, (struct linux_dirent *)buffer_.data(), buffer_.size());
+ if (!read)
+ return result;
+ if (internal_iserror(read)) {
+ Report("Can't read directory entries from /proc/%d/task.\n", pid_);
+ return Error;
+ }
+
+ for (uptr begin = (uptr)buffer_.data(), end = begin + read; begin < end;) {
+ struct linux_dirent *entry = (struct linux_dirent *)begin;
+ begin += entry->d_reclen;
+ if (entry->d_ino == 1) {
+ // Inode 1 is for bad blocks and also can be a reason for early return.
+ // Should be emitted if kernel tried to output terminating thread.
+ // See proc_task_readdir implementation in Linux.
+ result = Incomplete;
+ }
+ if (entry->d_ino && *entry->d_name >= '0' && *entry->d_name <= '9')
+ threads->push_back(internal_atoll(entry->d_name));
+ }
+
+ // Now we are going to detect short-read or early EOF. In such cases Linux
+ // can return inconsistent list with missing alive threads.
+ // Code will just remember that the list can be incomplete but it will
+ // continue reads to return as much as possible.
+ if (!first_read) {
+ // The first one was a short-read by definition.
+ result = Incomplete;
+ } else if (read > buffer_.size() - 1024) {
+ // Read was close to the buffer size. So double the size and assume the
+ // worst.
+ buffer_.resize(buffer_.size() * 2);
+ result = Incomplete;
+ } else if (!threads->empty() && !IsAlive(threads->back())) {
+ // Maybe Linux early returned from read on terminated thread (!pid_alive)
+ // and failed to restore read position.
+ // See next_tid and proc_task_instantiate in Linux.
+ result = Incomplete;
+ }
+ }
+}
+
+bool ThreadLister::IsAlive(int tid) {
+ // /proc/%d/task/%d/status uses same call to detect alive threads as
+ // proc_task_readdir. See task_state implementation in Linux.
+ char path[80];
+ internal_snprintf(path, sizeof(path), "/proc/%d/task/%d/status", pid_, tid);
+ if (!ReadFileToVector(path, &buffer_) || buffer_.empty())
+ return false;
+ buffer_.push_back(0);
+ static const char kPrefix[] = "\nPPid:";
+ const char *field = internal_strstr(buffer_.data(), kPrefix);
+ if (!field)
+ return false;
+ field += internal_strlen(kPrefix);
+ return (int)internal_atoll(field) != 0;
+}
+
+ThreadLister::~ThreadLister() {
+ if (!internal_iserror(descriptor_))
+ internal_close(descriptor_);
+}
+#endif
+
+#if SANITIZER_WORDSIZE == 32
+// Take care of unusable kernel area in top gigabyte.
+static uptr GetKernelAreaSize() {
+#if SANITIZER_LINUX && !SANITIZER_X32
+ const uptr gbyte = 1UL << 30;
+
+ // Firstly check if there are writable segments
+ // mapped to top gigabyte (e.g. stack).
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+ if (proc_maps.Error())
+ return 0;
+ MemoryMappedSegment segment;
+ while (proc_maps.Next(&segment)) {
+ if ((segment.end >= 3 * gbyte) && segment.IsWritable()) return 0;
+ }
+
+#if !SANITIZER_ANDROID
+ // Even if nothing is mapped, top Gb may still be accessible
+ // if we are running on 64-bit kernel.
+ // Uname may report misleading results if personality type
+ // is modified (e.g. under schroot) so check this as well.
+ struct utsname uname_info;
+ int pers = personality(0xffffffffUL);
+ if (!(pers & PER_MASK) && internal_uname(&uname_info) == 0 &&
+ internal_strstr(uname_info.machine, "64"))
+ return 0;
+#endif // SANITIZER_ANDROID
+
+ // Top gigabyte is reserved for kernel.
+ return gbyte;
+#else
+ return 0;
+#endif // SANITIZER_LINUX && !SANITIZER_X32
+}
+#endif // SANITIZER_WORDSIZE == 32
+
+uptr GetMaxVirtualAddress() {
+#if SANITIZER_NETBSD && defined(__x86_64__)
+ return 0x7f7ffffff000ULL; // (0x00007f8000000000 - PAGE_SIZE)
+#elif SANITIZER_WORDSIZE == 64
+# if defined(__powerpc64__) || defined(__aarch64__) || defined(__loongarch__)
+ // On PowerPC64 we have two different address space layouts: 44- and 46-bit.
+ // We somehow need to figure out which one we are using now and choose
+ // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
+ // Note that with 'ulimit -s unlimited' the stack is moved away from the top
+ // of the address space, so simply checking the stack address is not enough.
+ // This should (does) work for both PowerPC64 Endian modes.
+ // Similarly, aarch64 has multiple address space layouts: 39, 42 and 47-bit.
+ // loongarch64 also has multiple address space layouts: default is 47-bit.
+ return (1ULL << (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1)) - 1;
+#elif SANITIZER_RISCV64
+ return (1ULL << 38) - 1;
+# elif SANITIZER_MIPS64
+ return (1ULL << 40) - 1; // 0x000000ffffffffffUL;
+# elif defined(__s390x__)
+ return (1ULL << 53) - 1; // 0x001fffffffffffffUL;
+#elif defined(__sparc__)
+ return ~(uptr)0;
+# else
+ return (1ULL << 47) - 1; // 0x00007fffffffffffUL;
+# endif
+#else // SANITIZER_WORDSIZE == 32
+# if defined(__s390__)
+ return (1ULL << 31) - 1; // 0x7fffffff;
+# else
+ return (1ULL << 32) - 1; // 0xffffffff;
+# endif
+#endif // SANITIZER_WORDSIZE
+}
+
+uptr GetMaxUserVirtualAddress() {
+ uptr addr = GetMaxVirtualAddress();
+#if SANITIZER_WORDSIZE == 32 && !defined(__s390__)
+ if (!common_flags()->full_address_space)
+ addr -= GetKernelAreaSize();
+ CHECK_LT(reinterpret_cast<uptr>(&addr), addr);
+#endif
+ return addr;
+}
+
+#if !SANITIZER_ANDROID
+uptr GetPageSize() {
+#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__)) && \
+ defined(EXEC_PAGESIZE)
+ return EXEC_PAGESIZE;
+#elif SANITIZER_FREEBSD || SANITIZER_NETBSD
+// Use sysctl as sysconf can trigger interceptors internally.
+ int pz = 0;
+ uptr pzl = sizeof(pz);
+ int mib[2] = {CTL_HW, HW_PAGESIZE};
+ int rv = internal_sysctl(mib, 2, &pz, &pzl, nullptr, 0);
+ CHECK_EQ(rv, 0);
+ return (uptr)pz;
+#elif SANITIZER_USE_GETAUXVAL
+ return getauxval(AT_PAGESZ);
+#else
+ return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.
+#endif
+}
+#endif // !SANITIZER_ANDROID
+
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
+#if SANITIZER_SOLARIS
+ const char *default_module_name = getexecname();
+ CHECK_NE(default_module_name, NULL);
+ return internal_snprintf(buf, buf_len, "%s", default_module_name);
+#else
+#if SANITIZER_FREEBSD || SANITIZER_NETBSD
+#if SANITIZER_FREEBSD
+ const int Mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
+#else
+ const int Mib[4] = {CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME};
+#endif
+ const char *default_module_name = "kern.proc.pathname";
+ uptr Size = buf_len;
+ bool IsErr =
+ (internal_sysctl(Mib, ARRAY_SIZE(Mib), buf, &Size, NULL, 0) != 0);
+ int readlink_error = IsErr ? errno : 0;
+ uptr module_name_len = Size;
+#else
+ const char *default_module_name = "/proc/self/exe";
+ uptr module_name_len = internal_readlink(
+ default_module_name, buf, buf_len);
+ int readlink_error;
+ bool IsErr = internal_iserror(module_name_len, &readlink_error);
+#endif // SANITIZER_SOLARIS
+ if (IsErr) {
+ // We can't read binary name for some reason, assume it's unknown.
+ Report("WARNING: reading executable name failed with errno %d, "
+ "some stack frames may not be symbolized\n", readlink_error);
+ module_name_len = internal_snprintf(buf, buf_len, "%s",
+ default_module_name);
+ CHECK_LT(module_name_len, buf_len);
+ }
+ return module_name_len;
+#endif
+}
+
+uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
+#if SANITIZER_LINUX
+ char *tmpbuf;
+ uptr tmpsize;
+ uptr tmplen;
+ if (ReadFileToBuffer("/proc/self/cmdline", &tmpbuf, &tmpsize, &tmplen,
+ 1024 * 1024)) {
+ internal_strncpy(buf, tmpbuf, buf_len);
+ UnmapOrDie(tmpbuf, tmpsize);
+ return internal_strlen(buf);
+ }
+#endif
+ return ReadBinaryName(buf, buf_len);
+}
+
+// Match full names of the form /path/to/base_name{-,.}*
+bool LibraryNameIs(const char *full_name, const char *base_name) {
+ const char *name = full_name;
+ // Strip path.
+ while (*name != '\0') name++;
+ while (name > full_name && *name != '/') name--;
+ if (*name == '/') name++;
+ uptr base_name_length = internal_strlen(base_name);
+ if (internal_strncmp(name, base_name, base_name_length)) return false;
+ return (name[base_name_length] == '-' || name[base_name_length] == '.');
+}
+
+#if !SANITIZER_ANDROID
+// Call cb for each region mapped by map.
+void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
+ CHECK_NE(map, nullptr);
+#if !SANITIZER_FREEBSD
+ typedef ElfW(Phdr) Elf_Phdr;
+ typedef ElfW(Ehdr) Elf_Ehdr;
+#endif // !SANITIZER_FREEBSD
+ char *base = (char *)map->l_addr;
+ Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
+ char *phdrs = base + ehdr->e_phoff;
+ char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize;
+
+ // Find the segment with the minimum base so we can "relocate" the p_vaddr
+ // fields. Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC
+ // objects have a non-zero base.
+ uptr preferred_base = (uptr)-1;
+ for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
+ Elf_Phdr *phdr = (Elf_Phdr *)iter;
+ if (phdr->p_type == PT_LOAD && preferred_base > (uptr)phdr->p_vaddr)
+ preferred_base = (uptr)phdr->p_vaddr;
+ }
+
+ // Compute the delta from the real base to get a relocation delta.
+ sptr delta = (uptr)base - preferred_base;
+ // Now we can figure out what the loader really mapped.
+ for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
+ Elf_Phdr *phdr = (Elf_Phdr *)iter;
+ if (phdr->p_type == PT_LOAD) {
+ uptr seg_start = phdr->p_vaddr + delta;
+ uptr seg_end = seg_start + phdr->p_memsz;
+ // None of these values are aligned. We consider the ragged edges of the
+ // load command as defined, since they are mapped from the file.
+ seg_start = RoundDownTo(seg_start, GetPageSizeCached());
+ seg_end = RoundUpTo(seg_end, GetPageSizeCached());
+ cb((void *)seg_start, seg_end - seg_start);
+ }
+ }
+}
+#endif
+
+#if SANITIZER_LINUX
+#if defined(__x86_64__)
+// We cannot use glibc's clone wrapper, because it messes with the child
+// task's TLS. It writes the PID and TID of the child task to its thread
+// descriptor, but in our case the child task shares the thread descriptor with
+// the parent (because we don't know how to allocate a new thread
+// descriptor to keep glibc happy). So the stock version of clone(), when
+// used with CLONE_VM, would end up corrupting the parent's thread descriptor.
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+ int *parent_tidptr, void *newtls, int *child_tidptr) {
+ long long res;
+ if (!fn || !child_stack)
+ return -EINVAL;
+ CHECK_EQ(0, (uptr)child_stack % 16);
+ child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
+ ((unsigned long long *)child_stack)[0] = (uptr)fn;
+ ((unsigned long long *)child_stack)[1] = (uptr)arg;
+ register void *r8 __asm__("r8") = newtls;
+ register int *r10 __asm__("r10") = child_tidptr;
+ __asm__ __volatile__(
+ /* %rax = syscall(%rax = SYSCALL(clone),
+ * %rdi = flags,
+ * %rsi = child_stack,
+ * %rdx = parent_tidptr,
+ * %r8 = new_tls,
+ * %r10 = child_tidptr)
+ */
+ "syscall\n"
+
+ /* if (%rax != 0)
+ * return;
+ */
+ "testq %%rax,%%rax\n"
+ "jnz 1f\n"
+
+ /* In the child. Terminate unwind chain. */
+ // XXX: We should also terminate the CFI unwind chain
+ // here. Unfortunately clang 3.2 doesn't support the
+ // necessary CFI directives, so we skip that part.
+ "xorq %%rbp,%%rbp\n"
+
+ /* Call "fn(arg)". */
+ "popq %%rax\n"
+ "popq %%rdi\n"
+ "call *%%rax\n"
+
+ /* Call _exit(%rax). */
+ "movq %%rax,%%rdi\n"
+ "movq %2,%%rax\n"
+ "syscall\n"
+
+ /* Return to parent. */
+ "1:\n"
+ : "=a" (res)
+ : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
+ "S"(child_stack),
+ "D"(flags),
+ "d"(parent_tidptr),
+ "r"(r8),
+ "r"(r10)
+ : "memory", "r11", "rcx");
+ return res;
+}
+#elif defined(__mips__)
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+ int *parent_tidptr, void *newtls, int *child_tidptr) {
+ long long res;
+ if (!fn || !child_stack)
+ return -EINVAL;
+ CHECK_EQ(0, (uptr)child_stack % 16);
+ child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
+ ((unsigned long long *)child_stack)[0] = (uptr)fn;
+ ((unsigned long long *)child_stack)[1] = (uptr)arg;
+ register void *a3 __asm__("$7") = newtls;
+ register int *a4 __asm__("$8") = child_tidptr;
+ // We don't have proper CFI directives here because it requires alot of code
+ // for very marginal benefits.
+ __asm__ __volatile__(
+ /* $v0 = syscall($v0 = __NR_clone,
+ * $a0 = flags,
+ * $a1 = child_stack,
+ * $a2 = parent_tidptr,
+ * $a3 = new_tls,
+ * $a4 = child_tidptr)
+ */
+ ".cprestore 16;\n"
+ "move $4,%1;\n"
+ "move $5,%2;\n"
+ "move $6,%3;\n"
+ "move $7,%4;\n"
+ /* Store the fifth argument on stack
+ * if we are using 32-bit abi.
+ */
+#if SANITIZER_WORDSIZE == 32
+ "lw %5,16($29);\n"
+#else
+ "move $8,%5;\n"
+#endif
+ "li $2,%6;\n"
+ "syscall;\n"
+
+ /* if ($v0 != 0)
+ * return;
+ */
+ "bnez $2,1f;\n"
+
+ /* Call "fn(arg)". */
+#if SANITIZER_WORDSIZE == 32
+#ifdef __BIG_ENDIAN__
+ "lw $25,4($29);\n"
+ "lw $4,12($29);\n"
+#else
+ "lw $25,0($29);\n"
+ "lw $4,8($29);\n"
+#endif
+#else
+ "ld $25,0($29);\n"
+ "ld $4,8($29);\n"
+#endif
+ "jal $25;\n"
+
+ /* Call _exit($v0). */
+ "move $4,$2;\n"
+ "li $2,%7;\n"
+ "syscall;\n"
+
+ /* Return to parent. */
+ "1:\n"
+ : "=r" (res)
+ : "r"(flags),
+ "r"(child_stack),
+ "r"(parent_tidptr),
+ "r"(a3),
+ "r"(a4),
+ "i"(__NR_clone),
+ "i"(__NR_exit)
+ : "memory", "$29" );
+ return res;
+}
+#elif SANITIZER_RISCV64
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+ int *parent_tidptr, void *newtls, int *child_tidptr) {
+ if (!fn || !child_stack)
+ return -EINVAL;
+
+ CHECK_EQ(0, (uptr)child_stack % 16);
+
+ register int res __asm__("a0");
+ register int __flags __asm__("a0") = flags;
+ register void *__stack __asm__("a1") = child_stack;
+ register int *__ptid __asm__("a2") = parent_tidptr;
+ register void *__tls __asm__("a3") = newtls;
+ register int *__ctid __asm__("a4") = child_tidptr;
+ register int (*__fn)(void *) __asm__("a5") = fn;
+ register void *__arg __asm__("a6") = arg;
+ register int nr_clone __asm__("a7") = __NR_clone;
+
+ __asm__ __volatile__(
+ "ecall\n"
+
+ /* if (a0 != 0)
+ * return a0;
+ */
+ "bnez a0, 1f\n"
+
+ // In the child, now. Call "fn(arg)".
+ "mv a0, a6\n"
+ "jalr a5\n"
+
+ // Call _exit(a0).
+ "addi a7, zero, %9\n"
+ "ecall\n"
+ "1:\n"
+
+ : "=r"(res)
+ : "0"(__flags), "r"(__stack), "r"(__ptid), "r"(__tls), "r"(__ctid),
+ "r"(__fn), "r"(__arg), "r"(nr_clone), "i"(__NR_exit)
+ : "memory");
+ return res;
+}
+#elif defined(__aarch64__)
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+ int *parent_tidptr, void *newtls, int *child_tidptr) {
+ register long long res __asm__("x0");
+ if (!fn || !child_stack)
+ return -EINVAL;
+ CHECK_EQ(0, (uptr)child_stack % 16);
+ child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
+ ((unsigned long long *)child_stack)[0] = (uptr)fn;
+ ((unsigned long long *)child_stack)[1] = (uptr)arg;
+
+ register int (*__fn)(void *) __asm__("x0") = fn;
+ register void *__stack __asm__("x1") = child_stack;
+ register int __flags __asm__("x2") = flags;
+ register void *__arg __asm__("x3") = arg;
+ register int *__ptid __asm__("x4") = parent_tidptr;
+ register void *__tls __asm__("x5") = newtls;
+ register int *__ctid __asm__("x6") = child_tidptr;
+
+ __asm__ __volatile__(
+ "mov x0,x2\n" /* flags */
+ "mov x2,x4\n" /* ptid */
+ "mov x3,x5\n" /* tls */
+ "mov x4,x6\n" /* ctid */
+ "mov x8,%9\n" /* clone */
+
+ "svc 0x0\n"
+
+ /* if (%r0 != 0)
+ * return %r0;
+ */
+ "cmp x0, #0\n"
+ "bne 1f\n"
+
+ /* In the child, now. Call "fn(arg)". */
+ "ldp x1, x0, [sp], #16\n"
+ "blr x1\n"
+
+ /* Call _exit(%r0). */
+ "mov x8, %10\n"
+ "svc 0x0\n"
+ "1:\n"
+
+ : "=r" (res)
+ : "i"(-EINVAL),
+ "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg),
+ "r"(__ptid), "r"(__tls), "r"(__ctid),
+ "i"(__NR_clone), "i"(__NR_exit)
+ : "x30", "memory");
+ return res;
+}
+#elif SANITIZER_LOONGARCH64
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+ int *parent_tidptr, void *newtls, int *child_tidptr) {
+ if (!fn || !child_stack)
+ return -EINVAL;
+
+ CHECK_EQ(0, (uptr)child_stack % 16);
+
+ register int res __asm__("$a0");
+ register int __flags __asm__("$a0") = flags;
+ register void *__stack __asm__("$a1") = child_stack;
+ register int *__ptid __asm__("$a2") = parent_tidptr;
+ register int *__ctid __asm__("$a3") = child_tidptr;
+ register void *__tls __asm__("$a4") = newtls;
+ register int (*__fn)(void *) __asm__("$a5") = fn;
+ register void *__arg __asm__("$a6") = arg;
+ register int nr_clone __asm__("$a7") = __NR_clone;
+
+ __asm__ __volatile__(
+ "syscall 0\n"
+
+ // if ($a0 != 0)
+ // return $a0;
+ "bnez $a0, 1f\n"
+
+ // In the child, now. Call "fn(arg)".
+ "move $a0, $a6\n"
+ "jirl $ra, $a5, 0\n"
+
+ // Call _exit($a0).
+ "addi.d $a7, $zero, %9\n"
+ "syscall 0\n"
+
+ "1:\n"
+
+ : "=r"(res)
+ : "0"(__flags), "r"(__stack), "r"(__ptid), "r"(__ctid), "r"(__tls),
+ "r"(__fn), "r"(__arg), "r"(nr_clone), "i"(__NR_exit)
+ : "memory", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8");
+ return res;
+}
+#elif defined(__powerpc64__)
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+ int *parent_tidptr, void *newtls, int *child_tidptr) {
+ long long res;
+// Stack frame structure.
+#if SANITIZER_PPC64V1
+// Back chain == 0 (SP + 112)
+// Frame (112 bytes):
+// Parameter save area (SP + 48), 8 doublewords
+// TOC save area (SP + 40)
+// Link editor doubleword (SP + 32)
+// Compiler doubleword (SP + 24)
+// LR save area (SP + 16)
+// CR save area (SP + 8)
+// Back chain (SP + 0)
+# define FRAME_SIZE 112
+# define FRAME_TOC_SAVE_OFFSET 40
+#elif SANITIZER_PPC64V2
+// Back chain == 0 (SP + 32)
+// Frame (32 bytes):
+// TOC save area (SP + 24)
+// LR save area (SP + 16)
+// CR save area (SP + 8)
+// Back chain (SP + 0)
+# define FRAME_SIZE 32
+# define FRAME_TOC_SAVE_OFFSET 24
+#else
+# error "Unsupported PPC64 ABI"
+#endif
+ if (!fn || !child_stack)
+ return -EINVAL;
+ CHECK_EQ(0, (uptr)child_stack % 16);
+
+ register int (*__fn)(void *) __asm__("r3") = fn;
+ register void *__cstack __asm__("r4") = child_stack;
+ register int __flags __asm__("r5") = flags;
+ register void *__arg __asm__("r6") = arg;
+ register int *__ptidptr __asm__("r7") = parent_tidptr;
+ register void *__newtls __asm__("r8") = newtls;
+ register int *__ctidptr __asm__("r9") = child_tidptr;
+
+ __asm__ __volatile__(
+ /* fn and arg are saved across the syscall */
+ "mr 28, %5\n\t"
+ "mr 27, %8\n\t"
+
+ /* syscall
+ r0 == __NR_clone
+ r3 == flags
+ r4 == child_stack
+ r5 == parent_tidptr
+ r6 == newtls
+ r7 == child_tidptr */
+ "mr 3, %7\n\t"
+ "mr 5, %9\n\t"
+ "mr 6, %10\n\t"
+ "mr 7, %11\n\t"
+ "li 0, %3\n\t"
+ "sc\n\t"
+
+ /* Test if syscall was successful */
+ "cmpdi cr1, 3, 0\n\t"
+ "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t"
+ "bne- cr1, 1f\n\t"
+
+ /* Set up stack frame */
+ "li 29, 0\n\t"
+ "stdu 29, -8(1)\n\t"
+ "stdu 1, -%12(1)\n\t"
+ /* Do the function call */
+ "std 2, %13(1)\n\t"
+#if SANITIZER_PPC64V1
+ "ld 0, 0(28)\n\t"
+ "ld 2, 8(28)\n\t"
+ "mtctr 0\n\t"
+#elif SANITIZER_PPC64V2
+ "mr 12, 28\n\t"
+ "mtctr 12\n\t"
+#else
+# error "Unsupported PPC64 ABI"
+#endif
+ "mr 3, 27\n\t"
+ "bctrl\n\t"
+ "ld 2, %13(1)\n\t"
+
+ /* Call _exit(r3) */
+ "li 0, %4\n\t"
+ "sc\n\t"
+
+ /* Return to parent */
+ "1:\n\t"
+ "mr %0, 3\n\t"
+ : "=r" (res)
+ : "0" (-1),
+ "i" (EINVAL),
+ "i" (__NR_clone),
+ "i" (__NR_exit),
+ "r" (__fn),
+ "r" (__cstack),
+ "r" (__flags),
+ "r" (__arg),
+ "r" (__ptidptr),
+ "r" (__newtls),
+ "r" (__ctidptr),
+ "i" (FRAME_SIZE),
+ "i" (FRAME_TOC_SAVE_OFFSET)
+ : "cr0", "cr1", "memory", "ctr", "r0", "r27", "r28", "r29");
+ return res;
+}
+#elif defined(__i386__)
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+ int *parent_tidptr, void *newtls, int *child_tidptr) {
+ int res;
+ if (!fn || !child_stack)
+ return -EINVAL;
+ CHECK_EQ(0, (uptr)child_stack % 16);
+ child_stack = (char *)child_stack - 7 * sizeof(unsigned int);
+ ((unsigned int *)child_stack)[0] = (uptr)flags;
+ ((unsigned int *)child_stack)[1] = (uptr)0;
+ ((unsigned int *)child_stack)[2] = (uptr)fn;
+ ((unsigned int *)child_stack)[3] = (uptr)arg;
+ __asm__ __volatile__(
+ /* %eax = syscall(%eax = SYSCALL(clone),
+ * %ebx = flags,
+ * %ecx = child_stack,
+ * %edx = parent_tidptr,
+ * %esi = new_tls,
+ * %edi = child_tidptr)
+ */
+
+ /* Obtain flags */
+ "movl (%%ecx), %%ebx\n"
+ /* Do the system call */
+ "pushl %%ebx\n"
+ "pushl %%esi\n"
+ "pushl %%edi\n"
+ /* Remember the flag value. */
+ "movl %%ebx, (%%ecx)\n"
+ "int $0x80\n"
+ "popl %%edi\n"
+ "popl %%esi\n"
+ "popl %%ebx\n"
+
+ /* if (%eax != 0)
+ * return;
+ */
+
+ "test %%eax,%%eax\n"
+ "jnz 1f\n"
+
+ /* terminate the stack frame */
+ "xorl %%ebp,%%ebp\n"
+ /* Call FN. */
+ "call *%%ebx\n"
+#ifdef PIC
+ "call here\n"
+ "here:\n"
+ "popl %%ebx\n"
+ "addl $_GLOBAL_OFFSET_TABLE_+[.-here], %%ebx\n"
+#endif
+ /* Call exit */
+ "movl %%eax, %%ebx\n"
+ "movl %2, %%eax\n"
+ "int $0x80\n"
+ "1:\n"
+ : "=a" (res)
+ : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
+ "c"(child_stack),
+ "d"(parent_tidptr),
+ "S"(newtls),
+ "D"(child_tidptr)
+ : "memory");
+ return res;
+}
+#elif defined(__arm__)
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+ int *parent_tidptr, void *newtls, int *child_tidptr) {
+ unsigned int res;
+ if (!fn || !child_stack)
+ return -EINVAL;
+ child_stack = (char *)child_stack - 2 * sizeof(unsigned int);
+ ((unsigned int *)child_stack)[0] = (uptr)fn;
+ ((unsigned int *)child_stack)[1] = (uptr)arg;
+ register int r0 __asm__("r0") = flags;
+ register void *r1 __asm__("r1") = child_stack;
+ register int *r2 __asm__("r2") = parent_tidptr;
+ register void *r3 __asm__("r3") = newtls;
+ register int *r4 __asm__("r4") = child_tidptr;
+ register int r7 __asm__("r7") = __NR_clone;
+
+#if __ARM_ARCH > 4 || defined (__ARM_ARCH_4T__)
+# define ARCH_HAS_BX
+#endif
+#if __ARM_ARCH > 4
+# define ARCH_HAS_BLX
+#endif
+
+#ifdef ARCH_HAS_BX
+# ifdef ARCH_HAS_BLX
+# define BLX(R) "blx " #R "\n"
+# else
+# define BLX(R) "mov lr, pc; bx " #R "\n"
+# endif
+#else
+# define BLX(R) "mov lr, pc; mov pc," #R "\n"
+#endif
+
+ __asm__ __volatile__(
+ /* %r0 = syscall(%r7 = SYSCALL(clone),
+ * %r0 = flags,
+ * %r1 = child_stack,
+ * %r2 = parent_tidptr,
+ * %r3 = new_tls,
+ * %r4 = child_tidptr)
+ */
+
+ /* Do the system call */
+ "swi 0x0\n"
+
+ /* if (%r0 != 0)
+ * return %r0;
+ */
+ "cmp r0, #0\n"
+ "bne 1f\n"
+
+ /* In the child, now. Call "fn(arg)". */
+ "ldr r0, [sp, #4]\n"
+ "ldr ip, [sp], #8\n"
+ BLX(ip)
+ /* Call _exit(%r0). */
+ "mov r7, %7\n"
+ "swi 0x0\n"
+ "1:\n"
+ "mov %0, r0\n"
+ : "=r"(res)
+ : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r7),
+ "i"(__NR_exit)
+ : "memory");
+ return res;
+}
+#endif
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX
+int internal_uname(struct utsname *buf) {
+ return internal_syscall(SYSCALL(uname), buf);
+}
+#endif
+
+#if SANITIZER_ANDROID
+#if __ANDROID_API__ < 21
+extern "C" __attribute__((weak)) int dl_iterate_phdr(
+ int (*)(struct dl_phdr_info *, size_t, void *), void *);
+#endif
+
+static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
+ void *data) {
+ // Any name starting with "lib" indicates a bug in L where library base names
+ // are returned instead of paths.
+ if (info->dlpi_name && info->dlpi_name[0] == 'l' &&
+ info->dlpi_name[1] == 'i' && info->dlpi_name[2] == 'b') {
+ *(bool *)data = true;
+ return 1;
+ }
+ return 0;
+}
+
+static atomic_uint32_t android_api_level;
+
+static AndroidApiLevel AndroidDetectApiLevelStatic() {
+#if __ANDROID_API__ <= 19
+ return ANDROID_KITKAT;
+#elif __ANDROID_API__ <= 22
+ return ANDROID_LOLLIPOP_MR1;
+#else
+ return ANDROID_POST_LOLLIPOP;
+#endif
+}
+
+static AndroidApiLevel AndroidDetectApiLevel() {
+ if (!&dl_iterate_phdr)
+ return ANDROID_KITKAT; // K or lower
+ bool base_name_seen = false;
+ dl_iterate_phdr(dl_iterate_phdr_test_cb, &base_name_seen);
+ if (base_name_seen)
+ return ANDROID_LOLLIPOP_MR1; // L MR1
+ return ANDROID_POST_LOLLIPOP; // post-L
+ // Plain L (API level 21) is completely broken wrt ASan and not very
+ // interesting to detect.
+}
+
+extern "C" __attribute__((weak)) void* _DYNAMIC;
+
+AndroidApiLevel AndroidGetApiLevel() {
+ AndroidApiLevel level =
+ (AndroidApiLevel)atomic_load(&android_api_level, memory_order_relaxed);
+ if (level) return level;
+ level = &_DYNAMIC == nullptr ? AndroidDetectApiLevelStatic()
+ : AndroidDetectApiLevel();
+ atomic_store(&android_api_level, level, memory_order_relaxed);
+ return level;
+}
+
+#endif
+
+static HandleSignalMode GetHandleSignalModeImpl(int signum) {
+ switch (signum) {
+ case SIGABRT:
+ return common_flags()->handle_abort;
+ case SIGILL:
+ return common_flags()->handle_sigill;
+ case SIGTRAP:
+ return common_flags()->handle_sigtrap;
+ case SIGFPE:
+ return common_flags()->handle_sigfpe;
+ case SIGSEGV:
+ return common_flags()->handle_segv;
+ case SIGBUS:
+ return common_flags()->handle_sigbus;
+ }
+ return kHandleSignalNo;
+}
+
+HandleSignalMode GetHandleSignalMode(int signum) {
+ HandleSignalMode result = GetHandleSignalModeImpl(signum);
+ if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler)
+ return kHandleSignalExclusive;
+ return result;
+}
+
+#if !SANITIZER_GO
+void *internal_start_thread(void *(*func)(void *arg), void *arg) {
+ if (&real_pthread_create == 0)
+ return nullptr;
+ // Start the thread with signals blocked, otherwise it can steal user signals.
+ ScopedBlockSignals block(nullptr);
+ void *th;
+ real_pthread_create(&th, nullptr, func, arg);
+ return th;
+}
+
+void internal_join_thread(void *th) {
+ if (&real_pthread_join)
+ real_pthread_join(th, nullptr);
+}
+#else
+void *internal_start_thread(void *(*func)(void *), void *arg) { return 0; }
+
+void internal_join_thread(void *th) {}
+#endif
+
+#if SANITIZER_LINUX && defined(__aarch64__)
+// Android headers in the older NDK releases miss this definition.
+struct __sanitizer_esr_context {
+ struct _aarch64_ctx head;
+ uint64_t esr;
+};
+
+static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) {
+ static const u32 kEsrMagic = 0x45535201;
+ u8 *aux = reinterpret_cast<u8 *>(ucontext->uc_mcontext.__reserved);
+ while (true) {
+ _aarch64_ctx *ctx = (_aarch64_ctx *)aux;
+ if (ctx->size == 0) break;
+ if (ctx->magic == kEsrMagic) {
+ *esr = ((__sanitizer_esr_context *)ctx)->esr;
+ return true;
+ }
+ aux += ctx->size;
+ }
+ return false;
+}
+#elif SANITIZER_FREEBSD && defined(__aarch64__)
+// FreeBSD doesn't provide ESR in the ucontext.
+static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) {
+ return false;
+}
+#endif
+
+using Context = ucontext_t;
+
+SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
+ Context *ucontext = (Context *)context;
+#if defined(__x86_64__) || defined(__i386__)
+ static const uptr PF_WRITE = 1U << 1;
+#if SANITIZER_FREEBSD
+ uptr err = ucontext->uc_mcontext.mc_err;
+#elif SANITIZER_NETBSD
+ uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR];
+#elif SANITIZER_SOLARIS && defined(__i386__)
+ const int Err = 13;
+ uptr err = ucontext->uc_mcontext.gregs[Err];
+#else
+ uptr err = ucontext->uc_mcontext.gregs[REG_ERR];
+#endif // SANITIZER_FREEBSD
+ return err & PF_WRITE ? Write : Read;
+#elif defined(__mips__)
+ uint32_t *exception_source;
+ uint32_t faulty_instruction;
+ uint32_t op_code;
+
+ exception_source = (uint32_t *)ucontext->uc_mcontext.pc;
+ faulty_instruction = (uint32_t)(*exception_source);
+
+ op_code = (faulty_instruction >> 26) & 0x3f;
+
+ // FIXME: Add support for FPU, microMIPS, DSP, MSA memory instructions.
+ switch (op_code) {
+ case 0x28: // sb
+ case 0x29: // sh
+ case 0x2b: // sw
+ case 0x3f: // sd
+#if __mips_isa_rev < 6
+ case 0x2c: // sdl
+ case 0x2d: // sdr
+ case 0x2a: // swl
+ case 0x2e: // swr
+#endif
+ return SignalContext::Write;
+
+ case 0x20: // lb
+ case 0x24: // lbu
+ case 0x21: // lh
+ case 0x25: // lhu
+ case 0x23: // lw
+ case 0x27: // lwu
+ case 0x37: // ld
+#if __mips_isa_rev < 6
+ case 0x1a: // ldl
+ case 0x1b: // ldr
+ case 0x22: // lwl
+ case 0x26: // lwr
+#endif
+ return SignalContext::Read;
+#if __mips_isa_rev == 6
+ case 0x3b: // pcrel
+ op_code = (faulty_instruction >> 19) & 0x3;
+ switch (op_code) {
+ case 0x1: // lwpc
+ case 0x2: // lwupc
+ return SignalContext::Read;
+ }
+#endif
+ }
+ return SignalContext::Unknown;
+#elif defined(__arm__)
+ static const uptr FSR_WRITE = 1U << 11;
+ uptr fsr = ucontext->uc_mcontext.error_code;
+ return fsr & FSR_WRITE ? Write : Read;
+#elif defined(__aarch64__)
+ static const u64 ESR_ELx_WNR = 1U << 6;
+ u64 esr;
+ if (!Aarch64GetESR(ucontext, &esr)) return Unknown;
+ return esr & ESR_ELx_WNR ? Write : Read;
+#elif defined(__loongarch__)
+ u32 flags = ucontext->uc_mcontext.__flags;
+ if (flags & SC_ADDRERR_RD)
+ return SignalContext::Read;
+ if (flags & SC_ADDRERR_WR)
+ return SignalContext::Write;
+ return SignalContext::Unknown;
+#elif defined(__sparc__)
+ // Decode the instruction to determine the access type.
+ // From OpenSolaris $SRC/uts/sun4/os/trap.c (get_accesstype).
+#if SANITIZER_SOLARIS
+ uptr pc = ucontext->uc_mcontext.gregs[REG_PC];
+#else
+ // Historical BSDism here.
+ struct sigcontext *scontext = (struct sigcontext *)context;
+#if defined(__arch64__)
+ uptr pc = scontext->sigc_regs.tpc;
+#else
+ uptr pc = scontext->si_regs.pc;
+#endif
+#endif
+ u32 instr = *(u32 *)pc;
+ return (instr >> 21) & 1 ? Write: Read;
+#elif defined(__riscv)
+#if SANITIZER_FREEBSD
+ unsigned long pc = ucontext->uc_mcontext.mc_gpregs.gp_sepc;
+#else
+ unsigned long pc = ucontext->uc_mcontext.__gregs[REG_PC];
+#endif
+ unsigned faulty_instruction = *(uint16_t *)pc;
+
+#if defined(__riscv_compressed)
+ if ((faulty_instruction & 0x3) != 0x3) { // it's a compressed instruction
+ // set op_bits to the instruction bits [1, 0, 15, 14, 13]
+ unsigned op_bits =
+ ((faulty_instruction & 0x3) << 3) | (faulty_instruction >> 13);
+ unsigned rd = faulty_instruction & 0xF80; // bits 7-11, inclusive
+ switch (op_bits) {
+ case 0b10'010: // c.lwsp (rd != x0)
+#if __riscv_xlen == 64
+ case 0b10'011: // c.ldsp (rd != x0)
+#endif
+ return rd ? SignalContext::Read : SignalContext::Unknown;
+ case 0b00'010: // c.lw
+#if __riscv_flen >= 32 && __riscv_xlen == 32
+ case 0b10'011: // c.flwsp
+#endif
+#if __riscv_flen >= 32 || __riscv_xlen == 64
+ case 0b00'011: // c.flw / c.ld
+#endif
+#if __riscv_flen == 64
+ case 0b00'001: // c.fld
+ case 0b10'001: // c.fldsp
+#endif
+ return SignalContext::Read;
+ case 0b00'110: // c.sw
+ case 0b10'110: // c.swsp
+#if __riscv_flen >= 32 || __riscv_xlen == 64
+ case 0b00'111: // c.fsw / c.sd
+ case 0b10'111: // c.fswsp / c.sdsp
+#endif
+#if __riscv_flen == 64
+ case 0b00'101: // c.fsd
+ case 0b10'101: // c.fsdsp
+#endif
+ return SignalContext::Write;
+ default:
+ return SignalContext::Unknown;
+ }
+ }
+#endif
+
+ unsigned opcode = faulty_instruction & 0x7f; // lower 7 bits
+ unsigned funct3 = (faulty_instruction >> 12) & 0x7; // bits 12-14, inclusive
+ switch (opcode) {
+ case 0b0000011: // loads
+ switch (funct3) {
+ case 0b000: // lb
+ case 0b001: // lh
+ case 0b010: // lw
+#if __riscv_xlen == 64
+ case 0b011: // ld
+#endif
+ case 0b100: // lbu
+ case 0b101: // lhu
+ return SignalContext::Read;
+ default:
+ return SignalContext::Unknown;
+ }
+ case 0b0100011: // stores
+ switch (funct3) {
+ case 0b000: // sb
+ case 0b001: // sh
+ case 0b010: // sw
+#if __riscv_xlen == 64
+ case 0b011: // sd
+#endif
+ return SignalContext::Write;
+ default:
+ return SignalContext::Unknown;
+ }
+#if __riscv_flen >= 32
+ case 0b0000111: // floating-point loads
+ switch (funct3) {
+ case 0b010: // flw
+#if __riscv_flen == 64
+ case 0b011: // fld
+#endif
+ return SignalContext::Read;
+ default:
+ return SignalContext::Unknown;
+ }
+ case 0b0100111: // floating-point stores
+ switch (funct3) {
+ case 0b010: // fsw
+#if __riscv_flen == 64
+ case 0b011: // fsd
+#endif
+ return SignalContext::Write;
+ default:
+ return SignalContext::Unknown;
+ }
+#endif
+ default:
+ return SignalContext::Unknown;
+ }
+#else
+ (void)ucontext;
+ return Unknown; // FIXME: Implement.
+#endif
+}
+
+bool SignalContext::IsTrueFaultingAddress() const {
+ auto si = static_cast<const siginfo_t *>(siginfo);
+ // SIGSEGV signals without a true fault address have si_code set to 128.
+ return si->si_signo == SIGSEGV && si->si_code != 128;
+}
+
+void SignalContext::DumpAllRegisters(void *context) {
+ // FIXME: Implement this.
+}
+
+static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
+#if SANITIZER_NETBSD
+ // This covers all NetBSD architectures
+ ucontext_t *ucontext = (ucontext_t *)context;
+ *pc = _UC_MACHINE_PC(ucontext);
+ *bp = _UC_MACHINE_FP(ucontext);
+ *sp = _UC_MACHINE_SP(ucontext);
+#elif defined(__arm__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.arm_pc;
+ *bp = ucontext->uc_mcontext.arm_fp;
+ *sp = ucontext->uc_mcontext.arm_sp;
+#elif defined(__aarch64__)
+# if SANITIZER_FREEBSD
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.mc_gpregs.gp_elr;
+ *bp = ucontext->uc_mcontext.mc_gpregs.gp_x[29];
+ *sp = ucontext->uc_mcontext.mc_gpregs.gp_sp;
+# else
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.pc;
+ *bp = ucontext->uc_mcontext.regs[29];
+ *sp = ucontext->uc_mcontext.sp;
+# endif
+#elif defined(__hppa__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.sc_iaoq[0];
+ /* GCC uses %r3 whenever a frame pointer is needed. */
+ *bp = ucontext->uc_mcontext.sc_gr[3];
+ *sp = ucontext->uc_mcontext.sc_gr[30];
+#elif defined(__x86_64__)
+# if SANITIZER_FREEBSD
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.mc_rip;
+ *bp = ucontext->uc_mcontext.mc_rbp;
+ *sp = ucontext->uc_mcontext.mc_rsp;
+# else
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.gregs[REG_RIP];
+ *bp = ucontext->uc_mcontext.gregs[REG_RBP];
+ *sp = ucontext->uc_mcontext.gregs[REG_RSP];
+# endif
+#elif defined(__i386__)
+# if SANITIZER_FREEBSD
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.mc_eip;
+ *bp = ucontext->uc_mcontext.mc_ebp;
+ *sp = ucontext->uc_mcontext.mc_esp;
+# else
+ ucontext_t *ucontext = (ucontext_t*)context;
+# if SANITIZER_SOLARIS
+ /* Use the numeric values: the symbolic ones are undefined by llvm
+ include/llvm/Support/Solaris.h. */
+# ifndef REG_EIP
+# define REG_EIP 14 // REG_PC
+# endif
+# ifndef REG_EBP
+# define REG_EBP 6 // REG_FP
+# endif
+# ifndef REG_UESP
+# define REG_UESP 17 // REG_SP
+# endif
+# endif
+ *pc = ucontext->uc_mcontext.gregs[REG_EIP];
+ *bp = ucontext->uc_mcontext.gregs[REG_EBP];
+ *sp = ucontext->uc_mcontext.gregs[REG_UESP];
+# endif
+#elif defined(__powerpc__) || defined(__powerpc64__)
+# if SANITIZER_FREEBSD
+ ucontext_t *ucontext = (ucontext_t *)context;
+ *pc = ucontext->uc_mcontext.mc_srr0;
+ *sp = ucontext->uc_mcontext.mc_frame[1];
+ *bp = ucontext->uc_mcontext.mc_frame[31];
+# else
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.regs->nip;
+ *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
+ // The powerpc{,64}-linux ABIs do not specify r31 as the frame
+ // pointer, but GCC always uses r31 when we need a frame pointer.
+ *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
+# endif
+#elif defined(__sparc__)
+#if defined(__arch64__) || defined(__sparcv9)
+#define STACK_BIAS 2047
+#else
+#define STACK_BIAS 0
+# endif
+# if SANITIZER_SOLARIS
+ ucontext_t *ucontext = (ucontext_t *)context;
+ *pc = ucontext->uc_mcontext.gregs[REG_PC];
+ *sp = ucontext->uc_mcontext.gregs[REG_O6] + STACK_BIAS;
+#else
+ // Historical BSDism here.
+ struct sigcontext *scontext = (struct sigcontext *)context;
+#if defined(__arch64__)
+ *pc = scontext->sigc_regs.tpc;
+ *sp = scontext->sigc_regs.u_regs[14] + STACK_BIAS;
+#else
+ *pc = scontext->si_regs.pc;
+ *sp = scontext->si_regs.u_regs[14];
+#endif
+# endif
+ *bp = (uptr)((uhwptr *)*sp)[14] + STACK_BIAS;
+#elif defined(__mips__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.pc;
+ *bp = ucontext->uc_mcontext.gregs[30];
+ *sp = ucontext->uc_mcontext.gregs[29];
+#elif defined(__s390__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+# if defined(__s390x__)
+ *pc = ucontext->uc_mcontext.psw.addr;
+# else
+ *pc = ucontext->uc_mcontext.psw.addr & 0x7fffffff;
+# endif
+ *bp = ucontext->uc_mcontext.gregs[11];
+ *sp = ucontext->uc_mcontext.gregs[15];
+#elif defined(__riscv)
+ ucontext_t *ucontext = (ucontext_t*)context;
+# if SANITIZER_FREEBSD
+ *pc = ucontext->uc_mcontext.mc_gpregs.gp_sepc;
+ *bp = ucontext->uc_mcontext.mc_gpregs.gp_s[0];
+ *sp = ucontext->uc_mcontext.mc_gpregs.gp_sp;
+# else
+ *pc = ucontext->uc_mcontext.__gregs[REG_PC];
+ *bp = ucontext->uc_mcontext.__gregs[REG_S0];
+ *sp = ucontext->uc_mcontext.__gregs[REG_SP];
+# endif
+# elif defined(__hexagon__)
+ ucontext_t *ucontext = (ucontext_t *)context;
+ *pc = ucontext->uc_mcontext.pc;
+ *bp = ucontext->uc_mcontext.r30;
+ *sp = ucontext->uc_mcontext.r29;
+# elif defined(__loongarch__)
+ ucontext_t *ucontext = (ucontext_t *)context;
+ *pc = ucontext->uc_mcontext.__pc;
+ *bp = ucontext->uc_mcontext.__gregs[22];
+ *sp = ucontext->uc_mcontext.__gregs[3];
+# else
+# error "Unsupported arch"
+# endif
+}
+
+void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); }
+
+void InitializePlatformEarly() {
+ // Do nothing.
+}
+
+void CheckASLR() {
+#if SANITIZER_NETBSD
+ int mib[3];
+ int paxflags;
+ uptr len = sizeof(paxflags);
+
+ mib[0] = CTL_PROC;
+ mib[1] = internal_getpid();
+ mib[2] = PROC_PID_PAXFLAGS;
+
+ if (UNLIKELY(internal_sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)) {
+ Printf("sysctl failed\n");
+ Die();
+ }
+
+ if (UNLIKELY(paxflags & CTL_PROC_PAXFLAGS_ASLR)) {
+ Printf("This sanitizer is not compatible with enabled ASLR.\n"
+ "To disable ASLR, please run \"paxctl +a %s\" and try again.\n",
+ GetArgv()[0]);
+ Die();
+ }
+#elif SANITIZER_FREEBSD
+ int aslr_status;
+ int r = internal_procctl(P_PID, 0, PROC_ASLR_STATUS, &aslr_status);
+ if (UNLIKELY(r == -1)) {
+ // We're making things less 'dramatic' here since
+ // the cmd is not necessarily guaranteed to be here
+ // just yet regarding FreeBSD release
+ return;
+ }
+ if ((aslr_status & PROC_ASLR_ACTIVE) != 0) {
+ Printf("This sanitizer is not compatible with enabled ASLR "
+ "and binaries compiled with PIE\n");
+ Die();
+ }
+# elif SANITIZER_PPC64V2
+ // Disable ASLR for Linux PPC64LE.
+ int old_personality = personality(0xffffffff);
+ if (old_personality != -1 && (old_personality & ADDR_NO_RANDOMIZE) == 0) {
+ VReport(1,
+ "WARNING: Program is being run with address space layout "
+ "randomization (ASLR) enabled which prevents the thread and "
+ "memory sanitizers from working on powerpc64le.\n"
+ "ASLR will be disabled and the program re-executed.\n");
+ CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
+ ReExec();
+ }
+# else
+ // Do nothing
+# endif
+}
+
+void CheckMPROTECT() {
+#if SANITIZER_NETBSD
+ int mib[3];
+ int paxflags;
+ uptr len = sizeof(paxflags);
+
+ mib[0] = CTL_PROC;
+ mib[1] = internal_getpid();
+ mib[2] = PROC_PID_PAXFLAGS;
+
+ if (UNLIKELY(internal_sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)) {
+ Printf("sysctl failed\n");
+ Die();
+ }
+
+ if (UNLIKELY(paxflags & CTL_PROC_PAXFLAGS_MPROTECT)) {
+ Printf("This sanitizer is not compatible with enabled MPROTECT\n");
+ Die();
+ }
+#else
+ // Do nothing
+#endif
+}
+
+void CheckNoDeepBind(const char *filename, int flag) {
+#ifdef RTLD_DEEPBIND
+ if (flag & RTLD_DEEPBIND) {
+ Report(
+ "You are trying to dlopen a %s shared library with RTLD_DEEPBIND flag"
+ " which is incompatible with sanitizer runtime "
+ "(see https://github.com/google/sanitizers/issues/611 for details"
+ "). If you want to run %s library under sanitizers please remove "
+ "RTLD_DEEPBIND from dlopen flags.\n",
+ filename, filename);
+ Die();
+ }
+#endif
+}
+
+uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
+ uptr *largest_gap_found,
+ uptr *max_occupied_addr) {
+ UNREACHABLE("FindAvailableMemoryRange is not available");
+ return 0;
+}
+
+bool GetRandom(void *buffer, uptr length, bool blocking) {
+ if (!buffer || !length || length > 256)
+ return false;
+#if SANITIZER_USE_GETENTROPY
+ uptr rnd = getentropy(buffer, length);
+ int rverrno = 0;
+ if (internal_iserror(rnd, &rverrno) && rverrno == EFAULT)
+ return false;
+ else if (rnd == 0)
+ return true;
+#endif // SANITIZER_USE_GETENTROPY
+
+#if SANITIZER_USE_GETRANDOM
+ static atomic_uint8_t skip_getrandom_syscall;
+ if (!atomic_load_relaxed(&skip_getrandom_syscall)) {
+ // Up to 256 bytes, getrandom will not be interrupted.
+ uptr res = internal_syscall(SYSCALL(getrandom), buffer, length,
+ blocking ? 0 : GRND_NONBLOCK);
+ int rverrno = 0;
+ if (internal_iserror(res, &rverrno) && rverrno == ENOSYS)
+ atomic_store_relaxed(&skip_getrandom_syscall, 1);
+ else if (res == length)
+ return true;
+ }
+#endif // SANITIZER_USE_GETRANDOM
+ // Up to 256 bytes, a read off /dev/urandom will not be interrupted.
+ // blocking is moot here, O_NONBLOCK has no effect when opening /dev/urandom.
+ uptr fd = internal_open("/dev/urandom", O_RDONLY);
+ if (internal_iserror(fd))
+ return false;
+ uptr res = internal_read(fd, buffer, length);
+ if (internal_iserror(res))
+ return false;
+ internal_close(fd);
+ return true;
+}
+
+} // namespace __sanitizer
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux.h
new file mode 100644
index 00000000000..2c769dd59aa
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux.h
@@ -0,0 +1,179 @@
+//===-- sanitizer_linux.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Linux-specific syscall wrappers and classes.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_LINUX_H
+#define SANITIZER_LINUX_H
+
+#include "sanitizer_platform.h"
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
+ SANITIZER_SOLARIS
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform_limits_freebsd.h"
+#include "sanitizer_platform_limits_netbsd.h"
+#include "sanitizer_platform_limits_posix.h"
+#include "sanitizer_platform_limits_solaris.h"
+#include "sanitizer_posix.h"
+
+struct link_map; // Opaque type returned by dlopen().
+struct utsname;
+
+namespace __sanitizer {
+// Dirent structure for getdents(). Note that this structure is different from
+// the one in <dirent.h>, which is used by readdir().
+struct linux_dirent;
+
+struct ProcSelfMapsBuff {
+ char *data;
+ uptr mmaped_size;
+ uptr len;
+};
+
+struct MemoryMappingLayoutData {
+ ProcSelfMapsBuff proc_self_maps;
+ const char *current;
+};
+
+void ReadProcMaps(ProcSelfMapsBuff *proc_maps);
+
+// Syscall wrappers.
+uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count);
+uptr internal_sigaltstack(const void* ss, void* oss);
+uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
+ __sanitizer_sigset_t *oldset);
+
+void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset);
+struct ScopedBlockSignals {
+ explicit ScopedBlockSignals(__sanitizer_sigset_t *copy);
+ ~ScopedBlockSignals();
+
+ ScopedBlockSignals &operator=(const ScopedBlockSignals &) = delete;
+ ScopedBlockSignals(const ScopedBlockSignals &) = delete;
+
+ private:
+ __sanitizer_sigset_t saved_;
+};
+
+# if SANITIZER_GLIBC
+uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp);
+#endif
+
+// Linux-only syscalls.
+#if SANITIZER_LINUX
+uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5);
+# if defined(__x86_64__)
+uptr internal_arch_prctl(int option, uptr arg2);
+# endif
+// Used only by sanitizer_stoptheworld. Signal handlers that are actually used
+// (like the process-wide error reporting SEGV handler) must use
+// internal_sigaction instead.
+int internal_sigaction_norestorer(int signum, const void *act, void *oldact);
+void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
+# if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \
+ defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \
+ defined(__arm__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+ int *parent_tidptr, void *newtls, int *child_tidptr);
+#endif
+int internal_uname(struct utsname *buf);
+#elif SANITIZER_FREEBSD
+uptr internal_procctl(int type, int id, int cmd, void *data);
+void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
+#elif SANITIZER_NETBSD
+void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg);
+#endif // SANITIZER_LINUX
+
+// This class reads thread IDs from /proc/<pid>/task using only syscalls.
+class ThreadLister {
+ public:
+ explicit ThreadLister(pid_t pid);
+ ~ThreadLister();
+ enum Result {
+ Error,
+ Incomplete,
+ Ok,
+ };
+ Result ListThreads(InternalMmapVector<tid_t> *threads);
+
+ private:
+ bool IsAlive(int tid);
+
+ pid_t pid_;
+ int descriptor_ = -1;
+ InternalMmapVector<char> buffer_;
+};
+
+// Exposed for testing.
+uptr ThreadDescriptorSize();
+uptr ThreadSelf();
+
+// Matches a library's file name against a base name (stripping path and version
+// information).
+bool LibraryNameIs(const char *full_name, const char *base_name);
+
+// Call cb for each region mapped by map.
+void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr));
+
+// Releases memory pages entirely within the [beg, end] address range.
+// The pages no longer count toward RSS; reads are guaranteed to return 0.
+// Requires (but does not verify!) that pages are MAP_PRIVATE.
+inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) {
+ // man madvise on Linux promises zero-fill for anonymous private pages.
+ // Testing shows the same behaviour for private (but not anonymous) mappings
+ // of shm_open() files, as long as the underlying file is untouched.
+ CHECK(SANITIZER_LINUX);
+ ReleaseMemoryPagesToOS(beg, end);
+}
+
+#if SANITIZER_ANDROID
+
+#if defined(__aarch64__)
+# define __get_tls() \
+ ({ void** __v; __asm__("mrs %0, tpidr_el0" : "=r"(__v)); __v; })
+#elif defined(__arm__)
+# define __get_tls() \
+ ({ void** __v; __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__v)); __v; })
+#elif defined(__mips__)
+// On mips32r1, this goes via a kernel illegal instruction trap that's
+// optimized for v1.
+# define __get_tls() \
+ ({ register void** __v asm("v1"); \
+ __asm__(".set push\n" \
+ ".set mips32r2\n" \
+ "rdhwr %0,$29\n" \
+ ".set pop\n" : "=r"(__v)); \
+ __v; })
+#elif defined(__i386__)
+# define __get_tls() \
+ ({ void** __v; __asm__("movl %%gs:0, %0" : "=r"(__v)); __v; })
+#elif defined(__x86_64__)
+# define __get_tls() \
+ ({ void** __v; __asm__("mov %%fs:0, %0" : "=r"(__v)); __v; })
+#else
+#error "Unsupported architecture."
+#endif
+
+// The Android Bionic team has allocated a TLS slot for sanitizers starting
+// with Q, given that Android currently doesn't support ELF TLS. It is used to
+// store sanitizer thread specific data.
+static const int TLS_SLOT_SANITIZER = 6;
+
+ALWAYS_INLINE uptr *get_android_tls_ptr() {
+ return reinterpret_cast<uptr *>(&__get_tls()[TLS_SLOT_SANITIZER]);
+}
+
+#endif // SANITIZER_ANDROID
+
+} // namespace __sanitizer
+
+#endif
+#endif // SANITIZER_LINUX_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
new file mode 100644
index 00000000000..40ed96e8948
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
@@ -0,0 +1,1079 @@
+//===-- sanitizer_linux_libcdep.cpp ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries and implements linux-specific functions from
+// sanitizer_libc.h.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
+ SANITIZER_SOLARIS
+
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_atomic.h"
+#include "sanitizer_common.h"
+#include "sanitizer_file.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_freebsd.h"
+#include "sanitizer_getauxval.h"
+#include "sanitizer_glibc_version.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_procmaps.h"
+#include "sanitizer_solaris.h"
+
+#if SANITIZER_NETBSD
+#define _RTLD_SOURCE // for __lwp_gettcb_fast() / __lwp_getprivate_fast()
+#endif
+
+#include <dlfcn.h> // for dlsym()
+#include <link.h>
+#include <pthread.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <syslog.h>
+
+#if !defined(ElfW)
+#define ElfW(type) Elf_##type
+#endif
+
+#if SANITIZER_FREEBSD
+#include <pthread_np.h>
+#include <osreldate.h>
+#include <sys/sysctl.h>
+#define pthread_getattr_np pthread_attr_get_np
+// The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
+// that, it was never implemented. So just define it to zero.
+#undef MAP_NORESERVE
+#define MAP_NORESERVE 0
+#endif
+
+#if SANITIZER_NETBSD
+#include <sys/sysctl.h>
+#error #include <sys/tls.h>
+#include <lwp.h>
+#endif
+
+#if SANITIZER_SOLARIS
+#include <stddef.h>
+#include <stdlib.h>
+#include <thread.h>
+#endif
+
+#if SANITIZER_ANDROID
+#include <android/api-level.h>
+#if !defined(CPU_COUNT) && !defined(__aarch64__)
+#include <dirent.h>
+#include <fcntl.h>
+struct __sanitizer::linux_dirent {
+ long d_ino;
+ off_t d_off;
+ unsigned short d_reclen;
+ char d_name[];
+};
+#endif
+#endif
+
+#if !SANITIZER_ANDROID
+#include <elf.h>
+#include <unistd.h>
+#endif
+
+namespace __sanitizer {
+
+SANITIZER_WEAK_ATTRIBUTE int
+real_sigaction(int signum, const void *act, void *oldact);
+
+int internal_sigaction(int signum, const void *act, void *oldact) {
+#if !SANITIZER_GO
+ if (&real_sigaction)
+ return real_sigaction(signum, act, oldact);
+#endif
+ return sigaction(signum, (const struct sigaction *)act,
+ (struct sigaction *)oldact);
+}
+
+void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
+ uptr *stack_bottom) {
+ CHECK(stack_top);
+ CHECK(stack_bottom);
+ if (at_initialization) {
+ // This is the main thread. Libpthread may not be initialized yet.
+ struct rlimit rl;
+ CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
+
+ // Find the mapping that contains a stack variable.
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+ if (proc_maps.Error()) {
+ *stack_top = *stack_bottom = 0;
+ return;
+ }
+ MemoryMappedSegment segment;
+ uptr prev_end = 0;
+ while (proc_maps.Next(&segment)) {
+ if ((uptr)&rl < segment.end) break;
+ prev_end = segment.end;
+ }
+ CHECK((uptr)&rl >= segment.start && (uptr)&rl < segment.end);
+
+ // Get stacksize from rlimit, but clip it so that it does not overlap
+ // with other mappings.
+ uptr stacksize = rl.rlim_cur;
+ if (stacksize > segment.end - prev_end) stacksize = segment.end - prev_end;
+ // When running with unlimited stack size, we still want to set some limit.
+ // The unlimited stack size is caused by 'ulimit -s unlimited'.
+ // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
+ if (stacksize > kMaxThreadStackSize)
+ stacksize = kMaxThreadStackSize;
+ *stack_top = segment.end;
+ *stack_bottom = segment.end - stacksize;
+ return;
+ }
+ uptr stacksize = 0;
+ void *stackaddr = nullptr;
+#if SANITIZER_SOLARIS
+ stack_t ss;
+ CHECK_EQ(thr_stksegment(&ss), 0);
+ stacksize = ss.ss_size;
+ stackaddr = (char *)ss.ss_sp - stacksize;
+#else // !SANITIZER_SOLARIS
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
+ my_pthread_attr_getstack(&attr, &stackaddr, &stacksize);
+ pthread_attr_destroy(&attr);
+#endif // SANITIZER_SOLARIS
+
+ *stack_top = (uptr)stackaddr + stacksize;
+ *stack_bottom = (uptr)stackaddr;
+}
+
+#if !SANITIZER_GO
+bool SetEnv(const char *name, const char *value) {
+ void *f = dlsym(RTLD_NEXT, "setenv");
+ if (!f)
+ return false;
+ typedef int(*setenv_ft)(const char *name, const char *value, int overwrite);
+ setenv_ft setenv_f;
+ CHECK_EQ(sizeof(setenv_f), sizeof(f));
+ internal_memcpy(&setenv_f, &f, sizeof(f));
+ return setenv_f(name, value, 1) == 0;
+}
+#endif
+
+__attribute__((unused)) static bool GetLibcVersion(int *major, int *minor,
+ int *patch) {
+#ifdef _CS_GNU_LIBC_VERSION
+ char buf[64];
+ uptr len = confstr(_CS_GNU_LIBC_VERSION, buf, sizeof(buf));
+ if (len >= sizeof(buf))
+ return false;
+ buf[len] = 0;
+ static const char kGLibC[] = "glibc ";
+ if (internal_strncmp(buf, kGLibC, sizeof(kGLibC) - 1) != 0)
+ return false;
+ const char *p = buf + sizeof(kGLibC) - 1;
+ *major = internal_simple_strtoll(p, &p, 10);
+ *minor = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
+ *patch = (*p == '.') ? internal_simple_strtoll(p + 1, &p, 10) : 0;
+ return true;
+#else
+ return false;
+#endif
+}
+
+// True if we can use dlpi_tls_data. glibc before 2.25 may leave NULL (BZ
+// #19826) so dlpi_tls_data cannot be used.
+//
+// musl before 1.2.3 and FreeBSD as of 12.2 incorrectly set dlpi_tls_data to
+// the TLS initialization image
+// https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=254774
+__attribute__((unused)) static int g_use_dlpi_tls_data;
+
+#if SANITIZER_GLIBC && !SANITIZER_GO
+__attribute__((unused)) static size_t g_tls_size;
+void InitTlsSize() {
+ int major, minor, patch;
+ g_use_dlpi_tls_data =
+ GetLibcVersion(&major, &minor, &patch) && major == 2 && minor >= 25;
+
+#if defined(__aarch64__) || defined(__x86_64__) || defined(__powerpc64__) || \
+ defined(__loongarch__)
+ void *get_tls_static_info = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
+ size_t tls_align;
+ ((void (*)(size_t *, size_t *))get_tls_static_info)(&g_tls_size, &tls_align);
+#endif
+}
+#else
+void InitTlsSize() { }
+#endif // SANITIZER_GLIBC && !SANITIZER_GO
+
+// On glibc x86_64, ThreadDescriptorSize() needs to be precise due to the usage
+// of g_tls_size. On other targets, ThreadDescriptorSize() is only used by lsan
+// to get the pointer to thread-specific data keys in the thread control block.
+#if (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS) && \
+ !SANITIZER_ANDROID && !SANITIZER_GO
+// sizeof(struct pthread) from glibc.
+static atomic_uintptr_t thread_descriptor_size;
+
+static uptr ThreadDescriptorSizeFallback() {
+ uptr val = 0;
+#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
+ int major;
+ int minor;
+ int patch;
+ if (GetLibcVersion(&major, &minor, &patch) && major == 2) {
+ /* sizeof(struct pthread) values from various glibc versions. */
+ if (SANITIZER_X32)
+ val = 1728; // Assume only one particular version for x32.
+ // For ARM sizeof(struct pthread) changed in Glibc 2.23.
+ else if (SANITIZER_ARM)
+ val = minor <= 22 ? 1120 : 1216;
+ else if (minor <= 3)
+ val = FIRST_32_SECOND_64(1104, 1696);
+ else if (minor == 4)
+ val = FIRST_32_SECOND_64(1120, 1728);
+ else if (minor == 5)
+ val = FIRST_32_SECOND_64(1136, 1728);
+ else if (minor <= 9)
+ val = FIRST_32_SECOND_64(1136, 1712);
+ else if (minor == 10)
+ val = FIRST_32_SECOND_64(1168, 1776);
+ else if (minor == 11 || (minor == 12 && patch == 1))
+ val = FIRST_32_SECOND_64(1168, 2288);
+ else if (minor <= 14)
+ val = FIRST_32_SECOND_64(1168, 2304);
+ else if (minor < 32) // Unknown version
+ val = FIRST_32_SECOND_64(1216, 2304);
+ else // minor == 32
+ val = FIRST_32_SECOND_64(1344, 2496);
+ }
+#elif defined(__s390__) || defined(__sparc__)
+ // The size of a prefix of TCB including pthread::{specific_1stblock,specific}
+ // suffices. Just return offsetof(struct pthread, specific_used), which hasn't
+ // changed since 2007-05. Technically this applies to i386/x86_64 as well but
+ // we call _dl_get_tls_static_info and need the precise size of struct
+ // pthread.
+ return FIRST_32_SECOND_64(524, 1552);
+#elif defined(__mips__)
+ // TODO(sagarthakur): add more values as per different glibc versions.
+ val = FIRST_32_SECOND_64(1152, 1776);
+#elif SANITIZER_LOONGARCH64
+ val = 1856; // from glibc 2.36
+#elif SANITIZER_RISCV64
+ int major;
+ int minor;
+ int patch;
+ if (GetLibcVersion(&major, &minor, &patch) && major == 2) {
+ // TODO: consider adding an optional runtime check for an unknown (untested)
+ // glibc version
+ if (minor <= 28) // WARNING: the highest tested version is 2.29
+ val = 1772; // no guarantees for this one
+ else if (minor <= 31)
+ val = 1772; // tested against glibc 2.29, 2.31
+ else
+ val = 1936; // tested against glibc 2.32
+ }
+
+#elif defined(__aarch64__)
+ // The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22.
+ val = 1776;
+#elif defined(__powerpc64__)
+ val = 1776; // from glibc.ppc64le 2.20-8.fc21
+#endif
+ return val;
+}
+
+uptr ThreadDescriptorSize() {
+ uptr val = atomic_load_relaxed(&thread_descriptor_size);
+ if (val)
+ return val;
+ // _thread_db_sizeof_pthread is a GLIBC_PRIVATE symbol that is exported in
+ // glibc 2.34 and later.
+ if (unsigned *psizeof = static_cast<unsigned *>(
+ dlsym(RTLD_DEFAULT, "_thread_db_sizeof_pthread")))
+ val = *psizeof;
+ if (!val)
+ val = ThreadDescriptorSizeFallback();
+ atomic_store_relaxed(&thread_descriptor_size, val);
+ return val;
+}
+
+#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 || \
+ SANITIZER_LOONGARCH64
+// TlsPreTcbSize includes size of struct pthread_descr and size of tcb
+// head structure. It lies before the static tls blocks.
+static uptr TlsPreTcbSize() {
+#if defined(__mips__)
+ const uptr kTcbHead = 16; // sizeof (tcbhead_t)
+#elif defined(__powerpc64__)
+ const uptr kTcbHead = 88; // sizeof (tcbhead_t)
+#elif SANITIZER_RISCV64
+ const uptr kTcbHead = 16; // sizeof (tcbhead_t)
+#elif SANITIZER_LOONGARCH64
+ const uptr kTcbHead = 16; // sizeof (tcbhead_t)
+#endif
+ const uptr kTlsAlign = 16;
+ const uptr kTlsPreTcbSize =
+ RoundUpTo(ThreadDescriptorSize() + kTcbHead, kTlsAlign);
+ return kTlsPreTcbSize;
+}
+#endif
+
+namespace {
+struct TlsBlock {
+ uptr begin, end, align;
+ size_t tls_modid;
+ bool operator<(const TlsBlock &rhs) const { return begin < rhs.begin; }
+};
+} // namespace
+
+#ifdef __s390__
+extern "C" uptr __tls_get_offset(void *arg);
+
+static uptr TlsGetOffset(uptr ti_module, uptr ti_offset) {
+ // The __tls_get_offset ABI requires %r12 to point to GOT and %r2 to be an
+ // offset of a struct tls_index inside GOT. We don't possess either of the
+ // two, so violate the letter of the "ELF Handling For Thread-Local
+ // Storage" document and assume that the implementation just dereferences
+ // %r2 + %r12.
+ uptr tls_index[2] = {ti_module, ti_offset};
+ register uptr r2 asm("2") = 0;
+ register void *r12 asm("12") = tls_index;
+ asm("basr %%r14, %[__tls_get_offset]"
+ : "+r"(r2)
+ : [__tls_get_offset] "r"(__tls_get_offset), "r"(r12)
+ : "memory", "cc", "0", "1", "3", "4", "5", "14");
+ return r2;
+}
+#else
+extern "C" void *__tls_get_addr(size_t *);
+#endif
+
+static size_t main_tls_modid;
+
+static int CollectStaticTlsBlocks(struct dl_phdr_info *info, size_t size,
+ void *data) {
+ size_t tls_modid;
+#if SANITIZER_SOLARIS
+ // dlpi_tls_modid is only available since Solaris 11.4 SRU 10. Use
+ // dlinfo(RTLD_DI_LINKMAP) instead which works on all of Solaris 11.3,
+ // 11.4, and Illumos. The tlsmodid of the executable was changed to 1 in
+ // 11.4 to match other implementations.
+ if (size >= offsetof(dl_phdr_info_test, dlpi_tls_modid))
+ main_tls_modid = 1;
+ else
+ main_tls_modid = 0;
+ g_use_dlpi_tls_data = 0;
+ Rt_map *map;
+ dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &map);
+ tls_modid = map->rt_tlsmodid;
+#else
+ main_tls_modid = 1;
+ tls_modid = info->dlpi_tls_modid;
+#endif
+
+ if (tls_modid < main_tls_modid)
+ return 0;
+ uptr begin;
+#if !SANITIZER_SOLARIS
+ begin = (uptr)info->dlpi_tls_data;
+#endif
+ if (!g_use_dlpi_tls_data) {
+ // Call __tls_get_addr as a fallback. This forces TLS allocation on glibc
+ // and FreeBSD.
+#ifdef __s390__
+ begin = (uptr)__builtin_thread_pointer() +
+ TlsGetOffset(tls_modid, 0);
+#else
+ size_t mod_and_off[2] = {tls_modid, 0};
+ begin = (uptr)__tls_get_addr(mod_and_off);
+#endif
+ }
+ for (unsigned i = 0; i != info->dlpi_phnum; ++i)
+ if (info->dlpi_phdr[i].p_type == PT_TLS) {
+ static_cast<InternalMmapVector<TlsBlock> *>(data)->push_back(
+ TlsBlock{begin, begin + info->dlpi_phdr[i].p_memsz,
+ info->dlpi_phdr[i].p_align, tls_modid});
+ break;
+ }
+ return 0;
+}
+
+__attribute__((unused)) static void GetStaticTlsBoundary(uptr *addr, uptr *size,
+ uptr *align) {
+ InternalMmapVector<TlsBlock> ranges;
+ dl_iterate_phdr(CollectStaticTlsBlocks, &ranges);
+ uptr len = ranges.size();
+ Sort(ranges.begin(), len);
+ // Find the range with tls_modid == main_tls_modid. For glibc, because
+ // libc.so uses PT_TLS, this module is guaranteed to exist and is one of
+ // the initially loaded modules.
+ uptr one = 0;
+ while (one != len && ranges[one].tls_modid != main_tls_modid) ++one;
+ if (one == len) {
+ // This may happen with musl if no module uses PT_TLS.
+ *addr = 0;
+ *size = 0;
+ *align = 1;
+ return;
+ }
+ // Find the maximum consecutive ranges. We consider two modules consecutive if
+ // the gap is smaller than the alignment of the latter range. The dynamic
+ // loader places static TLS blocks this way not to waste space.
+ uptr l = one;
+ *align = ranges[l].align;
+ while (l != 0 && ranges[l].begin < ranges[l - 1].end + ranges[l].align)
+ *align = Max(*align, ranges[--l].align);
+ uptr r = one + 1;
+ while (r != len && ranges[r].begin < ranges[r - 1].end + ranges[r].align)
+ *align = Max(*align, ranges[r++].align);
+ *addr = ranges[l].begin;
+ *size = ranges[r - 1].end - ranges[l].begin;
+}
+#endif // (x86_64 || i386 || mips || ...) && (SANITIZER_FREEBSD ||
+ // SANITIZER_LINUX) && !SANITIZER_ANDROID && !SANITIZER_GO
+
+#if SANITIZER_NETBSD
+static struct tls_tcb * ThreadSelfTlsTcb() {
+ struct tls_tcb *tcb = nullptr;
+#ifdef __HAVE___LWP_GETTCB_FAST
+ tcb = (struct tls_tcb *)__lwp_gettcb_fast();
+#elif defined(__HAVE___LWP_GETPRIVATE_FAST)
+ tcb = (struct tls_tcb *)__lwp_getprivate_fast();
+#endif
+ return tcb;
+}
+
+uptr ThreadSelf() {
+ return (uptr)ThreadSelfTlsTcb()->tcb_pthread;
+}
+
+int GetSizeFromHdr(struct dl_phdr_info *info, size_t size, void *data) {
+ const Elf_Phdr *hdr = info->dlpi_phdr;
+ const Elf_Phdr *last_hdr = hdr + info->dlpi_phnum;
+
+ for (; hdr != last_hdr; ++hdr) {
+ if (hdr->p_type == PT_TLS && info->dlpi_tls_modid == 1) {
+ *(uptr*)data = hdr->p_memsz;
+ break;
+ }
+ }
+ return 0;
+}
+#endif // SANITIZER_NETBSD
+
+#if SANITIZER_ANDROID
+// Bionic provides this API since S.
+extern "C" SANITIZER_WEAK_ATTRIBUTE void __libc_get_static_tls_bounds(void **,
+ void **);
+#endif
+
+#if !SANITIZER_GO
+static void GetTls(uptr *addr, uptr *size) {
+#if SANITIZER_ANDROID
+ if (&__libc_get_static_tls_bounds) {
+ void *start_addr;
+ void *end_addr;
+ __libc_get_static_tls_bounds(&start_addr, &end_addr);
+ *addr = reinterpret_cast<uptr>(start_addr);
+ *size =
+ reinterpret_cast<uptr>(end_addr) - reinterpret_cast<uptr>(start_addr);
+ } else {
+ *addr = 0;
+ *size = 0;
+ }
+#elif SANITIZER_GLIBC && defined(__x86_64__)
+ // For aarch64 and x86-64, use an O(1) approach which requires relatively
+ // precise ThreadDescriptorSize. g_tls_size was initialized in InitTlsSize.
+# if SANITIZER_X32
+ asm("mov %%fs:8,%0" : "=r"(*addr));
+# else
+ asm("mov %%fs:16,%0" : "=r"(*addr));
+# endif
+ *size = g_tls_size;
+ *addr -= *size;
+ *addr += ThreadDescriptorSize();
+#elif SANITIZER_GLIBC && defined(__aarch64__)
+ *addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) -
+ ThreadDescriptorSize();
+ *size = g_tls_size + ThreadDescriptorSize();
+#elif SANITIZER_GLIBC && defined(__loongarch__)
+# ifdef __clang__
+ *addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) -
+ ThreadDescriptorSize();
+# else
+ asm("or %0,$tp,$zero" : "=r"(*addr));
+ *addr -= ThreadDescriptorSize();
+# endif
+ *size = g_tls_size + ThreadDescriptorSize();
+#elif SANITIZER_GLIBC && defined(__powerpc64__)
+ // Workaround for glibc<2.25(?). 2.27 is known to not need this.
+ uptr tp;
+ asm("addi %0,13,-0x7000" : "=r"(tp));
+ const uptr pre_tcb_size = TlsPreTcbSize();
+ *addr = tp - pre_tcb_size;
+ *size = g_tls_size + pre_tcb_size;
+#elif SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS
+ uptr align;
+ GetStaticTlsBoundary(addr, size, &align);
+#if defined(__x86_64__) || defined(__i386__) || defined(__s390__) || \
+ defined(__sparc__)
+ if (SANITIZER_GLIBC) {
+#if defined(__x86_64__) || defined(__i386__)
+ align = Max<uptr>(align, 64);
+#else
+ align = Max<uptr>(align, 16);
+#endif
+ }
+ const uptr tp = RoundUpTo(*addr + *size, align);
+
+ // lsan requires the range to additionally cover the static TLS surplus
+ // (elf/dl-tls.c defines 1664). Otherwise there may be false positives for
+ // allocations only referenced by tls in dynamically loaded modules.
+ if (SANITIZER_GLIBC)
+ *size += 1644;
+ else if (SANITIZER_FREEBSD)
+ *size += 128; // RTLD_STATIC_TLS_EXTRA
+
+ // Extend the range to include the thread control block. On glibc, lsan needs
+ // the range to include pthread::{specific_1stblock,specific} so that
+ // allocations only referenced by pthread_setspecific can be scanned. This may
+ // underestimate by at most TLS_TCB_ALIGN-1 bytes but it should be fine
+ // because the number of bytes after pthread::specific is larger.
+ *addr = tp - RoundUpTo(*size, align);
+ *size = tp - *addr + ThreadDescriptorSize();
+#else
+ if (SANITIZER_GLIBC)
+ *size += 1664;
+ else if (SANITIZER_FREEBSD)
+ *size += 128; // RTLD_STATIC_TLS_EXTRA
+#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64
+ const uptr pre_tcb_size = TlsPreTcbSize();
+ *addr -= pre_tcb_size;
+ *size += pre_tcb_size;
+#else
+ // arm and aarch64 reserve two words at TP, so this underestimates the range.
+ // However, this is sufficient for the purpose of finding the pointers to
+ // thread-specific data keys.
+ const uptr tcb_size = ThreadDescriptorSize();
+ *addr -= tcb_size;
+ *size += tcb_size;
+#endif
+#endif
+#elif SANITIZER_NETBSD
+ struct tls_tcb * const tcb = ThreadSelfTlsTcb();
+ *addr = 0;
+ *size = 0;
+ if (tcb != 0) {
+ // Find size (p_memsz) of dlpi_tls_modid 1 (TLS block of the main program).
+ // ld.elf_so hardcodes the index 1.
+ dl_iterate_phdr(GetSizeFromHdr, size);
+
+ if (*size != 0) {
+ // The block has been found and tcb_dtv[1] contains the base address
+ *addr = (uptr)tcb->tcb_dtv[1];
+ }
+ }
+#else
+#error "Unknown OS"
+#endif
+}
+#endif
+
+#if !SANITIZER_GO
+uptr GetTlsSize() {
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
+ SANITIZER_SOLARIS
+ uptr addr, size;
+ GetTls(&addr, &size);
+ return size;
+#else
+ return 0;
+#endif
+}
+#endif
+
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+ uptr *tls_addr, uptr *tls_size) {
+#if SANITIZER_GO
+ // Stub implementation for Go.
+ *stk_addr = *stk_size = *tls_addr = *tls_size = 0;
+#else
+ GetTls(tls_addr, tls_size);
+
+ uptr stack_top, stack_bottom;
+ GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
+ *stk_addr = stack_bottom;
+ *stk_size = stack_top - stack_bottom;
+
+ if (!main) {
+ // If stack and tls intersect, make them non-intersecting.
+ if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) {
+ if (*stk_addr + *stk_size < *tls_addr + *tls_size)
+ *tls_size = *stk_addr + *stk_size - *tls_addr;
+ *stk_size = *tls_addr - *stk_addr;
+ }
+ }
+#endif
+}
+
+#if !SANITIZER_FREEBSD
+typedef ElfW(Phdr) Elf_Phdr;
+#elif SANITIZER_WORDSIZE == 32 && __FreeBSD_version <= 902001 // v9.2
+#define Elf_Phdr XElf32_Phdr
+#define dl_phdr_info xdl_phdr_info
+#define dl_iterate_phdr(c, b) xdl_iterate_phdr((c), (b))
+#endif // !SANITIZER_FREEBSD
+
+struct DlIteratePhdrData {
+ InternalMmapVectorNoCtor<LoadedModule> *modules;
+ bool first;
+};
+
+static int AddModuleSegments(const char *module_name, dl_phdr_info *info,
+ InternalMmapVectorNoCtor<LoadedModule> *modules) {
+ if (module_name[0] == '\0')
+ return 0;
+ LoadedModule cur_module;
+ cur_module.set(module_name, info->dlpi_addr);
+ for (int i = 0; i < (int)info->dlpi_phnum; i++) {
+ const Elf_Phdr *phdr = &info->dlpi_phdr[i];
+ if (phdr->p_type == PT_LOAD) {
+ uptr cur_beg = info->dlpi_addr + phdr->p_vaddr;
+ uptr cur_end = cur_beg + phdr->p_memsz;
+ bool executable = phdr->p_flags & PF_X;
+ bool writable = phdr->p_flags & PF_W;
+ cur_module.addAddressRange(cur_beg, cur_end, executable,
+ writable);
+ } else if (phdr->p_type == PT_NOTE) {
+# ifdef NT_GNU_BUILD_ID
+ uptr off = 0;
+ while (off + sizeof(ElfW(Nhdr)) < phdr->p_memsz) {
+ auto *nhdr = reinterpret_cast<const ElfW(Nhdr) *>(info->dlpi_addr +
+ phdr->p_vaddr + off);
+ constexpr auto kGnuNamesz = 4; // "GNU" with NUL-byte.
+ static_assert(kGnuNamesz % 4 == 0, "kGnuNameSize is aligned to 4.");
+ if (nhdr->n_type == NT_GNU_BUILD_ID && nhdr->n_namesz == kGnuNamesz) {
+ if (off + sizeof(ElfW(Nhdr)) + nhdr->n_namesz + nhdr->n_descsz >
+ phdr->p_memsz) {
+ // Something is very wrong, bail out instead of reading potentially
+ // arbitrary memory.
+ break;
+ }
+ const char *name =
+ reinterpret_cast<const char *>(nhdr) + sizeof(*nhdr);
+ if (internal_memcmp(name, "GNU", 3) == 0) {
+ const char *value = reinterpret_cast<const char *>(nhdr) +
+ sizeof(*nhdr) + kGnuNamesz;
+ cur_module.setUuid(value, nhdr->n_descsz);
+ break;
+ }
+ }
+ off += sizeof(*nhdr) + RoundUpTo(nhdr->n_namesz, 4) +
+ RoundUpTo(nhdr->n_descsz, 4);
+ }
+# endif
+ }
+ }
+ modules->push_back(cur_module);
+ return 0;
+}
+
+static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
+ DlIteratePhdrData *data = (DlIteratePhdrData *)arg;
+ if (data->first) {
+ InternalMmapVector<char> module_name(kMaxPathLength);
+ data->first = false;
+ // First module is the binary itself.
+ ReadBinaryNameCached(module_name.data(), module_name.size());
+ return AddModuleSegments(module_name.data(), info, data->modules);
+ }
+
+ if (info->dlpi_name) {
+ InternalScopedString module_name;
+ module_name.append("%s", info->dlpi_name);
+ return AddModuleSegments(module_name.data(), info, data->modules);
+ }
+
+ return 0;
+}
+
+#if SANITIZER_ANDROID && __ANDROID_API__ < 21
+extern "C" __attribute__((weak)) int dl_iterate_phdr(
+ int (*)(struct dl_phdr_info *, size_t, void *), void *);
+#endif
+
+static bool requiresProcmaps() {
+#if SANITIZER_ANDROID && __ANDROID_API__ <= 22
+ // Fall back to /proc/maps if dl_iterate_phdr is unavailable or broken.
+ // The runtime check allows the same library to work with
+ // both K and L (and future) Android releases.
+ return AndroidGetApiLevel() <= ANDROID_LOLLIPOP_MR1;
+#else
+ return false;
+#endif
+}
+
+static void procmapsInit(InternalMmapVectorNoCtor<LoadedModule> *modules) {
+ MemoryMappingLayout memory_mapping(/*cache_enabled*/true);
+ memory_mapping.DumpListOfModules(modules);
+}
+
+void ListOfModules::init() {
+ clearOrInit();
+ if (requiresProcmaps()) {
+ procmapsInit(&modules_);
+ } else {
+ DlIteratePhdrData data = {&modules_, true};
+ dl_iterate_phdr(dl_iterate_phdr_cb, &data);
+ }
+}
+
+// When a custom loader is used, dl_iterate_phdr may not contain the full
+// list of modules. Allow callers to fall back to using procmaps.
+void ListOfModules::fallbackInit() {
+ if (!requiresProcmaps()) {
+ clearOrInit();
+ procmapsInit(&modules_);
+ } else {
+ clear();
+ }
+}
+
+// getrusage does not give us the current RSS, only the max RSS.
+// Still, this is better than nothing if /proc/self/statm is not available
+// for some reason, e.g. due to a sandbox.
+static uptr GetRSSFromGetrusage() {
+ struct rusage usage;
+ if (getrusage(RUSAGE_SELF, &usage)) // Failed, probably due to a sandbox.
+ return 0;
+ return usage.ru_maxrss << 10; // ru_maxrss is in Kb.
+}
+
+uptr GetRSS() {
+ if (!common_flags()->can_use_proc_maps_statm)
+ return GetRSSFromGetrusage();
+ fd_t fd = OpenFile("/proc/self/statm", RdOnly);
+ if (fd == kInvalidFd)
+ return GetRSSFromGetrusage();
+ char buf[64];
+ uptr len = internal_read(fd, buf, sizeof(buf) - 1);
+ internal_close(fd);
+ if ((sptr)len <= 0)
+ return 0;
+ buf[len] = 0;
+ // The format of the file is:
+ // 1084 89 69 11 0 79 0
+ // We need the second number which is RSS in pages.
+ char *pos = buf;
+ // Skip the first number.
+ while (*pos >= '0' && *pos <= '9')
+ pos++;
+ // Skip whitespaces.
+ while (!(*pos >= '0' && *pos <= '9') && *pos != 0)
+ pos++;
+ // Read the number.
+ uptr rss = 0;
+ while (*pos >= '0' && *pos <= '9')
+ rss = rss * 10 + *pos++ - '0';
+ return rss * GetPageSizeCached();
+}
+
+// sysconf(_SC_NPROCESSORS_{CONF,ONLN}) cannot be used on most platforms as
+// they allocate memory.
+u32 GetNumberOfCPUs() {
+#if SANITIZER_FREEBSD || SANITIZER_NETBSD
+ u32 ncpu;
+ int req[2];
+ uptr len = sizeof(ncpu);
+ req[0] = CTL_HW;
+ req[1] = HW_NCPU;
+ CHECK_EQ(internal_sysctl(req, 2, &ncpu, &len, NULL, 0), 0);
+ return ncpu;
+#elif SANITIZER_ANDROID && !defined(CPU_COUNT) && !defined(__aarch64__)
+ // Fall back to /sys/devices/system/cpu on Android when cpu_set_t doesn't
+ // exist in sched.h. That is the case for toolchains generated with older
+ // NDKs.
+ // This code doesn't work on AArch64 because internal_getdents makes use of
+ // the 64bit getdents syscall, but cpu_set_t seems to always exist on AArch64.
+ uptr fd = internal_open("/sys/devices/system/cpu", O_RDONLY | O_DIRECTORY);
+ if (internal_iserror(fd))
+ return 0;
+ InternalMmapVector<u8> buffer(4096);
+ uptr bytes_read = buffer.size();
+ uptr n_cpus = 0;
+ u8 *d_type;
+ struct linux_dirent *entry = (struct linux_dirent *)&buffer[bytes_read];
+ while (true) {
+ if ((u8 *)entry >= &buffer[bytes_read]) {
+ bytes_read = internal_getdents(fd, (struct linux_dirent *)buffer.data(),
+ buffer.size());
+ if (internal_iserror(bytes_read) || !bytes_read)
+ break;
+ entry = (struct linux_dirent *)buffer.data();
+ }
+ d_type = (u8 *)entry + entry->d_reclen - 1;
+ if (d_type >= &buffer[bytes_read] ||
+ (u8 *)&entry->d_name[3] >= &buffer[bytes_read])
+ break;
+ if (entry->d_ino != 0 && *d_type == DT_DIR) {
+ if (entry->d_name[0] == 'c' && entry->d_name[1] == 'p' &&
+ entry->d_name[2] == 'u' &&
+ entry->d_name[3] >= '0' && entry->d_name[3] <= '9')
+ n_cpus++;
+ }
+ entry = (struct linux_dirent *)(((u8 *)entry) + entry->d_reclen);
+ }
+ internal_close(fd);
+ return n_cpus;
+#elif SANITIZER_SOLARIS
+ return sysconf(_SC_NPROCESSORS_ONLN);
+#else
+ cpu_set_t CPUs;
+ CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0);
+ return CPU_COUNT(&CPUs);
+#endif
+}
+
+#if SANITIZER_LINUX
+
+#if SANITIZER_ANDROID
+static atomic_uint8_t android_log_initialized;
+
+void AndroidLogInit() {
+ openlog(GetProcessName(), 0, LOG_USER);
+ atomic_store(&android_log_initialized, 1, memory_order_release);
+}
+
+static bool ShouldLogAfterPrintf() {
+ return atomic_load(&android_log_initialized, memory_order_acquire);
+}
+
+extern "C" SANITIZER_WEAK_ATTRIBUTE
+int async_safe_write_log(int pri, const char* tag, const char* msg);
+extern "C" SANITIZER_WEAK_ATTRIBUTE
+int __android_log_write(int prio, const char* tag, const char* msg);
+
+// ANDROID_LOG_INFO is 4, but can't be resolved at runtime.
+#define SANITIZER_ANDROID_LOG_INFO 4
+
+// async_safe_write_log is a new public version of __libc_write_log that is
+// used behind syslog. It is preferable to syslog as it will not do any dynamic
+// memory allocation or formatting.
+// If the function is not available, syslog is preferred for L+ (it was broken
+// pre-L) as __android_log_write triggers a racey behavior with the strncpy
+// interceptor. Fallback to __android_log_write pre-L.
+void WriteOneLineToSyslog(const char *s) {
+ if (&async_safe_write_log) {
+ async_safe_write_log(SANITIZER_ANDROID_LOG_INFO, GetProcessName(), s);
+ } else if (AndroidGetApiLevel() > ANDROID_KITKAT) {
+ syslog(LOG_INFO, "%s", s);
+ } else {
+ CHECK(&__android_log_write);
+ __android_log_write(SANITIZER_ANDROID_LOG_INFO, nullptr, s);
+ }
+}
+
+extern "C" SANITIZER_WEAK_ATTRIBUTE
+void android_set_abort_message(const char *);
+
+void SetAbortMessage(const char *str) {
+ if (&android_set_abort_message)
+ android_set_abort_message(str);
+}
+#else
+void AndroidLogInit() {}
+
+static bool ShouldLogAfterPrintf() { return true; }
+
+void WriteOneLineToSyslog(const char *s) { syslog(LOG_INFO, "%s", s); }
+
+void SetAbortMessage(const char *str) {}
+#endif // SANITIZER_ANDROID
+
+void LogMessageOnPrintf(const char *str) {
+ if (common_flags()->log_to_syslog && ShouldLogAfterPrintf())
+ WriteToSyslog(str);
+}
+
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_GLIBC && !SANITIZER_GO
+// glibc crashes when using clock_gettime from a preinit_array function as the
+// vDSO function pointers haven't been initialized yet. __progname is
+// initialized after the vDSO function pointers, so if it exists, is not null
+// and is not empty, we can use clock_gettime.
+extern "C" SANITIZER_WEAK_ATTRIBUTE char *__progname;
+inline bool CanUseVDSO() { return &__progname && __progname && *__progname; }
+
+// MonotonicNanoTime is a timing function that can leverage the vDSO by calling
+// clock_gettime. real_clock_gettime only exists if clock_gettime is
+// intercepted, so define it weakly and use it if available.
+extern "C" SANITIZER_WEAK_ATTRIBUTE
+int real_clock_gettime(u32 clk_id, void *tp);
+u64 MonotonicNanoTime() {
+ timespec ts;
+ if (CanUseVDSO()) {
+ if (&real_clock_gettime)
+ real_clock_gettime(CLOCK_MONOTONIC, &ts);
+ else
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ } else {
+ internal_clock_gettime(CLOCK_MONOTONIC, &ts);
+ }
+ return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec;
+}
+#else
+// Non-glibc & Go always use the regular function.
+u64 MonotonicNanoTime() {
+ timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec;
+}
+#endif // SANITIZER_GLIBC && !SANITIZER_GO
+
+void ReExec() {
+ const char *pathname = "/proc/self/exe";
+
+#if SANITIZER_NETBSD
+ static const int name[] = {
+ CTL_KERN,
+ KERN_PROC_ARGS,
+ -1,
+ KERN_PROC_PATHNAME,
+ };
+ char path[400];
+ uptr len;
+
+ len = sizeof(path);
+ if (internal_sysctl(name, ARRAY_SIZE(name), path, &len, NULL, 0) != -1)
+ pathname = path;
+#elif SANITIZER_SOLARIS
+ pathname = getexecname();
+ CHECK_NE(pathname, NULL);
+#elif SANITIZER_USE_GETAUXVAL
+ // Calling execve with /proc/self/exe sets that as $EXEC_ORIGIN. Binaries that
+ // rely on that will fail to load shared libraries. Query AT_EXECFN instead.
+ pathname = reinterpret_cast<const char *>(getauxval(AT_EXECFN));
+#endif
+
+ uptr rv = internal_execve(pathname, GetArgv(), GetEnviron());
+ int rverrno;
+ CHECK_EQ(internal_iserror(rv, &rverrno), true);
+ Printf("execve failed, errno %d\n", rverrno);
+ Die();
+}
+
+void UnmapFromTo(uptr from, uptr to) {
+ if (to == from)
+ return;
+ CHECK(to >= from);
+ uptr res = internal_munmap(reinterpret_cast<void *>(from), to - from);
+ if (UNLIKELY(internal_iserror(res))) {
+ Report("ERROR: %s failed to unmap 0x%zx (%zd) bytes at address %p\n",
+ SanitizerToolName, to - from, to - from, (void *)from);
+ CHECK("unable to unmap" && 0);
+ }
+}
+
+uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
+ uptr min_shadow_base_alignment,
+ UNUSED uptr &high_mem_end) {
+ const uptr granularity = GetMmapGranularity();
+ const uptr alignment =
+ Max<uptr>(granularity << shadow_scale, 1ULL << min_shadow_base_alignment);
+ const uptr left_padding =
+ Max<uptr>(granularity, 1ULL << min_shadow_base_alignment);
+
+ const uptr shadow_size = RoundUpTo(shadow_size_bytes, granularity);
+ const uptr map_size = shadow_size + left_padding + alignment;
+
+ const uptr map_start = (uptr)MmapNoAccess(map_size);
+ CHECK_NE(map_start, ~(uptr)0);
+
+ const uptr shadow_start = RoundUpTo(map_start + left_padding, alignment);
+
+ UnmapFromTo(map_start, shadow_start - left_padding);
+ UnmapFromTo(shadow_start + shadow_size, map_start + map_size);
+
+ return shadow_start;
+}
+
+static uptr MmapSharedNoReserve(uptr addr, uptr size) {
+ return internal_mmap(
+ reinterpret_cast<void *>(addr), size, PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
+}
+
+static uptr MremapCreateAlias(uptr base_addr, uptr alias_addr,
+ uptr alias_size) {
+#if SANITIZER_LINUX
+ return internal_mremap(reinterpret_cast<void *>(base_addr), 0, alias_size,
+ MREMAP_MAYMOVE | MREMAP_FIXED,
+ reinterpret_cast<void *>(alias_addr));
+#else
+ CHECK(false && "mremap is not supported outside of Linux");
+ return 0;
+#endif
+}
+
+static void CreateAliases(uptr start_addr, uptr alias_size, uptr num_aliases) {
+ uptr total_size = alias_size * num_aliases;
+ uptr mapped = MmapSharedNoReserve(start_addr, total_size);
+ CHECK_EQ(mapped, start_addr);
+
+ for (uptr i = 1; i < num_aliases; ++i) {
+ uptr alias_addr = start_addr + i * alias_size;
+ CHECK_EQ(MremapCreateAlias(start_addr, alias_addr, alias_size), alias_addr);
+ }
+}
+
+uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,
+ uptr num_aliases, uptr ring_buffer_size) {
+ CHECK_EQ(alias_size & (alias_size - 1), 0);
+ CHECK_EQ(num_aliases & (num_aliases - 1), 0);
+ CHECK_EQ(ring_buffer_size & (ring_buffer_size - 1), 0);
+
+ const uptr granularity = GetMmapGranularity();
+ shadow_size = RoundUpTo(shadow_size, granularity);
+ CHECK_EQ(shadow_size & (shadow_size - 1), 0);
+
+ const uptr alias_region_size = alias_size * num_aliases;
+ const uptr alignment =
+ 2 * Max(Max(shadow_size, alias_region_size), ring_buffer_size);
+ const uptr left_padding = ring_buffer_size;
+
+ const uptr right_size = alignment;
+ const uptr map_size = left_padding + 2 * alignment;
+
+ const uptr map_start = reinterpret_cast<uptr>(MmapNoAccess(map_size));
+ CHECK_NE(map_start, static_cast<uptr>(-1));
+ const uptr right_start = RoundUpTo(map_start + left_padding, alignment);
+
+ UnmapFromTo(map_start, right_start - left_padding);
+ UnmapFromTo(right_start + right_size, map_start + map_size);
+
+ CreateAliases(right_start + right_size / 2, alias_size, num_aliases);
+
+ return right_start;
+}
+
+void InitializePlatformCommonFlags(CommonFlags *cf) {
+#if SANITIZER_ANDROID
+ if (&__libc_get_static_tls_bounds == nullptr)
+ cf->detect_leaks = false;
+#endif
+}
+
+} // namespace __sanitizer
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux_s390.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux_s390.cpp
new file mode 100644
index 00000000000..74db831b0aa
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_linux_s390.cpp
@@ -0,0 +1,228 @@
+//===-- sanitizer_linux_s390.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries and implements s390-linux-specific functions from
+// sanitizer_libc.h.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_LINUX && SANITIZER_S390
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <sys/syscall.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+
+#include "sanitizer_libc.h"
+#include "sanitizer_linux.h"
+
+namespace __sanitizer {
+
+// --------------- sanitizer_libc.h
+uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
+ u64 offset) {
+ struct s390_mmap_params {
+ unsigned long addr;
+ unsigned long length;
+ unsigned long prot;
+ unsigned long flags;
+ unsigned long fd;
+ unsigned long offset;
+ } params = {
+ (unsigned long)addr,
+ (unsigned long)length,
+ (unsigned long)prot,
+ (unsigned long)flags,
+ (unsigned long)fd,
+# ifdef __s390x__
+ (unsigned long)offset,
+# else
+ (unsigned long)(offset / 4096),
+# endif
+ };
+# ifdef __s390x__
+ return syscall(__NR_mmap, &params);
+# else
+ return syscall(__NR_mmap2, &params);
+# endif
+}
+
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+ int *parent_tidptr, void *newtls, int *child_tidptr) {
+ if (!fn || !child_stack) {
+ errno = EINVAL;
+ return -1;
+ }
+ CHECK_EQ(0, (uptr)child_stack % 16);
+ // Minimum frame size.
+#ifdef __s390x__
+ child_stack = (char *)child_stack - 160;
+#else
+ child_stack = (char *)child_stack - 96;
+#endif
+ // Terminate unwind chain.
+ ((unsigned long *)child_stack)[0] = 0;
+ // And pass parameters.
+ ((unsigned long *)child_stack)[1] = (uptr)fn;
+ ((unsigned long *)child_stack)[2] = (uptr)arg;
+ register uptr res __asm__("r2");
+ register void *__cstack __asm__("r2") = child_stack;
+ register long __flags __asm__("r3") = flags;
+ register int * __ptidptr __asm__("r4") = parent_tidptr;
+ register int * __ctidptr __asm__("r5") = child_tidptr;
+ register void * __newtls __asm__("r6") = newtls;
+
+ __asm__ __volatile__(
+ /* Clone. */
+ "svc %1\n"
+
+ /* if (%r2 != 0)
+ * return;
+ */
+#ifdef __s390x__
+ "cghi %%r2, 0\n"
+#else
+ "chi %%r2, 0\n"
+#endif
+ "jne 1f\n"
+
+ /* Call "fn(arg)". */
+#ifdef __s390x__
+ "lmg %%r1, %%r2, 8(%%r15)\n"
+#else
+ "lm %%r1, %%r2, 4(%%r15)\n"
+#endif
+ "basr %%r14, %%r1\n"
+
+ /* Call _exit(%r2). */
+ "svc %2\n"
+
+ /* Return to parent. */
+ "1:\n"
+ : "=r" (res)
+ : "i"(__NR_clone), "i"(__NR_exit),
+ "r"(__cstack),
+ "r"(__flags),
+ "r"(__ptidptr),
+ "r"(__ctidptr),
+ "r"(__newtls)
+ : "memory", "cc");
+ if (res >= (uptr)-4095) {
+ errno = -res;
+ return -1;
+ }
+ return res;
+}
+
+#if SANITIZER_S390_64
+static bool FixedCVE_2016_2143() {
+ // Try to determine if the running kernel has a fix for CVE-2016-2143,
+ // return false if in doubt (better safe than sorry). Distros may want to
+ // adjust this for their own kernels.
+ struct utsname buf;
+ unsigned int major, minor, patch = 0;
+ // This should never fail, but just in case...
+ if (internal_uname(&buf))
+ return false;
+ const char *ptr = buf.release;
+ major = internal_simple_strtoll(ptr, &ptr, 10);
+ // At least first 2 should be matched.
+ if (ptr[0] != '.')
+ return false;
+ minor = internal_simple_strtoll(ptr+1, &ptr, 10);
+ // Third is optional.
+ if (ptr[0] == '.')
+ patch = internal_simple_strtoll(ptr+1, &ptr, 10);
+ if (major < 3) {
+ if (major == 2 && minor == 6 && patch == 32 && ptr[0] == '-' &&
+ internal_strstr(ptr, ".el6")) {
+ // Check RHEL6
+ int r1 = internal_simple_strtoll(ptr+1, &ptr, 10);
+ if (r1 >= 657) // 2.6.32-657.el6 or later
+ return true;
+ if (r1 == 642 && ptr[0] == '.') {
+ int r2 = internal_simple_strtoll(ptr+1, &ptr, 10);
+ if (r2 >= 9) // 2.6.32-642.9.1.el6 or later
+ return true;
+ }
+ }
+ // <3.0 is bad.
+ return false;
+ } else if (major == 3) {
+ // 3.2.79+ is OK.
+ if (minor == 2 && patch >= 79)
+ return true;
+ // 3.12.58+ is OK.
+ if (minor == 12 && patch >= 58)
+ return true;
+ if (minor == 10 && patch == 0 && ptr[0] == '-' &&
+ internal_strstr(ptr, ".el7")) {
+ // Check RHEL7
+ int r1 = internal_simple_strtoll(ptr+1, &ptr, 10);
+ if (r1 >= 426) // 3.10.0-426.el7 or later
+ return true;
+ if (r1 == 327 && ptr[0] == '.') {
+ int r2 = internal_simple_strtoll(ptr+1, &ptr, 10);
+ if (r2 >= 27) // 3.10.0-327.27.1.el7 or later
+ return true;
+ }
+ }
+ // Otherwise, bad.
+ return false;
+ } else if (major == 4) {
+ // 4.1.21+ is OK.
+ if (minor == 1 && patch >= 21)
+ return true;
+ // 4.4.6+ is OK.
+ if (minor == 4 && patch >= 6)
+ return true;
+ if (minor == 4 && patch == 0 && ptr[0] == '-' &&
+ internal_strstr(buf.version, "Ubuntu")) {
+ // Check Ubuntu 16.04
+ int r1 = internal_simple_strtoll(ptr+1, &ptr, 10);
+ if (r1 >= 13) // 4.4.0-13 or later
+ return true;
+ }
+ // Otherwise, OK if 4.5+.
+ return minor >= 5;
+ } else {
+ // Linux 5 and up are fine.
+ return true;
+ }
+}
+
+void AvoidCVE_2016_2143() {
+ // Older kernels are affected by CVE-2016-2143 - they will crash hard
+ // if someone uses 4-level page tables (ie. virtual addresses >= 4TB)
+ // and fork() in the same process. Unfortunately, sanitizers tend to
+ // require such addresses. Since this is very likely to crash the whole
+ // machine (sanitizers themselves use fork() for llvm-symbolizer, for one),
+ // abort the process at initialization instead.
+ if (FixedCVE_2016_2143())
+ return;
+ if (GetEnv("SANITIZER_IGNORE_CVE_2016_2143"))
+ return;
+ Report(
+ "ERROR: Your kernel seems to be vulnerable to CVE-2016-2143. Using ASan,\n"
+ "MSan, TSan, DFSan or LSan with such kernel can and will crash your\n"
+ "machine, or worse.\n"
+ "\n"
+ "If you are certain your kernel is not vulnerable (you have compiled it\n"
+ "yourself, or are using an unrecognized distribution kernel), you can\n"
+ "override this safety check by exporting SANITIZER_IGNORE_CVE_2016_2143\n"
+ "with any value.\n");
+ Die();
+}
+#endif
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_LINUX && SANITIZER_S390
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_list.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_list.h
new file mode 100644
index 00000000000..f0b925945e6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_list.h
@@ -0,0 +1,166 @@
+//===-- sanitizer_list.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains implementation of a list class to be used by
+// ThreadSanitizer, etc run-times.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_LIST_H
+#define SANITIZER_LIST_H
+
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+// Intrusive singly-linked list with size(), push_back(), push_front()
+// pop_front(), append_front() and append_back().
+// This class should be a POD (so that it can be put into TLS)
+// and an object with all zero fields should represent a valid empty list.
+// This class does not have a CTOR, so clear() should be called on all
+// non-zero-initialized objects before using.
+template<class Item>
+struct IntrusiveList {
+ friend class Iterator;
+
+ void clear() {
+ first_ = last_ = nullptr;
+ size_ = 0;
+ }
+
+ bool empty() const { return size_ == 0; }
+ uptr size() const { return size_; }
+
+ void push_back(Item *x) {
+ if (empty()) {
+ x->next = nullptr;
+ first_ = last_ = x;
+ size_ = 1;
+ } else {
+ x->next = nullptr;
+ last_->next = x;
+ last_ = x;
+ size_++;
+ }
+ }
+
+ void push_front(Item *x) {
+ if (empty()) {
+ x->next = nullptr;
+ first_ = last_ = x;
+ size_ = 1;
+ } else {
+ x->next = first_;
+ first_ = x;
+ size_++;
+ }
+ }
+
+ void pop_front() {
+ CHECK(!empty());
+ first_ = first_->next;
+ if (!first_)
+ last_ = nullptr;
+ size_--;
+ }
+
+ void extract(Item *prev, Item *x) {
+ CHECK(!empty());
+ CHECK_NE(prev, nullptr);
+ CHECK_NE(x, nullptr);
+ CHECK_EQ(prev->next, x);
+ prev->next = x->next;
+ if (last_ == x)
+ last_ = prev;
+ size_--;
+ }
+
+ Item *front() { return first_; }
+ const Item *front() const { return first_; }
+ Item *back() { return last_; }
+ const Item *back() const { return last_; }
+
+ void append_front(IntrusiveList<Item> *l) {
+ CHECK_NE(this, l);
+ if (l->empty())
+ return;
+ if (empty()) {
+ *this = *l;
+ } else if (!l->empty()) {
+ l->last_->next = first_;
+ first_ = l->first_;
+ size_ += l->size();
+ }
+ l->clear();
+ }
+
+ void append_back(IntrusiveList<Item> *l) {
+ CHECK_NE(this, l);
+ if (l->empty())
+ return;
+ if (empty()) {
+ *this = *l;
+ } else {
+ last_->next = l->first_;
+ last_ = l->last_;
+ size_ += l->size();
+ }
+ l->clear();
+ }
+
+ void CheckConsistency() {
+ if (size_ == 0) {
+ CHECK_EQ(first_, 0);
+ CHECK_EQ(last_, 0);
+ } else {
+ uptr count = 0;
+ for (Item *i = first_; ; i = i->next) {
+ count++;
+ if (i == last_) break;
+ }
+ CHECK_EQ(size(), count);
+ CHECK_EQ(last_->next, 0);
+ }
+ }
+
+ template<class ItemTy>
+ class IteratorBase {
+ public:
+ explicit IteratorBase(ItemTy *current) : current_(current) {}
+ IteratorBase &operator++() {
+ current_ = current_->next;
+ return *this;
+ }
+ bool operator!=(IteratorBase other) const {
+ return current_ != other.current_;
+ }
+ ItemTy &operator*() {
+ return *current_;
+ }
+ private:
+ ItemTy *current_;
+ };
+
+ typedef IteratorBase<Item> Iterator;
+ typedef IteratorBase<const Item> ConstIterator;
+
+ Iterator begin() { return Iterator(first_); }
+ Iterator end() { return Iterator(0); }
+
+ ConstIterator begin() const { return ConstIterator(first_); }
+ ConstIterator end() const { return ConstIterator(0); }
+
+// private, don't use directly.
+ uptr size_;
+ Item *first_;
+ Item *last_;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_LIST_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_local_address_space_view.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_local_address_space_view.h
new file mode 100644
index 00000000000..a47cfc945cd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_local_address_space_view.h
@@ -0,0 +1,76 @@
+//===-- sanitizer_local_address_space_view.h --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// `LocalAddressSpaceView` provides the local (i.e. target and current address
+// space are the same) implementation of the `AddressSpaceView` interface which
+// provides a simple interface to load memory from another process (i.e.
+// out-of-process)
+//
+// The `AddressSpaceView` interface requires that the type can be used as a
+// template parameter to objects that wish to be able to operate in an
+// out-of-process manner. In normal usage, objects are in-process and are thus
+// instantiated with the `LocalAddressSpaceView` type. This type is used to
+// load any pointers in instance methods. This implementation is effectively
+// a no-op. When an object is to be used in an out-of-process manner it is
+// instantiated with the `RemoteAddressSpaceView` type.
+//
+// By making `AddressSpaceView` a template parameter of an object, it can
+// change its implementation at compile time which has no run time overhead.
+// This also allows unifying in-process and out-of-process code which avoids
+// code duplication.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_LOCAL_ADDRES_SPACE_VIEW_H
+#define SANITIZER_LOCAL_ADDRES_SPACE_VIEW_H
+
+namespace __sanitizer {
+struct LocalAddressSpaceView {
+ // Load memory `sizeof(T) * num_elements` bytes of memory from the target
+ // process (always local for this implementation) starting at address
+ // `target_address`. The local copy of this memory is returned as a pointer.
+ // The caller should not write to this memory. The behaviour when doing so is
+ // undefined. Callers should use `LoadWritable()` to get access to memory
+ // that is writable.
+ //
+ // The lifetime of loaded memory is implementation defined.
+ template <typename T>
+ static const T *Load(const T *target_address, uptr num_elements = 1) {
+ // The target address space is the local address space so
+ // nothing needs to be copied. Just return the pointer.
+ return target_address;
+ }
+
+ // Load memory `sizeof(T) * num_elements` bytes of memory from the target
+ // process (always local for this implementation) starting at address
+ // `target_address`. The local copy of this memory is returned as a pointer.
+ // The memory returned may be written to.
+ //
+ // Writes made to the returned memory will be visible in the memory returned
+ // by subsequent `Load()` or `LoadWritable()` calls provided the
+ // `target_address` parameter is the same. It is not guaranteed that the
+ // memory returned by previous calls to `Load()` will contain any performed
+ // writes. If two or more overlapping regions of memory are loaded via
+ // separate calls to `LoadWritable()`, it is implementation defined whether
+ // writes made to the region returned by one call are visible in the regions
+ // returned by other calls.
+ //
+ // Given the above it is recommended to load the largest possible object
+ // that requires modification (e.g. a class) rather than individual fields
+ // from a class to avoid issues with overlapping writable regions.
+ //
+ // The lifetime of loaded memory is implementation defined.
+ template <typename T>
+ static T *LoadWritable(T *target_address, uptr num_elements = 1) {
+ // The target address space is the local address space so
+ // nothing needs to be copied. Just return the pointer.
+ return target_address;
+ }
+};
+} // namespace __sanitizer
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_lzw.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_lzw.h
new file mode 100644
index 00000000000..42acfbdcea0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_lzw.h
@@ -0,0 +1,159 @@
+//===-- sanitizer_lzw.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Lempel–Ziv–Welch encoding/decoding
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_LZW_H
+#define SANITIZER_LZW_H
+
+#include "sanitizer_dense_map.h"
+
+namespace __sanitizer {
+
+using LzwCodeType = u32;
+
+template <class T, class ItIn, class ItOut>
+ItOut LzwEncode(ItIn begin, ItIn end, ItOut out) {
+ using Substring =
+ detail::DenseMapPair<LzwCodeType /* Prefix */, T /* Next input */>;
+
+ // Sentinel value for substrings of len 1.
+ static constexpr LzwCodeType kNoPrefix =
+ Min(DenseMapInfo<Substring>::getEmptyKey().first,
+ DenseMapInfo<Substring>::getTombstoneKey().first) -
+ 1;
+ DenseMap<Substring, LzwCodeType> prefix_to_code;
+ {
+ // Add all substring of len 1 as initial dictionary.
+ InternalMmapVector<T> dict_len1;
+ for (auto it = begin; it != end; ++it)
+ if (prefix_to_code.try_emplace({kNoPrefix, *it}, 0).second)
+ dict_len1.push_back(*it);
+
+ // Slightly helps with later delta encoding.
+ Sort(dict_len1.data(), dict_len1.size());
+
+ // For large sizeof(T) we have to store dict_len1. Smaller types like u8 can
+ // just generate them.
+ *out = dict_len1.size();
+ ++out;
+
+ for (uptr i = 0; i != dict_len1.size(); ++i) {
+ // Remap after the Sort.
+ prefix_to_code[{kNoPrefix, dict_len1[i]}] = i;
+ *out = dict_len1[i];
+ ++out;
+ }
+ CHECK_EQ(prefix_to_code.size(), dict_len1.size());
+ }
+
+ if (begin == end)
+ return out;
+
+ // Main LZW encoding loop.
+ LzwCodeType match = prefix_to_code.find({kNoPrefix, *begin})->second;
+ ++begin;
+ for (auto it = begin; it != end; ++it) {
+ // Extend match with the new item.
+ auto ins = prefix_to_code.try_emplace({match, *it}, prefix_to_code.size());
+ if (ins.second) {
+ // This is a new substring, but emit the code for the current match
+ // (before extend). This allows LZW decoder to recover the dictionary.
+ *out = match;
+ ++out;
+ // Reset the match to a single item, which must be already in the map.
+ match = prefix_to_code.find({kNoPrefix, *it})->second;
+ } else {
+ // Already known, use as the current match.
+ match = ins.first->second;
+ }
+ }
+
+ *out = match;
+ ++out;
+
+ return out;
+}
+
+template <class T, class ItIn, class ItOut>
+ItOut LzwDecode(ItIn begin, ItIn end, ItOut out) {
+ if (begin == end)
+ return out;
+
+ // Load dictionary of len 1 substrings. Theses correspont to lowest codes.
+ InternalMmapVector<T> dict_len1(*begin);
+ ++begin;
+
+ if (begin == end)
+ return out;
+
+ for (auto& v : dict_len1) {
+ v = *begin;
+ ++begin;
+ }
+
+ // Substrings of len 2 and up. Indexes are shifted because [0,
+ // dict_len1.size()) stored in dict_len1. Substings get here after being
+ // emitted to the output, so we can use output position.
+ InternalMmapVector<detail::DenseMapPair<ItOut /* begin. */, ItOut /* end */>>
+ code_to_substr;
+
+ // Copies already emitted substrings into the output again.
+ auto copy = [&code_to_substr, &dict_len1](LzwCodeType code, ItOut out) {
+ if (code < dict_len1.size()) {
+ *out = dict_len1[code];
+ ++out;
+ return out;
+ }
+ const auto& s = code_to_substr[code - dict_len1.size()];
+
+ for (ItOut it = s.first; it != s.second; ++it, ++out) *out = *it;
+ return out;
+ };
+
+ // Returns lens of the substring with the given code.
+ auto code_to_len = [&code_to_substr, &dict_len1](LzwCodeType code) -> uptr {
+ if (code < dict_len1.size())
+ return 1;
+ const auto& s = code_to_substr[code - dict_len1.size()];
+ return s.second - s.first;
+ };
+
+ // Main LZW decoding loop.
+ LzwCodeType prev_code = *begin;
+ ++begin;
+ out = copy(prev_code, out);
+ for (auto it = begin; it != end; ++it) {
+ LzwCodeType code = *it;
+ auto start = out;
+ if (code == dict_len1.size() + code_to_substr.size()) {
+ // Special LZW case. The code is not in the dictionary yet. This is
+ // possible only when the new substring is the same as previous one plus
+ // the first item of the previous substring. We can emit that in two
+ // steps.
+ out = copy(prev_code, out);
+ *out = *start;
+ ++out;
+ } else {
+ out = copy(code, out);
+ }
+
+ // Every time encoded emits the code, it also creates substing of len + 1
+ // including the first item of the just emmited substring. Do the same here.
+ uptr len = code_to_len(prev_code);
+ code_to_substr.push_back({start - len, start + 1});
+
+ prev_code = code;
+ }
+ return out;
+}
+
+} // namespace __sanitizer
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mac.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mac.cpp
new file mode 100644
index 00000000000..23c4c6619de
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mac.cpp
@@ -0,0 +1,1457 @@
+//===-- sanitizer_mac.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between various sanitizers' runtime libraries and
+// implements OSX-specific functions.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_APPLE
+#include "sanitizer_mac.h"
+#include "interception/interception.h"
+
+// Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
+// the clients will most certainly use 64-bit ones as well.
+#ifndef _DARWIN_USE_64_BIT_INODE
+#define _DARWIN_USE_64_BIT_INODE 1
+#endif
+#include <stdio.h>
+
+#include "sanitizer_common.h"
+#include "sanitizer_file.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_interface_internal.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_platform_limits_posix.h"
+#include "sanitizer_procmaps.h"
+#include "sanitizer_ptrauth.h"
+
+#if !SANITIZER_IOS
+#include <crt_externs.h> // for _NSGetEnviron
+#else
+extern char **environ;
+#endif
+
+#if defined(__has_include) && __has_include(<os/trace.h>)
+#define SANITIZER_OS_TRACE 1
+#include <os/trace.h>
+#else
+#define SANITIZER_OS_TRACE 0
+#endif
+
+// import new crash reporting api
+#if defined(__has_include) && __has_include(<CrashReporterClient.h>)
+#define HAVE_CRASHREPORTERCLIENT_H 1
+#include <CrashReporterClient.h>
+#else
+#define HAVE_CRASHREPORTERCLIENT_H 0
+#endif
+
+#if !SANITIZER_IOS
+#include <crt_externs.h> // for _NSGetArgv and _NSGetEnviron
+#else
+extern "C" {
+ extern char ***_NSGetArgv(void);
+}
+#endif
+
+#include <asl.h>
+#include <dlfcn.h> // for dladdr()
+#include <errno.h>
+#include <fcntl.h>
+#include <libkern/OSAtomic.h>
+#include <mach-o/dyld.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#include <mach/vm_statistics.h>
+#include <malloc/malloc.h>
+#include <os/log.h>
+#include <pthread.h>
+#include <pthread/introspection.h>
+#include <sched.h>
+#include <signal.h>
+#include <spawn.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <util.h>
+
+// From <crt_externs.h>, but we don't have that file on iOS.
+extern "C" {
+ extern char ***_NSGetArgv(void);
+ extern char ***_NSGetEnviron(void);
+}
+
+// From <mach/mach_vm.h>, but we don't have that file on iOS.
+extern "C" {
+ extern kern_return_t mach_vm_region_recurse(
+ vm_map_t target_task,
+ mach_vm_address_t *address,
+ mach_vm_size_t *size,
+ natural_t *nesting_depth,
+ vm_region_recurse_info_t info,
+ mach_msg_type_number_t *infoCnt);
+}
+
+namespace __sanitizer {
+
+#include "sanitizer_syscall_generic.inc"
+
+// Direct syscalls, don't call libmalloc hooks (but not available on 10.6).
+extern "C" void *__mmap(void *addr, size_t len, int prot, int flags, int fildes,
+ off_t off) SANITIZER_WEAK_ATTRIBUTE;
+extern "C" int __munmap(void *, size_t) SANITIZER_WEAK_ATTRIBUTE;
+
+// ---------------------- sanitizer_libc.h
+
+// From <mach/vm_statistics.h>, but not on older OSs.
+#ifndef VM_MEMORY_SANITIZER
+#define VM_MEMORY_SANITIZER 99
+#endif
+
+// XNU on Darwin provides a mmap flag that optimizes allocation/deallocation of
+// giant memory regions (i.e. shadow memory regions).
+#define kXnuFastMmapFd 0x4
+static size_t kXnuFastMmapThreshold = 2 << 30; // 2 GB
+static bool use_xnu_fast_mmap = false;
+
+uptr internal_mmap(void *addr, size_t length, int prot, int flags,
+ int fd, u64 offset) {
+ if (fd == -1) {
+ fd = VM_MAKE_TAG(VM_MEMORY_SANITIZER);
+ if (length >= kXnuFastMmapThreshold) {
+ if (use_xnu_fast_mmap) fd |= kXnuFastMmapFd;
+ }
+ }
+ if (&__mmap) return (uptr)__mmap(addr, length, prot, flags, fd, offset);
+ return (uptr)mmap(addr, length, prot, flags, fd, offset);
+}
+
+uptr internal_munmap(void *addr, uptr length) {
+ if (&__munmap) return __munmap(addr, length);
+ return munmap(addr, length);
+}
+
+uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags,
+ void *new_address) {
+ CHECK(false && "internal_mremap is unimplemented on Mac");
+ return 0;
+}
+
+int internal_mprotect(void *addr, uptr length, int prot) {
+ return mprotect(addr, length, prot);
+}
+
+int internal_madvise(uptr addr, uptr length, int advice) {
+ return madvise((void *)addr, length, advice);
+}
+
+uptr internal_close(fd_t fd) {
+ return close(fd);
+}
+
+uptr internal_open(const char *filename, int flags) {
+ return open(filename, flags);
+}
+
+uptr internal_open(const char *filename, int flags, u32 mode) {
+ return open(filename, flags, mode);
+}
+
+uptr internal_read(fd_t fd, void *buf, uptr count) {
+ return read(fd, buf, count);
+}
+
+uptr internal_write(fd_t fd, const void *buf, uptr count) {
+ return write(fd, buf, count);
+}
+
+uptr internal_stat(const char *path, void *buf) {
+ return stat(path, (struct stat *)buf);
+}
+
+uptr internal_lstat(const char *path, void *buf) {
+ return lstat(path, (struct stat *)buf);
+}
+
+uptr internal_fstat(fd_t fd, void *buf) {
+ return fstat(fd, (struct stat *)buf);
+}
+
+uptr internal_filesize(fd_t fd) {
+ struct stat st;
+ if (internal_fstat(fd, &st))
+ return -1;
+ return (uptr)st.st_size;
+}
+
+uptr internal_dup(int oldfd) {
+ return dup(oldfd);
+}
+
+uptr internal_dup2(int oldfd, int newfd) {
+ return dup2(oldfd, newfd);
+}
+
+uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
+ return readlink(path, buf, bufsize);
+}
+
+uptr internal_unlink(const char *path) {
+ return unlink(path);
+}
+
+uptr internal_sched_yield() {
+ return sched_yield();
+}
+
+void internal__exit(int exitcode) {
+ _exit(exitcode);
+}
+
+void internal_usleep(u64 useconds) { usleep(useconds); }
+
+uptr internal_getpid() {
+ return getpid();
+}
+
+int internal_dlinfo(void *handle, int request, void *p) {
+ UNIMPLEMENTED();
+}
+
+int internal_sigaction(int signum, const void *act, void *oldact) {
+ return sigaction(signum,
+ (const struct sigaction *)act, (struct sigaction *)oldact);
+}
+
+void internal_sigfillset(__sanitizer_sigset_t *set) { sigfillset(set); }
+
+uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
+ __sanitizer_sigset_t *oldset) {
+ // Don't use sigprocmask here, because it affects all threads.
+ return pthread_sigmask(how, set, oldset);
+}
+
+// Doesn't call pthread_atfork() handlers (but not available on 10.6).
+extern "C" pid_t __fork(void) SANITIZER_WEAK_ATTRIBUTE;
+
+int internal_fork() {
+ if (&__fork)
+ return __fork();
+ return fork();
+}
+
+int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
+ uptr *oldlenp, const void *newp, uptr newlen) {
+ return sysctl(const_cast<int *>(name), namelen, oldp, (size_t *)oldlenp,
+ const_cast<void *>(newp), (size_t)newlen);
+}
+
+int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
+ const void *newp, uptr newlen) {
+ return sysctlbyname(sname, oldp, (size_t *)oldlenp, const_cast<void *>(newp),
+ (size_t)newlen);
+}
+
+static fd_t internal_spawn_impl(const char *argv[], const char *envp[],
+ pid_t *pid) {
+ fd_t primary_fd = kInvalidFd;
+ fd_t secondary_fd = kInvalidFd;
+
+ auto fd_closer = at_scope_exit([&] {
+ internal_close(primary_fd);
+ internal_close(secondary_fd);
+ });
+
+ // We need a new pseudoterminal to avoid buffering problems. The 'atos' tool
+ // in particular detects when it's talking to a pipe and forgets to flush the
+ // output stream after sending a response.
+ primary_fd = posix_openpt(O_RDWR);
+ if (primary_fd == kInvalidFd)
+ return kInvalidFd;
+
+ int res = grantpt(primary_fd) || unlockpt(primary_fd);
+ if (res != 0) return kInvalidFd;
+
+ // Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
+ char secondary_pty_name[128];
+ res = ioctl(primary_fd, TIOCPTYGNAME, secondary_pty_name);
+ if (res == -1) return kInvalidFd;
+
+ secondary_fd = internal_open(secondary_pty_name, O_RDWR);
+ if (secondary_fd == kInvalidFd)
+ return kInvalidFd;
+
+ // File descriptor actions
+ posix_spawn_file_actions_t acts;
+ res = posix_spawn_file_actions_init(&acts);
+ if (res != 0) return kInvalidFd;
+
+ auto acts_cleanup = at_scope_exit([&] {
+ posix_spawn_file_actions_destroy(&acts);
+ });
+
+ res = posix_spawn_file_actions_adddup2(&acts, secondary_fd, STDIN_FILENO) ||
+ posix_spawn_file_actions_adddup2(&acts, secondary_fd, STDOUT_FILENO) ||
+ posix_spawn_file_actions_addclose(&acts, secondary_fd);
+ if (res != 0) return kInvalidFd;
+
+ // Spawn attributes
+ posix_spawnattr_t attrs;
+ res = posix_spawnattr_init(&attrs);
+ if (res != 0) return kInvalidFd;
+
+ auto attrs_cleanup = at_scope_exit([&] {
+ posix_spawnattr_destroy(&attrs);
+ });
+
+ // In the spawned process, close all file descriptors that are not explicitly
+ // described by the file actions object. This is Darwin-specific extension.
+ res = posix_spawnattr_setflags(&attrs, POSIX_SPAWN_CLOEXEC_DEFAULT);
+ if (res != 0) return kInvalidFd;
+
+ // posix_spawn
+ char **argv_casted = const_cast<char **>(argv);
+ char **envp_casted = const_cast<char **>(envp);
+ res = posix_spawn(pid, argv[0], &acts, &attrs, argv_casted, envp_casted);
+ if (res != 0) return kInvalidFd;
+
+ // Disable echo in the new terminal, disable CR.
+ struct termios termflags;
+ tcgetattr(primary_fd, &termflags);
+ termflags.c_oflag &= ~ONLCR;
+ termflags.c_lflag &= ~ECHO;
+ tcsetattr(primary_fd, TCSANOW, &termflags);
+
+ // On success, do not close primary_fd on scope exit.
+ fd_t fd = primary_fd;
+ primary_fd = kInvalidFd;
+
+ return fd;
+}
+
+fd_t internal_spawn(const char *argv[], const char *envp[], pid_t *pid) {
+ // The client program may close its stdin and/or stdout and/or stderr thus
+ // allowing open/posix_openpt to reuse file descriptors 0, 1 or 2. In this
+ // case the communication is broken if either the parent or the child tries to
+ // close or duplicate these descriptors. We temporarily reserve these
+ // descriptors here to prevent this.
+ fd_t low_fds[3];
+ size_t count = 0;
+
+ for (; count < 3; count++) {
+ low_fds[count] = posix_openpt(O_RDWR);
+ if (low_fds[count] >= STDERR_FILENO)
+ break;
+ }
+
+ fd_t fd = internal_spawn_impl(argv, envp, pid);
+
+ for (; count > 0; count--) {
+ internal_close(low_fds[count]);
+ }
+
+ return fd;
+}
+
+uptr internal_rename(const char *oldpath, const char *newpath) {
+ return rename(oldpath, newpath);
+}
+
+uptr internal_ftruncate(fd_t fd, uptr size) {
+ return ftruncate(fd, size);
+}
+
+uptr internal_execve(const char *filename, char *const argv[],
+ char *const envp[]) {
+ return execve(filename, argv, envp);
+}
+
+uptr internal_waitpid(int pid, int *status, int options) {
+ return waitpid(pid, status, options);
+}
+
+// ----------------- sanitizer_common.h
+bool FileExists(const char *filename) {
+ if (ShouldMockFailureToOpen(filename))
+ return false;
+ struct stat st;
+ if (stat(filename, &st))
+ return false;
+ // Sanity check: filename is a regular file.
+ return S_ISREG(st.st_mode);
+}
+
+bool DirExists(const char *path) {
+ struct stat st;
+ if (stat(path, &st))
+ return false;
+ return S_ISDIR(st.st_mode);
+}
+
+tid_t GetTid() {
+ tid_t tid;
+ pthread_threadid_np(nullptr, &tid);
+ return tid;
+}
+
+void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
+ uptr *stack_bottom) {
+ CHECK(stack_top);
+ CHECK(stack_bottom);
+ uptr stacksize = pthread_get_stacksize_np(pthread_self());
+ // pthread_get_stacksize_np() returns an incorrect stack size for the main
+ // thread on Mavericks. See
+ // https://github.com/google/sanitizers/issues/261
+ if ((GetMacosAlignedVersion() >= MacosVersion(10, 9)) && at_initialization &&
+ stacksize == (1 << 19)) {
+ struct rlimit rl;
+ CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
+ // Most often rl.rlim_cur will be the desired 8M.
+ if (rl.rlim_cur < kMaxThreadStackSize) {
+ stacksize = rl.rlim_cur;
+ } else {
+ stacksize = kMaxThreadStackSize;
+ }
+ }
+ void *stackaddr = pthread_get_stackaddr_np(pthread_self());
+ *stack_top = (uptr)stackaddr;
+ *stack_bottom = *stack_top - stacksize;
+}
+
+char **GetEnviron() {
+#if !SANITIZER_IOS
+ char ***env_ptr = _NSGetEnviron();
+ if (!env_ptr) {
+ Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is "
+ "called after libSystem_initializer().\n");
+ CHECK(env_ptr);
+ }
+ char **environ = *env_ptr;
+#endif
+ CHECK(environ);
+ return environ;
+}
+
+const char *GetEnv(const char *name) {
+ char **env = GetEnviron();
+ uptr name_len = internal_strlen(name);
+ while (*env != 0) {
+ uptr len = internal_strlen(*env);
+ if (len > name_len) {
+ const char *p = *env;
+ if (!internal_memcmp(p, name, name_len) &&
+ p[name_len] == '=') { // Match.
+ return *env + name_len + 1; // String starting after =.
+ }
+ }
+ env++;
+ }
+ return 0;
+}
+
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
+ CHECK_LE(kMaxPathLength, buf_len);
+
+ // On OS X the executable path is saved to the stack by dyld. Reading it
+ // from there is much faster than calling dladdr, especially for large
+ // binaries with symbols.
+ InternalMmapVector<char> exe_path(kMaxPathLength);
+ uint32_t size = exe_path.size();
+ if (_NSGetExecutablePath(exe_path.data(), &size) == 0 &&
+ realpath(exe_path.data(), buf) != 0) {
+ return internal_strlen(buf);
+ }
+ return 0;
+}
+
+uptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) {
+ return ReadBinaryName(buf, buf_len);
+}
+
+void ReExec() {
+ UNIMPLEMENTED();
+}
+
+void CheckASLR() {
+ // Do nothing
+}
+
+void CheckMPROTECT() {
+ // Do nothing
+}
+
+uptr GetPageSize() {
+ return sysconf(_SC_PAGESIZE);
+}
+
+extern "C" unsigned malloc_num_zones;
+extern "C" malloc_zone_t **malloc_zones;
+malloc_zone_t sanitizer_zone;
+
+// We need to make sure that sanitizer_zone is registered as malloc_zones[0]. If
+// libmalloc tries to set up a different zone as malloc_zones[0], it will call
+// mprotect(malloc_zones, ..., PROT_READ). This interceptor will catch that and
+// make sure we are still the first (default) zone.
+void MprotectMallocZones(void *addr, int prot) {
+ if (addr == malloc_zones && prot == PROT_READ) {
+ if (malloc_num_zones > 1 && malloc_zones[0] != &sanitizer_zone) {
+ for (unsigned i = 1; i < malloc_num_zones; i++) {
+ if (malloc_zones[i] == &sanitizer_zone) {
+ // Swap malloc_zones[0] and malloc_zones[i].
+ malloc_zones[i] = malloc_zones[0];
+ malloc_zones[0] = &sanitizer_zone;
+ break;
+ }
+ }
+ }
+ }
+}
+
+void FutexWait(atomic_uint32_t *p, u32 cmp) {
+ // FIXME: implement actual blocking.
+ sched_yield();
+}
+
+void FutexWake(atomic_uint32_t *p, u32 count) {}
+
+u64 NanoTime() {
+ timeval tv;
+ internal_memset(&tv, 0, sizeof(tv));
+ gettimeofday(&tv, 0);
+ return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
+}
+
+// This needs to be called during initialization to avoid being racy.
+u64 MonotonicNanoTime() {
+ static mach_timebase_info_data_t timebase_info;
+ if (timebase_info.denom == 0) mach_timebase_info(&timebase_info);
+ return (mach_absolute_time() * timebase_info.numer) / timebase_info.denom;
+}
+
+uptr GetTlsSize() {
+ return 0;
+}
+
+void InitTlsSize() {
+}
+
+uptr TlsBaseAddr() {
+ uptr segbase = 0;
+#if defined(__x86_64__)
+ asm("movq %%gs:0,%0" : "=r"(segbase));
+#elif defined(__i386__)
+ asm("movl %%gs:0,%0" : "=r"(segbase));
+#elif defined(__aarch64__)
+ asm("mrs %x0, tpidrro_el0" : "=r"(segbase));
+ segbase &= 0x07ul; // clearing lower bits, cpu id stored there
+#endif
+ return segbase;
+}
+
+// The size of the tls on darwin does not appear to be well documented,
+// however the vm memory map suggests that it is 1024 uptrs in size,
+// with a size of 0x2000 bytes on x86_64 and 0x1000 bytes on i386.
+uptr TlsSize() {
+#if defined(__x86_64__) || defined(__i386__)
+ return 1024 * sizeof(uptr);
+#else
+ return 0;
+#endif
+}
+
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+ uptr *tls_addr, uptr *tls_size) {
+#if !SANITIZER_GO
+ uptr stack_top, stack_bottom;
+ GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
+ *stk_addr = stack_bottom;
+ *stk_size = stack_top - stack_bottom;
+ *tls_addr = TlsBaseAddr();
+ *tls_size = TlsSize();
+#else
+ *stk_addr = 0;
+ *stk_size = 0;
+ *tls_addr = 0;
+ *tls_size = 0;
+#endif
+}
+
+void ListOfModules::init() {
+ clearOrInit();
+ MemoryMappingLayout memory_mapping(false);
+ memory_mapping.DumpListOfModules(&modules_);
+}
+
+void ListOfModules::fallbackInit() { clear(); }
+
+static HandleSignalMode GetHandleSignalModeImpl(int signum) {
+ switch (signum) {
+ case SIGABRT:
+ return common_flags()->handle_abort;
+ case SIGILL:
+ return common_flags()->handle_sigill;
+ case SIGTRAP:
+ return common_flags()->handle_sigtrap;
+ case SIGFPE:
+ return common_flags()->handle_sigfpe;
+ case SIGSEGV:
+ return common_flags()->handle_segv;
+ case SIGBUS:
+ return common_flags()->handle_sigbus;
+ }
+ return kHandleSignalNo;
+}
+
+HandleSignalMode GetHandleSignalMode(int signum) {
+ // Handling fatal signals on watchOS and tvOS devices is disallowed.
+ if ((SANITIZER_WATCHOS || SANITIZER_TVOS) && !(SANITIZER_IOSSIM))
+ return kHandleSignalNo;
+ HandleSignalMode result = GetHandleSignalModeImpl(signum);
+ if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler)
+ return kHandleSignalExclusive;
+ return result;
+}
+
+// Offset example:
+// XNU 17 -- macOS 10.13 -- iOS 11 -- tvOS 11 -- watchOS 4
+constexpr u16 GetOSMajorKernelOffset() {
+ if (TARGET_OS_OSX) return 4;
+ if (TARGET_OS_IOS || TARGET_OS_TV) return 6;
+ if (TARGET_OS_WATCH) return 13;
+}
+
+using VersStr = char[64];
+
+static uptr ApproximateOSVersionViaKernelVersion(VersStr vers) {
+ u16 kernel_major = GetDarwinKernelVersion().major;
+ u16 offset = GetOSMajorKernelOffset();
+ CHECK_GE(kernel_major, offset);
+ u16 os_major = kernel_major - offset;
+
+ const char *format = "%d.0";
+ if (TARGET_OS_OSX) {
+ if (os_major >= 16) { // macOS 11+
+ os_major -= 5;
+ } else { // macOS 10.15 and below
+ format = "10.%d";
+ }
+ }
+ return internal_snprintf(vers, sizeof(VersStr), format, os_major);
+}
+
+static void GetOSVersion(VersStr vers) {
+ uptr len = sizeof(VersStr);
+ if (SANITIZER_IOSSIM) {
+ const char *vers_env = GetEnv("SIMULATOR_RUNTIME_VERSION");
+ if (!vers_env) {
+ Report("ERROR: Running in simulator but SIMULATOR_RUNTIME_VERSION env "
+ "var is not set.\n");
+ Die();
+ }
+ len = internal_strlcpy(vers, vers_env, len);
+ } else {
+ int res =
+ internal_sysctlbyname("kern.osproductversion", vers, &len, nullptr, 0);
+
+ // XNU 17 (macOS 10.13) and below do not provide the sysctl
+ // `kern.osproductversion` entry (res != 0).
+ bool no_os_version = res != 0;
+
+ // For launchd, sanitizer initialization runs before sysctl is setup
+ // (res == 0 && len != strlen(vers), vers is not a valid version). However,
+ // the kernel version `kern.osrelease` is available.
+ bool launchd = (res == 0 && internal_strlen(vers) < 3);
+ if (launchd) CHECK_EQ(internal_getpid(), 1);
+
+ if (no_os_version || launchd) {
+ len = ApproximateOSVersionViaKernelVersion(vers);
+ }
+ }
+ CHECK_LT(len, sizeof(VersStr));
+}
+
+void ParseVersion(const char *vers, u16 *major, u16 *minor) {
+ // Format: <major>.<minor>[.<patch>]\0
+ CHECK_GE(internal_strlen(vers), 3);
+ const char *p = vers;
+ *major = internal_simple_strtoll(p, &p, /*base=*/10);
+ CHECK_EQ(*p, '.');
+ p += 1;
+ *minor = internal_simple_strtoll(p, &p, /*base=*/10);
+}
+
+// Aligned versions example:
+// macOS 10.15 -- iOS 13 -- tvOS 13 -- watchOS 6
+static void MapToMacos(u16 *major, u16 *minor) {
+ if (TARGET_OS_OSX)
+ return;
+
+ if (TARGET_OS_IOS || TARGET_OS_TV)
+ *major += 2;
+ else if (TARGET_OS_WATCH)
+ *major += 9;
+ else
+ UNREACHABLE("unsupported platform");
+
+ if (*major >= 16) { // macOS 11+
+ *major -= 5;
+ } else { // macOS 10.15 and below
+ *minor = *major;
+ *major = 10;
+ }
+}
+
+static MacosVersion GetMacosAlignedVersionInternal() {
+ VersStr vers = {};
+ GetOSVersion(vers);
+
+ u16 major, minor;
+ ParseVersion(vers, &major, &minor);
+ MapToMacos(&major, &minor);
+
+ return MacosVersion(major, minor);
+}
+
+static_assert(sizeof(MacosVersion) == sizeof(atomic_uint32_t::Type),
+ "MacosVersion cache size");
+static atomic_uint32_t cached_macos_version;
+
+MacosVersion GetMacosAlignedVersion() {
+ atomic_uint32_t::Type result =
+ atomic_load(&cached_macos_version, memory_order_acquire);
+ if (!result) {
+ MacosVersion version = GetMacosAlignedVersionInternal();
+ result = *reinterpret_cast<atomic_uint32_t::Type *>(&version);
+ atomic_store(&cached_macos_version, result, memory_order_release);
+ }
+ return *reinterpret_cast<MacosVersion *>(&result);
+}
+
+DarwinKernelVersion GetDarwinKernelVersion() {
+ VersStr vers = {};
+ uptr len = sizeof(VersStr);
+ int res = internal_sysctlbyname("kern.osrelease", vers, &len, nullptr, 0);
+ CHECK_EQ(res, 0);
+ CHECK_LT(len, sizeof(VersStr));
+
+ u16 major, minor;
+ ParseVersion(vers, &major, &minor);
+
+ return DarwinKernelVersion(major, minor);
+}
+
+uptr GetRSS() {
+ struct task_basic_info info;
+ unsigned count = TASK_BASIC_INFO_COUNT;
+ kern_return_t result =
+ task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &count);
+ if (UNLIKELY(result != KERN_SUCCESS)) {
+ Report("Cannot get task info. Error: %d\n", result);
+ Die();
+ }
+ return info.resident_size;
+}
+
+void *internal_start_thread(void *(*func)(void *arg), void *arg) {
+ // Start the thread with signals blocked, otherwise it can steal user signals.
+ __sanitizer_sigset_t set, old;
+ internal_sigfillset(&set);
+ internal_sigprocmask(SIG_SETMASK, &set, &old);
+ pthread_t th;
+ pthread_create(&th, 0, func, arg);
+ internal_sigprocmask(SIG_SETMASK, &old, 0);
+ return th;
+}
+
+void internal_join_thread(void *th) { pthread_join((pthread_t)th, 0); }
+
+#if !SANITIZER_GO
+static Mutex syslog_lock;
+# endif
+
+void WriteOneLineToSyslog(const char *s) {
+#if !SANITIZER_GO
+ syslog_lock.CheckLocked();
+ if (GetMacosAlignedVersion() >= MacosVersion(10, 12)) {
+ os_log_error(OS_LOG_DEFAULT, "%{public}s", s);
+ } else {
+ asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", s);
+ }
+#endif
+}
+
+// buffer to store crash report application information
+static char crashreporter_info_buff[__sanitizer::kErrorMessageBufferSize] = {};
+static Mutex crashreporter_info_mutex;
+
+extern "C" {
+// Integrate with crash reporter libraries.
+#if HAVE_CRASHREPORTERCLIENT_H
+CRASH_REPORTER_CLIENT_HIDDEN
+struct crashreporter_annotations_t gCRAnnotations
+ __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) = {
+ CRASHREPORTER_ANNOTATIONS_VERSION,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+#if CRASHREPORTER_ANNOTATIONS_VERSION > 4
+ 0,
+#endif
+};
+
+#else
+// fall back to old crashreporter api
+static const char *__crashreporter_info__ __attribute__((__used__)) =
+ &crashreporter_info_buff[0];
+asm(".desc ___crashreporter_info__, 0x10");
+#endif
+
+} // extern "C"
+
+static void CRAppendCrashLogMessage(const char *msg) {
+ Lock l(&crashreporter_info_mutex);
+ internal_strlcat(crashreporter_info_buff, msg,
+ sizeof(crashreporter_info_buff));
+#if HAVE_CRASHREPORTERCLIENT_H
+ (void)CRSetCrashLogMessage(crashreporter_info_buff);
+#endif
+}
+
+void LogMessageOnPrintf(const char *str) {
+ // Log all printf output to CrashLog.
+ if (common_flags()->abort_on_error)
+ CRAppendCrashLogMessage(str);
+}
+
+void LogFullErrorReport(const char *buffer) {
+#if !SANITIZER_GO
+ // Log with os_trace. This will make it into the crash log.
+#if SANITIZER_OS_TRACE
+ if (GetMacosAlignedVersion() >= MacosVersion(10, 10)) {
+ // os_trace requires the message (format parameter) to be a string literal.
+ if (internal_strncmp(SanitizerToolName, "AddressSanitizer",
+ sizeof("AddressSanitizer") - 1) == 0)
+ os_trace("Address Sanitizer reported a failure.");
+ else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer",
+ sizeof("UndefinedBehaviorSanitizer") - 1) == 0)
+ os_trace("Undefined Behavior Sanitizer reported a failure.");
+ else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer",
+ sizeof("ThreadSanitizer") - 1) == 0)
+ os_trace("Thread Sanitizer reported a failure.");
+ else
+ os_trace("Sanitizer tool reported a failure.");
+
+ if (common_flags()->log_to_syslog)
+ os_trace("Consult syslog for more information.");
+ }
+#endif
+
+ // Log to syslog.
+ // The logging on OS X may call pthread_create so we need the threading
+ // environment to be fully initialized. Also, this should never be called when
+ // holding the thread registry lock since that may result in a deadlock. If
+ // the reporting thread holds the thread registry mutex, and asl_log waits
+ // for GCD to dispatch a new thread, the process will deadlock, because the
+ // pthread_create wrapper needs to acquire the lock as well.
+ Lock l(&syslog_lock);
+ if (common_flags()->log_to_syslog)
+ WriteToSyslog(buffer);
+
+ // The report is added to CrashLog as part of logging all of Printf output.
+#endif
+}
+
+SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
+#if defined(__x86_64__) || defined(__i386__)
+ ucontext_t *ucontext = static_cast<ucontext_t*>(context);
+ return ucontext->uc_mcontext->__es.__err & 2 /*T_PF_WRITE*/ ? Write : Read;
+#elif defined(__arm64__)
+ ucontext_t *ucontext = static_cast<ucontext_t*>(context);
+ return ucontext->uc_mcontext->__es.__esr & 0x40 /*ISS_DA_WNR*/ ? Write : Read;
+#else
+ return Unknown;
+#endif
+}
+
+bool SignalContext::IsTrueFaultingAddress() const {
+ auto si = static_cast<const siginfo_t *>(siginfo);
+ // "Real" SIGSEGV codes (e.g., SEGV_MAPERR, SEGV_MAPERR) are non-zero.
+ return si->si_signo == SIGSEGV && si->si_code != 0;
+}
+
+#if defined(__aarch64__) && defined(arm_thread_state64_get_sp)
+ #define AARCH64_GET_REG(r) \
+ (uptr)ptrauth_strip( \
+ (void *)arm_thread_state64_get_##r(ucontext->uc_mcontext->__ss), 0)
+#else
+ #define AARCH64_GET_REG(r) (uptr)ucontext->uc_mcontext->__ss.__##r
+#endif
+
+static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
+ ucontext_t *ucontext = (ucontext_t*)context;
+# if defined(__aarch64__)
+ *pc = AARCH64_GET_REG(pc);
+ *bp = AARCH64_GET_REG(fp);
+ *sp = AARCH64_GET_REG(sp);
+# elif defined(__x86_64__)
+ *pc = ucontext->uc_mcontext->__ss.__rip;
+ *bp = ucontext->uc_mcontext->__ss.__rbp;
+ *sp = ucontext->uc_mcontext->__ss.__rsp;
+# elif defined(__arm__)
+ *pc = ucontext->uc_mcontext->__ss.__pc;
+ *bp = ucontext->uc_mcontext->__ss.__r[7];
+ *sp = ucontext->uc_mcontext->__ss.__sp;
+# elif defined(__i386__)
+ *pc = ucontext->uc_mcontext->__ss.__eip;
+ *bp = ucontext->uc_mcontext->__ss.__ebp;
+ *sp = ucontext->uc_mcontext->__ss.__esp;
+# else
+# error "Unknown architecture"
+# endif
+}
+
+void SignalContext::InitPcSpBp() {
+ addr = (uptr)ptrauth_strip((void *)addr, 0);
+ GetPcSpBp(context, &pc, &sp, &bp);
+}
+
+// ASan/TSan use mmap in a way that creates “deallocation gaps” which triggers
+// EXC_GUARD exceptions on macOS 10.15+ (XNU 19.0+).
+static void DisableMmapExcGuardExceptions() {
+ using task_exc_guard_behavior_t = uint32_t;
+ using task_set_exc_guard_behavior_t =
+ kern_return_t(task_t task, task_exc_guard_behavior_t behavior);
+ auto *set_behavior = (task_set_exc_guard_behavior_t *)dlsym(
+ RTLD_DEFAULT, "task_set_exc_guard_behavior");
+ if (set_behavior == nullptr) return;
+ const task_exc_guard_behavior_t task_exc_guard_none = 0;
+ set_behavior(mach_task_self(), task_exc_guard_none);
+}
+
+static void VerifyInterceptorsWorking();
+static void StripEnv();
+
+void InitializePlatformEarly() {
+ // Only use xnu_fast_mmap when on x86_64 and the kernel supports it.
+ use_xnu_fast_mmap =
+#if defined(__x86_64__)
+ GetDarwinKernelVersion() >= DarwinKernelVersion(17, 5);
+#else
+ false;
+#endif
+ if (GetDarwinKernelVersion() >= DarwinKernelVersion(19, 0))
+ DisableMmapExcGuardExceptions();
+
+# if !SANITIZER_GO
+ MonotonicNanoTime(); // Call to initialize mach_timebase_info
+ VerifyInterceptorsWorking();
+ StripEnv();
+# endif
+}
+
+#if !SANITIZER_GO
+static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES";
+LowLevelAllocator allocator_for_env;
+
+static bool ShouldCheckInterceptors() {
+ // Restrict "interceptors working?" check to ASan and TSan.
+ const char *sanitizer_names[] = {"AddressSanitizer", "ThreadSanitizer"};
+ size_t count = sizeof(sanitizer_names) / sizeof(sanitizer_names[0]);
+ for (size_t i = 0; i < count; i++) {
+ if (internal_strcmp(sanitizer_names[i], SanitizerToolName) == 0)
+ return true;
+ }
+ return false;
+}
+
+static void VerifyInterceptorsWorking() {
+ if (!common_flags()->verify_interceptors || !ShouldCheckInterceptors())
+ return;
+
+ // Verify that interceptors really work. We'll use dlsym to locate
+ // "puts", if interceptors are working, it should really point to
+ // "wrap_puts" within our own dylib.
+ Dl_info info_puts, info_runtime;
+ RAW_CHECK(dladdr(dlsym(RTLD_DEFAULT, "puts"), &info_puts));
+ RAW_CHECK(dladdr((void *)__sanitizer_report_error_summary, &info_runtime));
+ if (internal_strcmp(info_puts.dli_fname, info_runtime.dli_fname) != 0) {
+ Report(
+ "ERROR: Interceptors are not working. This may be because %s is "
+ "loaded too late (e.g. via dlopen). Please launch the executable "
+ "with:\n%s=%s\n",
+ SanitizerToolName, kDyldInsertLibraries, info_runtime.dli_fname);
+ RAW_CHECK("interceptors not installed" && 0);
+ }
+}
+
+// Change the value of the env var |name|, leaking the original value.
+// If |name_value| is NULL, the variable is deleted from the environment,
+// otherwise the corresponding "NAME=value" string is replaced with
+// |name_value|.
+static void LeakyResetEnv(const char *name, const char *name_value) {
+ char **env = GetEnviron();
+ uptr name_len = internal_strlen(name);
+ while (*env != 0) {
+ uptr len = internal_strlen(*env);
+ if (len > name_len) {
+ const char *p = *env;
+ if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') {
+ // Match.
+ if (name_value) {
+ // Replace the old value with the new one.
+ *env = const_cast<char*>(name_value);
+ } else {
+ // Shift the subsequent pointers back.
+ char **del = env;
+ do {
+ del[0] = del[1];
+ } while (*del++);
+ }
+ }
+ }
+ env++;
+ }
+}
+
+static void StripEnv() {
+ if (!common_flags()->strip_env)
+ return;
+
+ char *dyld_insert_libraries =
+ const_cast<char *>(GetEnv(kDyldInsertLibraries));
+ if (!dyld_insert_libraries)
+ return;
+
+ Dl_info info;
+ RAW_CHECK(dladdr((void *)__sanitizer_report_error_summary, &info));
+ const char *dylib_name = StripModuleName(info.dli_fname);
+ bool lib_is_in_env = internal_strstr(dyld_insert_libraries, dylib_name);
+ if (!lib_is_in_env)
+ return;
+
+ // DYLD_INSERT_LIBRARIES is set and contains the runtime library. Let's remove
+ // the dylib from the environment variable, because interceptors are installed
+ // and we don't want our children to inherit the variable.
+
+ uptr old_env_len = internal_strlen(dyld_insert_libraries);
+ uptr dylib_name_len = internal_strlen(dylib_name);
+ uptr env_name_len = internal_strlen(kDyldInsertLibraries);
+ // Allocate memory to hold the previous env var name, its value, the '='
+ // sign and the '\0' char.
+ char *new_env = (char*)allocator_for_env.Allocate(
+ old_env_len + 2 + env_name_len);
+ RAW_CHECK(new_env);
+ internal_memset(new_env, '\0', old_env_len + 2 + env_name_len);
+ internal_strncpy(new_env, kDyldInsertLibraries, env_name_len);
+ new_env[env_name_len] = '=';
+ char *new_env_pos = new_env + env_name_len + 1;
+
+ // Iterate over colon-separated pieces of |dyld_insert_libraries|.
+ char *piece_start = dyld_insert_libraries;
+ char *piece_end = NULL;
+ char *old_env_end = dyld_insert_libraries + old_env_len;
+ do {
+ if (piece_start[0] == ':') piece_start++;
+ piece_end = internal_strchr(piece_start, ':');
+ if (!piece_end) piece_end = dyld_insert_libraries + old_env_len;
+ if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break;
+ uptr piece_len = piece_end - piece_start;
+
+ char *filename_start =
+ (char *)internal_memrchr(piece_start, '/', piece_len);
+ uptr filename_len = piece_len;
+ if (filename_start) {
+ filename_start += 1;
+ filename_len = piece_len - (filename_start - piece_start);
+ } else {
+ filename_start = piece_start;
+ }
+
+ // If the current piece isn't the runtime library name,
+ // append it to new_env.
+ if ((dylib_name_len != filename_len) ||
+ (internal_memcmp(filename_start, dylib_name, dylib_name_len) != 0)) {
+ if (new_env_pos != new_env + env_name_len + 1) {
+ new_env_pos[0] = ':';
+ new_env_pos++;
+ }
+ internal_strncpy(new_env_pos, piece_start, piece_len);
+ new_env_pos += piece_len;
+ }
+ // Move on to the next piece.
+ piece_start = piece_end;
+ } while (piece_start < old_env_end);
+
+ // Can't use setenv() here, because it requires the allocator to be
+ // initialized.
+ // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in
+ // a separate function called after InitializeAllocator().
+ if (new_env_pos == new_env + env_name_len + 1) new_env = NULL;
+ LeakyResetEnv(kDyldInsertLibraries, new_env);
+}
+#endif // SANITIZER_GO
+
+char **GetArgv() {
+ return *_NSGetArgv();
+}
+
+#if SANITIZER_IOS && !SANITIZER_IOSSIM
+// The task_vm_info struct is normally provided by the macOS SDK, but we need
+// fields only available in 10.12+. Declare the struct manually to be able to
+// build against older SDKs.
+struct __sanitizer_task_vm_info {
+ mach_vm_size_t virtual_size;
+ integer_t region_count;
+ integer_t page_size;
+ mach_vm_size_t resident_size;
+ mach_vm_size_t resident_size_peak;
+ mach_vm_size_t device;
+ mach_vm_size_t device_peak;
+ mach_vm_size_t internal;
+ mach_vm_size_t internal_peak;
+ mach_vm_size_t external;
+ mach_vm_size_t external_peak;
+ mach_vm_size_t reusable;
+ mach_vm_size_t reusable_peak;
+ mach_vm_size_t purgeable_volatile_pmap;
+ mach_vm_size_t purgeable_volatile_resident;
+ mach_vm_size_t purgeable_volatile_virtual;
+ mach_vm_size_t compressed;
+ mach_vm_size_t compressed_peak;
+ mach_vm_size_t compressed_lifetime;
+ mach_vm_size_t phys_footprint;
+ mach_vm_address_t min_address;
+ mach_vm_address_t max_address;
+};
+#define __SANITIZER_TASK_VM_INFO_COUNT ((mach_msg_type_number_t) \
+ (sizeof(__sanitizer_task_vm_info) / sizeof(natural_t)))
+
+static uptr GetTaskInfoMaxAddress() {
+ __sanitizer_task_vm_info vm_info = {} /* zero initialize */;
+ mach_msg_type_number_t count = __SANITIZER_TASK_VM_INFO_COUNT;
+ int err = task_info(mach_task_self(), TASK_VM_INFO, (int *)&vm_info, &count);
+ return err ? 0 : vm_info.max_address;
+}
+
+uptr GetMaxUserVirtualAddress() {
+ static uptr max_vm = GetTaskInfoMaxAddress();
+ if (max_vm != 0) {
+ const uptr ret_value = max_vm - 1;
+ CHECK_LE(ret_value, SANITIZER_MMAP_RANGE_SIZE);
+ return ret_value;
+ }
+
+ // xnu cannot provide vm address limit
+# if SANITIZER_WORDSIZE == 32
+ constexpr uptr fallback_max_vm = 0xffe00000 - 1;
+# else
+ constexpr uptr fallback_max_vm = 0x200000000 - 1;
+# endif
+ static_assert(fallback_max_vm <= SANITIZER_MMAP_RANGE_SIZE,
+ "Max virtual address must be less than mmap range size.");
+ return fallback_max_vm;
+}
+
+#else // !SANITIZER_IOS
+
+uptr GetMaxUserVirtualAddress() {
+# if SANITIZER_WORDSIZE == 64
+ constexpr uptr max_vm = (1ULL << 47) - 1; // 0x00007fffffffffffUL;
+# else // SANITIZER_WORDSIZE == 32
+ static_assert(SANITIZER_WORDSIZE == 32, "Wrong wordsize");
+ constexpr uptr max_vm = (1ULL << 32) - 1; // 0xffffffff;
+# endif
+ static_assert(max_vm <= SANITIZER_MMAP_RANGE_SIZE,
+ "Max virtual address must be less than mmap range size.");
+ return max_vm;
+}
+#endif
+
+uptr GetMaxVirtualAddress() {
+ return GetMaxUserVirtualAddress();
+}
+
+uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
+ uptr min_shadow_base_alignment, uptr &high_mem_end) {
+ const uptr granularity = GetMmapGranularity();
+ const uptr alignment =
+ Max<uptr>(granularity << shadow_scale, 1ULL << min_shadow_base_alignment);
+ const uptr left_padding =
+ Max<uptr>(granularity, 1ULL << min_shadow_base_alignment);
+
+ uptr space_size = shadow_size_bytes + left_padding;
+
+ uptr largest_gap_found = 0;
+ uptr max_occupied_addr = 0;
+ VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size);
+ uptr shadow_start =
+ FindAvailableMemoryRange(space_size, alignment, granularity,
+ &largest_gap_found, &max_occupied_addr);
+ // If the shadow doesn't fit, restrict the address space to make it fit.
+ if (shadow_start == 0) {
+ VReport(
+ 2,
+ "Shadow doesn't fit, largest_gap_found = %p, max_occupied_addr = %p\n",
+ (void *)largest_gap_found, (void *)max_occupied_addr);
+ uptr new_max_vm = RoundDownTo(largest_gap_found << shadow_scale, alignment);
+ if (new_max_vm < max_occupied_addr) {
+ Report("Unable to find a memory range for dynamic shadow.\n");
+ Report(
+ "space_size = %p, largest_gap_found = %p, max_occupied_addr = %p, "
+ "new_max_vm = %p\n",
+ (void *)space_size, (void *)largest_gap_found,
+ (void *)max_occupied_addr, (void *)new_max_vm);
+ CHECK(0 && "cannot place shadow");
+ }
+ RestrictMemoryToMaxAddress(new_max_vm);
+ high_mem_end = new_max_vm - 1;
+ space_size = (high_mem_end >> shadow_scale) + left_padding;
+ VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size);
+ shadow_start = FindAvailableMemoryRange(space_size, alignment, granularity,
+ nullptr, nullptr);
+ if (shadow_start == 0) {
+ Report("Unable to find a memory range after restricting VM.\n");
+ CHECK(0 && "cannot place shadow after restricting vm");
+ }
+ }
+ CHECK_NE((uptr)0, shadow_start);
+ CHECK(IsAligned(shadow_start, alignment));
+ return shadow_start;
+}
+
+uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,
+ uptr num_aliases, uptr ring_buffer_size) {
+ CHECK(false && "HWASan aliasing is unimplemented on Mac");
+ return 0;
+}
+
+uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
+ uptr *largest_gap_found,
+ uptr *max_occupied_addr) {
+ typedef vm_region_submap_short_info_data_64_t RegionInfo;
+ enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 };
+ // Start searching for available memory region past PAGEZERO, which is
+ // 4KB on 32-bit and 4GB on 64-bit.
+ mach_vm_address_t start_address =
+ (SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000;
+
+ const mach_vm_address_t max_vm_address = GetMaxVirtualAddress() + 1;
+ mach_vm_address_t address = start_address;
+ mach_vm_address_t free_begin = start_address;
+ kern_return_t kr = KERN_SUCCESS;
+ if (largest_gap_found) *largest_gap_found = 0;
+ if (max_occupied_addr) *max_occupied_addr = 0;
+ while (kr == KERN_SUCCESS) {
+ mach_vm_size_t vmsize = 0;
+ natural_t depth = 0;
+ RegionInfo vminfo;
+ mach_msg_type_number_t count = kRegionInfoSize;
+ kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
+ (vm_region_info_t)&vminfo, &count);
+ if (kr == KERN_INVALID_ADDRESS) {
+ // No more regions beyond "address", consider the gap at the end of VM.
+ address = max_vm_address;
+ vmsize = 0;
+ } else {
+ if (max_occupied_addr) *max_occupied_addr = address + vmsize;
+ }
+ if (free_begin != address) {
+ // We found a free region [free_begin..address-1].
+ uptr gap_start = RoundUpTo((uptr)free_begin + left_padding, alignment);
+ uptr gap_end = RoundDownTo((uptr)Min(address, max_vm_address), alignment);
+ uptr gap_size = gap_end > gap_start ? gap_end - gap_start : 0;
+ if (size < gap_size) {
+ return gap_start;
+ }
+
+ if (largest_gap_found && *largest_gap_found < gap_size) {
+ *largest_gap_found = gap_size;
+ }
+ }
+ // Move to the next region.
+ address += vmsize;
+ free_begin = address;
+ }
+
+ // We looked at all free regions and could not find one large enough.
+ return 0;
+}
+
+// FIXME implement on this platform.
+void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
+
+void SignalContext::DumpAllRegisters(void *context) {
+ Report("Register values:\n");
+
+ ucontext_t *ucontext = (ucontext_t*)context;
+# define DUMPREG64(r) \
+ Printf("%s = 0x%016llx ", #r, ucontext->uc_mcontext->__ss.__ ## r);
+# define DUMPREGA64(r) \
+ Printf(" %s = 0x%016lx ", #r, AARCH64_GET_REG(r));
+# define DUMPREG32(r) \
+ Printf("%s = 0x%08x ", #r, ucontext->uc_mcontext->__ss.__ ## r);
+# define DUMPREG_(r) Printf(" "); DUMPREG(r);
+# define DUMPREG__(r) Printf(" "); DUMPREG(r);
+# define DUMPREG___(r) Printf(" "); DUMPREG(r);
+
+# if defined(__x86_64__)
+# define DUMPREG(r) DUMPREG64(r)
+ DUMPREG(rax); DUMPREG(rbx); DUMPREG(rcx); DUMPREG(rdx); Printf("\n");
+ DUMPREG(rdi); DUMPREG(rsi); DUMPREG(rbp); DUMPREG(rsp); Printf("\n");
+ DUMPREG_(r8); DUMPREG_(r9); DUMPREG(r10); DUMPREG(r11); Printf("\n");
+ DUMPREG(r12); DUMPREG(r13); DUMPREG(r14); DUMPREG(r15); Printf("\n");
+# elif defined(__i386__)
+# define DUMPREG(r) DUMPREG32(r)
+ DUMPREG(eax); DUMPREG(ebx); DUMPREG(ecx); DUMPREG(edx); Printf("\n");
+ DUMPREG(edi); DUMPREG(esi); DUMPREG(ebp); DUMPREG(esp); Printf("\n");
+# elif defined(__aarch64__)
+# define DUMPREG(r) DUMPREG64(r)
+ DUMPREG_(x[0]); DUMPREG_(x[1]); DUMPREG_(x[2]); DUMPREG_(x[3]); Printf("\n");
+ DUMPREG_(x[4]); DUMPREG_(x[5]); DUMPREG_(x[6]); DUMPREG_(x[7]); Printf("\n");
+ DUMPREG_(x[8]); DUMPREG_(x[9]); DUMPREG(x[10]); DUMPREG(x[11]); Printf("\n");
+ DUMPREG(x[12]); DUMPREG(x[13]); DUMPREG(x[14]); DUMPREG(x[15]); Printf("\n");
+ DUMPREG(x[16]); DUMPREG(x[17]); DUMPREG(x[18]); DUMPREG(x[19]); Printf("\n");
+ DUMPREG(x[20]); DUMPREG(x[21]); DUMPREG(x[22]); DUMPREG(x[23]); Printf("\n");
+ DUMPREG(x[24]); DUMPREG(x[25]); DUMPREG(x[26]); DUMPREG(x[27]); Printf("\n");
+ DUMPREG(x[28]); DUMPREGA64(fp); DUMPREGA64(lr); DUMPREGA64(sp); Printf("\n");
+# elif defined(__arm__)
+# define DUMPREG(r) DUMPREG32(r)
+ DUMPREG_(r[0]); DUMPREG_(r[1]); DUMPREG_(r[2]); DUMPREG_(r[3]); Printf("\n");
+ DUMPREG_(r[4]); DUMPREG_(r[5]); DUMPREG_(r[6]); DUMPREG_(r[7]); Printf("\n");
+ DUMPREG_(r[8]); DUMPREG_(r[9]); DUMPREG(r[10]); DUMPREG(r[11]); Printf("\n");
+ DUMPREG(r[12]); DUMPREG___(sp); DUMPREG___(lr); DUMPREG___(pc); Printf("\n");
+# else
+# error "Unknown architecture"
+# endif
+
+# undef DUMPREG64
+# undef DUMPREG32
+# undef DUMPREG_
+# undef DUMPREG__
+# undef DUMPREG___
+# undef DUMPREG
+}
+
+static inline bool CompareBaseAddress(const LoadedModule &a,
+ const LoadedModule &b) {
+ return a.base_address() < b.base_address();
+}
+
+void FormatUUID(char *out, uptr size, const u8 *uuid) {
+ internal_snprintf(out, size,
+ "<%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-"
+ "%02X%02X%02X%02X%02X%02X>",
+ uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
+ uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
+ uuid[12], uuid[13], uuid[14], uuid[15]);
+}
+
+void DumpProcessMap() {
+ Printf("Process module map:\n");
+ MemoryMappingLayout memory_mapping(false);
+ InternalMmapVector<LoadedModule> modules;
+ modules.reserve(128);
+ memory_mapping.DumpListOfModules(&modules);
+ Sort(modules.data(), modules.size(), CompareBaseAddress);
+ for (uptr i = 0; i < modules.size(); ++i) {
+ char uuid_str[128];
+ FormatUUID(uuid_str, sizeof(uuid_str), modules[i].uuid());
+ Printf("0x%zx-0x%zx %s (%s) %s\n", modules[i].base_address(),
+ modules[i].max_address(), modules[i].full_name(),
+ ModuleArchToString(modules[i].arch()), uuid_str);
+ }
+ Printf("End of module map.\n");
+}
+
+void CheckNoDeepBind(const char *filename, int flag) {
+ // Do nothing.
+}
+
+bool GetRandom(void *buffer, uptr length, bool blocking) {
+ if (!buffer || !length || length > 256)
+ return false;
+ // arc4random never fails.
+ REAL(arc4random_buf)(buffer, length);
+ return true;
+}
+
+u32 GetNumberOfCPUs() {
+ return (u32)sysconf(_SC_NPROCESSORS_ONLN);
+}
+
+void InitializePlatformCommonFlags(CommonFlags *cf) {}
+
+// Pthread introspection hook
+//
+// * GCD worker threads are created without a call to pthread_create(), but we
+// still need to register these threads (with ThreadCreate/Start()).
+// * We use the "pthread introspection hook" below to observe the creation of
+// such threads.
+// * GCD worker threads don't have parent threads and the CREATE event is
+// delivered in the context of the thread itself. CREATE events for regular
+// threads, are delivered on the parent. We use this to tell apart which
+// threads are GCD workers with `thread == pthread_self()`.
+//
+static pthread_introspection_hook_t prev_pthread_introspection_hook;
+static ThreadEventCallbacks thread_event_callbacks;
+
+static void sanitizer_pthread_introspection_hook(unsigned int event,
+ pthread_t thread, void *addr,
+ size_t size) {
+ // create -> start -> terminate -> destroy
+ // * create/destroy are usually (not guaranteed) delivered on the parent and
+ // track resource allocation/reclamation
+ // * start/terminate are guaranteed to be delivered in the context of the
+ // thread and give hooks into "just after (before) thread starts (stops)
+ // executing"
+ DCHECK(event >= PTHREAD_INTROSPECTION_THREAD_CREATE &&
+ event <= PTHREAD_INTROSPECTION_THREAD_DESTROY);
+
+ if (event == PTHREAD_INTROSPECTION_THREAD_CREATE) {
+ bool gcd_worker = (thread == pthread_self());
+ if (thread_event_callbacks.create)
+ thread_event_callbacks.create((uptr)thread, gcd_worker);
+ } else if (event == PTHREAD_INTROSPECTION_THREAD_START) {
+ CHECK_EQ(thread, pthread_self());
+ if (thread_event_callbacks.start)
+ thread_event_callbacks.start((uptr)thread);
+ }
+
+ if (prev_pthread_introspection_hook)
+ prev_pthread_introspection_hook(event, thread, addr, size);
+
+ if (event == PTHREAD_INTROSPECTION_THREAD_TERMINATE) {
+ CHECK_EQ(thread, pthread_self());
+ if (thread_event_callbacks.terminate)
+ thread_event_callbacks.terminate((uptr)thread);
+ } else if (event == PTHREAD_INTROSPECTION_THREAD_DESTROY) {
+ if (thread_event_callbacks.destroy)
+ thread_event_callbacks.destroy((uptr)thread);
+ }
+}
+
+void InstallPthreadIntrospectionHook(const ThreadEventCallbacks &callbacks) {
+ thread_event_callbacks = callbacks;
+ prev_pthread_introspection_hook =
+ pthread_introspection_hook_install(&sanitizer_pthread_introspection_hook);
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mac.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mac.h
new file mode 100644
index 00000000000..f0a97d098ee
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mac.h
@@ -0,0 +1,79 @@
+//===-- sanitizer_mac.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between various sanitizers' runtime libraries and
+// provides definitions for OSX-specific functions.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_APPLE_H
+#define SANITIZER_APPLE_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_platform.h"
+#if SANITIZER_APPLE
+#include "sanitizer_posix.h"
+
+namespace __sanitizer {
+
+struct MemoryMappingLayoutData {
+ int current_image;
+ u32 current_magic;
+ u32 current_filetype;
+ ModuleArch current_arch;
+ u8 current_uuid[kModuleUUIDSize];
+ int current_load_cmd_count;
+ const char *current_load_cmd_addr;
+ bool current_instrumented;
+};
+
+template <typename VersionType>
+struct VersionBase {
+ u16 major;
+ u16 minor;
+
+ VersionBase(u16 major, u16 minor) : major(major), minor(minor) {}
+
+ bool operator==(const VersionType &other) const {
+ return major == other.major && minor == other.minor;
+ }
+ bool operator>=(const VersionType &other) const {
+ return major > other.major ||
+ (major == other.major && minor >= other.minor);
+ }
+ bool operator<(const VersionType &other) const { return !(*this >= other); }
+};
+
+struct MacosVersion : VersionBase<MacosVersion> {
+ MacosVersion(u16 major, u16 minor) : VersionBase(major, minor) {}
+};
+
+struct DarwinKernelVersion : VersionBase<DarwinKernelVersion> {
+ DarwinKernelVersion(u16 major, u16 minor) : VersionBase(major, minor) {}
+};
+
+MacosVersion GetMacosAlignedVersion();
+DarwinKernelVersion GetDarwinKernelVersion();
+
+char **GetEnviron();
+
+void RestrictMemoryToMaxAddress(uptr max_address);
+
+using ThreadEventCallback = void (*)(uptr thread);
+using ThreadCreateEventCallback = void (*)(uptr thread, bool gcd_worker);
+struct ThreadEventCallbacks {
+ ThreadCreateEventCallback create;
+ ThreadEventCallback start;
+ ThreadEventCallback terminate;
+ ThreadEventCallback destroy;
+};
+
+void InstallPthreadIntrospectionHook(const ThreadEventCallbacks &callbacks);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_APPLE
+#endif // SANITIZER_APPLE_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mac_libcdep.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mac_libcdep.cpp
new file mode 100644
index 00000000000..b452dc4a49e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mac_libcdep.cpp
@@ -0,0 +1,29 @@
+//===-- sanitizer_mac_libcdep.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between various sanitizers' runtime libraries and
+// implements OSX-specific functions.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_APPLE
+#include "sanitizer_mac.h"
+
+#include <sys/mman.h>
+
+namespace __sanitizer {
+
+void RestrictMemoryToMaxAddress(uptr max_address) {
+ uptr size_to_mmap = GetMaxUserVirtualAddress() + 1 - max_address;
+ void *res = MmapFixedNoAccess(max_address, size_to_mmap, "high gap");
+ CHECK(res != MAP_FAILED);
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc
new file mode 100644
index 00000000000..fe76b3f8aa0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc
@@ -0,0 +1,414 @@
+//===-- sanitizer_malloc_mac.inc --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains Mac-specific malloc interceptors and a custom zone
+// implementation, which together replace the system allocator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if !SANITIZER_APPLE
+#error "This file should only be compiled on Darwin."
+#endif
+
+#include <AvailabilityMacros.h>
+#include <CoreFoundation/CFBase.h>
+#include <dlfcn.h>
+#include <malloc/malloc.h>
+#include <sys/mman.h>
+
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_allocator_dlsym.h"
+#include "sanitizer_common/sanitizer_mac.h"
+
+// Similar code is used in Google Perftools,
+// https://github.com/gperftools/gperftools.
+
+namespace __sanitizer {
+
+extern malloc_zone_t sanitizer_zone;
+
+struct sanitizer_malloc_introspection_t : public malloc_introspection_t {
+ // IMPORTANT: Do not change the order, alignment, or types of these fields to
+ // maintain binary compatibility. You should only add fields to this struct.
+
+ // Used to track changes to the allocator that will affect
+ // zone enumeration.
+ u64 allocator_enumeration_version;
+ uptr allocator_ptr;
+ uptr allocator_size;
+};
+
+u64 GetMallocZoneAllocatorEnumerationVersion() {
+ // This represents the current allocator ABI version.
+ // This field should be incremented every time the Allocator
+ // ABI changes in a way that breaks allocator enumeration.
+ return 0;
+}
+
+} // namespace __sanitizer
+
+INTERCEPTOR(malloc_zone_t *, malloc_create_zone,
+ vm_size_t start_size, unsigned zone_flags) {
+ COMMON_MALLOC_ENTER();
+ uptr page_size = GetPageSizeCached();
+ uptr allocated_size = RoundUpTo(sizeof(sanitizer_zone), page_size);
+ COMMON_MALLOC_MEMALIGN(page_size, allocated_size);
+ malloc_zone_t *new_zone = (malloc_zone_t *)p;
+ internal_memcpy(new_zone, &sanitizer_zone, sizeof(sanitizer_zone));
+ new_zone->zone_name = NULL; // The name will be changed anyway.
+ // Prevent the client app from overwriting the zone contents.
+ // Library functions that need to modify the zone will set PROT_WRITE on it.
+ // This matches the behavior of malloc_create_zone() on OSX 10.7 and higher.
+ mprotect(new_zone, allocated_size, PROT_READ);
+ // We're explicitly *NOT* registering the zone.
+ return new_zone;
+}
+
+INTERCEPTOR(void, malloc_destroy_zone, malloc_zone_t *zone) {
+ COMMON_MALLOC_ENTER();
+ // We don't need to do anything here. We're not registering new zones, so we
+ // don't to unregister. Just un-mprotect and free() the zone.
+ uptr page_size = GetPageSizeCached();
+ uptr allocated_size = RoundUpTo(sizeof(sanitizer_zone), page_size);
+ mprotect(zone, allocated_size, PROT_READ | PROT_WRITE);
+ if (zone->zone_name) {
+ COMMON_MALLOC_FREE((void *)zone->zone_name);
+ }
+ COMMON_MALLOC_FREE(zone);
+}
+
+INTERCEPTOR(malloc_zone_t *, malloc_default_zone, void) {
+ COMMON_MALLOC_ENTER();
+ return &sanitizer_zone;
+}
+
+INTERCEPTOR(malloc_zone_t *, malloc_zone_from_ptr, const void *ptr) {
+ COMMON_MALLOC_ENTER();
+ size_t size = sanitizer_zone.size(&sanitizer_zone, ptr);
+ if (size) { // Claimed by sanitizer zone?
+ return &sanitizer_zone;
+ }
+ return REAL(malloc_zone_from_ptr)(ptr);
+}
+
+INTERCEPTOR(malloc_zone_t *, malloc_default_purgeable_zone, void) {
+ // FIXME: ASan should support purgeable allocations.
+ // https://github.com/google/sanitizers/issues/139
+ COMMON_MALLOC_ENTER();
+ return &sanitizer_zone;
+}
+
+INTERCEPTOR(void, malloc_make_purgeable, void *ptr) {
+ // FIXME: ASan should support purgeable allocations. Ignoring them is fine
+ // for now.
+ COMMON_MALLOC_ENTER();
+}
+
+INTERCEPTOR(int, malloc_make_nonpurgeable, void *ptr) {
+ // FIXME: ASan should support purgeable allocations. Ignoring them is fine
+ // for now.
+ COMMON_MALLOC_ENTER();
+ // Must return 0 if the contents were not purged since the last call to
+ // malloc_make_purgeable().
+ return 0;
+}
+
+INTERCEPTOR(void, malloc_set_zone_name, malloc_zone_t *zone, const char *name) {
+ COMMON_MALLOC_ENTER();
+ InternalScopedString new_name;
+ if (name && zone->introspect == sanitizer_zone.introspect) {
+ new_name.append(COMMON_MALLOC_ZONE_NAME "-%s", name);
+ name = new_name.data();
+ }
+
+ // Call the system malloc's implementation for both external and our zones,
+ // since that appropriately changes VM region protections on the zone.
+ REAL(malloc_set_zone_name)(zone, name);
+}
+
+INTERCEPTOR(void *, malloc, size_t size) {
+ COMMON_MALLOC_ENTER();
+ COMMON_MALLOC_MALLOC(size);
+ return p;
+}
+
+INTERCEPTOR(void, free, void *ptr) {
+ COMMON_MALLOC_ENTER();
+ if (!ptr) return;
+ COMMON_MALLOC_FREE(ptr);
+}
+
+INTERCEPTOR(void *, realloc, void *ptr, size_t size) {
+ COMMON_MALLOC_ENTER();
+ COMMON_MALLOC_REALLOC(ptr, size);
+ return p;
+}
+
+INTERCEPTOR(void *, calloc, size_t nmemb, size_t size) {
+ COMMON_MALLOC_ENTER();
+ COMMON_MALLOC_CALLOC(nmemb, size);
+ return p;
+}
+
+INTERCEPTOR(void *, valloc, size_t size) {
+ COMMON_MALLOC_ENTER();
+ COMMON_MALLOC_VALLOC(size);
+ return p;
+}
+
+INTERCEPTOR(size_t, malloc_good_size, size_t size) {
+ COMMON_MALLOC_ENTER();
+ return sanitizer_zone.introspect->good_size(&sanitizer_zone, size);
+}
+
+INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) {
+ COMMON_MALLOC_ENTER();
+ CHECK(memptr);
+ COMMON_MALLOC_POSIX_MEMALIGN(memptr, alignment, size);
+ return res;
+}
+
+namespace {
+
+// TODO(glider): the __sanitizer_mz_* functions should be united with the Linux
+// wrappers, as they are basically copied from there.
+extern "C"
+SANITIZER_INTERFACE_ATTRIBUTE
+size_t __sanitizer_mz_size(malloc_zone_t* zone, const void* ptr) {
+ COMMON_MALLOC_SIZE(ptr);
+ return size;
+}
+
+extern "C"
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer_mz_malloc(malloc_zone_t *zone, uptr size) {
+ COMMON_MALLOC_ENTER();
+ COMMON_MALLOC_MALLOC(size);
+ return p;
+}
+
+struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
+ static bool UseImpl() { return !COMMON_MALLOC_SANITIZER_INITIALIZED; }
+};
+
+extern "C"
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer_mz_calloc(malloc_zone_t *zone, size_t nmemb, size_t size) {
+ if (DlsymAlloc::Use())
+ return DlsymAlloc::Callocate(nmemb, size);
+ COMMON_MALLOC_CALLOC(nmemb, size);
+ return p;
+}
+
+extern "C"
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer_mz_valloc(malloc_zone_t *zone, size_t size) {
+ COMMON_MALLOC_ENTER();
+ COMMON_MALLOC_VALLOC(size);
+ return p;
+}
+
+// TODO(glider): the allocation callbacks need to be refactored.
+extern "C"
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_mz_free(malloc_zone_t *zone, void *ptr) {
+ if (!ptr) return;
+ if (DlsymAlloc::PointerIsMine(ptr))
+ return DlsymAlloc::Free(ptr);
+ COMMON_MALLOC_FREE(ptr);
+}
+
+#define GET_ZONE_FOR_PTR(ptr) \
+ malloc_zone_t *zone_ptr = WRAP(malloc_zone_from_ptr)(ptr); \
+ const char *zone_name = (zone_ptr == 0) ? 0 : zone_ptr->zone_name
+
+extern "C"
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer_mz_realloc(malloc_zone_t *zone, void *ptr, size_t new_size) {
+ if (!ptr) {
+ COMMON_MALLOC_MALLOC(new_size);
+ return p;
+ } else {
+ COMMON_MALLOC_SIZE(ptr);
+ if (size) {
+ COMMON_MALLOC_REALLOC(ptr, new_size);
+ return p;
+ } else {
+ // We can't recover from reallocating an unknown address, because
+ // this would require reading at most |new_size| bytes from
+ // potentially unaccessible memory.
+ GET_ZONE_FOR_PTR(ptr);
+ COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name);
+ return nullptr;
+ }
+ }
+}
+
+extern "C"
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_mz_destroy(malloc_zone_t* zone) {
+ // A no-op -- we will not be destroyed!
+ Report("__sanitizer_mz_destroy() called -- ignoring\n");
+}
+
+extern "C"
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__sanitizer_mz_memalign(malloc_zone_t *zone, size_t align, size_t size) {
+ COMMON_MALLOC_ENTER();
+ COMMON_MALLOC_MEMALIGN(align, size);
+ return p;
+}
+
+// This public API exists purely for testing purposes.
+extern "C"
+SANITIZER_INTERFACE_ATTRIBUTE
+malloc_zone_t* __sanitizer_mz_default_zone() {
+ return &sanitizer_zone;
+}
+
+// This function is currently unused, and we build with -Werror.
+#if 0
+void __sanitizer_mz_free_definite_size(
+ malloc_zone_t* zone, void *ptr, size_t size) {
+ // TODO(glider): check that |size| is valid.
+ UNIMPLEMENTED();
+}
+#endif
+
+#ifndef COMMON_MALLOC_HAS_ZONE_ENUMERATOR
+#error "COMMON_MALLOC_HAS_ZONE_ENUMERATOR must be defined"
+#endif
+static_assert((COMMON_MALLOC_HAS_ZONE_ENUMERATOR) == 0 ||
+ (COMMON_MALLOC_HAS_ZONE_ENUMERATOR) == 1,
+ "COMMON_MALLOC_HAS_ZONE_ENUMERATOR must be 0 or 1");
+
+#if COMMON_MALLOC_HAS_ZONE_ENUMERATOR
+// Forward declare and expect the implementation to provided by
+// includer.
+kern_return_t mi_enumerator(task_t task, void *, unsigned type_mask,
+ vm_address_t zone_address, memory_reader_t reader,
+ vm_range_recorder_t recorder);
+#else
+// Provide stub implementation that fails.
+kern_return_t mi_enumerator(task_t task, void *, unsigned type_mask,
+ vm_address_t zone_address, memory_reader_t reader,
+ vm_range_recorder_t recorder) {
+ // Not supported.
+ return KERN_FAILURE;
+}
+#endif
+
+#ifndef COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT
+#error "COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT must be defined"
+#endif
+static_assert((COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT) == 0 ||
+ (COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT) == 1,
+ "COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT must be 0 or 1");
+#if COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT
+// Forward declare and expect the implementation to provided by
+// includer.
+void mi_extra_init(
+ sanitizer_malloc_introspection_t *mi);
+#else
+void mi_extra_init(
+ sanitizer_malloc_introspection_t *mi) {
+ // Just zero initialize the fields.
+ mi->allocator_ptr = 0;
+ mi->allocator_size = 0;
+}
+#endif
+
+size_t mi_good_size(malloc_zone_t *zone, size_t size) {
+ // I think it's always safe to return size, but we maybe could do better.
+ return size;
+}
+
+boolean_t mi_check(malloc_zone_t *zone) {
+ UNIMPLEMENTED();
+}
+
+void mi_print(malloc_zone_t *zone, boolean_t verbose) {
+ UNIMPLEMENTED();
+}
+
+void mi_log(malloc_zone_t *zone, void *address) {
+ // I don't think we support anything like this
+}
+
+void mi_force_lock(malloc_zone_t *zone) {
+ COMMON_MALLOC_FORCE_LOCK();
+}
+
+void mi_force_unlock(malloc_zone_t *zone) {
+ COMMON_MALLOC_FORCE_UNLOCK();
+}
+
+void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) {
+ COMMON_MALLOC_FILL_STATS(zone, stats);
+}
+
+boolean_t mi_zone_locked(malloc_zone_t *zone) {
+ // UNIMPLEMENTED();
+ return false;
+}
+
+} // unnamed namespace
+
+namespace COMMON_MALLOC_NAMESPACE {
+
+void InitMallocZoneFields() {
+ static sanitizer_malloc_introspection_t sanitizer_zone_introspection;
+ // Ok to use internal_memset, these places are not performance-critical.
+ internal_memset(&sanitizer_zone_introspection, 0,
+ sizeof(sanitizer_zone_introspection));
+
+ sanitizer_zone_introspection.enumerator = &mi_enumerator;
+ sanitizer_zone_introspection.good_size = &mi_good_size;
+ sanitizer_zone_introspection.check = &mi_check;
+ sanitizer_zone_introspection.print = &mi_print;
+ sanitizer_zone_introspection.log = &mi_log;
+ sanitizer_zone_introspection.force_lock = &mi_force_lock;
+ sanitizer_zone_introspection.force_unlock = &mi_force_unlock;
+ sanitizer_zone_introspection.statistics = &mi_statistics;
+ sanitizer_zone_introspection.zone_locked = &mi_zone_locked;
+
+ // Set current allocator enumeration version.
+ sanitizer_zone_introspection.allocator_enumeration_version =
+ GetMallocZoneAllocatorEnumerationVersion();
+
+ // Perform any sanitizer specific initialization.
+ mi_extra_init(&sanitizer_zone_introspection);
+
+ internal_memset(&sanitizer_zone, 0, sizeof(malloc_zone_t));
+
+ // Use version 6 for OSX >= 10.6.
+ sanitizer_zone.version = 6;
+ sanitizer_zone.zone_name = COMMON_MALLOC_ZONE_NAME;
+ sanitizer_zone.size = &__sanitizer_mz_size;
+ sanitizer_zone.malloc = &__sanitizer_mz_malloc;
+ sanitizer_zone.calloc = &__sanitizer_mz_calloc;
+ sanitizer_zone.valloc = &__sanitizer_mz_valloc;
+ sanitizer_zone.free = &__sanitizer_mz_free;
+ sanitizer_zone.realloc = &__sanitizer_mz_realloc;
+ sanitizer_zone.destroy = &__sanitizer_mz_destroy;
+ sanitizer_zone.batch_malloc = 0;
+ sanitizer_zone.batch_free = 0;
+ sanitizer_zone.free_definite_size = 0;
+ sanitizer_zone.memalign = &__sanitizer_mz_memalign;
+ sanitizer_zone.introspect = &sanitizer_zone_introspection;
+}
+
+void ReplaceSystemMalloc() {
+ InitMallocZoneFields();
+
+ // Register the zone.
+ malloc_zone_register(&sanitizer_zone);
+}
+
+} // namespace COMMON_MALLOC_NAMESPACE
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mutex.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mutex.cpp
new file mode 100644
index 00000000000..40fe5666125
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mutex.cpp
@@ -0,0 +1,225 @@
+//===-- sanitizer_mutex.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_mutex.h"
+
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+
+void StaticSpinMutex::LockSlow() {
+ for (int i = 0;; i++) {
+ if (i < 100)
+ proc_yield(1);
+ else
+ internal_sched_yield();
+ if (atomic_load(&state_, memory_order_relaxed) == 0 &&
+ atomic_exchange(&state_, 1, memory_order_acquire) == 0)
+ return;
+ }
+}
+
+void Semaphore::Wait() {
+ u32 count = atomic_load(&state_, memory_order_relaxed);
+ for (;;) {
+ if (count == 0) {
+ FutexWait(&state_, 0);
+ count = atomic_load(&state_, memory_order_relaxed);
+ continue;
+ }
+ if (atomic_compare_exchange_weak(&state_, &count, count - 1,
+ memory_order_acquire))
+ break;
+ }
+}
+
+void Semaphore::Post(u32 count) {
+ CHECK_NE(count, 0);
+ atomic_fetch_add(&state_, count, memory_order_release);
+ FutexWake(&state_, count);
+}
+
+#if SANITIZER_CHECK_DEADLOCKS
+// An empty mutex meta table, it effectively disables deadlock detection.
+// Each tool can override the table to define own mutex hierarchy and
+// enable deadlock detection.
+// The table defines a static mutex type hierarchy (what mutex types can be locked
+// under what mutex types). This table is checked to be acyclic and then
+// actual mutex lock/unlock operations are checked to adhere to this hierarchy.
+// The checking happens on mutex types rather than on individual mutex instances
+// because doing it on mutex instances will both significantly complicate
+// the implementation, worsen performance and memory overhead and is mostly
+// unnecessary (we almost never lock multiple mutexes of the same type recursively).
+static constexpr int kMutexTypeMax = 20;
+SANITIZER_WEAK_ATTRIBUTE MutexMeta mutex_meta[kMutexTypeMax] = {};
+SANITIZER_WEAK_ATTRIBUTE void PrintMutexPC(uptr pc) {}
+static StaticSpinMutex mutex_meta_mtx;
+static int mutex_type_count = -1;
+// Adjacency matrix of what mutexes can be locked under what mutexes.
+static bool mutex_can_lock[kMutexTypeMax][kMutexTypeMax];
+// Mutex types with MutexMulti mark.
+static bool mutex_multi[kMutexTypeMax];
+
+void DebugMutexInit() {
+ // Build adjacency matrix.
+ bool leaf[kMutexTypeMax];
+ internal_memset(&leaf, 0, sizeof(leaf));
+ int cnt[kMutexTypeMax];
+ internal_memset(&cnt, 0, sizeof(cnt));
+ for (int t = 0; t < kMutexTypeMax; t++) {
+ mutex_type_count = t;
+ if (!mutex_meta[t].name)
+ break;
+ CHECK_EQ(t, mutex_meta[t].type);
+ for (uptr j = 0; j < ARRAY_SIZE(mutex_meta[t].can_lock); j++) {
+ MutexType z = mutex_meta[t].can_lock[j];
+ if (z == MutexInvalid)
+ break;
+ if (z == MutexLeaf) {
+ CHECK(!leaf[t]);
+ leaf[t] = true;
+ continue;
+ }
+ if (z == MutexMulti) {
+ mutex_multi[t] = true;
+ continue;
+ }
+ CHECK_LT(z, kMutexTypeMax);
+ CHECK(!mutex_can_lock[t][z]);
+ mutex_can_lock[t][z] = true;
+ cnt[t]++;
+ }
+ }
+ // Indicates the array is not properly terminated.
+ CHECK_LT(mutex_type_count, kMutexTypeMax);
+ // Add leaf mutexes.
+ for (int t = 0; t < mutex_type_count; t++) {
+ if (!leaf[t])
+ continue;
+ CHECK_EQ(cnt[t], 0);
+ for (int z = 0; z < mutex_type_count; z++) {
+ if (z == MutexInvalid || t == z || leaf[z])
+ continue;
+ CHECK(!mutex_can_lock[z][t]);
+ mutex_can_lock[z][t] = true;
+ }
+ }
+ // Build the transitive closure and check that the graphs is acyclic.
+ u32 trans[kMutexTypeMax];
+ static_assert(sizeof(trans[0]) * 8 >= kMutexTypeMax,
+ "kMutexTypeMax does not fit into u32, switch to u64");
+ internal_memset(&trans, 0, sizeof(trans));
+ for (int i = 0; i < mutex_type_count; i++) {
+ for (int j = 0; j < mutex_type_count; j++)
+ if (mutex_can_lock[i][j])
+ trans[i] |= 1 << j;
+ }
+ for (int k = 0; k < mutex_type_count; k++) {
+ for (int i = 0; i < mutex_type_count; i++) {
+ if (trans[i] & (1 << k))
+ trans[i] |= trans[k];
+ }
+ }
+ for (int i = 0; i < mutex_type_count; i++) {
+ if (trans[i] & (1 << i)) {
+ Printf("Mutex %s participates in a cycle\n", mutex_meta[i].name);
+ Die();
+ }
+ }
+}
+
+struct InternalDeadlockDetector {
+ struct LockDesc {
+ u64 seq;
+ uptr pc;
+ int recursion;
+ };
+ int initialized;
+ u64 sequence;
+ LockDesc locked[kMutexTypeMax];
+
+ void Lock(MutexType type, uptr pc) {
+ if (!Initialize(type))
+ return;
+ CHECK_LT(type, mutex_type_count);
+ // Find the last locked mutex type.
+ // This is the type we will use for hierarchy checks.
+ u64 max_seq = 0;
+ MutexType max_idx = MutexInvalid;
+ for (int i = 0; i != mutex_type_count; i++) {
+ if (locked[i].seq == 0)
+ continue;
+ CHECK_NE(locked[i].seq, max_seq);
+ if (max_seq < locked[i].seq) {
+ max_seq = locked[i].seq;
+ max_idx = (MutexType)i;
+ }
+ }
+ if (max_idx == type && mutex_multi[type]) {
+ // Recursive lock of the same type.
+ CHECK_EQ(locked[type].seq, max_seq);
+ CHECK(locked[type].pc);
+ locked[type].recursion++;
+ return;
+ }
+ if (max_idx != MutexInvalid && !mutex_can_lock[max_idx][type]) {
+ Printf("%s: internal deadlock: can't lock %s under %s mutex\n", SanitizerToolName,
+ mutex_meta[type].name, mutex_meta[max_idx].name);
+ PrintMutexPC(locked[max_idx].pc);
+ CHECK(0);
+ }
+ locked[type].seq = ++sequence;
+ locked[type].pc = pc;
+ locked[type].recursion = 1;
+ }
+
+ void Unlock(MutexType type) {
+ if (!Initialize(type))
+ return;
+ CHECK_LT(type, mutex_type_count);
+ CHECK(locked[type].seq);
+ CHECK_GT(locked[type].recursion, 0);
+ if (--locked[type].recursion)
+ return;
+ locked[type].seq = 0;
+ locked[type].pc = 0;
+ }
+
+ void CheckNoLocks() {
+ for (int i = 0; i < mutex_type_count; i++) CHECK_EQ(locked[i].recursion, 0);
+ }
+
+ bool Initialize(MutexType type) {
+ if (type == MutexUnchecked || type == MutexInvalid)
+ return false;
+ CHECK_GT(type, MutexInvalid);
+ if (initialized != 0)
+ return initialized > 0;
+ initialized = -1;
+ SpinMutexLock lock(&mutex_meta_mtx);
+ if (mutex_type_count < 0)
+ DebugMutexInit();
+ initialized = mutex_type_count ? 1 : -1;
+ return initialized > 0;
+ }
+};
+
+static THREADLOCAL InternalDeadlockDetector deadlock_detector;
+
+void CheckedMutex::LockImpl(uptr pc) { deadlock_detector.Lock(type_, pc); }
+
+void CheckedMutex::UnlockImpl() { deadlock_detector.Unlock(type_); }
+
+void CheckedMutex::CheckNoLocksImpl() { deadlock_detector.CheckNoLocks(); }
+#endif
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mutex.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mutex.h
new file mode 100644
index 00000000000..b1a58e421d8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_mutex.h
@@ -0,0 +1,446 @@
+//===-- sanitizer_mutex.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_MUTEX_H
+#define SANITIZER_MUTEX_H
+
+#include "sanitizer_atomic.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_thread_safety.h"
+
+namespace __sanitizer {
+
+class SANITIZER_MUTEX StaticSpinMutex {
+ public:
+ void Init() {
+ atomic_store(&state_, 0, memory_order_relaxed);
+ }
+
+ void Lock() SANITIZER_ACQUIRE() {
+ if (LIKELY(TryLock()))
+ return;
+ LockSlow();
+ }
+
+ bool TryLock() SANITIZER_TRY_ACQUIRE(true) {
+ return atomic_exchange(&state_, 1, memory_order_acquire) == 0;
+ }
+
+ void Unlock() SANITIZER_RELEASE() {
+ atomic_store(&state_, 0, memory_order_release);
+ }
+
+ void CheckLocked() const SANITIZER_CHECK_LOCKED() {
+ CHECK_EQ(atomic_load(&state_, memory_order_relaxed), 1);
+ }
+
+ private:
+ atomic_uint8_t state_;
+
+ void LockSlow();
+};
+
+class SANITIZER_MUTEX SpinMutex : public StaticSpinMutex {
+ public:
+ SpinMutex() {
+ Init();
+ }
+
+ SpinMutex(const SpinMutex &) = delete;
+ void operator=(const SpinMutex &) = delete;
+};
+
+// Semaphore provides an OS-dependent way to park/unpark threads.
+// The last thread returned from Wait can destroy the object
+// (destruction-safety).
+class Semaphore {
+ public:
+ constexpr Semaphore() {}
+ Semaphore(const Semaphore &) = delete;
+ void operator=(const Semaphore &) = delete;
+
+ void Wait();
+ void Post(u32 count = 1);
+
+ private:
+ atomic_uint32_t state_ = {0};
+};
+
+typedef int MutexType;
+
+enum {
+ // Used as sentinel and to catch unassigned types
+ // (should not be used as real Mutex type).
+ MutexInvalid = 0,
+ MutexThreadRegistry,
+ // Each tool own mutexes must start at this number.
+ MutexLastCommon,
+ // Type for legacy mutexes that are not checked for deadlocks.
+ MutexUnchecked = -1,
+ // Special marks that can be used in MutexMeta::can_lock table.
+ // The leaf mutexes can be locked under any other non-leaf mutex,
+ // but no other mutex can be locked while under a leaf mutex.
+ MutexLeaf = -1,
+ // Multiple mutexes of this type can be locked at the same time.
+ MutexMulti = -3,
+};
+
+// Go linker does not support THREADLOCAL variables,
+// so we can't use per-thread state.
+// Disable checked locks on Darwin. Although Darwin platforms support
+// THREADLOCAL variables they are not usable early on during process init when
+// `__sanitizer::Mutex` is used.
+#define SANITIZER_CHECK_DEADLOCKS \
+ (SANITIZER_DEBUG && !SANITIZER_GO && SANITIZER_SUPPORTS_THREADLOCAL && !SANITIZER_APPLE)
+
+#if SANITIZER_CHECK_DEADLOCKS
+struct MutexMeta {
+ MutexType type;
+ const char *name;
+ // The table fixes what mutexes can be locked under what mutexes.
+ // If the entry for MutexTypeFoo contains MutexTypeBar,
+ // then Bar mutex can be locked while under Foo mutex.
+ // Can also contain the special MutexLeaf/MutexMulti marks.
+ MutexType can_lock[10];
+};
+#endif
+
+class CheckedMutex {
+ public:
+ explicit constexpr CheckedMutex(MutexType type)
+#if SANITIZER_CHECK_DEADLOCKS
+ : type_(type)
+#endif
+ {
+ }
+
+ ALWAYS_INLINE void Lock() {
+#if SANITIZER_CHECK_DEADLOCKS
+ LockImpl(GET_CALLER_PC());
+#endif
+ }
+
+ ALWAYS_INLINE void Unlock() {
+#if SANITIZER_CHECK_DEADLOCKS
+ UnlockImpl();
+#endif
+ }
+
+ // Checks that the current thread does not hold any mutexes
+ // (e.g. when returning from a runtime function to user code).
+ static void CheckNoLocks() {
+#if SANITIZER_CHECK_DEADLOCKS
+ CheckNoLocksImpl();
+#endif
+ }
+
+ private:
+#if SANITIZER_CHECK_DEADLOCKS
+ const MutexType type_;
+
+ void LockImpl(uptr pc);
+ void UnlockImpl();
+ static void CheckNoLocksImpl();
+#endif
+};
+
+// Reader-writer mutex.
+// Derive from CheckedMutex for the purposes of EBO.
+// We could make it a field marked with [[no_unique_address]],
+// but this attribute is not supported by some older compilers.
+class SANITIZER_MUTEX Mutex : CheckedMutex {
+ public:
+ explicit constexpr Mutex(MutexType type = MutexUnchecked)
+ : CheckedMutex(type) {}
+
+ void Lock() SANITIZER_ACQUIRE() {
+ CheckedMutex::Lock();
+ u64 reset_mask = ~0ull;
+ u64 state = atomic_load_relaxed(&state_);
+ for (uptr spin_iters = 0;; spin_iters++) {
+ u64 new_state;
+ bool locked = (state & (kWriterLock | kReaderLockMask)) != 0;
+ if (LIKELY(!locked)) {
+ // The mutex is not read-/write-locked, try to lock.
+ new_state = (state | kWriterLock) & reset_mask;
+ } else if (spin_iters > kMaxSpinIters) {
+ // We've spun enough, increment waiting writers count and block.
+ // The counter will be decremented by whoever wakes us.
+ new_state = (state + kWaitingWriterInc) & reset_mask;
+ } else if ((state & kWriterSpinWait) == 0) {
+ // Active spinning, but denote our presence so that unlocking
+ // thread does not wake up other threads.
+ new_state = state | kWriterSpinWait;
+ } else {
+ // Active spinning.
+ state = atomic_load(&state_, memory_order_relaxed);
+ continue;
+ }
+ if (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state,
+ memory_order_acquire)))
+ continue;
+ if (LIKELY(!locked))
+ return; // We've locked the mutex.
+ if (spin_iters > kMaxSpinIters) {
+ // We've incremented waiting writers, so now block.
+ writers_.Wait();
+ spin_iters = 0;
+ } else {
+ // We've set kWriterSpinWait, but we are still in active spinning.
+ }
+ // We either blocked and were unblocked,
+ // or we just spun but set kWriterSpinWait.
+ // Either way we need to reset kWriterSpinWait
+ // next time we take the lock or block again.
+ reset_mask = ~kWriterSpinWait;
+ state = atomic_load(&state_, memory_order_relaxed);
+ DCHECK_NE(state & kWriterSpinWait, 0);
+ }
+ }
+
+ bool TryLock() SANITIZER_TRY_ACQUIRE(true) {
+ u64 state = atomic_load_relaxed(&state_);
+ for (;;) {
+ if (UNLIKELY(state & (kWriterLock | kReaderLockMask)))
+ return false;
+ // The mutex is not read-/write-locked, try to lock.
+ if (LIKELY(atomic_compare_exchange_weak(
+ &state_, &state, state | kWriterLock, memory_order_acquire))) {
+ CheckedMutex::Lock();
+ return true;
+ }
+ }
+ }
+
+ void Unlock() SANITIZER_RELEASE() {
+ CheckedMutex::Unlock();
+ bool wake_writer;
+ u64 wake_readers;
+ u64 new_state;
+ u64 state = atomic_load_relaxed(&state_);
+ do {
+ DCHECK_NE(state & kWriterLock, 0);
+ DCHECK_EQ(state & kReaderLockMask, 0);
+ new_state = state & ~kWriterLock;
+ wake_writer = (state & (kWriterSpinWait | kReaderSpinWait)) == 0 &&
+ (state & kWaitingWriterMask) != 0;
+ if (wake_writer)
+ new_state = (new_state - kWaitingWriterInc) | kWriterSpinWait;
+ wake_readers =
+ wake_writer || (state & kWriterSpinWait) != 0
+ ? 0
+ : ((state & kWaitingReaderMask) >> kWaitingReaderShift);
+ if (wake_readers)
+ new_state = (new_state & ~kWaitingReaderMask) | kReaderSpinWait;
+ } while (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state,
+ memory_order_release)));
+ if (UNLIKELY(wake_writer))
+ writers_.Post();
+ else if (UNLIKELY(wake_readers))
+ readers_.Post(wake_readers);
+ }
+
+ void ReadLock() SANITIZER_ACQUIRE_SHARED() {
+ CheckedMutex::Lock();
+ u64 reset_mask = ~0ull;
+ u64 state = atomic_load_relaxed(&state_);
+ for (uptr spin_iters = 0;; spin_iters++) {
+ bool locked = (state & kWriterLock) != 0;
+ u64 new_state;
+ if (LIKELY(!locked)) {
+ new_state = (state + kReaderLockInc) & reset_mask;
+ } else if (spin_iters > kMaxSpinIters) {
+ new_state = (state + kWaitingReaderInc) & reset_mask;
+ } else if ((state & kReaderSpinWait) == 0) {
+ // Active spinning, but denote our presence so that unlocking
+ // thread does not wake up other threads.
+ new_state = state | kReaderSpinWait;
+ } else {
+ // Active spinning.
+ state = atomic_load(&state_, memory_order_relaxed);
+ continue;
+ }
+ if (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state,
+ memory_order_acquire)))
+ continue;
+ if (LIKELY(!locked))
+ return; // We've locked the mutex.
+ if (spin_iters > kMaxSpinIters) {
+ // We've incremented waiting readers, so now block.
+ readers_.Wait();
+ spin_iters = 0;
+ } else {
+ // We've set kReaderSpinWait, but we are still in active spinning.
+ }
+ reset_mask = ~kReaderSpinWait;
+ state = atomic_load(&state_, memory_order_relaxed);
+ }
+ }
+
+ void ReadUnlock() SANITIZER_RELEASE_SHARED() {
+ CheckedMutex::Unlock();
+ bool wake;
+ u64 new_state;
+ u64 state = atomic_load_relaxed(&state_);
+ do {
+ DCHECK_NE(state & kReaderLockMask, 0);
+ DCHECK_EQ(state & kWriterLock, 0);
+ new_state = state - kReaderLockInc;
+ wake = (new_state &
+ (kReaderLockMask | kWriterSpinWait | kReaderSpinWait)) == 0 &&
+ (new_state & kWaitingWriterMask) != 0;
+ if (wake)
+ new_state = (new_state - kWaitingWriterInc) | kWriterSpinWait;
+ } while (UNLIKELY(!atomic_compare_exchange_weak(&state_, &state, new_state,
+ memory_order_release)));
+ if (UNLIKELY(wake))
+ writers_.Post();
+ }
+
+ // This function does not guarantee an explicit check that the calling thread
+ // is the thread which owns the mutex. This behavior, while more strictly
+ // correct, causes problems in cases like StopTheWorld, where a parent thread
+ // owns the mutex but a child checks that it is locked. Rather than
+ // maintaining complex state to work around those situations, the check only
+ // checks that the mutex is owned.
+ void CheckWriteLocked() const SANITIZER_CHECK_LOCKED() {
+ CHECK(atomic_load(&state_, memory_order_relaxed) & kWriterLock);
+ }
+
+ void CheckLocked() const SANITIZER_CHECK_LOCKED() { CheckWriteLocked(); }
+
+ void CheckReadLocked() const SANITIZER_CHECK_LOCKED() {
+ CHECK(atomic_load(&state_, memory_order_relaxed) & kReaderLockMask);
+ }
+
+ private:
+ atomic_uint64_t state_ = {0};
+ Semaphore writers_;
+ Semaphore readers_;
+
+ // The state has 3 counters:
+ // - number of readers holding the lock,
+ // if non zero, the mutex is read-locked
+ // - number of waiting readers,
+ // if not zero, the mutex is write-locked
+ // - number of waiting writers,
+ // if non zero, the mutex is read- or write-locked
+ // And 2 flags:
+ // - writer lock
+ // if set, the mutex is write-locked
+ // - a writer is awake and spin-waiting
+ // the flag is used to prevent thundering herd problem
+ // (new writers are not woken if this flag is set)
+ // - a reader is awake and spin-waiting
+ //
+ // Both writers and readers use active spinning before blocking.
+ // But readers are more aggressive and always take the mutex
+ // if there are any other readers.
+ // After wake up both writers and readers compete to lock the
+ // mutex again. This is needed to allow repeated locks even in presence
+ // of other blocked threads.
+ static constexpr u64 kCounterWidth = 20;
+ static constexpr u64 kReaderLockShift = 0;
+ static constexpr u64 kReaderLockInc = 1ull << kReaderLockShift;
+ static constexpr u64 kReaderLockMask = ((1ull << kCounterWidth) - 1)
+ << kReaderLockShift;
+ static constexpr u64 kWaitingReaderShift = kCounterWidth;
+ static constexpr u64 kWaitingReaderInc = 1ull << kWaitingReaderShift;
+ static constexpr u64 kWaitingReaderMask = ((1ull << kCounterWidth) - 1)
+ << kWaitingReaderShift;
+ static constexpr u64 kWaitingWriterShift = 2 * kCounterWidth;
+ static constexpr u64 kWaitingWriterInc = 1ull << kWaitingWriterShift;
+ static constexpr u64 kWaitingWriterMask = ((1ull << kCounterWidth) - 1)
+ << kWaitingWriterShift;
+ static constexpr u64 kWriterLock = 1ull << (3 * kCounterWidth);
+ static constexpr u64 kWriterSpinWait = 1ull << (3 * kCounterWidth + 1);
+ static constexpr u64 kReaderSpinWait = 1ull << (3 * kCounterWidth + 2);
+
+ static constexpr uptr kMaxSpinIters = 1500;
+
+ Mutex(LinkerInitialized) = delete;
+ Mutex(const Mutex &) = delete;
+ void operator=(const Mutex &) = delete;
+};
+
+void FutexWait(atomic_uint32_t *p, u32 cmp);
+void FutexWake(atomic_uint32_t *p, u32 count);
+
+template <typename MutexType>
+class SANITIZER_SCOPED_LOCK GenericScopedLock {
+ public:
+ explicit GenericScopedLock(MutexType *mu) SANITIZER_ACQUIRE(mu) : mu_(mu) {
+ mu_->Lock();
+ }
+
+ ~GenericScopedLock() SANITIZER_RELEASE() { mu_->Unlock(); }
+
+ private:
+ MutexType *mu_;
+
+ GenericScopedLock(const GenericScopedLock &) = delete;
+ void operator=(const GenericScopedLock &) = delete;
+};
+
+template <typename MutexType>
+class SANITIZER_SCOPED_LOCK GenericScopedReadLock {
+ public:
+ explicit GenericScopedReadLock(MutexType *mu) SANITIZER_ACQUIRE(mu)
+ : mu_(mu) {
+ mu_->ReadLock();
+ }
+
+ ~GenericScopedReadLock() SANITIZER_RELEASE() { mu_->ReadUnlock(); }
+
+ private:
+ MutexType *mu_;
+
+ GenericScopedReadLock(const GenericScopedReadLock &) = delete;
+ void operator=(const GenericScopedReadLock &) = delete;
+};
+
+template <typename MutexType>
+class SANITIZER_SCOPED_LOCK GenericScopedRWLock {
+ public:
+ ALWAYS_INLINE explicit GenericScopedRWLock(MutexType *mu, bool write)
+ SANITIZER_ACQUIRE(mu)
+ : mu_(mu), write_(write) {
+ if (write_)
+ mu_->Lock();
+ else
+ mu_->ReadLock();
+ }
+
+ ALWAYS_INLINE ~GenericScopedRWLock() SANITIZER_RELEASE() {
+ if (write_)
+ mu_->Unlock();
+ else
+ mu_->ReadUnlock();
+ }
+
+ private:
+ MutexType *mu_;
+ bool write_;
+
+ GenericScopedRWLock(const GenericScopedRWLock &) = delete;
+ void operator=(const GenericScopedRWLock &) = delete;
+};
+
+typedef GenericScopedLock<StaticSpinMutex> SpinMutexLock;
+typedef GenericScopedLock<Mutex> Lock;
+typedef GenericScopedReadLock<Mutex> ReadLock;
+typedef GenericScopedRWLock<Mutex> RWLock;
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_MUTEX_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_netbsd.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_netbsd.cpp
new file mode 100644
index 00000000000..5e601bdcde1
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_netbsd.cpp
@@ -0,0 +1,351 @@
+//===-- sanitizer_netbsd.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between Sanitizer run-time libraries and implements
+// NetBSD-specific functions from sanitizer_libc.h.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_NETBSD
+
+#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_getauxval.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_mutex.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_procmaps.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <sys/exec.h>
+#include <sys/mman.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <link.h>
+#include <lwp.h>
+#include <pthread.h>
+#include <sched.h>
+#include <signal.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+extern "C" void *__mmap(void *, size_t, int, int, int, int,
+ off_t) SANITIZER_WEAK_ATTRIBUTE;
+extern "C" int __sysctl(const int *, unsigned int, void *, size_t *,
+ const void *, size_t) SANITIZER_WEAK_ATTRIBUTE;
+extern "C" int _sys_close(int) SANITIZER_WEAK_ATTRIBUTE;
+extern "C" int _sys_open(const char *, int, ...) SANITIZER_WEAK_ATTRIBUTE;
+extern "C" ssize_t _sys_read(int, void *, size_t) SANITIZER_WEAK_ATTRIBUTE;
+extern "C" ssize_t _sys_write(int, const void *,
+ size_t) SANITIZER_WEAK_ATTRIBUTE;
+extern "C" int __ftruncate(int, int, off_t) SANITIZER_WEAK_ATTRIBUTE;
+extern "C" ssize_t _sys_readlink(const char *, char *,
+ size_t) SANITIZER_WEAK_ATTRIBUTE;
+extern "C" int _sys_sched_yield() SANITIZER_WEAK_ATTRIBUTE;
+extern "C" int _sys___nanosleep50(const void *,
+ void *) SANITIZER_WEAK_ATTRIBUTE;
+extern "C" int _sys_execve(const char *, char *const[],
+ char *const[]) SANITIZER_WEAK_ATTRIBUTE;
+extern "C" off_t __lseek(int, int, off_t, int) SANITIZER_WEAK_ATTRIBUTE;
+extern "C" int __fork() SANITIZER_WEAK_ATTRIBUTE;
+extern "C" int _sys___sigprocmask14(int, const void *,
+ void *) SANITIZER_WEAK_ATTRIBUTE;
+extern "C" int _sys___wait450(int wpid, int *, int,
+ void *) SANITIZER_WEAK_ATTRIBUTE;
+
+namespace __sanitizer {
+
+static void *GetRealLibcAddress(const char *symbol) {
+ void *real = dlsym(RTLD_NEXT, symbol);
+ if (!real)
+ real = dlsym(RTLD_DEFAULT, symbol);
+ if (!real) {
+ Printf("GetRealLibcAddress failed for symbol=%s", symbol);
+ Die();
+ }
+ return real;
+}
+
+#define _REAL(func, ...) real##_##func(__VA_ARGS__)
+#define DEFINE__REAL(ret_type, func, ...) \
+ static ret_type (*real_##func)(__VA_ARGS__) = NULL; \
+ if (!real_##func) { \
+ real_##func = (ret_type(*)(__VA_ARGS__))GetRealLibcAddress(#func); \
+ } \
+ CHECK(real_##func);
+
+// --------------- sanitizer_libc.h
+uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
+ u64 offset) {
+ CHECK(&__mmap);
+ return (uptr)__mmap(addr, length, prot, flags, fd, 0, offset);
+}
+
+uptr internal_munmap(void *addr, uptr length) {
+ DEFINE__REAL(int, munmap, void *a, uptr b);
+ return _REAL(munmap, addr, length);
+}
+
+uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags,
+ void *new_address) {
+ CHECK(false && "internal_mremap is unimplemented on NetBSD");
+ return 0;
+}
+
+int internal_mprotect(void *addr, uptr length, int prot) {
+ DEFINE__REAL(int, mprotect, void *a, uptr b, int c);
+ return _REAL(mprotect, addr, length, prot);
+}
+
+int internal_madvise(uptr addr, uptr length, int advice) {
+ DEFINE__REAL(int, madvise, void *a, uptr b, int c);
+ return _REAL(madvise, (void *)addr, length, advice);
+}
+
+uptr internal_close(fd_t fd) {
+ CHECK(&_sys_close);
+ return _sys_close(fd);
+}
+
+uptr internal_open(const char *filename, int flags) {
+ CHECK(&_sys_open);
+ return _sys_open(filename, flags);
+}
+
+uptr internal_open(const char *filename, int flags, u32 mode) {
+ CHECK(&_sys_open);
+ return _sys_open(filename, flags, mode);
+}
+
+uptr internal_read(fd_t fd, void *buf, uptr count) {
+ sptr res;
+ CHECK(&_sys_read);
+ HANDLE_EINTR(res, (sptr)_sys_read(fd, buf, (size_t)count));
+ return res;
+}
+
+uptr internal_write(fd_t fd, const void *buf, uptr count) {
+ sptr res;
+ CHECK(&_sys_write);
+ HANDLE_EINTR(res, (sptr)_sys_write(fd, buf, count));
+ return res;
+}
+
+uptr internal_ftruncate(fd_t fd, uptr size) {
+ sptr res;
+ CHECK(&__ftruncate);
+ HANDLE_EINTR(res, __ftruncate(fd, 0, (s64)size));
+ return res;
+}
+
+uptr internal_stat(const char *path, void *buf) {
+ DEFINE__REAL(int, __stat50, const char *a, void *b);
+ return _REAL(__stat50, path, buf);
+}
+
+uptr internal_lstat(const char *path, void *buf) {
+ DEFINE__REAL(int, __lstat50, const char *a, void *b);
+ return _REAL(__lstat50, path, buf);
+}
+
+uptr internal_fstat(fd_t fd, void *buf) {
+ DEFINE__REAL(int, __fstat50, int a, void *b);
+ return _REAL(__fstat50, fd, buf);
+}
+
+uptr internal_filesize(fd_t fd) {
+ struct stat st;
+ if (internal_fstat(fd, &st))
+ return -1;
+ return (uptr)st.st_size;
+}
+
+uptr internal_dup(int oldfd) {
+ DEFINE__REAL(int, dup, int a);
+ return _REAL(dup, oldfd);
+}
+
+uptr internal_dup2(int oldfd, int newfd) {
+ DEFINE__REAL(int, dup2, int a, int b);
+ return _REAL(dup2, oldfd, newfd);
+}
+
+uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
+ CHECK(&_sys_readlink);
+ return (uptr)_sys_readlink(path, buf, bufsize);
+}
+
+uptr internal_unlink(const char *path) {
+ DEFINE__REAL(int, unlink, const char *a);
+ return _REAL(unlink, path);
+}
+
+uptr internal_rename(const char *oldpath, const char *newpath) {
+ DEFINE__REAL(int, rename, const char *a, const char *b);
+ return _REAL(rename, oldpath, newpath);
+}
+
+uptr internal_sched_yield() {
+ CHECK(&_sys_sched_yield);
+ return _sys_sched_yield();
+}
+
+void internal__exit(int exitcode) {
+ DEFINE__REAL(void, _exit, int a);
+ _REAL(_exit, exitcode);
+ Die(); // Unreachable.
+}
+
+void internal_usleep(u64 useconds) {
+ struct timespec ts;
+ ts.tv_sec = useconds / 1000000;
+ ts.tv_nsec = (useconds % 1000000) * 1000;
+ CHECK(&_sys___nanosleep50);
+ _sys___nanosleep50(&ts, &ts);
+}
+
+uptr internal_execve(const char *filename, char *const argv[],
+ char *const envp[]) {
+ CHECK(&_sys_execve);
+ return _sys_execve(filename, argv, envp);
+}
+
+tid_t GetTid() {
+ DEFINE__REAL(int, _lwp_self);
+ return _REAL(_lwp_self);
+}
+
+int TgKill(pid_t pid, tid_t tid, int sig) {
+ DEFINE__REAL(int, _lwp_kill, int a, int b);
+ (void)pid;
+ return _REAL(_lwp_kill, tid, sig);
+}
+
+u64 NanoTime() {
+ timeval tv;
+ DEFINE__REAL(int, __gettimeofday50, void *a, void *b);
+ internal_memset(&tv, 0, sizeof(tv));
+ _REAL(__gettimeofday50, &tv, 0);
+ return (u64)tv.tv_sec * 1000 * 1000 * 1000 + tv.tv_usec * 1000;
+}
+
+uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
+ DEFINE__REAL(int, __clock_gettime50, __sanitizer_clockid_t a, void *b);
+ return _REAL(__clock_gettime50, clk_id, tp);
+}
+
+uptr internal_ptrace(int request, int pid, void *addr, int data) {
+ DEFINE__REAL(int, ptrace, int a, int b, void *c, int d);
+ return _REAL(ptrace, request, pid, addr, data);
+}
+
+uptr internal_waitpid(int pid, int *status, int options) {
+ CHECK(&_sys___wait450);
+ return _sys___wait450(pid, status, options, 0 /* rusage */);
+}
+
+uptr internal_getpid() {
+ DEFINE__REAL(int, getpid);
+ return _REAL(getpid);
+}
+
+uptr internal_getppid() {
+ DEFINE__REAL(int, getppid);
+ return _REAL(getppid);
+}
+
+int internal_dlinfo(void *handle, int request, void *p) {
+ DEFINE__REAL(int, dlinfo, void *a, int b, void *c);
+ return _REAL(dlinfo, handle, request, p);
+}
+
+uptr internal_getdents(fd_t fd, void *dirp, unsigned int count) {
+ DEFINE__REAL(int, __getdents30, int a, void *b, size_t c);
+ return _REAL(__getdents30, fd, dirp, count);
+}
+
+uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
+ CHECK(&__lseek);
+ return __lseek(fd, 0, offset, whence);
+}
+
+uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
+ Printf("internal_prctl not implemented for NetBSD");
+ Die();
+ return 0;
+}
+
+uptr internal_sigaltstack(const void *ss, void *oss) {
+ DEFINE__REAL(int, __sigaltstack14, const void *a, void *b);
+ return _REAL(__sigaltstack14, ss, oss);
+}
+
+int internal_fork() {
+ CHECK(&__fork);
+ return __fork();
+}
+
+int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
+ uptr *oldlenp, const void *newp, uptr newlen) {
+ CHECK(&__sysctl);
+ return __sysctl(name, namelen, oldp, (size_t *)oldlenp, newp, (size_t)newlen);
+}
+
+int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
+ const void *newp, uptr newlen) {
+ DEFINE__REAL(int, sysctlbyname, const char *a, void *b, size_t *c,
+ const void *d, size_t e);
+ return _REAL(sysctlbyname, sname, oldp, (size_t *)oldlenp, newp,
+ (size_t)newlen);
+}
+
+uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
+ __sanitizer_sigset_t *oldset) {
+ CHECK(&_sys___sigprocmask14);
+ return _sys___sigprocmask14(how, set, oldset);
+}
+
+void internal_sigfillset(__sanitizer_sigset_t *set) {
+ DEFINE__REAL(int, __sigfillset14, const void *a);
+ (void)_REAL(__sigfillset14, set);
+}
+
+void internal_sigemptyset(__sanitizer_sigset_t *set) {
+ DEFINE__REAL(int, __sigemptyset14, const void *a);
+ (void)_REAL(__sigemptyset14, set);
+}
+
+void internal_sigdelset(__sanitizer_sigset_t *set, int signo) {
+ DEFINE__REAL(int, __sigdelset14, const void *a, int b);
+ (void)_REAL(__sigdelset14, set, signo);
+}
+
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags,
+ void *arg) {
+ DEFINE__REAL(int, clone, int (*a)(void *b), void *c, int d, void *e);
+
+ return _REAL(clone, fn, child_stack, flags, arg);
+}
+
+} // namespace __sanitizer
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_placement_new.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_placement_new.h
new file mode 100644
index 00000000000..1ceb8b90926
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_placement_new.h
@@ -0,0 +1,24 @@
+//===-- sanitizer_placement_new.h -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+//
+// The file provides 'placement new'.
+// Do not include it into header files, only into source files.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_PLACEMENT_NEW_H
+#define SANITIZER_PLACEMENT_NEW_H
+
+#include "sanitizer_internal_defs.h"
+
+inline void *operator new(__sanitizer::operator_new_size_type sz, void *p) {
+ return p;
+}
+
+#endif // SANITIZER_PLACEMENT_NEW_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform.h
new file mode 100644
index 00000000000..764996e5735
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform.h
@@ -0,0 +1,448 @@
+//===-- sanitizer_platform.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Common platform macros.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_PLATFORM_H
+#define SANITIZER_PLATFORM_H
+
+#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
+ !defined(__APPLE__) && !defined(_WIN32) && !defined(__Fuchsia__) && \
+ !(defined(__sun__) && defined(__svr4__))
+# error "This operating system is not supported"
+#endif
+
+// Get __GLIBC__ on a glibc platform. Exclude Android: features.h includes C
+// function declarations into a .S file which doesn't compile.
+// https://crbug.com/1162741
+#if __has_include(<features.h>) && !defined(__ANDROID__)
+# include <features.h>
+#endif
+
+#if defined(__linux__)
+# define SANITIZER_LINUX 1
+#else
+# define SANITIZER_LINUX 0
+#endif
+
+#if defined(__GLIBC__)
+# define SANITIZER_GLIBC 1
+#else
+# define SANITIZER_GLIBC 0
+#endif
+
+#if defined(__FreeBSD__)
+# define SANITIZER_FREEBSD 1
+#else
+# define SANITIZER_FREEBSD 0
+#endif
+
+#if defined(__NetBSD__)
+# define SANITIZER_NETBSD 1
+#else
+# define SANITIZER_NETBSD 0
+#endif
+
+#if defined(__sun__) && defined(__svr4__)
+# define SANITIZER_SOLARIS 1
+#else
+# define SANITIZER_SOLARIS 0
+#endif
+
+// - SANITIZER_APPLE: all Apple code
+// - TARGET_OS_OSX: macOS
+// - SANITIZER_IOS: devices (iOS and iOS-like)
+// - SANITIZER_WATCHOS
+// - SANITIZER_TVOS
+// - SANITIZER_IOSSIM: simulators (iOS and iOS-like)
+// - SANITIZER_DRIVERKIT
+#if defined(__APPLE__)
+# define SANITIZER_APPLE 1
+# include <TargetConditionals.h>
+# if TARGET_OS_OSX
+# define SANITIZER_OSX 1
+# else
+# define SANITIZER_OSX 0
+# endif
+# if TARGET_OS_IPHONE
+# define SANITIZER_IOS 1
+# else
+# define SANITIZER_IOS 0
+# endif
+# if TARGET_OS_WATCH
+# define SANITIZER_WATCHOS 1
+# else
+# define SANITIZER_WATCHOS 0
+# endif
+# if TARGET_OS_TV
+# define SANITIZER_TVOS 1
+# else
+# define SANITIZER_TVOS 0
+# endif
+# if TARGET_OS_SIMULATOR
+# define SANITIZER_IOSSIM 1
+# else
+# define SANITIZER_IOSSIM 0
+# endif
+# if defined(TARGET_OS_DRIVERKIT) && TARGET_OS_DRIVERKIT
+# define SANITIZER_DRIVERKIT 1
+# else
+# define SANITIZER_DRIVERKIT 0
+# endif
+#else
+# define SANITIZER_APPLE 0
+# define SANITIZER_OSX 0
+# define SANITIZER_IOS 0
+# define SANITIZER_WATCHOS 0
+# define SANITIZER_TVOS 0
+# define SANITIZER_IOSSIM 0
+# define SANITIZER_DRIVERKIT 0
+#endif
+
+#if defined(_WIN32)
+# define SANITIZER_WINDOWS 1
+#else
+# define SANITIZER_WINDOWS 0
+#endif
+
+#if defined(_WIN64)
+# define SANITIZER_WINDOWS64 1
+#else
+# define SANITIZER_WINDOWS64 0
+#endif
+
+#if defined(__ANDROID__)
+# define SANITIZER_ANDROID 1
+#else
+# define SANITIZER_ANDROID 0
+#endif
+
+#if defined(__Fuchsia__)
+# define SANITIZER_FUCHSIA 1
+#else
+# define SANITIZER_FUCHSIA 0
+#endif
+
+// Assume linux that is not glibc or android is musl libc.
+#if SANITIZER_LINUX && !SANITIZER_GLIBC && !SANITIZER_ANDROID
+# define SANITIZER_MUSL 1
+#else
+# define SANITIZER_MUSL 0
+#endif
+
+#define SANITIZER_POSIX \
+ (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \
+ SANITIZER_NETBSD || SANITIZER_SOLARIS)
+
+#if __LP64__ || defined(_WIN64)
+# define SANITIZER_WORDSIZE 64
+#else
+# define SANITIZER_WORDSIZE 32
+#endif
+
+#if SANITIZER_WORDSIZE == 64
+# define FIRST_32_SECOND_64(a, b) (b)
+#else
+# define FIRST_32_SECOND_64(a, b) (a)
+#endif
+
+#if defined(__x86_64__) && !defined(_LP64)
+# define SANITIZER_X32 1
+#else
+# define SANITIZER_X32 0
+#endif
+
+#if defined(__x86_64__) || defined(_M_X64)
+# define SANITIZER_X64 1
+#else
+# define SANITIZER_X64 0
+#endif
+
+#if defined(__i386__) || defined(_M_IX86)
+# define SANITIZER_I386 1
+#else
+# define SANITIZER_I386 0
+#endif
+
+#if defined(__mips__)
+# define SANITIZER_MIPS 1
+# if defined(__mips64) && _MIPS_SIM == _ABI64
+# define SANITIZER_MIPS32 0
+# define SANITIZER_MIPS64 1
+# else
+# define SANITIZER_MIPS32 1
+# define SANITIZER_MIPS64 0
+# endif
+#else
+# define SANITIZER_MIPS 0
+# define SANITIZER_MIPS32 0
+# define SANITIZER_MIPS64 0
+#endif
+
+#if defined(__s390__)
+# define SANITIZER_S390 1
+# if defined(__s390x__)
+# define SANITIZER_S390_31 0
+# define SANITIZER_S390_64 1
+# else
+# define SANITIZER_S390_31 1
+# define SANITIZER_S390_64 0
+# endif
+#else
+# define SANITIZER_S390 0
+# define SANITIZER_S390_31 0
+# define SANITIZER_S390_64 0
+#endif
+
+#if defined(__sparc__)
+# define SANITIZER_SPARC 1
+# if defined(__arch64__)
+# define SANITIZER_SPARC32 0
+# define SANITIZER_SPARC64 1
+# else
+# define SANITIZER_SPARC32 1
+# define SANITIZER_SPARC64 0
+# endif
+#else
+# define SANITIZER_SPARC 0
+# define SANITIZER_SPARC32 0
+# define SANITIZER_SPARC64 0
+#endif
+
+#if defined(__powerpc__)
+# define SANITIZER_PPC 1
+# if defined(__powerpc64__)
+# define SANITIZER_PPC32 0
+# define SANITIZER_PPC64 1
+// 64-bit PPC has two ABIs (v1 and v2). The old powerpc64 target is
+// big-endian, and uses v1 ABI (known for its function descriptors),
+// while the new powerpc64le target is little-endian and uses v2.
+// In theory, you could convince gcc to compile for their evil twins
+// (eg. big-endian v2), but you won't find such combinations in the wild
+// (it'd require bootstrapping a whole system, which would be quite painful
+// - there's no target triple for that). LLVM doesn't support them either.
+# if _CALL_ELF == 2
+# define SANITIZER_PPC64V1 0
+# define SANITIZER_PPC64V2 1
+# else
+# define SANITIZER_PPC64V1 1
+# define SANITIZER_PPC64V2 0
+# endif
+# else
+# define SANITIZER_PPC32 1
+# define SANITIZER_PPC64 0
+# define SANITIZER_PPC64V1 0
+# define SANITIZER_PPC64V2 0
+# endif
+#else
+# define SANITIZER_PPC 0
+# define SANITIZER_PPC32 0
+# define SANITIZER_PPC64 0
+# define SANITIZER_PPC64V1 0
+# define SANITIZER_PPC64V2 0
+#endif
+
+#if defined(__arm__) || defined(_M_ARM)
+# define SANITIZER_ARM 1
+#else
+# define SANITIZER_ARM 0
+#endif
+
+#if defined(__aarch64__) || defined(_M_ARM64)
+# define SANITIZER_ARM64 1
+#else
+# define SANITIZER_ARM64 0
+#endif
+
+#if SANITIZER_SOLARIS && SANITIZER_WORDSIZE == 32
+# define SANITIZER_SOLARIS32 1
+#else
+# define SANITIZER_SOLARIS32 0
+#endif
+
+#if defined(__riscv) && (__riscv_xlen == 64)
+# define SANITIZER_RISCV64 1
+#else
+# define SANITIZER_RISCV64 0
+#endif
+
+#if defined(__loongarch_lp64)
+# define SANITIZER_LOONGARCH64 1
+#else
+# define SANITIZER_LOONGARCH64 0
+#endif
+
+// By default we allow to use SizeClassAllocator64 on 64-bit platform.
+// But in some cases SizeClassAllocator64 does not work well and we need to
+// fallback to SizeClassAllocator32.
+// For such platforms build this code with -DSANITIZER_CAN_USE_ALLOCATOR64=0 or
+// change the definition of SANITIZER_CAN_USE_ALLOCATOR64 here.
+#ifndef SANITIZER_CAN_USE_ALLOCATOR64
+# if SANITIZER_RISCV64 || SANITIZER_IOS
+# define SANITIZER_CAN_USE_ALLOCATOR64 0
+# elif defined(__mips64) || defined(__hexagon__)
+# define SANITIZER_CAN_USE_ALLOCATOR64 0
+# else
+# define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64)
+# endif
+#endif
+
+// The range of addresses which can be returned my mmap.
+// FIXME: this value should be different on different platforms. Larger values
+// will still work but will consume more memory for TwoLevelByteMap.
+#if defined(__mips__)
+# if SANITIZER_GO && defined(__mips64)
+# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
+# else
+# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 40)
+# endif
+#elif SANITIZER_RISCV64
+# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 38)
+#elif defined(__aarch64__)
+# if SANITIZER_APPLE
+# if SANITIZER_OSX || SANITIZER_IOSSIM
+# define SANITIZER_MMAP_RANGE_SIZE \
+ FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
+# else
+// Darwin iOS/ARM64 has a 36-bit VMA, 64GiB VM
+# define SANITIZER_MMAP_RANGE_SIZE \
+ FIRST_32_SECOND_64(1ULL << 32, 1ULL << 36)
+# endif
+# else
+# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 48)
+# endif
+#elif defined(__sparc__)
+# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 52)
+#else
+# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
+#endif
+
+// Whether the addresses are sign-extended from the VMA range to the word.
+// The SPARC64 Linux port implements this to split the VMA space into two
+// non-contiguous halves with a huge hole in the middle.
+#if defined(__sparc__) && SANITIZER_WORDSIZE == 64
+# define SANITIZER_SIGN_EXTENDED_ADDRESSES 1
+#else
+# define SANITIZER_SIGN_EXTENDED_ADDRESSES 0
+#endif
+
+// udi16 syscalls can only be used when the following conditions are
+// met:
+// * target is one of arm32, x86-32, sparc32, sh or m68k
+// * libc version is libc5, glibc-2.0, glibc-2.1 or glibc-2.2 to 2.15
+// built against > linux-2.2 kernel headers
+// Since we don't want to include libc headers here, we check the
+// target only.
+#if defined(__arm__) || SANITIZER_X32 || defined(__sparc__)
+# define SANITIZER_USES_UID16_SYSCALLS 1
+#else
+# define SANITIZER_USES_UID16_SYSCALLS 0
+#endif
+
+#if defined(__mips__)
+# define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 10)
+#else
+# define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 12)
+#endif
+
+/// \macro MSC_PREREQ
+/// \brief Is the compiler MSVC of at least the specified version?
+/// The common \param version values to check for are:
+/// * 1800: Microsoft Visual Studio 2013 / 12.0
+/// * 1900: Microsoft Visual Studio 2015 / 14.0
+#ifdef _MSC_VER
+# define MSC_PREREQ(version) (_MSC_VER >= (version))
+#else
+# define MSC_PREREQ(version) 0
+#endif
+
+#if SANITIZER_APPLE && defined(__x86_64__)
+# define SANITIZER_NON_UNIQUE_TYPEINFO 0
+#else
+# define SANITIZER_NON_UNIQUE_TYPEINFO 1
+#endif
+
+// On linux, some architectures had an ABI transition from 64-bit long double
+// (ie. same as double) to 128-bit long double. On those, glibc symbols
+// involving long doubles come in two versions, and we need to pass the
+// correct one to dlvsym when intercepting them.
+#if SANITIZER_LINUX && (SANITIZER_S390 || SANITIZER_PPC32 || SANITIZER_PPC64V1)
+# define SANITIZER_NLDBL_VERSION "GLIBC_2.4"
+#endif
+
+#if SANITIZER_GO == 0
+# define SANITIZER_GO 0
+#endif
+
+// On PowerPC and ARM Thumb, calling pthread_exit() causes LSan to detect leaks.
+// pthread_exit() performs unwinding that leads to dlopen'ing libgcc_s.so.
+// dlopen mallocs "libgcc_s.so" string which confuses LSan, it fails to realize
+// that this allocation happens in dynamic linker and should be ignored.
+#if SANITIZER_PPC || defined(__thumb__)
+# define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 1
+#else
+# define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 0
+#endif
+
+#if SANITIZER_FREEBSD || SANITIZER_APPLE || SANITIZER_NETBSD || SANITIZER_SOLARIS
+# define SANITIZER_MADVISE_DONTNEED MADV_FREE
+#else
+# define SANITIZER_MADVISE_DONTNEED MADV_DONTNEED
+#endif
+
+// Older gcc have issues aligning to a constexpr, and require an integer.
+// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56859 among others.
+#if defined(__powerpc__) || defined(__powerpc64__)
+# define SANITIZER_CACHE_LINE_SIZE 128
+#else
+# define SANITIZER_CACHE_LINE_SIZE 64
+#endif
+
+// Enable offline markup symbolizer for Fuchsia.
+#if SANITIZER_FUCHSIA
+# define SANITIZER_SYMBOLIZER_MARKUP 1
+#else
+# define SANITIZER_SYMBOLIZER_MARKUP 0
+#endif
+
+// Enable ability to support sanitizer initialization that is
+// compatible with the sanitizer library being loaded via
+// `dlopen()`.
+#if SANITIZER_APPLE
+# define SANITIZER_SUPPORTS_INIT_FOR_DLOPEN 1
+#else
+# define SANITIZER_SUPPORTS_INIT_FOR_DLOPEN 0
+#endif
+
+// SANITIZER_SUPPORTS_THREADLOCAL
+// 1 - THREADLOCAL macro is supported by target
+// 0 - THREADLOCAL macro is not supported by target
+#ifndef __has_feature
+// TODO: Support other compilers here
+# define SANITIZER_SUPPORTS_THREADLOCAL 1
+#else
+# if __has_feature(tls)
+# define SANITIZER_SUPPORTS_THREADLOCAL 1
+# else
+# define SANITIZER_SUPPORTS_THREADLOCAL 0
+# endif
+#endif
+
+#if defined(__thumb__) && defined(__linux__)
+// Workaround for
+// https://lab.llvm.org/buildbot/#/builders/clang-thumbv7-full-2stage
+// or
+// https://lab.llvm.org/staging/#/builders/clang-thumbv7-full-2stage
+// It fails *rss_limit_mb_test* without meaningful errors.
+# define SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 1
+#else
+# define SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 0
+#endif
+
+#endif // SANITIZER_PLATFORM_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
new file mode 100644
index 00000000000..b06953a3adf
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -0,0 +1,617 @@
+//===-- sanitizer_platform_interceptors.h -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines macro telling whether sanitizer tools can/should intercept
+// given library functions on a given platform.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
+#define SANITIZER_PLATFORM_INTERCEPTORS_H
+
+#include "sanitizer_glibc_version.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform.h"
+
+#if SANITIZER_POSIX
+#define SI_POSIX 1
+#else
+#define SI_POSIX 0
+#endif
+
+#if !SANITIZER_WINDOWS
+#define SI_WINDOWS 0
+#else
+#define SI_WINDOWS 1
+#endif
+
+#if SI_WINDOWS && SI_POSIX
+#error "Windows is not POSIX!"
+#endif
+
+#if SI_POSIX
+#include "sanitizer_platform_limits_freebsd.h"
+#include "sanitizer_platform_limits_netbsd.h"
+#include "sanitizer_platform_limits_posix.h"
+#include "sanitizer_platform_limits_solaris.h"
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#define SI_LINUX_NOT_ANDROID 1
+#else
+#define SI_LINUX_NOT_ANDROID 0
+#endif
+
+#if SANITIZER_GLIBC
+#define SI_GLIBC 1
+#else
+#define SI_GLIBC 0
+#endif
+
+#if SANITIZER_ANDROID
+#define SI_ANDROID 1
+#else
+#define SI_ANDROID 0
+#endif
+
+#if SANITIZER_FREEBSD
+#define SI_FREEBSD 1
+#else
+#define SI_FREEBSD 0
+#endif
+
+#if SANITIZER_NETBSD
+#define SI_NETBSD 1
+#else
+#define SI_NETBSD 0
+#endif
+
+#if SANITIZER_LINUX
+#define SI_LINUX 1
+#else
+#define SI_LINUX 0
+#endif
+
+#if SANITIZER_APPLE
+#define SI_MAC 1
+#define SI_NOT_MAC 0
+#else
+#define SI_MAC 0
+#define SI_NOT_MAC 1
+#endif
+
+#if SANITIZER_IOS
+#define SI_IOS 1
+#else
+#define SI_IOS 0
+#endif
+
+#if SANITIZER_IOSSIM
+#define SI_IOSSIM 1
+#else
+#define SI_IOSSIM 0
+#endif
+
+#if SANITIZER_WATCHOS
+#define SI_WATCHOS 1
+#else
+#define SI_WATCHOS 0
+#endif
+
+#if SANITIZER_TVOS
+#define SI_TVOS 1
+#else
+#define SI_TVOS 0
+#endif
+
+#if SANITIZER_FUCHSIA
+#define SI_NOT_FUCHSIA 0
+#else
+#define SI_NOT_FUCHSIA 1
+#endif
+
+#if SANITIZER_SOLARIS
+#define SI_SOLARIS 1
+#else
+#define SI_SOLARIS 0
+#endif
+
+#if SANITIZER_SOLARIS32
+#define SI_SOLARIS32 1
+#else
+#define SI_SOLARIS32 0
+#endif
+
+#if SANITIZER_POSIX && !SANITIZER_APPLE
+#define SI_POSIX_NOT_MAC 1
+#else
+#define SI_POSIX_NOT_MAC 0
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_FREEBSD
+#define SI_LINUX_NOT_FREEBSD 1
+#else
+#define SI_LINUX_NOT_FREEBSD 0
+#endif
+
+#define SANITIZER_INTERCEPT_STRLEN SI_NOT_FUCHSIA
+#define SANITIZER_INTERCEPT_STRNLEN (SI_NOT_MAC && SI_NOT_FUCHSIA)
+#define SANITIZER_INTERCEPT_STRCMP SI_NOT_FUCHSIA
+#define SANITIZER_INTERCEPT_STRSTR SI_NOT_FUCHSIA
+#define SANITIZER_INTERCEPT_STRCASESTR SI_POSIX
+#define SANITIZER_INTERCEPT_STRTOK SI_NOT_FUCHSIA
+#define SANITIZER_INTERCEPT_STRCHR SI_NOT_FUCHSIA
+#define SANITIZER_INTERCEPT_STRCHRNUL SI_POSIX_NOT_MAC
+#define SANITIZER_INTERCEPT_STRRCHR SI_NOT_FUCHSIA
+#define SANITIZER_INTERCEPT_STRSPN SI_NOT_FUCHSIA
+#define SANITIZER_INTERCEPT_STRPBRK SI_NOT_FUCHSIA
+#define SANITIZER_INTERCEPT_TEXTDOMAIN SI_LINUX_NOT_ANDROID || SI_SOLARIS
+#define SANITIZER_INTERCEPT_STRCASECMP SI_POSIX
+#define SANITIZER_INTERCEPT_MEMSET 1
+#define SANITIZER_INTERCEPT_MEMMOVE 1
+#define SANITIZER_INTERCEPT_MEMCPY 1
+#define SANITIZER_INTERCEPT_MEMCMP SI_NOT_FUCHSIA
+#define SANITIZER_INTERCEPT_BCMP \
+ SANITIZER_INTERCEPT_MEMCMP && \
+ ((SI_POSIX && _GNU_SOURCE) || SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_STRNDUP SI_POSIX
+#define SANITIZER_INTERCEPT___STRNDUP SI_GLIBC
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
+ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070
+#define SI_MAC_DEPLOYMENT_BELOW_10_7 1
+#else
+#define SI_MAC_DEPLOYMENT_BELOW_10_7 0
+#endif
+// memmem on Darwin doesn't exist on 10.6
+// FIXME: enable memmem on Windows.
+#define SANITIZER_INTERCEPT_MEMMEM (SI_POSIX && !SI_MAC_DEPLOYMENT_BELOW_10_7)
+#define SANITIZER_INTERCEPT_MEMCHR SI_NOT_FUCHSIA
+#define SANITIZER_INTERCEPT_MEMRCHR (SI_FREEBSD || SI_LINUX || SI_NETBSD)
+
+#define SANITIZER_INTERCEPT_READ SI_POSIX
+#define SANITIZER_INTERCEPT_PREAD SI_POSIX
+#define SANITIZER_INTERCEPT_WRITE SI_POSIX
+#define SANITIZER_INTERCEPT_PWRITE SI_POSIX
+
+#define SANITIZER_INTERCEPT_FREAD SI_POSIX
+#define SANITIZER_INTERCEPT_FWRITE SI_POSIX
+#define SANITIZER_INTERCEPT_FGETS SI_POSIX
+#define SANITIZER_INTERCEPT_FPUTS SI_POSIX
+#define SANITIZER_INTERCEPT_PUTS SI_POSIX
+
+#define SANITIZER_INTERCEPT_PREAD64 (SI_GLIBC || SI_SOLARIS32)
+#define SANITIZER_INTERCEPT_PWRITE64 (SI_GLIBC || SI_SOLARIS32)
+
+#define SANITIZER_INTERCEPT_READV SI_POSIX
+#define SANITIZER_INTERCEPT_WRITEV SI_POSIX
+
+#define SANITIZER_INTERCEPT_PREADV \
+ (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID)
+#define SANITIZER_INTERCEPT_PWRITEV SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_PREADV64 SI_GLIBC
+#define SANITIZER_INTERCEPT_PWRITEV64 SI_GLIBC
+
+#define SANITIZER_INTERCEPT_PRCTL SI_LINUX
+
+#define SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS SI_POSIX
+#define SANITIZER_INTERCEPT_STRPTIME SI_POSIX
+
+#define SANITIZER_INTERCEPT_SCANF SI_POSIX
+#define SANITIZER_INTERCEPT_ISOC99_SCANF SI_GLIBC
+
+#ifndef SANITIZER_INTERCEPT_PRINTF
+#define SANITIZER_INTERCEPT_PRINTF SI_POSIX
+#define SANITIZER_INTERCEPT_PRINTF_L (SI_FREEBSD || SI_NETBSD)
+#define SANITIZER_INTERCEPT_ISOC99_PRINTF SI_GLIBC
+#endif
+
+#define SANITIZER_INTERCEPT___PRINTF_CHK \
+ (SANITIZER_INTERCEPT_PRINTF && SI_GLIBC)
+
+#define SANITIZER_INTERCEPT_FREXP SI_NOT_FUCHSIA
+#define SANITIZER_INTERCEPT_FREXPF_FREXPL SI_POSIX
+
+#define SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS SI_POSIX
+#define SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS \
+ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_GETPWENT \
+ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_FGETGRENT_R (SI_GLIBC || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_FGETPWENT SI_LINUX_NOT_ANDROID || SI_SOLARIS
+#define SANITIZER_INTERCEPT_GETPWENT_R \
+ (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_FGETPWENT_R (SI_FREEBSD || SI_GLIBC || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_SETPWENT \
+ (SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_CLOCK_GETTIME \
+ (SI_FREEBSD || SI_NETBSD || SI_LINUX || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID \
+ (SI_LINUX || SI_FREEBSD || SI_NETBSD)
+#define SANITIZER_INTERCEPT_GETITIMER SI_POSIX
+#define SANITIZER_INTERCEPT_TIME SI_POSIX
+#define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_GLOB64 SI_GLIBC
+#define SANITIZER_INTERCEPT___B64_TO SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_DN_COMP_EXPAND 0
+#define SANITIZER_INTERCEPT_POSIX_SPAWN SI_POSIX
+#define SANITIZER_INTERCEPT_WAIT SI_POSIX
+#define SANITIZER_INTERCEPT_INET SI_POSIX
+#define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM SI_POSIX
+#define SANITIZER_INTERCEPT_GETADDRINFO SI_POSIX
+#define SANITIZER_INTERCEPT_GETNAMEINFO SI_POSIX
+#define SANITIZER_INTERCEPT_GETSOCKNAME SI_POSIX
+#define SANITIZER_INTERCEPT_GETHOSTBYNAME SI_POSIX
+#define SANITIZER_INTERCEPT_GETHOSTBYNAME2 SI_POSIX && !SI_SOLARIS
+#define SANITIZER_INTERCEPT_GETHOSTBYNAME_R \
+ (SI_FREEBSD || SI_LINUX || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_GETHOSTBYNAME2_R \
+ (SI_FREEBSD || SI_LINUX_NOT_ANDROID)
+#define SANITIZER_INTERCEPT_GETHOSTBYADDR_R \
+ (SI_FREEBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_GETHOSTENT_R (SI_FREEBSD || SI_GLIBC || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_GETSOCKOPT SI_POSIX
+#define SANITIZER_INTERCEPT_ACCEPT SI_POSIX
+#define SANITIZER_INTERCEPT_ACCEPT4 \
+ (SI_LINUX_NOT_ANDROID || SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_PACCEPT SI_NETBSD
+#define SANITIZER_INTERCEPT_MODF SI_POSIX
+#define SANITIZER_INTERCEPT_RECVMSG SI_POSIX
+#define SANITIZER_INTERCEPT_SENDMSG SI_POSIX
+#define SANITIZER_INTERCEPT_RECVMMSG SI_LINUX
+#define SANITIZER_INTERCEPT_SENDMMSG SI_LINUX
+#define SANITIZER_INTERCEPT_SYSMSG SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_GETPEERNAME SI_POSIX
+#define SANITIZER_INTERCEPT_IOCTL SI_POSIX
+#define SANITIZER_INTERCEPT_INET_ATON SI_POSIX
+#define SANITIZER_INTERCEPT_SYSINFO SI_LINUX
+#define SANITIZER_INTERCEPT_READDIR SI_POSIX
+#define SANITIZER_INTERCEPT_READDIR64 SI_GLIBC || SI_SOLARIS32
+#if SI_LINUX_NOT_ANDROID && \
+ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
+ defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
+ defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64)
+#define SANITIZER_INTERCEPT_PTRACE 1
+#else
+#define SANITIZER_INTERCEPT_PTRACE 0
+#endif
+#define SANITIZER_INTERCEPT_SETLOCALE SI_POSIX
+#define SANITIZER_INTERCEPT_GETCWD SI_POSIX
+#define SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_STRTOIMAX SI_POSIX
+#define SANITIZER_INTERCEPT_MBSTOWCS SI_POSIX
+#define SANITIZER_INTERCEPT_MBSNRTOWCS \
+ (SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_WCSTOMBS SI_POSIX
+#define SANITIZER_INTERCEPT_STRXFRM SI_POSIX
+#define SANITIZER_INTERCEPT___STRXFRM_L SI_LINUX
+#define SANITIZER_INTERCEPT_WCSXFRM SI_POSIX
+#define SANITIZER_INTERCEPT___WCSXFRM_L SI_LINUX
+#define SANITIZER_INTERCEPT_WCSNRTOMBS \
+ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_WCRTOMB \
+ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_WCTOMB \
+ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_TCGETATTR SI_LINUX_NOT_ANDROID || SI_SOLARIS
+#define SANITIZER_INTERCEPT_REALPATH SI_POSIX
+#define SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME (SI_GLIBC || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_CONFSTR \
+ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_SCHED_GETAFFINITY SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_SCHED_GETPARAM SI_LINUX_NOT_ANDROID || SI_SOLARIS
+#define SANITIZER_INTERCEPT_STRERROR SI_POSIX
+#define SANITIZER_INTERCEPT_STRERROR_R SI_POSIX
+#define SANITIZER_INTERCEPT_XPG_STRERROR_R SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_SCANDIR \
+ (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_SCANDIR64 SI_GLIBC || SI_SOLARIS32
+#define SANITIZER_INTERCEPT_GETGROUPS SI_POSIX
+#define SANITIZER_INTERCEPT_POLL SI_POSIX
+#define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID || SI_SOLARIS
+#define SANITIZER_INTERCEPT_WORDEXP \
+ (SI_FREEBSD || SI_NETBSD || (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID || \
+ SI_SOLARIS)
+#define SANITIZER_INTERCEPT_SIGWAIT SI_POSIX
+#define SANITIZER_INTERCEPT_SIGWAITINFO SI_LINUX_NOT_ANDROID || SI_SOLARIS
+#define SANITIZER_INTERCEPT_SIGTIMEDWAIT SI_LINUX_NOT_ANDROID || SI_SOLARIS
+#define SANITIZER_INTERCEPT_SIGSETOPS \
+ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_SIGSET_LOGICOPS SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_SIGPENDING SI_POSIX
+#define SANITIZER_INTERCEPT_SIGPROCMASK SI_POSIX
+#define SANITIZER_INTERCEPT_PTHREAD_SIGMASK SI_POSIX
+#define SANITIZER_INTERCEPT_BACKTRACE \
+ (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_GETMNTENT SI_LINUX
+#define SANITIZER_INTERCEPT_GETMNTENT_R SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_STATFS \
+ (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_STATFS64 SI_GLIBC && SANITIZER_HAS_STATFS64
+#define SANITIZER_INTERCEPT_STATVFS \
+ (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID)
+#define SANITIZER_INTERCEPT_STATVFS64 SI_GLIBC
+#define SANITIZER_INTERCEPT_INITGROUPS SI_POSIX
+#define SANITIZER_INTERCEPT_ETHER_NTOA_ATON SI_POSIX
+#define SANITIZER_INTERCEPT_ETHER_HOST \
+ (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID)
+#define SANITIZER_INTERCEPT_ETHER_R (SI_FREEBSD || SI_LINUX_NOT_ANDROID)
+#define SANITIZER_INTERCEPT_SHMCTL \
+ (((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && SANITIZER_WORDSIZE == 64) || \
+ SI_NETBSD || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_RANDOM_R SI_GLIBC
+#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_POSIX
+#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED \
+ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP SI_GLIBC
+#define SANITIZER_INTERCEPT_PTHREAD_GETAFFINITY_NP SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET_SCHED SI_POSIX
+#define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED \
+ (SI_POSIX && !SI_NETBSD)
+#define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETTYPE SI_POSIX
+#define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPROTOCOL \
+ (SI_MAC || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPRIOCEILING \
+ (SI_MAC || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST \
+ (SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST_NP SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETPSHARED \
+ (SI_POSIX && !SI_NETBSD)
+#define SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETKIND_NP SI_GLIBC
+#define SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETPSHARED (SI_POSIX && !SI_NETBSD)
+#define SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETCLOCK \
+ (SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GETPSHARED \
+ (SI_LINUX_NOT_ANDROID && !SI_NETBSD)
+#define SANITIZER_INTERCEPT_THR_EXIT SI_FREEBSD
+#define SANITIZER_INTERCEPT_TMPNAM SI_POSIX
+#define SANITIZER_INTERCEPT_TMPNAM_R (SI_GLIBC || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_PTSNAME SI_LINUX
+#define SANITIZER_INTERCEPT_PTSNAME_R SI_LINUX
+#define SANITIZER_INTERCEPT_TTYNAME SI_POSIX
+#define SANITIZER_INTERCEPT_TTYNAME_R SI_POSIX
+#define SANITIZER_INTERCEPT_TEMPNAM SI_POSIX
+#define SANITIZER_INTERCEPT_SINCOS SI_LINUX || SI_SOLARIS
+#define SANITIZER_INTERCEPT_REMQUO SI_POSIX
+#define SANITIZER_INTERCEPT_REMQUOL (SI_POSIX && !SI_NETBSD)
+#define SANITIZER_INTERCEPT_LGAMMA SI_POSIX
+#define SANITIZER_INTERCEPT_LGAMMAL (SI_POSIX && !SI_NETBSD)
+#define SANITIZER_INTERCEPT_LGAMMA_R (SI_FREEBSD || SI_LINUX || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_LGAMMAL_R SI_LINUX_NOT_ANDROID || SI_SOLARIS
+#define SANITIZER_INTERCEPT_DRAND48_R SI_GLIBC
+#define SANITIZER_INTERCEPT_RAND_R \
+ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_ICONV \
+ (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_TIMES SI_POSIX
+
+// FIXME: getline seems to be available on OSX 10.7
+#define SANITIZER_INTERCEPT_GETLINE \
+ (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS)
+
+#define SANITIZER_INTERCEPT__EXIT \
+ (SI_LINUX || SI_FREEBSD || SI_NETBSD || SI_MAC || SI_SOLARIS)
+
+#define SANITIZER_INTERCEPT___LIBC_MUTEX SI_NETBSD
+#define SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP \
+ (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_PTHREAD_GETNAME_NP \
+ (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS)
+
+#define SANITIZER_INTERCEPT_TLS_GET_ADDR \
+ (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID)
+
+#define SANITIZER_INTERCEPT_LISTXATTR SI_LINUX
+#define SANITIZER_INTERCEPT_GETXATTR SI_LINUX
+#define SANITIZER_INTERCEPT_GETRESID SI_LINUX
+#define SANITIZER_INTERCEPT_GETIFADDRS \
+ (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_MAC || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_IF_INDEXTONAME \
+ (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_MAC || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_CAPGET SI_LINUX_NOT_ANDROID
+#if SI_LINUX && defined(__arm__)
+#define SANITIZER_INTERCEPT_AEABI_MEM 1
+#else
+#define SANITIZER_INTERCEPT_AEABI_MEM 0
+#endif
+#define SANITIZER_INTERCEPT___BZERO SI_MAC || SI_GLIBC
+#define SANITIZER_INTERCEPT_BZERO SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_FTIME (!SI_FREEBSD && !SI_NETBSD && SI_POSIX)
+#define SANITIZER_INTERCEPT_XDR (SI_GLIBC || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_XDRREC SI_GLIBC
+#define SANITIZER_INTERCEPT_TSEARCH \
+ (SI_LINUX_NOT_ANDROID || SI_MAC || SI_NETBSD || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_LIBIO_INTERNALS SI_GLIBC
+#define SANITIZER_INTERCEPT_FOPEN SI_POSIX
+#define SANITIZER_INTERCEPT_FOPEN64 (SI_GLIBC || SI_SOLARIS32)
+#define SANITIZER_INTERCEPT_OPEN_MEMSTREAM \
+ (SI_LINUX_NOT_ANDROID || SI_NETBSD || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_OBSTACK SI_GLIBC
+#define SANITIZER_INTERCEPT_FFLUSH SI_POSIX
+#define SANITIZER_INTERCEPT_FCLOSE SI_POSIX
+
+#ifndef SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
+#define SANITIZER_INTERCEPT_DLOPEN_DLCLOSE \
+ (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_MAC || SI_SOLARIS)
+#endif
+
+#define SANITIZER_INTERCEPT_GETPASS \
+ (SI_LINUX_NOT_ANDROID || SI_MAC || SI_NETBSD)
+#define SANITIZER_INTERCEPT_TIMERFD SI_LINUX_NOT_ANDROID
+
+#define SANITIZER_INTERCEPT_MLOCKX SI_POSIX
+#define SANITIZER_INTERCEPT_FOPENCOOKIE SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_SEM \
+ (SI_LINUX || SI_FREEBSD || SI_NETBSD || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_PTHREAD_SETCANCEL SI_POSIX
+#define SANITIZER_INTERCEPT_MINCORE \
+ (SI_LINUX || SI_NETBSD || SI_FREEBSD || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_PROCESS_VM_READV SI_LINUX
+#define SANITIZER_INTERCEPT_CTERMID \
+ (SI_LINUX || SI_MAC || SI_FREEBSD || SI_NETBSD || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_CTERMID_R (SI_MAC || SI_FREEBSD || SI_SOLARIS)
+
+#define SANITIZER_INTERCEPTOR_HOOKS \
+ (SI_LINUX || SI_MAC || SI_WINDOWS || SI_FREEBSD || SI_NETBSD || SI_SOLARIS)
+#define SANITIZER_INTERCEPT_RECV_RECVFROM SI_POSIX
+#define SANITIZER_INTERCEPT_SEND_SENDTO SI_POSIX
+#define SANITIZER_INTERCEPT_EVENTFD_READ_WRITE SI_LINUX
+
+#define SI_STAT_LINUX (SI_LINUX && __GLIBC_PREREQ(2, 33))
+#define SANITIZER_INTERCEPT_STAT \
+ (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS || \
+ SI_STAT_LINUX)
+#define SANITIZER_INTERCEPT_STAT64 SI_STAT_LINUX && SANITIZER_HAS_STAT64
+#define SANITIZER_INTERCEPT_LSTAT (SI_NETBSD || SI_FREEBSD || SI_STAT_LINUX)
+#define SANITIZER_INTERCEPT___XSTAT \
+ ((!SANITIZER_INTERCEPT_STAT && SI_POSIX) || SI_STAT_LINUX)
+#define SANITIZER_INTERCEPT___XSTAT64 SI_GLIBC
+#define SANITIZER_INTERCEPT___LXSTAT SANITIZER_INTERCEPT___XSTAT
+#define SANITIZER_INTERCEPT___LXSTAT64 SI_GLIBC
+
+#define SANITIZER_INTERCEPT_UTMP \
+ (SI_POSIX && !SI_MAC && !SI_FREEBSD && !SI_NETBSD)
+#define SANITIZER_INTERCEPT_UTMPX \
+ (SI_LINUX_NOT_ANDROID || SI_MAC || SI_FREEBSD || SI_NETBSD)
+
+#define SANITIZER_INTERCEPT_GETLOADAVG \
+ (SI_LINUX_NOT_ANDROID || SI_MAC || SI_FREEBSD || SI_NETBSD)
+
+#define SANITIZER_INTERCEPT_MMAP SI_POSIX
+#define SANITIZER_INTERCEPT_MMAP64 SI_GLIBC || SI_SOLARIS
+#define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO (SI_GLIBC || SI_ANDROID)
+#define SANITIZER_INTERCEPT_MEMALIGN (!SI_FREEBSD && !SI_MAC && !SI_NETBSD)
+#define SANITIZER_INTERCEPT___LIBC_MEMALIGN SI_GLIBC
+#define SANITIZER_INTERCEPT_PVALLOC (SI_GLIBC || SI_ANDROID)
+#define SANITIZER_INTERCEPT_CFREE (SI_GLIBC && !SANITIZER_RISCV64)
+#define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX
+#define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC)
+#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD)
+#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_WCSCAT SI_POSIX
+#define SANITIZER_INTERCEPT_WCSDUP SI_POSIX
+#define SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION (!SI_WINDOWS && SI_NOT_FUCHSIA)
+#define SANITIZER_INTERCEPT_BSD_SIGNAL SI_ANDROID
+
+#define SANITIZER_INTERCEPT_ACCT (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_USER_FROM_UID SI_NETBSD
+#define SANITIZER_INTERCEPT_UID_FROM_USER SI_NETBSD
+#define SANITIZER_INTERCEPT_GROUP_FROM_GID SI_NETBSD
+#define SANITIZER_INTERCEPT_GID_FROM_GROUP SI_NETBSD
+#define SANITIZER_INTERCEPT_ACCESS (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_FACCESSAT (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_GETGROUPLIST \
+ (SI_NETBSD || SI_FREEBSD || SI_LINUX)
+#define SANITIZER_INTERCEPT_STRLCPY \
+ (SI_NETBSD || SI_FREEBSD || SI_MAC || SI_ANDROID)
+
+#define SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT SI_LINUX_NOT_ANDROID
+
+#define SANITIZER_INTERCEPT_READLINK SI_POSIX
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
+ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101000
+#define SI_MAC_DEPLOYMENT_BELOW_10_10 1
+#else
+#define SI_MAC_DEPLOYMENT_BELOW_10_10 0
+#endif
+#define SANITIZER_INTERCEPT_READLINKAT \
+ (SI_POSIX && !SI_MAC_DEPLOYMENT_BELOW_10_10)
+
+#define SANITIZER_INTERCEPT_DEVNAME (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_DEVNAME_R (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_FGETLN (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_STRMODE (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_TTYENT (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_TTYENTPATH SI_NETBSD
+#define SANITIZER_INTERCEPT_PROTOENT (SI_LINUX || SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_PROTOENT_R SI_GLIBC
+#define SANITIZER_INTERCEPT_NETENT (SI_LINUX || SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_SETVBUF \
+ (SI_NETBSD || SI_FREEBSD || SI_LINUX || SI_MAC)
+#define SANITIZER_INTERCEPT_GETMNTINFO (SI_NETBSD || SI_FREEBSD || SI_MAC)
+#define SANITIZER_INTERCEPT_MI_VECTOR_HASH SI_NETBSD
+#define SANITIZER_INTERCEPT_GETVFSSTAT SI_NETBSD
+#define SANITIZER_INTERCEPT_REGEX (SI_NETBSD || SI_FREEBSD || SI_LINUX)
+#define SANITIZER_INTERCEPT_REGEXSUB SI_NETBSD
+#define SANITIZER_INTERCEPT_FTS (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_SYSCTL (SI_NETBSD || SI_FREEBSD || SI_MAC)
+#define SANITIZER_INTERCEPT_ASYSCTL SI_NETBSD
+#define SANITIZER_INTERCEPT_SYSCTLGETMIBINFO SI_NETBSD
+#define SANITIZER_INTERCEPT_NL_LANGINFO (SI_NETBSD || SI_FREEBSD || SI_MAC)
+#define SANITIZER_INTERCEPT_MODCTL SI_NETBSD
+#define SANITIZER_INTERCEPT_CAPSICUM SI_FREEBSD
+#define SANITIZER_INTERCEPT_STRTONUM (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_FPARSELN (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_STATVFS1 SI_NETBSD
+#define SANITIZER_INTERCEPT_STRTOI SI_NETBSD
+#define SANITIZER_INTERCEPT_CAPSICUM SI_FREEBSD
+#define SANITIZER_INTERCEPT_SHA1 SI_NETBSD
+#define SANITIZER_INTERCEPT_MD4 SI_NETBSD
+#define SANITIZER_INTERCEPT_RMD160 SI_NETBSD
+#define SANITIZER_INTERCEPT_MD5 (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_FSEEK (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_MD2 SI_NETBSD
+#define SANITIZER_INTERCEPT_SHA2 (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_CDB SI_NETBSD
+#define SANITIZER_INTERCEPT_VIS (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_POPEN SI_POSIX
+#define SANITIZER_INTERCEPT_POPENVE SI_NETBSD
+#define SANITIZER_INTERCEPT_PCLOSE SI_POSIX
+#define SANITIZER_INTERCEPT_FUNOPEN (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_FUNOPEN2 SI_NETBSD
+#define SANITIZER_INTERCEPT_GETFSENT (SI_FREEBSD || SI_NETBSD || SI_MAC)
+#define SANITIZER_INTERCEPT_ARC4RANDOM (SI_FREEBSD || SI_NETBSD || SI_MAC)
+#define SANITIZER_INTERCEPT_FDEVNAME SI_FREEBSD
+#define SANITIZER_INTERCEPT_GETUSERSHELL (SI_POSIX && !SI_ANDROID)
+#define SANITIZER_INTERCEPT_SL_INIT (SI_FREEBSD || SI_NETBSD)
+#define SANITIZER_INTERCEPT_CRYPT (SI_POSIX && !SI_ANDROID)
+#define SANITIZER_INTERCEPT_CRYPT_R (SI_LINUX && !SI_ANDROID)
+
+#define SANITIZER_INTERCEPT_GETRANDOM \
+ ((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD)
+#define SANITIZER_INTERCEPT___CXA_ATEXIT SI_NETBSD
+#define SANITIZER_INTERCEPT_ATEXIT SI_NETBSD
+#define SANITIZER_INTERCEPT_PTHREAD_ATFORK SI_NETBSD
+#define SANITIZER_INTERCEPT_GETENTROPY SI_FREEBSD
+#define SANITIZER_INTERCEPT_QSORT \
+ (SI_POSIX && !SI_IOSSIM && !SI_WATCHOS && !SI_TVOS && !SI_ANDROID)
+#define SANITIZER_INTERCEPT_QSORT_R SI_GLIBC
+#define SANITIZER_INTERCEPT_BSEARCH \
+ (SI_POSIX && !SI_IOSSIM && !SI_WATCHOS && !SI_TVOS && !SI_ANDROID)
+// sigaltstack on i386 macOS cannot be intercepted due to setjmp()
+// calling it and assuming that it does not clobber registers.
+#define SANITIZER_INTERCEPT_SIGALTSTACK \
+ (SI_POSIX && !(SANITIZER_APPLE && SANITIZER_I386))
+#define SANITIZER_INTERCEPT_UNAME (SI_POSIX && !SI_FREEBSD)
+#define SANITIZER_INTERCEPT___XUNAME SI_FREEBSD
+#define SANITIZER_INTERCEPT_FLOPEN SI_FREEBSD
+#define SANITIZER_INTERCEPT_PROCCTL SI_FREEBSD
+#define SANITIZER_INTERCEPT_HEXDUMP SI_FREEBSD
+
+// This macro gives a way for downstream users to override the above
+// interceptor macros irrespective of the platform they are on. They have
+// to do two things:
+// 1. Build compiler-rt with -DSANITIZER_OVERRIDE_INTERCEPTORS.
+// 2. Provide a header file named sanitizer_intercept_overriders.h in the
+// include path for their compiler-rt build.
+// An example of an overrider for strlen interceptor that one can list in
+// sanitizer_intercept_overriders.h is as follows:
+//
+// #ifdef SANITIZER_INTERCEPT_STRLEN
+// #undef SANITIZER_INTERCEPT_STRLEN
+// #define SANITIZER_INTERCEPT_STRLEN <value of choice>
+// #endif
+//
+// This "feature" is useful for downstream users who do not want some of
+// their libc funtions to be intercepted. They can selectively disable
+// interception of those functions.
+#ifdef SANITIZER_OVERRIDE_INTERCEPTORS
+#error #include <sanitizer_intercept_overriders.h>
+#endif
+
+#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp
new file mode 100644
index 00000000000..4debd33c154
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp
@@ -0,0 +1,561 @@
+//===-- sanitizer_platform_limits_freebsd.cpp -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer common code.
+//
+// Sizes and layouts of platform-specific FreeBSD data structures.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_FREEBSD
+
+#error #include <sys/capsicum.h>
+#error #include <sys/consio.h>
+#include <sys/filio.h>
+#include <sys/ipc.h>
+#error #include <sys/kbio.h>
+#error #include <sys/link_elf.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#error #include <sys/mqueue.h>
+#include <sys/msg.h>
+#include <sys/mtio.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/soundcard.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/time.h>
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-W#warnings"
+#include <sys/timeb.h>
+#pragma clang diagnostic pop
+#include <sys/times.h>
+#include <sys/timespec.h>
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <sys/utsname.h>
+//
+#include <arpa/inet.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#error #include <net/ppp_defs.h>
+#include <net/route.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#error #include <netinet/ip_mroute.h>
+//
+#include <dirent.h>
+#include <dlfcn.h>
+#include <fstab.h>
+#include <fts.h>
+#include <glob.h>
+#include <grp.h>
+#include <ifaddrs.h>
+#include <limits.h>
+#include <poll.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <regex.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stddef.h>
+#error #include <md5.h>
+#error #include <sha224.h>
+#error #include <sha256.h>
+#error #include <sha384.h>
+#error #include <sha512.h>
+#include <stdio.h>
+#error #include <stringlist.h>
+#include <term.h>
+#include <termios.h>
+#include <time.h>
+#include <ttyent.h>
+#include <utime.h>
+#include <utmpx.h>
+#include <vis.h>
+#include <wchar.h>
+#include <wordexp.h>
+
+#define _KERNEL // to declare 'shminfo' structure
+#include <sys/shm.h>
+#undef _KERNEL
+
+#undef IOC_DIRMASK
+
+// Include these after system headers to avoid name clashes and ambiguities.
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_platform_limits_freebsd.h"
+
+namespace __sanitizer {
+void *__sanitizer_get_link_map_by_dlopen_handle(void *handle) {
+ void *p = nullptr;
+ return internal_dlinfo(handle, RTLD_DI_LINKMAP, &p) == 0 ? p : nullptr;
+}
+
+unsigned struct_cap_rights_sz = sizeof(cap_rights_t);
+unsigned struct_utsname_sz = sizeof(struct utsname);
+unsigned struct_stat_sz = sizeof(struct stat);
+unsigned struct_rusage_sz = sizeof(struct rusage);
+unsigned struct_tm_sz = sizeof(struct tm);
+unsigned struct_passwd_sz = sizeof(struct passwd);
+unsigned struct_group_sz = sizeof(struct group);
+unsigned siginfo_t_sz = sizeof(siginfo_t);
+unsigned struct_sigaction_sz = sizeof(struct sigaction);
+unsigned struct_stack_t_sz = sizeof(stack_t);
+unsigned struct_itimerval_sz = sizeof(struct itimerval);
+unsigned pthread_t_sz = sizeof(pthread_t);
+unsigned pthread_mutex_t_sz = sizeof(pthread_mutex_t);
+unsigned pthread_cond_t_sz = sizeof(pthread_cond_t);
+unsigned pid_t_sz = sizeof(pid_t);
+unsigned timeval_sz = sizeof(timeval);
+unsigned uid_t_sz = sizeof(uid_t);
+unsigned gid_t_sz = sizeof(gid_t);
+unsigned fpos_t_sz = sizeof(fpos_t);
+unsigned mbstate_t_sz = sizeof(mbstate_t);
+unsigned sigset_t_sz = sizeof(sigset_t);
+unsigned struct_timezone_sz = sizeof(struct timezone);
+unsigned struct_tms_sz = sizeof(struct tms);
+unsigned struct_sigevent_sz = sizeof(struct sigevent);
+unsigned struct_sched_param_sz = sizeof(struct sched_param);
+unsigned struct_statfs_sz = sizeof(struct statfs);
+unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
+unsigned ucontext_t_sz(void *ctx) { return sizeof(ucontext_t); }
+unsigned struct_rlimit_sz = sizeof(struct rlimit);
+unsigned struct_timespec_sz = sizeof(struct timespec);
+unsigned struct_utimbuf_sz = sizeof(struct utimbuf);
+unsigned struct_itimerspec_sz = sizeof(struct itimerspec);
+unsigned struct_timeb_sz = sizeof(struct timeb);
+unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds);
+unsigned struct_mq_attr_sz = sizeof(struct mq_attr);
+unsigned struct_statvfs_sz = sizeof(struct statvfs);
+unsigned struct_shminfo_sz = sizeof(struct shminfo);
+unsigned struct_shm_info_sz = sizeof(struct shm_info);
+unsigned struct_regmatch_sz = sizeof(regmatch_t);
+unsigned struct_regex_sz = sizeof(regex_t);
+unsigned struct_fstab_sz = sizeof(struct fstab);
+unsigned struct_FTS_sz = sizeof(FTS);
+unsigned struct_FTSENT_sz = sizeof(FTSENT);
+unsigned struct_StringList_sz = sizeof(StringList);
+
+const uptr sig_ign = (uptr)SIG_IGN;
+const uptr sig_dfl = (uptr)SIG_DFL;
+const uptr sig_err = (uptr)SIG_ERR;
+const uptr sa_siginfo = (uptr)SA_SIGINFO;
+
+int shmctl_ipc_stat = (int)IPC_STAT;
+int shmctl_ipc_info = (int)IPC_INFO;
+int shmctl_shm_info = (int)SHM_INFO;
+int shmctl_shm_stat = (int)SHM_STAT;
+unsigned struct_utmpx_sz = sizeof(struct utmpx);
+
+int map_fixed = MAP_FIXED;
+
+int af_inet = (int)AF_INET;
+int af_inet6 = (int)AF_INET6;
+
+uptr __sanitizer_in_addr_sz(int af) {
+ if (af == AF_INET)
+ return sizeof(struct in_addr);
+ else if (af == AF_INET6)
+ return sizeof(struct in6_addr);
+ else
+ return 0;
+}
+
+unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
+int glob_nomatch = GLOB_NOMATCH;
+int glob_altdirfunc = GLOB_ALTDIRFUNC;
+const int wordexp_wrde_dooffs = WRDE_DOOFFS;
+
+unsigned path_max = PATH_MAX;
+
+int struct_ttyent_sz = sizeof(struct ttyent);
+
+// ioctl arguments
+unsigned struct_ifreq_sz = sizeof(struct ifreq);
+unsigned struct_termios_sz = sizeof(struct termios);
+unsigned struct_winsize_sz = sizeof(struct winsize);
+#if SOUND_VERSION >= 0x040000
+unsigned struct_copr_buffer_sz = 0;
+unsigned struct_copr_debug_buf_sz = 0;
+unsigned struct_copr_msg_sz = 0;
+#else
+unsigned struct_copr_buffer_sz = sizeof(struct copr_buffer);
+unsigned struct_copr_debug_buf_sz = sizeof(struct copr_debug_buf);
+unsigned struct_copr_msg_sz = sizeof(struct copr_msg);
+#endif
+unsigned struct_midi_info_sz = sizeof(struct midi_info);
+unsigned struct_mtget_sz = sizeof(struct mtget);
+unsigned struct_mtop_sz = sizeof(struct mtop);
+unsigned struct_sbi_instrument_sz = sizeof(struct sbi_instrument);
+unsigned struct_seq_event_rec_sz = sizeof(struct seq_event_rec);
+unsigned struct_synth_info_sz = sizeof(struct synth_info);
+unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);
+unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
+unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
+unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
+unsigned struct_procctl_reaper_status_sz = sizeof(struct __sanitizer_procctl_reaper_status);
+unsigned struct_procctl_reaper_pidinfo_sz = sizeof(struct __sanitizer_procctl_reaper_pidinfo);
+unsigned struct_procctl_reaper_pids_sz = sizeof(struct __sanitizer_procctl_reaper_pids);
+unsigned struct_procctl_reaper_kill_sz = sizeof(struct __sanitizer_procctl_reaper_kill);
+const unsigned long __sanitizer_bufsiz = BUFSIZ;
+
+const unsigned IOCTL_NOT_PRESENT = 0;
+
+unsigned IOCTL_FIOASYNC = FIOASYNC;
+unsigned IOCTL_FIOCLEX = FIOCLEX;
+unsigned IOCTL_FIOGETOWN = FIOGETOWN;
+unsigned IOCTL_FIONBIO = FIONBIO;
+unsigned IOCTL_FIONCLEX = FIONCLEX;
+unsigned IOCTL_FIOSETOWN = FIOSETOWN;
+unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
+unsigned IOCTL_SIOCATMARK = SIOCATMARK;
+unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
+unsigned IOCTL_SIOCGIFADDR = SIOCGIFADDR;
+unsigned IOCTL_SIOCGIFBRDADDR = SIOCGIFBRDADDR;
+unsigned IOCTL_SIOCGIFCONF = SIOCGIFCONF;
+unsigned IOCTL_SIOCGIFDSTADDR = SIOCGIFDSTADDR;
+unsigned IOCTL_SIOCGIFFLAGS = SIOCGIFFLAGS;
+unsigned IOCTL_SIOCGIFMETRIC = SIOCGIFMETRIC;
+unsigned IOCTL_SIOCGIFMTU = SIOCGIFMTU;
+unsigned IOCTL_SIOCGIFNETMASK = SIOCGIFNETMASK;
+unsigned IOCTL_SIOCGPGRP = SIOCGPGRP;
+unsigned IOCTL_SIOCSIFADDR = SIOCSIFADDR;
+unsigned IOCTL_SIOCSIFBRDADDR = SIOCSIFBRDADDR;
+unsigned IOCTL_SIOCSIFDSTADDR = SIOCSIFDSTADDR;
+unsigned IOCTL_SIOCSIFFLAGS = SIOCSIFFLAGS;
+unsigned IOCTL_SIOCSIFMETRIC = SIOCSIFMETRIC;
+unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
+unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
+unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
+unsigned IOCTL_TIOCCONS = TIOCCONS;
+unsigned IOCTL_TIOCEXCL = TIOCEXCL;
+unsigned IOCTL_TIOCGETD = TIOCGETD;
+unsigned IOCTL_TIOCGPGRP = TIOCGPGRP;
+unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ;
+unsigned IOCTL_TIOCMBIC = TIOCMBIC;
+unsigned IOCTL_TIOCMBIS = TIOCMBIS;
+unsigned IOCTL_TIOCMGET = TIOCMGET;
+unsigned IOCTL_TIOCMSET = TIOCMSET;
+unsigned IOCTL_TIOCNOTTY = TIOCNOTTY;
+unsigned IOCTL_TIOCNXCL = TIOCNXCL;
+unsigned IOCTL_TIOCOUTQ = TIOCOUTQ;
+unsigned IOCTL_TIOCPKT = TIOCPKT;
+unsigned IOCTL_TIOCSCTTY = TIOCSCTTY;
+unsigned IOCTL_TIOCSETD = TIOCSETD;
+unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
+unsigned IOCTL_TIOCSTI = TIOCSTI;
+unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
+unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT;
+unsigned IOCTL_SIOCGETVIFCNT = SIOCGETVIFCNT;
+unsigned IOCTL_MTIOCGET = MTIOCGET;
+unsigned IOCTL_MTIOCTOP = MTIOCTOP;
+unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE = SNDCTL_DSP_GETBLKSIZE;
+unsigned IOCTL_SNDCTL_DSP_GETFMTS = SNDCTL_DSP_GETFMTS;
+unsigned IOCTL_SNDCTL_DSP_NONBLOCK = SNDCTL_DSP_NONBLOCK;
+unsigned IOCTL_SNDCTL_DSP_POST = SNDCTL_DSP_POST;
+unsigned IOCTL_SNDCTL_DSP_RESET = SNDCTL_DSP_RESET;
+unsigned IOCTL_SNDCTL_DSP_SETFMT = SNDCTL_DSP_SETFMT;
+unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT = SNDCTL_DSP_SETFRAGMENT;
+unsigned IOCTL_SNDCTL_DSP_SPEED = SNDCTL_DSP_SPEED;
+unsigned IOCTL_SNDCTL_DSP_STEREO = SNDCTL_DSP_STEREO;
+unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE = SNDCTL_DSP_SUBDIVIDE;
+unsigned IOCTL_SNDCTL_DSP_SYNC = SNDCTL_DSP_SYNC;
+unsigned IOCTL_SNDCTL_FM_4OP_ENABLE = SNDCTL_FM_4OP_ENABLE;
+unsigned IOCTL_SNDCTL_FM_LOAD_INSTR = SNDCTL_FM_LOAD_INSTR;
+unsigned IOCTL_SNDCTL_MIDI_INFO = SNDCTL_MIDI_INFO;
+unsigned IOCTL_SNDCTL_MIDI_PRETIME = SNDCTL_MIDI_PRETIME;
+unsigned IOCTL_SNDCTL_SEQ_CTRLRATE = SNDCTL_SEQ_CTRLRATE;
+unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT = SNDCTL_SEQ_GETINCOUNT;
+unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT = SNDCTL_SEQ_GETOUTCOUNT;
+unsigned IOCTL_SNDCTL_SEQ_NRMIDIS = SNDCTL_SEQ_NRMIDIS;
+unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS = SNDCTL_SEQ_NRSYNTHS;
+unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND = SNDCTL_SEQ_OUTOFBAND;
+unsigned IOCTL_SNDCTL_SEQ_PANIC = SNDCTL_SEQ_PANIC;
+unsigned IOCTL_SNDCTL_SEQ_PERCMODE = SNDCTL_SEQ_PERCMODE;
+unsigned IOCTL_SNDCTL_SEQ_RESET = SNDCTL_SEQ_RESET;
+unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES = SNDCTL_SEQ_RESETSAMPLES;
+unsigned IOCTL_SNDCTL_SEQ_SYNC = SNDCTL_SEQ_SYNC;
+unsigned IOCTL_SNDCTL_SEQ_TESTMIDI = SNDCTL_SEQ_TESTMIDI;
+unsigned IOCTL_SNDCTL_SEQ_THRESHOLD = SNDCTL_SEQ_THRESHOLD;
+unsigned IOCTL_SNDCTL_SYNTH_INFO = SNDCTL_SYNTH_INFO;
+unsigned IOCTL_SNDCTL_SYNTH_MEMAVL = SNDCTL_SYNTH_MEMAVL;
+unsigned IOCTL_SNDCTL_TMR_CONTINUE = SNDCTL_TMR_CONTINUE;
+unsigned IOCTL_SNDCTL_TMR_METRONOME = SNDCTL_TMR_METRONOME;
+unsigned IOCTL_SNDCTL_TMR_SELECT = SNDCTL_TMR_SELECT;
+unsigned IOCTL_SNDCTL_TMR_SOURCE = SNDCTL_TMR_SOURCE;
+unsigned IOCTL_SNDCTL_TMR_START = SNDCTL_TMR_START;
+unsigned IOCTL_SNDCTL_TMR_STOP = SNDCTL_TMR_STOP;
+unsigned IOCTL_SNDCTL_TMR_TEMPO = SNDCTL_TMR_TEMPO;
+unsigned IOCTL_SNDCTL_TMR_TIMEBASE = SNDCTL_TMR_TIMEBASE;
+unsigned IOCTL_SOUND_MIXER_READ_ALTPCM = SOUND_MIXER_READ_ALTPCM;
+unsigned IOCTL_SOUND_MIXER_READ_BASS = SOUND_MIXER_READ_BASS;
+unsigned IOCTL_SOUND_MIXER_READ_CAPS = SOUND_MIXER_READ_CAPS;
+unsigned IOCTL_SOUND_MIXER_READ_CD = SOUND_MIXER_READ_CD;
+unsigned IOCTL_SOUND_MIXER_READ_DEVMASK = SOUND_MIXER_READ_DEVMASK;
+unsigned IOCTL_SOUND_MIXER_READ_ENHANCE = SOUND_MIXER_READ_ENHANCE;
+unsigned IOCTL_SOUND_MIXER_READ_IGAIN = SOUND_MIXER_READ_IGAIN;
+unsigned IOCTL_SOUND_MIXER_READ_IMIX = SOUND_MIXER_READ_IMIX;
+unsigned IOCTL_SOUND_MIXER_READ_LINE = SOUND_MIXER_READ_LINE;
+unsigned IOCTL_SOUND_MIXER_READ_LINE1 = SOUND_MIXER_READ_LINE1;
+unsigned IOCTL_SOUND_MIXER_READ_LINE2 = SOUND_MIXER_READ_LINE2;
+unsigned IOCTL_SOUND_MIXER_READ_LINE3 = SOUND_MIXER_READ_LINE3;
+unsigned IOCTL_SOUND_MIXER_READ_LOUD = SOUND_MIXER_READ_LOUD;
+unsigned IOCTL_SOUND_MIXER_READ_MIC = SOUND_MIXER_READ_MIC;
+unsigned IOCTL_SOUND_MIXER_READ_MUTE = SOUND_MIXER_READ_MUTE;
+unsigned IOCTL_SOUND_MIXER_READ_OGAIN = SOUND_MIXER_READ_OGAIN;
+unsigned IOCTL_SOUND_MIXER_READ_PCM = SOUND_MIXER_READ_PCM;
+unsigned IOCTL_SOUND_MIXER_READ_RECLEV = SOUND_MIXER_READ_RECLEV;
+unsigned IOCTL_SOUND_MIXER_READ_RECMASK = SOUND_MIXER_READ_RECMASK;
+unsigned IOCTL_SOUND_MIXER_READ_RECSRC = SOUND_MIXER_READ_RECSRC;
+unsigned IOCTL_SOUND_MIXER_READ_SPEAKER = SOUND_MIXER_READ_SPEAKER;
+unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS = SOUND_MIXER_READ_STEREODEVS;
+unsigned IOCTL_SOUND_MIXER_READ_SYNTH = SOUND_MIXER_READ_SYNTH;
+unsigned IOCTL_SOUND_MIXER_READ_TREBLE = SOUND_MIXER_READ_TREBLE;
+unsigned IOCTL_SOUND_MIXER_READ_VOLUME = SOUND_MIXER_READ_VOLUME;
+unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM = SOUND_MIXER_WRITE_ALTPCM;
+unsigned IOCTL_SOUND_MIXER_WRITE_BASS = SOUND_MIXER_WRITE_BASS;
+unsigned IOCTL_SOUND_MIXER_WRITE_CD = SOUND_MIXER_WRITE_CD;
+unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE = SOUND_MIXER_WRITE_ENHANCE;
+unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN = SOUND_MIXER_WRITE_IGAIN;
+unsigned IOCTL_SOUND_MIXER_WRITE_IMIX = SOUND_MIXER_WRITE_IMIX;
+unsigned IOCTL_SOUND_MIXER_WRITE_LINE = SOUND_MIXER_WRITE_LINE;
+unsigned IOCTL_SOUND_MIXER_WRITE_LINE1 = SOUND_MIXER_WRITE_LINE1;
+unsigned IOCTL_SOUND_MIXER_WRITE_LINE2 = SOUND_MIXER_WRITE_LINE2;
+unsigned IOCTL_SOUND_MIXER_WRITE_LINE3 = SOUND_MIXER_WRITE_LINE3;
+unsigned IOCTL_SOUND_MIXER_WRITE_LOUD = SOUND_MIXER_WRITE_LOUD;
+unsigned IOCTL_SOUND_MIXER_WRITE_MIC = SOUND_MIXER_WRITE_MIC;
+unsigned IOCTL_SOUND_MIXER_WRITE_MUTE = SOUND_MIXER_WRITE_MUTE;
+unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN = SOUND_MIXER_WRITE_OGAIN;
+unsigned IOCTL_SOUND_MIXER_WRITE_PCM = SOUND_MIXER_WRITE_PCM;
+unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV = SOUND_MIXER_WRITE_RECLEV;
+unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC = SOUND_MIXER_WRITE_RECSRC;
+unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER = SOUND_MIXER_WRITE_SPEAKER;
+unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH = SOUND_MIXER_WRITE_SYNTH;
+unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE = SOUND_MIXER_WRITE_TREBLE;
+unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME = SOUND_MIXER_WRITE_VOLUME;
+unsigned IOCTL_VT_ACTIVATE = VT_ACTIVATE;
+unsigned IOCTL_VT_GETMODE = VT_GETMODE;
+unsigned IOCTL_VT_OPENQRY = VT_OPENQRY;
+unsigned IOCTL_VT_RELDISP = VT_RELDISP;
+unsigned IOCTL_VT_SETMODE = VT_SETMODE;
+unsigned IOCTL_VT_WAITACTIVE = VT_WAITACTIVE;
+unsigned IOCTL_GIO_SCRNMAP = GIO_SCRNMAP;
+unsigned IOCTL_KDDISABIO = KDDISABIO;
+unsigned IOCTL_KDENABIO = KDENABIO;
+unsigned IOCTL_KDGETLED = KDGETLED;
+unsigned IOCTL_KDGETMODE = KDGETMODE;
+unsigned IOCTL_KDGKBMODE = KDGKBMODE;
+unsigned IOCTL_KDGKBTYPE = KDGKBTYPE;
+unsigned IOCTL_KDMKTONE = KDMKTONE;
+unsigned IOCTL_KDSETLED = KDSETLED;
+unsigned IOCTL_KDSETMODE = KDSETMODE;
+unsigned IOCTL_KDSKBMODE = KDSKBMODE;
+unsigned IOCTL_KIOCSOUND = KIOCSOUND;
+unsigned IOCTL_PIO_SCRNMAP = PIO_SCRNMAP;
+unsigned IOCTL_SNDCTL_DSP_GETISPACE = SNDCTL_DSP_GETISPACE;
+
+const int si_SEGV_MAPERR = SEGV_MAPERR;
+const int si_SEGV_ACCERR = SEGV_ACCERR;
+const int unvis_valid = UNVIS_VALID;
+const int unvis_validpush = UNVIS_VALIDPUSH;
+
+const unsigned MD5_CTX_sz = sizeof(MD5_CTX);
+const unsigned MD5_return_length = MD5_DIGEST_STRING_LENGTH;
+
+#define SHA2_CONST(LEN) \
+ const unsigned SHA##LEN##_CTX_sz = sizeof(SHA##LEN##_CTX); \
+ const unsigned SHA##LEN##_return_length = SHA##LEN##_DIGEST_STRING_LENGTH; \
+ const unsigned SHA##LEN##_block_length = SHA##LEN##_BLOCK_LENGTH; \
+ const unsigned SHA##LEN##_digest_length = SHA##LEN##_DIGEST_LENGTH
+
+SHA2_CONST(224);
+SHA2_CONST(256);
+SHA2_CONST(384);
+SHA2_CONST(512);
+
+#undef SHA2_CONST
+} // namespace __sanitizer
+
+using namespace __sanitizer;
+
+COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
+
+COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned));
+CHECK_TYPE_SIZE(pthread_key_t);
+
+// There are more undocumented fields in dl_phdr_info that we are not interested
+// in.
+COMPILER_CHECK(sizeof(__sanitizer_dl_phdr_info) <= sizeof(dl_phdr_info));
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_addr);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum);
+
+CHECK_TYPE_SIZE(glob_t);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_offs);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_flags);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_closedir);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_readdir);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_opendir);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_lstat);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_stat);
+
+CHECK_TYPE_SIZE(addrinfo);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_flags);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_family);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_socktype);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_addrlen);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_canonname);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_addr);
+
+CHECK_TYPE_SIZE(hostent);
+CHECK_SIZE_AND_OFFSET(hostent, h_name);
+CHECK_SIZE_AND_OFFSET(hostent, h_aliases);
+CHECK_SIZE_AND_OFFSET(hostent, h_addrtype);
+CHECK_SIZE_AND_OFFSET(hostent, h_length);
+CHECK_SIZE_AND_OFFSET(hostent, h_addr_list);
+
+CHECK_TYPE_SIZE(iovec);
+CHECK_SIZE_AND_OFFSET(iovec, iov_base);
+CHECK_SIZE_AND_OFFSET(iovec, iov_len);
+
+CHECK_TYPE_SIZE(msghdr);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_name);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_namelen);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_iov);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_iovlen);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_control);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_controllen);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_flags);
+
+CHECK_TYPE_SIZE(cmsghdr);
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
+
+COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
+CHECK_SIZE_AND_OFFSET(dirent, d_ino);
+CHECK_SIZE_AND_OFFSET(dirent, d_reclen);
+
+CHECK_TYPE_SIZE(ifconf);
+CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
+CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);
+
+CHECK_TYPE_SIZE(pollfd);
+CHECK_SIZE_AND_OFFSET(pollfd, fd);
+CHECK_SIZE_AND_OFFSET(pollfd, events);
+CHECK_SIZE_AND_OFFSET(pollfd, revents);
+
+CHECK_TYPE_SIZE(nfds_t);
+
+CHECK_TYPE_SIZE(sigset_t);
+
+COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction));
+// Can't write checks for sa_handler and sa_sigaction due to them being
+// preprocessor macros.
+CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
+
+CHECK_TYPE_SIZE(wordexp_t);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_offs);
+
+CHECK_TYPE_SIZE(tm);
+CHECK_SIZE_AND_OFFSET(tm, tm_sec);
+CHECK_SIZE_AND_OFFSET(tm, tm_min);
+CHECK_SIZE_AND_OFFSET(tm, tm_hour);
+CHECK_SIZE_AND_OFFSET(tm, tm_mday);
+CHECK_SIZE_AND_OFFSET(tm, tm_mon);
+CHECK_SIZE_AND_OFFSET(tm, tm_year);
+CHECK_SIZE_AND_OFFSET(tm, tm_wday);
+CHECK_SIZE_AND_OFFSET(tm, tm_yday);
+CHECK_SIZE_AND_OFFSET(tm, tm_isdst);
+CHECK_SIZE_AND_OFFSET(tm, tm_gmtoff);
+CHECK_SIZE_AND_OFFSET(tm, tm_zone);
+
+CHECK_TYPE_SIZE(ether_addr);
+
+CHECK_TYPE_SIZE(ipc_perm);
+CHECK_SIZE_AND_OFFSET(ipc_perm, key);
+CHECK_SIZE_AND_OFFSET(ipc_perm, seq);
+CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
+
+CHECK_TYPE_SIZE(shmid_ds);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_perm);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_segsz);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_atime);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_dtime);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_ctime);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_cpid);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_lpid);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_nattch);
+
+CHECK_TYPE_SIZE(clock_t);
+
+CHECK_TYPE_SIZE(ifaddrs);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask);
+#undef ifa_dstaddr
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data);
+
+CHECK_TYPE_SIZE(timeb);
+CHECK_SIZE_AND_OFFSET(timeb, time);
+CHECK_SIZE_AND_OFFSET(timeb, millitm);
+CHECK_SIZE_AND_OFFSET(timeb, timezone);
+CHECK_SIZE_AND_OFFSET(timeb, dstflag);
+
+CHECK_TYPE_SIZE(passwd);
+CHECK_SIZE_AND_OFFSET(passwd, pw_name);
+CHECK_SIZE_AND_OFFSET(passwd, pw_passwd);
+CHECK_SIZE_AND_OFFSET(passwd, pw_uid);
+CHECK_SIZE_AND_OFFSET(passwd, pw_gid);
+CHECK_SIZE_AND_OFFSET(passwd, pw_dir);
+CHECK_SIZE_AND_OFFSET(passwd, pw_shell);
+
+CHECK_SIZE_AND_OFFSET(passwd, pw_gecos);
+
+CHECK_TYPE_SIZE(group);
+CHECK_SIZE_AND_OFFSET(group, gr_name);
+CHECK_SIZE_AND_OFFSET(group, gr_passwd);
+CHECK_SIZE_AND_OFFSET(group, gr_gid);
+CHECK_SIZE_AND_OFFSET(group, gr_mem);
+
+#if HAVE_RPC_XDR_H
+CHECK_TYPE_SIZE(XDR);
+CHECK_SIZE_AND_OFFSET(XDR, x_op);
+CHECK_SIZE_AND_OFFSET(XDR, x_ops);
+CHECK_SIZE_AND_OFFSET(XDR, x_public);
+CHECK_SIZE_AND_OFFSET(XDR, x_private);
+CHECK_SIZE_AND_OFFSET(XDR, x_base);
+CHECK_SIZE_AND_OFFSET(XDR, x_handy);
+COMPILER_CHECK(__sanitizer_XDR_ENCODE == XDR_ENCODE);
+COMPILER_CHECK(__sanitizer_XDR_DECODE == XDR_DECODE);
+COMPILER_CHECK(__sanitizer_XDR_FREE == XDR_FREE);
+#endif
+
+CHECK_TYPE_SIZE(sem_t);
+
+COMPILER_CHECK(sizeof(__sanitizer_cap_rights_t) >= sizeof(cap_rights_t));
+#endif // SANITIZER_FREEBSD
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h
new file mode 100644
index 00000000000..daef1177a2d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h
@@ -0,0 +1,735 @@
+//===-- sanitizer_platform_limits_freebsd.h -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer common code.
+//
+// Sizes and layouts of platform-specific FreeBSD data structures.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_PLATFORM_LIMITS_FREEBSD_H
+#define SANITIZER_PLATFORM_LIMITS_FREEBSD_H
+
+#if SANITIZER_FREEBSD
+
+# include "sanitizer_internal_defs.h"
+# include "sanitizer_platform.h"
+# include "sanitizer_platform_limits_posix.h"
+
+// Get sys/_types.h, because that tells us whether 64-bit inodes are
+// used in struct dirent below.
+# include <sys/_types.h>
+
+namespace __sanitizer {
+void *__sanitizer_get_link_map_by_dlopen_handle(void *handle);
+# define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \
+ (link_map *)__sanitizer_get_link_map_by_dlopen_handle(handle)
+
+extern unsigned struct_utsname_sz;
+extern unsigned struct_stat_sz;
+# if defined(__powerpc64__)
+const unsigned struct___old_kernel_stat_sz = 0;
+# else
+const unsigned struct___old_kernel_stat_sz = 32;
+# endif
+extern unsigned struct_rusage_sz;
+extern unsigned siginfo_t_sz;
+extern unsigned struct_itimerval_sz;
+extern unsigned pthread_t_sz;
+extern unsigned pthread_mutex_t_sz;
+extern unsigned pthread_cond_t_sz;
+extern unsigned pid_t_sz;
+extern unsigned timeval_sz;
+extern unsigned uid_t_sz;
+extern unsigned gid_t_sz;
+extern unsigned fpos_t_sz;
+extern unsigned mbstate_t_sz;
+extern unsigned struct_timezone_sz;
+extern unsigned struct_tms_sz;
+extern unsigned struct_itimerspec_sz;
+extern unsigned struct_sigevent_sz;
+extern unsigned struct_stack_t_sz;
+extern unsigned struct_sched_param_sz;
+extern unsigned struct_statfs64_sz;
+extern unsigned struct_statfs_sz;
+extern unsigned struct_sockaddr_sz;
+unsigned ucontext_t_sz(void *ctx);
+extern unsigned struct_rlimit_sz;
+extern unsigned struct_utimbuf_sz;
+extern unsigned struct_timespec_sz;
+extern unsigned struct_regmatch_sz;
+extern unsigned struct_regex_sz;
+extern unsigned struct_FTS_sz;
+extern unsigned struct_FTSENT_sz;
+extern const int unvis_valid;
+extern const int unvis_validpush;
+
+struct __sanitizer_iocb {
+ u64 aio_data;
+ u32 aio_key_or_aio_reserved1; // Simply crazy.
+ u32 aio_reserved1_or_aio_key; // Luckily, we don't need these.
+ u16 aio_lio_opcode;
+ s16 aio_reqprio;
+ u32 aio_fildes;
+ u64 aio_buf;
+ u64 aio_nbytes;
+ s64 aio_offset;
+ u64 aio_reserved2;
+ u64 aio_reserved3;
+};
+
+struct __sanitizer_io_event {
+ u64 data;
+ u64 obj;
+ u64 res;
+ u64 res2;
+};
+
+const unsigned iocb_cmd_pread = 0;
+const unsigned iocb_cmd_pwrite = 1;
+const unsigned iocb_cmd_preadv = 7;
+const unsigned iocb_cmd_pwritev = 8;
+
+struct __sanitizer___sysctl_args {
+ int *name;
+ int nlen;
+ void *oldval;
+ uptr *oldlenp;
+ void *newval;
+ uptr newlen;
+ unsigned long ___unused[4];
+};
+
+struct __sanitizer_ipc_perm {
+ unsigned int cuid;
+ unsigned int cgid;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned short mode;
+ unsigned short seq;
+ long key;
+};
+
+struct __sanitizer_protoent {
+ char *p_name;
+ char **p_aliases;
+ int p_proto;
+};
+
+struct __sanitizer_netent {
+ char *n_name;
+ char **n_aliases;
+ int n_addrtype;
+ u32 n_net;
+};
+
+# if !defined(__i386__)
+typedef long long __sanitizer_time_t;
+# else
+typedef long __sanitizer_time_t;
+# endif
+
+struct __sanitizer_shmid_ds {
+ __sanitizer_ipc_perm shm_perm;
+ unsigned long shm_segsz;
+ unsigned int shm_lpid;
+ unsigned int shm_cpid;
+ int shm_nattch;
+ __sanitizer_time_t shm_atime;
+ __sanitizer_time_t shm_dtime;
+ __sanitizer_time_t shm_ctime;
+};
+
+extern unsigned struct_msqid_ds_sz;
+extern unsigned struct_mq_attr_sz;
+extern unsigned struct_timeb_sz;
+extern unsigned struct_statvfs_sz;
+
+struct __sanitizer_iovec {
+ void *iov_base;
+ uptr iov_len;
+};
+
+struct __sanitizer_ifaddrs {
+ struct __sanitizer_ifaddrs *ifa_next;
+ char *ifa_name;
+ unsigned int ifa_flags;
+ void *ifa_addr; // (struct sockaddr *)
+ void *ifa_netmask; // (struct sockaddr *)
+# undef ifa_dstaddr
+ void *ifa_dstaddr; // (struct sockaddr *)
+ void *ifa_data;
+};
+
+typedef unsigned __sanitizer_pthread_key_t;
+
+struct __sanitizer_passwd {
+ char *pw_name;
+ char *pw_passwd;
+ int pw_uid;
+ int pw_gid;
+ __sanitizer_time_t pw_change;
+ char *pw_class;
+ char *pw_gecos;
+ char *pw_dir;
+ char *pw_shell;
+ __sanitizer_time_t pw_expire;
+ int pw_fields;
+};
+
+struct __sanitizer_group {
+ char *gr_name;
+ char *gr_passwd;
+ int gr_gid;
+ char **gr_mem;
+};
+
+typedef long __sanitizer_suseconds_t;
+
+struct __sanitizer_timeval {
+ __sanitizer_time_t tv_sec;
+ __sanitizer_suseconds_t tv_usec;
+};
+
+struct __sanitizer_itimerval {
+ struct __sanitizer_timeval it_interval;
+ struct __sanitizer_timeval it_value;
+};
+
+struct __sanitizer_timeb {
+ __sanitizer_time_t time;
+ unsigned short millitm;
+ short timezone;
+ short dstflag;
+};
+
+struct __sanitizer_ether_addr {
+ u8 octet[6];
+};
+
+struct __sanitizer_tm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+ long int tm_gmtoff;
+ const char *tm_zone;
+};
+
+struct __sanitizer_msghdr {
+ void *msg_name;
+ unsigned msg_namelen;
+ struct __sanitizer_iovec *msg_iov;
+ unsigned msg_iovlen;
+ void *msg_control;
+ unsigned msg_controllen;
+ int msg_flags;
+};
+
+struct __sanitizer_cmsghdr {
+ unsigned cmsg_len;
+ int cmsg_level;
+ int cmsg_type;
+};
+
+struct __sanitizer_dirent {
+# if defined(__INO64)
+ unsigned long long d_fileno;
+ unsigned long long d_off;
+# else
+ unsigned int d_fileno;
+# endif
+ unsigned short d_reclen;
+ // more fields that we don't care about
+};
+
+// 'clock_t' is 32 bits wide on x64 FreeBSD
+typedef int __sanitizer_clock_t;
+typedef int __sanitizer_clockid_t;
+
+# if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
+ defined(__mips__)
+typedef unsigned __sanitizer___kernel_uid_t;
+typedef unsigned __sanitizer___kernel_gid_t;
+# else
+typedef unsigned short __sanitizer___kernel_uid_t;
+typedef unsigned short __sanitizer___kernel_gid_t;
+# endif
+typedef long long __sanitizer___kernel_off_t;
+
+# if defined(__powerpc__) || defined(__mips__)
+typedef unsigned int __sanitizer___kernel_old_uid_t;
+typedef unsigned int __sanitizer___kernel_old_gid_t;
+# else
+typedef unsigned short __sanitizer___kernel_old_uid_t;
+typedef unsigned short __sanitizer___kernel_old_gid_t;
+# endif
+
+typedef long long __sanitizer___kernel_loff_t;
+typedef struct {
+ unsigned long fds_bits[1024 / (8 * sizeof(long))];
+} __sanitizer___kernel_fd_set;
+
+// This thing depends on the platform. We are only interested in the upper
+// limit. Verified with a compiler assert in .cpp.
+union __sanitizer_pthread_attr_t {
+ char size[128];
+ void *align;
+};
+
+const unsigned old_sigset_t_sz = sizeof(unsigned long);
+
+struct __sanitizer_sigset_t {
+ // uint32_t * 4
+ unsigned int __bits[4];
+};
+
+typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t;
+
+struct __sanitizer_siginfo {
+ // The size is determined by looking at sizeof of real siginfo_t on linux.
+ u64 opaque[128 / sizeof(u64)];
+};
+
+using __sanitizer_sighandler_ptr = void (*)(int sig);
+using __sanitizer_sigactionhandler_ptr = void (*)(int sig,
+ __sanitizer_siginfo *siginfo,
+ void *uctx);
+
+struct __sanitizer_sigaction {
+ union {
+ __sanitizer_sigactionhandler_ptr sigaction;
+ __sanitizer_sighandler_ptr handler;
+ };
+ int sa_flags;
+ __sanitizer_sigset_t sa_mask;
+};
+
+struct __sanitizer_sem_t {
+ u32 data[4];
+};
+
+extern const uptr sig_ign;
+extern const uptr sig_dfl;
+extern const uptr sig_err;
+extern const uptr sa_siginfo;
+
+extern int af_inet;
+extern int af_inet6;
+uptr __sanitizer_in_addr_sz(int af);
+
+struct __sanitizer_dl_phdr_info {
+ uptr dlpi_addr;
+ const char *dlpi_name;
+ const void *dlpi_phdr;
+ short dlpi_phnum;
+};
+
+extern unsigned struct_ElfW_Phdr_sz;
+
+struct __sanitizer_addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ unsigned ai_addrlen;
+ char *ai_canonname;
+ void *ai_addr;
+ struct __sanitizer_addrinfo *ai_next;
+};
+
+struct __sanitizer_hostent {
+ char *h_name;
+ char **h_aliases;
+ int h_addrtype;
+ int h_length;
+ char **h_addr_list;
+};
+
+struct __sanitizer_pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+typedef unsigned __sanitizer_nfds_t;
+
+struct __sanitizer_glob_t {
+ uptr gl_pathc;
+ uptr gl_matchc;
+ uptr gl_offs;
+ int gl_flags;
+ char **gl_pathv;
+ int (*gl_errfunc)(const char *, int);
+ void (*gl_closedir)(void *dirp);
+ struct dirent *(*gl_readdir)(void *dirp);
+ void *(*gl_opendir)(const char *);
+ int (*gl_lstat)(const char *, void * /* struct stat* */);
+ int (*gl_stat)(const char *, void * /* struct stat* */);
+};
+
+extern int glob_nomatch;
+extern int glob_altdirfunc;
+extern const int wordexp_wrde_dooffs;
+
+extern unsigned path_max;
+
+extern int struct_ttyent_sz;
+
+struct __sanitizer_wordexp_t {
+ uptr we_wordc;
+ char **we_wordv;
+ uptr we_offs;
+ char *we_strings;
+ uptr we_nbytes;
+};
+
+typedef void __sanitizer_FILE;
+
+extern unsigned struct_shminfo_sz;
+extern unsigned struct_shm_info_sz;
+extern int shmctl_ipc_stat;
+extern int shmctl_ipc_info;
+extern int shmctl_shm_info;
+extern int shmctl_shm_stat;
+
+extern unsigned struct_utmpx_sz;
+
+extern int map_fixed;
+
+// ioctl arguments
+struct __sanitizer_ifconf {
+ int ifc_len;
+ union {
+ void *ifcu_req;
+ } ifc_ifcu;
+};
+
+struct __sanitizer__ttyent {
+ char *ty_name;
+ char *ty_getty;
+ char *ty_type;
+ int ty_status;
+ char *ty_window;
+ char *ty_comment;
+ char *ty_group;
+};
+
+// procctl reaper data for PROCCTL_REAPER flags
+struct __sanitizer_procctl_reaper_status {
+ unsigned int rs_flags;
+ unsigned int rs_children;
+ unsigned int rs_descendants;
+ pid_t rs_reaper;
+ pid_t rs_pid;
+ unsigned int rs_pad0[15];
+};
+
+struct __sanitizer_procctl_reaper_pidinfo {
+ pid_t pi_pid;
+ pid_t pi_subtree;
+ unsigned int pi_flags;
+ unsigned int pi_pad0[15];
+};
+
+struct __sanitizer_procctl_reaper_pids {
+ unsigned int rp_count;
+ unsigned int rp_pad0[15];
+ struct __sanitize_procctl_reapper_pidinfo *rp_pids;
+};
+
+struct __sanitizer_procctl_reaper_kill {
+ int rk_sig;
+ unsigned int rk_flags;
+ pid_t rk_subtree;
+ unsigned int rk_killed;
+ pid_t rk_fpid;
+ unsigned int rk_pad[15];
+};
+
+# define IOC_NRBITS 8
+# define IOC_TYPEBITS 8
+# if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__)
+# define IOC_SIZEBITS 13
+# define IOC_DIRBITS 3
+# define IOC_NONE 1U
+# define IOC_WRITE 4U
+# define IOC_READ 2U
+# else
+# define IOC_SIZEBITS 14
+# define IOC_DIRBITS 2
+# define IOC_NONE 0U
+# define IOC_WRITE 1U
+# define IOC_READ 2U
+# endif
+# define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
+# define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
+# define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
+# if defined(IOC_DIRMASK)
+# undef IOC_DIRMASK
+# endif
+# define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
+# define IOC_NRSHIFT 0
+# define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
+# define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
+# define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
+# define EVIOC_EV_MAX 0x1f
+# define EVIOC_ABS_MAX 0x3f
+
+# define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
+# define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
+# define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
+# define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
+
+extern unsigned struct_ifreq_sz;
+extern unsigned struct_termios_sz;
+extern unsigned struct_winsize_sz;
+
+extern unsigned struct_copr_buffer_sz;
+extern unsigned struct_copr_debug_buf_sz;
+extern unsigned struct_copr_msg_sz;
+extern unsigned struct_midi_info_sz;
+extern unsigned struct_mtget_sz;
+extern unsigned struct_mtop_sz;
+extern unsigned struct_rtentry_sz;
+extern unsigned struct_sbi_instrument_sz;
+extern unsigned struct_seq_event_rec_sz;
+extern unsigned struct_synth_info_sz;
+extern unsigned struct_vt_mode_sz;
+
+extern const unsigned long __sanitizer_bufsiz;
+extern unsigned struct_audio_buf_info_sz;
+extern unsigned struct_ppp_stats_sz;
+extern unsigned struct_sioc_sg_req_sz;
+extern unsigned struct_sioc_vif_req_sz;
+
+extern unsigned struct_procctl_reaper_status_sz;
+extern unsigned struct_procctl_reaper_pidinfo_sz;
+extern unsigned struct_procctl_reaper_pids_sz;
+extern unsigned struct_procctl_reaper_kill_sz;
+
+// ioctl request identifiers
+
+// A special value to mark ioctls that are not present on the target platform,
+// when it can not be determined without including any system headers.
+extern const unsigned IOCTL_NOT_PRESENT;
+
+extern unsigned IOCTL_FIOASYNC;
+extern unsigned IOCTL_FIOCLEX;
+extern unsigned IOCTL_FIOGETOWN;
+extern unsigned IOCTL_FIONBIO;
+extern unsigned IOCTL_FIONCLEX;
+extern unsigned IOCTL_FIOSETOWN;
+extern unsigned IOCTL_SIOCADDMULTI;
+extern unsigned IOCTL_SIOCATMARK;
+extern unsigned IOCTL_SIOCDELMULTI;
+extern unsigned IOCTL_SIOCGIFADDR;
+extern unsigned IOCTL_SIOCGIFBRDADDR;
+extern unsigned IOCTL_SIOCGIFCONF;
+extern unsigned IOCTL_SIOCGIFDSTADDR;
+extern unsigned IOCTL_SIOCGIFFLAGS;
+extern unsigned IOCTL_SIOCGIFMETRIC;
+extern unsigned IOCTL_SIOCGIFMTU;
+extern unsigned IOCTL_SIOCGIFNETMASK;
+extern unsigned IOCTL_SIOCGPGRP;
+extern unsigned IOCTL_SIOCSIFADDR;
+extern unsigned IOCTL_SIOCSIFBRDADDR;
+extern unsigned IOCTL_SIOCSIFDSTADDR;
+extern unsigned IOCTL_SIOCSIFFLAGS;
+extern unsigned IOCTL_SIOCSIFMETRIC;
+extern unsigned IOCTL_SIOCSIFMTU;
+extern unsigned IOCTL_SIOCSIFNETMASK;
+extern unsigned IOCTL_SIOCSPGRP;
+extern unsigned IOCTL_TIOCCONS;
+extern unsigned IOCTL_TIOCEXCL;
+extern unsigned IOCTL_TIOCGETD;
+extern unsigned IOCTL_TIOCGPGRP;
+extern unsigned IOCTL_TIOCGWINSZ;
+extern unsigned IOCTL_TIOCMBIC;
+extern unsigned IOCTL_TIOCMBIS;
+extern unsigned IOCTL_TIOCMGET;
+extern unsigned IOCTL_TIOCMSET;
+extern unsigned IOCTL_TIOCNOTTY;
+extern unsigned IOCTL_TIOCNXCL;
+extern unsigned IOCTL_TIOCOUTQ;
+extern unsigned IOCTL_TIOCPKT;
+extern unsigned IOCTL_TIOCSCTTY;
+extern unsigned IOCTL_TIOCSETD;
+extern unsigned IOCTL_TIOCSPGRP;
+extern unsigned IOCTL_TIOCSTI;
+extern unsigned IOCTL_TIOCSWINSZ;
+extern unsigned IOCTL_SIOCGETSGCNT;
+extern unsigned IOCTL_SIOCGETVIFCNT;
+extern unsigned IOCTL_MTIOCGET;
+extern unsigned IOCTL_MTIOCTOP;
+extern unsigned IOCTL_SIOCADDRT;
+extern unsigned IOCTL_SIOCDELRT;
+extern unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE;
+extern unsigned IOCTL_SNDCTL_DSP_GETFMTS;
+extern unsigned IOCTL_SNDCTL_DSP_NONBLOCK;
+extern unsigned IOCTL_SNDCTL_DSP_POST;
+extern unsigned IOCTL_SNDCTL_DSP_RESET;
+extern unsigned IOCTL_SNDCTL_DSP_SETFMT;
+extern unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT;
+extern unsigned IOCTL_SNDCTL_DSP_SPEED;
+extern unsigned IOCTL_SNDCTL_DSP_STEREO;
+extern unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE;
+extern unsigned IOCTL_SNDCTL_DSP_SYNC;
+extern unsigned IOCTL_SNDCTL_FM_4OP_ENABLE;
+extern unsigned IOCTL_SNDCTL_FM_LOAD_INSTR;
+extern unsigned IOCTL_SNDCTL_MIDI_INFO;
+extern unsigned IOCTL_SNDCTL_MIDI_PRETIME;
+extern unsigned IOCTL_SNDCTL_SEQ_CTRLRATE;
+extern unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT;
+extern unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT;
+extern unsigned IOCTL_SNDCTL_SEQ_NRMIDIS;
+extern unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS;
+extern unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND;
+extern unsigned IOCTL_SNDCTL_SEQ_PANIC;
+extern unsigned IOCTL_SNDCTL_SEQ_PERCMODE;
+extern unsigned IOCTL_SNDCTL_SEQ_RESET;
+extern unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES;
+extern unsigned IOCTL_SNDCTL_SEQ_SYNC;
+extern unsigned IOCTL_SNDCTL_SEQ_TESTMIDI;
+extern unsigned IOCTL_SNDCTL_SEQ_THRESHOLD;
+extern unsigned IOCTL_SNDCTL_SYNTH_INFO;
+extern unsigned IOCTL_SNDCTL_SYNTH_MEMAVL;
+extern unsigned IOCTL_SNDCTL_TMR_CONTINUE;
+extern unsigned IOCTL_SNDCTL_TMR_METRONOME;
+extern unsigned IOCTL_SNDCTL_TMR_SELECT;
+extern unsigned IOCTL_SNDCTL_TMR_SOURCE;
+extern unsigned IOCTL_SNDCTL_TMR_START;
+extern unsigned IOCTL_SNDCTL_TMR_STOP;
+extern unsigned IOCTL_SNDCTL_TMR_TEMPO;
+extern unsigned IOCTL_SNDCTL_TMR_TIMEBASE;
+extern unsigned IOCTL_SOUND_MIXER_READ_ALTPCM;
+extern unsigned IOCTL_SOUND_MIXER_READ_BASS;
+extern unsigned IOCTL_SOUND_MIXER_READ_CAPS;
+extern unsigned IOCTL_SOUND_MIXER_READ_CD;
+extern unsigned IOCTL_SOUND_MIXER_READ_DEVMASK;
+extern unsigned IOCTL_SOUND_MIXER_READ_ENHANCE;
+extern unsigned IOCTL_SOUND_MIXER_READ_IGAIN;
+extern unsigned IOCTL_SOUND_MIXER_READ_IMIX;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE1;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE2;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE3;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE;
+extern unsigned IOCTL_SOUND_MIXER_READ_LOUD;
+extern unsigned IOCTL_SOUND_MIXER_READ_MIC;
+extern unsigned IOCTL_SOUND_MIXER_READ_MUTE;
+extern unsigned IOCTL_SOUND_MIXER_READ_OGAIN;
+extern unsigned IOCTL_SOUND_MIXER_READ_PCM;
+extern unsigned IOCTL_SOUND_MIXER_READ_RECLEV;
+extern unsigned IOCTL_SOUND_MIXER_READ_RECMASK;
+extern unsigned IOCTL_SOUND_MIXER_READ_RECSRC;
+extern unsigned IOCTL_SOUND_MIXER_READ_SPEAKER;
+extern unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS;
+extern unsigned IOCTL_SOUND_MIXER_READ_SYNTH;
+extern unsigned IOCTL_SOUND_MIXER_READ_TREBLE;
+extern unsigned IOCTL_SOUND_MIXER_READ_VOLUME;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_BASS;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_CD;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_IMIX;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE1;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE2;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE3;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LOUD;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_MIC;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_MUTE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_PCM;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME;
+extern unsigned IOCTL_SOUND_PCM_READ_BITS;
+extern unsigned IOCTL_SOUND_PCM_READ_CHANNELS;
+extern unsigned IOCTL_SOUND_PCM_READ_FILTER;
+extern unsigned IOCTL_SOUND_PCM_READ_RATE;
+extern unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS;
+extern unsigned IOCTL_SOUND_PCM_WRITE_FILTER;
+extern unsigned IOCTL_VT_ACTIVATE;
+extern unsigned IOCTL_VT_GETMODE;
+extern unsigned IOCTL_VT_OPENQRY;
+extern unsigned IOCTL_VT_RELDISP;
+extern unsigned IOCTL_VT_SETMODE;
+extern unsigned IOCTL_VT_WAITACTIVE;
+extern unsigned IOCTL_GIO_SCRNMAP;
+extern unsigned IOCTL_KDDISABIO;
+extern unsigned IOCTL_KDENABIO;
+extern unsigned IOCTL_KDGETLED;
+extern unsigned IOCTL_KDGETMODE;
+extern unsigned IOCTL_KDGKBMODE;
+extern unsigned IOCTL_KDGKBTYPE;
+extern unsigned IOCTL_KDMKTONE;
+extern unsigned IOCTL_KDSETLED;
+extern unsigned IOCTL_KDSETMODE;
+extern unsigned IOCTL_KDSKBMODE;
+
+extern const int si_SEGV_MAPERR;
+extern const int si_SEGV_ACCERR;
+
+extern const unsigned MD5_CTX_sz;
+extern const unsigned MD5_return_length;
+
+#define SHA2_EXTERN(LEN) \
+ extern const unsigned SHA##LEN##_CTX_sz; \
+ extern const unsigned SHA##LEN##_return_length; \
+ extern const unsigned SHA##LEN##_block_length; \
+ extern const unsigned SHA##LEN##_digest_length
+
+SHA2_EXTERN(224);
+SHA2_EXTERN(256);
+SHA2_EXTERN(384);
+SHA2_EXTERN(512);
+
+#undef SHA2_EXTERN
+
+struct __sanitizer_cap_rights {
+ u64 cr_rights[2];
+};
+
+typedef struct __sanitizer_cap_rights __sanitizer_cap_rights_t;
+extern unsigned struct_cap_rights_sz;
+
+extern unsigned struct_fstab_sz;
+extern unsigned struct_StringList_sz;
+} // namespace __sanitizer
+
+# define CHECK_TYPE_SIZE(TYPE) \
+ COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
+
+# define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \
+ COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \
+ sizeof(((CLASS *)NULL)->MEMBER)); \
+ COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
+ offsetof(CLASS, MEMBER))
+
+// For sigaction, which is a function and struct at the same time,
+// and thus requires explicit "struct" in sizeof() expression.
+# define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
+ COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \
+ sizeof(((struct CLASS *)NULL)->MEMBER)); \
+ COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
+ offsetof(struct CLASS, MEMBER))
+
+# define SIGACTION_SYMNAME sigaction
+
+#endif
+
+#endif // SANITIZER_FREEBSD
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp
new file mode 100644
index 00000000000..bf0f355847c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp
@@ -0,0 +1,103 @@
+//===-- sanitizer_platform_limits_linux.cpp -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer common code.
+//
+// Sizes and layouts of linux kernel data structures.
+//===----------------------------------------------------------------------===//
+
+// This is a separate compilation unit for linux headers that conflict with
+// userspace headers.
+// Most "normal" includes go in sanitizer_platform_limits_posix.cpp
+
+#include "sanitizer_platform.h"
+#if SANITIZER_LINUX
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform_limits_posix.h"
+
+// For offsetof -> __builtin_offsetof definition.
+#include <stddef.h>
+
+// With old kernels (and even new kernels on powerpc) asm/stat.h uses types that
+// are not defined anywhere in userspace headers. Fake them. This seems to work
+// fine with newer headers, too.
+#include <linux/posix_types.h>
+# if defined(__x86_64__) || defined(__mips__) || defined(__hexagon__)
+# include <sys/stat.h>
+# else
+# define ino_t __kernel_ino_t
+# define mode_t __kernel_mode_t
+# define nlink_t __kernel_nlink_t
+# define uid_t __kernel_uid_t
+# define gid_t __kernel_gid_t
+# define off_t __kernel_off_t
+# define time_t __kernel_time_t
+// This header seems to contain the definitions of _kernel_ stat* structs.
+# include <asm/stat.h>
+# undef ino_t
+# undef mode_t
+# undef nlink_t
+# undef uid_t
+# undef gid_t
+# undef off_t
+# endif
+
+# include <linux/aio_abi.h>
+
+# if !SANITIZER_ANDROID
+# include <sys/statfs.h>
+# include <linux/perf_event.h>
+# endif
+
+using namespace __sanitizer;
+
+# if !defined(__powerpc64__) && !defined(__x86_64__) && \
+ !defined(__aarch64__) && !defined(__mips__) && !defined(__s390__) && \
+ !defined(__sparc__) && !defined(__riscv) && !defined(__hexagon__) && \
+ !defined(__loongarch__)
+COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat));
+#endif
+
+COMPILER_CHECK(struct_kernel_stat_sz == sizeof(struct stat));
+
+#if defined(__i386__)
+COMPILER_CHECK(struct_kernel_stat64_sz == sizeof(struct stat64));
+#endif
+
+CHECK_TYPE_SIZE(io_event);
+CHECK_SIZE_AND_OFFSET(io_event, data);
+CHECK_SIZE_AND_OFFSET(io_event, obj);
+CHECK_SIZE_AND_OFFSET(io_event, res);
+CHECK_SIZE_AND_OFFSET(io_event, res2);
+
+#if !SANITIZER_ANDROID
+COMPILER_CHECK(sizeof(struct __sanitizer_perf_event_attr) <=
+ sizeof(struct perf_event_attr));
+CHECK_SIZE_AND_OFFSET(perf_event_attr, type);
+CHECK_SIZE_AND_OFFSET(perf_event_attr, size);
+#endif
+
+COMPILER_CHECK(iocb_cmd_pread == IOCB_CMD_PREAD);
+COMPILER_CHECK(iocb_cmd_pwrite == IOCB_CMD_PWRITE);
+#if !SANITIZER_ANDROID
+COMPILER_CHECK(iocb_cmd_preadv == IOCB_CMD_PREADV);
+COMPILER_CHECK(iocb_cmd_pwritev == IOCB_CMD_PWRITEV);
+#endif
+
+CHECK_TYPE_SIZE(iocb);
+CHECK_SIZE_AND_OFFSET(iocb, aio_data);
+// Skip aio_key, it's weird.
+CHECK_SIZE_AND_OFFSET(iocb, aio_lio_opcode);
+CHECK_SIZE_AND_OFFSET(iocb, aio_reqprio);
+CHECK_SIZE_AND_OFFSET(iocb, aio_fildes);
+CHECK_SIZE_AND_OFFSET(iocb, aio_buf);
+CHECK_SIZE_AND_OFFSET(iocb, aio_nbytes);
+CHECK_SIZE_AND_OFFSET(iocb, aio_offset);
+
+#endif // SANITIZER_LINUX
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp
new file mode 100644
index 00000000000..076bfd04076
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp
@@ -0,0 +1,2740 @@
+//===-- sanitizer_platform_limits_netbsd.cpp ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer common code.
+//
+// Sizes and layouts of platform-specific NetBSD data structures.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_NETBSD
+
+#define _KMEMUSER
+#define RAY_DO_SIGLEV
+#define __LEGACY_PT_LWPINFO
+
+// clang-format off
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/disk.h>
+#include <sys/disklabel.h>
+#include <sys/mount.h>
+#error #include <sys/agpio.h>
+#error #include <sys/ataio.h>
+#error #include <sys/audioio.h>
+#error #include <sys/cdbr.h>
+#error #include <sys/cdio.h>
+#error #include <sys/chio.h>
+#error #include <sys/clockctl.h>
+#error #include <sys/cpuio.h>
+#error #include <sys/dkbad.h>
+#error #include <sys/dkio.h>
+#error #include <sys/drvctlio.h>
+#error #include <sys/dvdio.h>
+#error #include <sys/envsys.h>
+#include <sys/event.h>
+#error #include <sys/fdio.h>
+#include <sys/filio.h>
+#error #include <sys/gpio.h>
+#include <sys/ioctl.h>
+#error #include <sys/ioctl_compat.h>
+#error #include <sys/joystick.h>
+#error #include <sys/ksyms.h>
+#error #include <sys/lua.h>
+#error #include <sys/midiio.h>
+#include <sys/mtio.h>
+#error #include <sys/power.h>
+#error #include <sys/radioio.h>
+#error #include <sys/rndio.h>
+#error #include <sys/scanio.h>
+#error #include <sys/scsiio.h>
+#include <sys/sockio.h>
+#error #include <sys/timepps.h>
+#include <sys/ttycom.h>
+#error #include <sys/verified_exec.h>
+#include <sys/videoio.h>
+#error #include <sys/wdog.h>
+#include <sys/event.h>
+#include <sys/filio.h>
+#include <sys/ipc.h>
+#error #include <sys/ipmi.h>
+#error #include <sys/kcov.h>
+#include <sys/mman.h>
+#include <sys/module.h>
+#include <sys/mount.h>
+#error #include <sys/mqueue.h>
+#include <sys/msg.h>
+#include <sys/mtio.h>
+#include <sys/ptrace.h>
+
+// Compat for NetBSD < 9.99.30.
+#ifndef PT_LWPSTATUS
+#define PT_LWPSTATUS 24
+#endif
+#ifndef PT_LWPNEXT
+#define PT_LWPNEXT 25
+#endif
+
+#include <sys/resource.h>
+#include <sys/sem.h>
+#error #include <sys/scsiio.h>
+#error #include <sys/sha1.h>
+#error #include <sys/sha2.h>
+#include <sys/shm.h>
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/soundcard.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/times.h>
+#include <sys/timespec.h>
+#include <sys/timex.h>
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <sys/utsname.h>
+#error #include <altq/altq.h>
+#error #include <altq/altq_afmap.h>
+#error #include <altq/altq_blue.h>
+#error #include <altq/altq_cbq.h>
+#error #include <altq/altq_cdnr.h>
+#error #include <altq/altq_fifoq.h>
+#error #include <altq/altq_hfsc.h>
+#error #include <altq/altq_jobs.h>
+#error #include <altq/altq_priq.h>
+#error #include <altq/altq_red.h>
+#error #include <altq/altq_rio.h>
+#error #include <altq/altq_wfq.h>
+#include <arpa/inet.h>
+#include <crypto/cryptodev.h>
+#error #include <dev/apm/apmio.h>
+#error #include <dev/dm/netbsd-dm.h>
+#error #include <dev/dmover/dmover_io.h>
+#error #include <dev/dtv/dtvio_demux.h>
+#error #include <dev/dtv/dtvio_frontend.h>
+#if !__NetBSD_Prereq__(9, 99, 26)
+#error #include <dev/filemon/filemon.h>
+#else
+#define FILEMON_SET_FD _IOWR('S', 1, int)
+#define FILEMON_SET_PID _IOWR('S', 2, pid_t)
+#endif
+#error #include <dev/hdaudio/hdaudioio.h>
+#error #include <dev/hdmicec/hdmicecio.h>
+#error #include <dev/hpc/hpcfbio.h>
+#error #include <dev/i2o/iopio.h>
+#error #include <dev/ic/athioctl.h>
+#error #include <dev/ic/bt8xx.h>
+#error #include <dev/ic/icp_ioctl.h>
+#error #include <dev/ic/isp_ioctl.h>
+#error #include <dev/ic/mlxio.h>
+#error #include <dev/ic/qemufwcfgio.h>
+#error #include <dev/ic/nvmeio.h>
+#error #include <dev/ir/irdaio.h>
+#error #include <dev/isa/isvio.h>
+#error #include <dev/isa/wtreg.h>
+#if __has_include(<dev/iscsi/iscsi_ioctl.h>)
+#error #include <dev/iscsi/iscsi_ioctl.h>
+#else
+/* Fallback for MKISCSI=no */
+
+typedef struct {
+ uint32_t status;
+ uint32_t session_id;
+ uint32_t connection_id;
+} iscsi_conn_status_parameters_t;
+
+typedef struct {
+ uint32_t status;
+ uint16_t interface_version;
+ uint16_t major;
+ uint16_t minor;
+ uint8_t version_string[224];
+} iscsi_get_version_parameters_t;
+
+typedef struct {
+ uint32_t status;
+ uint32_t session_id;
+ uint32_t connection_id;
+ struct {
+ unsigned int immediate : 1;
+ } options;
+ uint64_t lun;
+ scsireq_t req; /* from <sys/scsiio.h> */
+} iscsi_iocommand_parameters_t;
+
+typedef enum {
+ ISCSI_AUTH_None = 0,
+ ISCSI_AUTH_CHAP = 1,
+ ISCSI_AUTH_KRB5 = 2,
+ ISCSI_AUTH_SRP = 3
+} iscsi_auth_types_t;
+
+typedef enum {
+ ISCSI_LOGINTYPE_DISCOVERY = 0,
+ ISCSI_LOGINTYPE_NOMAP = 1,
+ ISCSI_LOGINTYPE_MAP = 2
+} iscsi_login_session_type_t;
+
+typedef enum { ISCSI_DIGEST_None = 0, ISCSI_DIGEST_CRC32C = 1 } iscsi_digest_t;
+
+typedef enum {
+ ISCSI_SESSION_TERMINATED = 1,
+ ISCSI_CONNECTION_TERMINATED,
+ ISCSI_RECOVER_CONNECTION,
+ ISCSI_DRIVER_TERMINATING
+} iscsi_event_t;
+
+typedef struct {
+ unsigned int mutual_auth : 1;
+ unsigned int is_secure : 1;
+ unsigned int auth_number : 4;
+ iscsi_auth_types_t auth_type[4];
+} iscsi_auth_info_t;
+
+typedef struct {
+ uint32_t status;
+ int socket;
+ struct {
+ unsigned int HeaderDigest : 1;
+ unsigned int DataDigest : 1;
+ unsigned int MaxConnections : 1;
+ unsigned int DefaultTime2Wait : 1;
+ unsigned int DefaultTime2Retain : 1;
+ unsigned int MaxRecvDataSegmentLength : 1;
+ unsigned int auth_info : 1;
+ unsigned int user_name : 1;
+ unsigned int password : 1;
+ unsigned int target_password : 1;
+ unsigned int TargetName : 1;
+ unsigned int TargetAlias : 1;
+ unsigned int ErrorRecoveryLevel : 1;
+ } is_present;
+ iscsi_auth_info_t auth_info;
+ iscsi_login_session_type_t login_type;
+ iscsi_digest_t HeaderDigest;
+ iscsi_digest_t DataDigest;
+ uint32_t session_id;
+ uint32_t connection_id;
+ uint32_t MaxRecvDataSegmentLength;
+ uint16_t MaxConnections;
+ uint16_t DefaultTime2Wait;
+ uint16_t DefaultTime2Retain;
+ uint16_t ErrorRecoveryLevel;
+ void *user_name;
+ void *password;
+ void *target_password;
+ void *TargetName;
+ void *TargetAlias;
+} iscsi_login_parameters_t;
+
+typedef struct {
+ uint32_t status;
+ uint32_t session_id;
+} iscsi_logout_parameters_t;
+
+typedef struct {
+ uint32_t status;
+ uint32_t event_id;
+} iscsi_register_event_parameters_t;
+
+typedef struct {
+ uint32_t status;
+ uint32_t session_id;
+ uint32_t connection_id;
+} iscsi_remove_parameters_t;
+
+typedef struct {
+ uint32_t status;
+ uint32_t session_id;
+ void *response_buffer;
+ uint32_t response_size;
+ uint32_t response_used;
+ uint32_t response_total;
+ uint8_t key[224];
+} iscsi_send_targets_parameters_t;
+
+typedef struct {
+ uint32_t status;
+ uint8_t InitiatorName[224];
+ uint8_t InitiatorAlias[224];
+ uint8_t ISID[6];
+} iscsi_set_node_name_parameters_t;
+
+typedef struct {
+ uint32_t status;
+ uint32_t event_id;
+ iscsi_event_t event_kind;
+ uint32_t session_id;
+ uint32_t connection_id;
+ uint32_t reason;
+} iscsi_wait_event_parameters_t;
+
+#define ISCSI_GET_VERSION _IOWR(0, 1, iscsi_get_version_parameters_t)
+#define ISCSI_LOGIN _IOWR(0, 2, iscsi_login_parameters_t)
+#define ISCSI_LOGOUT _IOWR(0, 3, iscsi_logout_parameters_t)
+#define ISCSI_ADD_CONNECTION _IOWR(0, 4, iscsi_login_parameters_t)
+#define ISCSI_RESTORE_CONNECTION _IOWR(0, 5, iscsi_login_parameters_t)
+#define ISCSI_REMOVE_CONNECTION _IOWR(0, 6, iscsi_remove_parameters_t)
+#define ISCSI_CONNECTION_STATUS _IOWR(0, 7, iscsi_conn_status_parameters_t)
+#define ISCSI_SEND_TARGETS _IOWR(0, 8, iscsi_send_targets_parameters_t)
+#define ISCSI_SET_NODE_NAME _IOWR(0, 9, iscsi_set_node_name_parameters_t)
+#define ISCSI_IO_COMMAND _IOWR(0, 10, iscsi_iocommand_parameters_t)
+#define ISCSI_REGISTER_EVENT _IOWR(0, 11, iscsi_register_event_parameters_t)
+#define ISCSI_DEREGISTER_EVENT _IOWR(0, 12, iscsi_register_event_parameters_t)
+#define ISCSI_WAIT_EVENT _IOWR(0, 13, iscsi_wait_event_parameters_t)
+#define ISCSI_POLL_EVENT _IOWR(0, 14, iscsi_wait_event_parameters_t)
+#endif
+#error #include <dev/ofw/openfirmio.h>
+#error #include <dev/pci/amrio.h>
+#error #include <dev/pci/mlyreg.h>
+#error #include <dev/pci/mlyio.h>
+#error #include <dev/pci/pciio.h>
+#error #include <dev/pci/tweio.h>
+#error #include <dev/pcmcia/if_cnwioctl.h>
+#include <net/bpf.h>
+#error #include <net/if_gre.h>
+#error #include <net/ppp_defs.h>
+#include <net/if_ppp.h>
+#error #include <net/if_pppoe.h>
+#error #include <net/if_sppp.h>
+#error #include <net/if_srt.h>
+#error #include <net/if_tap.h>
+#error #include <net/if_tun.h>
+#error #include <net/npf.h>
+#include <net/pfvar.h>
+#error #include <net/slip.h>
+#error #include <netbt/hci.h>
+#error #include <netinet/ip_compat.h>
+#if __has_include(<netinet/ip_fil.h>)
+#error #include <netinet/ip_fil.h>
+#error #include <netinet/ip_nat.h>
+#error #include <netinet/ip_proxy.h>
+#else
+/* Fallback for MKIPFILTER=no */
+
+typedef struct ap_control {
+ char apc_label[16];
+ char apc_config[16];
+ unsigned char apc_p;
+ unsigned long apc_cmd;
+ unsigned long apc_arg;
+ void *apc_data;
+ size_t apc_dsize;
+} ap_ctl_t;
+
+typedef struct ipftq {
+ ipfmutex_t ifq_lock;
+ unsigned int ifq_ttl;
+ void *ifq_head;
+ void **ifq_tail;
+ void *ifq_next;
+ void **ifq_pnext;
+ int ifq_ref;
+ unsigned int ifq_flags;
+} ipftq_t;
+
+typedef struct ipfobj {
+ uint32_t ipfo_rev;
+ uint32_t ipfo_size;
+ void *ipfo_ptr;
+ int ipfo_type;
+ int ipfo_offset;
+ int ipfo_retval;
+ unsigned char ipfo_xxxpad[28];
+} ipfobj_t;
+
+#define SIOCADNAT _IOW('r', 60, struct ipfobj)
+#define SIOCRMNAT _IOW('r', 61, struct ipfobj)
+#define SIOCGNATS _IOWR('r', 62, struct ipfobj)
+#define SIOCGNATL _IOWR('r', 63, struct ipfobj)
+#define SIOCPURGENAT _IOWR('r', 100, struct ipfobj)
+#endif
+#error #include <netinet6/in6_var.h>
+#error #include <netinet6/nd6.h>
+#if !__NetBSD_Prereq__(9, 99, 51)
+#error #include <netsmb/smb_dev.h>
+#else
+struct smbioc_flags {
+ int ioc_level;
+ int ioc_mask;
+ int ioc_flags;
+};
+struct smbioc_oshare {
+ int ioc_opt;
+ int ioc_stype;
+ char ioc_share[129];
+ char ioc_password[129];
+ uid_t ioc_owner;
+ gid_t ioc_group;
+ mode_t ioc_mode;
+ mode_t ioc_rights;
+};
+struct smbioc_ossn {
+ int ioc_opt;
+ uint32_t ioc_svlen;
+ struct sockaddr *ioc_server;
+ uint32_t ioc_lolen;
+ struct sockaddr *ioc_local;
+ char ioc_srvname[16];
+ int ioc_timeout;
+ int ioc_retrycount;
+ char ioc_localcs[16];
+ char ioc_servercs[16];
+ char ioc_user[129];
+ char ioc_workgroup[129];
+ char ioc_password[129];
+ uid_t ioc_owner;
+ gid_t ioc_group;
+ mode_t ioc_mode;
+ mode_t ioc_rights;
+};
+struct smbioc_lookup {
+ int ioc_level;
+ int ioc_flags;
+ struct smbioc_ossn ioc_ssn;
+ struct smbioc_oshare ioc_sh;
+};
+struct smbioc_rq {
+ u_char ioc_cmd;
+ u_char ioc_twc;
+ void *ioc_twords;
+ u_short ioc_tbc;
+ void *ioc_tbytes;
+ int ioc_rpbufsz;
+ char *ioc_rpbuf;
+ u_char ioc_rwc;
+ u_short ioc_rbc;
+};
+struct smbioc_rw {
+ u_int16_t ioc_fh;
+ char *ioc_base;
+ off_t ioc_offset;
+ int ioc_cnt;
+};
+#define SMBIOC_OPENSESSION _IOW('n', 100, struct smbioc_ossn)
+#define SMBIOC_OPENSHARE _IOW('n', 101, struct smbioc_oshare)
+#define SMBIOC_REQUEST _IOWR('n', 102, struct smbioc_rq)
+#define SMBIOC_T2RQ _IOWR('n', 103, struct smbioc_t2rq)
+#define SMBIOC_SETFLAGS _IOW('n', 104, struct smbioc_flags)
+#define SMBIOC_LOOKUP _IOW('n', 106, struct smbioc_lookup)
+#define SMBIOC_READ _IOWR('n', 107, struct smbioc_rw)
+#define SMBIOC_WRITE _IOWR('n', 108, struct smbioc_rw)
+#endif
+#error #include <dev/biovar.h>
+#error #include <dev/bluetooth/btdev.h>
+#error #include <dev/bluetooth/btsco.h>
+#error #include <dev/ccdvar.h>
+#error #include <dev/cgdvar.h>
+#error #include <dev/fssvar.h>
+#error #include <dev/kttcpio.h>
+#error #include <dev/lockstat.h>
+#error #include <dev/md.h>
+#error #include <net/if_ether.h>
+#error #include <dev/pcmcia/if_rayreg.h>
+#include <stdio.h>
+#error #include <dev/raidframe/raidframeio.h>
+#error #include <dev/sbus/mbppio.h>
+#error #include <dev/scsipi/ses.h>
+#error #include <dev/spi/spi_io.h>
+#error #include <dev/spkrio.h>
+#error #include <dev/sun/disklabel.h>
+#error #include <dev/sun/fbio.h>
+#error #include <dev/sun/kbio.h>
+#error #include <dev/sun/vuid_event.h>
+#error #include <dev/tc/sticio.h>
+#error #include <dev/usb/ukyopon.h>
+#if !__NetBSD_Prereq__(9, 99, 44)
+#error #include <dev/usb/urio.h>
+#else
+struct urio_command {
+ unsigned short length;
+ int request;
+ int requesttype;
+ int value;
+ int index;
+ void *buffer;
+ int timeout;
+};
+#define URIO_SEND_COMMAND _IOWR('U', 200, struct urio_command)
+#define URIO_RECV_COMMAND _IOWR('U', 201, struct urio_command)
+#endif
+#error #include <dev/usb/usb.h>
+#error #include <dev/usb/utoppy.h>
+#error #include <dev/vme/xio.h>
+#error #include <dev/vndvar.h>
+#error #include <dev/wscons/wsconsio.h>
+#error #include <dev/wscons/wsdisplay_usl_io.h>
+#error #include <fs/autofs/autofs_ioctl.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <glob.h>
+#include <grp.h>
+#include <ifaddrs.h>
+#include <limits.h>
+#error #include <link_elf.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#error #include <netinet/ip_mroute.h>
+#include <netinet/sctp_uio.h>
+#include <poll.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stddef.h>
+#include <md2.h>
+#include <md4.h>
+#error #include <md5.h>
+#error #include <rmd160.h>
+#include <soundcard.h>
+#include <term.h>
+#include <termios.h>
+#include <time.h>
+#include <ttyent.h>
+#include <utime.h>
+#include <utmp.h>
+#include <utmpx.h>
+#include <vis.h>
+#include <wchar.h>
+#include <wordexp.h>
+#include <ttyent.h>
+#include <fts.h>
+#include <regex.h>
+#include <fstab.h>
+#error #include <stringlist.h>
+
+#if defined(__x86_64__)
+#error #include <nvmm.h>
+#endif
+// clang-format on
+
+// Include these after system headers to avoid name clashes and ambiguities.
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_platform_limits_netbsd.h"
+
+namespace __sanitizer {
+void *__sanitizer_get_link_map_by_dlopen_handle(void *handle) {
+ void *p = nullptr;
+ return internal_dlinfo(handle, RTLD_DI_LINKMAP, &p) == 0 ? p : nullptr;
+}
+
+unsigned struct_utsname_sz = sizeof(struct utsname);
+unsigned struct_stat_sz = sizeof(struct stat);
+unsigned struct_rusage_sz = sizeof(struct rusage);
+unsigned struct_tm_sz = sizeof(struct tm);
+unsigned struct_passwd_sz = sizeof(struct passwd);
+unsigned struct_group_sz = sizeof(struct group);
+unsigned siginfo_t_sz = sizeof(siginfo_t);
+unsigned struct_sigaction_sz = sizeof(struct sigaction);
+unsigned struct_stack_t_sz = sizeof(stack_t);
+unsigned struct_itimerval_sz = sizeof(struct itimerval);
+unsigned pthread_t_sz = sizeof(pthread_t);
+unsigned pthread_mutex_t_sz = sizeof(pthread_mutex_t);
+unsigned pthread_cond_t_sz = sizeof(pthread_cond_t);
+unsigned pid_t_sz = sizeof(pid_t);
+unsigned timeval_sz = sizeof(timeval);
+unsigned uid_t_sz = sizeof(uid_t);
+unsigned gid_t_sz = sizeof(gid_t);
+unsigned mbstate_t_sz = sizeof(mbstate_t);
+unsigned sigset_t_sz = sizeof(sigset_t);
+unsigned struct_timezone_sz = sizeof(struct timezone);
+unsigned struct_tms_sz = sizeof(struct tms);
+unsigned struct_sigevent_sz = sizeof(struct sigevent);
+unsigned struct_sched_param_sz = sizeof(struct sched_param);
+unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
+unsigned ucontext_t_sz(void *ctx) { return sizeof(ucontext_t); }
+unsigned struct_rlimit_sz = sizeof(struct rlimit);
+unsigned struct_timespec_sz = sizeof(struct timespec);
+unsigned struct_sembuf_sz = sizeof(struct sembuf);
+unsigned struct_kevent_sz = sizeof(struct kevent);
+unsigned struct_FTS_sz = sizeof(FTS);
+unsigned struct_FTSENT_sz = sizeof(FTSENT);
+unsigned struct_regex_sz = sizeof(regex_t);
+unsigned struct_regmatch_sz = sizeof(regmatch_t);
+unsigned struct_fstab_sz = sizeof(struct fstab);
+unsigned struct_utimbuf_sz = sizeof(struct utimbuf);
+unsigned struct_itimerspec_sz = sizeof(struct itimerspec);
+unsigned struct_timex_sz = sizeof(struct timex);
+unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds);
+unsigned struct_mq_attr_sz = sizeof(struct mq_attr);
+unsigned struct_statvfs_sz = sizeof(struct statvfs);
+unsigned struct_sigaltstack_sz = sizeof(stack_t);
+
+const uptr sig_ign = (uptr)SIG_IGN;
+const uptr sig_dfl = (uptr)SIG_DFL;
+const uptr sig_err = (uptr)SIG_ERR;
+const uptr sa_siginfo = (uptr)SA_SIGINFO;
+
+const unsigned long __sanitizer_bufsiz = BUFSIZ;
+
+int ptrace_pt_io = PT_IO;
+int ptrace_pt_lwpinfo = PT_LWPINFO;
+int ptrace_pt_set_event_mask = PT_SET_EVENT_MASK;
+int ptrace_pt_get_event_mask = PT_GET_EVENT_MASK;
+int ptrace_pt_get_process_state = PT_GET_PROCESS_STATE;
+int ptrace_pt_set_siginfo = PT_SET_SIGINFO;
+int ptrace_pt_get_siginfo = PT_GET_SIGINFO;
+int ptrace_pt_lwpstatus = PT_LWPSTATUS;
+int ptrace_pt_lwpnext = PT_LWPNEXT;
+int ptrace_piod_read_d = PIOD_READ_D;
+int ptrace_piod_write_d = PIOD_WRITE_D;
+int ptrace_piod_read_i = PIOD_READ_I;
+int ptrace_piod_write_i = PIOD_WRITE_I;
+int ptrace_piod_read_auxv = PIOD_READ_AUXV;
+
+#if defined(PT_SETREGS) && defined(PT_GETREGS)
+int ptrace_pt_setregs = PT_SETREGS;
+int ptrace_pt_getregs = PT_GETREGS;
+#else
+int ptrace_pt_setregs = -1;
+int ptrace_pt_getregs = -1;
+#endif
+
+#if defined(PT_SETFPREGS) && defined(PT_GETFPREGS)
+int ptrace_pt_setfpregs = PT_SETFPREGS;
+int ptrace_pt_getfpregs = PT_GETFPREGS;
+#else
+int ptrace_pt_setfpregs = -1;
+int ptrace_pt_getfpregs = -1;
+#endif
+
+#if defined(PT_SETDBREGS) && defined(PT_GETDBREGS)
+int ptrace_pt_setdbregs = PT_SETDBREGS;
+int ptrace_pt_getdbregs = PT_GETDBREGS;
+#else
+int ptrace_pt_setdbregs = -1;
+int ptrace_pt_getdbregs = -1;
+#endif
+
+unsigned struct_ptrace_ptrace_io_desc_struct_sz = sizeof(struct ptrace_io_desc);
+unsigned struct_ptrace_ptrace_lwpinfo_struct_sz = sizeof(struct ptrace_lwpinfo);
+unsigned struct_ptrace_ptrace_lwpstatus_struct_sz =
+ sizeof(struct __sanitizer_ptrace_lwpstatus);
+unsigned struct_ptrace_ptrace_event_struct_sz = sizeof(ptrace_event_t);
+unsigned struct_ptrace_ptrace_siginfo_struct_sz = sizeof(ptrace_siginfo_t);
+
+#if defined(PT_SETREGS)
+unsigned struct_ptrace_reg_struct_sz = sizeof(struct reg);
+#else
+unsigned struct_ptrace_reg_struct_sz = -1;
+#endif
+
+#if defined(PT_SETFPREGS)
+unsigned struct_ptrace_fpreg_struct_sz = sizeof(struct fpreg);
+#else
+unsigned struct_ptrace_fpreg_struct_sz = -1;
+#endif
+
+#if defined(PT_SETDBREGS)
+unsigned struct_ptrace_dbreg_struct_sz = sizeof(struct dbreg);
+#else
+unsigned struct_ptrace_dbreg_struct_sz = -1;
+#endif
+
+int shmctl_ipc_stat = (int)IPC_STAT;
+
+unsigned struct_utmp_sz = sizeof(struct utmp);
+unsigned struct_utmpx_sz = sizeof(struct utmpx);
+
+int map_fixed = MAP_FIXED;
+
+int af_inet = (int)AF_INET;
+int af_inet6 = (int)AF_INET6;
+
+uptr __sanitizer_in_addr_sz(int af) {
+ if (af == AF_INET)
+ return sizeof(struct in_addr);
+ else if (af == AF_INET6)
+ return sizeof(struct in6_addr);
+ else
+ return 0;
+}
+
+unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
+
+int glob_nomatch = GLOB_NOMATCH;
+int glob_altdirfunc = GLOB_ALTDIRFUNC;
+const int wordexp_wrde_dooffs = WRDE_DOOFFS;
+
+unsigned path_max = PATH_MAX;
+
+int struct_ttyent_sz = sizeof(struct ttyent);
+
+struct __sanitizer_nvlist_ref_t {
+ void *buf;
+ uptr len;
+ int flags;
+};
+
+typedef __sanitizer_nvlist_ref_t nvlist_ref_t;
+
+// ioctl arguments
+unsigned struct_altqreq_sz = sizeof(altqreq);
+unsigned struct_amr_user_ioctl_sz = sizeof(amr_user_ioctl);
+unsigned struct_ap_control_sz = sizeof(ap_control);
+unsigned struct_apm_ctl_sz = sizeof(apm_ctl);
+unsigned struct_apm_event_info_sz = sizeof(apm_event_info);
+unsigned struct_apm_power_info_sz = sizeof(apm_power_info);
+unsigned struct_atabusiodetach_args_sz = sizeof(atabusiodetach_args);
+unsigned struct_atabusioscan_args_sz = sizeof(atabusioscan_args);
+unsigned struct_ath_diag_sz = sizeof(ath_diag);
+unsigned struct_atm_flowmap_sz = sizeof(atm_flowmap);
+unsigned struct_audio_buf_info_sz = sizeof(audio_buf_info);
+unsigned struct_audio_device_sz = sizeof(audio_device);
+unsigned struct_audio_encoding_sz = sizeof(audio_encoding);
+unsigned struct_audio_info_sz = sizeof(audio_info);
+unsigned struct_audio_offset_sz = sizeof(audio_offset);
+unsigned struct_bio_locate_sz = sizeof(bio_locate);
+unsigned struct_bioc_alarm_sz = sizeof(bioc_alarm);
+unsigned struct_bioc_blink_sz = sizeof(bioc_blink);
+unsigned struct_bioc_disk_sz = sizeof(bioc_disk);
+unsigned struct_bioc_inq_sz = sizeof(bioc_inq);
+unsigned struct_bioc_setstate_sz = sizeof(bioc_setstate);
+unsigned struct_bioc_vol_sz = sizeof(bioc_vol);
+unsigned struct_bioc_volops_sz = sizeof(bioc_volops);
+unsigned struct_bktr_chnlset_sz = sizeof(bktr_chnlset);
+unsigned struct_bktr_remote_sz = sizeof(bktr_remote);
+unsigned struct_blue_conf_sz = sizeof(blue_conf);
+unsigned struct_blue_interface_sz = sizeof(blue_interface);
+unsigned struct_blue_stats_sz = sizeof(blue_stats);
+unsigned struct_bpf_dltlist_sz = sizeof(bpf_dltlist);
+unsigned struct_bpf_program_sz = sizeof(bpf_program);
+unsigned struct_bpf_stat_old_sz = sizeof(bpf_stat_old);
+unsigned struct_bpf_stat_sz = sizeof(bpf_stat);
+unsigned struct_bpf_version_sz = sizeof(bpf_version);
+unsigned struct_btreq_sz = sizeof(btreq);
+unsigned struct_btsco_info_sz = sizeof(btsco_info);
+unsigned struct_buffmem_desc_sz = sizeof(buffmem_desc);
+unsigned struct_cbq_add_class_sz = sizeof(cbq_add_class);
+unsigned struct_cbq_add_filter_sz = sizeof(cbq_add_filter);
+unsigned struct_cbq_delete_class_sz = sizeof(cbq_delete_class);
+unsigned struct_cbq_delete_filter_sz = sizeof(cbq_delete_filter);
+unsigned struct_cbq_getstats_sz = sizeof(cbq_getstats);
+unsigned struct_cbq_interface_sz = sizeof(cbq_interface);
+unsigned struct_cbq_modify_class_sz = sizeof(cbq_modify_class);
+unsigned struct_ccd_ioctl_sz = sizeof(ccd_ioctl);
+unsigned struct_cdnr_add_element_sz = sizeof(cdnr_add_element);
+unsigned struct_cdnr_add_filter_sz = sizeof(cdnr_add_filter);
+unsigned struct_cdnr_add_tbmeter_sz = sizeof(cdnr_add_tbmeter);
+unsigned struct_cdnr_add_trtcm_sz = sizeof(cdnr_add_trtcm);
+unsigned struct_cdnr_add_tswtcm_sz = sizeof(cdnr_add_tswtcm);
+unsigned struct_cdnr_delete_element_sz = sizeof(cdnr_delete_element);
+unsigned struct_cdnr_delete_filter_sz = sizeof(cdnr_delete_filter);
+unsigned struct_cdnr_get_stats_sz = sizeof(cdnr_get_stats);
+unsigned struct_cdnr_interface_sz = sizeof(cdnr_interface);
+unsigned struct_cdnr_modify_tbmeter_sz = sizeof(cdnr_modify_tbmeter);
+unsigned struct_cdnr_modify_trtcm_sz = sizeof(cdnr_modify_trtcm);
+unsigned struct_cdnr_modify_tswtcm_sz = sizeof(cdnr_modify_tswtcm);
+unsigned struct_cdnr_tbmeter_stats_sz = sizeof(cdnr_tbmeter_stats);
+unsigned struct_cdnr_tcm_stats_sz = sizeof(cdnr_tcm_stats);
+unsigned struct_cgd_ioctl_sz = sizeof(cgd_ioctl);
+unsigned struct_cgd_user_sz = sizeof(cgd_user);
+unsigned struct_changer_element_status_request_sz =
+ sizeof(changer_element_status_request);
+unsigned struct_changer_exchange_request_sz = sizeof(changer_exchange_request);
+unsigned struct_changer_move_request_sz = sizeof(changer_move_request);
+unsigned struct_changer_params_sz = sizeof(changer_params);
+unsigned struct_changer_position_request_sz = sizeof(changer_position_request);
+unsigned struct_changer_set_voltag_request_sz =
+ sizeof(changer_set_voltag_request);
+unsigned struct_clockctl_adjtime_sz = sizeof(clockctl_adjtime);
+unsigned struct_clockctl_clock_settime_sz = sizeof(clockctl_clock_settime);
+unsigned struct_clockctl_ntp_adjtime_sz = sizeof(clockctl_ntp_adjtime);
+unsigned struct_clockctl_settimeofday_sz = sizeof(clockctl_settimeofday);
+unsigned struct_cnwistats_sz = sizeof(cnwistats);
+unsigned struct_cnwitrail_sz = sizeof(cnwitrail);
+unsigned struct_cnwstatus_sz = sizeof(cnwstatus);
+unsigned struct_count_info_sz = sizeof(count_info);
+unsigned struct_cpu_ucode_sz = sizeof(cpu_ucode);
+unsigned struct_cpu_ucode_version_sz = sizeof(cpu_ucode_version);
+unsigned struct_crypt_kop_sz = sizeof(crypt_kop);
+unsigned struct_crypt_mkop_sz = sizeof(crypt_mkop);
+unsigned struct_crypt_mop_sz = sizeof(crypt_mop);
+unsigned struct_crypt_op_sz = sizeof(crypt_op);
+unsigned struct_crypt_result_sz = sizeof(crypt_result);
+unsigned struct_crypt_sfop_sz = sizeof(crypt_sfop);
+unsigned struct_crypt_sgop_sz = sizeof(crypt_sgop);
+unsigned struct_cryptret_sz = sizeof(cryptret);
+unsigned struct_devdetachargs_sz = sizeof(devdetachargs);
+unsigned struct_devlistargs_sz = sizeof(devlistargs);
+unsigned struct_devpmargs_sz = sizeof(devpmargs);
+unsigned struct_devrescanargs_sz = sizeof(devrescanargs);
+unsigned struct_disk_badsecinfo_sz = sizeof(disk_badsecinfo);
+unsigned struct_disk_strategy_sz = sizeof(disk_strategy);
+unsigned struct_disklabel_sz = sizeof(disklabel);
+unsigned struct_dkbad_sz = sizeof(dkbad);
+unsigned struct_dkwedge_info_sz = sizeof(dkwedge_info);
+unsigned struct_dkwedge_list_sz = sizeof(dkwedge_list);
+unsigned struct_dmio_setfunc_sz = sizeof(dmio_setfunc);
+unsigned struct_dmx_pes_filter_params_sz = sizeof(dmx_pes_filter_params);
+unsigned struct_dmx_sct_filter_params_sz = sizeof(dmx_sct_filter_params);
+unsigned struct_dmx_stc_sz = sizeof(dmx_stc);
+unsigned struct_dvb_diseqc_master_cmd_sz = sizeof(dvb_diseqc_master_cmd);
+unsigned struct_dvb_diseqc_slave_reply_sz = sizeof(dvb_diseqc_slave_reply);
+unsigned struct_dvb_frontend_event_sz = sizeof(dvb_frontend_event);
+unsigned struct_dvb_frontend_info_sz = sizeof(dvb_frontend_info);
+unsigned struct_dvb_frontend_parameters_sz = sizeof(dvb_frontend_parameters);
+unsigned struct_eccapreq_sz = sizeof(eccapreq);
+unsigned struct_fbcmap_sz = sizeof(fbcmap);
+unsigned struct_fbcurpos_sz = sizeof(fbcurpos);
+unsigned struct_fbcursor_sz = sizeof(fbcursor);
+unsigned struct_fbgattr_sz = sizeof(fbgattr);
+unsigned struct_fbsattr_sz = sizeof(fbsattr);
+unsigned struct_fbtype_sz = sizeof(fbtype);
+unsigned struct_fdformat_cmd_sz = sizeof(fdformat_cmd);
+unsigned struct_fdformat_parms_sz = sizeof(fdformat_parms);
+unsigned struct_fifoq_conf_sz = sizeof(fifoq_conf);
+unsigned struct_fifoq_getstats_sz = sizeof(fifoq_getstats);
+unsigned struct_fifoq_interface_sz = sizeof(fifoq_interface);
+unsigned struct_format_op_sz = sizeof(format_op);
+unsigned struct_fss_get_sz = sizeof(fss_get);
+unsigned struct_fss_set_sz = sizeof(fss_set);
+unsigned struct_gpio_attach_sz = sizeof(gpio_attach);
+unsigned struct_gpio_info_sz = sizeof(gpio_info);
+unsigned struct_gpio_req_sz = sizeof(gpio_req);
+unsigned struct_gpio_set_sz = sizeof(gpio_set);
+unsigned struct_hfsc_add_class_sz = sizeof(hfsc_add_class);
+unsigned struct_hfsc_add_filter_sz = sizeof(hfsc_add_filter);
+unsigned struct_hfsc_attach_sz = sizeof(hfsc_attach);
+unsigned struct_hfsc_class_stats_sz = sizeof(hfsc_class_stats);
+unsigned struct_hfsc_delete_class_sz = sizeof(hfsc_delete_class);
+unsigned struct_hfsc_delete_filter_sz = sizeof(hfsc_delete_filter);
+unsigned struct_hfsc_interface_sz = sizeof(hfsc_interface);
+unsigned struct_hfsc_modify_class_sz = sizeof(hfsc_modify_class);
+unsigned struct_hpcfb_dsp_op_sz = sizeof(hpcfb_dsp_op);
+unsigned struct_hpcfb_dspconf_sz = sizeof(hpcfb_dspconf);
+unsigned struct_hpcfb_fbconf_sz = sizeof(hpcfb_fbconf);
+unsigned struct_if_addrprefreq_sz = sizeof(if_addrprefreq);
+unsigned struct_if_clonereq_sz = sizeof(if_clonereq);
+unsigned struct_if_laddrreq_sz = sizeof(if_laddrreq);
+unsigned struct_ifaddr_sz = sizeof(ifaddr);
+unsigned struct_ifaliasreq_sz = sizeof(ifaliasreq);
+unsigned struct_ifcapreq_sz = sizeof(ifcapreq);
+unsigned struct_ifconf_sz = sizeof(ifconf);
+unsigned struct_ifdatareq_sz = sizeof(ifdatareq);
+unsigned struct_ifdrv_sz = sizeof(ifdrv);
+unsigned struct_ifmediareq_sz = sizeof(ifmediareq);
+unsigned struct_ifpppcstatsreq_sz = sizeof(ifpppcstatsreq);
+unsigned struct_ifpppstatsreq_sz = sizeof(ifpppstatsreq);
+unsigned struct_ifreq_sz = sizeof(ifreq);
+unsigned struct_in6_addrpolicy_sz = sizeof(in6_addrpolicy);
+unsigned struct_in6_ndireq_sz = sizeof(in6_ndireq);
+unsigned struct_ioc_load_unload_sz = sizeof(ioc_load_unload);
+unsigned struct_ioc_patch_sz = sizeof(ioc_patch);
+unsigned struct_ioc_play_blocks_sz = sizeof(ioc_play_blocks);
+unsigned struct_ioc_play_msf_sz = sizeof(ioc_play_msf);
+unsigned struct_ioc_play_track_sz = sizeof(ioc_play_track);
+unsigned struct_ioc_read_subchannel_sz = sizeof(ioc_read_subchannel);
+unsigned struct_ioc_read_toc_entry_sz = sizeof(ioc_read_toc_entry);
+unsigned struct_ioc_toc_header_sz = sizeof(ioc_toc_header);
+unsigned struct_ioc_vol_sz = sizeof(ioc_vol);
+unsigned struct_ioctl_pt_sz = sizeof(ioctl_pt);
+unsigned struct_ioppt_sz = sizeof(ioppt);
+unsigned struct_iovec_sz = sizeof(iovec);
+unsigned struct_ipfobj_sz = sizeof(ipfobj);
+unsigned struct_irda_params_sz = sizeof(irda_params);
+unsigned struct_isp_fc_device_sz = sizeof(isp_fc_device);
+unsigned struct_isp_fc_tsk_mgmt_sz = sizeof(isp_fc_tsk_mgmt);
+unsigned struct_isp_hba_device_sz = sizeof(isp_hba_device);
+unsigned struct_isv_cmd_sz = sizeof(isv_cmd);
+unsigned struct_jobs_add_class_sz = sizeof(jobs_add_class);
+unsigned struct_jobs_add_filter_sz = sizeof(jobs_add_filter);
+unsigned struct_jobs_attach_sz = sizeof(jobs_attach);
+unsigned struct_jobs_class_stats_sz = sizeof(jobs_class_stats);
+unsigned struct_jobs_delete_class_sz = sizeof(jobs_delete_class);
+unsigned struct_jobs_delete_filter_sz = sizeof(jobs_delete_filter);
+unsigned struct_jobs_interface_sz = sizeof(jobs_interface);
+unsigned struct_jobs_modify_class_sz = sizeof(jobs_modify_class);
+unsigned struct_kbentry_sz = sizeof(kbentry);
+unsigned struct_kfilter_mapping_sz = sizeof(kfilter_mapping);
+unsigned struct_kiockeymap_sz = sizeof(kiockeymap);
+unsigned struct_ksyms_gsymbol_sz = sizeof(ksyms_gsymbol);
+unsigned struct_ksyms_gvalue_sz = sizeof(ksyms_gvalue);
+unsigned struct_ksyms_ogsymbol_sz = sizeof(ksyms_ogsymbol);
+unsigned struct_kttcp_io_args_sz = sizeof(kttcp_io_args);
+unsigned struct_ltchars_sz = sizeof(ltchars);
+unsigned struct_lua_create_sz = sizeof(struct lua_create);
+unsigned struct_lua_info_sz = sizeof(struct lua_info);
+unsigned struct_lua_load_sz = sizeof(struct lua_load);
+unsigned struct_lua_require_sz = sizeof(lua_require);
+unsigned struct_mbpp_param_sz = sizeof(mbpp_param);
+unsigned struct_md_conf_sz = sizeof(md_conf);
+unsigned struct_meteor_capframe_sz = sizeof(meteor_capframe);
+unsigned struct_meteor_counts_sz = sizeof(meteor_counts);
+unsigned struct_meteor_geomet_sz = sizeof(meteor_geomet);
+unsigned struct_meteor_pixfmt_sz = sizeof(meteor_pixfmt);
+unsigned struct_meteor_video_sz = sizeof(meteor_video);
+unsigned struct_mlx_cinfo_sz = sizeof(mlx_cinfo);
+unsigned struct_mlx_pause_sz = sizeof(mlx_pause);
+unsigned struct_mlx_rebuild_request_sz = sizeof(mlx_rebuild_request);
+unsigned struct_mlx_rebuild_status_sz = sizeof(mlx_rebuild_status);
+unsigned struct_mlx_usercommand_sz = sizeof(mlx_usercommand);
+unsigned struct_mly_user_command_sz = sizeof(mly_user_command);
+unsigned struct_mly_user_health_sz = sizeof(mly_user_health);
+unsigned struct_mtget_sz = sizeof(mtget);
+unsigned struct_mtop_sz = sizeof(mtop);
+unsigned struct_npf_ioctl_table_sz = sizeof(npf_ioctl_table);
+unsigned struct_npioctl_sz = sizeof(npioctl);
+unsigned struct_nvme_pt_command_sz = sizeof(nvme_pt_command);
+unsigned struct_ochanger_element_status_request_sz =
+ sizeof(ochanger_element_status_request);
+unsigned struct_ofiocdesc_sz = sizeof(ofiocdesc);
+unsigned struct_okiockey_sz = sizeof(okiockey);
+unsigned struct_ortentry_sz = sizeof(ortentry);
+unsigned struct_oscsi_addr_sz = sizeof(oscsi_addr);
+unsigned struct_oss_audioinfo_sz = sizeof(oss_audioinfo);
+unsigned struct_oss_sysinfo_sz = sizeof(oss_sysinfo);
+unsigned struct_pciio_bdf_cfgreg_sz = sizeof(pciio_bdf_cfgreg);
+unsigned struct_pciio_businfo_sz = sizeof(pciio_businfo);
+unsigned struct_pciio_cfgreg_sz = sizeof(pciio_cfgreg);
+unsigned struct_pciio_drvname_sz = sizeof(pciio_drvname);
+unsigned struct_pciio_drvnameonbus_sz = sizeof(pciio_drvnameonbus);
+unsigned struct_pcvtid_sz = sizeof(pcvtid);
+unsigned struct_pf_osfp_ioctl_sz = sizeof(pf_osfp_ioctl);
+unsigned struct_pf_status_sz = sizeof(pf_status);
+unsigned struct_pfioc_altq_sz = sizeof(pfioc_altq);
+unsigned struct_pfioc_if_sz = sizeof(pfioc_if);
+unsigned struct_pfioc_iface_sz = sizeof(pfioc_iface);
+unsigned struct_pfioc_limit_sz = sizeof(pfioc_limit);
+unsigned struct_pfioc_natlook_sz = sizeof(pfioc_natlook);
+unsigned struct_pfioc_pooladdr_sz = sizeof(pfioc_pooladdr);
+unsigned struct_pfioc_qstats_sz = sizeof(pfioc_qstats);
+unsigned struct_pfioc_rule_sz = sizeof(pfioc_rule);
+unsigned struct_pfioc_ruleset_sz = sizeof(pfioc_ruleset);
+unsigned struct_pfioc_src_node_kill_sz = sizeof(pfioc_src_node_kill);
+unsigned struct_pfioc_src_nodes_sz = sizeof(pfioc_src_nodes);
+unsigned struct_pfioc_state_kill_sz = sizeof(pfioc_state_kill);
+unsigned struct_pfioc_state_sz = sizeof(pfioc_state);
+unsigned struct_pfioc_states_sz = sizeof(pfioc_states);
+unsigned struct_pfioc_table_sz = sizeof(pfioc_table);
+unsigned struct_pfioc_tm_sz = sizeof(pfioc_tm);
+unsigned struct_pfioc_trans_sz = sizeof(pfioc_trans);
+unsigned struct_plistref_sz = sizeof(plistref);
+unsigned struct_power_type_sz = sizeof(power_type);
+unsigned struct_ppp_idle_sz = sizeof(ppp_idle);
+unsigned struct_ppp_option_data_sz = sizeof(ppp_option_data);
+unsigned struct_ppp_rawin_sz = sizeof(ppp_rawin);
+unsigned struct_pppoeconnectionstate_sz = sizeof(pppoeconnectionstate);
+unsigned struct_pppoediscparms_sz = sizeof(pppoediscparms);
+unsigned struct_priq_add_class_sz = sizeof(priq_add_class);
+unsigned struct_priq_add_filter_sz = sizeof(priq_add_filter);
+unsigned struct_priq_class_stats_sz = sizeof(priq_class_stats);
+unsigned struct_priq_delete_class_sz = sizeof(priq_delete_class);
+unsigned struct_priq_delete_filter_sz = sizeof(priq_delete_filter);
+unsigned struct_priq_interface_sz = sizeof(priq_interface);
+unsigned struct_priq_modify_class_sz = sizeof(priq_modify_class);
+unsigned struct_ptmget_sz = sizeof(ptmget);
+unsigned struct_radio_info_sz = sizeof(radio_info);
+unsigned struct_red_conf_sz = sizeof(red_conf);
+unsigned struct_red_interface_sz = sizeof(red_interface);
+unsigned struct_red_stats_sz = sizeof(red_stats);
+unsigned struct_redparams_sz = sizeof(redparams);
+unsigned struct_rf_pmparams_sz = sizeof(rf_pmparams);
+unsigned struct_rf_pmstat_sz = sizeof(rf_pmstat);
+unsigned struct_rf_recon_req_sz = sizeof(rf_recon_req);
+unsigned struct_rio_conf_sz = sizeof(rio_conf);
+unsigned struct_rio_interface_sz = sizeof(rio_interface);
+unsigned struct_rio_stats_sz = sizeof(rio_stats);
+unsigned struct_scan_io_sz = sizeof(scan_io);
+unsigned struct_scbusaccel_args_sz = sizeof(scbusaccel_args);
+unsigned struct_scbusiodetach_args_sz = sizeof(scbusiodetach_args);
+unsigned struct_scbusioscan_args_sz = sizeof(scbusioscan_args);
+unsigned struct_scsi_addr_sz = sizeof(scsi_addr);
+unsigned struct_seq_event_rec_sz = sizeof(seq_event_rec);
+unsigned struct_session_op_sz = sizeof(session_op);
+unsigned struct_sgttyb_sz = sizeof(sgttyb);
+unsigned struct_sioc_sg_req_sz = sizeof(sioc_sg_req);
+unsigned struct_sioc_vif_req_sz = sizeof(sioc_vif_req);
+unsigned struct_smbioc_flags_sz = sizeof(smbioc_flags);
+unsigned struct_smbioc_lookup_sz = sizeof(smbioc_lookup);
+unsigned struct_smbioc_oshare_sz = sizeof(smbioc_oshare);
+unsigned struct_smbioc_ossn_sz = sizeof(smbioc_ossn);
+unsigned struct_smbioc_rq_sz = sizeof(smbioc_rq);
+unsigned struct_smbioc_rw_sz = sizeof(smbioc_rw);
+unsigned struct_spppauthcfg_sz = sizeof(spppauthcfg);
+unsigned struct_spppauthfailuresettings_sz = sizeof(spppauthfailuresettings);
+unsigned struct_spppauthfailurestats_sz = sizeof(spppauthfailurestats);
+unsigned struct_spppdnsaddrs_sz = sizeof(spppdnsaddrs);
+unsigned struct_spppdnssettings_sz = sizeof(spppdnssettings);
+unsigned struct_spppidletimeout_sz = sizeof(spppidletimeout);
+unsigned struct_spppkeepalivesettings_sz = sizeof(spppkeepalivesettings);
+unsigned struct_sppplcpcfg_sz = sizeof(sppplcpcfg);
+unsigned struct_spppstatus_sz = sizeof(spppstatus);
+unsigned struct_spppstatusncp_sz = sizeof(spppstatusncp);
+unsigned struct_srt_rt_sz = sizeof(srt_rt);
+unsigned struct_stic_xinfo_sz = sizeof(stic_xinfo);
+unsigned struct_sun_dkctlr_sz = sizeof(sun_dkctlr);
+unsigned struct_sun_dkgeom_sz = sizeof(sun_dkgeom);
+unsigned struct_sun_dkpart_sz = sizeof(sun_dkpart);
+unsigned struct_synth_info_sz = sizeof(synth_info);
+unsigned struct_tbrreq_sz = sizeof(tbrreq);
+unsigned struct_tchars_sz = sizeof(tchars);
+unsigned struct_termios_sz = sizeof(termios);
+unsigned struct_timeval_sz = sizeof(timeval);
+unsigned struct_twe_drivecommand_sz = sizeof(twe_drivecommand);
+unsigned struct_twe_paramcommand_sz = sizeof(twe_paramcommand);
+unsigned struct_twe_usercommand_sz = sizeof(twe_usercommand);
+unsigned struct_ukyopon_identify_sz = sizeof(ukyopon_identify);
+unsigned struct_urio_command_sz = sizeof(urio_command);
+unsigned struct_usb_alt_interface_sz = sizeof(usb_alt_interface);
+unsigned struct_usb_bulk_ra_wb_opt_sz = sizeof(usb_bulk_ra_wb_opt);
+unsigned struct_usb_config_desc_sz = sizeof(usb_config_desc);
+unsigned struct_usb_ctl_report_desc_sz = sizeof(usb_ctl_report_desc);
+unsigned struct_usb_ctl_report_sz = sizeof(usb_ctl_report);
+unsigned struct_usb_ctl_request_sz = sizeof(usb_ctl_request);
+#if defined(__x86_64__)
+unsigned struct_nvmm_ioc_capability_sz = sizeof(nvmm_ioc_capability);
+unsigned struct_nvmm_ioc_machine_create_sz = sizeof(nvmm_ioc_machine_create);
+unsigned struct_nvmm_ioc_machine_destroy_sz = sizeof(nvmm_ioc_machine_destroy);
+unsigned struct_nvmm_ioc_machine_configure_sz =
+ sizeof(nvmm_ioc_machine_configure);
+unsigned struct_nvmm_ioc_vcpu_create_sz = sizeof(nvmm_ioc_vcpu_create);
+unsigned struct_nvmm_ioc_vcpu_destroy_sz = sizeof(nvmm_ioc_vcpu_destroy);
+unsigned struct_nvmm_ioc_vcpu_configure_sz = sizeof(nvmm_ioc_vcpu_configure);
+unsigned struct_nvmm_ioc_vcpu_setstate_sz = sizeof(nvmm_ioc_vcpu_destroy);
+unsigned struct_nvmm_ioc_vcpu_getstate_sz = sizeof(nvmm_ioc_vcpu_getstate);
+unsigned struct_nvmm_ioc_vcpu_inject_sz = sizeof(nvmm_ioc_vcpu_inject);
+unsigned struct_nvmm_ioc_vcpu_run_sz = sizeof(nvmm_ioc_vcpu_run);
+unsigned struct_nvmm_ioc_gpa_map_sz = sizeof(nvmm_ioc_gpa_map);
+unsigned struct_nvmm_ioc_gpa_unmap_sz = sizeof(nvmm_ioc_gpa_unmap);
+unsigned struct_nvmm_ioc_hva_map_sz = sizeof(nvmm_ioc_hva_map);
+unsigned struct_nvmm_ioc_hva_unmap_sz = sizeof(nvmm_ioc_hva_unmap);
+unsigned struct_nvmm_ioc_ctl_sz = sizeof(nvmm_ioc_ctl);
+#endif
+unsigned struct_spi_ioctl_configure_sz = sizeof(spi_ioctl_configure);
+unsigned struct_spi_ioctl_transfer_sz = sizeof(spi_ioctl_transfer);
+unsigned struct_autofs_daemon_request_sz = sizeof(autofs_daemon_request);
+unsigned struct_autofs_daemon_done_sz = sizeof(autofs_daemon_done);
+unsigned struct_sctp_connectx_addrs_sz = sizeof(sctp_connectx_addrs);
+unsigned struct_usb_device_info_old_sz = sizeof(usb_device_info_old);
+unsigned struct_usb_device_info_sz = sizeof(usb_device_info);
+unsigned struct_usb_device_stats_sz = sizeof(usb_device_stats);
+unsigned struct_usb_endpoint_desc_sz = sizeof(usb_endpoint_desc);
+unsigned struct_usb_full_desc_sz = sizeof(usb_full_desc);
+unsigned struct_usb_interface_desc_sz = sizeof(usb_interface_desc);
+unsigned struct_usb_string_desc_sz = sizeof(usb_string_desc);
+unsigned struct_utoppy_readfile_sz = sizeof(utoppy_readfile);
+unsigned struct_utoppy_rename_sz = sizeof(utoppy_rename);
+unsigned struct_utoppy_stats_sz = sizeof(utoppy_stats);
+unsigned struct_utoppy_writefile_sz = sizeof(utoppy_writefile);
+unsigned struct_v4l2_audio_sz = sizeof(v4l2_audio);
+unsigned struct_v4l2_audioout_sz = sizeof(v4l2_audioout);
+unsigned struct_v4l2_buffer_sz = sizeof(v4l2_buffer);
+unsigned struct_v4l2_capability_sz = sizeof(v4l2_capability);
+unsigned struct_v4l2_control_sz = sizeof(v4l2_control);
+unsigned struct_v4l2_crop_sz = sizeof(v4l2_crop);
+unsigned struct_v4l2_cropcap_sz = sizeof(v4l2_cropcap);
+unsigned struct_v4l2_fmtdesc_sz = sizeof(v4l2_fmtdesc);
+unsigned struct_v4l2_format_sz = sizeof(v4l2_format);
+unsigned struct_v4l2_framebuffer_sz = sizeof(v4l2_framebuffer);
+unsigned struct_v4l2_frequency_sz = sizeof(v4l2_frequency);
+unsigned struct_v4l2_frmivalenum_sz = sizeof(v4l2_frmivalenum);
+unsigned struct_v4l2_frmsizeenum_sz = sizeof(v4l2_frmsizeenum);
+unsigned struct_v4l2_input_sz = sizeof(v4l2_input);
+unsigned struct_v4l2_jpegcompression_sz = sizeof(v4l2_jpegcompression);
+unsigned struct_v4l2_modulator_sz = sizeof(v4l2_modulator);
+unsigned struct_v4l2_output_sz = sizeof(v4l2_output);
+unsigned struct_v4l2_queryctrl_sz = sizeof(v4l2_queryctrl);
+unsigned struct_v4l2_querymenu_sz = sizeof(v4l2_querymenu);
+unsigned struct_v4l2_requestbuffers_sz = sizeof(v4l2_requestbuffers);
+unsigned struct_v4l2_standard_sz = sizeof(v4l2_standard);
+unsigned struct_v4l2_streamparm_sz = sizeof(v4l2_streamparm);
+unsigned struct_v4l2_tuner_sz = sizeof(v4l2_tuner);
+unsigned struct_vnd_ioctl_sz = sizeof(vnd_ioctl);
+unsigned struct_vnd_user_sz = sizeof(vnd_user);
+unsigned struct_vt_stat_sz = sizeof(vt_stat);
+unsigned struct_wdog_conf_sz = sizeof(wdog_conf);
+unsigned struct_wdog_mode_sz = sizeof(wdog_mode);
+unsigned struct_ipmi_recv_sz = sizeof(ipmi_recv);
+unsigned struct_ipmi_req_sz = sizeof(ipmi_req);
+unsigned struct_ipmi_cmdspec_sz = sizeof(ipmi_cmdspec);
+unsigned struct_wfq_conf_sz = sizeof(wfq_conf);
+unsigned struct_wfq_getqid_sz = sizeof(wfq_getqid);
+unsigned struct_wfq_getstats_sz = sizeof(wfq_getstats);
+unsigned struct_wfq_interface_sz = sizeof(wfq_interface);
+unsigned struct_wfq_setweight_sz = sizeof(wfq_setweight);
+unsigned struct_winsize_sz = sizeof(winsize);
+unsigned struct_wscons_event_sz = sizeof(wscons_event);
+unsigned struct_wsdisplay_addscreendata_sz = sizeof(wsdisplay_addscreendata);
+unsigned struct_wsdisplay_char_sz = sizeof(wsdisplay_char);
+unsigned struct_wsdisplay_cmap_sz = sizeof(wsdisplay_cmap);
+unsigned struct_wsdisplay_curpos_sz = sizeof(wsdisplay_curpos);
+unsigned struct_wsdisplay_cursor_sz = sizeof(wsdisplay_cursor);
+unsigned struct_wsdisplay_delscreendata_sz = sizeof(wsdisplay_delscreendata);
+unsigned struct_wsdisplay_fbinfo_sz = sizeof(wsdisplay_fbinfo);
+unsigned struct_wsdisplay_font_sz = sizeof(wsdisplay_font);
+unsigned struct_wsdisplay_kbddata_sz = sizeof(wsdisplay_kbddata);
+unsigned struct_wsdisplay_msgattrs_sz = sizeof(wsdisplay_msgattrs);
+unsigned struct_wsdisplay_param_sz = sizeof(wsdisplay_param);
+unsigned struct_wsdisplay_scroll_data_sz = sizeof(wsdisplay_scroll_data);
+unsigned struct_wsdisplay_usefontdata_sz = sizeof(wsdisplay_usefontdata);
+unsigned struct_wsdisplayio_blit_sz = sizeof(wsdisplayio_blit);
+unsigned struct_wsdisplayio_bus_id_sz = sizeof(wsdisplayio_bus_id);
+unsigned struct_wsdisplayio_edid_info_sz = sizeof(wsdisplayio_edid_info);
+unsigned struct_wsdisplayio_fbinfo_sz = sizeof(wsdisplayio_fbinfo);
+unsigned struct_wskbd_bell_data_sz = sizeof(wskbd_bell_data);
+unsigned struct_wskbd_keyrepeat_data_sz = sizeof(wskbd_keyrepeat_data);
+unsigned struct_wskbd_map_data_sz = sizeof(wskbd_map_data);
+unsigned struct_wskbd_scroll_data_sz = sizeof(wskbd_scroll_data);
+unsigned struct_wsmouse_calibcoords_sz = sizeof(wsmouse_calibcoords);
+unsigned struct_wsmouse_id_sz = sizeof(wsmouse_id);
+unsigned struct_wsmouse_repeat_sz = sizeof(wsmouse_repeat);
+unsigned struct_wsmux_device_list_sz = sizeof(wsmux_device_list);
+unsigned struct_wsmux_device_sz = sizeof(wsmux_device);
+unsigned struct_xd_iocmd_sz = sizeof(xd_iocmd);
+
+unsigned struct_scsireq_sz = sizeof(struct scsireq);
+unsigned struct_tone_sz = sizeof(tone_t);
+unsigned union_twe_statrequest_sz = sizeof(union twe_statrequest);
+unsigned struct_usb_device_descriptor_sz = sizeof(usb_device_descriptor_t);
+unsigned struct_vt_mode_sz = sizeof(struct vt_mode);
+unsigned struct__old_mixer_info_sz = sizeof(struct _old_mixer_info);
+unsigned struct__agp_allocate_sz = sizeof(struct _agp_allocate);
+unsigned struct__agp_bind_sz = sizeof(struct _agp_bind);
+unsigned struct__agp_info_sz = sizeof(struct _agp_info);
+unsigned struct__agp_setup_sz = sizeof(struct _agp_setup);
+unsigned struct__agp_unbind_sz = sizeof(struct _agp_unbind);
+unsigned struct_atareq_sz = sizeof(struct atareq);
+unsigned struct_cpustate_sz = sizeof(struct cpustate);
+unsigned struct_dmx_caps_sz = sizeof(struct dmx_caps);
+unsigned enum_dmx_source_sz = sizeof(dmx_source_t);
+unsigned union_dvd_authinfo_sz = sizeof(dvd_authinfo);
+unsigned union_dvd_struct_sz = sizeof(dvd_struct);
+unsigned enum_v4l2_priority_sz = sizeof(enum v4l2_priority);
+unsigned struct_envsys_basic_info_sz = sizeof(struct envsys_basic_info);
+unsigned struct_envsys_tre_data_sz = sizeof(struct envsys_tre_data);
+unsigned enum_fe_sec_mini_cmd_sz = sizeof(enum fe_sec_mini_cmd);
+unsigned enum_fe_sec_tone_mode_sz = sizeof(enum fe_sec_tone_mode);
+unsigned enum_fe_sec_voltage_sz = sizeof(enum fe_sec_voltage);
+unsigned enum_fe_status_sz = sizeof(enum fe_status);
+unsigned struct_gdt_ctrt_sz = sizeof(struct gdt_ctrt);
+unsigned struct_gdt_event_sz = sizeof(struct gdt_event);
+unsigned struct_gdt_osv_sz = sizeof(struct gdt_osv);
+unsigned struct_gdt_rescan_sz = sizeof(struct gdt_rescan);
+unsigned struct_gdt_statist_sz = sizeof(struct gdt_statist);
+unsigned struct_gdt_ucmd_sz = sizeof(struct gdt_ucmd);
+unsigned struct_iscsi_conn_status_parameters_sz =
+ sizeof(iscsi_conn_status_parameters_t);
+unsigned struct_iscsi_get_version_parameters_sz =
+ sizeof(iscsi_get_version_parameters_t);
+unsigned struct_iscsi_iocommand_parameters_sz =
+ sizeof(iscsi_iocommand_parameters_t);
+unsigned struct_iscsi_login_parameters_sz = sizeof(iscsi_login_parameters_t);
+unsigned struct_iscsi_logout_parameters_sz = sizeof(iscsi_logout_parameters_t);
+unsigned struct_iscsi_register_event_parameters_sz =
+ sizeof(iscsi_register_event_parameters_t);
+unsigned struct_iscsi_remove_parameters_sz = sizeof(iscsi_remove_parameters_t);
+unsigned struct_iscsi_send_targets_parameters_sz =
+ sizeof(iscsi_send_targets_parameters_t);
+unsigned struct_iscsi_set_node_name_parameters_sz =
+ sizeof(iscsi_set_node_name_parameters_t);
+unsigned struct_iscsi_wait_event_parameters_sz =
+ sizeof(iscsi_wait_event_parameters_t);
+unsigned struct_isp_stats_sz = sizeof(isp_stats_t);
+unsigned struct_lsenable_sz = sizeof(struct lsenable);
+unsigned struct_lsdisable_sz = sizeof(struct lsdisable);
+unsigned struct_audio_format_query_sz = sizeof(audio_format_query);
+unsigned struct_mixer_ctrl_sz = sizeof(struct mixer_ctrl);
+unsigned struct_mixer_devinfo_sz = sizeof(struct mixer_devinfo);
+unsigned struct_mpu_command_rec_sz = sizeof(mpu_command_rec);
+unsigned struct_rndstat_sz = sizeof(rndstat_t);
+unsigned struct_rndstat_name_sz = sizeof(rndstat_name_t);
+unsigned struct_rndctl_sz = sizeof(rndctl_t);
+unsigned struct_rnddata_sz = sizeof(rnddata_t);
+unsigned struct_rndpoolstat_sz = sizeof(rndpoolstat_t);
+unsigned struct_rndstat_est_sz = sizeof(rndstat_est_t);
+unsigned struct_rndstat_est_name_sz = sizeof(rndstat_est_name_t);
+unsigned struct_pps_params_sz = sizeof(pps_params_t);
+unsigned struct_pps_info_sz = sizeof(pps_info_t);
+unsigned struct_mixer_info_sz = sizeof(struct mixer_info);
+unsigned struct_RF_SparetWait_sz = sizeof(RF_SparetWait_t);
+unsigned struct_RF_ComponentLabel_sz = sizeof(RF_ComponentLabel_t);
+unsigned struct_RF_SingleComponent_sz = sizeof(RF_SingleComponent_t);
+unsigned struct_RF_ProgressInfo_sz = sizeof(RF_ProgressInfo_t);
+unsigned struct_nvlist_ref_sz = sizeof(struct __sanitizer_nvlist_ref_t);
+unsigned struct_StringList_sz = sizeof(StringList);
+
+const unsigned IOCTL_NOT_PRESENT = 0;
+
+unsigned IOCTL_AFM_ADDFMAP = AFM_ADDFMAP;
+unsigned IOCTL_AFM_DELFMAP = AFM_DELFMAP;
+unsigned IOCTL_AFM_CLEANFMAP = AFM_CLEANFMAP;
+unsigned IOCTL_AFM_GETFMAP = AFM_GETFMAP;
+unsigned IOCTL_ALTQGTYPE = ALTQGTYPE;
+unsigned IOCTL_ALTQTBRSET = ALTQTBRSET;
+unsigned IOCTL_ALTQTBRGET = ALTQTBRGET;
+unsigned IOCTL_BLUE_IF_ATTACH = BLUE_IF_ATTACH;
+unsigned IOCTL_BLUE_IF_DETACH = BLUE_IF_DETACH;
+unsigned IOCTL_BLUE_ENABLE = BLUE_ENABLE;
+unsigned IOCTL_BLUE_DISABLE = BLUE_DISABLE;
+unsigned IOCTL_BLUE_CONFIG = BLUE_CONFIG;
+unsigned IOCTL_BLUE_GETSTATS = BLUE_GETSTATS;
+unsigned IOCTL_CBQ_IF_ATTACH = CBQ_IF_ATTACH;
+unsigned IOCTL_CBQ_IF_DETACH = CBQ_IF_DETACH;
+unsigned IOCTL_CBQ_ENABLE = CBQ_ENABLE;
+unsigned IOCTL_CBQ_DISABLE = CBQ_DISABLE;
+unsigned IOCTL_CBQ_CLEAR_HIERARCHY = CBQ_CLEAR_HIERARCHY;
+unsigned IOCTL_CBQ_ADD_CLASS = CBQ_ADD_CLASS;
+unsigned IOCTL_CBQ_DEL_CLASS = CBQ_DEL_CLASS;
+unsigned IOCTL_CBQ_MODIFY_CLASS = CBQ_MODIFY_CLASS;
+unsigned IOCTL_CBQ_ADD_FILTER = CBQ_ADD_FILTER;
+unsigned IOCTL_CBQ_DEL_FILTER = CBQ_DEL_FILTER;
+unsigned IOCTL_CBQ_GETSTATS = CBQ_GETSTATS;
+unsigned IOCTL_CDNR_IF_ATTACH = CDNR_IF_ATTACH;
+unsigned IOCTL_CDNR_IF_DETACH = CDNR_IF_DETACH;
+unsigned IOCTL_CDNR_ENABLE = CDNR_ENABLE;
+unsigned IOCTL_CDNR_DISABLE = CDNR_DISABLE;
+unsigned IOCTL_CDNR_ADD_FILTER = CDNR_ADD_FILTER;
+unsigned IOCTL_CDNR_DEL_FILTER = CDNR_DEL_FILTER;
+unsigned IOCTL_CDNR_GETSTATS = CDNR_GETSTATS;
+unsigned IOCTL_CDNR_ADD_ELEM = CDNR_ADD_ELEM;
+unsigned IOCTL_CDNR_DEL_ELEM = CDNR_DEL_ELEM;
+unsigned IOCTL_CDNR_ADD_TBM = CDNR_ADD_TBM;
+unsigned IOCTL_CDNR_MOD_TBM = CDNR_MOD_TBM;
+unsigned IOCTL_CDNR_TBM_STATS = CDNR_TBM_STATS;
+unsigned IOCTL_CDNR_ADD_TCM = CDNR_ADD_TCM;
+unsigned IOCTL_CDNR_MOD_TCM = CDNR_MOD_TCM;
+unsigned IOCTL_CDNR_TCM_STATS = CDNR_TCM_STATS;
+unsigned IOCTL_CDNR_ADD_TSW = CDNR_ADD_TSW;
+unsigned IOCTL_CDNR_MOD_TSW = CDNR_MOD_TSW;
+unsigned IOCTL_FIFOQ_IF_ATTACH = FIFOQ_IF_ATTACH;
+unsigned IOCTL_FIFOQ_IF_DETACH = FIFOQ_IF_DETACH;
+unsigned IOCTL_FIFOQ_ENABLE = FIFOQ_ENABLE;
+unsigned IOCTL_FIFOQ_DISABLE = FIFOQ_DISABLE;
+unsigned IOCTL_FIFOQ_CONFIG = FIFOQ_CONFIG;
+unsigned IOCTL_FIFOQ_GETSTATS = FIFOQ_GETSTATS;
+unsigned IOCTL_HFSC_IF_ATTACH = HFSC_IF_ATTACH;
+unsigned IOCTL_HFSC_IF_DETACH = HFSC_IF_DETACH;
+unsigned IOCTL_HFSC_ENABLE = HFSC_ENABLE;
+unsigned IOCTL_HFSC_DISABLE = HFSC_DISABLE;
+unsigned IOCTL_HFSC_CLEAR_HIERARCHY = HFSC_CLEAR_HIERARCHY;
+unsigned IOCTL_HFSC_ADD_CLASS = HFSC_ADD_CLASS;
+unsigned IOCTL_HFSC_DEL_CLASS = HFSC_DEL_CLASS;
+unsigned IOCTL_HFSC_MOD_CLASS = HFSC_MOD_CLASS;
+unsigned IOCTL_HFSC_ADD_FILTER = HFSC_ADD_FILTER;
+unsigned IOCTL_HFSC_DEL_FILTER = HFSC_DEL_FILTER;
+unsigned IOCTL_HFSC_GETSTATS = HFSC_GETSTATS;
+unsigned IOCTL_JOBS_IF_ATTACH = JOBS_IF_ATTACH;
+unsigned IOCTL_JOBS_IF_DETACH = JOBS_IF_DETACH;
+unsigned IOCTL_JOBS_ENABLE = JOBS_ENABLE;
+unsigned IOCTL_JOBS_DISABLE = JOBS_DISABLE;
+unsigned IOCTL_JOBS_CLEAR = JOBS_CLEAR;
+unsigned IOCTL_JOBS_ADD_CLASS = JOBS_ADD_CLASS;
+unsigned IOCTL_JOBS_DEL_CLASS = JOBS_DEL_CLASS;
+unsigned IOCTL_JOBS_MOD_CLASS = JOBS_MOD_CLASS;
+unsigned IOCTL_JOBS_ADD_FILTER = JOBS_ADD_FILTER;
+unsigned IOCTL_JOBS_DEL_FILTER = JOBS_DEL_FILTER;
+unsigned IOCTL_JOBS_GETSTATS = JOBS_GETSTATS;
+unsigned IOCTL_PRIQ_IF_ATTACH = PRIQ_IF_ATTACH;
+unsigned IOCTL_PRIQ_IF_DETACH = PRIQ_IF_DETACH;
+unsigned IOCTL_PRIQ_ENABLE = PRIQ_ENABLE;
+unsigned IOCTL_PRIQ_DISABLE = PRIQ_DISABLE;
+unsigned IOCTL_PRIQ_CLEAR = PRIQ_CLEAR;
+unsigned IOCTL_PRIQ_ADD_CLASS = PRIQ_ADD_CLASS;
+unsigned IOCTL_PRIQ_DEL_CLASS = PRIQ_DEL_CLASS;
+unsigned IOCTL_PRIQ_MOD_CLASS = PRIQ_MOD_CLASS;
+unsigned IOCTL_PRIQ_ADD_FILTER = PRIQ_ADD_FILTER;
+unsigned IOCTL_PRIQ_DEL_FILTER = PRIQ_DEL_FILTER;
+unsigned IOCTL_PRIQ_GETSTATS = PRIQ_GETSTATS;
+unsigned IOCTL_RED_IF_ATTACH = RED_IF_ATTACH;
+unsigned IOCTL_RED_IF_DETACH = RED_IF_DETACH;
+unsigned IOCTL_RED_ENABLE = RED_ENABLE;
+unsigned IOCTL_RED_DISABLE = RED_DISABLE;
+unsigned IOCTL_RED_CONFIG = RED_CONFIG;
+unsigned IOCTL_RED_GETSTATS = RED_GETSTATS;
+unsigned IOCTL_RED_SETDEFAULTS = RED_SETDEFAULTS;
+unsigned IOCTL_RIO_IF_ATTACH = RIO_IF_ATTACH;
+unsigned IOCTL_RIO_IF_DETACH = RIO_IF_DETACH;
+unsigned IOCTL_RIO_ENABLE = RIO_ENABLE;
+unsigned IOCTL_RIO_DISABLE = RIO_DISABLE;
+unsigned IOCTL_RIO_CONFIG = RIO_CONFIG;
+unsigned IOCTL_RIO_GETSTATS = RIO_GETSTATS;
+unsigned IOCTL_RIO_SETDEFAULTS = RIO_SETDEFAULTS;
+unsigned IOCTL_WFQ_IF_ATTACH = WFQ_IF_ATTACH;
+unsigned IOCTL_WFQ_IF_DETACH = WFQ_IF_DETACH;
+unsigned IOCTL_WFQ_ENABLE = WFQ_ENABLE;
+unsigned IOCTL_WFQ_DISABLE = WFQ_DISABLE;
+unsigned IOCTL_WFQ_CONFIG = WFQ_CONFIG;
+unsigned IOCTL_WFQ_GET_STATS = WFQ_GET_STATS;
+unsigned IOCTL_WFQ_GET_QID = WFQ_GET_QID;
+unsigned IOCTL_WFQ_SET_WEIGHT = WFQ_SET_WEIGHT;
+unsigned IOCTL_CRIOGET = CRIOGET;
+unsigned IOCTL_CIOCFSESSION = CIOCFSESSION;
+unsigned IOCTL_CIOCKEY = CIOCKEY;
+unsigned IOCTL_CIOCNFKEYM = CIOCNFKEYM;
+unsigned IOCTL_CIOCNFSESSION = CIOCNFSESSION;
+unsigned IOCTL_CIOCNCRYPTRETM = CIOCNCRYPTRETM;
+unsigned IOCTL_CIOCNCRYPTRET = CIOCNCRYPTRET;
+unsigned IOCTL_CIOCGSESSION = CIOCGSESSION;
+unsigned IOCTL_CIOCNGSESSION = CIOCNGSESSION;
+unsigned IOCTL_CIOCCRYPT = CIOCCRYPT;
+unsigned IOCTL_CIOCNCRYPTM = CIOCNCRYPTM;
+unsigned IOCTL_CIOCASYMFEAT = CIOCASYMFEAT;
+unsigned IOCTL_APM_IOC_REJECT = APM_IOC_REJECT;
+unsigned IOCTL_APM_IOC_STANDBY = APM_IOC_STANDBY;
+unsigned IOCTL_APM_IOC_SUSPEND = APM_IOC_SUSPEND;
+unsigned IOCTL_OAPM_IOC_GETPOWER = OAPM_IOC_GETPOWER;
+unsigned IOCTL_APM_IOC_GETPOWER = APM_IOC_GETPOWER;
+unsigned IOCTL_APM_IOC_NEXTEVENT = APM_IOC_NEXTEVENT;
+unsigned IOCTL_APM_IOC_DEV_CTL = APM_IOC_DEV_CTL;
+unsigned IOCTL_NETBSD_DM_IOCTL = NETBSD_DM_IOCTL;
+unsigned IOCTL_DMIO_SETFUNC = DMIO_SETFUNC;
+unsigned IOCTL_DMX_START = DMX_START;
+unsigned IOCTL_DMX_STOP = DMX_STOP;
+unsigned IOCTL_DMX_SET_FILTER = DMX_SET_FILTER;
+unsigned IOCTL_DMX_SET_PES_FILTER = DMX_SET_PES_FILTER;
+unsigned IOCTL_DMX_SET_BUFFER_SIZE = DMX_SET_BUFFER_SIZE;
+unsigned IOCTL_DMX_GET_STC = DMX_GET_STC;
+unsigned IOCTL_DMX_ADD_PID = DMX_ADD_PID;
+unsigned IOCTL_DMX_REMOVE_PID = DMX_REMOVE_PID;
+unsigned IOCTL_DMX_GET_CAPS = DMX_GET_CAPS;
+unsigned IOCTL_DMX_SET_SOURCE = DMX_SET_SOURCE;
+unsigned IOCTL_FE_READ_STATUS = FE_READ_STATUS;
+unsigned IOCTL_FE_READ_BER = FE_READ_BER;
+unsigned IOCTL_FE_READ_SNR = FE_READ_SNR;
+unsigned IOCTL_FE_READ_SIGNAL_STRENGTH = FE_READ_SIGNAL_STRENGTH;
+unsigned IOCTL_FE_READ_UNCORRECTED_BLOCKS = FE_READ_UNCORRECTED_BLOCKS;
+unsigned IOCTL_FE_SET_FRONTEND = FE_SET_FRONTEND;
+unsigned IOCTL_FE_GET_FRONTEND = FE_GET_FRONTEND;
+unsigned IOCTL_FE_GET_EVENT = FE_GET_EVENT;
+unsigned IOCTL_FE_GET_INFO = FE_GET_INFO;
+unsigned IOCTL_FE_DISEQC_RESET_OVERLOAD = FE_DISEQC_RESET_OVERLOAD;
+unsigned IOCTL_FE_DISEQC_SEND_MASTER_CMD = FE_DISEQC_SEND_MASTER_CMD;
+unsigned IOCTL_FE_DISEQC_RECV_SLAVE_REPLY = FE_DISEQC_RECV_SLAVE_REPLY;
+unsigned IOCTL_FE_DISEQC_SEND_BURST = FE_DISEQC_SEND_BURST;
+unsigned IOCTL_FE_SET_TONE = FE_SET_TONE;
+unsigned IOCTL_FE_SET_VOLTAGE = FE_SET_VOLTAGE;
+unsigned IOCTL_FE_ENABLE_HIGH_LNB_VOLTAGE = FE_ENABLE_HIGH_LNB_VOLTAGE;
+unsigned IOCTL_FE_SET_FRONTEND_TUNE_MODE = FE_SET_FRONTEND_TUNE_MODE;
+unsigned IOCTL_FE_DISHNETWORK_SEND_LEGACY_CMD = FE_DISHNETWORK_SEND_LEGACY_CMD;
+unsigned IOCTL_FILEMON_SET_FD = FILEMON_SET_FD;
+unsigned IOCTL_FILEMON_SET_PID = FILEMON_SET_PID;
+unsigned IOCTL_HDAUDIO_FGRP_INFO = HDAUDIO_FGRP_INFO;
+unsigned IOCTL_HDAUDIO_FGRP_GETCONFIG = HDAUDIO_FGRP_GETCONFIG;
+unsigned IOCTL_HDAUDIO_FGRP_SETCONFIG = HDAUDIO_FGRP_SETCONFIG;
+unsigned IOCTL_HDAUDIO_FGRP_WIDGET_INFO = HDAUDIO_FGRP_WIDGET_INFO;
+unsigned IOCTL_HDAUDIO_FGRP_CODEC_INFO = HDAUDIO_FGRP_CODEC_INFO;
+unsigned IOCTL_HDAUDIO_AFG_WIDGET_INFO = HDAUDIO_AFG_WIDGET_INFO;
+unsigned IOCTL_HDAUDIO_AFG_CODEC_INFO = HDAUDIO_AFG_CODEC_INFO;
+unsigned IOCTL_CEC_GET_PHYS_ADDR = CEC_GET_PHYS_ADDR;
+unsigned IOCTL_CEC_GET_LOG_ADDRS = CEC_GET_LOG_ADDRS;
+unsigned IOCTL_CEC_SET_LOG_ADDRS = CEC_SET_LOG_ADDRS;
+unsigned IOCTL_CEC_GET_VENDOR_ID = CEC_GET_VENDOR_ID;
+unsigned IOCTL_HPCFBIO_GCONF = HPCFBIO_GCONF;
+unsigned IOCTL_HPCFBIO_SCONF = HPCFBIO_SCONF;
+unsigned IOCTL_HPCFBIO_GDSPCONF = HPCFBIO_GDSPCONF;
+unsigned IOCTL_HPCFBIO_SDSPCONF = HPCFBIO_SDSPCONF;
+unsigned IOCTL_HPCFBIO_GOP = HPCFBIO_GOP;
+unsigned IOCTL_HPCFBIO_SOP = HPCFBIO_SOP;
+unsigned IOCTL_IOPIOCPT = IOPIOCPT;
+unsigned IOCTL_IOPIOCGLCT = IOPIOCGLCT;
+unsigned IOCTL_IOPIOCGSTATUS = IOPIOCGSTATUS;
+unsigned IOCTL_IOPIOCRECONFIG = IOPIOCRECONFIG;
+unsigned IOCTL_IOPIOCGTIDMAP = IOPIOCGTIDMAP;
+unsigned IOCTL_SIOCGATHSTATS = SIOCGATHSTATS;
+unsigned IOCTL_SIOCGATHDIAG = SIOCGATHDIAG;
+unsigned IOCTL_METEORCAPTUR = METEORCAPTUR;
+unsigned IOCTL_METEORCAPFRM = METEORCAPFRM;
+unsigned IOCTL_METEORSETGEO = METEORSETGEO;
+unsigned IOCTL_METEORGETGEO = METEORGETGEO;
+unsigned IOCTL_METEORSTATUS = METEORSTATUS;
+unsigned IOCTL_METEORSHUE = METEORSHUE;
+unsigned IOCTL_METEORGHUE = METEORGHUE;
+unsigned IOCTL_METEORSFMT = METEORSFMT;
+unsigned IOCTL_METEORGFMT = METEORGFMT;
+unsigned IOCTL_METEORSINPUT = METEORSINPUT;
+unsigned IOCTL_METEORGINPUT = METEORGINPUT;
+unsigned IOCTL_METEORSCHCV = METEORSCHCV;
+unsigned IOCTL_METEORGCHCV = METEORGCHCV;
+unsigned IOCTL_METEORSCOUNT = METEORSCOUNT;
+unsigned IOCTL_METEORGCOUNT = METEORGCOUNT;
+unsigned IOCTL_METEORSFPS = METEORSFPS;
+unsigned IOCTL_METEORGFPS = METEORGFPS;
+unsigned IOCTL_METEORSSIGNAL = METEORSSIGNAL;
+unsigned IOCTL_METEORGSIGNAL = METEORGSIGNAL;
+unsigned IOCTL_METEORSVIDEO = METEORSVIDEO;
+unsigned IOCTL_METEORGVIDEO = METEORGVIDEO;
+unsigned IOCTL_METEORSBRIG = METEORSBRIG;
+unsigned IOCTL_METEORGBRIG = METEORGBRIG;
+unsigned IOCTL_METEORSCSAT = METEORSCSAT;
+unsigned IOCTL_METEORGCSAT = METEORGCSAT;
+unsigned IOCTL_METEORSCONT = METEORSCONT;
+unsigned IOCTL_METEORGCONT = METEORGCONT;
+unsigned IOCTL_METEORSHWS = METEORSHWS;
+unsigned IOCTL_METEORGHWS = METEORGHWS;
+unsigned IOCTL_METEORSVWS = METEORSVWS;
+unsigned IOCTL_METEORGVWS = METEORGVWS;
+unsigned IOCTL_METEORSTS = METEORSTS;
+unsigned IOCTL_METEORGTS = METEORGTS;
+unsigned IOCTL_TVTUNER_SETCHNL = TVTUNER_SETCHNL;
+unsigned IOCTL_TVTUNER_GETCHNL = TVTUNER_GETCHNL;
+unsigned IOCTL_TVTUNER_SETTYPE = TVTUNER_SETTYPE;
+unsigned IOCTL_TVTUNER_GETTYPE = TVTUNER_GETTYPE;
+unsigned IOCTL_TVTUNER_GETSTATUS = TVTUNER_GETSTATUS;
+unsigned IOCTL_TVTUNER_SETFREQ = TVTUNER_SETFREQ;
+unsigned IOCTL_TVTUNER_GETFREQ = TVTUNER_GETFREQ;
+unsigned IOCTL_TVTUNER_SETAFC = TVTUNER_SETAFC;
+unsigned IOCTL_TVTUNER_GETAFC = TVTUNER_GETAFC;
+unsigned IOCTL_RADIO_SETMODE = RADIO_SETMODE;
+unsigned IOCTL_RADIO_GETMODE = RADIO_GETMODE;
+unsigned IOCTL_RADIO_SETFREQ = RADIO_SETFREQ;
+unsigned IOCTL_RADIO_GETFREQ = RADIO_GETFREQ;
+unsigned IOCTL_METEORSACTPIXFMT = METEORSACTPIXFMT;
+unsigned IOCTL_METEORGACTPIXFMT = METEORGACTPIXFMT;
+unsigned IOCTL_METEORGSUPPIXFMT = METEORGSUPPIXFMT;
+unsigned IOCTL_TVTUNER_GETCHNLSET = TVTUNER_GETCHNLSET;
+unsigned IOCTL_REMOTE_GETKEY = REMOTE_GETKEY;
+unsigned IOCTL_GDT_IOCTL_GENERAL = GDT_IOCTL_GENERAL;
+unsigned IOCTL_GDT_IOCTL_DRVERS = GDT_IOCTL_DRVERS;
+unsigned IOCTL_GDT_IOCTL_CTRTYPE = GDT_IOCTL_CTRTYPE;
+unsigned IOCTL_GDT_IOCTL_OSVERS = GDT_IOCTL_OSVERS;
+unsigned IOCTL_GDT_IOCTL_CTRCNT = GDT_IOCTL_CTRCNT;
+unsigned IOCTL_GDT_IOCTL_EVENT = GDT_IOCTL_EVENT;
+unsigned IOCTL_GDT_IOCTL_STATIST = GDT_IOCTL_STATIST;
+unsigned IOCTL_GDT_IOCTL_RESCAN = GDT_IOCTL_RESCAN;
+unsigned IOCTL_ISP_SDBLEV = ISP_SDBLEV;
+unsigned IOCTL_ISP_RESETHBA = ISP_RESETHBA;
+unsigned IOCTL_ISP_RESCAN = ISP_RESCAN;
+unsigned IOCTL_ISP_SETROLE = ISP_SETROLE;
+unsigned IOCTL_ISP_GETROLE = ISP_GETROLE;
+unsigned IOCTL_ISP_GET_STATS = ISP_GET_STATS;
+unsigned IOCTL_ISP_CLR_STATS = ISP_CLR_STATS;
+unsigned IOCTL_ISP_FC_LIP = ISP_FC_LIP;
+unsigned IOCTL_ISP_FC_GETDINFO = ISP_FC_GETDINFO;
+unsigned IOCTL_ISP_GET_FW_CRASH_DUMP = ISP_GET_FW_CRASH_DUMP;
+unsigned IOCTL_ISP_FORCE_CRASH_DUMP = ISP_FORCE_CRASH_DUMP;
+unsigned IOCTL_ISP_FC_GETHINFO = ISP_FC_GETHINFO;
+unsigned IOCTL_ISP_TSK_MGMT = ISP_TSK_MGMT;
+unsigned IOCTL_ISP_FC_GETDLIST = ISP_FC_GETDLIST;
+unsigned IOCTL_MLXD_STATUS = MLXD_STATUS;
+unsigned IOCTL_MLXD_CHECKASYNC = MLXD_CHECKASYNC;
+unsigned IOCTL_MLXD_DETACH = MLXD_DETACH;
+unsigned IOCTL_MLX_RESCAN_DRIVES = MLX_RESCAN_DRIVES;
+unsigned IOCTL_MLX_PAUSE_CHANNEL = MLX_PAUSE_CHANNEL;
+unsigned IOCTL_MLX_COMMAND = MLX_COMMAND;
+unsigned IOCTL_MLX_REBUILDASYNC = MLX_REBUILDASYNC;
+unsigned IOCTL_MLX_REBUILDSTAT = MLX_REBUILDSTAT;
+unsigned IOCTL_MLX_GET_SYSDRIVE = MLX_GET_SYSDRIVE;
+unsigned IOCTL_MLX_GET_CINFO = MLX_GET_CINFO;
+unsigned IOCTL_NVME_PASSTHROUGH_CMD = NVME_PASSTHROUGH_CMD;
+unsigned IOCTL_FWCFGIO_SET_INDEX = FWCFGIO_SET_INDEX;
+unsigned IOCTL_IRDA_RESET_PARAMS = IRDA_RESET_PARAMS;
+unsigned IOCTL_IRDA_SET_PARAMS = IRDA_SET_PARAMS;
+unsigned IOCTL_IRDA_GET_SPEEDMASK = IRDA_GET_SPEEDMASK;
+unsigned IOCTL_IRDA_GET_TURNAROUNDMASK = IRDA_GET_TURNAROUNDMASK;
+unsigned IOCTL_IRFRAMETTY_GET_DEVICE = IRFRAMETTY_GET_DEVICE;
+unsigned IOCTL_IRFRAMETTY_GET_DONGLE = IRFRAMETTY_GET_DONGLE;
+unsigned IOCTL_IRFRAMETTY_SET_DONGLE = IRFRAMETTY_SET_DONGLE;
+unsigned IOCTL_ISV_CMD = ISV_CMD;
+unsigned IOCTL_WTQICMD = WTQICMD;
+unsigned IOCTL_ISCSI_GET_VERSION = ISCSI_GET_VERSION;
+unsigned IOCTL_ISCSI_LOGIN = ISCSI_LOGIN;
+unsigned IOCTL_ISCSI_LOGOUT = ISCSI_LOGOUT;
+unsigned IOCTL_ISCSI_ADD_CONNECTION = ISCSI_ADD_CONNECTION;
+unsigned IOCTL_ISCSI_RESTORE_CONNECTION = ISCSI_RESTORE_CONNECTION;
+unsigned IOCTL_ISCSI_REMOVE_CONNECTION = ISCSI_REMOVE_CONNECTION;
+unsigned IOCTL_ISCSI_CONNECTION_STATUS = ISCSI_CONNECTION_STATUS;
+unsigned IOCTL_ISCSI_SEND_TARGETS = ISCSI_SEND_TARGETS;
+unsigned IOCTL_ISCSI_SET_NODE_NAME = ISCSI_SET_NODE_NAME;
+unsigned IOCTL_ISCSI_IO_COMMAND = ISCSI_IO_COMMAND;
+unsigned IOCTL_ISCSI_REGISTER_EVENT = ISCSI_REGISTER_EVENT;
+unsigned IOCTL_ISCSI_DEREGISTER_EVENT = ISCSI_DEREGISTER_EVENT;
+unsigned IOCTL_ISCSI_WAIT_EVENT = ISCSI_WAIT_EVENT;
+unsigned IOCTL_ISCSI_POLL_EVENT = ISCSI_POLL_EVENT;
+unsigned IOCTL_OFIOCGET = OFIOCGET;
+unsigned IOCTL_OFIOCSET = OFIOCSET;
+unsigned IOCTL_OFIOCNEXTPROP = OFIOCNEXTPROP;
+unsigned IOCTL_OFIOCGETOPTNODE = OFIOCGETOPTNODE;
+unsigned IOCTL_OFIOCGETNEXT = OFIOCGETNEXT;
+unsigned IOCTL_OFIOCGETCHILD = OFIOCGETCHILD;
+unsigned IOCTL_OFIOCFINDDEVICE = OFIOCFINDDEVICE;
+unsigned IOCTL_AMR_IO_VERSION = AMR_IO_VERSION;
+unsigned IOCTL_AMR_IO_COMMAND = AMR_IO_COMMAND;
+unsigned IOCTL_MLYIO_COMMAND = MLYIO_COMMAND;
+unsigned IOCTL_MLYIO_HEALTH = MLYIO_HEALTH;
+unsigned IOCTL_PCI_IOC_CFGREAD = PCI_IOC_CFGREAD;
+unsigned IOCTL_PCI_IOC_CFGWRITE = PCI_IOC_CFGWRITE;
+unsigned IOCTL_PCI_IOC_BDF_CFGREAD = PCI_IOC_BDF_CFGREAD;
+unsigned IOCTL_PCI_IOC_BDF_CFGWRITE = PCI_IOC_BDF_CFGWRITE;
+unsigned IOCTL_PCI_IOC_BUSINFO = PCI_IOC_BUSINFO;
+unsigned IOCTL_PCI_IOC_DRVNAME = PCI_IOC_DRVNAME;
+unsigned IOCTL_PCI_IOC_DRVNAMEONBUS = PCI_IOC_DRVNAMEONBUS;
+unsigned IOCTL_TWEIO_COMMAND = TWEIO_COMMAND;
+unsigned IOCTL_TWEIO_STATS = TWEIO_STATS;
+unsigned IOCTL_TWEIO_AEN_POLL = TWEIO_AEN_POLL;
+unsigned IOCTL_TWEIO_AEN_WAIT = TWEIO_AEN_WAIT;
+unsigned IOCTL_TWEIO_SET_PARAM = TWEIO_SET_PARAM;
+unsigned IOCTL_TWEIO_GET_PARAM = TWEIO_GET_PARAM;
+unsigned IOCTL_TWEIO_RESET = TWEIO_RESET;
+unsigned IOCTL_TWEIO_ADD_UNIT = TWEIO_ADD_UNIT;
+unsigned IOCTL_TWEIO_DEL_UNIT = TWEIO_DEL_UNIT;
+unsigned IOCTL_SIOCSCNWDOMAIN = SIOCSCNWDOMAIN;
+unsigned IOCTL_SIOCGCNWDOMAIN = SIOCGCNWDOMAIN;
+unsigned IOCTL_SIOCSCNWKEY = SIOCSCNWKEY;
+unsigned IOCTL_SIOCGCNWSTATUS = SIOCGCNWSTATUS;
+unsigned IOCTL_SIOCGCNWSTATS = SIOCGCNWSTATS;
+unsigned IOCTL_SIOCGCNWTRAIL = SIOCGCNWTRAIL;
+unsigned IOCTL_SIOCGRAYSIGLEV = SIOCGRAYSIGLEV;
+unsigned IOCTL_RAIDFRAME_SHUTDOWN = RAIDFRAME_SHUTDOWN;
+unsigned IOCTL_RAIDFRAME_TUR = RAIDFRAME_TUR;
+unsigned IOCTL_RAIDFRAME_FAIL_DISK = RAIDFRAME_FAIL_DISK;
+unsigned IOCTL_RAIDFRAME_CHECK_RECON_STATUS = RAIDFRAME_CHECK_RECON_STATUS;
+unsigned IOCTL_RAIDFRAME_REWRITEPARITY = RAIDFRAME_REWRITEPARITY;
+unsigned IOCTL_RAIDFRAME_COPYBACK = RAIDFRAME_COPYBACK;
+unsigned IOCTL_RAIDFRAME_SPARET_WAIT = RAIDFRAME_SPARET_WAIT;
+unsigned IOCTL_RAIDFRAME_SEND_SPARET = RAIDFRAME_SEND_SPARET;
+unsigned IOCTL_RAIDFRAME_ABORT_SPARET_WAIT = RAIDFRAME_ABORT_SPARET_WAIT;
+unsigned IOCTL_RAIDFRAME_START_ATRACE = RAIDFRAME_START_ATRACE;
+unsigned IOCTL_RAIDFRAME_STOP_ATRACE = RAIDFRAME_STOP_ATRACE;
+unsigned IOCTL_RAIDFRAME_GET_SIZE = RAIDFRAME_GET_SIZE;
+unsigned IOCTL_RAIDFRAME_RESET_ACCTOTALS = RAIDFRAME_RESET_ACCTOTALS;
+unsigned IOCTL_RAIDFRAME_KEEP_ACCTOTALS = RAIDFRAME_KEEP_ACCTOTALS;
+unsigned IOCTL_RAIDFRAME_GET_COMPONENT_LABEL = RAIDFRAME_GET_COMPONENT_LABEL;
+unsigned IOCTL_RAIDFRAME_SET_COMPONENT_LABEL = RAIDFRAME_SET_COMPONENT_LABEL;
+unsigned IOCTL_RAIDFRAME_INIT_LABELS = RAIDFRAME_INIT_LABELS;
+unsigned IOCTL_RAIDFRAME_ADD_HOT_SPARE = RAIDFRAME_ADD_HOT_SPARE;
+unsigned IOCTL_RAIDFRAME_REMOVE_HOT_SPARE = RAIDFRAME_REMOVE_HOT_SPARE;
+unsigned IOCTL_RAIDFRAME_REBUILD_IN_PLACE = RAIDFRAME_REBUILD_IN_PLACE;
+unsigned IOCTL_RAIDFRAME_CHECK_PARITY = RAIDFRAME_CHECK_PARITY;
+unsigned IOCTL_RAIDFRAME_CHECK_PARITYREWRITE_STATUS =
+ RAIDFRAME_CHECK_PARITYREWRITE_STATUS;
+unsigned IOCTL_RAIDFRAME_CHECK_COPYBACK_STATUS =
+ RAIDFRAME_CHECK_COPYBACK_STATUS;
+unsigned IOCTL_RAIDFRAME_SET_AUTOCONFIG = RAIDFRAME_SET_AUTOCONFIG;
+unsigned IOCTL_RAIDFRAME_SET_ROOT = RAIDFRAME_SET_ROOT;
+unsigned IOCTL_RAIDFRAME_DELETE_COMPONENT = RAIDFRAME_DELETE_COMPONENT;
+unsigned IOCTL_RAIDFRAME_INCORPORATE_HOT_SPARE =
+ RAIDFRAME_INCORPORATE_HOT_SPARE;
+unsigned IOCTL_RAIDFRAME_CHECK_RECON_STATUS_EXT =
+ RAIDFRAME_CHECK_RECON_STATUS_EXT;
+unsigned IOCTL_RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT =
+ RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT;
+unsigned IOCTL_RAIDFRAME_CHECK_COPYBACK_STATUS_EXT =
+ RAIDFRAME_CHECK_COPYBACK_STATUS_EXT;
+unsigned IOCTL_RAIDFRAME_CONFIGURE = RAIDFRAME_CONFIGURE;
+unsigned IOCTL_RAIDFRAME_GET_INFO = RAIDFRAME_GET_INFO;
+unsigned IOCTL_RAIDFRAME_PARITYMAP_STATUS = RAIDFRAME_PARITYMAP_STATUS;
+unsigned IOCTL_RAIDFRAME_PARITYMAP_GET_DISABLE =
+ RAIDFRAME_PARITYMAP_GET_DISABLE;
+unsigned IOCTL_RAIDFRAME_PARITYMAP_SET_DISABLE =
+ RAIDFRAME_PARITYMAP_SET_DISABLE;
+unsigned IOCTL_RAIDFRAME_PARITYMAP_SET_PARAMS = RAIDFRAME_PARITYMAP_SET_PARAMS;
+unsigned IOCTL_RAIDFRAME_SET_LAST_UNIT = RAIDFRAME_SET_LAST_UNIT;
+unsigned IOCTL_MBPPIOCSPARAM = MBPPIOCSPARAM;
+unsigned IOCTL_MBPPIOCGPARAM = MBPPIOCGPARAM;
+unsigned IOCTL_MBPPIOCGSTAT = MBPPIOCGSTAT;
+unsigned IOCTL_SESIOC_GETNOBJ = SESIOC_GETNOBJ;
+unsigned IOCTL_SESIOC_GETOBJMAP = SESIOC_GETOBJMAP;
+unsigned IOCTL_SESIOC_GETENCSTAT = SESIOC_GETENCSTAT;
+unsigned IOCTL_SESIOC_SETENCSTAT = SESIOC_SETENCSTAT;
+unsigned IOCTL_SESIOC_GETOBJSTAT = SESIOC_GETOBJSTAT;
+unsigned IOCTL_SESIOC_SETOBJSTAT = SESIOC_SETOBJSTAT;
+unsigned IOCTL_SESIOC_GETTEXT = SESIOC_GETTEXT;
+unsigned IOCTL_SESIOC_INIT = SESIOC_INIT;
+unsigned IOCTL_SUN_DKIOCGGEOM = SUN_DKIOCGGEOM;
+unsigned IOCTL_SUN_DKIOCINFO = SUN_DKIOCINFO;
+unsigned IOCTL_SUN_DKIOCGPART = SUN_DKIOCGPART;
+unsigned IOCTL_FBIOGTYPE = FBIOGTYPE;
+unsigned IOCTL_FBIOPUTCMAP = FBIOPUTCMAP;
+unsigned IOCTL_FBIOGETCMAP = FBIOGETCMAP;
+unsigned IOCTL_FBIOGATTR = FBIOGATTR;
+unsigned IOCTL_FBIOSVIDEO = FBIOSVIDEO;
+unsigned IOCTL_FBIOGVIDEO = FBIOGVIDEO;
+unsigned IOCTL_FBIOSCURSOR = FBIOSCURSOR;
+unsigned IOCTL_FBIOGCURSOR = FBIOGCURSOR;
+unsigned IOCTL_FBIOSCURPOS = FBIOSCURPOS;
+unsigned IOCTL_FBIOGCURPOS = FBIOGCURPOS;
+unsigned IOCTL_FBIOGCURMAX = FBIOGCURMAX;
+unsigned IOCTL_KIOCTRANS = KIOCTRANS;
+unsigned IOCTL_KIOCSETKEY = KIOCSETKEY;
+unsigned IOCTL_KIOCGETKEY = KIOCGETKEY;
+unsigned IOCTL_KIOCGTRANS = KIOCGTRANS;
+unsigned IOCTL_KIOCCMD = KIOCCMD;
+unsigned IOCTL_KIOCTYPE = KIOCTYPE;
+unsigned IOCTL_KIOCSDIRECT = KIOCSDIRECT;
+unsigned IOCTL_KIOCSKEY = KIOCSKEY;
+unsigned IOCTL_KIOCGKEY = KIOCGKEY;
+unsigned IOCTL_KIOCSLED = KIOCSLED;
+unsigned IOCTL_KIOCGLED = KIOCGLED;
+unsigned IOCTL_KIOCLAYOUT = KIOCLAYOUT;
+unsigned IOCTL_VUIDSFORMAT = VUIDSFORMAT;
+unsigned IOCTL_VUIDGFORMAT = VUIDGFORMAT;
+unsigned IOCTL_STICIO_GXINFO = STICIO_GXINFO;
+unsigned IOCTL_STICIO_RESET = STICIO_RESET;
+unsigned IOCTL_STICIO_STARTQ = STICIO_STARTQ;
+unsigned IOCTL_STICIO_STOPQ = STICIO_STOPQ;
+unsigned IOCTL_UKYOPON_IDENTIFY = UKYOPON_IDENTIFY;
+unsigned IOCTL_URIO_SEND_COMMAND = URIO_SEND_COMMAND;
+unsigned IOCTL_URIO_RECV_COMMAND = URIO_RECV_COMMAND;
+unsigned IOCTL_USB_REQUEST = USB_REQUEST;
+unsigned IOCTL_USB_SETDEBUG = USB_SETDEBUG;
+unsigned IOCTL_USB_DISCOVER = USB_DISCOVER;
+unsigned IOCTL_USB_DEVICEINFO = USB_DEVICEINFO;
+unsigned IOCTL_USB_DEVICEINFO_OLD = USB_DEVICEINFO_OLD;
+unsigned IOCTL_USB_DEVICESTATS = USB_DEVICESTATS;
+unsigned IOCTL_USB_GET_REPORT_DESC = USB_GET_REPORT_DESC;
+unsigned IOCTL_USB_SET_IMMED = USB_SET_IMMED;
+unsigned IOCTL_USB_GET_REPORT = USB_GET_REPORT;
+unsigned IOCTL_USB_SET_REPORT = USB_SET_REPORT;
+unsigned IOCTL_USB_GET_REPORT_ID = USB_GET_REPORT_ID;
+unsigned IOCTL_USB_GET_CONFIG = USB_GET_CONFIG;
+unsigned IOCTL_USB_SET_CONFIG = USB_SET_CONFIG;
+unsigned IOCTL_USB_GET_ALTINTERFACE = USB_GET_ALTINTERFACE;
+unsigned IOCTL_USB_SET_ALTINTERFACE = USB_SET_ALTINTERFACE;
+unsigned IOCTL_USB_GET_NO_ALT = USB_GET_NO_ALT;
+unsigned IOCTL_USB_GET_DEVICE_DESC = USB_GET_DEVICE_DESC;
+unsigned IOCTL_USB_GET_CONFIG_DESC = USB_GET_CONFIG_DESC;
+unsigned IOCTL_USB_GET_INTERFACE_DESC = USB_GET_INTERFACE_DESC;
+unsigned IOCTL_USB_GET_ENDPOINT_DESC = USB_GET_ENDPOINT_DESC;
+unsigned IOCTL_USB_GET_FULL_DESC = USB_GET_FULL_DESC;
+unsigned IOCTL_USB_GET_STRING_DESC = USB_GET_STRING_DESC;
+unsigned IOCTL_USB_DO_REQUEST = USB_DO_REQUEST;
+unsigned IOCTL_USB_GET_DEVICEINFO = USB_GET_DEVICEINFO;
+unsigned IOCTL_USB_GET_DEVICEINFO_OLD = USB_GET_DEVICEINFO_OLD;
+unsigned IOCTL_USB_SET_SHORT_XFER = USB_SET_SHORT_XFER;
+unsigned IOCTL_USB_SET_TIMEOUT = USB_SET_TIMEOUT;
+unsigned IOCTL_USB_SET_BULK_RA = USB_SET_BULK_RA;
+unsigned IOCTL_USB_SET_BULK_WB = USB_SET_BULK_WB;
+unsigned IOCTL_USB_SET_BULK_RA_OPT = USB_SET_BULK_RA_OPT;
+unsigned IOCTL_USB_SET_BULK_WB_OPT = USB_SET_BULK_WB_OPT;
+unsigned IOCTL_USB_GET_CM_OVER_DATA = USB_GET_CM_OVER_DATA;
+unsigned IOCTL_USB_SET_CM_OVER_DATA = USB_SET_CM_OVER_DATA;
+unsigned IOCTL_UTOPPYIOTURBO = UTOPPYIOTURBO;
+unsigned IOCTL_UTOPPYIOCANCEL = UTOPPYIOCANCEL;
+unsigned IOCTL_UTOPPYIOREBOOT = UTOPPYIOREBOOT;
+unsigned IOCTL_UTOPPYIOSTATS = UTOPPYIOSTATS;
+unsigned IOCTL_UTOPPYIORENAME = UTOPPYIORENAME;
+unsigned IOCTL_UTOPPYIOMKDIR = UTOPPYIOMKDIR;
+unsigned IOCTL_UTOPPYIODELETE = UTOPPYIODELETE;
+unsigned IOCTL_UTOPPYIOREADDIR = UTOPPYIOREADDIR;
+unsigned IOCTL_UTOPPYIOREADFILE = UTOPPYIOREADFILE;
+unsigned IOCTL_UTOPPYIOWRITEFILE = UTOPPYIOWRITEFILE;
+unsigned IOCTL_DIOSXDCMD = DIOSXDCMD;
+unsigned IOCTL_VT_OPENQRY = VT_OPENQRY;
+unsigned IOCTL_VT_SETMODE = VT_SETMODE;
+unsigned IOCTL_VT_GETMODE = VT_GETMODE;
+unsigned IOCTL_VT_RELDISP = VT_RELDISP;
+unsigned IOCTL_VT_ACTIVATE = VT_ACTIVATE;
+unsigned IOCTL_VT_WAITACTIVE = VT_WAITACTIVE;
+unsigned IOCTL_VT_GETACTIVE = VT_GETACTIVE;
+unsigned IOCTL_VT_GETSTATE = VT_GETSTATE;
+unsigned IOCTL_KDGETKBENT = KDGETKBENT;
+unsigned IOCTL_KDGKBMODE = KDGKBMODE;
+unsigned IOCTL_KDSKBMODE = KDSKBMODE;
+unsigned IOCTL_KDMKTONE = KDMKTONE;
+unsigned IOCTL_KDSETMODE = KDSETMODE;
+unsigned IOCTL_KDENABIO = KDENABIO;
+unsigned IOCTL_KDDISABIO = KDDISABIO;
+unsigned IOCTL_KDGKBTYPE = KDGKBTYPE;
+unsigned IOCTL_KDGETLED = KDGETLED;
+unsigned IOCTL_KDSETLED = KDSETLED;
+unsigned IOCTL_KDSETRAD = KDSETRAD;
+unsigned IOCTL_VGAPCVTID = VGAPCVTID;
+unsigned IOCTL_CONS_GETVERS = CONS_GETVERS;
+unsigned IOCTL_WSKBDIO_GTYPE = WSKBDIO_GTYPE;
+unsigned IOCTL_WSKBDIO_BELL = WSKBDIO_BELL;
+unsigned IOCTL_WSKBDIO_COMPLEXBELL = WSKBDIO_COMPLEXBELL;
+unsigned IOCTL_WSKBDIO_SETBELL = WSKBDIO_SETBELL;
+unsigned IOCTL_WSKBDIO_GETBELL = WSKBDIO_GETBELL;
+unsigned IOCTL_WSKBDIO_SETDEFAULTBELL = WSKBDIO_SETDEFAULTBELL;
+unsigned IOCTL_WSKBDIO_GETDEFAULTBELL = WSKBDIO_GETDEFAULTBELL;
+unsigned IOCTL_WSKBDIO_SETKEYREPEAT = WSKBDIO_SETKEYREPEAT;
+unsigned IOCTL_WSKBDIO_GETKEYREPEAT = WSKBDIO_GETKEYREPEAT;
+unsigned IOCTL_WSKBDIO_SETDEFAULTKEYREPEAT = WSKBDIO_SETDEFAULTKEYREPEAT;
+unsigned IOCTL_WSKBDIO_GETDEFAULTKEYREPEAT = WSKBDIO_GETDEFAULTKEYREPEAT;
+unsigned IOCTL_WSKBDIO_SETLEDS = WSKBDIO_SETLEDS;
+unsigned IOCTL_WSKBDIO_GETLEDS = WSKBDIO_GETLEDS;
+unsigned IOCTL_WSKBDIO_GETMAP = WSKBDIO_GETMAP;
+unsigned IOCTL_WSKBDIO_SETMAP = WSKBDIO_SETMAP;
+unsigned IOCTL_WSKBDIO_GETENCODING = WSKBDIO_GETENCODING;
+unsigned IOCTL_WSKBDIO_SETENCODING = WSKBDIO_SETENCODING;
+unsigned IOCTL_WSKBDIO_SETMODE = WSKBDIO_SETMODE;
+unsigned IOCTL_WSKBDIO_GETMODE = WSKBDIO_GETMODE;
+unsigned IOCTL_WSKBDIO_SETKEYCLICK = WSKBDIO_SETKEYCLICK;
+unsigned IOCTL_WSKBDIO_GETKEYCLICK = WSKBDIO_GETKEYCLICK;
+unsigned IOCTL_WSKBDIO_GETSCROLL = WSKBDIO_GETSCROLL;
+unsigned IOCTL_WSKBDIO_SETSCROLL = WSKBDIO_SETSCROLL;
+unsigned IOCTL_WSKBDIO_SETVERSION = WSKBDIO_SETVERSION;
+unsigned IOCTL_WSMOUSEIO_GTYPE = WSMOUSEIO_GTYPE;
+unsigned IOCTL_WSMOUSEIO_SRES = WSMOUSEIO_SRES;
+unsigned IOCTL_WSMOUSEIO_SSCALE = WSMOUSEIO_SSCALE;
+unsigned IOCTL_WSMOUSEIO_SRATE = WSMOUSEIO_SRATE;
+unsigned IOCTL_WSMOUSEIO_SCALIBCOORDS = WSMOUSEIO_SCALIBCOORDS;
+unsigned IOCTL_WSMOUSEIO_GCALIBCOORDS = WSMOUSEIO_GCALIBCOORDS;
+unsigned IOCTL_WSMOUSEIO_GETID = WSMOUSEIO_GETID;
+unsigned IOCTL_WSMOUSEIO_GETREPEAT = WSMOUSEIO_GETREPEAT;
+unsigned IOCTL_WSMOUSEIO_SETREPEAT = WSMOUSEIO_SETREPEAT;
+unsigned IOCTL_WSMOUSEIO_SETVERSION = WSMOUSEIO_SETVERSION;
+unsigned IOCTL_WSDISPLAYIO_GTYPE = WSDISPLAYIO_GTYPE;
+unsigned IOCTL_WSDISPLAYIO_GINFO = WSDISPLAYIO_GINFO;
+unsigned IOCTL_WSDISPLAYIO_GETCMAP = WSDISPLAYIO_GETCMAP;
+unsigned IOCTL_WSDISPLAYIO_PUTCMAP = WSDISPLAYIO_PUTCMAP;
+unsigned IOCTL_WSDISPLAYIO_GVIDEO = WSDISPLAYIO_GVIDEO;
+unsigned IOCTL_WSDISPLAYIO_SVIDEO = WSDISPLAYIO_SVIDEO;
+unsigned IOCTL_WSDISPLAYIO_GCURPOS = WSDISPLAYIO_GCURPOS;
+unsigned IOCTL_WSDISPLAYIO_SCURPOS = WSDISPLAYIO_SCURPOS;
+unsigned IOCTL_WSDISPLAYIO_GCURMAX = WSDISPLAYIO_GCURMAX;
+unsigned IOCTL_WSDISPLAYIO_GCURSOR = WSDISPLAYIO_GCURSOR;
+unsigned IOCTL_WSDISPLAYIO_SCURSOR = WSDISPLAYIO_SCURSOR;
+unsigned IOCTL_WSDISPLAYIO_GMODE = WSDISPLAYIO_GMODE;
+unsigned IOCTL_WSDISPLAYIO_SMODE = WSDISPLAYIO_SMODE;
+unsigned IOCTL_WSDISPLAYIO_LDFONT = WSDISPLAYIO_LDFONT;
+unsigned IOCTL_WSDISPLAYIO_ADDSCREEN = WSDISPLAYIO_ADDSCREEN;
+unsigned IOCTL_WSDISPLAYIO_DELSCREEN = WSDISPLAYIO_DELSCREEN;
+unsigned IOCTL_WSDISPLAYIO_SFONT = WSDISPLAYIO_SFONT;
+unsigned IOCTL__O_WSDISPLAYIO_SETKEYBOARD = _O_WSDISPLAYIO_SETKEYBOARD;
+unsigned IOCTL_WSDISPLAYIO_GETPARAM = WSDISPLAYIO_GETPARAM;
+unsigned IOCTL_WSDISPLAYIO_SETPARAM = WSDISPLAYIO_SETPARAM;
+unsigned IOCTL_WSDISPLAYIO_GETACTIVESCREEN = WSDISPLAYIO_GETACTIVESCREEN;
+unsigned IOCTL_WSDISPLAYIO_GETWSCHAR = WSDISPLAYIO_GETWSCHAR;
+unsigned IOCTL_WSDISPLAYIO_PUTWSCHAR = WSDISPLAYIO_PUTWSCHAR;
+unsigned IOCTL_WSDISPLAYIO_DGSCROLL = WSDISPLAYIO_DGSCROLL;
+unsigned IOCTL_WSDISPLAYIO_DSSCROLL = WSDISPLAYIO_DSSCROLL;
+unsigned IOCTL_WSDISPLAYIO_GMSGATTRS = WSDISPLAYIO_GMSGATTRS;
+unsigned IOCTL_WSDISPLAYIO_SMSGATTRS = WSDISPLAYIO_SMSGATTRS;
+unsigned IOCTL_WSDISPLAYIO_GBORDER = WSDISPLAYIO_GBORDER;
+unsigned IOCTL_WSDISPLAYIO_SBORDER = WSDISPLAYIO_SBORDER;
+unsigned IOCTL_WSDISPLAYIO_SSPLASH = WSDISPLAYIO_SSPLASH;
+unsigned IOCTL_WSDISPLAYIO_SPROGRESS = WSDISPLAYIO_SPROGRESS;
+unsigned IOCTL_WSDISPLAYIO_LINEBYTES = WSDISPLAYIO_LINEBYTES;
+unsigned IOCTL_WSDISPLAYIO_SETVERSION = WSDISPLAYIO_SETVERSION;
+unsigned IOCTL_WSMUXIO_ADD_DEVICE = WSMUXIO_ADD_DEVICE;
+unsigned IOCTL_WSMUXIO_REMOVE_DEVICE = WSMUXIO_REMOVE_DEVICE;
+unsigned IOCTL_WSMUXIO_LIST_DEVICES = WSMUXIO_LIST_DEVICES;
+unsigned IOCTL_WSMUXIO_INJECTEVENT = WSMUXIO_INJECTEVENT;
+unsigned IOCTL_WSDISPLAYIO_GET_BUSID = WSDISPLAYIO_GET_BUSID;
+unsigned IOCTL_WSDISPLAYIO_GET_EDID = WSDISPLAYIO_GET_EDID;
+unsigned IOCTL_WSDISPLAYIO_SET_POLLING = WSDISPLAYIO_SET_POLLING;
+unsigned IOCTL_WSDISPLAYIO_GET_FBINFO = WSDISPLAYIO_GET_FBINFO;
+unsigned IOCTL_WSDISPLAYIO_DOBLIT = WSDISPLAYIO_DOBLIT;
+unsigned IOCTL_WSDISPLAYIO_WAITBLIT = WSDISPLAYIO_WAITBLIT;
+unsigned IOCTL_BIOCLOCATE = BIOCLOCATE;
+unsigned IOCTL_BIOCINQ = BIOCINQ;
+unsigned IOCTL_BIOCDISK_NOVOL = BIOCDISK_NOVOL;
+unsigned IOCTL_BIOCDISK = BIOCDISK;
+unsigned IOCTL_BIOCVOL = BIOCVOL;
+unsigned IOCTL_BIOCALARM = BIOCALARM;
+unsigned IOCTL_BIOCBLINK = BIOCBLINK;
+unsigned IOCTL_BIOCSETSTATE = BIOCSETSTATE;
+unsigned IOCTL_BIOCVOLOPS = BIOCVOLOPS;
+unsigned IOCTL_MD_GETCONF = MD_GETCONF;
+unsigned IOCTL_MD_SETCONF = MD_SETCONF;
+unsigned IOCTL_CCDIOCSET = CCDIOCSET;
+unsigned IOCTL_CCDIOCCLR = CCDIOCCLR;
+unsigned IOCTL_CGDIOCSET = CGDIOCSET;
+unsigned IOCTL_CGDIOCCLR = CGDIOCCLR;
+unsigned IOCTL_CGDIOCGET = CGDIOCGET;
+unsigned IOCTL_FSSIOCSET = FSSIOCSET;
+unsigned IOCTL_FSSIOCGET = FSSIOCGET;
+unsigned IOCTL_FSSIOCCLR = FSSIOCCLR;
+unsigned IOCTL_FSSIOFSET = FSSIOFSET;
+unsigned IOCTL_FSSIOFGET = FSSIOFGET;
+unsigned IOCTL_BTDEV_ATTACH = BTDEV_ATTACH;
+unsigned IOCTL_BTDEV_DETACH = BTDEV_DETACH;
+unsigned IOCTL_BTSCO_GETINFO = BTSCO_GETINFO;
+unsigned IOCTL_KTTCP_IO_SEND = KTTCP_IO_SEND;
+unsigned IOCTL_KTTCP_IO_RECV = KTTCP_IO_RECV;
+unsigned IOCTL_IOC_LOCKSTAT_GVERSION = IOC_LOCKSTAT_GVERSION;
+unsigned IOCTL_IOC_LOCKSTAT_ENABLE = IOC_LOCKSTAT_ENABLE;
+unsigned IOCTL_IOC_LOCKSTAT_DISABLE = IOC_LOCKSTAT_DISABLE;
+unsigned IOCTL_VNDIOCSET = VNDIOCSET;
+unsigned IOCTL_VNDIOCCLR = VNDIOCCLR;
+unsigned IOCTL_VNDIOCGET = VNDIOCGET;
+unsigned IOCTL_SPKRTONE = SPKRTONE;
+unsigned IOCTL_SPKRTUNE = SPKRTUNE;
+unsigned IOCTL_SPKRGETVOL = SPKRGETVOL;
+unsigned IOCTL_SPKRSETVOL = SPKRSETVOL;
+#if defined(__x86_64__)
+unsigned IOCTL_NVMM_IOC_CAPABILITY = NVMM_IOC_CAPABILITY;
+unsigned IOCTL_NVMM_IOC_MACHINE_CREATE = NVMM_IOC_MACHINE_CREATE;
+unsigned IOCTL_NVMM_IOC_MACHINE_DESTROY = NVMM_IOC_MACHINE_DESTROY;
+unsigned IOCTL_NVMM_IOC_MACHINE_CONFIGURE = NVMM_IOC_MACHINE_CONFIGURE;
+unsigned IOCTL_NVMM_IOC_VCPU_CREATE = NVMM_IOC_VCPU_CREATE;
+unsigned IOCTL_NVMM_IOC_VCPU_DESTROY = NVMM_IOC_VCPU_DESTROY;
+unsigned IOCTL_NVMM_IOC_VCPU_CONFIGURE = NVMM_IOC_VCPU_CONFIGURE;
+unsigned IOCTL_NVMM_IOC_VCPU_SETSTATE = NVMM_IOC_VCPU_SETSTATE;
+unsigned IOCTL_NVMM_IOC_VCPU_GETSTATE = NVMM_IOC_VCPU_GETSTATE;
+unsigned IOCTL_NVMM_IOC_VCPU_INJECT = NVMM_IOC_VCPU_INJECT;
+unsigned IOCTL_NVMM_IOC_VCPU_RUN = NVMM_IOC_VCPU_RUN;
+unsigned IOCTL_NVMM_IOC_GPA_MAP = NVMM_IOC_GPA_MAP;
+unsigned IOCTL_NVMM_IOC_GPA_UNMAP = NVMM_IOC_GPA_UNMAP;
+unsigned IOCTL_NVMM_IOC_HVA_MAP = NVMM_IOC_HVA_MAP;
+unsigned IOCTL_NVMM_IOC_HVA_UNMAP = NVMM_IOC_HVA_UNMAP;
+unsigned IOCTL_NVMM_IOC_CTL = NVMM_IOC_CTL;
+#endif
+unsigned IOCTL_SPI_IOCTL_CONFIGURE = SPI_IOCTL_CONFIGURE;
+unsigned IOCTL_SPI_IOCTL_TRANSFER = SPI_IOCTL_TRANSFER;
+unsigned IOCTL_AUTOFSREQUEST = AUTOFSREQUEST;
+unsigned IOCTL_AUTOFSDONE = AUTOFSDONE;
+unsigned IOCTL_BIOCGBLEN = BIOCGBLEN;
+unsigned IOCTL_BIOCSBLEN = BIOCSBLEN;
+unsigned IOCTL_BIOCSETF = BIOCSETF;
+unsigned IOCTL_BIOCFLUSH = BIOCFLUSH;
+unsigned IOCTL_BIOCPROMISC = BIOCPROMISC;
+unsigned IOCTL_BIOCGDLT = BIOCGDLT;
+unsigned IOCTL_BIOCGETIF = BIOCGETIF;
+unsigned IOCTL_BIOCSETIF = BIOCSETIF;
+unsigned IOCTL_BIOCGSTATS = BIOCGSTATS;
+unsigned IOCTL_BIOCGSTATSOLD = BIOCGSTATSOLD;
+unsigned IOCTL_BIOCIMMEDIATE = BIOCIMMEDIATE;
+unsigned IOCTL_BIOCVERSION = BIOCVERSION;
+unsigned IOCTL_BIOCSTCPF = BIOCSTCPF;
+unsigned IOCTL_BIOCSUDPF = BIOCSUDPF;
+unsigned IOCTL_BIOCGHDRCMPLT = BIOCGHDRCMPLT;
+unsigned IOCTL_BIOCSHDRCMPLT = BIOCSHDRCMPLT;
+unsigned IOCTL_BIOCSDLT = BIOCSDLT;
+unsigned IOCTL_BIOCGDLTLIST = BIOCGDLTLIST;
+unsigned IOCTL_BIOCGDIRECTION = BIOCGDIRECTION;
+unsigned IOCTL_BIOCSDIRECTION = BIOCSDIRECTION;
+unsigned IOCTL_BIOCSRTIMEOUT = BIOCSRTIMEOUT;
+unsigned IOCTL_BIOCGRTIMEOUT = BIOCGRTIMEOUT;
+unsigned IOCTL_BIOCGFEEDBACK = BIOCGFEEDBACK;
+unsigned IOCTL_BIOCSFEEDBACK = BIOCSFEEDBACK;
+unsigned IOCTL_GRESADDRS = GRESADDRS;
+unsigned IOCTL_GRESADDRD = GRESADDRD;
+unsigned IOCTL_GREGADDRS = GREGADDRS;
+unsigned IOCTL_GREGADDRD = GREGADDRD;
+unsigned IOCTL_GRESPROTO = GRESPROTO;
+unsigned IOCTL_GREGPROTO = GREGPROTO;
+unsigned IOCTL_GRESSOCK = GRESSOCK;
+unsigned IOCTL_GREDSOCK = GREDSOCK;
+unsigned IOCTL_PPPIOCGRAWIN = PPPIOCGRAWIN;
+unsigned IOCTL_PPPIOCGFLAGS = PPPIOCGFLAGS;
+unsigned IOCTL_PPPIOCSFLAGS = PPPIOCSFLAGS;
+unsigned IOCTL_PPPIOCGASYNCMAP = PPPIOCGASYNCMAP;
+unsigned IOCTL_PPPIOCSASYNCMAP = PPPIOCSASYNCMAP;
+unsigned IOCTL_PPPIOCGUNIT = PPPIOCGUNIT;
+unsigned IOCTL_PPPIOCGRASYNCMAP = PPPIOCGRASYNCMAP;
+unsigned IOCTL_PPPIOCSRASYNCMAP = PPPIOCSRASYNCMAP;
+unsigned IOCTL_PPPIOCGMRU = PPPIOCGMRU;
+unsigned IOCTL_PPPIOCSMRU = PPPIOCSMRU;
+unsigned IOCTL_PPPIOCSMAXCID = PPPIOCSMAXCID;
+unsigned IOCTL_PPPIOCGXASYNCMAP = PPPIOCGXASYNCMAP;
+unsigned IOCTL_PPPIOCSXASYNCMAP = PPPIOCSXASYNCMAP;
+unsigned IOCTL_PPPIOCXFERUNIT = PPPIOCXFERUNIT;
+unsigned IOCTL_PPPIOCSCOMPRESS = PPPIOCSCOMPRESS;
+unsigned IOCTL_PPPIOCGNPMODE = PPPIOCGNPMODE;
+unsigned IOCTL_PPPIOCSNPMODE = PPPIOCSNPMODE;
+unsigned IOCTL_PPPIOCGIDLE = PPPIOCGIDLE;
+unsigned IOCTL_PPPIOCGMTU = PPPIOCGMTU;
+unsigned IOCTL_PPPIOCSMTU = PPPIOCSMTU;
+unsigned IOCTL_SIOCGPPPSTATS = SIOCGPPPSTATS;
+unsigned IOCTL_SIOCGPPPCSTATS = SIOCGPPPCSTATS;
+unsigned IOCTL_IOC_NPF_VERSION = IOC_NPF_VERSION;
+unsigned IOCTL_IOC_NPF_SWITCH = IOC_NPF_SWITCH;
+unsigned IOCTL_IOC_NPF_LOAD = IOC_NPF_LOAD;
+unsigned IOCTL_IOC_NPF_TABLE = IOC_NPF_TABLE;
+unsigned IOCTL_IOC_NPF_STATS = IOC_NPF_STATS;
+unsigned IOCTL_IOC_NPF_SAVE = IOC_NPF_SAVE;
+unsigned IOCTL_IOC_NPF_RULE = IOC_NPF_RULE;
+unsigned IOCTL_IOC_NPF_CONN_LOOKUP = IOC_NPF_CONN_LOOKUP;
+unsigned IOCTL_IOC_NPF_TABLE_REPLACE = IOC_NPF_TABLE_REPLACE;
+unsigned IOCTL_PPPOESETPARMS = PPPOESETPARMS;
+unsigned IOCTL_PPPOEGETPARMS = PPPOEGETPARMS;
+unsigned IOCTL_PPPOEGETSESSION = PPPOEGETSESSION;
+unsigned IOCTL_SPPPGETAUTHCFG = SPPPGETAUTHCFG;
+unsigned IOCTL_SPPPSETAUTHCFG = SPPPSETAUTHCFG;
+unsigned IOCTL_SPPPGETLCPCFG = SPPPGETLCPCFG;
+unsigned IOCTL_SPPPSETLCPCFG = SPPPSETLCPCFG;
+unsigned IOCTL_SPPPGETSTATUS = SPPPGETSTATUS;
+unsigned IOCTL_SPPPGETSTATUSNCP = SPPPGETSTATUSNCP;
+unsigned IOCTL_SPPPGETIDLETO = SPPPGETIDLETO;
+unsigned IOCTL_SPPPSETIDLETO = SPPPSETIDLETO;
+unsigned IOCTL_SPPPGETAUTHFAILURES = SPPPGETAUTHFAILURES;
+unsigned IOCTL_SPPPSETAUTHFAILURE = SPPPSETAUTHFAILURE;
+unsigned IOCTL_SPPPSETDNSOPTS = SPPPSETDNSOPTS;
+unsigned IOCTL_SPPPGETDNSOPTS = SPPPGETDNSOPTS;
+unsigned IOCTL_SPPPGETDNSADDRS = SPPPGETDNSADDRS;
+unsigned IOCTL_SPPPSETKEEPALIVE = SPPPSETKEEPALIVE;
+unsigned IOCTL_SPPPGETKEEPALIVE = SPPPGETKEEPALIVE;
+unsigned IOCTL_SRT_GETNRT = SRT_GETNRT;
+unsigned IOCTL_SRT_GETRT = SRT_GETRT;
+unsigned IOCTL_SRT_SETRT = SRT_SETRT;
+unsigned IOCTL_SRT_DELRT = SRT_DELRT;
+unsigned IOCTL_SRT_SFLAGS = SRT_SFLAGS;
+unsigned IOCTL_SRT_GFLAGS = SRT_GFLAGS;
+unsigned IOCTL_SRT_SGFLAGS = SRT_SGFLAGS;
+unsigned IOCTL_SRT_DEBUG = SRT_DEBUG;
+unsigned IOCTL_TAPGIFNAME = TAPGIFNAME;
+unsigned IOCTL_TUNSDEBUG = TUNSDEBUG;
+unsigned IOCTL_TUNGDEBUG = TUNGDEBUG;
+unsigned IOCTL_TUNSIFMODE = TUNSIFMODE;
+unsigned IOCTL_TUNSLMODE = TUNSLMODE;
+unsigned IOCTL_TUNSIFHEAD = TUNSIFHEAD;
+unsigned IOCTL_TUNGIFHEAD = TUNGIFHEAD;
+unsigned IOCTL_DIOCSTART = DIOCSTART;
+unsigned IOCTL_DIOCSTOP = DIOCSTOP;
+unsigned IOCTL_DIOCADDRULE = DIOCADDRULE;
+unsigned IOCTL_DIOCGETRULES = DIOCGETRULES;
+unsigned IOCTL_DIOCGETRULE = DIOCGETRULE;
+unsigned IOCTL_DIOCSETLCK = DIOCSETLCK;
+unsigned IOCTL_DIOCCLRSTATES = DIOCCLRSTATES;
+unsigned IOCTL_DIOCGETSTATE = DIOCGETSTATE;
+unsigned IOCTL_DIOCSETSTATUSIF = DIOCSETSTATUSIF;
+unsigned IOCTL_DIOCGETSTATUS = DIOCGETSTATUS;
+unsigned IOCTL_DIOCCLRSTATUS = DIOCCLRSTATUS;
+unsigned IOCTL_DIOCNATLOOK = DIOCNATLOOK;
+unsigned IOCTL_DIOCSETDEBUG = DIOCSETDEBUG;
+unsigned IOCTL_DIOCGETSTATES = DIOCGETSTATES;
+unsigned IOCTL_DIOCCHANGERULE = DIOCCHANGERULE;
+unsigned IOCTL_DIOCSETTIMEOUT = DIOCSETTIMEOUT;
+unsigned IOCTL_DIOCGETTIMEOUT = DIOCGETTIMEOUT;
+unsigned IOCTL_DIOCADDSTATE = DIOCADDSTATE;
+unsigned IOCTL_DIOCCLRRULECTRS = DIOCCLRRULECTRS;
+unsigned IOCTL_DIOCGETLIMIT = DIOCGETLIMIT;
+unsigned IOCTL_DIOCSETLIMIT = DIOCSETLIMIT;
+unsigned IOCTL_DIOCKILLSTATES = DIOCKILLSTATES;
+unsigned IOCTL_DIOCSTARTALTQ = DIOCSTARTALTQ;
+unsigned IOCTL_DIOCSTOPALTQ = DIOCSTOPALTQ;
+unsigned IOCTL_DIOCADDALTQ = DIOCADDALTQ;
+unsigned IOCTL_DIOCGETALTQS = DIOCGETALTQS;
+unsigned IOCTL_DIOCGETALTQ = DIOCGETALTQ;
+unsigned IOCTL_DIOCCHANGEALTQ = DIOCCHANGEALTQ;
+unsigned IOCTL_DIOCGETQSTATS = DIOCGETQSTATS;
+unsigned IOCTL_DIOCBEGINADDRS = DIOCBEGINADDRS;
+unsigned IOCTL_DIOCADDADDR = DIOCADDADDR;
+unsigned IOCTL_DIOCGETADDRS = DIOCGETADDRS;
+unsigned IOCTL_DIOCGETADDR = DIOCGETADDR;
+unsigned IOCTL_DIOCCHANGEADDR = DIOCCHANGEADDR;
+unsigned IOCTL_DIOCADDSTATES = DIOCADDSTATES;
+unsigned IOCTL_DIOCGETRULESETS = DIOCGETRULESETS;
+unsigned IOCTL_DIOCGETRULESET = DIOCGETRULESET;
+unsigned IOCTL_DIOCRCLRTABLES = DIOCRCLRTABLES;
+unsigned IOCTL_DIOCRADDTABLES = DIOCRADDTABLES;
+unsigned IOCTL_DIOCRDELTABLES = DIOCRDELTABLES;
+unsigned IOCTL_DIOCRGETTABLES = DIOCRGETTABLES;
+unsigned IOCTL_DIOCRGETTSTATS = DIOCRGETTSTATS;
+unsigned IOCTL_DIOCRCLRTSTATS = DIOCRCLRTSTATS;
+unsigned IOCTL_DIOCRCLRADDRS = DIOCRCLRADDRS;
+unsigned IOCTL_DIOCRADDADDRS = DIOCRADDADDRS;
+unsigned IOCTL_DIOCRDELADDRS = DIOCRDELADDRS;
+unsigned IOCTL_DIOCRSETADDRS = DIOCRSETADDRS;
+unsigned IOCTL_DIOCRGETADDRS = DIOCRGETADDRS;
+unsigned IOCTL_DIOCRGETASTATS = DIOCRGETASTATS;
+unsigned IOCTL_DIOCRCLRASTATS = DIOCRCLRASTATS;
+unsigned IOCTL_DIOCRTSTADDRS = DIOCRTSTADDRS;
+unsigned IOCTL_DIOCRSETTFLAGS = DIOCRSETTFLAGS;
+unsigned IOCTL_DIOCRINADEFINE = DIOCRINADEFINE;
+unsigned IOCTL_DIOCOSFPFLUSH = DIOCOSFPFLUSH;
+unsigned IOCTL_DIOCOSFPADD = DIOCOSFPADD;
+unsigned IOCTL_DIOCOSFPGET = DIOCOSFPGET;
+unsigned IOCTL_DIOCXBEGIN = DIOCXBEGIN;
+unsigned IOCTL_DIOCXCOMMIT = DIOCXCOMMIT;
+unsigned IOCTL_DIOCXROLLBACK = DIOCXROLLBACK;
+unsigned IOCTL_DIOCGETSRCNODES = DIOCGETSRCNODES;
+unsigned IOCTL_DIOCCLRSRCNODES = DIOCCLRSRCNODES;
+unsigned IOCTL_DIOCSETHOSTID = DIOCSETHOSTID;
+unsigned IOCTL_DIOCIGETIFACES = DIOCIGETIFACES;
+unsigned IOCTL_DIOCSETIFFLAG = DIOCSETIFFLAG;
+unsigned IOCTL_DIOCCLRIFFLAG = DIOCCLRIFFLAG;
+unsigned IOCTL_DIOCKILLSRCNODES = DIOCKILLSRCNODES;
+unsigned IOCTL_SLIOCGUNIT = SLIOCGUNIT;
+unsigned IOCTL_SIOCGBTINFO = SIOCGBTINFO;
+unsigned IOCTL_SIOCGBTINFOA = SIOCGBTINFOA;
+unsigned IOCTL_SIOCNBTINFO = SIOCNBTINFO;
+unsigned IOCTL_SIOCSBTFLAGS = SIOCSBTFLAGS;
+unsigned IOCTL_SIOCSBTPOLICY = SIOCSBTPOLICY;
+unsigned IOCTL_SIOCSBTPTYPE = SIOCSBTPTYPE;
+unsigned IOCTL_SIOCGBTSTATS = SIOCGBTSTATS;
+unsigned IOCTL_SIOCZBTSTATS = SIOCZBTSTATS;
+unsigned IOCTL_SIOCBTDUMP = SIOCBTDUMP;
+unsigned IOCTL_SIOCSBTSCOMTU = SIOCSBTSCOMTU;
+unsigned IOCTL_SIOCGBTFEAT = SIOCGBTFEAT;
+unsigned IOCTL_SIOCADNAT = SIOCADNAT;
+unsigned IOCTL_SIOCRMNAT = SIOCRMNAT;
+unsigned IOCTL_SIOCGNATS = SIOCGNATS;
+unsigned IOCTL_SIOCGNATL = SIOCGNATL;
+unsigned IOCTL_SIOCPURGENAT = SIOCPURGENAT;
+unsigned IOCTL_SIOCCONNECTX = SIOCCONNECTX;
+unsigned IOCTL_SIOCCONNECTXDEL = SIOCCONNECTXDEL;
+unsigned IOCTL_SIOCSIFINFO_FLAGS = SIOCSIFINFO_FLAGS;
+unsigned IOCTL_SIOCAADDRCTL_POLICY = SIOCAADDRCTL_POLICY;
+unsigned IOCTL_SIOCDADDRCTL_POLICY = SIOCDADDRCTL_POLICY;
+unsigned IOCTL_SMBIOC_OPENSESSION = SMBIOC_OPENSESSION;
+unsigned IOCTL_SMBIOC_OPENSHARE = SMBIOC_OPENSHARE;
+unsigned IOCTL_SMBIOC_REQUEST = SMBIOC_REQUEST;
+unsigned IOCTL_SMBIOC_SETFLAGS = SMBIOC_SETFLAGS;
+unsigned IOCTL_SMBIOC_LOOKUP = SMBIOC_LOOKUP;
+unsigned IOCTL_SMBIOC_READ = SMBIOC_READ;
+unsigned IOCTL_SMBIOC_WRITE = SMBIOC_WRITE;
+unsigned IOCTL_AGPIOC_INFO = AGPIOC_INFO;
+unsigned IOCTL_AGPIOC_ACQUIRE = AGPIOC_ACQUIRE;
+unsigned IOCTL_AGPIOC_RELEASE = AGPIOC_RELEASE;
+unsigned IOCTL_AGPIOC_SETUP = AGPIOC_SETUP;
+unsigned IOCTL_AGPIOC_ALLOCATE = AGPIOC_ALLOCATE;
+unsigned IOCTL_AGPIOC_DEALLOCATE = AGPIOC_DEALLOCATE;
+unsigned IOCTL_AGPIOC_BIND = AGPIOC_BIND;
+unsigned IOCTL_AGPIOC_UNBIND = AGPIOC_UNBIND;
+unsigned IOCTL_AUDIO_GETINFO = AUDIO_GETINFO;
+unsigned IOCTL_AUDIO_SETINFO = AUDIO_SETINFO;
+unsigned IOCTL_AUDIO_DRAIN = AUDIO_DRAIN;
+unsigned IOCTL_AUDIO_FLUSH = AUDIO_FLUSH;
+unsigned IOCTL_AUDIO_WSEEK = AUDIO_WSEEK;
+unsigned IOCTL_AUDIO_RERROR = AUDIO_RERROR;
+unsigned IOCTL_AUDIO_GETDEV = AUDIO_GETDEV;
+unsigned IOCTL_AUDIO_GETENC = AUDIO_GETENC;
+unsigned IOCTL_AUDIO_GETFD = AUDIO_GETFD;
+unsigned IOCTL_AUDIO_SETFD = AUDIO_SETFD;
+unsigned IOCTL_AUDIO_PERROR = AUDIO_PERROR;
+unsigned IOCTL_AUDIO_GETIOFFS = AUDIO_GETIOFFS;
+unsigned IOCTL_AUDIO_GETOOFFS = AUDIO_GETOOFFS;
+unsigned IOCTL_AUDIO_GETPROPS = AUDIO_GETPROPS;
+unsigned IOCTL_AUDIO_GETBUFINFO = AUDIO_GETBUFINFO;
+unsigned IOCTL_AUDIO_SETCHAN = AUDIO_SETCHAN;
+unsigned IOCTL_AUDIO_GETCHAN = AUDIO_GETCHAN;
+unsigned IOCTL_AUDIO_QUERYFORMAT = AUDIO_QUERYFORMAT;
+unsigned IOCTL_AUDIO_GETFORMAT = AUDIO_GETFORMAT;
+unsigned IOCTL_AUDIO_SETFORMAT = AUDIO_SETFORMAT;
+unsigned IOCTL_AUDIO_MIXER_READ = AUDIO_MIXER_READ;
+unsigned IOCTL_AUDIO_MIXER_WRITE = AUDIO_MIXER_WRITE;
+unsigned IOCTL_AUDIO_MIXER_DEVINFO = AUDIO_MIXER_DEVINFO;
+unsigned IOCTL_ATAIOCCOMMAND = ATAIOCCOMMAND;
+unsigned IOCTL_ATABUSIOSCAN = ATABUSIOSCAN;
+unsigned IOCTL_ATABUSIORESET = ATABUSIORESET;
+unsigned IOCTL_ATABUSIODETACH = ATABUSIODETACH;
+unsigned IOCTL_CDIOCPLAYTRACKS = CDIOCPLAYTRACKS;
+unsigned IOCTL_CDIOCPLAYBLOCKS = CDIOCPLAYBLOCKS;
+unsigned IOCTL_CDIOCREADSUBCHANNEL = CDIOCREADSUBCHANNEL;
+unsigned IOCTL_CDIOREADTOCHEADER = CDIOREADTOCHEADER;
+unsigned IOCTL_CDIOREADTOCENTRIES = CDIOREADTOCENTRIES;
+unsigned IOCTL_CDIOREADMSADDR = CDIOREADMSADDR;
+unsigned IOCTL_CDIOCSETPATCH = CDIOCSETPATCH;
+unsigned IOCTL_CDIOCGETVOL = CDIOCGETVOL;
+unsigned IOCTL_CDIOCSETVOL = CDIOCSETVOL;
+unsigned IOCTL_CDIOCSETMONO = CDIOCSETMONO;
+unsigned IOCTL_CDIOCSETSTEREO = CDIOCSETSTEREO;
+unsigned IOCTL_CDIOCSETMUTE = CDIOCSETMUTE;
+unsigned IOCTL_CDIOCSETLEFT = CDIOCSETLEFT;
+unsigned IOCTL_CDIOCSETRIGHT = CDIOCSETRIGHT;
+unsigned IOCTL_CDIOCSETDEBUG = CDIOCSETDEBUG;
+unsigned IOCTL_CDIOCCLRDEBUG = CDIOCCLRDEBUG;
+unsigned IOCTL_CDIOCPAUSE = CDIOCPAUSE;
+unsigned IOCTL_CDIOCRESUME = CDIOCRESUME;
+unsigned IOCTL_CDIOCRESET = CDIOCRESET;
+unsigned IOCTL_CDIOCSTART = CDIOCSTART;
+unsigned IOCTL_CDIOCSTOP = CDIOCSTOP;
+unsigned IOCTL_CDIOCEJECT = CDIOCEJECT;
+unsigned IOCTL_CDIOCALLOW = CDIOCALLOW;
+unsigned IOCTL_CDIOCPREVENT = CDIOCPREVENT;
+unsigned IOCTL_CDIOCCLOSE = CDIOCCLOSE;
+unsigned IOCTL_CDIOCPLAYMSF = CDIOCPLAYMSF;
+unsigned IOCTL_CDIOCLOADUNLOAD = CDIOCLOADUNLOAD;
+unsigned IOCTL_CHIOMOVE = CHIOMOVE;
+unsigned IOCTL_CHIOEXCHANGE = CHIOEXCHANGE;
+unsigned IOCTL_CHIOPOSITION = CHIOPOSITION;
+unsigned IOCTL_CHIOGPICKER = CHIOGPICKER;
+unsigned IOCTL_CHIOSPICKER = CHIOSPICKER;
+unsigned IOCTL_CHIOGPARAMS = CHIOGPARAMS;
+unsigned IOCTL_CHIOIELEM = CHIOIELEM;
+unsigned IOCTL_OCHIOGSTATUS = OCHIOGSTATUS;
+unsigned IOCTL_CHIOGSTATUS = CHIOGSTATUS;
+unsigned IOCTL_CHIOSVOLTAG = CHIOSVOLTAG;
+unsigned IOCTL_CLOCKCTL_SETTIMEOFDAY = CLOCKCTL_SETTIMEOFDAY;
+unsigned IOCTL_CLOCKCTL_ADJTIME = CLOCKCTL_ADJTIME;
+unsigned IOCTL_CLOCKCTL_CLOCK_SETTIME = CLOCKCTL_CLOCK_SETTIME;
+unsigned IOCTL_CLOCKCTL_NTP_ADJTIME = CLOCKCTL_NTP_ADJTIME;
+unsigned IOCTL_IOC_CPU_SETSTATE = IOC_CPU_SETSTATE;
+unsigned IOCTL_IOC_CPU_GETSTATE = IOC_CPU_GETSTATE;
+unsigned IOCTL_IOC_CPU_GETCOUNT = IOC_CPU_GETCOUNT;
+unsigned IOCTL_IOC_CPU_MAPID = IOC_CPU_MAPID;
+unsigned IOCTL_IOC_CPU_UCODE_GET_VERSION = IOC_CPU_UCODE_GET_VERSION;
+unsigned IOCTL_IOC_CPU_UCODE_APPLY = IOC_CPU_UCODE_APPLY;
+unsigned IOCTL_DIOCGDINFO = DIOCGDINFO;
+unsigned IOCTL_DIOCSDINFO = DIOCSDINFO;
+unsigned IOCTL_DIOCWDINFO = DIOCWDINFO;
+unsigned IOCTL_DIOCRFORMAT = DIOCRFORMAT;
+unsigned IOCTL_DIOCWFORMAT = DIOCWFORMAT;
+unsigned IOCTL_DIOCSSTEP = DIOCSSTEP;
+unsigned IOCTL_DIOCSRETRIES = DIOCSRETRIES;
+unsigned IOCTL_DIOCKLABEL = DIOCKLABEL;
+unsigned IOCTL_DIOCWLABEL = DIOCWLABEL;
+unsigned IOCTL_DIOCSBAD = DIOCSBAD;
+unsigned IOCTL_DIOCEJECT = DIOCEJECT;
+unsigned IOCTL_ODIOCEJECT = ODIOCEJECT;
+unsigned IOCTL_DIOCLOCK = DIOCLOCK;
+unsigned IOCTL_DIOCGDEFLABEL = DIOCGDEFLABEL;
+unsigned IOCTL_DIOCCLRLABEL = DIOCCLRLABEL;
+unsigned IOCTL_DIOCGCACHE = DIOCGCACHE;
+unsigned IOCTL_DIOCSCACHE = DIOCSCACHE;
+unsigned IOCTL_DIOCCACHESYNC = DIOCCACHESYNC;
+unsigned IOCTL_DIOCBSLIST = DIOCBSLIST;
+unsigned IOCTL_DIOCBSFLUSH = DIOCBSFLUSH;
+unsigned IOCTL_DIOCAWEDGE = DIOCAWEDGE;
+unsigned IOCTL_DIOCGWEDGEINFO = DIOCGWEDGEINFO;
+unsigned IOCTL_DIOCDWEDGE = DIOCDWEDGE;
+unsigned IOCTL_DIOCLWEDGES = DIOCLWEDGES;
+unsigned IOCTL_DIOCGSTRATEGY = DIOCGSTRATEGY;
+unsigned IOCTL_DIOCSSTRATEGY = DIOCSSTRATEGY;
+unsigned IOCTL_DIOCGDISKINFO = DIOCGDISKINFO;
+unsigned IOCTL_DIOCTUR = DIOCTUR;
+unsigned IOCTL_DIOCMWEDGES = DIOCMWEDGES;
+unsigned IOCTL_DIOCGSECTORSIZE = DIOCGSECTORSIZE;
+unsigned IOCTL_DIOCGMEDIASIZE = DIOCGMEDIASIZE;
+unsigned IOCTL_DIOCRMWEDGES = DIOCRMWEDGES;
+unsigned IOCTL_DRVDETACHDEV = DRVDETACHDEV;
+unsigned IOCTL_DRVRESCANBUS = DRVRESCANBUS;
+unsigned IOCTL_DRVCTLCOMMAND = DRVCTLCOMMAND;
+unsigned IOCTL_DRVRESUMEDEV = DRVRESUMEDEV;
+unsigned IOCTL_DRVLISTDEV = DRVLISTDEV;
+unsigned IOCTL_DRVGETEVENT = DRVGETEVENT;
+unsigned IOCTL_DRVSUSPENDDEV = DRVSUSPENDDEV;
+unsigned IOCTL_DVD_READ_STRUCT = DVD_READ_STRUCT;
+unsigned IOCTL_DVD_WRITE_STRUCT = DVD_WRITE_STRUCT;
+unsigned IOCTL_DVD_AUTH = DVD_AUTH;
+unsigned IOCTL_ENVSYS_GETDICTIONARY = ENVSYS_GETDICTIONARY;
+unsigned IOCTL_ENVSYS_SETDICTIONARY = ENVSYS_SETDICTIONARY;
+unsigned IOCTL_ENVSYS_REMOVEPROPS = ENVSYS_REMOVEPROPS;
+unsigned IOCTL_ENVSYS_GTREDATA = ENVSYS_GTREDATA;
+unsigned IOCTL_ENVSYS_GTREINFO = ENVSYS_GTREINFO;
+unsigned IOCTL_KFILTER_BYFILTER = KFILTER_BYFILTER;
+unsigned IOCTL_KFILTER_BYNAME = KFILTER_BYNAME;
+unsigned IOCTL_FDIOCGETOPTS = FDIOCGETOPTS;
+unsigned IOCTL_FDIOCSETOPTS = FDIOCSETOPTS;
+unsigned IOCTL_FDIOCSETFORMAT = FDIOCSETFORMAT;
+unsigned IOCTL_FDIOCGETFORMAT = FDIOCGETFORMAT;
+unsigned IOCTL_FDIOCFORMAT_TRACK = FDIOCFORMAT_TRACK;
+unsigned IOCTL_FIOCLEX = FIOCLEX;
+unsigned IOCTL_FIONCLEX = FIONCLEX;
+unsigned IOCTL_FIOSEEKDATA = FIOSEEKDATA;
+unsigned IOCTL_FIOSEEKHOLE = FIOSEEKHOLE;
+unsigned IOCTL_FIONREAD = FIONREAD;
+unsigned IOCTL_FIONBIO = FIONBIO;
+unsigned IOCTL_FIOASYNC = FIOASYNC;
+unsigned IOCTL_FIOSETOWN = FIOSETOWN;
+unsigned IOCTL_FIOGETOWN = FIOGETOWN;
+unsigned IOCTL_OFIOGETBMAP = OFIOGETBMAP;
+unsigned IOCTL_FIOGETBMAP = FIOGETBMAP;
+unsigned IOCTL_FIONWRITE = FIONWRITE;
+unsigned IOCTL_FIONSPACE = FIONSPACE;
+unsigned IOCTL_GPIOINFO = GPIOINFO;
+unsigned IOCTL_GPIOSET = GPIOSET;
+unsigned IOCTL_GPIOUNSET = GPIOUNSET;
+unsigned IOCTL_GPIOREAD = GPIOREAD;
+unsigned IOCTL_GPIOWRITE = GPIOWRITE;
+unsigned IOCTL_GPIOTOGGLE = GPIOTOGGLE;
+unsigned IOCTL_GPIOATTACH = GPIOATTACH;
+unsigned IOCTL_PTIOCNETBSD = PTIOCNETBSD;
+unsigned IOCTL_PTIOCSUNOS = PTIOCSUNOS;
+unsigned IOCTL_PTIOCLINUX = PTIOCLINUX;
+unsigned IOCTL_PTIOCFREEBSD = PTIOCFREEBSD;
+unsigned IOCTL_PTIOCULTRIX = PTIOCULTRIX;
+unsigned IOCTL_TIOCHPCL = TIOCHPCL;
+unsigned IOCTL_TIOCGETP = TIOCGETP;
+unsigned IOCTL_TIOCSETP = TIOCSETP;
+unsigned IOCTL_TIOCSETN = TIOCSETN;
+unsigned IOCTL_TIOCSETC = TIOCSETC;
+unsigned IOCTL_TIOCGETC = TIOCGETC;
+unsigned IOCTL_TIOCLBIS = TIOCLBIS;
+unsigned IOCTL_TIOCLBIC = TIOCLBIC;
+unsigned IOCTL_TIOCLSET = TIOCLSET;
+unsigned IOCTL_TIOCLGET = TIOCLGET;
+unsigned IOCTL_TIOCSLTC = TIOCSLTC;
+unsigned IOCTL_TIOCGLTC = TIOCGLTC;
+unsigned IOCTL_OTIOCCONS = OTIOCCONS;
+unsigned IOCTL_JOY_SETTIMEOUT = JOY_SETTIMEOUT;
+unsigned IOCTL_JOY_GETTIMEOUT = JOY_GETTIMEOUT;
+unsigned IOCTL_JOY_SET_X_OFFSET = JOY_SET_X_OFFSET;
+unsigned IOCTL_JOY_SET_Y_OFFSET = JOY_SET_Y_OFFSET;
+unsigned IOCTL_JOY_GET_X_OFFSET = JOY_GET_X_OFFSET;
+unsigned IOCTL_JOY_GET_Y_OFFSET = JOY_GET_Y_OFFSET;
+unsigned IOCTL_OKIOCGSYMBOL = OKIOCGSYMBOL;
+unsigned IOCTL_OKIOCGVALUE = OKIOCGVALUE;
+unsigned IOCTL_KIOCGSIZE = KIOCGSIZE;
+unsigned IOCTL_KIOCGVALUE = KIOCGVALUE;
+unsigned IOCTL_KIOCGSYMBOL = KIOCGSYMBOL;
+unsigned IOCTL_LUAINFO = LUAINFO;
+unsigned IOCTL_LUACREATE = LUACREATE;
+unsigned IOCTL_LUADESTROY = LUADESTROY;
+unsigned IOCTL_LUAREQUIRE = LUAREQUIRE;
+unsigned IOCTL_LUALOAD = LUALOAD;
+unsigned IOCTL_MIDI_PRETIME = MIDI_PRETIME;
+unsigned IOCTL_MIDI_MPUMODE = MIDI_MPUMODE;
+unsigned IOCTL_MIDI_MPUCMD = MIDI_MPUCMD;
+unsigned IOCTL_SEQUENCER_RESET = SEQUENCER_RESET;
+unsigned IOCTL_SEQUENCER_SYNC = SEQUENCER_SYNC;
+unsigned IOCTL_SEQUENCER_INFO = SEQUENCER_INFO;
+unsigned IOCTL_SEQUENCER_CTRLRATE = SEQUENCER_CTRLRATE;
+unsigned IOCTL_SEQUENCER_GETOUTCOUNT = SEQUENCER_GETOUTCOUNT;
+unsigned IOCTL_SEQUENCER_GETINCOUNT = SEQUENCER_GETINCOUNT;
+unsigned IOCTL_SEQUENCER_RESETSAMPLES = SEQUENCER_RESETSAMPLES;
+unsigned IOCTL_SEQUENCER_NRSYNTHS = SEQUENCER_NRSYNTHS;
+unsigned IOCTL_SEQUENCER_NRMIDIS = SEQUENCER_NRMIDIS;
+unsigned IOCTL_SEQUENCER_THRESHOLD = SEQUENCER_THRESHOLD;
+unsigned IOCTL_SEQUENCER_MEMAVL = SEQUENCER_MEMAVL;
+unsigned IOCTL_SEQUENCER_PANIC = SEQUENCER_PANIC;
+unsigned IOCTL_SEQUENCER_OUTOFBAND = SEQUENCER_OUTOFBAND;
+unsigned IOCTL_SEQUENCER_GETTIME = SEQUENCER_GETTIME;
+unsigned IOCTL_SEQUENCER_TMR_TIMEBASE = SEQUENCER_TMR_TIMEBASE;
+unsigned IOCTL_SEQUENCER_TMR_START = SEQUENCER_TMR_START;
+unsigned IOCTL_SEQUENCER_TMR_STOP = SEQUENCER_TMR_STOP;
+unsigned IOCTL_SEQUENCER_TMR_CONTINUE = SEQUENCER_TMR_CONTINUE;
+unsigned IOCTL_SEQUENCER_TMR_TEMPO = SEQUENCER_TMR_TEMPO;
+unsigned IOCTL_SEQUENCER_TMR_SOURCE = SEQUENCER_TMR_SOURCE;
+unsigned IOCTL_SEQUENCER_TMR_METRONOME = SEQUENCER_TMR_METRONOME;
+unsigned IOCTL_SEQUENCER_TMR_SELECT = SEQUENCER_TMR_SELECT;
+unsigned IOCTL_MTIOCTOP = MTIOCTOP;
+unsigned IOCTL_MTIOCGET = MTIOCGET;
+unsigned IOCTL_MTIOCIEOT = MTIOCIEOT;
+unsigned IOCTL_MTIOCEEOT = MTIOCEEOT;
+unsigned IOCTL_MTIOCRDSPOS = MTIOCRDSPOS;
+unsigned IOCTL_MTIOCRDHPOS = MTIOCRDHPOS;
+unsigned IOCTL_MTIOCSLOCATE = MTIOCSLOCATE;
+unsigned IOCTL_MTIOCHLOCATE = MTIOCHLOCATE;
+unsigned IOCTL_POWER_EVENT_RECVDICT = POWER_EVENT_RECVDICT;
+unsigned IOCTL_POWER_IOC_GET_TYPE = POWER_IOC_GET_TYPE;
+unsigned IOCTL_RIOCGINFO = RIOCGINFO;
+unsigned IOCTL_RIOCSINFO = RIOCSINFO;
+unsigned IOCTL_RIOCSSRCH = RIOCSSRCH;
+unsigned IOCTL_RNDGETENTCNT = RNDGETENTCNT;
+unsigned IOCTL_RNDGETSRCNUM = RNDGETSRCNUM;
+unsigned IOCTL_RNDGETSRCNAME = RNDGETSRCNAME;
+unsigned IOCTL_RNDCTL = RNDCTL;
+unsigned IOCTL_RNDADDDATA = RNDADDDATA;
+unsigned IOCTL_RNDGETPOOLSTAT = RNDGETPOOLSTAT;
+unsigned IOCTL_RNDGETESTNUM = RNDGETESTNUM;
+unsigned IOCTL_RNDGETESTNAME = RNDGETESTNAME;
+unsigned IOCTL_SCIOCGET = SCIOCGET;
+unsigned IOCTL_SCIOCSET = SCIOCSET;
+unsigned IOCTL_SCIOCRESTART = SCIOCRESTART;
+unsigned IOCTL_SCIOC_USE_ADF = SCIOC_USE_ADF;
+unsigned IOCTL_SCIOCCOMMAND = SCIOCCOMMAND;
+unsigned IOCTL_SCIOCDEBUG = SCIOCDEBUG;
+unsigned IOCTL_SCIOCIDENTIFY = SCIOCIDENTIFY;
+unsigned IOCTL_OSCIOCIDENTIFY = OSCIOCIDENTIFY;
+unsigned IOCTL_SCIOCDECONFIG = SCIOCDECONFIG;
+unsigned IOCTL_SCIOCRECONFIG = SCIOCRECONFIG;
+unsigned IOCTL_SCIOCRESET = SCIOCRESET;
+unsigned IOCTL_SCBUSIOSCAN = SCBUSIOSCAN;
+unsigned IOCTL_SCBUSIORESET = SCBUSIORESET;
+unsigned IOCTL_SCBUSIODETACH = SCBUSIODETACH;
+unsigned IOCTL_SCBUSACCEL = SCBUSACCEL;
+unsigned IOCTL_SCBUSIOLLSCAN = SCBUSIOLLSCAN;
+unsigned IOCTL_SIOCSHIWAT = SIOCSHIWAT;
+unsigned IOCTL_SIOCGHIWAT = SIOCGHIWAT;
+unsigned IOCTL_SIOCSLOWAT = SIOCSLOWAT;
+unsigned IOCTL_SIOCGLOWAT = SIOCGLOWAT;
+unsigned IOCTL_SIOCATMARK = SIOCATMARK;
+unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
+unsigned IOCTL_SIOCGPGRP = SIOCGPGRP;
+unsigned IOCTL_SIOCPEELOFF = SIOCPEELOFF;
+unsigned IOCTL_SIOCADDRT = SIOCADDRT;
+unsigned IOCTL_SIOCDELRT = SIOCDELRT;
+unsigned IOCTL_SIOCSIFADDR = SIOCSIFADDR;
+unsigned IOCTL_SIOCGIFADDR = SIOCGIFADDR;
+unsigned IOCTL_SIOCSIFDSTADDR = SIOCSIFDSTADDR;
+unsigned IOCTL_SIOCGIFDSTADDR = SIOCGIFDSTADDR;
+unsigned IOCTL_SIOCSIFFLAGS = SIOCSIFFLAGS;
+unsigned IOCTL_SIOCGIFFLAGS = SIOCGIFFLAGS;
+unsigned IOCTL_SIOCGIFBRDADDR = SIOCGIFBRDADDR;
+unsigned IOCTL_SIOCSIFBRDADDR = SIOCSIFBRDADDR;
+unsigned IOCTL_SIOCGIFCONF = SIOCGIFCONF;
+unsigned IOCTL_SIOCGIFNETMASK = SIOCGIFNETMASK;
+unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
+unsigned IOCTL_SIOCGIFMETRIC = SIOCGIFMETRIC;
+unsigned IOCTL_SIOCSIFMETRIC = SIOCSIFMETRIC;
+unsigned IOCTL_SIOCDIFADDR = SIOCDIFADDR;
+unsigned IOCTL_SIOCAIFADDR = SIOCAIFADDR;
+unsigned IOCTL_SIOCGIFALIAS = SIOCGIFALIAS;
+unsigned IOCTL_SIOCGIFAFLAG_IN = SIOCGIFAFLAG_IN;
+unsigned IOCTL_SIOCALIFADDR = SIOCALIFADDR;
+unsigned IOCTL_SIOCGLIFADDR = SIOCGLIFADDR;
+unsigned IOCTL_SIOCDLIFADDR = SIOCDLIFADDR;
+unsigned IOCTL_SIOCSIFADDRPREF = SIOCSIFADDRPREF;
+unsigned IOCTL_SIOCGIFADDRPREF = SIOCGIFADDRPREF;
+unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
+unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
+unsigned IOCTL_SIOCGETVIFCNT = SIOCGETVIFCNT;
+unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT;
+unsigned IOCTL_SIOCSIFMEDIA = SIOCSIFMEDIA;
+unsigned IOCTL_SIOCGIFMEDIA = SIOCGIFMEDIA;
+unsigned IOCTL_SIOCSIFGENERIC = SIOCSIFGENERIC;
+unsigned IOCTL_SIOCGIFGENERIC = SIOCGIFGENERIC;
+unsigned IOCTL_SIOCSIFPHYADDR = SIOCSIFPHYADDR;
+unsigned IOCTL_SIOCGIFPSRCADDR = SIOCGIFPSRCADDR;
+unsigned IOCTL_SIOCGIFPDSTADDR = SIOCGIFPDSTADDR;
+unsigned IOCTL_SIOCDIFPHYADDR = SIOCDIFPHYADDR;
+unsigned IOCTL_SIOCSLIFPHYADDR = SIOCSLIFPHYADDR;
+unsigned IOCTL_SIOCGLIFPHYADDR = SIOCGLIFPHYADDR;
+unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
+unsigned IOCTL_SIOCGIFMTU = SIOCGIFMTU;
+unsigned IOCTL_SIOCSDRVSPEC = SIOCSDRVSPEC;
+unsigned IOCTL_SIOCGDRVSPEC = SIOCGDRVSPEC;
+unsigned IOCTL_SIOCIFCREATE = SIOCIFCREATE;
+unsigned IOCTL_SIOCIFDESTROY = SIOCIFDESTROY;
+unsigned IOCTL_SIOCIFGCLONERS = SIOCIFGCLONERS;
+unsigned IOCTL_SIOCGIFDLT = SIOCGIFDLT;
+unsigned IOCTL_SIOCGIFCAP = SIOCGIFCAP;
+unsigned IOCTL_SIOCSIFCAP = SIOCSIFCAP;
+unsigned IOCTL_SIOCSVH = SIOCSVH;
+unsigned IOCTL_SIOCGVH = SIOCGVH;
+unsigned IOCTL_SIOCINITIFADDR = SIOCINITIFADDR;
+unsigned IOCTL_SIOCGIFDATA = SIOCGIFDATA;
+unsigned IOCTL_SIOCZIFDATA = SIOCZIFDATA;
+unsigned IOCTL_SIOCGLINKSTR = SIOCGLINKSTR;
+unsigned IOCTL_SIOCSLINKSTR = SIOCSLINKSTR;
+unsigned IOCTL_SIOCGETHERCAP = SIOCGETHERCAP;
+unsigned IOCTL_SIOCGIFINDEX = SIOCGIFINDEX;
+unsigned IOCTL_SIOCSETHERCAP = SIOCSETHERCAP;
+unsigned IOCTL_SIOCSIFDESCR = SIOCSIFDESCR;
+unsigned IOCTL_SIOCGIFDESCR = SIOCGIFDESCR;
+unsigned IOCTL_SIOCGUMBINFO = SIOCGUMBINFO;
+unsigned IOCTL_SIOCSUMBPARAM = SIOCSUMBPARAM;
+unsigned IOCTL_SIOCGUMBPARAM = SIOCGUMBPARAM;
+unsigned IOCTL_SIOCSETPFSYNC = SIOCSETPFSYNC;
+unsigned IOCTL_SIOCGETPFSYNC = SIOCGETPFSYNC;
+unsigned IOCTL_PPS_IOC_CREATE = PPS_IOC_CREATE;
+unsigned IOCTL_PPS_IOC_DESTROY = PPS_IOC_DESTROY;
+unsigned IOCTL_PPS_IOC_SETPARAMS = PPS_IOC_SETPARAMS;
+unsigned IOCTL_PPS_IOC_GETPARAMS = PPS_IOC_GETPARAMS;
+unsigned IOCTL_PPS_IOC_GETCAP = PPS_IOC_GETCAP;
+unsigned IOCTL_PPS_IOC_FETCH = PPS_IOC_FETCH;
+unsigned IOCTL_PPS_IOC_KCBIND = PPS_IOC_KCBIND;
+unsigned IOCTL_TIOCEXCL = TIOCEXCL;
+unsigned IOCTL_TIOCNXCL = TIOCNXCL;
+unsigned IOCTL_TIOCFLUSH = TIOCFLUSH;
+unsigned IOCTL_TIOCGETA = TIOCGETA;
+unsigned IOCTL_TIOCSETA = TIOCSETA;
+unsigned IOCTL_TIOCSETAW = TIOCSETAW;
+unsigned IOCTL_TIOCSETAF = TIOCSETAF;
+unsigned IOCTL_TIOCGETD = TIOCGETD;
+unsigned IOCTL_TIOCSETD = TIOCSETD;
+unsigned IOCTL_TIOCGLINED = TIOCGLINED;
+unsigned IOCTL_TIOCSLINED = TIOCSLINED;
+unsigned IOCTL_TIOCSBRK = TIOCSBRK;
+unsigned IOCTL_TIOCCBRK = TIOCCBRK;
+unsigned IOCTL_TIOCSDTR = TIOCSDTR;
+unsigned IOCTL_TIOCCDTR = TIOCCDTR;
+unsigned IOCTL_TIOCGPGRP = TIOCGPGRP;
+unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
+unsigned IOCTL_TIOCOUTQ = TIOCOUTQ;
+unsigned IOCTL_TIOCSTI = TIOCSTI;
+unsigned IOCTL_TIOCNOTTY = TIOCNOTTY;
+unsigned IOCTL_TIOCPKT = TIOCPKT;
+unsigned IOCTL_TIOCSTOP = TIOCSTOP;
+unsigned IOCTL_TIOCSTART = TIOCSTART;
+unsigned IOCTL_TIOCMSET = TIOCMSET;
+unsigned IOCTL_TIOCMBIS = TIOCMBIS;
+unsigned IOCTL_TIOCMBIC = TIOCMBIC;
+unsigned IOCTL_TIOCMGET = TIOCMGET;
+unsigned IOCTL_TIOCREMOTE = TIOCREMOTE;
+unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ;
+unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
+unsigned IOCTL_TIOCUCNTL = TIOCUCNTL;
+unsigned IOCTL_TIOCSTAT = TIOCSTAT;
+unsigned IOCTL_TIOCGSID = TIOCGSID;
+unsigned IOCTL_TIOCCONS = TIOCCONS;
+unsigned IOCTL_TIOCSCTTY = TIOCSCTTY;
+unsigned IOCTL_TIOCEXT = TIOCEXT;
+unsigned IOCTL_TIOCSIG = TIOCSIG;
+unsigned IOCTL_TIOCDRAIN = TIOCDRAIN;
+unsigned IOCTL_TIOCGFLAGS = TIOCGFLAGS;
+unsigned IOCTL_TIOCSFLAGS = TIOCSFLAGS;
+unsigned IOCTL_TIOCDCDTIMESTAMP = TIOCDCDTIMESTAMP;
+unsigned IOCTL_TIOCRCVFRAME = TIOCRCVFRAME;
+unsigned IOCTL_TIOCXMTFRAME = TIOCXMTFRAME;
+unsigned IOCTL_TIOCPTMGET = TIOCPTMGET;
+unsigned IOCTL_TIOCGRANTPT = TIOCGRANTPT;
+unsigned IOCTL_TIOCPTSNAME = TIOCPTSNAME;
+unsigned IOCTL_TIOCSQSIZE = TIOCSQSIZE;
+unsigned IOCTL_TIOCGQSIZE = TIOCGQSIZE;
+unsigned IOCTL_VERIEXEC_LOAD = VERIEXEC_LOAD;
+unsigned IOCTL_VERIEXEC_TABLESIZE = VERIEXEC_TABLESIZE;
+unsigned IOCTL_VERIEXEC_DELETE = VERIEXEC_DELETE;
+unsigned IOCTL_VERIEXEC_QUERY = VERIEXEC_QUERY;
+unsigned IOCTL_VERIEXEC_DUMP = VERIEXEC_DUMP;
+unsigned IOCTL_VERIEXEC_FLUSH = VERIEXEC_FLUSH;
+unsigned IOCTL_VIDIOC_QUERYCAP = VIDIOC_QUERYCAP;
+unsigned IOCTL_VIDIOC_RESERVED = VIDIOC_RESERVED;
+unsigned IOCTL_VIDIOC_ENUM_FMT = VIDIOC_ENUM_FMT;
+unsigned IOCTL_VIDIOC_G_FMT = VIDIOC_G_FMT;
+unsigned IOCTL_VIDIOC_S_FMT = VIDIOC_S_FMT;
+unsigned IOCTL_VIDIOC_REQBUFS = VIDIOC_REQBUFS;
+unsigned IOCTL_VIDIOC_QUERYBUF = VIDIOC_QUERYBUF;
+unsigned IOCTL_VIDIOC_G_FBUF = VIDIOC_G_FBUF;
+unsigned IOCTL_VIDIOC_S_FBUF = VIDIOC_S_FBUF;
+unsigned IOCTL_VIDIOC_OVERLAY = VIDIOC_OVERLAY;
+unsigned IOCTL_VIDIOC_QBUF = VIDIOC_QBUF;
+unsigned IOCTL_VIDIOC_DQBUF = VIDIOC_DQBUF;
+unsigned IOCTL_VIDIOC_STREAMON = VIDIOC_STREAMON;
+unsigned IOCTL_VIDIOC_STREAMOFF = VIDIOC_STREAMOFF;
+unsigned IOCTL_VIDIOC_G_PARM = VIDIOC_G_PARM;
+unsigned IOCTL_VIDIOC_S_PARM = VIDIOC_S_PARM;
+unsigned IOCTL_VIDIOC_G_STD = VIDIOC_G_STD;
+unsigned IOCTL_VIDIOC_S_STD = VIDIOC_S_STD;
+unsigned IOCTL_VIDIOC_ENUMSTD = VIDIOC_ENUMSTD;
+unsigned IOCTL_VIDIOC_ENUMINPUT = VIDIOC_ENUMINPUT;
+unsigned IOCTL_VIDIOC_G_CTRL = VIDIOC_G_CTRL;
+unsigned IOCTL_VIDIOC_S_CTRL = VIDIOC_S_CTRL;
+unsigned IOCTL_VIDIOC_G_TUNER = VIDIOC_G_TUNER;
+unsigned IOCTL_VIDIOC_S_TUNER = VIDIOC_S_TUNER;
+unsigned IOCTL_VIDIOC_G_AUDIO = VIDIOC_G_AUDIO;
+unsigned IOCTL_VIDIOC_S_AUDIO = VIDIOC_S_AUDIO;
+unsigned IOCTL_VIDIOC_QUERYCTRL = VIDIOC_QUERYCTRL;
+unsigned IOCTL_VIDIOC_QUERYMENU = VIDIOC_QUERYMENU;
+unsigned IOCTL_VIDIOC_G_INPUT = VIDIOC_G_INPUT;
+unsigned IOCTL_VIDIOC_S_INPUT = VIDIOC_S_INPUT;
+unsigned IOCTL_VIDIOC_G_OUTPUT = VIDIOC_G_OUTPUT;
+unsigned IOCTL_VIDIOC_S_OUTPUT = VIDIOC_S_OUTPUT;
+unsigned IOCTL_VIDIOC_ENUMOUTPUT = VIDIOC_ENUMOUTPUT;
+unsigned IOCTL_VIDIOC_G_AUDOUT = VIDIOC_G_AUDOUT;
+unsigned IOCTL_VIDIOC_S_AUDOUT = VIDIOC_S_AUDOUT;
+unsigned IOCTL_VIDIOC_G_MODULATOR = VIDIOC_G_MODULATOR;
+unsigned IOCTL_VIDIOC_S_MODULATOR = VIDIOC_S_MODULATOR;
+unsigned IOCTL_VIDIOC_G_FREQUENCY = VIDIOC_G_FREQUENCY;
+unsigned IOCTL_VIDIOC_S_FREQUENCY = VIDIOC_S_FREQUENCY;
+unsigned IOCTL_VIDIOC_CROPCAP = VIDIOC_CROPCAP;
+unsigned IOCTL_VIDIOC_G_CROP = VIDIOC_G_CROP;
+unsigned IOCTL_VIDIOC_S_CROP = VIDIOC_S_CROP;
+unsigned IOCTL_VIDIOC_G_JPEGCOMP = VIDIOC_G_JPEGCOMP;
+unsigned IOCTL_VIDIOC_S_JPEGCOMP = VIDIOC_S_JPEGCOMP;
+unsigned IOCTL_VIDIOC_QUERYSTD = VIDIOC_QUERYSTD;
+unsigned IOCTL_VIDIOC_TRY_FMT = VIDIOC_TRY_FMT;
+unsigned IOCTL_VIDIOC_ENUMAUDIO = VIDIOC_ENUMAUDIO;
+unsigned IOCTL_VIDIOC_ENUMAUDOUT = VIDIOC_ENUMAUDOUT;
+unsigned IOCTL_VIDIOC_G_PRIORITY = VIDIOC_G_PRIORITY;
+unsigned IOCTL_VIDIOC_S_PRIORITY = VIDIOC_S_PRIORITY;
+unsigned IOCTL_VIDIOC_ENUM_FRAMESIZES = VIDIOC_ENUM_FRAMESIZES;
+unsigned IOCTL_VIDIOC_ENUM_FRAMEINTERVALS = VIDIOC_ENUM_FRAMEINTERVALS;
+unsigned IOCTL_WDOGIOC_GMODE = WDOGIOC_GMODE;
+unsigned IOCTL_WDOGIOC_SMODE = WDOGIOC_SMODE;
+unsigned IOCTL_WDOGIOC_WHICH = WDOGIOC_WHICH;
+unsigned IOCTL_WDOGIOC_TICKLE = WDOGIOC_TICKLE;
+unsigned IOCTL_WDOGIOC_GTICKLER = WDOGIOC_GTICKLER;
+unsigned IOCTL_WDOGIOC_GWDOGS = WDOGIOC_GWDOGS;
+unsigned IOCTL_KCOV_IOC_SETBUFSIZE = KCOV_IOC_SETBUFSIZE;
+unsigned IOCTL_KCOV_IOC_ENABLE = KCOV_IOC_ENABLE;
+unsigned IOCTL_KCOV_IOC_DISABLE = KCOV_IOC_DISABLE;
+unsigned IOCTL_IPMICTL_RECEIVE_MSG_TRUNC = IPMICTL_RECEIVE_MSG_TRUNC;
+unsigned IOCTL_IPMICTL_RECEIVE_MSG = IPMICTL_RECEIVE_MSG;
+unsigned IOCTL_IPMICTL_SEND_COMMAND = IPMICTL_SEND_COMMAND;
+unsigned IOCTL_IPMICTL_REGISTER_FOR_CMD = IPMICTL_REGISTER_FOR_CMD;
+unsigned IOCTL_IPMICTL_UNREGISTER_FOR_CMD = IPMICTL_UNREGISTER_FOR_CMD;
+unsigned IOCTL_IPMICTL_SET_GETS_EVENTS_CMD = IPMICTL_SET_GETS_EVENTS_CMD;
+unsigned IOCTL_IPMICTL_SET_MY_ADDRESS_CMD = IPMICTL_SET_MY_ADDRESS_CMD;
+unsigned IOCTL_IPMICTL_GET_MY_ADDRESS_CMD = IPMICTL_GET_MY_ADDRESS_CMD;
+unsigned IOCTL_IPMICTL_SET_MY_LUN_CMD = IPMICTL_SET_MY_LUN_CMD;
+unsigned IOCTL_IPMICTL_GET_MY_LUN_CMD = IPMICTL_GET_MY_LUN_CMD;
+unsigned IOCTL_SNDCTL_DSP_RESET = SNDCTL_DSP_RESET;
+unsigned IOCTL_SNDCTL_DSP_SYNC = SNDCTL_DSP_SYNC;
+unsigned IOCTL_SNDCTL_DSP_SPEED = SNDCTL_DSP_SPEED;
+unsigned IOCTL_SOUND_PCM_READ_RATE = SOUND_PCM_READ_RATE;
+unsigned IOCTL_SNDCTL_DSP_STEREO = SNDCTL_DSP_STEREO;
+unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE = SNDCTL_DSP_GETBLKSIZE;
+unsigned IOCTL_SNDCTL_DSP_SETFMT = SNDCTL_DSP_SETFMT;
+unsigned IOCTL_SOUND_PCM_READ_BITS = SOUND_PCM_READ_BITS;
+unsigned IOCTL_SNDCTL_DSP_CHANNELS = SNDCTL_DSP_CHANNELS;
+unsigned IOCTL_SOUND_PCM_READ_CHANNELS = SOUND_PCM_READ_CHANNELS;
+unsigned IOCTL_SOUND_PCM_WRITE_FILTER = SOUND_PCM_WRITE_FILTER;
+unsigned IOCTL_SOUND_PCM_READ_FILTER = SOUND_PCM_READ_FILTER;
+unsigned IOCTL_SNDCTL_DSP_POST = SNDCTL_DSP_POST;
+unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE = SNDCTL_DSP_SUBDIVIDE;
+unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT = SNDCTL_DSP_SETFRAGMENT;
+unsigned IOCTL_SNDCTL_DSP_GETFMTS = SNDCTL_DSP_GETFMTS;
+unsigned IOCTL_SNDCTL_DSP_GETOSPACE = SNDCTL_DSP_GETOSPACE;
+unsigned IOCTL_SNDCTL_DSP_GETISPACE = SNDCTL_DSP_GETISPACE;
+unsigned IOCTL_SNDCTL_DSP_NONBLOCK = SNDCTL_DSP_NONBLOCK;
+unsigned IOCTL_SNDCTL_DSP_GETCAPS = SNDCTL_DSP_GETCAPS;
+unsigned IOCTL_SNDCTL_DSP_GETTRIGGER = SNDCTL_DSP_GETTRIGGER;
+unsigned IOCTL_SNDCTL_DSP_SETTRIGGER = SNDCTL_DSP_SETTRIGGER;
+unsigned IOCTL_SNDCTL_DSP_GETIPTR = SNDCTL_DSP_GETIPTR;
+unsigned IOCTL_SNDCTL_DSP_GETOPTR = SNDCTL_DSP_GETOPTR;
+unsigned IOCTL_SNDCTL_DSP_MAPINBUF = SNDCTL_DSP_MAPINBUF;
+unsigned IOCTL_SNDCTL_DSP_MAPOUTBUF = SNDCTL_DSP_MAPOUTBUF;
+unsigned IOCTL_SNDCTL_DSP_SETSYNCRO = SNDCTL_DSP_SETSYNCRO;
+unsigned IOCTL_SNDCTL_DSP_SETDUPLEX = SNDCTL_DSP_SETDUPLEX;
+unsigned IOCTL_SNDCTL_DSP_PROFILE = SNDCTL_DSP_PROFILE;
+unsigned IOCTL_SNDCTL_DSP_GETODELAY = SNDCTL_DSP_GETODELAY;
+unsigned IOCTL_SOUND_MIXER_INFO = SOUND_MIXER_INFO;
+unsigned IOCTL_SOUND_OLD_MIXER_INFO = SOUND_OLD_MIXER_INFO;
+unsigned IOCTL_OSS_GETVERSION = OSS_GETVERSION;
+unsigned IOCTL_SNDCTL_SYSINFO = SNDCTL_SYSINFO;
+unsigned IOCTL_SNDCTL_AUDIOINFO = SNDCTL_AUDIOINFO;
+unsigned IOCTL_SNDCTL_ENGINEINFO = SNDCTL_ENGINEINFO;
+unsigned IOCTL_SNDCTL_DSP_GETPLAYVOL = SNDCTL_DSP_GETPLAYVOL;
+unsigned IOCTL_SNDCTL_DSP_SETPLAYVOL = SNDCTL_DSP_SETPLAYVOL;
+unsigned IOCTL_SNDCTL_DSP_GETRECVOL = SNDCTL_DSP_GETRECVOL;
+unsigned IOCTL_SNDCTL_DSP_SETRECVOL = SNDCTL_DSP_SETRECVOL;
+unsigned IOCTL_SNDCTL_DSP_SKIP = SNDCTL_DSP_SKIP;
+unsigned IOCTL_SNDCTL_DSP_SILENCE = SNDCTL_DSP_SILENCE;
+
+const int si_SEGV_MAPERR = SEGV_MAPERR;
+const int si_SEGV_ACCERR = SEGV_ACCERR;
+
+const int modctl_load = MODCTL_LOAD;
+const int modctl_unload = MODCTL_UNLOAD;
+const int modctl_stat = MODCTL_STAT;
+const int modctl_exists = MODCTL_EXISTS;
+
+const unsigned SHA1_CTX_sz = sizeof(SHA1_CTX);
+const unsigned SHA1_return_length = SHA1_DIGEST_STRING_LENGTH;
+
+const unsigned MD4_CTX_sz = sizeof(MD4_CTX);
+const unsigned MD4_return_length = MD4_DIGEST_STRING_LENGTH;
+
+const unsigned RMD160_CTX_sz = sizeof(RMD160_CTX);
+const unsigned RMD160_return_length = RMD160_DIGEST_STRING_LENGTH;
+
+const unsigned MD5_CTX_sz = sizeof(MD5_CTX);
+const unsigned MD5_return_length = MD5_DIGEST_STRING_LENGTH;
+
+const unsigned fpos_t_sz = sizeof(fpos_t);
+
+const unsigned MD2_CTX_sz = sizeof(MD2_CTX);
+const unsigned MD2_return_length = MD2_DIGEST_STRING_LENGTH;
+
+#define SHA2_CONST(LEN) \
+ const unsigned SHA##LEN##_CTX_sz = sizeof(SHA##LEN##_CTX); \
+ const unsigned SHA##LEN##_return_length = SHA##LEN##_DIGEST_STRING_LENGTH; \
+ const unsigned SHA##LEN##_block_length = SHA##LEN##_BLOCK_LENGTH; \
+ const unsigned SHA##LEN##_digest_length = SHA##LEN##_DIGEST_LENGTH
+
+SHA2_CONST(224);
+SHA2_CONST(256);
+SHA2_CONST(384);
+SHA2_CONST(512);
+
+#undef SHA2_CONST
+
+const int unvis_valid = UNVIS_VALID;
+const int unvis_validpush = UNVIS_VALIDPUSH;
+} // namespace __sanitizer
+
+using namespace __sanitizer;
+
+COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
+
+COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned));
+CHECK_TYPE_SIZE(pthread_key_t);
+
+// There are more undocumented fields in dl_phdr_info that we are not interested
+// in.
+COMPILER_CHECK(sizeof(__sanitizer_dl_phdr_info) <= sizeof(dl_phdr_info));
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_addr);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum);
+
+CHECK_TYPE_SIZE(glob_t);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_offs);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_flags);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_closedir);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_readdir);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_opendir);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_lstat);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_stat);
+
+CHECK_TYPE_SIZE(addrinfo);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_flags);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_family);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_socktype);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_addrlen);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_canonname);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_addr);
+
+CHECK_TYPE_SIZE(hostent);
+CHECK_SIZE_AND_OFFSET(hostent, h_name);
+CHECK_SIZE_AND_OFFSET(hostent, h_aliases);
+CHECK_SIZE_AND_OFFSET(hostent, h_addrtype);
+CHECK_SIZE_AND_OFFSET(hostent, h_length);
+CHECK_SIZE_AND_OFFSET(hostent, h_addr_list);
+
+CHECK_TYPE_SIZE(iovec);
+CHECK_SIZE_AND_OFFSET(iovec, iov_base);
+CHECK_SIZE_AND_OFFSET(iovec, iov_len);
+
+CHECK_TYPE_SIZE(msghdr);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_name);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_namelen);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_iov);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_iovlen);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_control);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_controllen);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_flags);
+
+CHECK_TYPE_SIZE(cmsghdr);
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
+
+COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
+CHECK_SIZE_AND_OFFSET(dirent, d_fileno);
+CHECK_SIZE_AND_OFFSET(dirent, d_reclen);
+
+CHECK_TYPE_SIZE(ifconf);
+CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
+CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);
+
+CHECK_TYPE_SIZE(pollfd);
+CHECK_SIZE_AND_OFFSET(pollfd, fd);
+CHECK_SIZE_AND_OFFSET(pollfd, events);
+CHECK_SIZE_AND_OFFSET(pollfd, revents);
+
+CHECK_TYPE_SIZE(nfds_t);
+
+CHECK_TYPE_SIZE(sigset_t);
+
+COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction));
+// Can't write checks for sa_handler and sa_sigaction due to them being
+// preprocessor macros.
+CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
+
+CHECK_TYPE_SIZE(wordexp_t);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_offs);
+
+COMPILER_CHECK(sizeof(__sanitizer_FILE) <= sizeof(FILE));
+CHECK_SIZE_AND_OFFSET(FILE, _p);
+CHECK_SIZE_AND_OFFSET(FILE, _r);
+CHECK_SIZE_AND_OFFSET(FILE, _w);
+CHECK_SIZE_AND_OFFSET(FILE, _flags);
+CHECK_SIZE_AND_OFFSET(FILE, _file);
+CHECK_SIZE_AND_OFFSET(FILE, _bf);
+CHECK_SIZE_AND_OFFSET(FILE, _lbfsize);
+CHECK_SIZE_AND_OFFSET(FILE, _cookie);
+CHECK_SIZE_AND_OFFSET(FILE, _close);
+CHECK_SIZE_AND_OFFSET(FILE, _read);
+CHECK_SIZE_AND_OFFSET(FILE, _seek);
+CHECK_SIZE_AND_OFFSET(FILE, _write);
+CHECK_SIZE_AND_OFFSET(FILE, _ext);
+CHECK_SIZE_AND_OFFSET(FILE, _up);
+CHECK_SIZE_AND_OFFSET(FILE, _ur);
+CHECK_SIZE_AND_OFFSET(FILE, _ubuf);
+CHECK_SIZE_AND_OFFSET(FILE, _nbuf);
+CHECK_SIZE_AND_OFFSET(FILE, _flush);
+CHECK_SIZE_AND_OFFSET(FILE, _lb_unused);
+CHECK_SIZE_AND_OFFSET(FILE, _blksize);
+CHECK_SIZE_AND_OFFSET(FILE, _offset);
+
+CHECK_TYPE_SIZE(tm);
+CHECK_SIZE_AND_OFFSET(tm, tm_sec);
+CHECK_SIZE_AND_OFFSET(tm, tm_min);
+CHECK_SIZE_AND_OFFSET(tm, tm_hour);
+CHECK_SIZE_AND_OFFSET(tm, tm_mday);
+CHECK_SIZE_AND_OFFSET(tm, tm_mon);
+CHECK_SIZE_AND_OFFSET(tm, tm_year);
+CHECK_SIZE_AND_OFFSET(tm, tm_wday);
+CHECK_SIZE_AND_OFFSET(tm, tm_yday);
+CHECK_SIZE_AND_OFFSET(tm, tm_isdst);
+CHECK_SIZE_AND_OFFSET(tm, tm_gmtoff);
+CHECK_SIZE_AND_OFFSET(tm, tm_zone);
+
+CHECK_TYPE_SIZE(ether_addr);
+
+CHECK_TYPE_SIZE(ipc_perm);
+CHECK_SIZE_AND_OFFSET(ipc_perm, _key);
+CHECK_SIZE_AND_OFFSET(ipc_perm, _seq);
+CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
+
+CHECK_TYPE_SIZE(shmid_ds);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_perm);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_segsz);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_atime);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_dtime);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_ctime);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_cpid);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_lpid);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_nattch);
+
+CHECK_TYPE_SIZE(clock_t);
+
+CHECK_TYPE_SIZE(ifaddrs);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask);
+// Compare against the union, because we can't reach into the union in a
+// compliant way.
+#ifdef ifa_dstaddr
+#undef ifa_dstaddr
+#endif
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data);
+
+CHECK_TYPE_SIZE(timeb);
+CHECK_SIZE_AND_OFFSET(timeb, time);
+CHECK_SIZE_AND_OFFSET(timeb, millitm);
+CHECK_SIZE_AND_OFFSET(timeb, timezone);
+CHECK_SIZE_AND_OFFSET(timeb, dstflag);
+
+CHECK_TYPE_SIZE(passwd);
+CHECK_SIZE_AND_OFFSET(passwd, pw_name);
+CHECK_SIZE_AND_OFFSET(passwd, pw_passwd);
+CHECK_SIZE_AND_OFFSET(passwd, pw_uid);
+CHECK_SIZE_AND_OFFSET(passwd, pw_gid);
+CHECK_SIZE_AND_OFFSET(passwd, pw_dir);
+CHECK_SIZE_AND_OFFSET(passwd, pw_shell);
+
+CHECK_SIZE_AND_OFFSET(passwd, pw_gecos);
+
+CHECK_TYPE_SIZE(group);
+CHECK_SIZE_AND_OFFSET(group, gr_name);
+CHECK_SIZE_AND_OFFSET(group, gr_passwd);
+CHECK_SIZE_AND_OFFSET(group, gr_gid);
+CHECK_SIZE_AND_OFFSET(group, gr_mem);
+
+CHECK_TYPE_SIZE(modctl_load_t);
+CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_filename);
+CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_flags);
+CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_props);
+CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_propslen);
+
+// Compat with 9.0
+struct statvfs90 {
+ unsigned long f_flag;
+ unsigned long f_bsize;
+ unsigned long f_frsize;
+ unsigned long f_iosize;
+
+ u64 f_blocks;
+ u64 f_bfree;
+ u64 f_bavail;
+ u64 f_bresvd;
+
+ u64 f_files;
+ u64 f_ffree;
+ u64 f_favail;
+ u64 f_fresvd;
+
+ u64 f_syncreads;
+ u64 f_syncwrites;
+
+ u64 f_asyncreads;
+ u64 f_asyncwrites;
+
+ struct {
+ s32 __fsid_val[2];
+ } f_fsidx;
+ unsigned long f_fsid;
+ unsigned long f_namemax;
+ u32 f_owner;
+
+ u32 f_spare[4];
+
+ char f_fstypename[32];
+ char f_mntonname[32];
+ char f_mntfromname[32];
+};
+unsigned struct_statvfs90_sz = sizeof(struct statvfs90);
+
+#endif // SANITIZER_NETBSD
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h
new file mode 100644
index 00000000000..dc6eb59b280
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h
@@ -0,0 +1,2421 @@
+//===-- sanitizer_platform_limits_netbsd.h --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer common code.
+//
+// Sizes and layouts of platform-specific NetBSD data structures.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_PLATFORM_LIMITS_NETBSD_H
+#define SANITIZER_PLATFORM_LIMITS_NETBSD_H
+
+#if SANITIZER_NETBSD
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform.h"
+
+namespace __sanitizer {
+void *__sanitizer_get_link_map_by_dlopen_handle(void *handle);
+#define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \
+ (link_map *)__sanitizer_get_link_map_by_dlopen_handle(handle)
+
+extern unsigned struct_utsname_sz;
+extern unsigned struct_stat_sz;
+extern unsigned struct_rusage_sz;
+extern unsigned siginfo_t_sz;
+extern unsigned struct_itimerval_sz;
+extern unsigned pthread_t_sz;
+extern unsigned pthread_mutex_t_sz;
+extern unsigned pthread_cond_t_sz;
+extern unsigned pid_t_sz;
+extern unsigned timeval_sz;
+extern unsigned uid_t_sz;
+extern unsigned gid_t_sz;
+extern unsigned mbstate_t_sz;
+extern unsigned struct_timezone_sz;
+extern unsigned struct_tms_sz;
+extern unsigned struct_itimerspec_sz;
+extern unsigned struct_sigevent_sz;
+extern unsigned struct_stack_t_sz;
+extern unsigned struct_sched_param_sz;
+extern unsigned struct_statfs_sz;
+extern unsigned struct_sockaddr_sz;
+unsigned ucontext_t_sz(void *ctx);
+
+extern unsigned struct_rlimit_sz;
+extern unsigned struct_utimbuf_sz;
+extern unsigned struct_timespec_sz;
+extern unsigned struct_sembuf_sz;
+
+extern unsigned struct_kevent_sz;
+extern unsigned struct_FTS_sz;
+extern unsigned struct_FTSENT_sz;
+
+extern unsigned struct_regex_sz;
+extern unsigned struct_regmatch_sz;
+
+extern unsigned struct_fstab_sz;
+
+struct __sanitizer_regmatch {
+ OFF_T rm_so;
+ OFF_T rm_eo;
+};
+
+typedef struct __sanitizer_modctl_load {
+ const char *ml_filename;
+ int ml_flags;
+ const char *ml_props;
+ uptr ml_propslen;
+} __sanitizer_modctl_load_t;
+extern const int modctl_load;
+extern const int modctl_unload;
+extern const int modctl_stat;
+extern const int modctl_exists;
+
+union __sanitizer_sigval {
+ int sival_int;
+ uptr sival_ptr;
+};
+
+struct __sanitizer_sigevent {
+ int sigev_notify;
+ int sigev_signo;
+ union __sanitizer_sigval sigev_value;
+ uptr sigev_notify_function;
+ uptr sigev_notify_attributes;
+};
+
+struct __sanitizer_aiocb {
+ u64 aio_offset;
+ uptr aio_buf;
+ uptr aio_nbytes;
+ int aio_fildes;
+ int aio_lio_opcode;
+ int aio_reqprio;
+ struct __sanitizer_sigevent aio_sigevent;
+ int _state;
+ int _errno;
+ long _retval;
+};
+
+struct __sanitizer_sem_t {
+ uptr data[5];
+};
+
+struct __sanitizer_ipc_perm {
+ u32 uid;
+ u32 gid;
+ u32 cuid;
+ u32 cgid;
+ u32 mode;
+ unsigned short _seq;
+ long _key;
+};
+
+struct __sanitizer_shmid_ds {
+ __sanitizer_ipc_perm shm_perm;
+ unsigned long shm_segsz;
+ u32 shm_lpid;
+ u32 shm_cpid;
+ unsigned int shm_nattch;
+ u64 shm_atime;
+ u64 shm_dtime;
+ u64 shm_ctime;
+ void *_shm_internal;
+};
+
+struct __sanitizer_protoent {
+ char *p_name;
+ char **p_aliases;
+ int p_proto;
+};
+
+struct __sanitizer_netent {
+ char *n_name;
+ char **n_aliases;
+ int n_addrtype;
+ u32 n_net;
+};
+
+extern unsigned struct_msqid_ds_sz;
+extern unsigned struct_mq_attr_sz;
+extern unsigned struct_timex_sz;
+extern unsigned struct_statvfs_sz;
+
+struct __sanitizer_iovec {
+ void *iov_base;
+ uptr iov_len;
+};
+
+struct __sanitizer_ifaddrs {
+ struct __sanitizer_ifaddrs *ifa_next;
+ char *ifa_name;
+ unsigned int ifa_flags;
+ void *ifa_addr; // (struct sockaddr *)
+ void *ifa_netmask; // (struct sockaddr *)
+ void *ifa_dstaddr; // (struct sockaddr *)
+ void *ifa_data;
+ unsigned int ifa_addrflags;
+};
+
+typedef unsigned int __sanitizer_socklen_t;
+
+typedef unsigned __sanitizer_pthread_key_t;
+
+typedef long long __sanitizer_time_t;
+typedef int __sanitizer_suseconds_t;
+
+struct __sanitizer_timeval {
+ __sanitizer_time_t tv_sec;
+ __sanitizer_suseconds_t tv_usec;
+};
+
+struct __sanitizer_itimerval {
+ struct __sanitizer_timeval it_interval;
+ struct __sanitizer_timeval it_value;
+};
+
+struct __sanitizer_timespec {
+ __sanitizer_time_t tv_sec;
+ long tv_nsec;
+};
+
+struct __sanitizer_passwd {
+ char *pw_name;
+ char *pw_passwd;
+ int pw_uid;
+ int pw_gid;
+ __sanitizer_time_t pw_change;
+ char *pw_class;
+ char *pw_gecos;
+ char *pw_dir;
+ char *pw_shell;
+ __sanitizer_time_t pw_expire;
+};
+
+struct __sanitizer_group {
+ char *gr_name;
+ char *gr_passwd;
+ int gr_gid;
+ char **gr_mem;
+};
+
+struct __sanitizer_timeb {
+ __sanitizer_time_t time;
+ unsigned short millitm;
+ short timezone;
+ short dstflag;
+};
+
+struct __sanitizer_ether_addr {
+ u8 octet[6];
+};
+
+struct __sanitizer_tm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+ long int tm_gmtoff;
+ const char *tm_zone;
+};
+
+struct __sanitizer_msghdr {
+ void *msg_name;
+ unsigned msg_namelen;
+ struct __sanitizer_iovec *msg_iov;
+ unsigned msg_iovlen;
+ void *msg_control;
+ unsigned msg_controllen;
+ int msg_flags;
+};
+
+struct __sanitizer_mmsghdr {
+ struct __sanitizer_msghdr msg_hdr;
+ unsigned int msg_len;
+};
+
+struct __sanitizer_cmsghdr {
+ unsigned cmsg_len;
+ int cmsg_level;
+ int cmsg_type;
+};
+
+struct __sanitizer_dirent {
+ u64 d_fileno;
+ u16 d_reclen;
+ // more fields that we don't care about
+};
+
+typedef int __sanitizer_clock_t;
+typedef int __sanitizer_clockid_t;
+
+typedef u32 __sanitizer___kernel_uid_t;
+typedef u32 __sanitizer___kernel_gid_t;
+typedef u64 __sanitizer___kernel_off_t;
+typedef struct {
+ u32 fds_bits[8];
+} __sanitizer___kernel_fd_set;
+
+typedef struct {
+ unsigned int pta_magic;
+ int pta_flags;
+ void *pta_private;
+} __sanitizer_pthread_attr_t;
+
+struct __sanitizer_sigset_t {
+ // uint32_t * 4
+ unsigned int __bits[4];
+};
+
+struct __sanitizer_siginfo {
+ // The size is determined by looking at sizeof of real siginfo_t on linux.
+ u64 opaque[128 / sizeof(u64)];
+};
+
+using __sanitizer_sighandler_ptr = void (*)(int sig);
+using __sanitizer_sigactionhandler_ptr = void (*)(int sig,
+ __sanitizer_siginfo *siginfo,
+ void *uctx);
+
+struct __sanitizer_sigaction {
+ union {
+ __sanitizer_sighandler_ptr handler;
+ __sanitizer_sigactionhandler_ptr sigaction;
+ };
+ __sanitizer_sigset_t sa_mask;
+ int sa_flags;
+};
+
+extern unsigned struct_sigaltstack_sz;
+
+typedef unsigned int __sanitizer_sigset13_t;
+
+struct __sanitizer_sigaction13 {
+ __sanitizer_sighandler_ptr osa_handler;
+ __sanitizer_sigset13_t osa_mask;
+ int osa_flags;
+};
+
+struct __sanitizer_sigaltstack {
+ void *ss_sp;
+ uptr ss_size;
+ int ss_flags;
+};
+
+typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t;
+
+struct __sanitizer_kernel_sigaction_t {
+ union {
+ void (*handler)(int signo);
+ void (*sigaction)(int signo, void *info, void *ctx);
+ };
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+ __sanitizer_kernel_sigset_t sa_mask;
+};
+
+extern const uptr sig_ign;
+extern const uptr sig_dfl;
+extern const uptr sig_err;
+extern const uptr sa_siginfo;
+
+extern int af_inet;
+extern int af_inet6;
+uptr __sanitizer_in_addr_sz(int af);
+
+struct __sanitizer_dl_phdr_info {
+ uptr dlpi_addr;
+ const char *dlpi_name;
+ const void *dlpi_phdr;
+ short dlpi_phnum;
+};
+
+extern unsigned struct_ElfW_Phdr_sz;
+
+struct __sanitizer_addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+#if defined(__sparc__) && defined(_LP64)
+ int __ai_pad0;
+#endif
+ unsigned ai_addrlen;
+#if defined(__alpha__) || (defined(__i386__) && defined(_LP64))
+ int __ai_pad0;
+#endif
+ char *ai_canonname;
+ void *ai_addr;
+ struct __sanitizer_addrinfo *ai_next;
+};
+
+struct __sanitizer_hostent {
+ char *h_name;
+ char **h_aliases;
+ int h_addrtype;
+ int h_length;
+ char **h_addr_list;
+};
+
+struct __sanitizer_pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+typedef unsigned __sanitizer_nfds_t;
+
+typedef int __sanitizer_lwpid_t;
+
+struct __sanitizer_glob_t {
+ uptr gl_pathc;
+ uptr gl_matchc;
+ uptr gl_offs;
+ int gl_flags;
+ char **gl_pathv;
+ int (*gl_errfunc)(const char *, int);
+ void (*gl_closedir)(void *dirp);
+ struct dirent *(*gl_readdir)(void *dirp);
+ void *(*gl_opendir)(const char *);
+ int (*gl_lstat)(const char *, void * /* struct stat* */);
+ int (*gl_stat)(const char *, void * /* struct stat* */);
+};
+
+extern int glob_nomatch;
+extern int glob_altdirfunc;
+extern const int wordexp_wrde_dooffs;
+
+extern unsigned path_max;
+
+extern int struct_ttyent_sz;
+
+extern int ptrace_pt_io;
+extern int ptrace_pt_lwpinfo;
+extern int ptrace_pt_set_event_mask;
+extern int ptrace_pt_get_event_mask;
+extern int ptrace_pt_get_process_state;
+extern int ptrace_pt_set_siginfo;
+extern int ptrace_pt_get_siginfo;
+extern int ptrace_pt_lwpstatus;
+extern int ptrace_pt_lwpnext;
+extern int ptrace_piod_read_d;
+extern int ptrace_piod_write_d;
+extern int ptrace_piod_read_i;
+extern int ptrace_piod_write_i;
+extern int ptrace_piod_read_auxv;
+extern int ptrace_pt_setregs;
+extern int ptrace_pt_getregs;
+extern int ptrace_pt_setfpregs;
+extern int ptrace_pt_getfpregs;
+extern int ptrace_pt_setdbregs;
+extern int ptrace_pt_getdbregs;
+
+struct __sanitizer_ptrace_io_desc {
+ int piod_op;
+ void *piod_offs;
+ void *piod_addr;
+ uptr piod_len;
+};
+
+struct __sanitizer_ptrace_lwpinfo {
+ __sanitizer_lwpid_t pl_lwpid;
+ int pl_event;
+};
+
+struct __sanitizer_ptrace_lwpstatus {
+ __sanitizer_lwpid_t pl_lwpid;
+ __sanitizer_sigset_t pl_sigpend;
+ __sanitizer_sigset_t pl_sigmask;
+ char pl_name[20];
+ void *pl_private;
+};
+
+extern unsigned struct_ptrace_ptrace_io_desc_struct_sz;
+extern unsigned struct_ptrace_ptrace_lwpinfo_struct_sz;
+extern unsigned struct_ptrace_ptrace_lwpstatus_struct_sz;
+extern unsigned struct_ptrace_ptrace_event_struct_sz;
+extern unsigned struct_ptrace_ptrace_siginfo_struct_sz;
+
+extern unsigned struct_ptrace_reg_struct_sz;
+extern unsigned struct_ptrace_fpreg_struct_sz;
+extern unsigned struct_ptrace_dbreg_struct_sz;
+
+struct __sanitizer_wordexp_t {
+ uptr we_wordc;
+ char **we_wordv;
+ uptr we_offs;
+ char *we_strings;
+ uptr we_nbytes;
+};
+
+struct __sanitizer_FILE {
+ unsigned char *_p;
+ int _r;
+ int _w;
+ unsigned short _flags;
+ short _file;
+ struct {
+ unsigned char *_base;
+ int _size;
+ } _bf;
+ int _lbfsize;
+ void *_cookie;
+ int (*_close)(void *ptr);
+ u64 (*_read)(void *, void *, uptr);
+ u64 (*_seek)(void *, u64, int);
+ uptr (*_write)(void *, const void *, uptr);
+ struct {
+ unsigned char *_base;
+ int _size;
+ } _ext;
+ unsigned char *_up;
+ int _ur;
+ unsigned char _ubuf[3];
+ unsigned char _nbuf[1];
+ int (*_flush)(void *ptr);
+ char _lb_unused[sizeof(uptr)];
+ int _blksize;
+ u64 _offset;
+};
+#define SANITIZER_HAS_STRUCT_FILE 1
+
+extern int shmctl_ipc_stat;
+
+// This simplifies generic code
+#define struct_shminfo_sz -1
+#define struct_shm_info_sz -1
+#define shmctl_shm_stat -1
+#define shmctl_ipc_info -1
+#define shmctl_shm_info -1
+
+extern unsigned struct_utmp_sz;
+extern unsigned struct_utmpx_sz;
+
+extern int map_fixed;
+
+// ioctl arguments
+struct __sanitizer_ifconf {
+ int ifc_len;
+ union {
+ void *ifcu_req;
+ } ifc_ifcu;
+};
+
+struct __sanitizer_ttyent {
+ char *ty_name;
+ char *ty_getty;
+ char *ty_type;
+ int ty_status;
+ char *ty_window;
+ char *ty_comment;
+ char *ty_class;
+};
+
+extern const unsigned long __sanitizer_bufsiz;
+
+#define IOC_NRBITS 8
+#define IOC_TYPEBITS 8
+#define IOC_SIZEBITS 14
+#define IOC_DIRBITS 2
+#define IOC_NONE 0U
+#define IOC_WRITE 1U
+#define IOC_READ 2U
+#define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
+#define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
+#define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
+#undef IOC_DIRMASK
+#define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
+#define IOC_NRSHIFT 0
+#define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
+#define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
+#define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
+#define EVIOC_EV_MAX 0x1f
+#define EVIOC_ABS_MAX 0x3f
+
+#define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
+#define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
+#define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
+#define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
+
+// ioctl request identifiers
+
+extern unsigned struct_altqreq_sz;
+extern unsigned struct_amr_user_ioctl_sz;
+extern unsigned struct_ap_control_sz;
+extern unsigned struct_apm_ctl_sz;
+extern unsigned struct_apm_event_info_sz;
+extern unsigned struct_apm_power_info_sz;
+extern unsigned struct_atabusiodetach_args_sz;
+extern unsigned struct_atabusioscan_args_sz;
+extern unsigned struct_ath_diag_sz;
+extern unsigned struct_atm_flowmap_sz;
+extern unsigned struct_audio_buf_info_sz;
+extern unsigned struct_audio_device_sz;
+extern unsigned struct_audio_encoding_sz;
+extern unsigned struct_audio_info_sz;
+extern unsigned struct_audio_offset_sz;
+extern unsigned struct_bio_locate_sz;
+extern unsigned struct_bioc_alarm_sz;
+extern unsigned struct_bioc_blink_sz;
+extern unsigned struct_bioc_disk_sz;
+extern unsigned struct_bioc_inq_sz;
+extern unsigned struct_bioc_setstate_sz;
+extern unsigned struct_bioc_vol_sz;
+extern unsigned struct_bioc_volops_sz;
+extern unsigned struct_bktr_chnlset_sz;
+extern unsigned struct_bktr_remote_sz;
+extern unsigned struct_blue_conf_sz;
+extern unsigned struct_blue_interface_sz;
+extern unsigned struct_blue_stats_sz;
+extern unsigned struct_bpf_dltlist_sz;
+extern unsigned struct_bpf_program_sz;
+extern unsigned struct_bpf_stat_old_sz;
+extern unsigned struct_bpf_stat_sz;
+extern unsigned struct_bpf_version_sz;
+extern unsigned struct_btreq_sz;
+extern unsigned struct_btsco_info_sz;
+extern unsigned struct_buffmem_desc_sz;
+extern unsigned struct_cbq_add_class_sz;
+extern unsigned struct_cbq_add_filter_sz;
+extern unsigned struct_cbq_delete_class_sz;
+extern unsigned struct_cbq_delete_filter_sz;
+extern unsigned struct_cbq_getstats_sz;
+extern unsigned struct_cbq_interface_sz;
+extern unsigned struct_cbq_modify_class_sz;
+extern unsigned struct_ccd_ioctl_sz;
+extern unsigned struct_cdnr_add_element_sz;
+extern unsigned struct_cdnr_add_filter_sz;
+extern unsigned struct_cdnr_add_tbmeter_sz;
+extern unsigned struct_cdnr_add_trtcm_sz;
+extern unsigned struct_cdnr_add_tswtcm_sz;
+extern unsigned struct_cdnr_delete_element_sz;
+extern unsigned struct_cdnr_delete_filter_sz;
+extern unsigned struct_cdnr_get_stats_sz;
+extern unsigned struct_cdnr_interface_sz;
+extern unsigned struct_cdnr_modify_tbmeter_sz;
+extern unsigned struct_cdnr_modify_trtcm_sz;
+extern unsigned struct_cdnr_modify_tswtcm_sz;
+extern unsigned struct_cdnr_tbmeter_stats_sz;
+extern unsigned struct_cdnr_tcm_stats_sz;
+extern unsigned struct_cgd_ioctl_sz;
+extern unsigned struct_cgd_user_sz;
+extern unsigned struct_changer_element_status_request_sz;
+extern unsigned struct_changer_exchange_request_sz;
+extern unsigned struct_changer_move_request_sz;
+extern unsigned struct_changer_params_sz;
+extern unsigned struct_changer_position_request_sz;
+extern unsigned struct_changer_set_voltag_request_sz;
+extern unsigned struct_clockctl_adjtime_sz;
+extern unsigned struct_clockctl_clock_settime_sz;
+extern unsigned struct_clockctl_ntp_adjtime_sz;
+extern unsigned struct_clockctl_settimeofday_sz;
+extern unsigned struct_cnwistats_sz;
+extern unsigned struct_cnwitrail_sz;
+extern unsigned struct_cnwstatus_sz;
+extern unsigned struct_count_info_sz;
+extern unsigned struct_cpu_ucode_sz;
+extern unsigned struct_cpu_ucode_version_sz;
+extern unsigned struct_crypt_kop_sz;
+extern unsigned struct_crypt_mkop_sz;
+extern unsigned struct_crypt_mop_sz;
+extern unsigned struct_crypt_op_sz;
+extern unsigned struct_crypt_result_sz;
+extern unsigned struct_crypt_sfop_sz;
+extern unsigned struct_crypt_sgop_sz;
+extern unsigned struct_cryptret_sz;
+extern unsigned struct_devdetachargs_sz;
+extern unsigned struct_devlistargs_sz;
+extern unsigned struct_devpmargs_sz;
+extern unsigned struct_devrescanargs_sz;
+extern unsigned struct_disk_badsecinfo_sz;
+extern unsigned struct_disk_strategy_sz;
+extern unsigned struct_disklabel_sz;
+extern unsigned struct_dkbad_sz;
+extern unsigned struct_dkwedge_info_sz;
+extern unsigned struct_dkwedge_list_sz;
+extern unsigned struct_dmio_setfunc_sz;
+extern unsigned struct_dmx_pes_filter_params_sz;
+extern unsigned struct_dmx_sct_filter_params_sz;
+extern unsigned struct_dmx_stc_sz;
+extern unsigned struct_dvb_diseqc_master_cmd_sz;
+extern unsigned struct_dvb_diseqc_slave_reply_sz;
+extern unsigned struct_dvb_frontend_event_sz;
+extern unsigned struct_dvb_frontend_info_sz;
+extern unsigned struct_dvb_frontend_parameters_sz;
+extern unsigned struct_eccapreq_sz;
+extern unsigned struct_fbcmap_sz;
+extern unsigned struct_fbcurpos_sz;
+extern unsigned struct_fbcursor_sz;
+extern unsigned struct_fbgattr_sz;
+extern unsigned struct_fbsattr_sz;
+extern unsigned struct_fbtype_sz;
+extern unsigned struct_fdformat_cmd_sz;
+extern unsigned struct_fdformat_parms_sz;
+extern unsigned struct_fifoq_conf_sz;
+extern unsigned struct_fifoq_getstats_sz;
+extern unsigned struct_fifoq_interface_sz;
+extern unsigned struct_format_op_sz;
+extern unsigned struct_fss_get_sz;
+extern unsigned struct_fss_set_sz;
+extern unsigned struct_gpio_attach_sz;
+extern unsigned struct_gpio_info_sz;
+extern unsigned struct_gpio_req_sz;
+extern unsigned struct_gpio_set_sz;
+extern unsigned struct_hfsc_add_class_sz;
+extern unsigned struct_hfsc_add_filter_sz;
+extern unsigned struct_hfsc_attach_sz;
+extern unsigned struct_hfsc_class_stats_sz;
+extern unsigned struct_hfsc_delete_class_sz;
+extern unsigned struct_hfsc_delete_filter_sz;
+extern unsigned struct_hfsc_interface_sz;
+extern unsigned struct_hfsc_modify_class_sz;
+extern unsigned struct_hpcfb_dsp_op_sz;
+extern unsigned struct_hpcfb_dspconf_sz;
+extern unsigned struct_hpcfb_fbconf_sz;
+extern unsigned struct_if_addrprefreq_sz;
+extern unsigned struct_if_clonereq_sz;
+extern unsigned struct_if_laddrreq_sz;
+extern unsigned struct_ifaddr_sz;
+extern unsigned struct_ifaliasreq_sz;
+extern unsigned struct_ifcapreq_sz;
+extern unsigned struct_ifconf_sz;
+extern unsigned struct_ifdatareq_sz;
+extern unsigned struct_ifdrv_sz;
+extern unsigned struct_ifmediareq_sz;
+extern unsigned struct_ifpppcstatsreq_sz;
+extern unsigned struct_ifpppstatsreq_sz;
+extern unsigned struct_ifreq_sz;
+extern unsigned struct_in6_addrpolicy_sz;
+extern unsigned struct_in6_ndireq_sz;
+extern unsigned struct_ioc_load_unload_sz;
+extern unsigned struct_ioc_patch_sz;
+extern unsigned struct_ioc_play_blocks_sz;
+extern unsigned struct_ioc_play_msf_sz;
+extern unsigned struct_ioc_play_track_sz;
+extern unsigned struct_ioc_read_subchannel_sz;
+extern unsigned struct_ioc_read_toc_entry_sz;
+extern unsigned struct_ioc_toc_header_sz;
+extern unsigned struct_ioc_vol_sz;
+extern unsigned struct_ioctl_pt_sz;
+extern unsigned struct_ioppt_sz;
+extern unsigned struct_iovec_sz;
+extern unsigned struct_ipfobj_sz;
+extern unsigned struct_irda_params_sz;
+extern unsigned struct_isp_fc_device_sz;
+extern unsigned struct_isp_fc_tsk_mgmt_sz;
+extern unsigned struct_isp_hba_device_sz;
+extern unsigned struct_isv_cmd_sz;
+extern unsigned struct_jobs_add_class_sz;
+extern unsigned struct_jobs_add_filter_sz;
+extern unsigned struct_jobs_attach_sz;
+extern unsigned struct_jobs_class_stats_sz;
+extern unsigned struct_jobs_delete_class_sz;
+extern unsigned struct_jobs_delete_filter_sz;
+extern unsigned struct_jobs_interface_sz;
+extern unsigned struct_jobs_modify_class_sz;
+extern unsigned struct_kbentry_sz;
+extern unsigned struct_kfilter_mapping_sz;
+extern unsigned struct_kiockeymap_sz;
+extern unsigned struct_ksyms_gsymbol_sz;
+extern unsigned struct_ksyms_gvalue_sz;
+extern unsigned struct_ksyms_ogsymbol_sz;
+extern unsigned struct_kttcp_io_args_sz;
+extern unsigned struct_ltchars_sz;
+extern unsigned struct_lua_create_sz;
+extern unsigned struct_lua_info_sz;
+extern unsigned struct_lua_load_sz;
+extern unsigned struct_lua_require_sz;
+extern unsigned struct_mbpp_param_sz;
+extern unsigned struct_md_conf_sz;
+extern unsigned struct_meteor_capframe_sz;
+extern unsigned struct_meteor_counts_sz;
+extern unsigned struct_meteor_geomet_sz;
+extern unsigned struct_meteor_pixfmt_sz;
+extern unsigned struct_meteor_video_sz;
+extern unsigned struct_mlx_cinfo_sz;
+extern unsigned struct_mlx_pause_sz;
+extern unsigned struct_mlx_rebuild_request_sz;
+extern unsigned struct_mlx_rebuild_status_sz;
+extern unsigned struct_mlx_usercommand_sz;
+extern unsigned struct_mly_user_command_sz;
+extern unsigned struct_mly_user_health_sz;
+extern unsigned struct_mtget_sz;
+extern unsigned struct_mtop_sz;
+extern unsigned struct_npf_ioctl_table_sz;
+extern unsigned struct_npioctl_sz;
+extern unsigned struct_nvme_pt_command_sz;
+extern unsigned struct_ochanger_element_status_request_sz;
+extern unsigned struct_ofiocdesc_sz;
+extern unsigned struct_okiockey_sz;
+extern unsigned struct_ortentry_sz;
+extern unsigned struct_oscsi_addr_sz;
+extern unsigned struct_oss_audioinfo_sz;
+extern unsigned struct_oss_sysinfo_sz;
+extern unsigned struct_pciio_bdf_cfgreg_sz;
+extern unsigned struct_pciio_businfo_sz;
+extern unsigned struct_pciio_cfgreg_sz;
+extern unsigned struct_pciio_drvname_sz;
+extern unsigned struct_pciio_drvnameonbus_sz;
+extern unsigned struct_pcvtid_sz;
+extern unsigned struct_pf_osfp_ioctl_sz;
+extern unsigned struct_pf_status_sz;
+extern unsigned struct_pfioc_altq_sz;
+extern unsigned struct_pfioc_if_sz;
+extern unsigned struct_pfioc_iface_sz;
+extern unsigned struct_pfioc_limit_sz;
+extern unsigned struct_pfioc_natlook_sz;
+extern unsigned struct_pfioc_pooladdr_sz;
+extern unsigned struct_pfioc_qstats_sz;
+extern unsigned struct_pfioc_rule_sz;
+extern unsigned struct_pfioc_ruleset_sz;
+extern unsigned struct_pfioc_src_node_kill_sz;
+extern unsigned struct_pfioc_src_nodes_sz;
+extern unsigned struct_pfioc_state_kill_sz;
+extern unsigned struct_pfioc_state_sz;
+extern unsigned struct_pfioc_states_sz;
+extern unsigned struct_pfioc_table_sz;
+extern unsigned struct_pfioc_tm_sz;
+extern unsigned struct_pfioc_trans_sz;
+extern unsigned struct_plistref_sz;
+extern unsigned struct_power_type_sz;
+extern unsigned struct_ppp_idle_sz;
+extern unsigned struct_ppp_option_data_sz;
+extern unsigned struct_ppp_rawin_sz;
+extern unsigned struct_pppoeconnectionstate_sz;
+extern unsigned struct_pppoediscparms_sz;
+extern unsigned struct_priq_add_class_sz;
+extern unsigned struct_priq_add_filter_sz;
+extern unsigned struct_priq_class_stats_sz;
+extern unsigned struct_priq_delete_class_sz;
+extern unsigned struct_priq_delete_filter_sz;
+extern unsigned struct_priq_interface_sz;
+extern unsigned struct_priq_modify_class_sz;
+extern unsigned struct_ptmget_sz;
+extern unsigned struct_pvctxreq_sz;
+extern unsigned struct_radio_info_sz;
+extern unsigned struct_red_conf_sz;
+extern unsigned struct_red_interface_sz;
+extern unsigned struct_red_stats_sz;
+extern unsigned struct_redparams_sz;
+extern unsigned struct_rf_pmparams_sz;
+extern unsigned struct_rf_pmstat_sz;
+extern unsigned struct_rf_recon_req_sz;
+extern unsigned struct_rio_conf_sz;
+extern unsigned struct_rio_interface_sz;
+extern unsigned struct_rio_stats_sz;
+extern unsigned struct_scan_io_sz;
+extern unsigned struct_scbusaccel_args_sz;
+extern unsigned struct_scbusiodetach_args_sz;
+extern unsigned struct_scbusioscan_args_sz;
+extern unsigned struct_scsi_addr_sz;
+extern unsigned struct_seq_event_rec_sz;
+extern unsigned struct_session_op_sz;
+extern unsigned struct_sgttyb_sz;
+extern unsigned struct_sioc_sg_req_sz;
+extern unsigned struct_sioc_vif_req_sz;
+extern unsigned struct_smbioc_flags_sz;
+extern unsigned struct_smbioc_lookup_sz;
+extern unsigned struct_smbioc_oshare_sz;
+extern unsigned struct_smbioc_ossn_sz;
+extern unsigned struct_smbioc_rq_sz;
+extern unsigned struct_smbioc_rw_sz;
+extern unsigned struct_spppauthcfg_sz;
+extern unsigned struct_spppauthfailuresettings_sz;
+extern unsigned struct_spppauthfailurestats_sz;
+extern unsigned struct_spppdnsaddrs_sz;
+extern unsigned struct_spppdnssettings_sz;
+extern unsigned struct_spppidletimeout_sz;
+extern unsigned struct_spppkeepalivesettings_sz;
+extern unsigned struct_sppplcpcfg_sz;
+extern unsigned struct_spppstatus_sz;
+extern unsigned struct_spppstatusncp_sz;
+extern unsigned struct_srt_rt_sz;
+extern unsigned struct_stic_xinfo_sz;
+extern unsigned struct_sun_dkctlr_sz;
+extern unsigned struct_sun_dkgeom_sz;
+extern unsigned struct_sun_dkpart_sz;
+extern unsigned struct_synth_info_sz;
+extern unsigned struct_tbrreq_sz;
+extern unsigned struct_tchars_sz;
+extern unsigned struct_termios_sz;
+extern unsigned struct_timeval_sz;
+extern unsigned struct_twe_drivecommand_sz;
+extern unsigned struct_twe_paramcommand_sz;
+extern unsigned struct_twe_usercommand_sz;
+extern unsigned struct_ukyopon_identify_sz;
+extern unsigned struct_urio_command_sz;
+extern unsigned struct_usb_alt_interface_sz;
+extern unsigned struct_usb_bulk_ra_wb_opt_sz;
+extern unsigned struct_usb_config_desc_sz;
+extern unsigned struct_usb_ctl_report_desc_sz;
+extern unsigned struct_usb_ctl_report_sz;
+extern unsigned struct_usb_ctl_request_sz;
+#if defined(__x86_64__)
+extern unsigned struct_nvmm_ioc_capability_sz;
+extern unsigned struct_nvmm_ioc_machine_create_sz;
+extern unsigned struct_nvmm_ioc_machine_destroy_sz;
+extern unsigned struct_nvmm_ioc_machine_configure_sz;
+extern unsigned struct_nvmm_ioc_vcpu_create_sz;
+extern unsigned struct_nvmm_ioc_vcpu_destroy_sz;
+extern unsigned struct_nvmm_ioc_vcpu_configure_sz;
+extern unsigned struct_nvmm_ioc_vcpu_setstate_sz;
+extern unsigned struct_nvmm_ioc_vcpu_getstate_sz;
+extern unsigned struct_nvmm_ioc_vcpu_inject_sz;
+extern unsigned struct_nvmm_ioc_vcpu_run_sz;
+extern unsigned struct_nvmm_ioc_gpa_map_sz;
+extern unsigned struct_nvmm_ioc_gpa_unmap_sz;
+extern unsigned struct_nvmm_ioc_hva_map_sz;
+extern unsigned struct_nvmm_ioc_hva_unmap_sz;
+extern unsigned struct_nvmm_ioc_ctl_sz;
+#endif
+extern unsigned struct_spi_ioctl_configure_sz;
+extern unsigned struct_spi_ioctl_transfer_sz;
+extern unsigned struct_autofs_daemon_request_sz;
+extern unsigned struct_autofs_daemon_done_sz;
+extern unsigned struct_sctp_connectx_addrs_sz;
+extern unsigned struct_usb_device_info_old_sz;
+extern unsigned struct_usb_device_info_sz;
+extern unsigned struct_usb_device_stats_sz;
+extern unsigned struct_usb_endpoint_desc_sz;
+extern unsigned struct_usb_full_desc_sz;
+extern unsigned struct_usb_interface_desc_sz;
+extern unsigned struct_usb_string_desc_sz;
+extern unsigned struct_utoppy_readfile_sz;
+extern unsigned struct_utoppy_rename_sz;
+extern unsigned struct_utoppy_stats_sz;
+extern unsigned struct_utoppy_writefile_sz;
+extern unsigned struct_v4l2_audio_sz;
+extern unsigned struct_v4l2_audioout_sz;
+extern unsigned struct_v4l2_buffer_sz;
+extern unsigned struct_v4l2_capability_sz;
+extern unsigned struct_v4l2_control_sz;
+extern unsigned struct_v4l2_crop_sz;
+extern unsigned struct_v4l2_cropcap_sz;
+extern unsigned struct_v4l2_fmtdesc_sz;
+extern unsigned struct_v4l2_format_sz;
+extern unsigned struct_v4l2_framebuffer_sz;
+extern unsigned struct_v4l2_frequency_sz;
+extern unsigned struct_v4l2_frmivalenum_sz;
+extern unsigned struct_v4l2_frmsizeenum_sz;
+extern unsigned struct_v4l2_input_sz;
+extern unsigned struct_v4l2_jpegcompression_sz;
+extern unsigned struct_v4l2_modulator_sz;
+extern unsigned struct_v4l2_output_sz;
+extern unsigned struct_v4l2_queryctrl_sz;
+extern unsigned struct_v4l2_querymenu_sz;
+extern unsigned struct_v4l2_requestbuffers_sz;
+extern unsigned struct_v4l2_standard_sz;
+extern unsigned struct_v4l2_streamparm_sz;
+extern unsigned struct_v4l2_tuner_sz;
+extern unsigned struct_vnd_ioctl_sz;
+extern unsigned struct_vnd_user_sz;
+extern unsigned struct_vt_stat_sz;
+extern unsigned struct_wdog_conf_sz;
+extern unsigned struct_wdog_mode_sz;
+extern unsigned struct_ipmi_recv_sz;
+extern unsigned struct_ipmi_req_sz;
+extern unsigned struct_ipmi_cmdspec_sz;
+extern unsigned struct_wfq_conf_sz;
+extern unsigned struct_wfq_getqid_sz;
+extern unsigned struct_wfq_getstats_sz;
+extern unsigned struct_wfq_interface_sz;
+extern unsigned struct_wfq_setweight_sz;
+extern unsigned struct_winsize_sz;
+extern unsigned struct_wscons_event_sz;
+extern unsigned struct_wsdisplay_addscreendata_sz;
+extern unsigned struct_wsdisplay_char_sz;
+extern unsigned struct_wsdisplay_cmap_sz;
+extern unsigned struct_wsdisplay_curpos_sz;
+extern unsigned struct_wsdisplay_cursor_sz;
+extern unsigned struct_wsdisplay_delscreendata_sz;
+extern unsigned struct_wsdisplay_fbinfo_sz;
+extern unsigned struct_wsdisplay_font_sz;
+extern unsigned struct_wsdisplay_kbddata_sz;
+extern unsigned struct_wsdisplay_msgattrs_sz;
+extern unsigned struct_wsdisplay_param_sz;
+extern unsigned struct_wsdisplay_scroll_data_sz;
+extern unsigned struct_wsdisplay_usefontdata_sz;
+extern unsigned struct_wsdisplayio_blit_sz;
+extern unsigned struct_wsdisplayio_bus_id_sz;
+extern unsigned struct_wsdisplayio_edid_info_sz;
+extern unsigned struct_wsdisplayio_fbinfo_sz;
+extern unsigned struct_wskbd_bell_data_sz;
+extern unsigned struct_wskbd_keyrepeat_data_sz;
+extern unsigned struct_wskbd_map_data_sz;
+extern unsigned struct_wskbd_scroll_data_sz;
+extern unsigned struct_wsmouse_calibcoords_sz;
+extern unsigned struct_wsmouse_id_sz;
+extern unsigned struct_wsmouse_repeat_sz;
+extern unsigned struct_wsmux_device_list_sz;
+extern unsigned struct_wsmux_device_sz;
+extern unsigned struct_xd_iocmd_sz;
+
+extern unsigned struct_scsireq_sz;
+extern unsigned struct_tone_sz;
+extern unsigned union_twe_statrequest_sz;
+extern unsigned struct_usb_device_descriptor_sz;
+extern unsigned struct_vt_mode_sz;
+extern unsigned struct__old_mixer_info_sz;
+extern unsigned struct__agp_allocate_sz;
+extern unsigned struct__agp_bind_sz;
+extern unsigned struct__agp_info_sz;
+extern unsigned struct__agp_setup_sz;
+extern unsigned struct__agp_unbind_sz;
+extern unsigned struct_atareq_sz;
+extern unsigned struct_cpustate_sz;
+extern unsigned struct_dmx_caps_sz;
+extern unsigned enum_dmx_source_sz;
+extern unsigned union_dvd_authinfo_sz;
+extern unsigned union_dvd_struct_sz;
+extern unsigned enum_v4l2_priority_sz;
+extern unsigned struct_envsys_basic_info_sz;
+extern unsigned struct_envsys_tre_data_sz;
+extern unsigned enum_fe_sec_mini_cmd_sz;
+extern unsigned enum_fe_sec_tone_mode_sz;
+extern unsigned enum_fe_sec_voltage_sz;
+extern unsigned enum_fe_status_sz;
+extern unsigned struct_gdt_ctrt_sz;
+extern unsigned struct_gdt_event_sz;
+extern unsigned struct_gdt_osv_sz;
+extern unsigned struct_gdt_rescan_sz;
+extern unsigned struct_gdt_statist_sz;
+extern unsigned struct_gdt_ucmd_sz;
+extern unsigned struct_iscsi_conn_status_parameters_sz;
+extern unsigned struct_iscsi_get_version_parameters_sz;
+extern unsigned struct_iscsi_iocommand_parameters_sz;
+extern unsigned struct_iscsi_login_parameters_sz;
+extern unsigned struct_iscsi_logout_parameters_sz;
+extern unsigned struct_iscsi_register_event_parameters_sz;
+extern unsigned struct_iscsi_remove_parameters_sz;
+extern unsigned struct_iscsi_send_targets_parameters_sz;
+extern unsigned struct_iscsi_set_node_name_parameters_sz;
+extern unsigned struct_iscsi_wait_event_parameters_sz;
+extern unsigned struct_isp_stats_sz;
+extern unsigned struct_lsenable_sz;
+extern unsigned struct_lsdisable_sz;
+extern unsigned struct_audio_format_query_sz;
+extern unsigned struct_mixer_ctrl_sz;
+extern unsigned struct_mixer_devinfo_sz;
+extern unsigned struct_mpu_command_rec_sz;
+extern unsigned struct_rndstat_sz;
+extern unsigned struct_rndstat_name_sz;
+extern unsigned struct_rndctl_sz;
+extern unsigned struct_rnddata_sz;
+extern unsigned struct_rndpoolstat_sz;
+extern unsigned struct_rndstat_est_sz;
+extern unsigned struct_rndstat_est_name_sz;
+extern unsigned struct_pps_params_sz;
+extern unsigned struct_pps_info_sz;
+extern unsigned struct_mixer_info_sz;
+extern unsigned struct_RF_SparetWait_sz;
+extern unsigned struct_RF_ComponentLabel_sz;
+extern unsigned struct_RF_SingleComponent_sz;
+extern unsigned struct_RF_ProgressInfo_sz;
+extern unsigned struct_nvlist_ref_sz;
+extern unsigned struct_StringList_sz;
+
+// A special value to mark ioctls that are not present on the target platform,
+// when it can not be determined without including any system headers.
+extern const unsigned IOCTL_NOT_PRESENT;
+
+extern unsigned IOCTL_AFM_ADDFMAP;
+extern unsigned IOCTL_AFM_DELFMAP;
+extern unsigned IOCTL_AFM_CLEANFMAP;
+extern unsigned IOCTL_AFM_GETFMAP;
+extern unsigned IOCTL_ALTQGTYPE;
+extern unsigned IOCTL_ALTQTBRSET;
+extern unsigned IOCTL_ALTQTBRGET;
+extern unsigned IOCTL_BLUE_IF_ATTACH;
+extern unsigned IOCTL_BLUE_IF_DETACH;
+extern unsigned IOCTL_BLUE_ENABLE;
+extern unsigned IOCTL_BLUE_DISABLE;
+extern unsigned IOCTL_BLUE_CONFIG;
+extern unsigned IOCTL_BLUE_GETSTATS;
+extern unsigned IOCTL_CBQ_IF_ATTACH;
+extern unsigned IOCTL_CBQ_IF_DETACH;
+extern unsigned IOCTL_CBQ_ENABLE;
+extern unsigned IOCTL_CBQ_DISABLE;
+extern unsigned IOCTL_CBQ_CLEAR_HIERARCHY;
+extern unsigned IOCTL_CBQ_ADD_CLASS;
+extern unsigned IOCTL_CBQ_DEL_CLASS;
+extern unsigned IOCTL_CBQ_MODIFY_CLASS;
+extern unsigned IOCTL_CBQ_ADD_FILTER;
+extern unsigned IOCTL_CBQ_DEL_FILTER;
+extern unsigned IOCTL_CBQ_GETSTATS;
+extern unsigned IOCTL_CDNR_IF_ATTACH;
+extern unsigned IOCTL_CDNR_IF_DETACH;
+extern unsigned IOCTL_CDNR_ENABLE;
+extern unsigned IOCTL_CDNR_DISABLE;
+extern unsigned IOCTL_CDNR_ADD_FILTER;
+extern unsigned IOCTL_CDNR_DEL_FILTER;
+extern unsigned IOCTL_CDNR_GETSTATS;
+extern unsigned IOCTL_CDNR_ADD_ELEM;
+extern unsigned IOCTL_CDNR_DEL_ELEM;
+extern unsigned IOCTL_CDNR_ADD_TBM;
+extern unsigned IOCTL_CDNR_MOD_TBM;
+extern unsigned IOCTL_CDNR_TBM_STATS;
+extern unsigned IOCTL_CDNR_ADD_TCM;
+extern unsigned IOCTL_CDNR_MOD_TCM;
+extern unsigned IOCTL_CDNR_TCM_STATS;
+extern unsigned IOCTL_CDNR_ADD_TSW;
+extern unsigned IOCTL_CDNR_MOD_TSW;
+extern unsigned IOCTL_FIFOQ_IF_ATTACH;
+extern unsigned IOCTL_FIFOQ_IF_DETACH;
+extern unsigned IOCTL_FIFOQ_ENABLE;
+extern unsigned IOCTL_FIFOQ_DISABLE;
+extern unsigned IOCTL_FIFOQ_CONFIG;
+extern unsigned IOCTL_FIFOQ_GETSTATS;
+extern unsigned IOCTL_HFSC_IF_ATTACH;
+extern unsigned IOCTL_HFSC_IF_DETACH;
+extern unsigned IOCTL_HFSC_ENABLE;
+extern unsigned IOCTL_HFSC_DISABLE;
+extern unsigned IOCTL_HFSC_CLEAR_HIERARCHY;
+extern unsigned IOCTL_HFSC_ADD_CLASS;
+extern unsigned IOCTL_HFSC_DEL_CLASS;
+extern unsigned IOCTL_HFSC_MOD_CLASS;
+extern unsigned IOCTL_HFSC_ADD_FILTER;
+extern unsigned IOCTL_HFSC_DEL_FILTER;
+extern unsigned IOCTL_HFSC_GETSTATS;
+extern unsigned IOCTL_JOBS_IF_ATTACH;
+extern unsigned IOCTL_JOBS_IF_DETACH;
+extern unsigned IOCTL_JOBS_ENABLE;
+extern unsigned IOCTL_JOBS_DISABLE;
+extern unsigned IOCTL_JOBS_CLEAR;
+extern unsigned IOCTL_JOBS_ADD_CLASS;
+extern unsigned IOCTL_JOBS_DEL_CLASS;
+extern unsigned IOCTL_JOBS_MOD_CLASS;
+extern unsigned IOCTL_JOBS_ADD_FILTER;
+extern unsigned IOCTL_JOBS_DEL_FILTER;
+extern unsigned IOCTL_JOBS_GETSTATS;
+extern unsigned IOCTL_PRIQ_IF_ATTACH;
+extern unsigned IOCTL_PRIQ_IF_DETACH;
+extern unsigned IOCTL_PRIQ_ENABLE;
+extern unsigned IOCTL_PRIQ_DISABLE;
+extern unsigned IOCTL_PRIQ_CLEAR;
+extern unsigned IOCTL_PRIQ_ADD_CLASS;
+extern unsigned IOCTL_PRIQ_DEL_CLASS;
+extern unsigned IOCTL_PRIQ_MOD_CLASS;
+extern unsigned IOCTL_PRIQ_ADD_FILTER;
+extern unsigned IOCTL_PRIQ_DEL_FILTER;
+extern unsigned IOCTL_PRIQ_GETSTATS;
+extern unsigned IOCTL_RED_IF_ATTACH;
+extern unsigned IOCTL_RED_IF_DETACH;
+extern unsigned IOCTL_RED_ENABLE;
+extern unsigned IOCTL_RED_DISABLE;
+extern unsigned IOCTL_RED_CONFIG;
+extern unsigned IOCTL_RED_GETSTATS;
+extern unsigned IOCTL_RED_SETDEFAULTS;
+extern unsigned IOCTL_RIO_IF_ATTACH;
+extern unsigned IOCTL_RIO_IF_DETACH;
+extern unsigned IOCTL_RIO_ENABLE;
+extern unsigned IOCTL_RIO_DISABLE;
+extern unsigned IOCTL_RIO_CONFIG;
+extern unsigned IOCTL_RIO_GETSTATS;
+extern unsigned IOCTL_RIO_SETDEFAULTS;
+extern unsigned IOCTL_WFQ_IF_ATTACH;
+extern unsigned IOCTL_WFQ_IF_DETACH;
+extern unsigned IOCTL_WFQ_ENABLE;
+extern unsigned IOCTL_WFQ_DISABLE;
+extern unsigned IOCTL_WFQ_CONFIG;
+extern unsigned IOCTL_WFQ_GET_STATS;
+extern unsigned IOCTL_WFQ_GET_QID;
+extern unsigned IOCTL_WFQ_SET_WEIGHT;
+extern unsigned IOCTL_CRIOGET;
+extern unsigned IOCTL_CIOCFSESSION;
+extern unsigned IOCTL_CIOCKEY;
+extern unsigned IOCTL_CIOCNFKEYM;
+extern unsigned IOCTL_CIOCNFSESSION;
+extern unsigned IOCTL_CIOCNCRYPTRETM;
+extern unsigned IOCTL_CIOCNCRYPTRET;
+extern unsigned IOCTL_CIOCGSESSION;
+extern unsigned IOCTL_CIOCNGSESSION;
+extern unsigned IOCTL_CIOCCRYPT;
+extern unsigned IOCTL_CIOCNCRYPTM;
+extern unsigned IOCTL_CIOCASYMFEAT;
+extern unsigned IOCTL_APM_IOC_REJECT;
+extern unsigned IOCTL_APM_IOC_STANDBY;
+extern unsigned IOCTL_APM_IOC_SUSPEND;
+extern unsigned IOCTL_OAPM_IOC_GETPOWER;
+extern unsigned IOCTL_APM_IOC_GETPOWER;
+extern unsigned IOCTL_APM_IOC_NEXTEVENT;
+extern unsigned IOCTL_APM_IOC_DEV_CTL;
+extern unsigned IOCTL_NETBSD_DM_IOCTL;
+extern unsigned IOCTL_DMIO_SETFUNC;
+extern unsigned IOCTL_DMX_START;
+extern unsigned IOCTL_DMX_STOP;
+extern unsigned IOCTL_DMX_SET_FILTER;
+extern unsigned IOCTL_DMX_SET_PES_FILTER;
+extern unsigned IOCTL_DMX_SET_BUFFER_SIZE;
+extern unsigned IOCTL_DMX_GET_STC;
+extern unsigned IOCTL_DMX_ADD_PID;
+extern unsigned IOCTL_DMX_REMOVE_PID;
+extern unsigned IOCTL_DMX_GET_CAPS;
+extern unsigned IOCTL_DMX_SET_SOURCE;
+extern unsigned IOCTL_FE_READ_STATUS;
+extern unsigned IOCTL_FE_READ_BER;
+extern unsigned IOCTL_FE_READ_SNR;
+extern unsigned IOCTL_FE_READ_SIGNAL_STRENGTH;
+extern unsigned IOCTL_FE_READ_UNCORRECTED_BLOCKS;
+extern unsigned IOCTL_FE_SET_FRONTEND;
+extern unsigned IOCTL_FE_GET_FRONTEND;
+extern unsigned IOCTL_FE_GET_EVENT;
+extern unsigned IOCTL_FE_GET_INFO;
+extern unsigned IOCTL_FE_DISEQC_RESET_OVERLOAD;
+extern unsigned IOCTL_FE_DISEQC_SEND_MASTER_CMD;
+extern unsigned IOCTL_FE_DISEQC_RECV_SLAVE_REPLY;
+extern unsigned IOCTL_FE_DISEQC_SEND_BURST;
+extern unsigned IOCTL_FE_SET_TONE;
+extern unsigned IOCTL_FE_SET_VOLTAGE;
+extern unsigned IOCTL_FE_ENABLE_HIGH_LNB_VOLTAGE;
+extern unsigned IOCTL_FE_SET_FRONTEND_TUNE_MODE;
+extern unsigned IOCTL_FE_DISHNETWORK_SEND_LEGACY_CMD;
+extern unsigned IOCTL_FILEMON_SET_FD;
+extern unsigned IOCTL_FILEMON_SET_PID;
+extern unsigned IOCTL_HDAUDIO_FGRP_INFO;
+extern unsigned IOCTL_HDAUDIO_FGRP_GETCONFIG;
+extern unsigned IOCTL_HDAUDIO_FGRP_SETCONFIG;
+extern unsigned IOCTL_HDAUDIO_FGRP_WIDGET_INFO;
+extern unsigned IOCTL_HDAUDIO_FGRP_CODEC_INFO;
+extern unsigned IOCTL_HDAUDIO_AFG_WIDGET_INFO;
+extern unsigned IOCTL_HDAUDIO_AFG_CODEC_INFO;
+extern unsigned IOCTL_CEC_GET_PHYS_ADDR;
+extern unsigned IOCTL_CEC_GET_LOG_ADDRS;
+extern unsigned IOCTL_CEC_SET_LOG_ADDRS;
+extern unsigned IOCTL_CEC_GET_VENDOR_ID;
+extern unsigned IOCTL_HPCFBIO_GCONF;
+extern unsigned IOCTL_HPCFBIO_SCONF;
+extern unsigned IOCTL_HPCFBIO_GDSPCONF;
+extern unsigned IOCTL_HPCFBIO_SDSPCONF;
+extern unsigned IOCTL_HPCFBIO_GOP;
+extern unsigned IOCTL_HPCFBIO_SOP;
+extern unsigned IOCTL_IOPIOCPT;
+extern unsigned IOCTL_IOPIOCGLCT;
+extern unsigned IOCTL_IOPIOCGSTATUS;
+extern unsigned IOCTL_IOPIOCRECONFIG;
+extern unsigned IOCTL_IOPIOCGTIDMAP;
+extern unsigned IOCTL_SIOCGATHSTATS;
+extern unsigned IOCTL_SIOCGATHDIAG;
+extern unsigned IOCTL_METEORCAPTUR;
+extern unsigned IOCTL_METEORCAPFRM;
+extern unsigned IOCTL_METEORSETGEO;
+extern unsigned IOCTL_METEORGETGEO;
+extern unsigned IOCTL_METEORSTATUS;
+extern unsigned IOCTL_METEORSHUE;
+extern unsigned IOCTL_METEORGHUE;
+extern unsigned IOCTL_METEORSFMT;
+extern unsigned IOCTL_METEORGFMT;
+extern unsigned IOCTL_METEORSINPUT;
+extern unsigned IOCTL_METEORGINPUT;
+extern unsigned IOCTL_METEORSCHCV;
+extern unsigned IOCTL_METEORGCHCV;
+extern unsigned IOCTL_METEORSCOUNT;
+extern unsigned IOCTL_METEORGCOUNT;
+extern unsigned IOCTL_METEORSFPS;
+extern unsigned IOCTL_METEORGFPS;
+extern unsigned IOCTL_METEORSSIGNAL;
+extern unsigned IOCTL_METEORGSIGNAL;
+extern unsigned IOCTL_METEORSVIDEO;
+extern unsigned IOCTL_METEORGVIDEO;
+extern unsigned IOCTL_METEORSBRIG;
+extern unsigned IOCTL_METEORGBRIG;
+extern unsigned IOCTL_METEORSCSAT;
+extern unsigned IOCTL_METEORGCSAT;
+extern unsigned IOCTL_METEORSCONT;
+extern unsigned IOCTL_METEORGCONT;
+extern unsigned IOCTL_METEORSHWS;
+extern unsigned IOCTL_METEORGHWS;
+extern unsigned IOCTL_METEORSVWS;
+extern unsigned IOCTL_METEORGVWS;
+extern unsigned IOCTL_METEORSTS;
+extern unsigned IOCTL_METEORGTS;
+extern unsigned IOCTL_TVTUNER_SETCHNL;
+extern unsigned IOCTL_TVTUNER_GETCHNL;
+extern unsigned IOCTL_TVTUNER_SETTYPE;
+extern unsigned IOCTL_TVTUNER_GETTYPE;
+extern unsigned IOCTL_TVTUNER_GETSTATUS;
+extern unsigned IOCTL_TVTUNER_SETFREQ;
+extern unsigned IOCTL_TVTUNER_GETFREQ;
+extern unsigned IOCTL_TVTUNER_SETAFC;
+extern unsigned IOCTL_TVTUNER_GETAFC;
+extern unsigned IOCTL_RADIO_SETMODE;
+extern unsigned IOCTL_RADIO_GETMODE;
+extern unsigned IOCTL_RADIO_SETFREQ;
+extern unsigned IOCTL_RADIO_GETFREQ;
+extern unsigned IOCTL_METEORSACTPIXFMT;
+extern unsigned IOCTL_METEORGACTPIXFMT;
+extern unsigned IOCTL_METEORGSUPPIXFMT;
+extern unsigned IOCTL_TVTUNER_GETCHNLSET;
+extern unsigned IOCTL_REMOTE_GETKEY;
+extern unsigned IOCTL_GDT_IOCTL_GENERAL;
+extern unsigned IOCTL_GDT_IOCTL_DRVERS;
+extern unsigned IOCTL_GDT_IOCTL_CTRTYPE;
+extern unsigned IOCTL_GDT_IOCTL_OSVERS;
+extern unsigned IOCTL_GDT_IOCTL_CTRCNT;
+extern unsigned IOCTL_GDT_IOCTL_EVENT;
+extern unsigned IOCTL_GDT_IOCTL_STATIST;
+extern unsigned IOCTL_GDT_IOCTL_RESCAN;
+extern unsigned IOCTL_ISP_SDBLEV;
+extern unsigned IOCTL_ISP_RESETHBA;
+extern unsigned IOCTL_ISP_RESCAN;
+extern unsigned IOCTL_ISP_SETROLE;
+extern unsigned IOCTL_ISP_GETROLE;
+extern unsigned IOCTL_ISP_GET_STATS;
+extern unsigned IOCTL_ISP_CLR_STATS;
+extern unsigned IOCTL_ISP_FC_LIP;
+extern unsigned IOCTL_ISP_FC_GETDINFO;
+extern unsigned IOCTL_ISP_GET_FW_CRASH_DUMP;
+extern unsigned IOCTL_ISP_FORCE_CRASH_DUMP;
+extern unsigned IOCTL_ISP_FC_GETHINFO;
+extern unsigned IOCTL_ISP_TSK_MGMT;
+extern unsigned IOCTL_ISP_FC_GETDLIST;
+extern unsigned IOCTL_MLXD_STATUS;
+extern unsigned IOCTL_MLXD_CHECKASYNC;
+extern unsigned IOCTL_MLXD_DETACH;
+extern unsigned IOCTL_MLX_RESCAN_DRIVES;
+extern unsigned IOCTL_MLX_PAUSE_CHANNEL;
+extern unsigned IOCTL_MLX_COMMAND;
+extern unsigned IOCTL_MLX_REBUILDASYNC;
+extern unsigned IOCTL_MLX_REBUILDSTAT;
+extern unsigned IOCTL_MLX_GET_SYSDRIVE;
+extern unsigned IOCTL_MLX_GET_CINFO;
+extern unsigned IOCTL_NVME_PASSTHROUGH_CMD;
+extern unsigned IOCTL_FWCFGIO_SET_INDEX;
+extern unsigned IOCTL_IRDA_RESET_PARAMS;
+extern unsigned IOCTL_IRDA_SET_PARAMS;
+extern unsigned IOCTL_IRDA_GET_SPEEDMASK;
+extern unsigned IOCTL_IRDA_GET_TURNAROUNDMASK;
+extern unsigned IOCTL_IRFRAMETTY_GET_DEVICE;
+extern unsigned IOCTL_IRFRAMETTY_GET_DONGLE;
+extern unsigned IOCTL_IRFRAMETTY_SET_DONGLE;
+extern unsigned IOCTL_ISV_CMD;
+extern unsigned IOCTL_WTQICMD;
+extern unsigned IOCTL_ISCSI_GET_VERSION;
+extern unsigned IOCTL_ISCSI_LOGIN;
+extern unsigned IOCTL_ISCSI_LOGOUT;
+extern unsigned IOCTL_ISCSI_ADD_CONNECTION;
+extern unsigned IOCTL_ISCSI_RESTORE_CONNECTION;
+extern unsigned IOCTL_ISCSI_REMOVE_CONNECTION;
+extern unsigned IOCTL_ISCSI_CONNECTION_STATUS;
+extern unsigned IOCTL_ISCSI_SEND_TARGETS;
+extern unsigned IOCTL_ISCSI_SET_NODE_NAME;
+extern unsigned IOCTL_ISCSI_IO_COMMAND;
+extern unsigned IOCTL_ISCSI_REGISTER_EVENT;
+extern unsigned IOCTL_ISCSI_DEREGISTER_EVENT;
+extern unsigned IOCTL_ISCSI_WAIT_EVENT;
+extern unsigned IOCTL_ISCSI_POLL_EVENT;
+extern unsigned IOCTL_OFIOCGET;
+extern unsigned IOCTL_OFIOCSET;
+extern unsigned IOCTL_OFIOCNEXTPROP;
+extern unsigned IOCTL_OFIOCGETOPTNODE;
+extern unsigned IOCTL_OFIOCGETNEXT;
+extern unsigned IOCTL_OFIOCGETCHILD;
+extern unsigned IOCTL_OFIOCFINDDEVICE;
+extern unsigned IOCTL_AMR_IO_VERSION;
+extern unsigned IOCTL_AMR_IO_COMMAND;
+extern unsigned IOCTL_MLYIO_COMMAND;
+extern unsigned IOCTL_MLYIO_HEALTH;
+extern unsigned IOCTL_PCI_IOC_CFGREAD;
+extern unsigned IOCTL_PCI_IOC_CFGWRITE;
+extern unsigned IOCTL_PCI_IOC_BDF_CFGREAD;
+extern unsigned IOCTL_PCI_IOC_BDF_CFGWRITE;
+extern unsigned IOCTL_PCI_IOC_BUSINFO;
+extern unsigned IOCTL_PCI_IOC_DRVNAME;
+extern unsigned IOCTL_PCI_IOC_DRVNAMEONBUS;
+extern unsigned IOCTL_TWEIO_COMMAND;
+extern unsigned IOCTL_TWEIO_STATS;
+extern unsigned IOCTL_TWEIO_AEN_POLL;
+extern unsigned IOCTL_TWEIO_AEN_WAIT;
+extern unsigned IOCTL_TWEIO_SET_PARAM;
+extern unsigned IOCTL_TWEIO_GET_PARAM;
+extern unsigned IOCTL_TWEIO_RESET;
+extern unsigned IOCTL_TWEIO_ADD_UNIT;
+extern unsigned IOCTL_TWEIO_DEL_UNIT;
+extern unsigned IOCTL_SIOCSCNWDOMAIN;
+extern unsigned IOCTL_SIOCGCNWDOMAIN;
+extern unsigned IOCTL_SIOCSCNWKEY;
+extern unsigned IOCTL_SIOCGCNWSTATUS;
+extern unsigned IOCTL_SIOCGCNWSTATS;
+extern unsigned IOCTL_SIOCGCNWTRAIL;
+extern unsigned IOCTL_SIOCGRAYSIGLEV;
+extern unsigned IOCTL_RAIDFRAME_SHUTDOWN;
+extern unsigned IOCTL_RAIDFRAME_TUR;
+extern unsigned IOCTL_RAIDFRAME_FAIL_DISK;
+extern unsigned IOCTL_RAIDFRAME_CHECK_RECON_STATUS;
+extern unsigned IOCTL_RAIDFRAME_REWRITEPARITY;
+extern unsigned IOCTL_RAIDFRAME_COPYBACK;
+extern unsigned IOCTL_RAIDFRAME_SPARET_WAIT;
+extern unsigned IOCTL_RAIDFRAME_SEND_SPARET;
+extern unsigned IOCTL_RAIDFRAME_ABORT_SPARET_WAIT;
+extern unsigned IOCTL_RAIDFRAME_START_ATRACE;
+extern unsigned IOCTL_RAIDFRAME_STOP_ATRACE;
+extern unsigned IOCTL_RAIDFRAME_GET_SIZE;
+extern unsigned IOCTL_RAIDFRAME_RESET_ACCTOTALS;
+extern unsigned IOCTL_RAIDFRAME_KEEP_ACCTOTALS;
+extern unsigned IOCTL_RAIDFRAME_GET_COMPONENT_LABEL;
+extern unsigned IOCTL_RAIDFRAME_SET_COMPONENT_LABEL;
+extern unsigned IOCTL_RAIDFRAME_INIT_LABELS;
+extern unsigned IOCTL_RAIDFRAME_ADD_HOT_SPARE;
+extern unsigned IOCTL_RAIDFRAME_REMOVE_HOT_SPARE;
+extern unsigned IOCTL_RAIDFRAME_REBUILD_IN_PLACE;
+extern unsigned IOCTL_RAIDFRAME_CHECK_PARITY;
+extern unsigned IOCTL_RAIDFRAME_CHECK_PARITYREWRITE_STATUS;
+extern unsigned IOCTL_RAIDFRAME_CHECK_COPYBACK_STATUS;
+extern unsigned IOCTL_RAIDFRAME_SET_AUTOCONFIG;
+extern unsigned IOCTL_RAIDFRAME_SET_ROOT;
+extern unsigned IOCTL_RAIDFRAME_DELETE_COMPONENT;
+extern unsigned IOCTL_RAIDFRAME_INCORPORATE_HOT_SPARE;
+extern unsigned IOCTL_RAIDFRAME_CHECK_RECON_STATUS_EXT;
+extern unsigned IOCTL_RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT;
+extern unsigned IOCTL_RAIDFRAME_CHECK_COPYBACK_STATUS_EXT;
+extern unsigned IOCTL_RAIDFRAME_CONFIGURE;
+extern unsigned IOCTL_RAIDFRAME_GET_INFO;
+extern unsigned IOCTL_RAIDFRAME_PARITYMAP_STATUS;
+extern unsigned IOCTL_RAIDFRAME_PARITYMAP_GET_DISABLE;
+extern unsigned IOCTL_RAIDFRAME_PARITYMAP_SET_DISABLE;
+extern unsigned IOCTL_RAIDFRAME_PARITYMAP_SET_PARAMS;
+extern unsigned IOCTL_RAIDFRAME_SET_LAST_UNIT;
+extern unsigned IOCTL_MBPPIOCSPARAM;
+extern unsigned IOCTL_MBPPIOCGPARAM;
+extern unsigned IOCTL_MBPPIOCGSTAT;
+extern unsigned IOCTL_SESIOC_GETNOBJ;
+extern unsigned IOCTL_SESIOC_GETOBJMAP;
+extern unsigned IOCTL_SESIOC_GETENCSTAT;
+extern unsigned IOCTL_SESIOC_SETENCSTAT;
+extern unsigned IOCTL_SESIOC_GETOBJSTAT;
+extern unsigned IOCTL_SESIOC_SETOBJSTAT;
+extern unsigned IOCTL_SESIOC_GETTEXT;
+extern unsigned IOCTL_SESIOC_INIT;
+extern unsigned IOCTL_SUN_DKIOCGGEOM;
+extern unsigned IOCTL_SUN_DKIOCINFO;
+extern unsigned IOCTL_SUN_DKIOCGPART;
+extern unsigned IOCTL_FBIOGTYPE;
+extern unsigned IOCTL_FBIOPUTCMAP;
+extern unsigned IOCTL_FBIOGETCMAP;
+extern unsigned IOCTL_FBIOGATTR;
+extern unsigned IOCTL_FBIOSVIDEO;
+extern unsigned IOCTL_FBIOGVIDEO;
+extern unsigned IOCTL_FBIOSCURSOR;
+extern unsigned IOCTL_FBIOGCURSOR;
+extern unsigned IOCTL_FBIOSCURPOS;
+extern unsigned IOCTL_FBIOGCURPOS;
+extern unsigned IOCTL_FBIOGCURMAX;
+extern unsigned IOCTL_KIOCTRANS;
+extern unsigned IOCTL_KIOCSETKEY;
+extern unsigned IOCTL_KIOCGETKEY;
+extern unsigned IOCTL_KIOCGTRANS;
+extern unsigned IOCTL_KIOCCMD;
+extern unsigned IOCTL_KIOCTYPE;
+extern unsigned IOCTL_KIOCSDIRECT;
+extern unsigned IOCTL_KIOCSKEY;
+extern unsigned IOCTL_KIOCGKEY;
+extern unsigned IOCTL_KIOCSLED;
+extern unsigned IOCTL_KIOCGLED;
+extern unsigned IOCTL_KIOCLAYOUT;
+extern unsigned IOCTL_VUIDSFORMAT;
+extern unsigned IOCTL_VUIDGFORMAT;
+extern unsigned IOCTL_STICIO_GXINFO;
+extern unsigned IOCTL_STICIO_RESET;
+extern unsigned IOCTL_STICIO_STARTQ;
+extern unsigned IOCTL_STICIO_STOPQ;
+extern unsigned IOCTL_UKYOPON_IDENTIFY;
+extern unsigned IOCTL_URIO_SEND_COMMAND;
+extern unsigned IOCTL_URIO_RECV_COMMAND;
+extern unsigned IOCTL_USB_REQUEST;
+extern unsigned IOCTL_USB_SETDEBUG;
+extern unsigned IOCTL_USB_DISCOVER;
+extern unsigned IOCTL_USB_DEVICEINFO;
+extern unsigned IOCTL_USB_DEVICEINFO_OLD;
+extern unsigned IOCTL_USB_DEVICESTATS;
+extern unsigned IOCTL_USB_GET_REPORT_DESC;
+extern unsigned IOCTL_USB_SET_IMMED;
+extern unsigned IOCTL_USB_GET_REPORT;
+extern unsigned IOCTL_USB_SET_REPORT;
+extern unsigned IOCTL_USB_GET_REPORT_ID;
+extern unsigned IOCTL_USB_GET_CONFIG;
+extern unsigned IOCTL_USB_SET_CONFIG;
+extern unsigned IOCTL_USB_GET_ALTINTERFACE;
+extern unsigned IOCTL_USB_SET_ALTINTERFACE;
+extern unsigned IOCTL_USB_GET_NO_ALT;
+extern unsigned IOCTL_USB_GET_DEVICE_DESC;
+extern unsigned IOCTL_USB_GET_CONFIG_DESC;
+extern unsigned IOCTL_USB_GET_INTERFACE_DESC;
+extern unsigned IOCTL_USB_GET_ENDPOINT_DESC;
+extern unsigned IOCTL_USB_GET_FULL_DESC;
+extern unsigned IOCTL_USB_GET_STRING_DESC;
+extern unsigned IOCTL_USB_DO_REQUEST;
+extern unsigned IOCTL_USB_GET_DEVICEINFO;
+extern unsigned IOCTL_USB_GET_DEVICEINFO_OLD;
+extern unsigned IOCTL_USB_SET_SHORT_XFER;
+extern unsigned IOCTL_USB_SET_TIMEOUT;
+extern unsigned IOCTL_USB_SET_BULK_RA;
+extern unsigned IOCTL_USB_SET_BULK_WB;
+extern unsigned IOCTL_USB_SET_BULK_RA_OPT;
+extern unsigned IOCTL_USB_SET_BULK_WB_OPT;
+extern unsigned IOCTL_USB_GET_CM_OVER_DATA;
+extern unsigned IOCTL_USB_SET_CM_OVER_DATA;
+extern unsigned IOCTL_UTOPPYIOTURBO;
+extern unsigned IOCTL_UTOPPYIOCANCEL;
+extern unsigned IOCTL_UTOPPYIOREBOOT;
+extern unsigned IOCTL_UTOPPYIOSTATS;
+extern unsigned IOCTL_UTOPPYIORENAME;
+extern unsigned IOCTL_UTOPPYIOMKDIR;
+extern unsigned IOCTL_UTOPPYIODELETE;
+extern unsigned IOCTL_UTOPPYIOREADDIR;
+extern unsigned IOCTL_UTOPPYIOREADFILE;
+extern unsigned IOCTL_UTOPPYIOWRITEFILE;
+extern unsigned IOCTL_DIOSXDCMD;
+extern unsigned IOCTL_VT_OPENQRY;
+extern unsigned IOCTL_VT_SETMODE;
+extern unsigned IOCTL_VT_GETMODE;
+extern unsigned IOCTL_VT_RELDISP;
+extern unsigned IOCTL_VT_ACTIVATE;
+extern unsigned IOCTL_VT_WAITACTIVE;
+extern unsigned IOCTL_VT_GETACTIVE;
+extern unsigned IOCTL_VT_GETSTATE;
+extern unsigned IOCTL_KDGETKBENT;
+extern unsigned IOCTL_KDGKBMODE;
+extern unsigned IOCTL_KDSKBMODE;
+extern unsigned IOCTL_KDMKTONE;
+extern unsigned IOCTL_KDSETMODE;
+extern unsigned IOCTL_KDENABIO;
+extern unsigned IOCTL_KDDISABIO;
+extern unsigned IOCTL_KDGKBTYPE;
+extern unsigned IOCTL_KDGETLED;
+extern unsigned IOCTL_KDSETLED;
+extern unsigned IOCTL_KDSETRAD;
+extern unsigned IOCTL_VGAPCVTID;
+extern unsigned IOCTL_CONS_GETVERS;
+extern unsigned IOCTL_WSKBDIO_GTYPE;
+extern unsigned IOCTL_WSKBDIO_BELL;
+extern unsigned IOCTL_WSKBDIO_COMPLEXBELL;
+extern unsigned IOCTL_WSKBDIO_SETBELL;
+extern unsigned IOCTL_WSKBDIO_GETBELL;
+extern unsigned IOCTL_WSKBDIO_SETDEFAULTBELL;
+extern unsigned IOCTL_WSKBDIO_GETDEFAULTBELL;
+extern unsigned IOCTL_WSKBDIO_SETKEYREPEAT;
+extern unsigned IOCTL_WSKBDIO_GETKEYREPEAT;
+extern unsigned IOCTL_WSKBDIO_SETDEFAULTKEYREPEAT;
+extern unsigned IOCTL_WSKBDIO_GETDEFAULTKEYREPEAT;
+extern unsigned IOCTL_WSKBDIO_SETLEDS;
+extern unsigned IOCTL_WSKBDIO_GETLEDS;
+extern unsigned IOCTL_WSKBDIO_GETMAP;
+extern unsigned IOCTL_WSKBDIO_SETMAP;
+extern unsigned IOCTL_WSKBDIO_GETENCODING;
+extern unsigned IOCTL_WSKBDIO_SETENCODING;
+extern unsigned IOCTL_WSKBDIO_SETMODE;
+extern unsigned IOCTL_WSKBDIO_GETMODE;
+extern unsigned IOCTL_WSKBDIO_SETKEYCLICK;
+extern unsigned IOCTL_WSKBDIO_GETKEYCLICK;
+extern unsigned IOCTL_WSKBDIO_GETSCROLL;
+extern unsigned IOCTL_WSKBDIO_SETSCROLL;
+extern unsigned IOCTL_WSKBDIO_SETVERSION;
+extern unsigned IOCTL_WSMOUSEIO_GTYPE;
+extern unsigned IOCTL_WSMOUSEIO_SRES;
+extern unsigned IOCTL_WSMOUSEIO_SSCALE;
+extern unsigned IOCTL_WSMOUSEIO_SRATE;
+extern unsigned IOCTL_WSMOUSEIO_SCALIBCOORDS;
+extern unsigned IOCTL_WSMOUSEIO_GCALIBCOORDS;
+extern unsigned IOCTL_WSMOUSEIO_GETID;
+extern unsigned IOCTL_WSMOUSEIO_GETREPEAT;
+extern unsigned IOCTL_WSMOUSEIO_SETREPEAT;
+extern unsigned IOCTL_WSMOUSEIO_SETVERSION;
+extern unsigned IOCTL_WSDISPLAYIO_GTYPE;
+extern unsigned IOCTL_WSDISPLAYIO_GINFO;
+extern unsigned IOCTL_WSDISPLAYIO_GETCMAP;
+extern unsigned IOCTL_WSDISPLAYIO_PUTCMAP;
+extern unsigned IOCTL_WSDISPLAYIO_GVIDEO;
+extern unsigned IOCTL_WSDISPLAYIO_SVIDEO;
+extern unsigned IOCTL_WSDISPLAYIO_GCURPOS;
+extern unsigned IOCTL_WSDISPLAYIO_SCURPOS;
+extern unsigned IOCTL_WSDISPLAYIO_GCURMAX;
+extern unsigned IOCTL_WSDISPLAYIO_GCURSOR;
+extern unsigned IOCTL_WSDISPLAYIO_SCURSOR;
+extern unsigned IOCTL_WSDISPLAYIO_GMODE;
+extern unsigned IOCTL_WSDISPLAYIO_SMODE;
+extern unsigned IOCTL_WSDISPLAYIO_LDFONT;
+extern unsigned IOCTL_WSDISPLAYIO_ADDSCREEN;
+extern unsigned IOCTL_WSDISPLAYIO_DELSCREEN;
+extern unsigned IOCTL_WSDISPLAYIO_SFONT;
+extern unsigned IOCTL__O_WSDISPLAYIO_SETKEYBOARD;
+extern unsigned IOCTL_WSDISPLAYIO_GETPARAM;
+extern unsigned IOCTL_WSDISPLAYIO_SETPARAM;
+extern unsigned IOCTL_WSDISPLAYIO_GETACTIVESCREEN;
+extern unsigned IOCTL_WSDISPLAYIO_GETWSCHAR;
+extern unsigned IOCTL_WSDISPLAYIO_PUTWSCHAR;
+extern unsigned IOCTL_WSDISPLAYIO_DGSCROLL;
+extern unsigned IOCTL_WSDISPLAYIO_DSSCROLL;
+extern unsigned IOCTL_WSDISPLAYIO_GMSGATTRS;
+extern unsigned IOCTL_WSDISPLAYIO_SMSGATTRS;
+extern unsigned IOCTL_WSDISPLAYIO_GBORDER;
+extern unsigned IOCTL_WSDISPLAYIO_SBORDER;
+extern unsigned IOCTL_WSDISPLAYIO_SSPLASH;
+extern unsigned IOCTL_WSDISPLAYIO_SPROGRESS;
+extern unsigned IOCTL_WSDISPLAYIO_LINEBYTES;
+extern unsigned IOCTL_WSDISPLAYIO_SETVERSION;
+extern unsigned IOCTL_WSMUXIO_ADD_DEVICE;
+extern unsigned IOCTL_WSMUXIO_REMOVE_DEVICE;
+extern unsigned IOCTL_WSMUXIO_LIST_DEVICES;
+extern unsigned IOCTL_WSMUXIO_INJECTEVENT;
+extern unsigned IOCTL_WSDISPLAYIO_GET_BUSID;
+extern unsigned IOCTL_WSDISPLAYIO_GET_EDID;
+extern unsigned IOCTL_WSDISPLAYIO_SET_POLLING;
+extern unsigned IOCTL_WSDISPLAYIO_GET_FBINFO;
+extern unsigned IOCTL_WSDISPLAYIO_DOBLIT;
+extern unsigned IOCTL_WSDISPLAYIO_WAITBLIT;
+extern unsigned IOCTL_BIOCLOCATE;
+extern unsigned IOCTL_BIOCINQ;
+extern unsigned IOCTL_BIOCDISK_NOVOL;
+extern unsigned IOCTL_BIOCDISK;
+extern unsigned IOCTL_BIOCVOL;
+extern unsigned IOCTL_BIOCALARM;
+extern unsigned IOCTL_BIOCBLINK;
+extern unsigned IOCTL_BIOCSETSTATE;
+extern unsigned IOCTL_BIOCVOLOPS;
+extern unsigned IOCTL_MD_GETCONF;
+extern unsigned IOCTL_MD_SETCONF;
+extern unsigned IOCTL_CCDIOCSET;
+extern unsigned IOCTL_CCDIOCCLR;
+extern unsigned IOCTL_CGDIOCSET;
+extern unsigned IOCTL_CGDIOCCLR;
+extern unsigned IOCTL_CGDIOCGET;
+extern unsigned IOCTL_FSSIOCSET;
+extern unsigned IOCTL_FSSIOCGET;
+extern unsigned IOCTL_FSSIOCCLR;
+extern unsigned IOCTL_FSSIOFSET;
+extern unsigned IOCTL_FSSIOFGET;
+extern unsigned IOCTL_BTDEV_ATTACH;
+extern unsigned IOCTL_BTDEV_DETACH;
+extern unsigned IOCTL_BTSCO_GETINFO;
+extern unsigned IOCTL_KTTCP_IO_SEND;
+extern unsigned IOCTL_KTTCP_IO_RECV;
+extern unsigned IOCTL_IOC_LOCKSTAT_GVERSION;
+extern unsigned IOCTL_IOC_LOCKSTAT_ENABLE;
+extern unsigned IOCTL_IOC_LOCKSTAT_DISABLE;
+extern unsigned IOCTL_VNDIOCSET;
+extern unsigned IOCTL_VNDIOCCLR;
+extern unsigned IOCTL_VNDIOCGET;
+extern unsigned IOCTL_SPKRTONE;
+extern unsigned IOCTL_SPKRTUNE;
+extern unsigned IOCTL_SPKRGETVOL;
+extern unsigned IOCTL_SPKRSETVOL;
+#if defined(__x86_64__)
+extern unsigned IOCTL_NVMM_IOC_CAPABILITY;
+extern unsigned IOCTL_NVMM_IOC_MACHINE_CREATE;
+extern unsigned IOCTL_NVMM_IOC_MACHINE_DESTROY;
+extern unsigned IOCTL_NVMM_IOC_MACHINE_CONFIGURE;
+extern unsigned IOCTL_NVMM_IOC_VCPU_CREATE;
+extern unsigned IOCTL_NVMM_IOC_VCPU_DESTROY;
+extern unsigned IOCTL_NVMM_IOC_VCPU_CONFIGURE;
+extern unsigned IOCTL_NVMM_IOC_VCPU_SETSTATE;
+extern unsigned IOCTL_NVMM_IOC_VCPU_GETSTATE;
+extern unsigned IOCTL_NVMM_IOC_VCPU_INJECT;
+extern unsigned IOCTL_NVMM_IOC_VCPU_RUN;
+extern unsigned IOCTL_NVMM_IOC_GPA_MAP;
+extern unsigned IOCTL_NVMM_IOC_GPA_UNMAP;
+extern unsigned IOCTL_NVMM_IOC_HVA_MAP;
+extern unsigned IOCTL_NVMM_IOC_HVA_UNMAP;
+extern unsigned IOCTL_NVMM_IOC_CTL;
+#endif
+extern unsigned IOCTL_AUTOFSREQUEST;
+extern unsigned IOCTL_AUTOFSDONE;
+extern unsigned IOCTL_BIOCGBLEN;
+extern unsigned IOCTL_BIOCSBLEN;
+extern unsigned IOCTL_BIOCSETF;
+extern unsigned IOCTL_BIOCFLUSH;
+extern unsigned IOCTL_BIOCPROMISC;
+extern unsigned IOCTL_BIOCGDLT;
+extern unsigned IOCTL_BIOCGETIF;
+extern unsigned IOCTL_BIOCSETIF;
+extern unsigned IOCTL_BIOCGSTATS;
+extern unsigned IOCTL_BIOCGSTATSOLD;
+extern unsigned IOCTL_BIOCIMMEDIATE;
+extern unsigned IOCTL_BIOCVERSION;
+extern unsigned IOCTL_BIOCSTCPF;
+extern unsigned IOCTL_BIOCSUDPF;
+extern unsigned IOCTL_BIOCGHDRCMPLT;
+extern unsigned IOCTL_BIOCSHDRCMPLT;
+extern unsigned IOCTL_BIOCSDLT;
+extern unsigned IOCTL_BIOCGDLTLIST;
+extern unsigned IOCTL_BIOCGDIRECTION;
+extern unsigned IOCTL_BIOCSDIRECTION;
+extern unsigned IOCTL_BIOCSRTIMEOUT;
+extern unsigned IOCTL_BIOCGRTIMEOUT;
+extern unsigned IOCTL_BIOCGFEEDBACK;
+extern unsigned IOCTL_BIOCSFEEDBACK;
+extern unsigned IOCTL_GRESADDRS;
+extern unsigned IOCTL_GRESADDRD;
+extern unsigned IOCTL_GREGADDRS;
+extern unsigned IOCTL_GREGADDRD;
+extern unsigned IOCTL_GRESPROTO;
+extern unsigned IOCTL_GREGPROTO;
+extern unsigned IOCTL_GRESSOCK;
+extern unsigned IOCTL_GREDSOCK;
+extern unsigned IOCTL_PPPIOCGRAWIN;
+extern unsigned IOCTL_PPPIOCGFLAGS;
+extern unsigned IOCTL_PPPIOCSFLAGS;
+extern unsigned IOCTL_PPPIOCGASYNCMAP;
+extern unsigned IOCTL_PPPIOCSASYNCMAP;
+extern unsigned IOCTL_PPPIOCGUNIT;
+extern unsigned IOCTL_PPPIOCGRASYNCMAP;
+extern unsigned IOCTL_PPPIOCSRASYNCMAP;
+extern unsigned IOCTL_PPPIOCGMRU;
+extern unsigned IOCTL_PPPIOCSMRU;
+extern unsigned IOCTL_PPPIOCSMAXCID;
+extern unsigned IOCTL_PPPIOCGXASYNCMAP;
+extern unsigned IOCTL_PPPIOCSXASYNCMAP;
+extern unsigned IOCTL_PPPIOCXFERUNIT;
+extern unsigned IOCTL_PPPIOCSCOMPRESS;
+extern unsigned IOCTL_PPPIOCGNPMODE;
+extern unsigned IOCTL_PPPIOCSNPMODE;
+extern unsigned IOCTL_PPPIOCGIDLE;
+extern unsigned IOCTL_PPPIOCGMTU;
+extern unsigned IOCTL_PPPIOCSMTU;
+extern unsigned IOCTL_SIOCGPPPSTATS;
+extern unsigned IOCTL_SIOCGPPPCSTATS;
+extern unsigned IOCTL_IOC_NPF_VERSION;
+extern unsigned IOCTL_IOC_NPF_SWITCH;
+extern unsigned IOCTL_IOC_NPF_LOAD;
+extern unsigned IOCTL_IOC_NPF_TABLE;
+extern unsigned IOCTL_IOC_NPF_STATS;
+extern unsigned IOCTL_IOC_NPF_SAVE;
+extern unsigned IOCTL_IOC_NPF_RULE;
+extern unsigned IOCTL_IOC_NPF_CONN_LOOKUP;
+extern unsigned IOCTL_IOC_NPF_TABLE_REPLACE;
+extern unsigned IOCTL_PPPOESETPARMS;
+extern unsigned IOCTL_PPPOEGETPARMS;
+extern unsigned IOCTL_PPPOEGETSESSION;
+extern unsigned IOCTL_SPPPGETAUTHCFG;
+extern unsigned IOCTL_SPPPSETAUTHCFG;
+extern unsigned IOCTL_SPPPGETLCPCFG;
+extern unsigned IOCTL_SPPPSETLCPCFG;
+extern unsigned IOCTL_SPPPGETSTATUS;
+extern unsigned IOCTL_SPPPGETSTATUSNCP;
+extern unsigned IOCTL_SPPPGETIDLETO;
+extern unsigned IOCTL_SPPPSETIDLETO;
+extern unsigned IOCTL_SPPPGETAUTHFAILURES;
+extern unsigned IOCTL_SPPPSETAUTHFAILURE;
+extern unsigned IOCTL_SPPPSETDNSOPTS;
+extern unsigned IOCTL_SPPPGETDNSOPTS;
+extern unsigned IOCTL_SPPPGETDNSADDRS;
+extern unsigned IOCTL_SPPPSETKEEPALIVE;
+extern unsigned IOCTL_SPPPGETKEEPALIVE;
+extern unsigned IOCTL_SRT_GETNRT;
+extern unsigned IOCTL_SRT_GETRT;
+extern unsigned IOCTL_SRT_SETRT;
+extern unsigned IOCTL_SRT_DELRT;
+extern unsigned IOCTL_SRT_SFLAGS;
+extern unsigned IOCTL_SRT_GFLAGS;
+extern unsigned IOCTL_SRT_SGFLAGS;
+extern unsigned IOCTL_SRT_DEBUG;
+extern unsigned IOCTL_TAPGIFNAME;
+extern unsigned IOCTL_TUNSDEBUG;
+extern unsigned IOCTL_TUNGDEBUG;
+extern unsigned IOCTL_TUNSIFMODE;
+extern unsigned IOCTL_TUNSLMODE;
+extern unsigned IOCTL_TUNSIFHEAD;
+extern unsigned IOCTL_TUNGIFHEAD;
+extern unsigned IOCTL_DIOCSTART;
+extern unsigned IOCTL_DIOCSTOP;
+extern unsigned IOCTL_DIOCADDRULE;
+extern unsigned IOCTL_DIOCGETRULES;
+extern unsigned IOCTL_DIOCGETRULE;
+extern unsigned IOCTL_DIOCSETLCK;
+extern unsigned IOCTL_DIOCCLRSTATES;
+extern unsigned IOCTL_DIOCGETSTATE;
+extern unsigned IOCTL_DIOCSETSTATUSIF;
+extern unsigned IOCTL_DIOCGETSTATUS;
+extern unsigned IOCTL_DIOCCLRSTATUS;
+extern unsigned IOCTL_DIOCNATLOOK;
+extern unsigned IOCTL_DIOCSETDEBUG;
+extern unsigned IOCTL_DIOCGETSTATES;
+extern unsigned IOCTL_DIOCCHANGERULE;
+extern unsigned IOCTL_DIOCSETTIMEOUT;
+extern unsigned IOCTL_DIOCGETTIMEOUT;
+extern unsigned IOCTL_DIOCADDSTATE;
+extern unsigned IOCTL_DIOCCLRRULECTRS;
+extern unsigned IOCTL_DIOCGETLIMIT;
+extern unsigned IOCTL_DIOCSETLIMIT;
+extern unsigned IOCTL_DIOCKILLSTATES;
+extern unsigned IOCTL_DIOCSTARTALTQ;
+extern unsigned IOCTL_DIOCSTOPALTQ;
+extern unsigned IOCTL_DIOCADDALTQ;
+extern unsigned IOCTL_DIOCGETALTQS;
+extern unsigned IOCTL_DIOCGETALTQ;
+extern unsigned IOCTL_DIOCCHANGEALTQ;
+extern unsigned IOCTL_DIOCGETQSTATS;
+extern unsigned IOCTL_DIOCBEGINADDRS;
+extern unsigned IOCTL_DIOCADDADDR;
+extern unsigned IOCTL_DIOCGETADDRS;
+extern unsigned IOCTL_DIOCGETADDR;
+extern unsigned IOCTL_DIOCCHANGEADDR;
+extern unsigned IOCTL_DIOCADDSTATES;
+extern unsigned IOCTL_DIOCGETRULESETS;
+extern unsigned IOCTL_DIOCGETRULESET;
+extern unsigned IOCTL_DIOCRCLRTABLES;
+extern unsigned IOCTL_DIOCRADDTABLES;
+extern unsigned IOCTL_DIOCRDELTABLES;
+extern unsigned IOCTL_DIOCRGETTABLES;
+extern unsigned IOCTL_DIOCRGETTSTATS;
+extern unsigned IOCTL_DIOCRCLRTSTATS;
+extern unsigned IOCTL_DIOCRCLRADDRS;
+extern unsigned IOCTL_DIOCRADDADDRS;
+extern unsigned IOCTL_DIOCRDELADDRS;
+extern unsigned IOCTL_DIOCRSETADDRS;
+extern unsigned IOCTL_DIOCRGETADDRS;
+extern unsigned IOCTL_DIOCRGETASTATS;
+extern unsigned IOCTL_DIOCRCLRASTATS;
+extern unsigned IOCTL_DIOCRTSTADDRS;
+extern unsigned IOCTL_DIOCRSETTFLAGS;
+extern unsigned IOCTL_DIOCRINADEFINE;
+extern unsigned IOCTL_DIOCOSFPFLUSH;
+extern unsigned IOCTL_DIOCOSFPADD;
+extern unsigned IOCTL_DIOCOSFPGET;
+extern unsigned IOCTL_DIOCXBEGIN;
+extern unsigned IOCTL_DIOCXCOMMIT;
+extern unsigned IOCTL_DIOCXROLLBACK;
+extern unsigned IOCTL_DIOCGETSRCNODES;
+extern unsigned IOCTL_DIOCCLRSRCNODES;
+extern unsigned IOCTL_DIOCSETHOSTID;
+extern unsigned IOCTL_DIOCIGETIFACES;
+extern unsigned IOCTL_DIOCSETIFFLAG;
+extern unsigned IOCTL_DIOCCLRIFFLAG;
+extern unsigned IOCTL_DIOCKILLSRCNODES;
+extern unsigned IOCTL_SLIOCGUNIT;
+extern unsigned IOCTL_SIOCGBTINFO;
+extern unsigned IOCTL_SIOCGBTINFOA;
+extern unsigned IOCTL_SIOCNBTINFO;
+extern unsigned IOCTL_SIOCSBTFLAGS;
+extern unsigned IOCTL_SIOCSBTPOLICY;
+extern unsigned IOCTL_SIOCSBTPTYPE;
+extern unsigned IOCTL_SIOCGBTSTATS;
+extern unsigned IOCTL_SIOCZBTSTATS;
+extern unsigned IOCTL_SIOCBTDUMP;
+extern unsigned IOCTL_SIOCSBTSCOMTU;
+extern unsigned IOCTL_SIOCGBTFEAT;
+extern unsigned IOCTL_SIOCADNAT;
+extern unsigned IOCTL_SIOCRMNAT;
+extern unsigned IOCTL_SIOCGNATS;
+extern unsigned IOCTL_SIOCGNATL;
+extern unsigned IOCTL_SIOCPURGENAT;
+extern unsigned IOCTL_SIOCCONNECTX;
+extern unsigned IOCTL_SIOCCONNECTXDEL;
+extern unsigned IOCTL_SIOCSIFINFO_FLAGS;
+extern unsigned IOCTL_SIOCAADDRCTL_POLICY;
+extern unsigned IOCTL_SIOCDADDRCTL_POLICY;
+extern unsigned IOCTL_SMBIOC_OPENSESSION;
+extern unsigned IOCTL_SMBIOC_OPENSHARE;
+extern unsigned IOCTL_SMBIOC_REQUEST;
+extern unsigned IOCTL_SMBIOC_SETFLAGS;
+extern unsigned IOCTL_SMBIOC_LOOKUP;
+extern unsigned IOCTL_SMBIOC_READ;
+extern unsigned IOCTL_SMBIOC_WRITE;
+extern unsigned IOCTL_AGPIOC_INFO;
+extern unsigned IOCTL_AGPIOC_ACQUIRE;
+extern unsigned IOCTL_AGPIOC_RELEASE;
+extern unsigned IOCTL_AGPIOC_SETUP;
+extern unsigned IOCTL_AGPIOC_ALLOCATE;
+extern unsigned IOCTL_AGPIOC_DEALLOCATE;
+extern unsigned IOCTL_AGPIOC_BIND;
+extern unsigned IOCTL_AGPIOC_UNBIND;
+extern unsigned IOCTL_AUDIO_GETINFO;
+extern unsigned IOCTL_AUDIO_SETINFO;
+extern unsigned IOCTL_AUDIO_DRAIN;
+extern unsigned IOCTL_AUDIO_FLUSH;
+extern unsigned IOCTL_AUDIO_WSEEK;
+extern unsigned IOCTL_AUDIO_RERROR;
+extern unsigned IOCTL_AUDIO_GETDEV;
+extern unsigned IOCTL_AUDIO_GETENC;
+extern unsigned IOCTL_AUDIO_GETFD;
+extern unsigned IOCTL_AUDIO_SETFD;
+extern unsigned IOCTL_AUDIO_PERROR;
+extern unsigned IOCTL_AUDIO_GETIOFFS;
+extern unsigned IOCTL_AUDIO_GETOOFFS;
+extern unsigned IOCTL_AUDIO_GETPROPS;
+extern unsigned IOCTL_AUDIO_GETBUFINFO;
+extern unsigned IOCTL_AUDIO_SETCHAN;
+extern unsigned IOCTL_AUDIO_GETCHAN;
+extern unsigned IOCTL_AUDIO_QUERYFORMAT;
+extern unsigned IOCTL_AUDIO_GETFORMAT;
+extern unsigned IOCTL_AUDIO_SETFORMAT;
+extern unsigned IOCTL_AUDIO_MIXER_READ;
+extern unsigned IOCTL_AUDIO_MIXER_WRITE;
+extern unsigned IOCTL_AUDIO_MIXER_DEVINFO;
+extern unsigned IOCTL_ATAIOCCOMMAND;
+extern unsigned IOCTL_ATABUSIOSCAN;
+extern unsigned IOCTL_ATABUSIORESET;
+extern unsigned IOCTL_ATABUSIODETACH;
+extern unsigned IOCTL_CDIOCPLAYTRACKS;
+extern unsigned IOCTL_CDIOCPLAYBLOCKS;
+extern unsigned IOCTL_CDIOCREADSUBCHANNEL;
+extern unsigned IOCTL_CDIOREADTOCHEADER;
+extern unsigned IOCTL_CDIOREADTOCENTRIES;
+extern unsigned IOCTL_CDIOREADMSADDR;
+extern unsigned IOCTL_CDIOCSETPATCH;
+extern unsigned IOCTL_CDIOCGETVOL;
+extern unsigned IOCTL_CDIOCSETVOL;
+extern unsigned IOCTL_CDIOCSETMONO;
+extern unsigned IOCTL_CDIOCSETSTEREO;
+extern unsigned IOCTL_CDIOCSETMUTE;
+extern unsigned IOCTL_CDIOCSETLEFT;
+extern unsigned IOCTL_CDIOCSETRIGHT;
+extern unsigned IOCTL_CDIOCSETDEBUG;
+extern unsigned IOCTL_CDIOCCLRDEBUG;
+extern unsigned IOCTL_CDIOCPAUSE;
+extern unsigned IOCTL_CDIOCRESUME;
+extern unsigned IOCTL_CDIOCRESET;
+extern unsigned IOCTL_CDIOCSTART;
+extern unsigned IOCTL_CDIOCSTOP;
+extern unsigned IOCTL_CDIOCEJECT;
+extern unsigned IOCTL_CDIOCALLOW;
+extern unsigned IOCTL_CDIOCPREVENT;
+extern unsigned IOCTL_CDIOCCLOSE;
+extern unsigned IOCTL_CDIOCPLAYMSF;
+extern unsigned IOCTL_CDIOCLOADUNLOAD;
+extern unsigned IOCTL_CHIOMOVE;
+extern unsigned IOCTL_CHIOEXCHANGE;
+extern unsigned IOCTL_CHIOPOSITION;
+extern unsigned IOCTL_CHIOGPICKER;
+extern unsigned IOCTL_CHIOSPICKER;
+extern unsigned IOCTL_CHIOGPARAMS;
+extern unsigned IOCTL_CHIOIELEM;
+extern unsigned IOCTL_OCHIOGSTATUS;
+extern unsigned IOCTL_CHIOGSTATUS;
+extern unsigned IOCTL_CHIOSVOLTAG;
+extern unsigned IOCTL_CLOCKCTL_SETTIMEOFDAY;
+extern unsigned IOCTL_CLOCKCTL_ADJTIME;
+extern unsigned IOCTL_CLOCKCTL_CLOCK_SETTIME;
+extern unsigned IOCTL_CLOCKCTL_NTP_ADJTIME;
+extern unsigned IOCTL_IOC_CPU_SETSTATE;
+extern unsigned IOCTL_IOC_CPU_GETSTATE;
+extern unsigned IOCTL_IOC_CPU_GETCOUNT;
+extern unsigned IOCTL_IOC_CPU_MAPID;
+extern unsigned IOCTL_IOC_CPU_UCODE_GET_VERSION;
+extern unsigned IOCTL_IOC_CPU_UCODE_APPLY;
+extern unsigned IOCTL_DIOCGDINFO;
+extern unsigned IOCTL_DIOCSDINFO;
+extern unsigned IOCTL_DIOCWDINFO;
+extern unsigned IOCTL_DIOCRFORMAT;
+extern unsigned IOCTL_DIOCWFORMAT;
+extern unsigned IOCTL_DIOCSSTEP;
+extern unsigned IOCTL_DIOCSRETRIES;
+extern unsigned IOCTL_DIOCKLABEL;
+extern unsigned IOCTL_DIOCWLABEL;
+extern unsigned IOCTL_DIOCSBAD;
+extern unsigned IOCTL_DIOCEJECT;
+extern unsigned IOCTL_ODIOCEJECT;
+extern unsigned IOCTL_DIOCLOCK;
+extern unsigned IOCTL_DIOCGDEFLABEL;
+extern unsigned IOCTL_DIOCCLRLABEL;
+extern unsigned IOCTL_DIOCGCACHE;
+extern unsigned IOCTL_DIOCSCACHE;
+extern unsigned IOCTL_DIOCCACHESYNC;
+extern unsigned IOCTL_DIOCBSLIST;
+extern unsigned IOCTL_DIOCBSFLUSH;
+extern unsigned IOCTL_DIOCAWEDGE;
+extern unsigned IOCTL_DIOCGWEDGEINFO;
+extern unsigned IOCTL_DIOCDWEDGE;
+extern unsigned IOCTL_DIOCLWEDGES;
+extern unsigned IOCTL_DIOCGSTRATEGY;
+extern unsigned IOCTL_DIOCSSTRATEGY;
+extern unsigned IOCTL_DIOCGDISKINFO;
+extern unsigned IOCTL_DIOCTUR;
+extern unsigned IOCTL_DIOCMWEDGES;
+extern unsigned IOCTL_DIOCGSECTORSIZE;
+extern unsigned IOCTL_DIOCGMEDIASIZE;
+extern unsigned IOCTL_DIOCRMWEDGES;
+extern unsigned IOCTL_DRVDETACHDEV;
+extern unsigned IOCTL_DRVRESCANBUS;
+extern unsigned IOCTL_DRVCTLCOMMAND;
+extern unsigned IOCTL_DRVRESUMEDEV;
+extern unsigned IOCTL_DRVLISTDEV;
+extern unsigned IOCTL_DRVGETEVENT;
+extern unsigned IOCTL_DRVSUSPENDDEV;
+extern unsigned IOCTL_DVD_READ_STRUCT;
+extern unsigned IOCTL_DVD_WRITE_STRUCT;
+extern unsigned IOCTL_DVD_AUTH;
+extern unsigned IOCTL_ENVSYS_GETDICTIONARY;
+extern unsigned IOCTL_ENVSYS_SETDICTIONARY;
+extern unsigned IOCTL_ENVSYS_REMOVEPROPS;
+extern unsigned IOCTL_ENVSYS_GTREDATA;
+extern unsigned IOCTL_ENVSYS_GTREINFO;
+extern unsigned IOCTL_KFILTER_BYFILTER;
+extern unsigned IOCTL_KFILTER_BYNAME;
+extern unsigned IOCTL_FDIOCGETOPTS;
+extern unsigned IOCTL_FDIOCSETOPTS;
+extern unsigned IOCTL_FDIOCSETFORMAT;
+extern unsigned IOCTL_FDIOCGETFORMAT;
+extern unsigned IOCTL_FDIOCFORMAT_TRACK;
+extern unsigned IOCTL_FIOCLEX;
+extern unsigned IOCTL_FIONCLEX;
+extern unsigned IOCTL_FIOSEEKDATA;
+extern unsigned IOCTL_FIOSEEKHOLE;
+extern unsigned IOCTL_FIONREAD;
+extern unsigned IOCTL_FIONBIO;
+extern unsigned IOCTL_FIOASYNC;
+extern unsigned IOCTL_FIOSETOWN;
+extern unsigned IOCTL_FIOGETOWN;
+extern unsigned IOCTL_OFIOGETBMAP;
+extern unsigned IOCTL_FIOGETBMAP;
+extern unsigned IOCTL_FIONWRITE;
+extern unsigned IOCTL_FIONSPACE;
+extern unsigned IOCTL_GPIOINFO;
+extern unsigned IOCTL_GPIOSET;
+extern unsigned IOCTL_GPIOUNSET;
+extern unsigned IOCTL_GPIOREAD;
+extern unsigned IOCTL_GPIOWRITE;
+extern unsigned IOCTL_GPIOTOGGLE;
+extern unsigned IOCTL_GPIOATTACH;
+extern unsigned IOCTL_PTIOCNETBSD;
+extern unsigned IOCTL_PTIOCSUNOS;
+extern unsigned IOCTL_PTIOCLINUX;
+extern unsigned IOCTL_PTIOCFREEBSD;
+extern unsigned IOCTL_PTIOCULTRIX;
+extern unsigned IOCTL_TIOCHPCL;
+extern unsigned IOCTL_TIOCGETP;
+extern unsigned IOCTL_TIOCSETP;
+extern unsigned IOCTL_TIOCSETN;
+extern unsigned IOCTL_TIOCSETC;
+extern unsigned IOCTL_TIOCGETC;
+extern unsigned IOCTL_TIOCLBIS;
+extern unsigned IOCTL_TIOCLBIC;
+extern unsigned IOCTL_TIOCLSET;
+extern unsigned IOCTL_TIOCLGET;
+extern unsigned IOCTL_TIOCSLTC;
+extern unsigned IOCTL_TIOCGLTC;
+extern unsigned IOCTL_OTIOCCONS;
+extern unsigned IOCTL_JOY_SETTIMEOUT;
+extern unsigned IOCTL_JOY_GETTIMEOUT;
+extern unsigned IOCTL_JOY_SET_X_OFFSET;
+extern unsigned IOCTL_JOY_SET_Y_OFFSET;
+extern unsigned IOCTL_JOY_GET_X_OFFSET;
+extern unsigned IOCTL_JOY_GET_Y_OFFSET;
+extern unsigned IOCTL_OKIOCGSYMBOL;
+extern unsigned IOCTL_OKIOCGVALUE;
+extern unsigned IOCTL_KIOCGSIZE;
+extern unsigned IOCTL_KIOCGVALUE;
+extern unsigned IOCTL_KIOCGSYMBOL;
+extern unsigned IOCTL_LUAINFO;
+extern unsigned IOCTL_LUACREATE;
+extern unsigned IOCTL_LUADESTROY;
+extern unsigned IOCTL_LUAREQUIRE;
+extern unsigned IOCTL_LUALOAD;
+extern unsigned IOCTL_MIDI_PRETIME;
+extern unsigned IOCTL_MIDI_MPUMODE;
+extern unsigned IOCTL_MIDI_MPUCMD;
+extern unsigned IOCTL_SEQUENCER_RESET;
+extern unsigned IOCTL_SEQUENCER_SYNC;
+extern unsigned IOCTL_SEQUENCER_INFO;
+extern unsigned IOCTL_SEQUENCER_CTRLRATE;
+extern unsigned IOCTL_SEQUENCER_GETOUTCOUNT;
+extern unsigned IOCTL_SEQUENCER_GETINCOUNT;
+extern unsigned IOCTL_SEQUENCER_RESETSAMPLES;
+extern unsigned IOCTL_SEQUENCER_NRSYNTHS;
+extern unsigned IOCTL_SEQUENCER_NRMIDIS;
+extern unsigned IOCTL_SEQUENCER_THRESHOLD;
+extern unsigned IOCTL_SEQUENCER_MEMAVL;
+extern unsigned IOCTL_SEQUENCER_PANIC;
+extern unsigned IOCTL_SEQUENCER_OUTOFBAND;
+extern unsigned IOCTL_SEQUENCER_GETTIME;
+extern unsigned IOCTL_SEQUENCER_TMR_TIMEBASE;
+extern unsigned IOCTL_SEQUENCER_TMR_START;
+extern unsigned IOCTL_SEQUENCER_TMR_STOP;
+extern unsigned IOCTL_SEQUENCER_TMR_CONTINUE;
+extern unsigned IOCTL_SEQUENCER_TMR_TEMPO;
+extern unsigned IOCTL_SEQUENCER_TMR_SOURCE;
+extern unsigned IOCTL_SEQUENCER_TMR_METRONOME;
+extern unsigned IOCTL_SEQUENCER_TMR_SELECT;
+extern unsigned IOCTL_SPI_IOCTL_CONFIGURE;
+extern unsigned IOCTL_SPI_IOCTL_TRANSFER;
+extern unsigned IOCTL_MTIOCTOP;
+extern unsigned IOCTL_MTIOCGET;
+extern unsigned IOCTL_MTIOCIEOT;
+extern unsigned IOCTL_MTIOCEEOT;
+extern unsigned IOCTL_MTIOCRDSPOS;
+extern unsigned IOCTL_MTIOCRDHPOS;
+extern unsigned IOCTL_MTIOCSLOCATE;
+extern unsigned IOCTL_MTIOCHLOCATE;
+extern unsigned IOCTL_POWER_EVENT_RECVDICT;
+extern unsigned IOCTL_POWER_IOC_GET_TYPE;
+extern unsigned IOCTL_RIOCGINFO;
+extern unsigned IOCTL_RIOCSINFO;
+extern unsigned IOCTL_RIOCSSRCH;
+extern unsigned IOCTL_RNDGETENTCNT;
+extern unsigned IOCTL_RNDGETSRCNUM;
+extern unsigned IOCTL_RNDGETSRCNAME;
+extern unsigned IOCTL_RNDCTL;
+extern unsigned IOCTL_RNDADDDATA;
+extern unsigned IOCTL_RNDGETPOOLSTAT;
+extern unsigned IOCTL_RNDGETESTNUM;
+extern unsigned IOCTL_RNDGETESTNAME;
+extern unsigned IOCTL_SCIOCGET;
+extern unsigned IOCTL_SCIOCSET;
+extern unsigned IOCTL_SCIOCRESTART;
+extern unsigned IOCTL_SCIOC_USE_ADF;
+extern unsigned IOCTL_SCIOCCOMMAND;
+extern unsigned IOCTL_SCIOCDEBUG;
+extern unsigned IOCTL_SCIOCIDENTIFY;
+extern unsigned IOCTL_OSCIOCIDENTIFY;
+extern unsigned IOCTL_SCIOCDECONFIG;
+extern unsigned IOCTL_SCIOCRECONFIG;
+extern unsigned IOCTL_SCIOCRESET;
+extern unsigned IOCTL_SCBUSIOSCAN;
+extern unsigned IOCTL_SCBUSIORESET;
+extern unsigned IOCTL_SCBUSIODETACH;
+extern unsigned IOCTL_SCBUSACCEL;
+extern unsigned IOCTL_SCBUSIOLLSCAN;
+extern unsigned IOCTL_SIOCSHIWAT;
+extern unsigned IOCTL_SIOCGHIWAT;
+extern unsigned IOCTL_SIOCSLOWAT;
+extern unsigned IOCTL_SIOCGLOWAT;
+extern unsigned IOCTL_SIOCATMARK;
+extern unsigned IOCTL_SIOCSPGRP;
+extern unsigned IOCTL_SIOCGPGRP;
+extern unsigned IOCTL_SIOCPEELOFF;
+extern unsigned IOCTL_SIOCADDRT;
+extern unsigned IOCTL_SIOCDELRT;
+extern unsigned IOCTL_SIOCSIFADDR;
+extern unsigned IOCTL_SIOCGIFADDR;
+extern unsigned IOCTL_SIOCSIFDSTADDR;
+extern unsigned IOCTL_SIOCGIFDSTADDR;
+extern unsigned IOCTL_SIOCSIFFLAGS;
+extern unsigned IOCTL_SIOCGIFFLAGS;
+extern unsigned IOCTL_SIOCGIFBRDADDR;
+extern unsigned IOCTL_SIOCSIFBRDADDR;
+extern unsigned IOCTL_SIOCGIFCONF;
+extern unsigned IOCTL_SIOCGIFNETMASK;
+extern unsigned IOCTL_SIOCSIFNETMASK;
+extern unsigned IOCTL_SIOCGIFMETRIC;
+extern unsigned IOCTL_SIOCSIFMETRIC;
+extern unsigned IOCTL_SIOCDIFADDR;
+extern unsigned IOCTL_SIOCAIFADDR;
+extern unsigned IOCTL_SIOCGIFALIAS;
+extern unsigned IOCTL_SIOCGIFAFLAG_IN;
+extern unsigned IOCTL_SIOCALIFADDR;
+extern unsigned IOCTL_SIOCGLIFADDR;
+extern unsigned IOCTL_SIOCDLIFADDR;
+extern unsigned IOCTL_SIOCSIFADDRPREF;
+extern unsigned IOCTL_SIOCGIFADDRPREF;
+extern unsigned IOCTL_SIOCADDMULTI;
+extern unsigned IOCTL_SIOCDELMULTI;
+extern unsigned IOCTL_SIOCGETVIFCNT;
+extern unsigned IOCTL_SIOCGETSGCNT;
+extern unsigned IOCTL_SIOCSIFMEDIA;
+extern unsigned IOCTL_SIOCGIFMEDIA;
+extern unsigned IOCTL_SIOCSIFGENERIC;
+extern unsigned IOCTL_SIOCGIFGENERIC;
+extern unsigned IOCTL_SIOCSIFPHYADDR;
+extern unsigned IOCTL_SIOCGIFPSRCADDR;
+extern unsigned IOCTL_SIOCGIFPDSTADDR;
+extern unsigned IOCTL_SIOCDIFPHYADDR;
+extern unsigned IOCTL_SIOCSLIFPHYADDR;
+extern unsigned IOCTL_SIOCGLIFPHYADDR;
+extern unsigned IOCTL_SIOCSIFMTU;
+extern unsigned IOCTL_SIOCGIFMTU;
+extern unsigned IOCTL_SIOCSDRVSPEC;
+extern unsigned IOCTL_SIOCGDRVSPEC;
+extern unsigned IOCTL_SIOCIFCREATE;
+extern unsigned IOCTL_SIOCIFDESTROY;
+extern unsigned IOCTL_SIOCIFGCLONERS;
+extern unsigned IOCTL_SIOCGIFDLT;
+extern unsigned IOCTL_SIOCGIFCAP;
+extern unsigned IOCTL_SIOCSIFCAP;
+extern unsigned IOCTL_SIOCSVH;
+extern unsigned IOCTL_SIOCGVH;
+extern unsigned IOCTL_SIOCINITIFADDR;
+extern unsigned IOCTL_SIOCGIFDATA;
+extern unsigned IOCTL_SIOCZIFDATA;
+extern unsigned IOCTL_SIOCGLINKSTR;
+extern unsigned IOCTL_SIOCSLINKSTR;
+extern unsigned IOCTL_SIOCGETHERCAP;
+extern unsigned IOCTL_SIOCGIFINDEX;
+extern unsigned IOCTL_SIOCSETHERCAP;
+extern unsigned IOCTL_SIOCSIFDESCR;
+extern unsigned IOCTL_SIOCGIFDESCR;
+extern unsigned IOCTL_SIOCGUMBINFO;
+extern unsigned IOCTL_SIOCSUMBPARAM;
+extern unsigned IOCTL_SIOCGUMBPARAM;
+extern unsigned IOCTL_SIOCSETPFSYNC;
+extern unsigned IOCTL_SIOCGETPFSYNC;
+extern unsigned IOCTL_PPS_IOC_CREATE;
+extern unsigned IOCTL_PPS_IOC_DESTROY;
+extern unsigned IOCTL_PPS_IOC_SETPARAMS;
+extern unsigned IOCTL_PPS_IOC_GETPARAMS;
+extern unsigned IOCTL_PPS_IOC_GETCAP;
+extern unsigned IOCTL_PPS_IOC_FETCH;
+extern unsigned IOCTL_PPS_IOC_KCBIND;
+extern unsigned IOCTL_TIOCEXCL;
+extern unsigned IOCTL_TIOCNXCL;
+extern unsigned IOCTL_TIOCFLUSH;
+extern unsigned IOCTL_TIOCGETA;
+extern unsigned IOCTL_TIOCSETA;
+extern unsigned IOCTL_TIOCSETAW;
+extern unsigned IOCTL_TIOCSETAF;
+extern unsigned IOCTL_TIOCGETD;
+extern unsigned IOCTL_TIOCSETD;
+extern unsigned IOCTL_TIOCGLINED;
+extern unsigned IOCTL_TIOCSLINED;
+extern unsigned IOCTL_TIOCSBRK;
+extern unsigned IOCTL_TIOCCBRK;
+extern unsigned IOCTL_TIOCSDTR;
+extern unsigned IOCTL_TIOCCDTR;
+extern unsigned IOCTL_TIOCGPGRP;
+extern unsigned IOCTL_TIOCSPGRP;
+extern unsigned IOCTL_TIOCOUTQ;
+extern unsigned IOCTL_TIOCSTI;
+extern unsigned IOCTL_TIOCNOTTY;
+extern unsigned IOCTL_TIOCPKT;
+extern unsigned IOCTL_TIOCSTOP;
+extern unsigned IOCTL_TIOCSTART;
+extern unsigned IOCTL_TIOCMSET;
+extern unsigned IOCTL_TIOCMBIS;
+extern unsigned IOCTL_TIOCMBIC;
+extern unsigned IOCTL_TIOCMGET;
+extern unsigned IOCTL_TIOCREMOTE;
+extern unsigned IOCTL_TIOCGWINSZ;
+extern unsigned IOCTL_TIOCSWINSZ;
+extern unsigned IOCTL_TIOCUCNTL;
+extern unsigned IOCTL_TIOCSTAT;
+extern unsigned IOCTL_TIOCGSID;
+extern unsigned IOCTL_TIOCCONS;
+extern unsigned IOCTL_TIOCSCTTY;
+extern unsigned IOCTL_TIOCEXT;
+extern unsigned IOCTL_TIOCSIG;
+extern unsigned IOCTL_TIOCDRAIN;
+extern unsigned IOCTL_TIOCGFLAGS;
+extern unsigned IOCTL_TIOCSFLAGS;
+extern unsigned IOCTL_TIOCDCDTIMESTAMP;
+extern unsigned IOCTL_TIOCRCVFRAME;
+extern unsigned IOCTL_TIOCXMTFRAME;
+extern unsigned IOCTL_TIOCPTMGET;
+extern unsigned IOCTL_TIOCGRANTPT;
+extern unsigned IOCTL_TIOCPTSNAME;
+extern unsigned IOCTL_TIOCSQSIZE;
+extern unsigned IOCTL_TIOCGQSIZE;
+extern unsigned IOCTL_VERIEXEC_LOAD;
+extern unsigned IOCTL_VERIEXEC_TABLESIZE;
+extern unsigned IOCTL_VERIEXEC_DELETE;
+extern unsigned IOCTL_VERIEXEC_QUERY;
+extern unsigned IOCTL_VERIEXEC_DUMP;
+extern unsigned IOCTL_VERIEXEC_FLUSH;
+extern unsigned IOCTL_VIDIOC_QUERYCAP;
+extern unsigned IOCTL_VIDIOC_RESERVED;
+extern unsigned IOCTL_VIDIOC_ENUM_FMT;
+extern unsigned IOCTL_VIDIOC_G_FMT;
+extern unsigned IOCTL_VIDIOC_S_FMT;
+extern unsigned IOCTL_VIDIOC_REQBUFS;
+extern unsigned IOCTL_VIDIOC_QUERYBUF;
+extern unsigned IOCTL_VIDIOC_G_FBUF;
+extern unsigned IOCTL_VIDIOC_S_FBUF;
+extern unsigned IOCTL_VIDIOC_OVERLAY;
+extern unsigned IOCTL_VIDIOC_QBUF;
+extern unsigned IOCTL_VIDIOC_DQBUF;
+extern unsigned IOCTL_VIDIOC_STREAMON;
+extern unsigned IOCTL_VIDIOC_STREAMOFF;
+extern unsigned IOCTL_VIDIOC_G_PARM;
+extern unsigned IOCTL_VIDIOC_S_PARM;
+extern unsigned IOCTL_VIDIOC_G_STD;
+extern unsigned IOCTL_VIDIOC_S_STD;
+extern unsigned IOCTL_VIDIOC_ENUMSTD;
+extern unsigned IOCTL_VIDIOC_ENUMINPUT;
+extern unsigned IOCTL_VIDIOC_G_CTRL;
+extern unsigned IOCTL_VIDIOC_S_CTRL;
+extern unsigned IOCTL_VIDIOC_G_TUNER;
+extern unsigned IOCTL_VIDIOC_S_TUNER;
+extern unsigned IOCTL_VIDIOC_G_AUDIO;
+extern unsigned IOCTL_VIDIOC_S_AUDIO;
+extern unsigned IOCTL_VIDIOC_QUERYCTRL;
+extern unsigned IOCTL_VIDIOC_QUERYMENU;
+extern unsigned IOCTL_VIDIOC_G_INPUT;
+extern unsigned IOCTL_VIDIOC_S_INPUT;
+extern unsigned IOCTL_VIDIOC_G_OUTPUT;
+extern unsigned IOCTL_VIDIOC_S_OUTPUT;
+extern unsigned IOCTL_VIDIOC_ENUMOUTPUT;
+extern unsigned IOCTL_VIDIOC_G_AUDOUT;
+extern unsigned IOCTL_VIDIOC_S_AUDOUT;
+extern unsigned IOCTL_VIDIOC_G_MODULATOR;
+extern unsigned IOCTL_VIDIOC_S_MODULATOR;
+extern unsigned IOCTL_VIDIOC_G_FREQUENCY;
+extern unsigned IOCTL_VIDIOC_S_FREQUENCY;
+extern unsigned IOCTL_VIDIOC_CROPCAP;
+extern unsigned IOCTL_VIDIOC_G_CROP;
+extern unsigned IOCTL_VIDIOC_S_CROP;
+extern unsigned IOCTL_VIDIOC_G_JPEGCOMP;
+extern unsigned IOCTL_VIDIOC_S_JPEGCOMP;
+extern unsigned IOCTL_VIDIOC_QUERYSTD;
+extern unsigned IOCTL_VIDIOC_TRY_FMT;
+extern unsigned IOCTL_VIDIOC_ENUMAUDIO;
+extern unsigned IOCTL_VIDIOC_ENUMAUDOUT;
+extern unsigned IOCTL_VIDIOC_G_PRIORITY;
+extern unsigned IOCTL_VIDIOC_S_PRIORITY;
+extern unsigned IOCTL_VIDIOC_ENUM_FRAMESIZES;
+extern unsigned IOCTL_VIDIOC_ENUM_FRAMEINTERVALS;
+extern unsigned IOCTL_WDOGIOC_GMODE;
+extern unsigned IOCTL_WDOGIOC_SMODE;
+extern unsigned IOCTL_WDOGIOC_WHICH;
+extern unsigned IOCTL_WDOGIOC_TICKLE;
+extern unsigned IOCTL_WDOGIOC_GTICKLER;
+extern unsigned IOCTL_WDOGIOC_GWDOGS;
+extern unsigned IOCTL_KCOV_IOC_SETBUFSIZE;
+extern unsigned IOCTL_KCOV_IOC_ENABLE;
+extern unsigned IOCTL_KCOV_IOC_DISABLE;
+extern unsigned IOCTL_IPMICTL_RECEIVE_MSG_TRUNC;
+extern unsigned IOCTL_IPMICTL_RECEIVE_MSG;
+extern unsigned IOCTL_IPMICTL_SEND_COMMAND;
+extern unsigned IOCTL_IPMICTL_REGISTER_FOR_CMD;
+extern unsigned IOCTL_IPMICTL_UNREGISTER_FOR_CMD;
+extern unsigned IOCTL_IPMICTL_SET_GETS_EVENTS_CMD;
+extern unsigned IOCTL_IPMICTL_SET_MY_ADDRESS_CMD;
+extern unsigned IOCTL_IPMICTL_GET_MY_ADDRESS_CMD;
+extern unsigned IOCTL_IPMICTL_SET_MY_LUN_CMD;
+extern unsigned IOCTL_IPMICTL_GET_MY_LUN_CMD;
+extern unsigned IOCTL_SNDCTL_DSP_RESET;
+extern unsigned IOCTL_SNDCTL_DSP_SYNC;
+extern unsigned IOCTL_SNDCTL_DSP_SPEED;
+extern unsigned IOCTL_SOUND_PCM_READ_RATE;
+extern unsigned IOCTL_SNDCTL_DSP_STEREO;
+extern unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE;
+extern unsigned IOCTL_SNDCTL_DSP_SETFMT;
+extern unsigned IOCTL_SOUND_PCM_READ_BITS;
+extern unsigned IOCTL_SNDCTL_DSP_CHANNELS;
+extern unsigned IOCTL_SOUND_PCM_READ_CHANNELS;
+extern unsigned IOCTL_SOUND_PCM_WRITE_FILTER;
+extern unsigned IOCTL_SOUND_PCM_READ_FILTER;
+extern unsigned IOCTL_SNDCTL_DSP_POST;
+extern unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE;
+extern unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT;
+extern unsigned IOCTL_SNDCTL_DSP_GETFMTS;
+extern unsigned IOCTL_SNDCTL_DSP_GETOSPACE;
+extern unsigned IOCTL_SNDCTL_DSP_GETISPACE;
+extern unsigned IOCTL_SNDCTL_DSP_NONBLOCK;
+extern unsigned IOCTL_SNDCTL_DSP_GETCAPS;
+extern unsigned IOCTL_SNDCTL_DSP_GETTRIGGER;
+extern unsigned IOCTL_SNDCTL_DSP_SETTRIGGER;
+extern unsigned IOCTL_SNDCTL_DSP_GETIPTR;
+extern unsigned IOCTL_SNDCTL_DSP_GETOPTR;
+extern unsigned IOCTL_SNDCTL_DSP_MAPINBUF;
+extern unsigned IOCTL_SNDCTL_DSP_MAPOUTBUF;
+extern unsigned IOCTL_SNDCTL_DSP_SETSYNCRO;
+extern unsigned IOCTL_SNDCTL_DSP_SETDUPLEX;
+extern unsigned IOCTL_SNDCTL_DSP_PROFILE;
+extern unsigned IOCTL_SNDCTL_DSP_GETODELAY;
+extern unsigned IOCTL_SOUND_MIXER_INFO;
+extern unsigned IOCTL_SOUND_OLD_MIXER_INFO;
+extern unsigned IOCTL_OSS_GETVERSION;
+extern unsigned IOCTL_SNDCTL_SYSINFO;
+extern unsigned IOCTL_SNDCTL_AUDIOINFO;
+extern unsigned IOCTL_SNDCTL_ENGINEINFO;
+extern unsigned IOCTL_SNDCTL_DSP_GETPLAYVOL;
+extern unsigned IOCTL_SNDCTL_DSP_SETPLAYVOL;
+extern unsigned IOCTL_SNDCTL_DSP_GETRECVOL;
+extern unsigned IOCTL_SNDCTL_DSP_SETRECVOL;
+extern unsigned IOCTL_SNDCTL_DSP_SKIP;
+extern unsigned IOCTL_SNDCTL_DSP_SILENCE;
+
+extern const int si_SEGV_MAPERR;
+extern const int si_SEGV_ACCERR;
+
+extern const unsigned SHA1_CTX_sz;
+extern const unsigned SHA1_return_length;
+
+extern const unsigned MD4_CTX_sz;
+extern const unsigned MD4_return_length;
+
+extern const unsigned RMD160_CTX_sz;
+extern const unsigned RMD160_return_length;
+
+extern const unsigned MD5_CTX_sz;
+extern const unsigned MD5_return_length;
+
+extern const unsigned fpos_t_sz;
+
+extern const unsigned MD2_CTX_sz;
+extern const unsigned MD2_return_length;
+
+#define SHA2_EXTERN(LEN) \
+ extern const unsigned SHA##LEN##_CTX_sz; \
+ extern const unsigned SHA##LEN##_return_length; \
+ extern const unsigned SHA##LEN##_block_length; \
+ extern const unsigned SHA##LEN##_digest_length
+
+SHA2_EXTERN(224);
+SHA2_EXTERN(256);
+SHA2_EXTERN(384);
+SHA2_EXTERN(512);
+
+#undef SHA2_EXTERN
+
+extern const int unvis_valid;
+extern const int unvis_validpush;
+
+struct __sanitizer_cdbr {
+ void (*unmap)(void *, void *, uptr);
+ void *cookie;
+ u8 *mmap_base;
+ uptr mmap_size;
+
+ u8 *hash_base;
+ u8 *offset_base;
+ u8 *data_base;
+
+ u32 data_size;
+ u32 entries;
+ u32 entries_index;
+ u32 seed;
+
+ u8 offset_size;
+ u8 index_size;
+
+ u32 entries_m;
+ u32 entries_index_m;
+ u8 entries_s1, entries_s2;
+ u8 entries_index_s1, entries_index_s2;
+};
+
+struct __sanitizer_cdbw {
+ uptr data_counter;
+ uptr data_allocated;
+ uptr data_size;
+ uptr *data_len;
+ void **data_ptr;
+ uptr hash_size;
+ void *hash;
+ uptr key_counter;
+};
+} // namespace __sanitizer
+
+#define CHECK_TYPE_SIZE(TYPE) \
+ COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
+
+#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \
+ COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \
+ sizeof(((CLASS *)NULL)->MEMBER)); \
+ COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
+ offsetof(CLASS, MEMBER))
+
+// For sigaction, which is a function and struct at the same time,
+// and thus requires explicit "struct" in sizeof() expression.
+#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
+ COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \
+ sizeof(((struct CLASS *)NULL)->MEMBER)); \
+ COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
+ offsetof(struct CLASS, MEMBER))
+
+#define SIGACTION_SYMNAME __sigaction14
+
+// Compat with 9.0
+extern unsigned struct_statvfs90_sz;
+
+#endif // SANITIZER_NETBSD
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_openbsd.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_openbsd.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_openbsd.h
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
new file mode 100644
index 00000000000..e7290e8cae4
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
@@ -0,0 +1,1345 @@
+//===-- sanitizer_platform_limits_posix.cpp -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer common code.
+//
+// Sizes and layouts of platform-specific POSIX data structures.
+//===----------------------------------------------------------------------===//
+
+#if defined(__linux__) || defined(__APPLE__)
+// Tests in this file assume that off_t-dependent data structures match the
+// libc ABI. For example, struct dirent here is what readdir() function (as
+// exported from libc) returns, and not the user-facing "dirent", which
+// depends on _FILE_OFFSET_BITS setting.
+// To get this "true" dirent definition, we undefine _FILE_OFFSET_BITS below.
+#undef _FILE_OFFSET_BITS
+#endif
+
+// Must go after undef _FILE_OFFSET_BITS.
+#include "sanitizer_platform.h"
+
+#if SANITIZER_LINUX || SANITIZER_APPLE
+// Must go after undef _FILE_OFFSET_BITS.
+#include "sanitizer_glibc_version.h"
+
+#include <arpa/inet.h>
+#include <dirent.h>
+#include <grp.h>
+#include <limits.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <poll.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <termios.h>
+#include <time.h>
+#include <wchar.h>
+#include <regex.h>
+#if !SANITIZER_APPLE
+#include <utmp.h>
+#endif
+
+#if !SANITIZER_IOS
+#include <net/route.h>
+#endif
+
+#if !SANITIZER_ANDROID
+#include <sys/mount.h>
+#include <sys/timeb.h>
+#include <utmpx.h>
+#endif
+
+#if SANITIZER_LINUX
+#include <malloc.h>
+#include <mntent.h>
+#include <netinet/ether.h>
+#include <sys/sysinfo.h>
+#include <sys/vt.h>
+#include <linux/cdrom.h>
+#include <linux/fd.h>
+#if SANITIZER_ANDROID
+#include <linux/fs.h>
+#endif
+#include <linux/hdreg.h>
+#include <linux/input.h>
+#include <linux/ioctl.h>
+#include <linux/soundcard.h>
+#include <linux/sysctl.h>
+#include <linux/utsname.h>
+#include <linux/posix_types.h>
+#include <net/if_arp.h>
+#endif
+
+#if SANITIZER_IOS
+#undef IOC_DIRMASK
+#endif
+
+#if SANITIZER_LINUX
+# include <utime.h>
+# include <sys/ptrace.h>
+# if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \
+ defined(__hexagon__) || defined(__loongarch__) ||SANITIZER_RISCV64
+# include <asm/ptrace.h>
+# ifdef __arm__
+typedef struct user_fpregs elf_fpregset_t;
+# define ARM_VFPREGS_SIZE_ASAN (32 * 8 /*fpregs*/ + 4 /*fpscr*/)
+# if !defined(ARM_VFPREGS_SIZE)
+# define ARM_VFPREGS_SIZE ARM_VFPREGS_SIZE_ASAN
+# endif
+# endif
+# endif
+# include <semaphore.h>
+#endif
+
+#if !SANITIZER_ANDROID
+#include <ifaddrs.h>
+#include <sys/ucontext.h>
+#include <wordexp.h>
+#endif
+
+#if SANITIZER_LINUX
+#if SANITIZER_GLIBC
+#include <fstab.h>
+#include <net/if_ppp.h>
+#include <netax25/ax25.h>
+#include <netipx/ipx.h>
+#include <netrom/netrom.h>
+#include <obstack.h>
+#if HAVE_RPC_XDR_H
+# error #include <rpc/xdr.h>
+#endif
+#include <scsi/scsi.h>
+#else
+#include <linux/if_ppp.h>
+#include <linux/kd.h>
+#include <linux/ppp_defs.h>
+#endif // SANITIZER_GLIBC
+
+#if SANITIZER_ANDROID
+#include <linux/mtio.h>
+#else
+#include <glob.h>
+#include <mqueue.h>
+#include <sys/kd.h>
+#include <sys/mtio.h>
+#include <sys/shm.h>
+#include <sys/statvfs.h>
+#include <sys/timex.h>
+#if defined(__mips64)
+# include <sys/procfs.h>
+#endif
+#include <sys/user.h>
+#include <linux/if_eql.h>
+#include <linux/if_plip.h>
+#include <linux/lp.h>
+#include <linux/mroute.h>
+#include <linux/mroute6.h>
+#include <linux/scc.h>
+#include <linux/serial.h>
+#include <sys/msg.h>
+#include <sys/ipc.h>
+#endif // SANITIZER_ANDROID
+
+#include <link.h>
+#include <sys/vfs.h>
+#include <sys/epoll.h>
+#include <linux/capability.h>
+#else
+#include <fstab.h>
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_APPLE
+#include <net/ethernet.h>
+#include <sys/filio.h>
+#include <sys/sockio.h>
+#endif
+
+// Include these after system headers to avoid name clashes and ambiguities.
+# include "sanitizer_common.h"
+# include "sanitizer_internal_defs.h"
+# include "sanitizer_platform_interceptors.h"
+# include "sanitizer_platform_limits_posix.h"
+
+#if SANITIZER_INTERCEPT_CRYPT_R
+#include <crypt.h>
+#endif
+
+namespace __sanitizer {
+ unsigned struct_utsname_sz = sizeof(struct utsname);
+ unsigned struct_stat_sz = sizeof(struct stat);
+#if SANITIZER_HAS_STAT64
+ unsigned struct_stat64_sz = sizeof(struct stat64);
+#endif // SANITIZER_HAS_STAT64
+ unsigned struct_rusage_sz = sizeof(struct rusage);
+ unsigned struct_tm_sz = sizeof(struct tm);
+ unsigned struct_passwd_sz = sizeof(struct passwd);
+ unsigned struct_group_sz = sizeof(struct group);
+ unsigned siginfo_t_sz = sizeof(siginfo_t);
+ unsigned struct_sigaction_sz = sizeof(struct sigaction);
+ unsigned struct_stack_t_sz = sizeof(stack_t);
+ unsigned struct_itimerval_sz = sizeof(struct itimerval);
+ unsigned pthread_t_sz = sizeof(pthread_t);
+ unsigned pthread_mutex_t_sz = sizeof(pthread_mutex_t);
+ unsigned pthread_cond_t_sz = sizeof(pthread_cond_t);
+ unsigned pid_t_sz = sizeof(pid_t);
+ unsigned timeval_sz = sizeof(timeval);
+ unsigned uid_t_sz = sizeof(uid_t);
+ unsigned gid_t_sz = sizeof(gid_t);
+ unsigned mbstate_t_sz = sizeof(mbstate_t);
+ unsigned sigset_t_sz = sizeof(sigset_t);
+ unsigned struct_timezone_sz = sizeof(struct timezone);
+ unsigned struct_tms_sz = sizeof(struct tms);
+ unsigned struct_sigevent_sz = sizeof(struct sigevent);
+ unsigned struct_sched_param_sz = sizeof(struct sched_param);
+ unsigned struct_regex_sz = sizeof(regex_t);
+ unsigned struct_regmatch_sz = sizeof(regmatch_t);
+
+#if SANITIZER_HAS_STATFS64
+ unsigned struct_statfs64_sz = sizeof(struct statfs64);
+#endif // SANITIZER_HAS_STATFS64
+
+#if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_APPLE
+ unsigned struct_fstab_sz = sizeof(struct fstab);
+#endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
+ // SANITIZER_APPLE
+#if !SANITIZER_ANDROID
+ unsigned struct_statfs_sz = sizeof(struct statfs);
+ unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
+
+ unsigned ucontext_t_sz(void *ctx) {
+# if SANITIZER_GLIBC && SANITIZER_X64
+ // Added in Linux kernel 3.4.0, merged to glibc in 2.16
+# ifndef FP_XSTATE_MAGIC1
+# define FP_XSTATE_MAGIC1 0x46505853U
+# endif
+ // See kernel arch/x86/kernel/fpu/signal.c for details.
+ const auto *fpregs = static_cast<ucontext_t *>(ctx)->uc_mcontext.fpregs;
+ // The member names differ across header versions, but the actual layout
+ // is always the same. So avoid using members, just use arithmetic.
+ const uint32_t *after_xmm =
+ reinterpret_cast<const uint32_t *>(fpregs + 1) - 24;
+ if (after_xmm[12] == FP_XSTATE_MAGIC1)
+ return reinterpret_cast<const char *>(fpregs) + after_xmm[13] -
+ static_cast<const char *>(ctx);
+# endif
+ return sizeof(ucontext_t);
+ }
+# endif // !SANITIZER_ANDROID
+
+# if SANITIZER_LINUX
+ unsigned struct_epoll_event_sz = sizeof(struct epoll_event);
+ unsigned struct_sysinfo_sz = sizeof(struct sysinfo);
+ unsigned __user_cap_header_struct_sz =
+ sizeof(struct __user_cap_header_struct);
+ unsigned __user_cap_data_struct_sz = sizeof(struct __user_cap_data_struct);
+ unsigned struct_new_utsname_sz = sizeof(struct new_utsname);
+ unsigned struct_old_utsname_sz = sizeof(struct old_utsname);
+ unsigned struct_oldold_utsname_sz = sizeof(struct oldold_utsname);
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX
+ unsigned struct_rlimit_sz = sizeof(struct rlimit);
+ unsigned struct_timespec_sz = sizeof(struct timespec);
+ unsigned struct_utimbuf_sz = sizeof(struct utimbuf);
+ unsigned struct_itimerspec_sz = sizeof(struct itimerspec);
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_GLIBC
+ // Use pre-computed size of struct ustat to avoid <sys/ustat.h> which
+ // has been removed from glibc 2.28.
+#if defined(__aarch64__) || defined(__s390x__) || defined(__mips64) || \
+ defined(__powerpc64__) || defined(__arch64__) || defined(__sparcv9) || \
+ defined(__x86_64__) || SANITIZER_RISCV64
+#define SIZEOF_STRUCT_USTAT 32
+# elif defined(__arm__) || defined(__i386__) || defined(__mips__) || \
+ defined(__powerpc__) || defined(__s390__) || defined(__sparc__) || \
+ defined(__hexagon__)
+# define SIZEOF_STRUCT_USTAT 20
+# elif defined(__loongarch__)
+ // Not used. The minimum Glibc version available for LoongArch is 2.36
+ // so ustat() wrapper is already gone.
+# define SIZEOF_STRUCT_USTAT 0
+# else
+# error Unknown size of struct ustat
+# endif
+ unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT;
+ unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
+ unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
+#endif // SANITIZER_GLIBC
+
+#if SANITIZER_INTERCEPT_CRYPT_R
+ unsigned struct_crypt_data_sz = sizeof(struct crypt_data);
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ unsigned struct_timex_sz = sizeof(struct timex);
+ unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds);
+ unsigned struct_mq_attr_sz = sizeof(struct mq_attr);
+ unsigned struct_statvfs_sz = sizeof(struct statvfs);
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+
+ const uptr sig_ign = (uptr)SIG_IGN;
+ const uptr sig_dfl = (uptr)SIG_DFL;
+ const uptr sig_err = (uptr)SIG_ERR;
+ const uptr sa_siginfo = (uptr)SA_SIGINFO;
+
+#if SANITIZER_LINUX
+ int e_tabsz = (int)E_TABSZ;
+#endif
+
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ unsigned struct_shminfo_sz = sizeof(struct shminfo);
+ unsigned struct_shm_info_sz = sizeof(struct shm_info);
+ int shmctl_ipc_stat = (int)IPC_STAT;
+ int shmctl_ipc_info = (int)IPC_INFO;
+ int shmctl_shm_info = (int)SHM_INFO;
+ int shmctl_shm_stat = (int)SHM_STAT;
+#endif
+
+#if !SANITIZER_APPLE && !SANITIZER_FREEBSD
+ unsigned struct_utmp_sz = sizeof(struct utmp);
+#endif
+#if !SANITIZER_ANDROID
+ unsigned struct_utmpx_sz = sizeof(struct utmpx);
+#endif
+
+ int map_fixed = MAP_FIXED;
+
+ int af_inet = (int)AF_INET;
+ int af_inet6 = (int)AF_INET6;
+
+ uptr __sanitizer_in_addr_sz(int af) {
+ if (af == AF_INET)
+ return sizeof(struct in_addr);
+ else if (af == AF_INET6)
+ return sizeof(struct in6_addr);
+ else
+ return 0;
+ }
+
+#if SANITIZER_LINUX
+unsigned struct_ElfW_Phdr_sz = sizeof(ElfW(Phdr));
+#elif SANITIZER_FREEBSD
+unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
+#endif
+
+#if SANITIZER_GLIBC
+ int glob_nomatch = GLOB_NOMATCH;
+ int glob_altdirfunc = GLOB_ALTDIRFUNC;
+#endif
+
+# if !SANITIZER_ANDROID
+ const int wordexp_wrde_dooffs = WRDE_DOOFFS;
+# endif // !SANITIZER_ANDROID
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
+ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
+ defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
+ defined(__s390__) || defined(__loongarch__)|| SANITIZER_RISCV64)
+#if defined(__mips64) || defined(__powerpc64__) || defined(__arm__)
+ unsigned struct_user_regs_struct_sz = sizeof(struct pt_regs);
+ unsigned struct_user_fpregs_struct_sz = sizeof(elf_fpregset_t);
+#elif SANITIZER_RISCV64
+ unsigned struct_user_regs_struct_sz = sizeof(struct user_regs_struct);
+ unsigned struct_user_fpregs_struct_sz = sizeof(struct __riscv_q_ext_state);
+#elif defined(__aarch64__)
+ unsigned struct_user_regs_struct_sz = sizeof(struct user_pt_regs);
+ unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpsimd_state);
+#elif defined(__loongarch__)
+ unsigned struct_user_regs_struct_sz = sizeof(struct user_pt_regs);
+ unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fp_state);
+#elif defined(__s390__)
+ unsigned struct_user_regs_struct_sz = sizeof(struct _user_regs_struct);
+ unsigned struct_user_fpregs_struct_sz = sizeof(struct _user_fpregs_struct);
+#else
+ unsigned struct_user_regs_struct_sz = sizeof(struct user_regs_struct);
+ unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpregs_struct);
+#endif // __mips64 || __powerpc64__ || __aarch64__ || __loongarch__
+#if defined(__x86_64) || defined(__mips64) || defined(__powerpc64__) || \
+ defined(__aarch64__) || defined(__arm__) || defined(__s390__) || \
+ defined(__loongarch__) || SANITIZER_RISCV64
+ unsigned struct_user_fpxregs_struct_sz = 0;
+#else
+ unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct);
+#endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ || __arm__
+// || __s390__ || __loongarch__
+#ifdef __arm__
+ unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE;
+#else
+ unsigned struct_user_vfpregs_struct_sz = 0;
+#endif
+
+ int ptrace_peektext = PTRACE_PEEKTEXT;
+ int ptrace_peekdata = PTRACE_PEEKDATA;
+ int ptrace_peekuser = PTRACE_PEEKUSER;
+#if (defined(PTRACE_GETREGS) && defined(PTRACE_SETREGS)) || \
+ (defined(PT_GETREGS) && defined(PT_SETREGS))
+ int ptrace_getregs = PTRACE_GETREGS;
+ int ptrace_setregs = PTRACE_SETREGS;
+#else
+ int ptrace_getregs = -1;
+ int ptrace_setregs = -1;
+#endif
+#if (defined(PTRACE_GETFPREGS) && defined(PTRACE_SETFPREGS)) || \
+ (defined(PT_GETFPREGS) && defined(PT_SETFPREGS))
+ int ptrace_getfpregs = PTRACE_GETFPREGS;
+ int ptrace_setfpregs = PTRACE_SETFPREGS;
+#else
+ int ptrace_getfpregs = -1;
+ int ptrace_setfpregs = -1;
+#endif
+#if (defined(PTRACE_GETFPXREGS) && defined(PTRACE_SETFPXREGS)) || \
+ (defined(PT_GETFPXREGS) && defined(PT_SETFPXREGS))
+ int ptrace_getfpxregs = PTRACE_GETFPXREGS;
+ int ptrace_setfpxregs = PTRACE_SETFPXREGS;
+#else
+ int ptrace_getfpxregs = -1;
+ int ptrace_setfpxregs = -1;
+#endif // PTRACE_GETFPXREGS/PTRACE_SETFPXREGS
+#if defined(PTRACE_GETVFPREGS) && defined(PTRACE_SETVFPREGS)
+ int ptrace_getvfpregs = PTRACE_GETVFPREGS;
+ int ptrace_setvfpregs = PTRACE_SETVFPREGS;
+#else
+ int ptrace_getvfpregs = -1;
+ int ptrace_setvfpregs = -1;
+#endif
+ int ptrace_geteventmsg = PTRACE_GETEVENTMSG;
+#if (defined(PTRACE_GETSIGINFO) && defined(PTRACE_SETSIGINFO)) || \
+ (defined(PT_GETSIGINFO) && defined(PT_SETSIGINFO))
+ int ptrace_getsiginfo = PTRACE_GETSIGINFO;
+ int ptrace_setsiginfo = PTRACE_SETSIGINFO;
+#else
+ int ptrace_getsiginfo = -1;
+ int ptrace_setsiginfo = -1;
+#endif // PTRACE_GETSIGINFO/PTRACE_SETSIGINFO
+#if defined(PTRACE_GETREGSET) && defined(PTRACE_SETREGSET)
+ int ptrace_getregset = PTRACE_GETREGSET;
+ int ptrace_setregset = PTRACE_SETREGSET;
+#else
+ int ptrace_getregset = -1;
+ int ptrace_setregset = -1;
+#endif // PTRACE_GETREGSET/PTRACE_SETREGSET
+#endif
+
+ unsigned path_max = PATH_MAX;
+
+ // ioctl arguments
+ unsigned struct_ifreq_sz = sizeof(struct ifreq);
+ unsigned struct_termios_sz = sizeof(struct termios);
+ unsigned struct_winsize_sz = sizeof(struct winsize);
+
+#if SANITIZER_LINUX
+ unsigned struct_arpreq_sz = sizeof(struct arpreq);
+ unsigned struct_cdrom_msf_sz = sizeof(struct cdrom_msf);
+ unsigned struct_cdrom_multisession_sz = sizeof(struct cdrom_multisession);
+ unsigned struct_cdrom_read_audio_sz = sizeof(struct cdrom_read_audio);
+ unsigned struct_cdrom_subchnl_sz = sizeof(struct cdrom_subchnl);
+ unsigned struct_cdrom_ti_sz = sizeof(struct cdrom_ti);
+ unsigned struct_cdrom_tocentry_sz = sizeof(struct cdrom_tocentry);
+ unsigned struct_cdrom_tochdr_sz = sizeof(struct cdrom_tochdr);
+ unsigned struct_cdrom_volctrl_sz = sizeof(struct cdrom_volctrl);
+ unsigned struct_ff_effect_sz = sizeof(struct ff_effect);
+ unsigned struct_floppy_drive_params_sz = sizeof(struct floppy_drive_params);
+ unsigned struct_floppy_drive_struct_sz = sizeof(struct floppy_drive_struct);
+ unsigned struct_floppy_fdc_state_sz = sizeof(struct floppy_fdc_state);
+ unsigned struct_floppy_max_errors_sz = sizeof(struct floppy_max_errors);
+ unsigned struct_floppy_raw_cmd_sz = sizeof(struct floppy_raw_cmd);
+ unsigned struct_floppy_struct_sz = sizeof(struct floppy_struct);
+ unsigned struct_floppy_write_errors_sz = sizeof(struct floppy_write_errors);
+ unsigned struct_format_descr_sz = sizeof(struct format_descr);
+ unsigned struct_hd_driveid_sz = sizeof(struct hd_driveid);
+ unsigned struct_hd_geometry_sz = sizeof(struct hd_geometry);
+ unsigned struct_input_absinfo_sz = sizeof(struct input_absinfo);
+ unsigned struct_input_id_sz = sizeof(struct input_id);
+ unsigned struct_mtpos_sz = sizeof(struct mtpos);
+ unsigned struct_rtentry_sz = sizeof(struct rtentry);
+#if SANITIZER_GLIBC || SANITIZER_ANDROID
+ unsigned struct_termio_sz = sizeof(struct termio);
+#endif
+ unsigned struct_vt_consize_sz = sizeof(struct vt_consize);
+ unsigned struct_vt_sizes_sz = sizeof(struct vt_sizes);
+ unsigned struct_vt_stat_sz = sizeof(struct vt_stat);
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX
+#if SOUND_VERSION >= 0x040000
+ unsigned struct_copr_buffer_sz = 0;
+ unsigned struct_copr_debug_buf_sz = 0;
+ unsigned struct_copr_msg_sz = 0;
+#else
+ unsigned struct_copr_buffer_sz = sizeof(struct copr_buffer);
+ unsigned struct_copr_debug_buf_sz = sizeof(struct copr_debug_buf);
+ unsigned struct_copr_msg_sz = sizeof(struct copr_msg);
+#endif
+ unsigned struct_midi_info_sz = sizeof(struct midi_info);
+ unsigned struct_mtget_sz = sizeof(struct mtget);
+ unsigned struct_mtop_sz = sizeof(struct mtop);
+ unsigned struct_sbi_instrument_sz = sizeof(struct sbi_instrument);
+ unsigned struct_seq_event_rec_sz = sizeof(struct seq_event_rec);
+ unsigned struct_synth_info_sz = sizeof(struct synth_info);
+ unsigned struct_vt_mode_sz = sizeof(struct vt_mode);
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_GLIBC
+ unsigned struct_ax25_parms_struct_sz = sizeof(struct ax25_parms_struct);
+#if EV_VERSION > (0x010000)
+ unsigned struct_input_keymap_entry_sz = sizeof(struct input_keymap_entry);
+#else
+ unsigned struct_input_keymap_entry_sz = 0;
+#endif
+ unsigned struct_ipx_config_data_sz = sizeof(struct ipx_config_data);
+ unsigned struct_kbdiacrs_sz = sizeof(struct kbdiacrs);
+ unsigned struct_kbentry_sz = sizeof(struct kbentry);
+ unsigned struct_kbkeycode_sz = sizeof(struct kbkeycode);
+ unsigned struct_kbsentry_sz = sizeof(struct kbsentry);
+ unsigned struct_mtconfiginfo_sz = sizeof(struct mtconfiginfo);
+ unsigned struct_nr_parms_struct_sz = sizeof(struct nr_parms_struct);
+ unsigned struct_scc_modem_sz = sizeof(struct scc_modem);
+ unsigned struct_scc_stat_sz = sizeof(struct scc_stat);
+ unsigned struct_serial_multiport_struct_sz
+ = sizeof(struct serial_multiport_struct);
+ unsigned struct_serial_struct_sz = sizeof(struct serial_struct);
+ unsigned struct_sockaddr_ax25_sz = sizeof(struct sockaddr_ax25);
+ unsigned struct_unimapdesc_sz = sizeof(struct unimapdesc);
+ unsigned struct_unimapinit_sz = sizeof(struct unimapinit);
+
+ unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);
+ unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
+#endif // SANITIZER_GLIBC
+
+#if !SANITIZER_ANDROID && !SANITIZER_APPLE
+ unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
+ unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
+#endif
+
+ const unsigned long __sanitizer_bufsiz = BUFSIZ;
+
+ const unsigned IOCTL_NOT_PRESENT = 0;
+
+ unsigned IOCTL_FIOASYNC = FIOASYNC;
+ unsigned IOCTL_FIOCLEX = FIOCLEX;
+ unsigned IOCTL_FIOGETOWN = FIOGETOWN;
+ unsigned IOCTL_FIONBIO = FIONBIO;
+ unsigned IOCTL_FIONCLEX = FIONCLEX;
+ unsigned IOCTL_FIOSETOWN = FIOSETOWN;
+ unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
+ unsigned IOCTL_SIOCATMARK = SIOCATMARK;
+ unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
+ unsigned IOCTL_SIOCGIFADDR = SIOCGIFADDR;
+ unsigned IOCTL_SIOCGIFBRDADDR = SIOCGIFBRDADDR;
+ unsigned IOCTL_SIOCGIFCONF = SIOCGIFCONF;
+ unsigned IOCTL_SIOCGIFDSTADDR = SIOCGIFDSTADDR;
+ unsigned IOCTL_SIOCGIFFLAGS = SIOCGIFFLAGS;
+ unsigned IOCTL_SIOCGIFMETRIC = SIOCGIFMETRIC;
+ unsigned IOCTL_SIOCGIFMTU = SIOCGIFMTU;
+ unsigned IOCTL_SIOCGIFNETMASK = SIOCGIFNETMASK;
+ unsigned IOCTL_SIOCGPGRP = SIOCGPGRP;
+ unsigned IOCTL_SIOCSIFADDR = SIOCSIFADDR;
+ unsigned IOCTL_SIOCSIFBRDADDR = SIOCSIFBRDADDR;
+ unsigned IOCTL_SIOCSIFDSTADDR = SIOCSIFDSTADDR;
+ unsigned IOCTL_SIOCSIFFLAGS = SIOCSIFFLAGS;
+ unsigned IOCTL_SIOCSIFMETRIC = SIOCSIFMETRIC;
+ unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
+ unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
+ unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
+ unsigned IOCTL_TIOCCONS = TIOCCONS;
+ unsigned IOCTL_TIOCEXCL = TIOCEXCL;
+ unsigned IOCTL_TIOCGETD = TIOCGETD;
+ unsigned IOCTL_TIOCGPGRP = TIOCGPGRP;
+ unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ;
+ unsigned IOCTL_TIOCMBIC = TIOCMBIC;
+ unsigned IOCTL_TIOCMBIS = TIOCMBIS;
+ unsigned IOCTL_TIOCMGET = TIOCMGET;
+ unsigned IOCTL_TIOCMSET = TIOCMSET;
+ unsigned IOCTL_TIOCNOTTY = TIOCNOTTY;
+ unsigned IOCTL_TIOCNXCL = TIOCNXCL;
+ unsigned IOCTL_TIOCOUTQ = TIOCOUTQ;
+ unsigned IOCTL_TIOCPKT = TIOCPKT;
+ unsigned IOCTL_TIOCSCTTY = TIOCSCTTY;
+ unsigned IOCTL_TIOCSETD = TIOCSETD;
+ unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
+ unsigned IOCTL_TIOCSTI = TIOCSTI;
+ unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT;
+ unsigned IOCTL_SIOCGETVIFCNT = SIOCGETVIFCNT;
+#endif
+
+#if SANITIZER_LINUX
+ unsigned IOCTL_EVIOCGABS = EVIOCGABS(0);
+ unsigned IOCTL_EVIOCGBIT = EVIOCGBIT(0, 0);
+ unsigned IOCTL_EVIOCGEFFECTS = EVIOCGEFFECTS;
+ unsigned IOCTL_EVIOCGID = EVIOCGID;
+ unsigned IOCTL_EVIOCGKEY = EVIOCGKEY(0);
+ unsigned IOCTL_EVIOCGKEYCODE = EVIOCGKEYCODE;
+ unsigned IOCTL_EVIOCGLED = EVIOCGLED(0);
+ unsigned IOCTL_EVIOCGNAME = EVIOCGNAME(0);
+ unsigned IOCTL_EVIOCGPHYS = EVIOCGPHYS(0);
+ unsigned IOCTL_EVIOCGRAB = EVIOCGRAB;
+ unsigned IOCTL_EVIOCGREP = EVIOCGREP;
+ unsigned IOCTL_EVIOCGSND = EVIOCGSND(0);
+ unsigned IOCTL_EVIOCGSW = EVIOCGSW(0);
+ unsigned IOCTL_EVIOCGUNIQ = EVIOCGUNIQ(0);
+ unsigned IOCTL_EVIOCGVERSION = EVIOCGVERSION;
+ unsigned IOCTL_EVIOCRMFF = EVIOCRMFF;
+ unsigned IOCTL_EVIOCSABS = EVIOCSABS(0);
+ unsigned IOCTL_EVIOCSFF = EVIOCSFF;
+ unsigned IOCTL_EVIOCSKEYCODE = EVIOCSKEYCODE;
+ unsigned IOCTL_EVIOCSREP = EVIOCSREP;
+ unsigned IOCTL_BLKFLSBUF = BLKFLSBUF;
+ unsigned IOCTL_BLKGETSIZE = BLKGETSIZE;
+ unsigned IOCTL_BLKRAGET = BLKRAGET;
+ unsigned IOCTL_BLKRASET = BLKRASET;
+ unsigned IOCTL_BLKROGET = BLKROGET;
+ unsigned IOCTL_BLKROSET = BLKROSET;
+ unsigned IOCTL_BLKRRPART = BLKRRPART;
+ unsigned IOCTL_BLKFRASET = BLKFRASET;
+ unsigned IOCTL_BLKFRAGET = BLKFRAGET;
+ unsigned IOCTL_BLKSECTSET = BLKSECTSET;
+ unsigned IOCTL_BLKSECTGET = BLKSECTGET;
+ unsigned IOCTL_BLKSSZGET = BLKSSZGET;
+ unsigned IOCTL_BLKBSZGET = BLKBSZGET;
+ unsigned IOCTL_BLKBSZSET = BLKBSZSET;
+ unsigned IOCTL_BLKGETSIZE64 = BLKGETSIZE64;
+ unsigned IOCTL_CDROMAUDIOBUFSIZ = CDROMAUDIOBUFSIZ;
+ unsigned IOCTL_CDROMEJECT = CDROMEJECT;
+ unsigned IOCTL_CDROMEJECT_SW = CDROMEJECT_SW;
+ unsigned IOCTL_CDROMMULTISESSION = CDROMMULTISESSION;
+ unsigned IOCTL_CDROMPAUSE = CDROMPAUSE;
+ unsigned IOCTL_CDROMPLAYMSF = CDROMPLAYMSF;
+ unsigned IOCTL_CDROMPLAYTRKIND = CDROMPLAYTRKIND;
+ unsigned IOCTL_CDROMREADAUDIO = CDROMREADAUDIO;
+ unsigned IOCTL_CDROMREADCOOKED = CDROMREADCOOKED;
+ unsigned IOCTL_CDROMREADMODE1 = CDROMREADMODE1;
+ unsigned IOCTL_CDROMREADMODE2 = CDROMREADMODE2;
+ unsigned IOCTL_CDROMREADRAW = CDROMREADRAW;
+ unsigned IOCTL_CDROMREADTOCENTRY = CDROMREADTOCENTRY;
+ unsigned IOCTL_CDROMREADTOCHDR = CDROMREADTOCHDR;
+ unsigned IOCTL_CDROMRESET = CDROMRESET;
+ unsigned IOCTL_CDROMRESUME = CDROMRESUME;
+ unsigned IOCTL_CDROMSEEK = CDROMSEEK;
+ unsigned IOCTL_CDROMSTART = CDROMSTART;
+ unsigned IOCTL_CDROMSTOP = CDROMSTOP;
+ unsigned IOCTL_CDROMSUBCHNL = CDROMSUBCHNL;
+ unsigned IOCTL_CDROMVOLCTRL = CDROMVOLCTRL;
+ unsigned IOCTL_CDROMVOLREAD = CDROMVOLREAD;
+ unsigned IOCTL_CDROM_GET_UPC = CDROM_GET_UPC;
+ unsigned IOCTL_FDCLRPRM = FDCLRPRM;
+ unsigned IOCTL_FDDEFPRM = FDDEFPRM;
+ unsigned IOCTL_FDFLUSH = FDFLUSH;
+ unsigned IOCTL_FDFMTBEG = FDFMTBEG;
+ unsigned IOCTL_FDFMTEND = FDFMTEND;
+ unsigned IOCTL_FDFMTTRK = FDFMTTRK;
+ unsigned IOCTL_FDGETDRVPRM = FDGETDRVPRM;
+ unsigned IOCTL_FDGETDRVSTAT = FDGETDRVSTAT;
+ unsigned IOCTL_FDGETDRVTYP = FDGETDRVTYP;
+ unsigned IOCTL_FDGETFDCSTAT = FDGETFDCSTAT;
+ unsigned IOCTL_FDGETMAXERRS = FDGETMAXERRS;
+ unsigned IOCTL_FDGETPRM = FDGETPRM;
+ unsigned IOCTL_FDMSGOFF = FDMSGOFF;
+ unsigned IOCTL_FDMSGON = FDMSGON;
+ unsigned IOCTL_FDPOLLDRVSTAT = FDPOLLDRVSTAT;
+ unsigned IOCTL_FDRAWCMD = FDRAWCMD;
+ unsigned IOCTL_FDRESET = FDRESET;
+ unsigned IOCTL_FDSETDRVPRM = FDSETDRVPRM;
+ unsigned IOCTL_FDSETEMSGTRESH = FDSETEMSGTRESH;
+ unsigned IOCTL_FDSETMAXERRS = FDSETMAXERRS;
+ unsigned IOCTL_FDSETPRM = FDSETPRM;
+ unsigned IOCTL_FDTWADDLE = FDTWADDLE;
+ unsigned IOCTL_FDWERRORCLR = FDWERRORCLR;
+ unsigned IOCTL_FDWERRORGET = FDWERRORGET;
+ unsigned IOCTL_HDIO_DRIVE_CMD = HDIO_DRIVE_CMD;
+ unsigned IOCTL_HDIO_GETGEO = HDIO_GETGEO;
+ unsigned IOCTL_HDIO_GET_32BIT = HDIO_GET_32BIT;
+ unsigned IOCTL_HDIO_GET_DMA = HDIO_GET_DMA;
+ unsigned IOCTL_HDIO_GET_IDENTITY = HDIO_GET_IDENTITY;
+ unsigned IOCTL_HDIO_GET_KEEPSETTINGS = HDIO_GET_KEEPSETTINGS;
+ unsigned IOCTL_HDIO_GET_MULTCOUNT = HDIO_GET_MULTCOUNT;
+ unsigned IOCTL_HDIO_GET_NOWERR = HDIO_GET_NOWERR;
+ unsigned IOCTL_HDIO_GET_UNMASKINTR = HDIO_GET_UNMASKINTR;
+ unsigned IOCTL_HDIO_SET_32BIT = HDIO_SET_32BIT;
+ unsigned IOCTL_HDIO_SET_DMA = HDIO_SET_DMA;
+ unsigned IOCTL_HDIO_SET_KEEPSETTINGS = HDIO_SET_KEEPSETTINGS;
+ unsigned IOCTL_HDIO_SET_MULTCOUNT = HDIO_SET_MULTCOUNT;
+ unsigned IOCTL_HDIO_SET_NOWERR = HDIO_SET_NOWERR;
+ unsigned IOCTL_HDIO_SET_UNMASKINTR = HDIO_SET_UNMASKINTR;
+ unsigned IOCTL_MTIOCPOS = MTIOCPOS;
+ unsigned IOCTL_PPPIOCGASYNCMAP = PPPIOCGASYNCMAP;
+ unsigned IOCTL_PPPIOCGDEBUG = PPPIOCGDEBUG;
+ unsigned IOCTL_PPPIOCGFLAGS = PPPIOCGFLAGS;
+ unsigned IOCTL_PPPIOCGUNIT = PPPIOCGUNIT;
+ unsigned IOCTL_PPPIOCGXASYNCMAP = PPPIOCGXASYNCMAP;
+ unsigned IOCTL_PPPIOCSASYNCMAP = PPPIOCSASYNCMAP;
+ unsigned IOCTL_PPPIOCSDEBUG = PPPIOCSDEBUG;
+ unsigned IOCTL_PPPIOCSFLAGS = PPPIOCSFLAGS;
+ unsigned IOCTL_PPPIOCSMAXCID = PPPIOCSMAXCID;
+ unsigned IOCTL_PPPIOCSMRU = PPPIOCSMRU;
+ unsigned IOCTL_PPPIOCSXASYNCMAP = PPPIOCSXASYNCMAP;
+ unsigned IOCTL_SIOCADDRT = SIOCADDRT;
+ unsigned IOCTL_SIOCDARP = SIOCDARP;
+ unsigned IOCTL_SIOCDELRT = SIOCDELRT;
+ unsigned IOCTL_SIOCDRARP = SIOCDRARP;
+ unsigned IOCTL_SIOCGARP = SIOCGARP;
+ unsigned IOCTL_SIOCGIFENCAP = SIOCGIFENCAP;
+ unsigned IOCTL_SIOCGIFHWADDR = SIOCGIFHWADDR;
+ unsigned IOCTL_SIOCGIFMAP = SIOCGIFMAP;
+ unsigned IOCTL_SIOCGIFMEM = SIOCGIFMEM;
+ unsigned IOCTL_SIOCGIFNAME = SIOCGIFNAME;
+ unsigned IOCTL_SIOCGIFSLAVE = SIOCGIFSLAVE;
+ unsigned IOCTL_SIOCGRARP = SIOCGRARP;
+ unsigned IOCTL_SIOCGSTAMP = SIOCGSTAMP;
+ unsigned IOCTL_SIOCSARP = SIOCSARP;
+ unsigned IOCTL_SIOCSIFENCAP = SIOCSIFENCAP;
+ unsigned IOCTL_SIOCSIFHWADDR = SIOCSIFHWADDR;
+ unsigned IOCTL_SIOCSIFLINK = SIOCSIFLINK;
+ unsigned IOCTL_SIOCSIFMAP = SIOCSIFMAP;
+ unsigned IOCTL_SIOCSIFMEM = SIOCSIFMEM;
+ unsigned IOCTL_SIOCSIFSLAVE = SIOCSIFSLAVE;
+ unsigned IOCTL_SIOCSRARP = SIOCSRARP;
+# if SOUND_VERSION >= 0x040000
+ unsigned IOCTL_SNDCTL_COPR_HALT = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_LOAD = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_RCODE = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_RCVMSG = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_RDATA = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_RESET = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_RUN = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_SENDMSG = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_WCODE = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_WDATA = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SOUND_PCM_READ_BITS = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SOUND_PCM_READ_CHANNELS = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SOUND_PCM_READ_FILTER = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SOUND_PCM_READ_RATE = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SOUND_PCM_WRITE_FILTER = IOCTL_NOT_PRESENT;
+# else // SOUND_VERSION
+ unsigned IOCTL_SNDCTL_COPR_HALT = SNDCTL_COPR_HALT;
+ unsigned IOCTL_SNDCTL_COPR_LOAD = SNDCTL_COPR_LOAD;
+ unsigned IOCTL_SNDCTL_COPR_RCODE = SNDCTL_COPR_RCODE;
+ unsigned IOCTL_SNDCTL_COPR_RCVMSG = SNDCTL_COPR_RCVMSG;
+ unsigned IOCTL_SNDCTL_COPR_RDATA = SNDCTL_COPR_RDATA;
+ unsigned IOCTL_SNDCTL_COPR_RESET = SNDCTL_COPR_RESET;
+ unsigned IOCTL_SNDCTL_COPR_RUN = SNDCTL_COPR_RUN;
+ unsigned IOCTL_SNDCTL_COPR_SENDMSG = SNDCTL_COPR_SENDMSG;
+ unsigned IOCTL_SNDCTL_COPR_WCODE = SNDCTL_COPR_WCODE;
+ unsigned IOCTL_SNDCTL_COPR_WDATA = SNDCTL_COPR_WDATA;
+ unsigned IOCTL_SOUND_PCM_READ_BITS = SOUND_PCM_READ_BITS;
+ unsigned IOCTL_SOUND_PCM_READ_CHANNELS = SOUND_PCM_READ_CHANNELS;
+ unsigned IOCTL_SOUND_PCM_READ_FILTER = SOUND_PCM_READ_FILTER;
+ unsigned IOCTL_SOUND_PCM_READ_RATE = SOUND_PCM_READ_RATE;
+ unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS = SOUND_PCM_WRITE_CHANNELS;
+ unsigned IOCTL_SOUND_PCM_WRITE_FILTER = SOUND_PCM_WRITE_FILTER;
+#endif // SOUND_VERSION
+ unsigned IOCTL_TCFLSH = TCFLSH;
+ unsigned IOCTL_TCGETA = TCGETA;
+ unsigned IOCTL_TCGETS = TCGETS;
+ unsigned IOCTL_TCSBRK = TCSBRK;
+ unsigned IOCTL_TCSBRKP = TCSBRKP;
+ unsigned IOCTL_TCSETA = TCSETA;
+ unsigned IOCTL_TCSETAF = TCSETAF;
+ unsigned IOCTL_TCSETAW = TCSETAW;
+ unsigned IOCTL_TCSETS = TCSETS;
+ unsigned IOCTL_TCSETSF = TCSETSF;
+ unsigned IOCTL_TCSETSW = TCSETSW;
+ unsigned IOCTL_TCXONC = TCXONC;
+ unsigned IOCTL_TIOCGLCKTRMIOS = TIOCGLCKTRMIOS;
+ unsigned IOCTL_TIOCGSOFTCAR = TIOCGSOFTCAR;
+ unsigned IOCTL_TIOCINQ = TIOCINQ;
+ unsigned IOCTL_TIOCLINUX = TIOCLINUX;
+ unsigned IOCTL_TIOCSERCONFIG = TIOCSERCONFIG;
+ unsigned IOCTL_TIOCSERGETLSR = TIOCSERGETLSR;
+ unsigned IOCTL_TIOCSERGWILD = TIOCSERGWILD;
+ unsigned IOCTL_TIOCSERSWILD = TIOCSERSWILD;
+ unsigned IOCTL_TIOCSLCKTRMIOS = TIOCSLCKTRMIOS;
+ unsigned IOCTL_TIOCSSOFTCAR = TIOCSSOFTCAR;
+ unsigned IOCTL_VT_DISALLOCATE = VT_DISALLOCATE;
+ unsigned IOCTL_VT_GETSTATE = VT_GETSTATE;
+ unsigned IOCTL_VT_RESIZE = VT_RESIZE;
+ unsigned IOCTL_VT_RESIZEX = VT_RESIZEX;
+ unsigned IOCTL_VT_SENDSIG = VT_SENDSIG;
+ unsigned IOCTL_MTIOCGET = MTIOCGET;
+ unsigned IOCTL_MTIOCTOP = MTIOCTOP;
+ unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE = SNDCTL_DSP_GETBLKSIZE;
+ unsigned IOCTL_SNDCTL_DSP_GETFMTS = SNDCTL_DSP_GETFMTS;
+ unsigned IOCTL_SNDCTL_DSP_NONBLOCK = SNDCTL_DSP_NONBLOCK;
+ unsigned IOCTL_SNDCTL_DSP_POST = SNDCTL_DSP_POST;
+ unsigned IOCTL_SNDCTL_DSP_RESET = SNDCTL_DSP_RESET;
+ unsigned IOCTL_SNDCTL_DSP_SETFMT = SNDCTL_DSP_SETFMT;
+ unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT = SNDCTL_DSP_SETFRAGMENT;
+ unsigned IOCTL_SNDCTL_DSP_SPEED = SNDCTL_DSP_SPEED;
+ unsigned IOCTL_SNDCTL_DSP_STEREO = SNDCTL_DSP_STEREO;
+ unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE = SNDCTL_DSP_SUBDIVIDE;
+ unsigned IOCTL_SNDCTL_DSP_SYNC = SNDCTL_DSP_SYNC;
+ unsigned IOCTL_SNDCTL_FM_4OP_ENABLE = SNDCTL_FM_4OP_ENABLE;
+ unsigned IOCTL_SNDCTL_FM_LOAD_INSTR = SNDCTL_FM_LOAD_INSTR;
+ unsigned IOCTL_SNDCTL_MIDI_INFO = SNDCTL_MIDI_INFO;
+ unsigned IOCTL_SNDCTL_MIDI_PRETIME = SNDCTL_MIDI_PRETIME;
+ unsigned IOCTL_SNDCTL_SEQ_CTRLRATE = SNDCTL_SEQ_CTRLRATE;
+ unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT = SNDCTL_SEQ_GETINCOUNT;
+ unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT = SNDCTL_SEQ_GETOUTCOUNT;
+ unsigned IOCTL_SNDCTL_SEQ_NRMIDIS = SNDCTL_SEQ_NRMIDIS;
+ unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS = SNDCTL_SEQ_NRSYNTHS;
+ unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND = SNDCTL_SEQ_OUTOFBAND;
+ unsigned IOCTL_SNDCTL_SEQ_PANIC = SNDCTL_SEQ_PANIC;
+ unsigned IOCTL_SNDCTL_SEQ_PERCMODE = SNDCTL_SEQ_PERCMODE;
+ unsigned IOCTL_SNDCTL_SEQ_RESET = SNDCTL_SEQ_RESET;
+ unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES = SNDCTL_SEQ_RESETSAMPLES;
+ unsigned IOCTL_SNDCTL_SEQ_SYNC = SNDCTL_SEQ_SYNC;
+ unsigned IOCTL_SNDCTL_SEQ_TESTMIDI = SNDCTL_SEQ_TESTMIDI;
+ unsigned IOCTL_SNDCTL_SEQ_THRESHOLD = SNDCTL_SEQ_THRESHOLD;
+ unsigned IOCTL_SNDCTL_SYNTH_INFO = SNDCTL_SYNTH_INFO;
+ unsigned IOCTL_SNDCTL_SYNTH_MEMAVL = SNDCTL_SYNTH_MEMAVL;
+ unsigned IOCTL_SNDCTL_TMR_CONTINUE = SNDCTL_TMR_CONTINUE;
+ unsigned IOCTL_SNDCTL_TMR_METRONOME = SNDCTL_TMR_METRONOME;
+ unsigned IOCTL_SNDCTL_TMR_SELECT = SNDCTL_TMR_SELECT;
+ unsigned IOCTL_SNDCTL_TMR_SOURCE = SNDCTL_TMR_SOURCE;
+ unsigned IOCTL_SNDCTL_TMR_START = SNDCTL_TMR_START;
+ unsigned IOCTL_SNDCTL_TMR_STOP = SNDCTL_TMR_STOP;
+ unsigned IOCTL_SNDCTL_TMR_TEMPO = SNDCTL_TMR_TEMPO;
+ unsigned IOCTL_SNDCTL_TMR_TIMEBASE = SNDCTL_TMR_TIMEBASE;
+ unsigned IOCTL_SOUND_MIXER_READ_ALTPCM = SOUND_MIXER_READ_ALTPCM;
+ unsigned IOCTL_SOUND_MIXER_READ_BASS = SOUND_MIXER_READ_BASS;
+ unsigned IOCTL_SOUND_MIXER_READ_CAPS = SOUND_MIXER_READ_CAPS;
+ unsigned IOCTL_SOUND_MIXER_READ_CD = SOUND_MIXER_READ_CD;
+ unsigned IOCTL_SOUND_MIXER_READ_DEVMASK = SOUND_MIXER_READ_DEVMASK;
+ unsigned IOCTL_SOUND_MIXER_READ_ENHANCE = SOUND_MIXER_READ_ENHANCE;
+ unsigned IOCTL_SOUND_MIXER_READ_IGAIN = SOUND_MIXER_READ_IGAIN;
+ unsigned IOCTL_SOUND_MIXER_READ_IMIX = SOUND_MIXER_READ_IMIX;
+ unsigned IOCTL_SOUND_MIXER_READ_LINE = SOUND_MIXER_READ_LINE;
+ unsigned IOCTL_SOUND_MIXER_READ_LINE1 = SOUND_MIXER_READ_LINE1;
+ unsigned IOCTL_SOUND_MIXER_READ_LINE2 = SOUND_MIXER_READ_LINE2;
+ unsigned IOCTL_SOUND_MIXER_READ_LINE3 = SOUND_MIXER_READ_LINE3;
+ unsigned IOCTL_SOUND_MIXER_READ_LOUD = SOUND_MIXER_READ_LOUD;
+ unsigned IOCTL_SOUND_MIXER_READ_MIC = SOUND_MIXER_READ_MIC;
+ unsigned IOCTL_SOUND_MIXER_READ_MUTE = SOUND_MIXER_READ_MUTE;
+ unsigned IOCTL_SOUND_MIXER_READ_OGAIN = SOUND_MIXER_READ_OGAIN;
+ unsigned IOCTL_SOUND_MIXER_READ_PCM = SOUND_MIXER_READ_PCM;
+ unsigned IOCTL_SOUND_MIXER_READ_RECLEV = SOUND_MIXER_READ_RECLEV;
+ unsigned IOCTL_SOUND_MIXER_READ_RECMASK = SOUND_MIXER_READ_RECMASK;
+ unsigned IOCTL_SOUND_MIXER_READ_RECSRC = SOUND_MIXER_READ_RECSRC;
+ unsigned IOCTL_SOUND_MIXER_READ_SPEAKER = SOUND_MIXER_READ_SPEAKER;
+ unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS = SOUND_MIXER_READ_STEREODEVS;
+ unsigned IOCTL_SOUND_MIXER_READ_SYNTH = SOUND_MIXER_READ_SYNTH;
+ unsigned IOCTL_SOUND_MIXER_READ_TREBLE = SOUND_MIXER_READ_TREBLE;
+ unsigned IOCTL_SOUND_MIXER_READ_VOLUME = SOUND_MIXER_READ_VOLUME;
+ unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM = SOUND_MIXER_WRITE_ALTPCM;
+ unsigned IOCTL_SOUND_MIXER_WRITE_BASS = SOUND_MIXER_WRITE_BASS;
+ unsigned IOCTL_SOUND_MIXER_WRITE_CD = SOUND_MIXER_WRITE_CD;
+ unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE = SOUND_MIXER_WRITE_ENHANCE;
+ unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN = SOUND_MIXER_WRITE_IGAIN;
+ unsigned IOCTL_SOUND_MIXER_WRITE_IMIX = SOUND_MIXER_WRITE_IMIX;
+ unsigned IOCTL_SOUND_MIXER_WRITE_LINE = SOUND_MIXER_WRITE_LINE;
+ unsigned IOCTL_SOUND_MIXER_WRITE_LINE1 = SOUND_MIXER_WRITE_LINE1;
+ unsigned IOCTL_SOUND_MIXER_WRITE_LINE2 = SOUND_MIXER_WRITE_LINE2;
+ unsigned IOCTL_SOUND_MIXER_WRITE_LINE3 = SOUND_MIXER_WRITE_LINE3;
+ unsigned IOCTL_SOUND_MIXER_WRITE_LOUD = SOUND_MIXER_WRITE_LOUD;
+ unsigned IOCTL_SOUND_MIXER_WRITE_MIC = SOUND_MIXER_WRITE_MIC;
+ unsigned IOCTL_SOUND_MIXER_WRITE_MUTE = SOUND_MIXER_WRITE_MUTE;
+ unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN = SOUND_MIXER_WRITE_OGAIN;
+ unsigned IOCTL_SOUND_MIXER_WRITE_PCM = SOUND_MIXER_WRITE_PCM;
+ unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV = SOUND_MIXER_WRITE_RECLEV;
+ unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC = SOUND_MIXER_WRITE_RECSRC;
+ unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER = SOUND_MIXER_WRITE_SPEAKER;
+ unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH = SOUND_MIXER_WRITE_SYNTH;
+ unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE = SOUND_MIXER_WRITE_TREBLE;
+ unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME = SOUND_MIXER_WRITE_VOLUME;
+ unsigned IOCTL_VT_ACTIVATE = VT_ACTIVATE;
+ unsigned IOCTL_VT_GETMODE = VT_GETMODE;
+ unsigned IOCTL_VT_OPENQRY = VT_OPENQRY;
+ unsigned IOCTL_VT_RELDISP = VT_RELDISP;
+ unsigned IOCTL_VT_SETMODE = VT_SETMODE;
+ unsigned IOCTL_VT_WAITACTIVE = VT_WAITACTIVE;
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ unsigned IOCTL_EQL_EMANCIPATE = EQL_EMANCIPATE;
+ unsigned IOCTL_EQL_ENSLAVE = EQL_ENSLAVE;
+ unsigned IOCTL_EQL_GETMASTRCFG = EQL_GETMASTRCFG;
+ unsigned IOCTL_EQL_GETSLAVECFG = EQL_GETSLAVECFG;
+ unsigned IOCTL_EQL_SETMASTRCFG = EQL_SETMASTRCFG;
+ unsigned IOCTL_EQL_SETSLAVECFG = EQL_SETSLAVECFG;
+#if EV_VERSION > (0x010000)
+ unsigned IOCTL_EVIOCGKEYCODE_V2 = EVIOCGKEYCODE_V2;
+ unsigned IOCTL_EVIOCGPROP = EVIOCGPROP(0);
+ unsigned IOCTL_EVIOCSKEYCODE_V2 = EVIOCSKEYCODE_V2;
+#else
+ unsigned IOCTL_EVIOCGKEYCODE_V2 = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_EVIOCGPROP = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_EVIOCSKEYCODE_V2 = IOCTL_NOT_PRESENT;
+#endif
+ unsigned IOCTL_FS_IOC_GETFLAGS = _IOR('f', 1, long);
+ unsigned IOCTL_FS_IOC_GETVERSION = _IOR('v', 1, long);
+ unsigned IOCTL_FS_IOC_SETFLAGS = _IOW('f', 2, long);
+ unsigned IOCTL_FS_IOC_SETVERSION = _IOW('v', 2, long);
+ unsigned IOCTL_GIO_CMAP = GIO_CMAP;
+ unsigned IOCTL_GIO_FONT = GIO_FONT;
+ unsigned IOCTL_GIO_UNIMAP = GIO_UNIMAP;
+ unsigned IOCTL_GIO_UNISCRNMAP = GIO_UNISCRNMAP;
+ unsigned IOCTL_KDADDIO = KDADDIO;
+ unsigned IOCTL_KDDELIO = KDDELIO;
+ unsigned IOCTL_KDGETKEYCODE = KDGETKEYCODE;
+ unsigned IOCTL_KDGKBDIACR = KDGKBDIACR;
+ unsigned IOCTL_KDGKBENT = KDGKBENT;
+ unsigned IOCTL_KDGKBLED = KDGKBLED;
+ unsigned IOCTL_KDGKBMETA = KDGKBMETA;
+ unsigned IOCTL_KDGKBSENT = KDGKBSENT;
+ unsigned IOCTL_KDMAPDISP = KDMAPDISP;
+ unsigned IOCTL_KDSETKEYCODE = KDSETKEYCODE;
+ unsigned IOCTL_KDSIGACCEPT = KDSIGACCEPT;
+ unsigned IOCTL_KDSKBDIACR = KDSKBDIACR;
+ unsigned IOCTL_KDSKBENT = KDSKBENT;
+ unsigned IOCTL_KDSKBLED = KDSKBLED;
+ unsigned IOCTL_KDSKBMETA = KDSKBMETA;
+ unsigned IOCTL_KDSKBSENT = KDSKBSENT;
+ unsigned IOCTL_KDUNMAPDISP = KDUNMAPDISP;
+ unsigned IOCTL_LPABORT = LPABORT;
+ unsigned IOCTL_LPABORTOPEN = LPABORTOPEN;
+ unsigned IOCTL_LPCAREFUL = LPCAREFUL;
+ unsigned IOCTL_LPCHAR = LPCHAR;
+ unsigned IOCTL_LPGETIRQ = LPGETIRQ;
+ unsigned IOCTL_LPGETSTATUS = LPGETSTATUS;
+ unsigned IOCTL_LPRESET = LPRESET;
+ unsigned IOCTL_LPSETIRQ = LPSETIRQ;
+ unsigned IOCTL_LPTIME = LPTIME;
+ unsigned IOCTL_LPWAIT = LPWAIT;
+ unsigned IOCTL_MTIOCGETCONFIG = MTIOCGETCONFIG;
+ unsigned IOCTL_MTIOCSETCONFIG = MTIOCSETCONFIG;
+ unsigned IOCTL_PIO_CMAP = PIO_CMAP;
+ unsigned IOCTL_PIO_FONT = PIO_FONT;
+ unsigned IOCTL_PIO_UNIMAP = PIO_UNIMAP;
+ unsigned IOCTL_PIO_UNIMAPCLR = PIO_UNIMAPCLR;
+ unsigned IOCTL_PIO_UNISCRNMAP = PIO_UNISCRNMAP;
+#if SANITIZER_GLIBC
+ unsigned IOCTL_SCSI_IOCTL_GET_IDLUN = SCSI_IOCTL_GET_IDLUN;
+ unsigned IOCTL_SCSI_IOCTL_PROBE_HOST = SCSI_IOCTL_PROBE_HOST;
+ unsigned IOCTL_SCSI_IOCTL_TAGGED_DISABLE = SCSI_IOCTL_TAGGED_DISABLE;
+ unsigned IOCTL_SCSI_IOCTL_TAGGED_ENABLE = SCSI_IOCTL_TAGGED_ENABLE;
+ unsigned IOCTL_SIOCAIPXITFCRT = SIOCAIPXITFCRT;
+ unsigned IOCTL_SIOCAIPXPRISLT = SIOCAIPXPRISLT;
+ unsigned IOCTL_SIOCAX25ADDUID = SIOCAX25ADDUID;
+ unsigned IOCTL_SIOCAX25DELUID = SIOCAX25DELUID;
+ unsigned IOCTL_SIOCAX25GETPARMS = SIOCAX25GETPARMS;
+ unsigned IOCTL_SIOCAX25GETUID = SIOCAX25GETUID;
+ unsigned IOCTL_SIOCAX25NOUID = SIOCAX25NOUID;
+ unsigned IOCTL_SIOCAX25SETPARMS = SIOCAX25SETPARMS;
+ unsigned IOCTL_SIOCDEVPLIP = SIOCDEVPLIP;
+ unsigned IOCTL_SIOCIPXCFGDATA = SIOCIPXCFGDATA;
+ unsigned IOCTL_SIOCNRDECOBS = SIOCNRDECOBS;
+ unsigned IOCTL_SIOCNRGETPARMS = SIOCNRGETPARMS;
+ unsigned IOCTL_SIOCNRRTCTL = SIOCNRRTCTL;
+ unsigned IOCTL_SIOCNRSETPARMS = SIOCNRSETPARMS;
+#endif
+ unsigned IOCTL_TIOCGSERIAL = TIOCGSERIAL;
+ unsigned IOCTL_TIOCSERGETMULTI = TIOCSERGETMULTI;
+ unsigned IOCTL_TIOCSERSETMULTI = TIOCSERSETMULTI;
+ unsigned IOCTL_TIOCSSERIAL = TIOCSSERIAL;
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ unsigned IOCTL_GIO_SCRNMAP = GIO_SCRNMAP;
+ unsigned IOCTL_KDDISABIO = KDDISABIO;
+ unsigned IOCTL_KDENABIO = KDENABIO;
+ unsigned IOCTL_KDGETLED = KDGETLED;
+ unsigned IOCTL_KDGETMODE = KDGETMODE;
+ unsigned IOCTL_KDGKBMODE = KDGKBMODE;
+ unsigned IOCTL_KDGKBTYPE = KDGKBTYPE;
+ unsigned IOCTL_KDMKTONE = KDMKTONE;
+ unsigned IOCTL_KDSETLED = KDSETLED;
+ unsigned IOCTL_KDSETMODE = KDSETMODE;
+ unsigned IOCTL_KDSKBMODE = KDSKBMODE;
+ unsigned IOCTL_KIOCSOUND = KIOCSOUND;
+ unsigned IOCTL_PIO_SCRNMAP = PIO_SCRNMAP;
+ unsigned IOCTL_SNDCTL_DSP_GETISPACE = SNDCTL_DSP_GETISPACE;
+ unsigned IOCTL_SNDCTL_DSP_GETOSPACE = SNDCTL_DSP_GETOSPACE;
+#endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
+
+ const int si_SEGV_MAPERR = SEGV_MAPERR;
+ const int si_SEGV_ACCERR = SEGV_ACCERR;
+} // namespace __sanitizer
+
+using namespace __sanitizer;
+
+COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
+
+COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned));
+CHECK_TYPE_SIZE(pthread_key_t);
+
+#if SANITIZER_LINUX
+// FIXME: We define those on Linux and Mac, but only check on Linux.
+COMPILER_CHECK(IOC_NRBITS == _IOC_NRBITS);
+COMPILER_CHECK(IOC_TYPEBITS == _IOC_TYPEBITS);
+COMPILER_CHECK(IOC_SIZEBITS == _IOC_SIZEBITS);
+COMPILER_CHECK(IOC_DIRBITS == _IOC_DIRBITS);
+COMPILER_CHECK(IOC_NRMASK == _IOC_NRMASK);
+COMPILER_CHECK(IOC_TYPEMASK == _IOC_TYPEMASK);
+COMPILER_CHECK(IOC_SIZEMASK == _IOC_SIZEMASK);
+COMPILER_CHECK(IOC_DIRMASK == _IOC_DIRMASK);
+COMPILER_CHECK(IOC_NRSHIFT == _IOC_NRSHIFT);
+COMPILER_CHECK(IOC_TYPESHIFT == _IOC_TYPESHIFT);
+COMPILER_CHECK(IOC_SIZESHIFT == _IOC_SIZESHIFT);
+COMPILER_CHECK(IOC_DIRSHIFT == _IOC_DIRSHIFT);
+COMPILER_CHECK(IOC_NONE == _IOC_NONE);
+COMPILER_CHECK(IOC_WRITE == _IOC_WRITE);
+COMPILER_CHECK(IOC_READ == _IOC_READ);
+COMPILER_CHECK(EVIOC_ABS_MAX == ABS_MAX);
+COMPILER_CHECK(EVIOC_EV_MAX == EV_MAX);
+COMPILER_CHECK(IOC_SIZE(0x12345678) == _IOC_SIZE(0x12345678));
+COMPILER_CHECK(IOC_DIR(0x12345678) == _IOC_DIR(0x12345678));
+COMPILER_CHECK(IOC_NR(0x12345678) == _IOC_NR(0x12345678));
+COMPILER_CHECK(IOC_TYPE(0x12345678) == _IOC_TYPE(0x12345678));
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
+// There are more undocumented fields in dl_phdr_info that we are not interested
+// in.
+COMPILER_CHECK(sizeof(__sanitizer_dl_phdr_info) <= sizeof(dl_phdr_info));
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_addr);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum);
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD
+
+#if SANITIZER_GLIBC || SANITIZER_FREEBSD
+CHECK_TYPE_SIZE(glob_t);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_offs);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_flags);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_closedir);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_readdir);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_opendir);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_lstat);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_stat);
+#endif // SANITIZER_GLIBC || SANITIZER_FREEBSD
+
+CHECK_TYPE_SIZE(addrinfo);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_flags);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_family);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_socktype);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_addrlen);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_canonname);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_addr);
+
+CHECK_TYPE_SIZE(hostent);
+CHECK_SIZE_AND_OFFSET(hostent, h_name);
+CHECK_SIZE_AND_OFFSET(hostent, h_aliases);
+CHECK_SIZE_AND_OFFSET(hostent, h_addrtype);
+CHECK_SIZE_AND_OFFSET(hostent, h_length);
+CHECK_SIZE_AND_OFFSET(hostent, h_addr_list);
+
+CHECK_TYPE_SIZE(iovec);
+CHECK_SIZE_AND_OFFSET(iovec, iov_base);
+CHECK_SIZE_AND_OFFSET(iovec, iov_len);
+
+// In POSIX, int msg_iovlen; socklen_t msg_controllen; socklen_t cmsg_len; but
+// many implementations don't conform to the standard. Since we pick the
+// non-conforming glibc definition, exclude the checks for musl (incompatible
+// sizes but compatible offsets).
+CHECK_TYPE_SIZE(msghdr);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_name);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_namelen);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_iov);
+#if SANITIZER_GLIBC || SANITIZER_ANDROID
+CHECK_SIZE_AND_OFFSET(msghdr, msg_iovlen);
+#endif
+CHECK_SIZE_AND_OFFSET(msghdr, msg_control);
+#if SANITIZER_GLIBC || SANITIZER_ANDROID
+CHECK_SIZE_AND_OFFSET(msghdr, msg_controllen);
+#endif
+CHECK_SIZE_AND_OFFSET(msghdr, msg_flags);
+
+CHECK_TYPE_SIZE(cmsghdr);
+#if SANITIZER_GLIBC || SANITIZER_ANDROID
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
+#endif
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
+
+#if SANITIZER_LINUX && (__ANDROID_API__ >= 21 || __GLIBC_PREREQ (2, 14))
+CHECK_TYPE_SIZE(mmsghdr);
+CHECK_SIZE_AND_OFFSET(mmsghdr, msg_hdr);
+CHECK_SIZE_AND_OFFSET(mmsghdr, msg_len);
+#endif
+
+COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
+CHECK_SIZE_AND_OFFSET(dirent, d_ino);
+#if SANITIZER_APPLE
+CHECK_SIZE_AND_OFFSET(dirent, d_seekoff);
+#elif SANITIZER_FREEBSD
+// There is no 'd_off' field on FreeBSD.
+#else
+CHECK_SIZE_AND_OFFSET(dirent, d_off);
+#endif
+CHECK_SIZE_AND_OFFSET(dirent, d_reclen);
+
+#if SANITIZER_GLIBC
+COMPILER_CHECK(sizeof(__sanitizer_dirent64) <= sizeof(dirent64));
+CHECK_SIZE_AND_OFFSET(dirent64, d_ino);
+CHECK_SIZE_AND_OFFSET(dirent64, d_off);
+CHECK_SIZE_AND_OFFSET(dirent64, d_reclen);
+#endif
+
+CHECK_TYPE_SIZE(ifconf);
+CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
+CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);
+
+CHECK_TYPE_SIZE(pollfd);
+CHECK_SIZE_AND_OFFSET(pollfd, fd);
+CHECK_SIZE_AND_OFFSET(pollfd, events);
+CHECK_SIZE_AND_OFFSET(pollfd, revents);
+
+CHECK_TYPE_SIZE(nfds_t);
+
+CHECK_TYPE_SIZE(sigset_t);
+
+COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction));
+// Can't write checks for sa_handler and sa_sigaction due to them being
+// preprocessor macros.
+CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
+#if !defined(__s390x__) || __GLIBC_PREREQ (2, 20)
+// On s390x glibc 2.19 and earlier sa_flags was unsigned long, and sa_resv
+// didn't exist.
+CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_flags);
+#endif
+#if SANITIZER_LINUX && (!SANITIZER_ANDROID || !SANITIZER_MIPS32)
+CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_restorer);
+#endif
+
+#if SANITIZER_HAS_SIGINFO
+COMPILER_CHECK(alignof(siginfo_t) == alignof(__sanitizer_siginfo));
+using __sanitizer_siginfo_t = __sanitizer_siginfo;
+CHECK_TYPE_SIZE(siginfo_t);
+CHECK_SIZE_AND_OFFSET(siginfo_t, si_signo);
+CHECK_SIZE_AND_OFFSET(siginfo_t, si_errno);
+CHECK_SIZE_AND_OFFSET(siginfo_t, si_code);
+#endif
+
+#if SANITIZER_LINUX
+CHECK_TYPE_SIZE(__sysctl_args);
+CHECK_SIZE_AND_OFFSET(__sysctl_args, name);
+CHECK_SIZE_AND_OFFSET(__sysctl_args, nlen);
+CHECK_SIZE_AND_OFFSET(__sysctl_args, oldval);
+CHECK_SIZE_AND_OFFSET(__sysctl_args, oldlenp);
+CHECK_SIZE_AND_OFFSET(__sysctl_args, newval);
+CHECK_SIZE_AND_OFFSET(__sysctl_args, newlen);
+
+CHECK_TYPE_SIZE(__kernel_uid_t);
+CHECK_TYPE_SIZE(__kernel_gid_t);
+
+#if SANITIZER_USES_UID16_SYSCALLS
+CHECK_TYPE_SIZE(__kernel_old_uid_t);
+CHECK_TYPE_SIZE(__kernel_old_gid_t);
+#endif
+
+CHECK_TYPE_SIZE(__kernel_off_t);
+CHECK_TYPE_SIZE(__kernel_loff_t);
+CHECK_TYPE_SIZE(__kernel_fd_set);
+#endif
+
+#if !SANITIZER_ANDROID
+CHECK_TYPE_SIZE(wordexp_t);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_offs);
+#endif
+
+CHECK_TYPE_SIZE(tm);
+CHECK_SIZE_AND_OFFSET(tm, tm_sec);
+CHECK_SIZE_AND_OFFSET(tm, tm_min);
+CHECK_SIZE_AND_OFFSET(tm, tm_hour);
+CHECK_SIZE_AND_OFFSET(tm, tm_mday);
+CHECK_SIZE_AND_OFFSET(tm, tm_mon);
+CHECK_SIZE_AND_OFFSET(tm, tm_year);
+CHECK_SIZE_AND_OFFSET(tm, tm_wday);
+CHECK_SIZE_AND_OFFSET(tm, tm_yday);
+CHECK_SIZE_AND_OFFSET(tm, tm_isdst);
+CHECK_SIZE_AND_OFFSET(tm, tm_gmtoff);
+CHECK_SIZE_AND_OFFSET(tm, tm_zone);
+
+#if SANITIZER_LINUX
+CHECK_TYPE_SIZE(mntent);
+CHECK_SIZE_AND_OFFSET(mntent, mnt_fsname);
+CHECK_SIZE_AND_OFFSET(mntent, mnt_dir);
+CHECK_SIZE_AND_OFFSET(mntent, mnt_type);
+CHECK_SIZE_AND_OFFSET(mntent, mnt_opts);
+CHECK_SIZE_AND_OFFSET(mntent, mnt_freq);
+CHECK_SIZE_AND_OFFSET(mntent, mnt_passno);
+#endif
+
+CHECK_TYPE_SIZE(ether_addr);
+
+#if SANITIZER_GLIBC || SANITIZER_FREEBSD
+CHECK_TYPE_SIZE(ipc_perm);
+# if SANITIZER_FREEBSD
+CHECK_SIZE_AND_OFFSET(ipc_perm, key);
+CHECK_SIZE_AND_OFFSET(ipc_perm, seq);
+# else
+CHECK_SIZE_AND_OFFSET(ipc_perm, __key);
+CHECK_SIZE_AND_OFFSET(ipc_perm, __seq);
+# endif
+CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
+#if !SANITIZER_LINUX || __GLIBC_PREREQ (2, 31)
+/* glibc 2.30 and earlier provided 16-bit mode field instead of 32-bit
+ on many architectures. */
+CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
+#endif
+
+CHECK_TYPE_SIZE(shmid_ds);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_perm);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_segsz);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_atime);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_dtime);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_ctime);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_cpid);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_lpid);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_nattch);
+#endif
+
+CHECK_TYPE_SIZE(clock_t);
+
+#if SANITIZER_LINUX
+CHECK_TYPE_SIZE(clockid_t);
+#endif
+
+#if !SANITIZER_ANDROID
+CHECK_TYPE_SIZE(ifaddrs);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask);
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
+// Compare against the union, because we can't reach into the union in a
+// compliant way.
+#ifdef ifa_dstaddr
+#undef ifa_dstaddr
+#endif
+# if SANITIZER_FREEBSD
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr);
+# else
+COMPILER_CHECK(sizeof(((__sanitizer_ifaddrs *)nullptr)->ifa_dstaddr) ==
+ sizeof(((ifaddrs *)nullptr)->ifa_ifu));
+COMPILER_CHECK(offsetof(__sanitizer_ifaddrs, ifa_dstaddr) ==
+ offsetof(ifaddrs, ifa_ifu));
+# endif // SANITIZER_FREEBSD
+#else
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr);
+#endif // SANITIZER_LINUX
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data);
+#endif
+
+#if SANITIZER_GLIBC || SANITIZER_ANDROID
+COMPILER_CHECK(sizeof(__sanitizer_struct_mallinfo) == sizeof(struct mallinfo));
+#endif
+
+#if !SANITIZER_ANDROID
+CHECK_TYPE_SIZE(timeb);
+CHECK_SIZE_AND_OFFSET(timeb, time);
+CHECK_SIZE_AND_OFFSET(timeb, millitm);
+CHECK_SIZE_AND_OFFSET(timeb, timezone);
+CHECK_SIZE_AND_OFFSET(timeb, dstflag);
+#endif
+
+CHECK_TYPE_SIZE(passwd);
+CHECK_SIZE_AND_OFFSET(passwd, pw_name);
+CHECK_SIZE_AND_OFFSET(passwd, pw_passwd);
+CHECK_SIZE_AND_OFFSET(passwd, pw_uid);
+CHECK_SIZE_AND_OFFSET(passwd, pw_gid);
+CHECK_SIZE_AND_OFFSET(passwd, pw_dir);
+CHECK_SIZE_AND_OFFSET(passwd, pw_shell);
+
+#if !SANITIZER_ANDROID
+CHECK_SIZE_AND_OFFSET(passwd, pw_gecos);
+#endif
+
+#if SANITIZER_APPLE
+CHECK_SIZE_AND_OFFSET(passwd, pw_change);
+CHECK_SIZE_AND_OFFSET(passwd, pw_expire);
+CHECK_SIZE_AND_OFFSET(passwd, pw_class);
+#endif
+
+
+CHECK_TYPE_SIZE(group);
+CHECK_SIZE_AND_OFFSET(group, gr_name);
+CHECK_SIZE_AND_OFFSET(group, gr_passwd);
+CHECK_SIZE_AND_OFFSET(group, gr_gid);
+CHECK_SIZE_AND_OFFSET(group, gr_mem);
+
+#if HAVE_RPC_XDR_H && !SANITIZER_APPLE
+CHECK_TYPE_SIZE(XDR);
+CHECK_SIZE_AND_OFFSET(XDR, x_op);
+CHECK_SIZE_AND_OFFSET(XDR, x_ops);
+CHECK_SIZE_AND_OFFSET(XDR, x_public);
+CHECK_SIZE_AND_OFFSET(XDR, x_private);
+CHECK_SIZE_AND_OFFSET(XDR, x_base);
+CHECK_SIZE_AND_OFFSET(XDR, x_handy);
+COMPILER_CHECK(__sanitizer_XDR_ENCODE == XDR_ENCODE);
+COMPILER_CHECK(__sanitizer_XDR_DECODE == XDR_DECODE);
+COMPILER_CHECK(__sanitizer_XDR_FREE == XDR_FREE);
+#endif
+
+#if SANITIZER_GLIBC
+COMPILER_CHECK(sizeof(__sanitizer_FILE) <= sizeof(FILE));
+CHECK_SIZE_AND_OFFSET(FILE, _flags);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_read_ptr);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_read_end);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_read_base);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_write_ptr);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_write_end);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_write_base);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_buf_base);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_buf_end);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_save_base);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_backup_base);
+CHECK_SIZE_AND_OFFSET(FILE, _IO_save_end);
+CHECK_SIZE_AND_OFFSET(FILE, _markers);
+CHECK_SIZE_AND_OFFSET(FILE, _chain);
+CHECK_SIZE_AND_OFFSET(FILE, _fileno);
+
+COMPILER_CHECK(sizeof(__sanitizer__obstack_chunk) <= sizeof(_obstack_chunk));
+CHECK_SIZE_AND_OFFSET(_obstack_chunk, limit);
+CHECK_SIZE_AND_OFFSET(_obstack_chunk, prev);
+CHECK_TYPE_SIZE(obstack);
+CHECK_SIZE_AND_OFFSET(obstack, chunk_size);
+CHECK_SIZE_AND_OFFSET(obstack, chunk);
+CHECK_SIZE_AND_OFFSET(obstack, object_base);
+CHECK_SIZE_AND_OFFSET(obstack, next_free);
+
+CHECK_TYPE_SIZE(cookie_io_functions_t);
+CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, read);
+CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, write);
+CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, seek);
+CHECK_SIZE_AND_OFFSET(cookie_io_functions_t, close);
+#endif // SANITIZER_GLIBC
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD
+CHECK_TYPE_SIZE(sem_t);
+#endif
+
+#if SANITIZER_LINUX && defined(__arm__)
+COMPILER_CHECK(ARM_VFPREGS_SIZE == ARM_VFPREGS_SIZE_ASAN);
+#endif
+
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
new file mode 100644
index 00000000000..fdc69b8a5fb
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -0,0 +1,1509 @@
+//===-- sanitizer_platform_limits_posix.h ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer common code.
+//
+// Sizes and layouts of platform-specific POSIX data structures.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H
+#define SANITIZER_PLATFORM_LIMITS_POSIX_H
+
+#if SANITIZER_LINUX || SANITIZER_APPLE
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform.h"
+
+#if SANITIZER_APPLE
+#include <sys/cdefs.h>
+#if !__DARWIN_ONLY_64_BIT_INO_T
+#define SANITIZER_HAS_STAT64 1
+#define SANITIZER_HAS_STATFS64 1
+#else
+#define SANITIZER_HAS_STAT64 0
+#define SANITIZER_HAS_STATFS64 0
+#endif
+#elif SANITIZER_GLIBC || SANITIZER_ANDROID
+#define SANITIZER_HAS_STAT64 1
+#define SANITIZER_HAS_STATFS64 1
+#endif
+
+#if defined(__sparc__)
+// FIXME: This can't be included from tsan which does not support sparc yet.
+#include "sanitizer_glibc_version.h"
+#endif
+
+# define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) ((link_map*)(handle))
+
+namespace __sanitizer {
+extern unsigned struct_utsname_sz;
+extern unsigned struct_stat_sz;
+#if SANITIZER_HAS_STAT64
+extern unsigned struct_stat64_sz;
+#endif
+extern unsigned struct_rusage_sz;
+extern unsigned siginfo_t_sz;
+extern unsigned struct_itimerval_sz;
+extern unsigned pthread_t_sz;
+extern unsigned pthread_mutex_t_sz;
+extern unsigned pthread_cond_t_sz;
+extern unsigned pid_t_sz;
+extern unsigned timeval_sz;
+extern unsigned uid_t_sz;
+extern unsigned gid_t_sz;
+extern unsigned mbstate_t_sz;
+extern unsigned struct_timezone_sz;
+extern unsigned struct_tms_sz;
+extern unsigned struct_itimerspec_sz;
+extern unsigned struct_sigevent_sz;
+extern unsigned struct_stack_t_sz;
+extern unsigned struct_sched_param_sz;
+#if SANITIZER_HAS_STATFS64
+extern unsigned struct_statfs64_sz;
+#endif
+extern unsigned struct_regex_sz;
+extern unsigned struct_regmatch_sz;
+
+#if !SANITIZER_ANDROID
+extern unsigned struct_fstab_sz;
+extern unsigned struct_statfs_sz;
+extern unsigned struct_sockaddr_sz;
+unsigned ucontext_t_sz(void *uctx);
+# endif // !SANITIZER_ANDROID
+
+# if SANITIZER_LINUX
+
+# if defined(__x86_64__)
+const unsigned struct_kernel_stat_sz = 144;
+const unsigned struct_kernel_stat64_sz = 0;
+#elif defined(__i386__)
+const unsigned struct_kernel_stat_sz = 64;
+const unsigned struct_kernel_stat64_sz = 96;
+#elif defined(__arm__)
+const unsigned struct_kernel_stat_sz = 64;
+const unsigned struct_kernel_stat64_sz = 104;
+#elif defined(__aarch64__)
+const unsigned struct_kernel_stat_sz = 128;
+const unsigned struct_kernel_stat64_sz = 104;
+#elif defined(__powerpc__) && !defined(__powerpc64__)
+const unsigned struct_kernel_stat_sz = 72;
+const unsigned struct_kernel_stat64_sz = 104;
+#elif defined(__powerpc64__)
+const unsigned struct_kernel_stat_sz = 144;
+const unsigned struct_kernel_stat64_sz = 104;
+#elif defined(__mips__)
+const unsigned struct_kernel_stat_sz =
+ SANITIZER_ANDROID
+ ? FIRST_32_SECOND_64(104, 128)
+ : FIRST_32_SECOND_64((_MIPS_SIM == _ABIN32) ? 176 : 160, 216);
+const unsigned struct_kernel_stat64_sz = 104;
+#elif defined(__s390__) && !defined(__s390x__)
+const unsigned struct_kernel_stat_sz = 64;
+const unsigned struct_kernel_stat64_sz = 104;
+#elif defined(__s390x__)
+const unsigned struct_kernel_stat_sz = 144;
+const unsigned struct_kernel_stat64_sz = 0;
+#elif defined(__sparc__) && defined(__arch64__)
+const unsigned struct___old_kernel_stat_sz = 0;
+const unsigned struct_kernel_stat_sz = 104;
+const unsigned struct_kernel_stat64_sz = 144;
+#elif defined(__sparc__) && !defined(__arch64__)
+const unsigned struct___old_kernel_stat_sz = 0;
+const unsigned struct_kernel_stat_sz = 64;
+const unsigned struct_kernel_stat64_sz = 104;
+#elif SANITIZER_RISCV64
+const unsigned struct_kernel_stat_sz = 128;
+const unsigned struct_kernel_stat64_sz = 0; // RISCV64 does not use stat64
+# elif defined(__hexagon__)
+const unsigned struct_kernel_stat_sz = 128;
+const unsigned struct_kernel_stat64_sz = 0;
+# elif defined(__loongarch__)
+const unsigned struct_kernel_stat_sz = 128;
+const unsigned struct_kernel_stat64_sz = 0;
+# endif
+struct __sanitizer_perf_event_attr {
+ unsigned type;
+ unsigned size;
+ // More fields that vary with the kernel version.
+};
+
+extern unsigned struct_epoll_event_sz;
+extern unsigned struct_sysinfo_sz;
+extern unsigned __user_cap_header_struct_sz;
+extern unsigned __user_cap_data_struct_sz;
+extern unsigned struct_new_utsname_sz;
+extern unsigned struct_old_utsname_sz;
+extern unsigned struct_oldold_utsname_sz;
+
+const unsigned struct_kexec_segment_sz = 4 * sizeof(unsigned long);
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX
+
+#if defined(__powerpc64__) || defined(__s390__) || defined(__loongarch__)
+const unsigned struct___old_kernel_stat_sz = 0;
+#elif !defined(__sparc__)
+const unsigned struct___old_kernel_stat_sz = 32;
+#endif
+
+extern unsigned struct_rlimit_sz;
+extern unsigned struct_utimbuf_sz;
+extern unsigned struct_timespec_sz;
+
+struct __sanitizer_iocb {
+ u64 aio_data;
+ u32 aio_key_or_aio_reserved1; // Simply crazy.
+ u32 aio_reserved1_or_aio_key; // Luckily, we don't need these.
+ u16 aio_lio_opcode;
+ s16 aio_reqprio;
+ u32 aio_fildes;
+ u64 aio_buf;
+ u64 aio_nbytes;
+ s64 aio_offset;
+ u64 aio_reserved2;
+ u64 aio_reserved3;
+};
+
+struct __sanitizer_io_event {
+ u64 data;
+ u64 obj;
+ u64 res;
+ u64 res2;
+};
+
+const unsigned iocb_cmd_pread = 0;
+const unsigned iocb_cmd_pwrite = 1;
+const unsigned iocb_cmd_preadv = 7;
+const unsigned iocb_cmd_pwritev = 8;
+
+struct __sanitizer___sysctl_args {
+ int *name;
+ int nlen;
+ void *oldval;
+ uptr *oldlenp;
+ void *newval;
+ uptr newlen;
+ unsigned long ___unused[4];
+};
+
+const unsigned old_sigset_t_sz = sizeof(unsigned long);
+
+struct __sanitizer_sem_t {
+#if SANITIZER_ANDROID && defined(_LP64)
+ int data[4];
+#elif SANITIZER_ANDROID && !defined(_LP64)
+ int data;
+#elif SANITIZER_LINUX
+ uptr data[4];
+#endif
+};
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_ANDROID
+struct __sanitizer_struct_mallinfo {
+ uptr v[10];
+};
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+struct __sanitizer_struct_mallinfo {
+ int v[10];
+};
+
+extern unsigned struct_ustat_sz;
+extern unsigned struct_rlimit64_sz;
+extern unsigned struct_statvfs64_sz;
+
+struct __sanitizer_ipc_perm {
+ int __key;
+ int uid;
+ int gid;
+ int cuid;
+ int cgid;
+#ifdef __powerpc__
+ unsigned mode;
+ unsigned __seq;
+ u64 __unused1;
+ u64 __unused2;
+#elif defined(__sparc__)
+ unsigned mode;
+ unsigned short __pad2;
+ unsigned short __seq;
+ unsigned long long __unused1;
+ unsigned long long __unused2;
+#else
+ unsigned int mode;
+ unsigned short __seq;
+ unsigned short __pad2;
+#if defined(__x86_64__) && !defined(_LP64)
+ u64 __unused1;
+ u64 __unused2;
+#else
+ unsigned long __unused1;
+ unsigned long __unused2;
+#endif
+#endif
+};
+
+struct __sanitizer_shmid_ds {
+ __sanitizer_ipc_perm shm_perm;
+#if defined(__sparc__)
+#if !defined(__arch64__)
+ u32 __pad1;
+#endif
+ long shm_atime;
+#if !defined(__arch64__)
+ u32 __pad2;
+#endif
+ long shm_dtime;
+#if !defined(__arch64__)
+ u32 __pad3;
+#endif
+ long shm_ctime;
+ uptr shm_segsz;
+ int shm_cpid;
+ int shm_lpid;
+ unsigned long shm_nattch;
+ unsigned long __glibc_reserved1;
+ unsigned long __glibc_reserved2;
+#else
+#ifndef __powerpc__
+ uptr shm_segsz;
+#elif !defined(__powerpc64__)
+ uptr __unused0;
+#endif
+#if defined(__x86_64__) && !defined(_LP64)
+ u64 shm_atime;
+ u64 shm_dtime;
+ u64 shm_ctime;
+#else
+ uptr shm_atime;
+#if !defined(_LP64) && !defined(__mips__)
+ uptr __unused1;
+#endif
+ uptr shm_dtime;
+#if !defined(_LP64) && !defined(__mips__)
+ uptr __unused2;
+#endif
+ uptr shm_ctime;
+#if !defined(_LP64) && !defined(__mips__)
+ uptr __unused3;
+#endif
+#endif
+#ifdef __powerpc__
+ uptr shm_segsz;
+#endif
+ int shm_cpid;
+ int shm_lpid;
+#if defined(__x86_64__) && !defined(_LP64)
+ u64 shm_nattch;
+ u64 __unused4;
+ u64 __unused5;
+#else
+ uptr shm_nattch;
+ uptr __unused4;
+ uptr __unused5;
+#endif
+#endif
+};
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+extern unsigned struct_msqid_ds_sz;
+extern unsigned struct_mq_attr_sz;
+extern unsigned struct_timex_sz;
+extern unsigned struct_statvfs_sz;
+extern unsigned struct_crypt_data_sz;
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+
+struct __sanitizer_iovec {
+ void *iov_base;
+ uptr iov_len;
+};
+
+#if !SANITIZER_ANDROID
+struct __sanitizer_ifaddrs {
+ struct __sanitizer_ifaddrs *ifa_next;
+ char *ifa_name;
+ unsigned int ifa_flags;
+ void *ifa_addr; // (struct sockaddr *)
+ void *ifa_netmask; // (struct sockaddr *)
+ // This is a union on Linux.
+# ifdef ifa_dstaddr
+# undef ifa_dstaddr
+# endif
+ void *ifa_dstaddr; // (struct sockaddr *)
+ void *ifa_data;
+};
+#endif // !SANITIZER_ANDROID
+
+#if SANITIZER_APPLE
+typedef unsigned long __sanitizer_pthread_key_t;
+#else
+typedef unsigned __sanitizer_pthread_key_t;
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+
+struct __sanitizer_XDR {
+ int x_op;
+ void *x_ops;
+ uptr x_public;
+ uptr x_private;
+ uptr x_base;
+ unsigned x_handy;
+};
+
+const int __sanitizer_XDR_ENCODE = 0;
+const int __sanitizer_XDR_DECODE = 1;
+const int __sanitizer_XDR_FREE = 2;
+#endif
+
+struct __sanitizer_passwd {
+ char *pw_name;
+ char *pw_passwd;
+ int pw_uid;
+ int pw_gid;
+#if SANITIZER_APPLE
+ long pw_change;
+ char *pw_class;
+#endif
+#if !(SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32))
+ char *pw_gecos;
+#endif
+ char *pw_dir;
+ char *pw_shell;
+#if SANITIZER_APPLE
+ long pw_expire;
+#endif
+};
+
+struct __sanitizer_group {
+ char *gr_name;
+ char *gr_passwd;
+ int gr_gid;
+ char **gr_mem;
+};
+
+# if (SANITIZER_LINUX && !SANITIZER_GLIBC && !SANITIZER_ANDROID) || \
+ (defined(__x86_64__) && !defined(_LP64)) || defined(__hexagon__)
+typedef long long __sanitizer_time_t;
+#else
+typedef long __sanitizer_time_t;
+#endif
+
+typedef long __sanitizer_suseconds_t;
+
+struct __sanitizer_timeval {
+ __sanitizer_time_t tv_sec;
+ __sanitizer_suseconds_t tv_usec;
+};
+
+struct __sanitizer_itimerval {
+ struct __sanitizer_timeval it_interval;
+ struct __sanitizer_timeval it_value;
+};
+
+struct __sanitizer_timeb {
+ __sanitizer_time_t time;
+ unsigned short millitm;
+ short timezone;
+ short dstflag;
+};
+
+struct __sanitizer_ether_addr {
+ u8 octet[6];
+};
+
+struct __sanitizer_tm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+ long int tm_gmtoff;
+ const char *tm_zone;
+};
+
+#if SANITIZER_LINUX
+struct __sanitizer_mntent {
+ char *mnt_fsname;
+ char *mnt_dir;
+ char *mnt_type;
+ char *mnt_opts;
+ int mnt_freq;
+ int mnt_passno;
+};
+
+struct __sanitizer_file_handle {
+ unsigned int handle_bytes;
+ int handle_type;
+ unsigned char f_handle[1]; // variable sized
+};
+#endif
+
+#if SANITIZER_APPLE
+struct __sanitizer_msghdr {
+ void *msg_name;
+ unsigned msg_namelen;
+ struct __sanitizer_iovec *msg_iov;
+ unsigned msg_iovlen;
+ void *msg_control;
+ unsigned msg_controllen;
+ int msg_flags;
+};
+struct __sanitizer_cmsghdr {
+ unsigned cmsg_len;
+ int cmsg_level;
+ int cmsg_type;
+};
+#else
+// In POSIX, int msg_iovlen; socklen_t msg_controllen; socklen_t cmsg_len; but
+// many implementations don't conform to the standard.
+struct __sanitizer_msghdr {
+ void *msg_name;
+ unsigned msg_namelen;
+ struct __sanitizer_iovec *msg_iov;
+ uptr msg_iovlen;
+ void *msg_control;
+ uptr msg_controllen;
+ int msg_flags;
+};
+struct __sanitizer_cmsghdr {
+ uptr cmsg_len;
+ int cmsg_level;
+ int cmsg_type;
+};
+#endif
+
+#if SANITIZER_LINUX
+struct __sanitizer_mmsghdr {
+ __sanitizer_msghdr msg_hdr;
+ unsigned int msg_len;
+};
+#endif
+
+#if SANITIZER_APPLE
+struct __sanitizer_dirent {
+ unsigned long long d_ino;
+ unsigned long long d_seekoff;
+ unsigned short d_reclen;
+ // more fields that we don't care about
+};
+# elif (SANITIZER_LINUX && !SANITIZER_GLIBC) || defined(__x86_64__) || \
+ defined(__hexagon__)
+struct __sanitizer_dirent {
+ unsigned long long d_ino;
+ unsigned long long d_off;
+ unsigned short d_reclen;
+ // more fields that we don't care about
+};
+# else
+struct __sanitizer_dirent {
+ uptr d_ino;
+ uptr d_off;
+ unsigned short d_reclen;
+ // more fields that we don't care about
+};
+# endif
+
+# if SANITIZER_GLIBC
+struct __sanitizer_dirent64 {
+ unsigned long long d_ino;
+ unsigned long long d_off;
+ unsigned short d_reclen;
+ // more fields that we don't care about
+};
+#endif
+
+#if defined(__x86_64__) && !defined(_LP64)
+typedef long long __sanitizer_clock_t;
+#else
+typedef long __sanitizer_clock_t;
+#endif
+
+#if SANITIZER_LINUX
+typedef int __sanitizer_clockid_t;
+#endif
+
+#if SANITIZER_LINUX
+# if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \
+ defined(__mips__) || defined(__hexagon__)
+typedef unsigned __sanitizer___kernel_uid_t;
+typedef unsigned __sanitizer___kernel_gid_t;
+#else
+typedef unsigned short __sanitizer___kernel_uid_t;
+typedef unsigned short __sanitizer___kernel_gid_t;
+#endif
+#if defined(__x86_64__) && !defined(_LP64)
+typedef long long __sanitizer___kernel_off_t;
+#else
+typedef long __sanitizer___kernel_off_t;
+#endif
+
+#if defined(__powerpc__) || defined(__mips__)
+typedef unsigned int __sanitizer___kernel_old_uid_t;
+typedef unsigned int __sanitizer___kernel_old_gid_t;
+#else
+typedef unsigned short __sanitizer___kernel_old_uid_t;
+typedef unsigned short __sanitizer___kernel_old_gid_t;
+#endif
+
+typedef long long __sanitizer___kernel_loff_t;
+typedef struct {
+ unsigned long fds_bits[1024 / (8 * sizeof(long))];
+} __sanitizer___kernel_fd_set;
+#endif
+
+// This thing depends on the platform. We are only interested in the upper
+// limit. Verified with a compiler assert in .cpp.
+union __sanitizer_pthread_attr_t {
+ char size[128];
+ void *align;
+};
+
+#if SANITIZER_ANDROID
+# if SANITIZER_MIPS
+typedef unsigned long __sanitizer_sigset_t[16 / sizeof(unsigned long)];
+# else
+typedef unsigned long __sanitizer_sigset_t;
+# endif
+#elif SANITIZER_APPLE
+typedef unsigned __sanitizer_sigset_t;
+#elif SANITIZER_LINUX
+struct __sanitizer_sigset_t {
+ // The size is determined by looking at sizeof of real sigset_t on linux.
+ uptr val[128 / sizeof(uptr)];
+};
+#endif
+
+struct __sanitizer_siginfo_pad {
+ // Require uptr, because siginfo_t is always pointer-size aligned on Linux.
+ uptr pad[128 / sizeof(uptr)];
+};
+
+#if SANITIZER_LINUX
+# define SANITIZER_HAS_SIGINFO 1
+union __sanitizer_siginfo {
+ struct {
+ int si_signo;
+# if SANITIZER_MIPS
+ int si_code;
+ int si_errno;
+# else
+ int si_errno;
+ int si_code;
+# endif
+ };
+ __sanitizer_siginfo_pad pad;
+};
+#else
+# define SANITIZER_HAS_SIGINFO 0
+typedef __sanitizer_siginfo_pad __sanitizer_siginfo;
+#endif
+
+using __sanitizer_sighandler_ptr = void (*)(int sig);
+using __sanitizer_sigactionhandler_ptr = void (*)(int sig,
+ __sanitizer_siginfo *siginfo,
+ void *uctx);
+
+// Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
+#if SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 64)
+struct __sanitizer_sigaction {
+ unsigned sa_flags;
+ union {
+ __sanitizer_sigactionhandler_ptr sigaction;
+ __sanitizer_sighandler_ptr handler;
+ };
+ __sanitizer_sigset_t sa_mask;
+ void (*sa_restorer)();
+};
+#elif SANITIZER_ANDROID && SANITIZER_MIPS32 // check this before WORDSIZE == 32
+struct __sanitizer_sigaction {
+ unsigned sa_flags;
+ union {
+ __sanitizer_sigactionhandler_ptr sigaction;
+ __sanitizer_sighandler_ptr handler;
+ };
+ __sanitizer_sigset_t sa_mask;
+};
+#elif SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32)
+struct __sanitizer_sigaction {
+ union {
+ __sanitizer_sigactionhandler_ptr sigaction;
+ __sanitizer_sighandler_ptr handler;
+ };
+ __sanitizer_sigset_t sa_mask;
+ uptr sa_flags;
+ void (*sa_restorer)();
+};
+#else // !SANITIZER_ANDROID
+struct __sanitizer_sigaction {
+#if defined(__mips__) && !SANITIZER_FREEBSD
+ unsigned int sa_flags;
+#endif
+ union {
+ __sanitizer_sigactionhandler_ptr sigaction;
+ __sanitizer_sighandler_ptr handler;
+ };
+#if SANITIZER_FREEBSD
+ int sa_flags;
+ __sanitizer_sigset_t sa_mask;
+#else
+#if defined(__s390x__)
+ int sa_resv;
+#else
+ __sanitizer_sigset_t sa_mask;
+#endif
+#ifndef __mips__
+#if defined(__sparc__)
+#if __GLIBC_PREREQ (2, 20)
+ // On sparc glibc 2.19 and earlier sa_flags was unsigned long.
+#if defined(__arch64__)
+ // To maintain ABI compatibility on sparc64 when switching to an int,
+ // __glibc_reserved0 was added.
+ int __glibc_reserved0;
+#endif
+ int sa_flags;
+#else
+ unsigned long sa_flags;
+#endif
+#else
+ int sa_flags;
+#endif
+#endif
+#endif
+#if SANITIZER_LINUX
+ void (*sa_restorer)();
+#endif
+#if defined(__mips__) && (SANITIZER_WORDSIZE == 32)
+ int sa_resv[1];
+#endif
+#if defined(__s390x__)
+ __sanitizer_sigset_t sa_mask;
+#endif
+};
+#endif // !SANITIZER_ANDROID
+
+#if defined(__mips__)
+#define __SANITIZER_KERNEL_NSIG 128
+#else
+#define __SANITIZER_KERNEL_NSIG 64
+#endif
+
+struct __sanitizer_kernel_sigset_t {
+ uptr sig[__SANITIZER_KERNEL_NSIG / (sizeof(uptr) * 8)];
+};
+
+// Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
+#if SANITIZER_MIPS
+struct __sanitizer_kernel_sigaction_t {
+ unsigned int sa_flags;
+ union {
+ void (*handler)(int signo);
+ void (*sigaction)(int signo, __sanitizer_siginfo *info, void *ctx);
+ };
+ __sanitizer_kernel_sigset_t sa_mask;
+ void (*sa_restorer)(void);
+};
+#else
+struct __sanitizer_kernel_sigaction_t {
+ union {
+ void (*handler)(int signo);
+ void (*sigaction)(int signo, __sanitizer_siginfo *info, void *ctx);
+ };
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+ __sanitizer_kernel_sigset_t sa_mask;
+};
+#endif
+
+extern const uptr sig_ign;
+extern const uptr sig_dfl;
+extern const uptr sig_err;
+extern const uptr sa_siginfo;
+
+#if SANITIZER_LINUX
+extern int e_tabsz;
+#endif
+
+extern int af_inet;
+extern int af_inet6;
+uptr __sanitizer_in_addr_sz(int af);
+
+#if SANITIZER_LINUX
+struct __sanitizer_dl_phdr_info {
+ uptr dlpi_addr;
+ const char *dlpi_name;
+ const void *dlpi_phdr;
+ short dlpi_phnum;
+};
+
+extern unsigned struct_ElfW_Phdr_sz;
+#endif
+
+struct __sanitizer_protoent {
+ char *p_name;
+ char **p_aliases;
+ int p_proto;
+};
+
+struct __sanitizer_netent {
+ char *n_name;
+ char **n_aliases;
+ int n_addrtype;
+ u32 n_net;
+};
+
+struct __sanitizer_addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+#if SANITIZER_ANDROID || SANITIZER_APPLE
+ unsigned ai_addrlen;
+ char *ai_canonname;
+ void *ai_addr;
+#else // LINUX
+ unsigned ai_addrlen;
+ void *ai_addr;
+ char *ai_canonname;
+#endif
+ struct __sanitizer_addrinfo *ai_next;
+};
+
+struct __sanitizer_hostent {
+ char *h_name;
+ char **h_aliases;
+ int h_addrtype;
+ int h_length;
+ char **h_addr_list;
+};
+
+struct __sanitizer_pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+#if SANITIZER_ANDROID || SANITIZER_APPLE
+typedef unsigned __sanitizer_nfds_t;
+#else
+typedef unsigned long __sanitizer_nfds_t;
+#endif
+
+#if !SANITIZER_ANDROID
+# if SANITIZER_LINUX
+struct __sanitizer_glob_t {
+ uptr gl_pathc;
+ char **gl_pathv;
+ uptr gl_offs;
+ int gl_flags;
+
+ void (*gl_closedir)(void *dirp);
+ void *(*gl_readdir)(void *dirp);
+ void *(*gl_opendir)(const char *);
+ int (*gl_lstat)(const char *, void *);
+ int (*gl_stat)(const char *, void *);
+};
+# endif // SANITIZER_LINUX
+
+# if SANITIZER_LINUX
+extern int glob_nomatch;
+extern int glob_altdirfunc;
+# endif
+#endif // !SANITIZER_ANDROID
+
+extern unsigned path_max;
+
+# if !SANITIZER_ANDROID
+extern const int wordexp_wrde_dooffs;
+# endif // !SANITIZER_ANDROID
+
+struct __sanitizer_wordexp_t {
+ uptr we_wordc;
+ char **we_wordv;
+ uptr we_offs;
+};
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+struct __sanitizer_FILE {
+ int _flags;
+ char *_IO_read_ptr;
+ char *_IO_read_end;
+ char *_IO_read_base;
+ char *_IO_write_base;
+ char *_IO_write_ptr;
+ char *_IO_write_end;
+ char *_IO_buf_base;
+ char *_IO_buf_end;
+ char *_IO_save_base;
+ char *_IO_backup_base;
+ char *_IO_save_end;
+ void *_markers;
+ __sanitizer_FILE *_chain;
+ int _fileno;
+};
+# define SANITIZER_HAS_STRUCT_FILE 1
+#else
+typedef void __sanitizer_FILE;
+# define SANITIZER_HAS_STRUCT_FILE 0
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
+ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \
+ defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
+ defined(__s390__) || defined(__loongarch__) || SANITIZER_RISCV64)
+extern unsigned struct_user_regs_struct_sz;
+extern unsigned struct_user_fpregs_struct_sz;
+extern unsigned struct_user_fpxregs_struct_sz;
+extern unsigned struct_user_vfpregs_struct_sz;
+
+extern int ptrace_peektext;
+extern int ptrace_peekdata;
+extern int ptrace_peekuser;
+extern int ptrace_getregs;
+extern int ptrace_setregs;
+extern int ptrace_getfpregs;
+extern int ptrace_setfpregs;
+extern int ptrace_getfpxregs;
+extern int ptrace_setfpxregs;
+extern int ptrace_getvfpregs;
+extern int ptrace_setvfpregs;
+extern int ptrace_getsiginfo;
+extern int ptrace_setsiginfo;
+extern int ptrace_getregset;
+extern int ptrace_setregset;
+extern int ptrace_geteventmsg;
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+extern unsigned struct_shminfo_sz;
+extern unsigned struct_shm_info_sz;
+extern int shmctl_ipc_stat;
+extern int shmctl_ipc_info;
+extern int shmctl_shm_info;
+extern int shmctl_shm_stat;
+#endif
+
+#if !SANITIZER_APPLE && !SANITIZER_FREEBSD
+extern unsigned struct_utmp_sz;
+#endif
+#if !SANITIZER_ANDROID
+extern unsigned struct_utmpx_sz;
+#endif
+
+extern int map_fixed;
+
+// ioctl arguments
+struct __sanitizer_ifconf {
+ int ifc_len;
+ union {
+ void *ifcu_req;
+ } ifc_ifcu;
+#if SANITIZER_APPLE
+} __attribute__((packed));
+#else
+};
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+struct __sanitizer__obstack_chunk {
+ char *limit;
+ struct __sanitizer__obstack_chunk *prev;
+};
+
+struct __sanitizer_obstack {
+ long chunk_size;
+ struct __sanitizer__obstack_chunk *chunk;
+ char *object_base;
+ char *next_free;
+ uptr more_fields[7];
+};
+
+typedef uptr (*__sanitizer_cookie_io_read)(void *cookie, char *buf, uptr size);
+typedef uptr (*__sanitizer_cookie_io_write)(void *cookie, const char *buf,
+ uptr size);
+typedef int (*__sanitizer_cookie_io_seek)(void *cookie, u64 *offset,
+ int whence);
+typedef int (*__sanitizer_cookie_io_close)(void *cookie);
+
+struct __sanitizer_cookie_io_functions_t {
+ __sanitizer_cookie_io_read read;
+ __sanitizer_cookie_io_write write;
+ __sanitizer_cookie_io_seek seek;
+ __sanitizer_cookie_io_close close;
+};
+#endif
+
+#define IOC_NRBITS 8
+#define IOC_TYPEBITS 8
+#if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__) || \
+ defined(__sparc__)
+#define IOC_SIZEBITS 13
+#define IOC_DIRBITS 3
+#define IOC_NONE 1U
+#define IOC_WRITE 4U
+#define IOC_READ 2U
+#else
+#define IOC_SIZEBITS 14
+#define IOC_DIRBITS 2
+#define IOC_NONE 0U
+#define IOC_WRITE 1U
+#define IOC_READ 2U
+#endif
+#define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
+#define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
+#define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
+#if defined(IOC_DIRMASK)
+#undef IOC_DIRMASK
+#endif
+#define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
+#define IOC_NRSHIFT 0
+#define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
+#define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
+#define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
+#define EVIOC_EV_MAX 0x1f
+#define EVIOC_ABS_MAX 0x3f
+
+#define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
+#define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
+#define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
+
+#if defined(__sparc__)
+// In sparc the 14 bits SIZE field overlaps with the
+// least significant bit of DIR, so either IOC_READ or
+// IOC_WRITE shall be 1 in order to get a non-zero SIZE.
+#define IOC_SIZE(nr) \
+ ((((((nr) >> 29) & 0x7) & (4U | 2U)) == 0) ? 0 : (((nr) >> 16) & 0x3fff))
+#else
+#define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
+#endif
+
+extern unsigned struct_ifreq_sz;
+extern unsigned struct_termios_sz;
+extern unsigned struct_winsize_sz;
+
+#if SANITIZER_LINUX
+extern unsigned struct_arpreq_sz;
+extern unsigned struct_cdrom_msf_sz;
+extern unsigned struct_cdrom_multisession_sz;
+extern unsigned struct_cdrom_read_audio_sz;
+extern unsigned struct_cdrom_subchnl_sz;
+extern unsigned struct_cdrom_ti_sz;
+extern unsigned struct_cdrom_tocentry_sz;
+extern unsigned struct_cdrom_tochdr_sz;
+extern unsigned struct_cdrom_volctrl_sz;
+extern unsigned struct_ff_effect_sz;
+extern unsigned struct_floppy_drive_params_sz;
+extern unsigned struct_floppy_drive_struct_sz;
+extern unsigned struct_floppy_fdc_state_sz;
+extern unsigned struct_floppy_max_errors_sz;
+extern unsigned struct_floppy_raw_cmd_sz;
+extern unsigned struct_floppy_struct_sz;
+extern unsigned struct_floppy_write_errors_sz;
+extern unsigned struct_format_descr_sz;
+extern unsigned struct_hd_driveid_sz;
+extern unsigned struct_hd_geometry_sz;
+extern unsigned struct_input_absinfo_sz;
+extern unsigned struct_input_id_sz;
+extern unsigned struct_mtpos_sz;
+extern unsigned struct_termio_sz;
+extern unsigned struct_vt_consize_sz;
+extern unsigned struct_vt_sizes_sz;
+extern unsigned struct_vt_stat_sz;
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX
+extern unsigned struct_copr_buffer_sz;
+extern unsigned struct_copr_debug_buf_sz;
+extern unsigned struct_copr_msg_sz;
+extern unsigned struct_midi_info_sz;
+extern unsigned struct_mtget_sz;
+extern unsigned struct_mtop_sz;
+extern unsigned struct_rtentry_sz;
+extern unsigned struct_sbi_instrument_sz;
+extern unsigned struct_seq_event_rec_sz;
+extern unsigned struct_synth_info_sz;
+extern unsigned struct_vt_mode_sz;
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+extern unsigned struct_ax25_parms_struct_sz;
+extern unsigned struct_input_keymap_entry_sz;
+extern unsigned struct_ipx_config_data_sz;
+extern unsigned struct_kbdiacrs_sz;
+extern unsigned struct_kbentry_sz;
+extern unsigned struct_kbkeycode_sz;
+extern unsigned struct_kbsentry_sz;
+extern unsigned struct_mtconfiginfo_sz;
+extern unsigned struct_nr_parms_struct_sz;
+extern unsigned struct_scc_modem_sz;
+extern unsigned struct_scc_stat_sz;
+extern unsigned struct_serial_multiport_struct_sz;
+extern unsigned struct_serial_struct_sz;
+extern unsigned struct_sockaddr_ax25_sz;
+extern unsigned struct_unimapdesc_sz;
+extern unsigned struct_unimapinit_sz;
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+
+extern const unsigned long __sanitizer_bufsiz;
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+extern unsigned struct_audio_buf_info_sz;
+extern unsigned struct_ppp_stats_sz;
+#endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID
+
+#if !SANITIZER_ANDROID && !SANITIZER_APPLE
+extern unsigned struct_sioc_sg_req_sz;
+extern unsigned struct_sioc_vif_req_sz;
+#endif
+
+// ioctl request identifiers
+
+// A special value to mark ioctls that are not present on the target platform,
+// when it can not be determined without including any system headers.
+extern const unsigned IOCTL_NOT_PRESENT;
+
+extern unsigned IOCTL_FIOASYNC;
+extern unsigned IOCTL_FIOCLEX;
+extern unsigned IOCTL_FIOGETOWN;
+extern unsigned IOCTL_FIONBIO;
+extern unsigned IOCTL_FIONCLEX;
+extern unsigned IOCTL_FIOSETOWN;
+extern unsigned IOCTL_SIOCADDMULTI;
+extern unsigned IOCTL_SIOCATMARK;
+extern unsigned IOCTL_SIOCDELMULTI;
+extern unsigned IOCTL_SIOCGIFADDR;
+extern unsigned IOCTL_SIOCGIFBRDADDR;
+extern unsigned IOCTL_SIOCGIFCONF;
+extern unsigned IOCTL_SIOCGIFDSTADDR;
+extern unsigned IOCTL_SIOCGIFFLAGS;
+extern unsigned IOCTL_SIOCGIFMETRIC;
+extern unsigned IOCTL_SIOCGIFMTU;
+extern unsigned IOCTL_SIOCGIFNETMASK;
+extern unsigned IOCTL_SIOCGPGRP;
+extern unsigned IOCTL_SIOCSIFADDR;
+extern unsigned IOCTL_SIOCSIFBRDADDR;
+extern unsigned IOCTL_SIOCSIFDSTADDR;
+extern unsigned IOCTL_SIOCSIFFLAGS;
+extern unsigned IOCTL_SIOCSIFMETRIC;
+extern unsigned IOCTL_SIOCSIFMTU;
+extern unsigned IOCTL_SIOCSIFNETMASK;
+extern unsigned IOCTL_SIOCSPGRP;
+extern unsigned IOCTL_TIOCCONS;
+extern unsigned IOCTL_TIOCEXCL;
+extern unsigned IOCTL_TIOCGETD;
+extern unsigned IOCTL_TIOCGPGRP;
+extern unsigned IOCTL_TIOCGWINSZ;
+extern unsigned IOCTL_TIOCMBIC;
+extern unsigned IOCTL_TIOCMBIS;
+extern unsigned IOCTL_TIOCMGET;
+extern unsigned IOCTL_TIOCMSET;
+extern unsigned IOCTL_TIOCNOTTY;
+extern unsigned IOCTL_TIOCNXCL;
+extern unsigned IOCTL_TIOCOUTQ;
+extern unsigned IOCTL_TIOCPKT;
+extern unsigned IOCTL_TIOCSCTTY;
+extern unsigned IOCTL_TIOCSETD;
+extern unsigned IOCTL_TIOCSPGRP;
+extern unsigned IOCTL_TIOCSTI;
+extern unsigned IOCTL_TIOCSWINSZ;
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+extern unsigned IOCTL_SIOCGETSGCNT;
+extern unsigned IOCTL_SIOCGETVIFCNT;
+#endif
+#if SANITIZER_LINUX
+extern unsigned IOCTL_EVIOCGABS;
+extern unsigned IOCTL_EVIOCGBIT;
+extern unsigned IOCTL_EVIOCGEFFECTS;
+extern unsigned IOCTL_EVIOCGID;
+extern unsigned IOCTL_EVIOCGKEY;
+extern unsigned IOCTL_EVIOCGKEYCODE;
+extern unsigned IOCTL_EVIOCGLED;
+extern unsigned IOCTL_EVIOCGNAME;
+extern unsigned IOCTL_EVIOCGPHYS;
+extern unsigned IOCTL_EVIOCGRAB;
+extern unsigned IOCTL_EVIOCGREP;
+extern unsigned IOCTL_EVIOCGSND;
+extern unsigned IOCTL_EVIOCGSW;
+extern unsigned IOCTL_EVIOCGUNIQ;
+extern unsigned IOCTL_EVIOCGVERSION;
+extern unsigned IOCTL_EVIOCRMFF;
+extern unsigned IOCTL_EVIOCSABS;
+extern unsigned IOCTL_EVIOCSFF;
+extern unsigned IOCTL_EVIOCSKEYCODE;
+extern unsigned IOCTL_EVIOCSREP;
+extern unsigned IOCTL_BLKFLSBUF;
+extern unsigned IOCTL_BLKGETSIZE;
+extern unsigned IOCTL_BLKRAGET;
+extern unsigned IOCTL_BLKRASET;
+extern unsigned IOCTL_BLKROGET;
+extern unsigned IOCTL_BLKROSET;
+extern unsigned IOCTL_BLKRRPART;
+extern unsigned IOCTL_BLKFRASET;
+extern unsigned IOCTL_BLKFRAGET;
+extern unsigned IOCTL_BLKSECTSET;
+extern unsigned IOCTL_BLKSECTGET;
+extern unsigned IOCTL_BLKSSZGET;
+extern unsigned IOCTL_BLKBSZGET;
+extern unsigned IOCTL_BLKBSZSET;
+extern unsigned IOCTL_BLKGETSIZE64;
+extern unsigned IOCTL_CDROMAUDIOBUFSIZ;
+extern unsigned IOCTL_CDROMEJECT;
+extern unsigned IOCTL_CDROMEJECT_SW;
+extern unsigned IOCTL_CDROMMULTISESSION;
+extern unsigned IOCTL_CDROMPAUSE;
+extern unsigned IOCTL_CDROMPLAYMSF;
+extern unsigned IOCTL_CDROMPLAYTRKIND;
+extern unsigned IOCTL_CDROMREADAUDIO;
+extern unsigned IOCTL_CDROMREADCOOKED;
+extern unsigned IOCTL_CDROMREADMODE1;
+extern unsigned IOCTL_CDROMREADMODE2;
+extern unsigned IOCTL_CDROMREADRAW;
+extern unsigned IOCTL_CDROMREADTOCENTRY;
+extern unsigned IOCTL_CDROMREADTOCHDR;
+extern unsigned IOCTL_CDROMRESET;
+extern unsigned IOCTL_CDROMRESUME;
+extern unsigned IOCTL_CDROMSEEK;
+extern unsigned IOCTL_CDROMSTART;
+extern unsigned IOCTL_CDROMSTOP;
+extern unsigned IOCTL_CDROMSUBCHNL;
+extern unsigned IOCTL_CDROMVOLCTRL;
+extern unsigned IOCTL_CDROMVOLREAD;
+extern unsigned IOCTL_CDROM_GET_UPC;
+extern unsigned IOCTL_FDCLRPRM;
+extern unsigned IOCTL_FDDEFPRM;
+extern unsigned IOCTL_FDFLUSH;
+extern unsigned IOCTL_FDFMTBEG;
+extern unsigned IOCTL_FDFMTEND;
+extern unsigned IOCTL_FDFMTTRK;
+extern unsigned IOCTL_FDGETDRVPRM;
+extern unsigned IOCTL_FDGETDRVSTAT;
+extern unsigned IOCTL_FDGETDRVTYP;
+extern unsigned IOCTL_FDGETFDCSTAT;
+extern unsigned IOCTL_FDGETMAXERRS;
+extern unsigned IOCTL_FDGETPRM;
+extern unsigned IOCTL_FDMSGOFF;
+extern unsigned IOCTL_FDMSGON;
+extern unsigned IOCTL_FDPOLLDRVSTAT;
+extern unsigned IOCTL_FDRAWCMD;
+extern unsigned IOCTL_FDRESET;
+extern unsigned IOCTL_FDSETDRVPRM;
+extern unsigned IOCTL_FDSETEMSGTRESH;
+extern unsigned IOCTL_FDSETMAXERRS;
+extern unsigned IOCTL_FDSETPRM;
+extern unsigned IOCTL_FDTWADDLE;
+extern unsigned IOCTL_FDWERRORCLR;
+extern unsigned IOCTL_FDWERRORGET;
+extern unsigned IOCTL_HDIO_DRIVE_CMD;
+extern unsigned IOCTL_HDIO_GETGEO;
+extern unsigned IOCTL_HDIO_GET_32BIT;
+extern unsigned IOCTL_HDIO_GET_DMA;
+extern unsigned IOCTL_HDIO_GET_IDENTITY;
+extern unsigned IOCTL_HDIO_GET_KEEPSETTINGS;
+extern unsigned IOCTL_HDIO_GET_MULTCOUNT;
+extern unsigned IOCTL_HDIO_GET_NOWERR;
+extern unsigned IOCTL_HDIO_GET_UNMASKINTR;
+extern unsigned IOCTL_HDIO_SET_32BIT;
+extern unsigned IOCTL_HDIO_SET_DMA;
+extern unsigned IOCTL_HDIO_SET_KEEPSETTINGS;
+extern unsigned IOCTL_HDIO_SET_MULTCOUNT;
+extern unsigned IOCTL_HDIO_SET_NOWERR;
+extern unsigned IOCTL_HDIO_SET_UNMASKINTR;
+extern unsigned IOCTL_MTIOCPOS;
+extern unsigned IOCTL_PPPIOCGASYNCMAP;
+extern unsigned IOCTL_PPPIOCGDEBUG;
+extern unsigned IOCTL_PPPIOCGFLAGS;
+extern unsigned IOCTL_PPPIOCGUNIT;
+extern unsigned IOCTL_PPPIOCGXASYNCMAP;
+extern unsigned IOCTL_PPPIOCSASYNCMAP;
+extern unsigned IOCTL_PPPIOCSDEBUG;
+extern unsigned IOCTL_PPPIOCSFLAGS;
+extern unsigned IOCTL_PPPIOCSMAXCID;
+extern unsigned IOCTL_PPPIOCSMRU;
+extern unsigned IOCTL_PPPIOCSXASYNCMAP;
+extern unsigned IOCTL_SIOCDARP;
+extern unsigned IOCTL_SIOCDRARP;
+extern unsigned IOCTL_SIOCGARP;
+extern unsigned IOCTL_SIOCGIFENCAP;
+extern unsigned IOCTL_SIOCGIFHWADDR;
+extern unsigned IOCTL_SIOCGIFMAP;
+extern unsigned IOCTL_SIOCGIFMEM;
+extern unsigned IOCTL_SIOCGIFNAME;
+extern unsigned IOCTL_SIOCGIFSLAVE;
+extern unsigned IOCTL_SIOCGRARP;
+extern unsigned IOCTL_SIOCGSTAMP;
+extern unsigned IOCTL_SIOCSARP;
+extern unsigned IOCTL_SIOCSIFENCAP;
+extern unsigned IOCTL_SIOCSIFHWADDR;
+extern unsigned IOCTL_SIOCSIFLINK;
+extern unsigned IOCTL_SIOCSIFMAP;
+extern unsigned IOCTL_SIOCSIFMEM;
+extern unsigned IOCTL_SIOCSIFSLAVE;
+extern unsigned IOCTL_SIOCSRARP;
+extern unsigned IOCTL_SNDCTL_COPR_HALT;
+extern unsigned IOCTL_SNDCTL_COPR_LOAD;
+extern unsigned IOCTL_SNDCTL_COPR_RCODE;
+extern unsigned IOCTL_SNDCTL_COPR_RCVMSG;
+extern unsigned IOCTL_SNDCTL_COPR_RDATA;
+extern unsigned IOCTL_SNDCTL_COPR_RESET;
+extern unsigned IOCTL_SNDCTL_COPR_RUN;
+extern unsigned IOCTL_SNDCTL_COPR_SENDMSG;
+extern unsigned IOCTL_SNDCTL_COPR_WCODE;
+extern unsigned IOCTL_SNDCTL_COPR_WDATA;
+extern unsigned IOCTL_TCFLSH;
+extern unsigned IOCTL_TCGETA;
+extern unsigned IOCTL_TCGETS;
+extern unsigned IOCTL_TCSBRK;
+extern unsigned IOCTL_TCSBRKP;
+extern unsigned IOCTL_TCSETA;
+extern unsigned IOCTL_TCSETAF;
+extern unsigned IOCTL_TCSETAW;
+extern unsigned IOCTL_TCSETS;
+extern unsigned IOCTL_TCSETSF;
+extern unsigned IOCTL_TCSETSW;
+extern unsigned IOCTL_TCXONC;
+extern unsigned IOCTL_TIOCGLCKTRMIOS;
+extern unsigned IOCTL_TIOCGSOFTCAR;
+extern unsigned IOCTL_TIOCINQ;
+extern unsigned IOCTL_TIOCLINUX;
+extern unsigned IOCTL_TIOCSERCONFIG;
+extern unsigned IOCTL_TIOCSERGETLSR;
+extern unsigned IOCTL_TIOCSERGWILD;
+extern unsigned IOCTL_TIOCSERSWILD;
+extern unsigned IOCTL_TIOCSLCKTRMIOS;
+extern unsigned IOCTL_TIOCSSOFTCAR;
+extern unsigned IOCTL_VT_DISALLOCATE;
+extern unsigned IOCTL_VT_GETSTATE;
+extern unsigned IOCTL_VT_RESIZE;
+extern unsigned IOCTL_VT_RESIZEX;
+extern unsigned IOCTL_VT_SENDSIG;
+extern unsigned IOCTL_MTIOCGET;
+extern unsigned IOCTL_MTIOCTOP;
+extern unsigned IOCTL_SIOCADDRT;
+extern unsigned IOCTL_SIOCDELRT;
+extern unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE;
+extern unsigned IOCTL_SNDCTL_DSP_GETFMTS;
+extern unsigned IOCTL_SNDCTL_DSP_NONBLOCK;
+extern unsigned IOCTL_SNDCTL_DSP_POST;
+extern unsigned IOCTL_SNDCTL_DSP_RESET;
+extern unsigned IOCTL_SNDCTL_DSP_SETFMT;
+extern unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT;
+extern unsigned IOCTL_SNDCTL_DSP_SPEED;
+extern unsigned IOCTL_SNDCTL_DSP_STEREO;
+extern unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE;
+extern unsigned IOCTL_SNDCTL_DSP_SYNC;
+extern unsigned IOCTL_SNDCTL_FM_4OP_ENABLE;
+extern unsigned IOCTL_SNDCTL_FM_LOAD_INSTR;
+extern unsigned IOCTL_SNDCTL_MIDI_INFO;
+extern unsigned IOCTL_SNDCTL_MIDI_PRETIME;
+extern unsigned IOCTL_SNDCTL_SEQ_CTRLRATE;
+extern unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT;
+extern unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT;
+extern unsigned IOCTL_SNDCTL_SEQ_NRMIDIS;
+extern unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS;
+extern unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND;
+extern unsigned IOCTL_SNDCTL_SEQ_PANIC;
+extern unsigned IOCTL_SNDCTL_SEQ_PERCMODE;
+extern unsigned IOCTL_SNDCTL_SEQ_RESET;
+extern unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES;
+extern unsigned IOCTL_SNDCTL_SEQ_SYNC;
+extern unsigned IOCTL_SNDCTL_SEQ_TESTMIDI;
+extern unsigned IOCTL_SNDCTL_SEQ_THRESHOLD;
+extern unsigned IOCTL_SNDCTL_SYNTH_INFO;
+extern unsigned IOCTL_SNDCTL_SYNTH_MEMAVL;
+extern unsigned IOCTL_SNDCTL_TMR_CONTINUE;
+extern unsigned IOCTL_SNDCTL_TMR_METRONOME;
+extern unsigned IOCTL_SNDCTL_TMR_SELECT;
+extern unsigned IOCTL_SNDCTL_TMR_SOURCE;
+extern unsigned IOCTL_SNDCTL_TMR_START;
+extern unsigned IOCTL_SNDCTL_TMR_STOP;
+extern unsigned IOCTL_SNDCTL_TMR_TEMPO;
+extern unsigned IOCTL_SNDCTL_TMR_TIMEBASE;
+extern unsigned IOCTL_SOUND_MIXER_READ_ALTPCM;
+extern unsigned IOCTL_SOUND_MIXER_READ_BASS;
+extern unsigned IOCTL_SOUND_MIXER_READ_CAPS;
+extern unsigned IOCTL_SOUND_MIXER_READ_CD;
+extern unsigned IOCTL_SOUND_MIXER_READ_DEVMASK;
+extern unsigned IOCTL_SOUND_MIXER_READ_ENHANCE;
+extern unsigned IOCTL_SOUND_MIXER_READ_IGAIN;
+extern unsigned IOCTL_SOUND_MIXER_READ_IMIX;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE1;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE2;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE3;
+extern unsigned IOCTL_SOUND_MIXER_READ_LINE;
+extern unsigned IOCTL_SOUND_MIXER_READ_LOUD;
+extern unsigned IOCTL_SOUND_MIXER_READ_MIC;
+extern unsigned IOCTL_SOUND_MIXER_READ_MUTE;
+extern unsigned IOCTL_SOUND_MIXER_READ_OGAIN;
+extern unsigned IOCTL_SOUND_MIXER_READ_PCM;
+extern unsigned IOCTL_SOUND_MIXER_READ_RECLEV;
+extern unsigned IOCTL_SOUND_MIXER_READ_RECMASK;
+extern unsigned IOCTL_SOUND_MIXER_READ_RECSRC;
+extern unsigned IOCTL_SOUND_MIXER_READ_SPEAKER;
+extern unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS;
+extern unsigned IOCTL_SOUND_MIXER_READ_SYNTH;
+extern unsigned IOCTL_SOUND_MIXER_READ_TREBLE;
+extern unsigned IOCTL_SOUND_MIXER_READ_VOLUME;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_BASS;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_CD;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_IMIX;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE1;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE2;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE3;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_LOUD;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_MIC;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_MUTE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_PCM;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE;
+extern unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME;
+extern unsigned IOCTL_SOUND_PCM_READ_BITS;
+extern unsigned IOCTL_SOUND_PCM_READ_CHANNELS;
+extern unsigned IOCTL_SOUND_PCM_READ_FILTER;
+extern unsigned IOCTL_SOUND_PCM_READ_RATE;
+extern unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS;
+extern unsigned IOCTL_SOUND_PCM_WRITE_FILTER;
+extern unsigned IOCTL_VT_ACTIVATE;
+extern unsigned IOCTL_VT_GETMODE;
+extern unsigned IOCTL_VT_OPENQRY;
+extern unsigned IOCTL_VT_RELDISP;
+extern unsigned IOCTL_VT_SETMODE;
+extern unsigned IOCTL_VT_WAITACTIVE;
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+extern unsigned IOCTL_EQL_EMANCIPATE;
+extern unsigned IOCTL_EQL_ENSLAVE;
+extern unsigned IOCTL_EQL_GETMASTRCFG;
+extern unsigned IOCTL_EQL_GETSLAVECFG;
+extern unsigned IOCTL_EQL_SETMASTRCFG;
+extern unsigned IOCTL_EQL_SETSLAVECFG;
+extern unsigned IOCTL_EVIOCGKEYCODE_V2;
+extern unsigned IOCTL_EVIOCGPROP;
+extern unsigned IOCTL_EVIOCSKEYCODE_V2;
+extern unsigned IOCTL_FS_IOC_GETFLAGS;
+extern unsigned IOCTL_FS_IOC_GETVERSION;
+extern unsigned IOCTL_FS_IOC_SETFLAGS;
+extern unsigned IOCTL_FS_IOC_SETVERSION;
+extern unsigned IOCTL_GIO_CMAP;
+extern unsigned IOCTL_GIO_FONT;
+extern unsigned IOCTL_GIO_UNIMAP;
+extern unsigned IOCTL_GIO_UNISCRNMAP;
+extern unsigned IOCTL_KDADDIO;
+extern unsigned IOCTL_KDDELIO;
+extern unsigned IOCTL_KDGETKEYCODE;
+extern unsigned IOCTL_KDGKBDIACR;
+extern unsigned IOCTL_KDGKBENT;
+extern unsigned IOCTL_KDGKBLED;
+extern unsigned IOCTL_KDGKBMETA;
+extern unsigned IOCTL_KDGKBSENT;
+extern unsigned IOCTL_KDMAPDISP;
+extern unsigned IOCTL_KDSETKEYCODE;
+extern unsigned IOCTL_KDSIGACCEPT;
+extern unsigned IOCTL_KDSKBDIACR;
+extern unsigned IOCTL_KDSKBENT;
+extern unsigned IOCTL_KDSKBLED;
+extern unsigned IOCTL_KDSKBMETA;
+extern unsigned IOCTL_KDSKBSENT;
+extern unsigned IOCTL_KDUNMAPDISP;
+extern unsigned IOCTL_LPABORT;
+extern unsigned IOCTL_LPABORTOPEN;
+extern unsigned IOCTL_LPCAREFUL;
+extern unsigned IOCTL_LPCHAR;
+extern unsigned IOCTL_LPGETIRQ;
+extern unsigned IOCTL_LPGETSTATUS;
+extern unsigned IOCTL_LPRESET;
+extern unsigned IOCTL_LPSETIRQ;
+extern unsigned IOCTL_LPTIME;
+extern unsigned IOCTL_LPWAIT;
+extern unsigned IOCTL_MTIOCGETCONFIG;
+extern unsigned IOCTL_MTIOCSETCONFIG;
+extern unsigned IOCTL_PIO_CMAP;
+extern unsigned IOCTL_PIO_FONT;
+extern unsigned IOCTL_PIO_UNIMAP;
+extern unsigned IOCTL_PIO_UNIMAPCLR;
+extern unsigned IOCTL_PIO_UNISCRNMAP;
+extern unsigned IOCTL_SCSI_IOCTL_GET_IDLUN;
+extern unsigned IOCTL_SCSI_IOCTL_PROBE_HOST;
+extern unsigned IOCTL_SCSI_IOCTL_TAGGED_DISABLE;
+extern unsigned IOCTL_SCSI_IOCTL_TAGGED_ENABLE;
+extern unsigned IOCTL_SIOCAIPXITFCRT;
+extern unsigned IOCTL_SIOCAIPXPRISLT;
+extern unsigned IOCTL_SIOCAX25ADDUID;
+extern unsigned IOCTL_SIOCAX25DELUID;
+extern unsigned IOCTL_SIOCAX25GETPARMS;
+extern unsigned IOCTL_SIOCAX25GETUID;
+extern unsigned IOCTL_SIOCAX25NOUID;
+extern unsigned IOCTL_SIOCAX25SETPARMS;
+extern unsigned IOCTL_SIOCDEVPLIP;
+extern unsigned IOCTL_SIOCIPXCFGDATA;
+extern unsigned IOCTL_SIOCNRDECOBS;
+extern unsigned IOCTL_SIOCNRGETPARMS;
+extern unsigned IOCTL_SIOCNRRTCTL;
+extern unsigned IOCTL_SIOCNRSETPARMS;
+extern unsigned IOCTL_SNDCTL_DSP_GETISPACE;
+extern unsigned IOCTL_SNDCTL_DSP_GETOSPACE;
+extern unsigned IOCTL_TIOCGSERIAL;
+extern unsigned IOCTL_TIOCSERGETMULTI;
+extern unsigned IOCTL_TIOCSERSETMULTI;
+extern unsigned IOCTL_TIOCSSERIAL;
+extern unsigned IOCTL_GIO_SCRNMAP;
+extern unsigned IOCTL_KDDISABIO;
+extern unsigned IOCTL_KDENABIO;
+extern unsigned IOCTL_KDGETLED;
+extern unsigned IOCTL_KDGETMODE;
+extern unsigned IOCTL_KDGKBMODE;
+extern unsigned IOCTL_KDGKBTYPE;
+extern unsigned IOCTL_KDMKTONE;
+extern unsigned IOCTL_KDSETLED;
+extern unsigned IOCTL_KDSETMODE;
+extern unsigned IOCTL_KDSKBMODE;
+extern unsigned IOCTL_KIOCSOUND;
+extern unsigned IOCTL_PIO_SCRNMAP;
+#endif
+
+extern const int si_SEGV_MAPERR;
+extern const int si_SEGV_ACCERR;
+} // namespace __sanitizer
+
+#define CHECK_TYPE_SIZE(TYPE) \
+ COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
+
+#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \
+ COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \
+ sizeof(((CLASS *)NULL)->MEMBER)); \
+ COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
+ offsetof(CLASS, MEMBER))
+
+// For sigaction, which is a function and struct at the same time,
+// and thus requires explicit "struct" in sizeof() expression.
+#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
+ COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \
+ sizeof(((struct CLASS *)NULL)->MEMBER)); \
+ COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
+ offsetof(struct CLASS, MEMBER))
+
+#define SIGACTION_SYMNAME sigaction
+
+#endif // SANITIZER_LINUX || SANITIZER_APPLE
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.cpp
new file mode 100644
index 00000000000..f1391a16bf0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.cpp
@@ -0,0 +1,368 @@
+//===-- sanitizer_platform_limits_solaris.cpp -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer common code.
+//
+// Sizes and layouts of platform-specific Solaris data structures.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_SOLARIS
+#include <arpa/inet.h>
+#include <dirent.h>
+#include <glob.h>
+#include <grp.h>
+#include <ifaddrs.h>
+#include <limits.h>
+#include <link.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <netdb.h>
+#error #include <netinet/ip_mroute.h>
+#include <poll.h>
+#include <pthread.h>
+#include <pwd.h>
+#error #include <rpc/xdr.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stddef.h>
+#include <sys/ethernet.h>
+#include <sys/filio.h>
+#include <sys/ipc.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/mtio.h>
+#error #include <sys/ptyvar.h>
+#include <sys/resource.h>
+#include <sys/shm.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/statvfs.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <termios.h>
+#include <time.h>
+#include <utmp.h>
+#include <utmpx.h>
+#include <wchar.h>
+#include <wordexp.h>
+
+// Include these after system headers to avoid name clashes and ambiguities.
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform_limits_solaris.h"
+
+namespace __sanitizer {
+ unsigned struct_utsname_sz = sizeof(struct utsname);
+ unsigned struct_stat_sz = sizeof(struct stat);
+ unsigned struct_stat64_sz = sizeof(struct stat64);
+ unsigned struct_rusage_sz = sizeof(struct rusage);
+ unsigned struct_tm_sz = sizeof(struct tm);
+ unsigned struct_passwd_sz = sizeof(struct passwd);
+ unsigned struct_group_sz = sizeof(struct group);
+ unsigned siginfo_t_sz = sizeof(siginfo_t);
+ unsigned struct_sigaction_sz = sizeof(struct sigaction);
+ unsigned struct_stack_t_sz = sizeof(stack_t);
+ unsigned struct_itimerval_sz = sizeof(struct itimerval);
+ unsigned pthread_t_sz = sizeof(pthread_t);
+ unsigned pthread_mutex_t_sz = sizeof(pthread_mutex_t);
+ unsigned pthread_cond_t_sz = sizeof(pthread_cond_t);
+ unsigned pid_t_sz = sizeof(pid_t);
+ unsigned timeval_sz = sizeof(timeval);
+ unsigned uid_t_sz = sizeof(uid_t);
+ unsigned gid_t_sz = sizeof(gid_t);
+ unsigned mbstate_t_sz = sizeof(mbstate_t);
+ unsigned sigset_t_sz = sizeof(sigset_t);
+ unsigned struct_timezone_sz = sizeof(struct timezone);
+ unsigned struct_tms_sz = sizeof(struct tms);
+ unsigned struct_sigevent_sz = sizeof(struct sigevent);
+ unsigned struct_sched_param_sz = sizeof(struct sched_param);
+ unsigned struct_statfs_sz = sizeof(struct statfs);
+ unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
+ unsigned ucontext_t_sz(void *ctx) { return sizeof(ucontext_t); }
+ unsigned struct_timespec_sz = sizeof(struct timespec);
+#if SANITIZER_SOLARIS32
+ unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
+#endif
+ unsigned struct_statvfs_sz = sizeof(struct statvfs);
+
+ const uptr sig_ign = (uptr)SIG_IGN;
+ const uptr sig_dfl = (uptr)SIG_DFL;
+ const uptr sig_err = (uptr)SIG_ERR;
+ const uptr sa_siginfo = (uptr)SA_SIGINFO;
+
+ int shmctl_ipc_stat = (int)IPC_STAT;
+
+ unsigned struct_utmp_sz = sizeof(struct utmp);
+ unsigned struct_utmpx_sz = sizeof(struct utmpx);
+
+ int map_fixed = MAP_FIXED;
+
+ int af_inet = (int)AF_INET;
+ int af_inet6 = (int)AF_INET6;
+
+ uptr __sanitizer_in_addr_sz(int af) {
+ if (af == AF_INET)
+ return sizeof(struct in_addr);
+ else if (af == AF_INET6)
+ return sizeof(struct in6_addr);
+ else
+ return 0;
+ }
+
+ unsigned struct_ElfW_Phdr_sz = sizeof(ElfW(Phdr));
+
+ int glob_nomatch = GLOB_NOMATCH;
+ const int wordexp_wrde_dooffs = WRDE_DOOFFS;
+
+ unsigned path_max = PATH_MAX;
+
+ // ioctl arguments
+ unsigned struct_ifreq_sz = sizeof(struct ifreq);
+ unsigned struct_termios_sz = sizeof(struct termios);
+ unsigned struct_winsize_sz = sizeof(struct winsize);
+
+ unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
+ unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
+
+ const unsigned IOCTL_NOT_PRESENT = 0;
+
+ unsigned IOCTL_FIOASYNC = FIOASYNC;
+ unsigned IOCTL_FIOCLEX = FIOCLEX;
+ unsigned IOCTL_FIOGETOWN = FIOGETOWN;
+ unsigned IOCTL_FIONBIO = FIONBIO;
+ unsigned IOCTL_FIONCLEX = FIONCLEX;
+ unsigned IOCTL_FIOSETOWN = FIOSETOWN;
+ unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
+ unsigned IOCTL_SIOCATMARK = SIOCATMARK;
+ unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
+ unsigned IOCTL_SIOCGIFADDR = SIOCGIFADDR;
+ unsigned IOCTL_SIOCGIFBRDADDR = SIOCGIFBRDADDR;
+ unsigned IOCTL_SIOCGIFCONF = SIOCGIFCONF;
+ unsigned IOCTL_SIOCGIFDSTADDR = SIOCGIFDSTADDR;
+ unsigned IOCTL_SIOCGIFFLAGS = SIOCGIFFLAGS;
+ unsigned IOCTL_SIOCGIFMETRIC = SIOCGIFMETRIC;
+ unsigned IOCTL_SIOCGIFMTU = SIOCGIFMTU;
+ unsigned IOCTL_SIOCGIFNETMASK = SIOCGIFNETMASK;
+ unsigned IOCTL_SIOCGPGRP = SIOCGPGRP;
+ unsigned IOCTL_SIOCSIFADDR = SIOCSIFADDR;
+ unsigned IOCTL_SIOCSIFBRDADDR = SIOCSIFBRDADDR;
+ unsigned IOCTL_SIOCSIFDSTADDR = SIOCSIFDSTADDR;
+ unsigned IOCTL_SIOCSIFFLAGS = SIOCSIFFLAGS;
+ unsigned IOCTL_SIOCSIFMETRIC = SIOCSIFMETRIC;
+ unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
+ unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
+ unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
+ unsigned IOCTL_TIOCEXCL = TIOCEXCL;
+ unsigned IOCTL_TIOCGETD = TIOCGETD;
+ unsigned IOCTL_TIOCGPGRP = TIOCGPGRP;
+ unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ;
+ unsigned IOCTL_TIOCMBIC = TIOCMBIC;
+ unsigned IOCTL_TIOCMBIS = TIOCMBIS;
+ unsigned IOCTL_TIOCMGET = TIOCMGET;
+ unsigned IOCTL_TIOCMSET = TIOCMSET;
+ unsigned IOCTL_TIOCNOTTY = TIOCNOTTY;
+ unsigned IOCTL_TIOCNXCL = TIOCNXCL;
+ unsigned IOCTL_TIOCOUTQ = TIOCOUTQ;
+ unsigned IOCTL_TIOCPKT = TIOCPKT;
+ unsigned IOCTL_TIOCSCTTY = TIOCSCTTY;
+ unsigned IOCTL_TIOCSETD = TIOCSETD;
+ unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
+ unsigned IOCTL_TIOCSTI = TIOCSTI;
+ unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
+
+ unsigned IOCTL_MTIOCGET = MTIOCGET;
+ unsigned IOCTL_MTIOCTOP = MTIOCTOP;
+
+ const int si_SEGV_MAPERR = SEGV_MAPERR;
+ const int si_SEGV_ACCERR = SEGV_ACCERR;
+} // namespace __sanitizer
+
+using namespace __sanitizer;
+
+COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
+
+COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned));
+CHECK_TYPE_SIZE(pthread_key_t);
+
+// There are more undocumented fields in dl_phdr_info that we are not interested
+// in.
+COMPILER_CHECK(sizeof(__sanitizer_dl_phdr_info) <= sizeof(dl_phdr_info));
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_addr);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum);
+
+// There are additional fields we are not interested in.
+COMPILER_CHECK(sizeof(__sanitizer_glob_t) <= sizeof(glob_t));
+CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_offs);
+
+CHECK_TYPE_SIZE(addrinfo);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_flags);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_family);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_socktype);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_addrlen);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_canonname);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_addr);
+
+CHECK_TYPE_SIZE(hostent);
+CHECK_SIZE_AND_OFFSET(hostent, h_name);
+CHECK_SIZE_AND_OFFSET(hostent, h_aliases);
+CHECK_SIZE_AND_OFFSET(hostent, h_addrtype);
+CHECK_SIZE_AND_OFFSET(hostent, h_length);
+CHECK_SIZE_AND_OFFSET(hostent, h_addr_list);
+
+CHECK_TYPE_SIZE(iovec);
+CHECK_SIZE_AND_OFFSET(iovec, iov_base);
+CHECK_SIZE_AND_OFFSET(iovec, iov_len);
+
+CHECK_TYPE_SIZE(msghdr);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_name);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_namelen);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_iov);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_iovlen);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_control);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_controllen);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_flags);
+
+CHECK_TYPE_SIZE(cmsghdr);
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
+
+COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
+CHECK_SIZE_AND_OFFSET(dirent, d_ino);
+CHECK_SIZE_AND_OFFSET(dirent, d_off);
+CHECK_SIZE_AND_OFFSET(dirent, d_reclen);
+
+#if SANITIZER_SOLARIS32
+COMPILER_CHECK(sizeof(__sanitizer_dirent64) <= sizeof(dirent64));
+CHECK_SIZE_AND_OFFSET(dirent64, d_ino);
+CHECK_SIZE_AND_OFFSET(dirent64, d_off);
+CHECK_SIZE_AND_OFFSET(dirent64, d_reclen);
+#endif
+
+CHECK_TYPE_SIZE(ifconf);
+CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
+CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);
+
+CHECK_TYPE_SIZE(pollfd);
+CHECK_SIZE_AND_OFFSET(pollfd, fd);
+CHECK_SIZE_AND_OFFSET(pollfd, events);
+CHECK_SIZE_AND_OFFSET(pollfd, revents);
+
+CHECK_TYPE_SIZE(nfds_t);
+
+CHECK_TYPE_SIZE(sigset_t);
+
+COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction));
+// Can't write checks for sa_handler and sa_sigaction due to them being
+// preprocessor macros.
+CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
+CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_flags);
+
+CHECK_TYPE_SIZE(wordexp_t);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_offs);
+
+CHECK_TYPE_SIZE(tm);
+CHECK_SIZE_AND_OFFSET(tm, tm_sec);
+CHECK_SIZE_AND_OFFSET(tm, tm_min);
+CHECK_SIZE_AND_OFFSET(tm, tm_hour);
+CHECK_SIZE_AND_OFFSET(tm, tm_mday);
+CHECK_SIZE_AND_OFFSET(tm, tm_mon);
+CHECK_SIZE_AND_OFFSET(tm, tm_year);
+CHECK_SIZE_AND_OFFSET(tm, tm_wday);
+CHECK_SIZE_AND_OFFSET(tm, tm_yday);
+CHECK_SIZE_AND_OFFSET(tm, tm_isdst);
+
+CHECK_TYPE_SIZE(ether_addr);
+
+CHECK_TYPE_SIZE(ipc_perm);
+CHECK_SIZE_AND_OFFSET(ipc_perm, key);
+CHECK_SIZE_AND_OFFSET(ipc_perm, seq);
+CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
+CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
+
+CHECK_TYPE_SIZE(shmid_ds);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_perm);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_segsz);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_atime);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_dtime);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_ctime);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_cpid);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_lpid);
+CHECK_SIZE_AND_OFFSET(shmid_ds, shm_nattch);
+
+CHECK_TYPE_SIZE(clock_t);
+
+CHECK_TYPE_SIZE(ifaddrs);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_addr);
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_netmask);
+// Compare against the union, because we can't reach into the union in a
+// compliant way.
+#ifdef ifa_dstaddr
+#undef ifa_dstaddr
+#endif
+COMPILER_CHECK(sizeof(((__sanitizer_ifaddrs *)nullptr)->ifa_dstaddr) ==
+ sizeof(((ifaddrs *)nullptr)->ifa_ifu));
+COMPILER_CHECK(offsetof(__sanitizer_ifaddrs, ifa_dstaddr) ==
+ offsetof(ifaddrs, ifa_ifu));
+CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data);
+
+CHECK_TYPE_SIZE(timeb);
+CHECK_SIZE_AND_OFFSET(timeb, time);
+CHECK_SIZE_AND_OFFSET(timeb, millitm);
+CHECK_SIZE_AND_OFFSET(timeb, timezone);
+CHECK_SIZE_AND_OFFSET(timeb, dstflag);
+
+CHECK_TYPE_SIZE(passwd);
+CHECK_SIZE_AND_OFFSET(passwd, pw_name);
+CHECK_SIZE_AND_OFFSET(passwd, pw_passwd);
+CHECK_SIZE_AND_OFFSET(passwd, pw_uid);
+CHECK_SIZE_AND_OFFSET(passwd, pw_gid);
+CHECK_SIZE_AND_OFFSET(passwd, pw_dir);
+CHECK_SIZE_AND_OFFSET(passwd, pw_shell);
+
+CHECK_SIZE_AND_OFFSET(passwd, pw_gecos);
+
+CHECK_TYPE_SIZE(group);
+CHECK_SIZE_AND_OFFSET(group, gr_name);
+CHECK_SIZE_AND_OFFSET(group, gr_passwd);
+CHECK_SIZE_AND_OFFSET(group, gr_gid);
+CHECK_SIZE_AND_OFFSET(group, gr_mem);
+
+CHECK_TYPE_SIZE(XDR);
+CHECK_SIZE_AND_OFFSET(XDR, x_op);
+CHECK_SIZE_AND_OFFSET(XDR, x_ops);
+CHECK_SIZE_AND_OFFSET(XDR, x_public);
+CHECK_SIZE_AND_OFFSET(XDR, x_private);
+CHECK_SIZE_AND_OFFSET(XDR, x_base);
+CHECK_SIZE_AND_OFFSET(XDR, x_handy);
+COMPILER_CHECK(__sanitizer_XDR_ENCODE == XDR_ENCODE);
+COMPILER_CHECK(__sanitizer_XDR_DECODE == XDR_DECODE);
+COMPILER_CHECK(__sanitizer_XDR_FREE == XDR_FREE);
+
+CHECK_TYPE_SIZE(sem_t);
+
+#endif // SANITIZER_SOLARIS
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.h
new file mode 100644
index 00000000000..84a81265162
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.h
@@ -0,0 +1,496 @@
+//===-- sanitizer_platform_limits_solaris.h -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer common code.
+//
+// Sizes and layouts of platform-specific Solaris data structures.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_PLATFORM_LIMITS_SOLARIS_H
+#define SANITIZER_PLATFORM_LIMITS_SOLARIS_H
+
+#if SANITIZER_SOLARIS
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform.h"
+
+namespace __sanitizer {
+extern unsigned struct_utsname_sz;
+extern unsigned struct_stat_sz;
+extern unsigned struct_stat64_sz;
+extern unsigned struct_rusage_sz;
+extern unsigned siginfo_t_sz;
+extern unsigned struct_itimerval_sz;
+extern unsigned pthread_t_sz;
+extern unsigned pthread_mutex_t_sz;
+extern unsigned pthread_cond_t_sz;
+extern unsigned pid_t_sz;
+extern unsigned timeval_sz;
+extern unsigned uid_t_sz;
+extern unsigned gid_t_sz;
+extern unsigned mbstate_t_sz;
+extern unsigned struct_timezone_sz;
+extern unsigned struct_tms_sz;
+extern unsigned struct_itimerspec_sz;
+extern unsigned struct_sigevent_sz;
+extern unsigned struct_stack_t_sz;
+extern unsigned struct_sched_param_sz;
+extern unsigned struct_statfs64_sz;
+extern unsigned struct_statfs_sz;
+extern unsigned struct_sockaddr_sz;
+unsigned ucontext_t_sz(void *ctx);
+
+extern unsigned struct_timespec_sz;
+extern unsigned struct_rlimit_sz;
+extern unsigned struct_utimbuf_sz;
+
+struct __sanitizer_sem_t {
+ //u64 data[6];
+ u32 sem_count;
+ u16 sem_type;
+ u16 sem_magic;
+ u64 sem_pad1[3];
+ u64 sem_pad2[2];
+};
+
+struct __sanitizer_ipc_perm {
+ unsigned int uid; // uid_t
+ unsigned int gid; // gid_t
+ unsigned int cuid; // uid_t
+ unsigned int cgid; // gid_t
+ unsigned int mode; // mode_t
+ unsigned int seq; // uint_t
+ int key; // key_t
+#if !defined(_LP64)
+ int pad[4];
+#endif
+};
+
+struct __sanitizer_shmid_ds {
+ __sanitizer_ipc_perm shm_perm;
+ unsigned long shm_segsz; // size_t
+ unsigned long shm_flags; // uintptr_t
+ unsigned short shm_lkcnt; // ushort_t
+ int shm_lpid; // pid_t
+ int shm_cpid; // pid_t
+ unsigned long shm_nattch; // shmatt_t
+ unsigned long shm_cnattch; // ulong_t
+#if defined(_LP64)
+ long shm_atime; // time_t
+ long shm_dtime;
+ long shm_ctime;
+ void *shm_amp;
+ u64 shm_gransize; // uint64_t
+ u64 shm_allocated; // uint64_t
+ u64 shm_pad4[1]; // int64_t
+#else
+ long shm_atime; // time_t
+ int shm_pad1; // int32_t
+ long shm_dtime; // time_t
+ int shm_pad2; // int32_t
+ long shm_ctime; // time_t
+ void *shm_amp;
+ u64 shm_gransize; // uint64_t
+ u64 shm_allocated; // uint64_t
+#endif
+};
+
+extern unsigned struct_statvfs_sz;
+#if SANITIZER_SOLARIS32
+extern unsigned struct_statvfs64_sz;
+#endif
+
+struct __sanitizer_iovec {
+ void *iov_base;
+ uptr iov_len;
+};
+
+struct __sanitizer_ifaddrs {
+ struct __sanitizer_ifaddrs *ifa_next;
+ char *ifa_name;
+ u64 ifa_flags; // uint64_t
+ void *ifa_addr; // (struct sockaddr *)
+ void *ifa_netmask; // (struct sockaddr *)
+ // This is a union on Linux.
+# ifdef ifa_dstaddr
+# undef ifa_dstaddr
+# endif
+ void *ifa_dstaddr; // (struct sockaddr *)
+ void *ifa_data;
+};
+
+typedef unsigned __sanitizer_pthread_key_t;
+
+struct __sanitizer_XDR {
+ int x_op;
+ void *x_ops;
+ uptr x_public;
+ uptr x_private;
+ uptr x_base;
+ unsigned x_handy;
+};
+
+const int __sanitizer_XDR_ENCODE = 0;
+const int __sanitizer_XDR_DECODE = 1;
+const int __sanitizer_XDR_FREE = 2;
+
+struct __sanitizer_passwd {
+ char *pw_name;
+ char *pw_passwd;
+ unsigned int pw_uid; // uid_t
+ unsigned int pw_gid; // gid_t
+ char *pw_age;
+ char *pw_comment;
+ char *pw_gecos;
+ char *pw_dir;
+ char *pw_shell;
+};
+
+struct __sanitizer_group {
+ char *gr_name;
+ char *gr_passwd;
+ int gr_gid;
+ char **gr_mem;
+};
+
+typedef long __sanitizer_time_t;
+
+typedef long __sanitizer_suseconds_t;
+
+struct __sanitizer_timeval {
+ __sanitizer_time_t tv_sec;
+ __sanitizer_suseconds_t tv_usec;
+};
+
+struct __sanitizer_itimerval {
+ struct __sanitizer_timeval it_interval;
+ struct __sanitizer_timeval it_value;
+};
+
+struct __sanitizer_timeb {
+ __sanitizer_time_t time;
+ unsigned short millitm;
+ short timezone;
+ short dstflag;
+};
+
+struct __sanitizer_ether_addr {
+ u8 octet[6];
+};
+
+struct __sanitizer_tm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+};
+
+struct __sanitizer_msghdr {
+ void *msg_name;
+ unsigned msg_namelen;
+ struct __sanitizer_iovec *msg_iov;
+ unsigned msg_iovlen;
+ void *msg_control;
+ unsigned msg_controllen;
+ int msg_flags;
+};
+struct __sanitizer_cmsghdr {
+ unsigned cmsg_len;
+ int cmsg_level;
+ int cmsg_type;
+};
+
+#if SANITIZER_SOLARIS && (defined(_LP64) || _FILE_OFFSET_BITS == 64)
+struct __sanitizer_dirent {
+ unsigned long long d_ino;
+ long long d_off;
+ unsigned short d_reclen;
+ // more fields that we don't care about
+};
+#else
+struct __sanitizer_dirent {
+ unsigned long d_ino;
+ long d_off;
+ unsigned short d_reclen;
+ // more fields that we don't care about
+};
+#endif
+
+struct __sanitizer_dirent64 {
+ unsigned long long d_ino;
+ unsigned long long d_off;
+ unsigned short d_reclen;
+ // more fields that we don't care about
+};
+
+typedef long __sanitizer_clock_t;
+typedef int __sanitizer_clockid_t;
+
+// This thing depends on the platform. We are only interested in the upper
+// limit. Verified with a compiler assert in .cpp.
+union __sanitizer_pthread_attr_t {
+ char size[128];
+ void *align;
+};
+
+struct __sanitizer_sigset_t {
+ // uint32_t * 4
+ unsigned int __bits[4];
+};
+
+struct __sanitizer_siginfo {
+ // The size is determined by looking at sizeof of real siginfo_t on linux.
+ u64 opaque[128 / sizeof(u64)];
+};
+
+using __sanitizer_sighandler_ptr = void (*)(int sig);
+using __sanitizer_sigactionhandler_ptr =
+ void (*)(int sig, __sanitizer_siginfo *siginfo, void *uctx);
+
+struct __sanitizer_sigaction {
+ int sa_flags;
+ union {
+ __sanitizer_sigactionhandler_ptr sigaction;
+ __sanitizer_sighandler_ptr handler;
+ };
+ __sanitizer_sigset_t sa_mask;
+#if !defined(_LP64)
+ int sa_resv[2];
+#endif
+};
+
+struct __sanitizer_kernel_sigset_t {
+ u8 sig[8];
+};
+
+struct __sanitizer_kernel_sigaction_t {
+ union {
+ void (*handler)(int signo);
+ void (*sigaction)(int signo, __sanitizer_siginfo *info, void *ctx);
+ };
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+ __sanitizer_kernel_sigset_t sa_mask;
+};
+
+extern const uptr sig_ign;
+extern const uptr sig_dfl;
+extern const uptr sig_err;
+extern const uptr sa_siginfo;
+
+extern int af_inet;
+extern int af_inet6;
+uptr __sanitizer_in_addr_sz(int af);
+
+struct __sanitizer_dl_phdr_info {
+ uptr dlpi_addr;
+ const char *dlpi_name;
+ const void *dlpi_phdr;
+ short dlpi_phnum;
+};
+
+extern unsigned struct_ElfW_Phdr_sz;
+
+struct __sanitizer_addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+#if defined(__sparcv9)
+ int _ai_pad;
+#endif
+ unsigned ai_addrlen;
+ char *ai_canonname;
+ void *ai_addr;
+ struct __sanitizer_addrinfo *ai_next;
+};
+
+struct __sanitizer_hostent {
+ char *h_name;
+ char **h_aliases;
+ int h_addrtype;
+ int h_length;
+ char **h_addr_list;
+};
+
+struct __sanitizer_pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+typedef unsigned long __sanitizer_nfds_t;
+
+struct __sanitizer_glob_t {
+ uptr gl_pathc;
+ char **gl_pathv;
+ uptr gl_offs;
+ char **gl_pathp;
+ int gl_pathn;
+};
+
+extern int glob_nomatch;
+extern int glob_altdirfunc;
+extern const int wordexp_wrde_dooffs;
+
+extern unsigned path_max;
+
+struct __sanitizer_wordexp_t {
+ uptr we_wordc;
+ char **we_wordv;
+ uptr we_offs;
+ char **we_wordp;
+ int we_wordn;
+};
+
+typedef void __sanitizer_FILE;
+#define SANITIZER_HAS_STRUCT_FILE 0
+
+// This simplifies generic code
+#define struct_shminfo_sz -1
+#define struct_shm_info_sz -1
+#define shmctl_shm_stat -1
+#define shmctl_ipc_info -1
+#define shmctl_shm_info -1
+
+extern int shmctl_ipc_stat;
+
+extern unsigned struct_utmp_sz;
+extern unsigned struct_utmpx_sz;
+
+extern int map_fixed;
+
+// ioctl arguments
+struct __sanitizer_ifconf {
+ int ifc_len;
+ union {
+ void *ifcu_req;
+ } ifc_ifcu;
+};
+
+// <sys/ioccom.h>
+#define IOC_NRBITS 8
+#define IOC_TYPEBITS 8
+#define IOC_SIZEBITS 12
+#define IOC_DIRBITS 4
+#undef IOC_NONE
+#define IOC_NONE 2U // IOC_VOID
+#define IOC_READ 4U // IOC_OUT
+#define IOC_WRITE 8U // IOC_IN
+
+#define IOC_NRMASK ((1 << IOC_NRBITS) - 1)
+#define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1)
+#define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1)
+#define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1)
+#define IOC_NRSHIFT 0
+#define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS)
+#define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS)
+#define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS)
+
+#define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
+#define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
+#define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
+
+#if defined(__sparc__)
+// In sparc the 14 bits SIZE field overlaps with the
+// least significant bit of DIR, so either IOC_READ or
+// IOC_WRITE shall be 1 in order to get a non-zero SIZE.
+#define IOC_SIZE(nr) \
+ ((((((nr) >> 29) & 0x7) & (4U | 2U)) == 0) ? 0 : (((nr) >> 16) & 0x3fff))
+#else
+#define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
+#endif
+
+extern unsigned struct_ifreq_sz;
+extern unsigned struct_termios_sz;
+extern unsigned struct_winsize_sz;
+
+extern unsigned struct_sioc_sg_req_sz;
+extern unsigned struct_sioc_vif_req_sz;
+
+// ioctl request identifiers
+
+// A special value to mark ioctls that are not present on the target platform,
+// when it can not be determined without including any system headers.
+extern const unsigned IOCTL_NOT_PRESENT;
+
+extern unsigned IOCTL_FIOASYNC;
+extern unsigned IOCTL_FIOCLEX;
+extern unsigned IOCTL_FIOGETOWN;
+extern unsigned IOCTL_FIONBIO;
+extern unsigned IOCTL_FIONCLEX;
+extern unsigned IOCTL_FIOSETOWN;
+extern unsigned IOCTL_SIOCADDMULTI;
+extern unsigned IOCTL_SIOCATMARK;
+extern unsigned IOCTL_SIOCDELMULTI;
+extern unsigned IOCTL_SIOCGIFADDR;
+extern unsigned IOCTL_SIOCGIFBRDADDR;
+extern unsigned IOCTL_SIOCGIFCONF;
+extern unsigned IOCTL_SIOCGIFDSTADDR;
+extern unsigned IOCTL_SIOCGIFFLAGS;
+extern unsigned IOCTL_SIOCGIFMETRIC;
+extern unsigned IOCTL_SIOCGIFMTU;
+extern unsigned IOCTL_SIOCGIFNETMASK;
+extern unsigned IOCTL_SIOCGPGRP;
+extern unsigned IOCTL_SIOCSIFADDR;
+extern unsigned IOCTL_SIOCSIFBRDADDR;
+extern unsigned IOCTL_SIOCSIFDSTADDR;
+extern unsigned IOCTL_SIOCSIFFLAGS;
+extern unsigned IOCTL_SIOCSIFMETRIC;
+extern unsigned IOCTL_SIOCSIFMTU;
+extern unsigned IOCTL_SIOCSIFNETMASK;
+extern unsigned IOCTL_SIOCSPGRP;
+extern unsigned IOCTL_TIOCEXCL;
+extern unsigned IOCTL_TIOCGETD;
+extern unsigned IOCTL_TIOCGPGRP;
+extern unsigned IOCTL_TIOCGWINSZ;
+extern unsigned IOCTL_TIOCMBIC;
+extern unsigned IOCTL_TIOCMBIS;
+extern unsigned IOCTL_TIOCMGET;
+extern unsigned IOCTL_TIOCMSET;
+extern unsigned IOCTL_TIOCNOTTY;
+extern unsigned IOCTL_TIOCNXCL;
+extern unsigned IOCTL_TIOCOUTQ;
+extern unsigned IOCTL_TIOCPKT;
+extern unsigned IOCTL_TIOCSCTTY;
+extern unsigned IOCTL_TIOCSETD;
+extern unsigned IOCTL_TIOCSPGRP;
+extern unsigned IOCTL_TIOCSTI;
+extern unsigned IOCTL_TIOCSWINSZ;
+extern unsigned IOCTL_MTIOCGET;
+extern unsigned IOCTL_MTIOCTOP;
+
+extern const int si_SEGV_MAPERR;
+extern const int si_SEGV_ACCERR;
+} // namespace __sanitizer
+
+#define CHECK_TYPE_SIZE(TYPE) \
+ COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
+
+#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \
+ COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *) NULL)->MEMBER) == \
+ sizeof(((CLASS *) NULL)->MEMBER)); \
+ COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
+ offsetof(CLASS, MEMBER))
+
+// For sigaction, which is a function and struct at the same time,
+// and thus requires explicit "struct" in sizeof() expression.
+#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
+ COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *) NULL)->MEMBER) == \
+ sizeof(((struct CLASS *) NULL)->MEMBER)); \
+ COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
+ offsetof(struct CLASS, MEMBER))
+
+#endif // SANITIZER_SOLARIS
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_posix.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_posix.cpp
new file mode 100644
index 00000000000..75968ad33cc
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_posix.cpp
@@ -0,0 +1,410 @@
+//===-- sanitizer_posix.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries and implements POSIX-specific functions from
+// sanitizer_posix.h.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_POSIX
+
+#include "sanitizer_common.h"
+#include "sanitizer_file.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_posix.h"
+#include "sanitizer_procmaps.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/mman.h>
+
+#if SANITIZER_FREEBSD
+// The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
+// that, it was never implemented. So just define it to zero.
+#undef MAP_NORESERVE
+#define MAP_NORESERVE 0
+#endif
+
+namespace __sanitizer {
+
+// ------------- sanitizer_common.h
+uptr GetMmapGranularity() {
+ return GetPageSize();
+}
+
+bool ErrorIsOOM(error_t err) { return err == ENOMEM; }
+
+void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
+ size = RoundUpTo(size, GetPageSizeCached());
+ uptr res = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON, mem_type);
+ int reserrno;
+ if (UNLIKELY(internal_iserror(res, &reserrno)))
+ ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno, raw_report);
+ IncreaseTotalMmap(size);
+ return (void *)res;
+}
+
+void UnmapOrDie(void *addr, uptr size) {
+ if (!addr || !size) return;
+ uptr res = internal_munmap(addr, size);
+ if (UNLIKELY(internal_iserror(res))) {
+ Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n",
+ SanitizerToolName, size, size, addr);
+ CHECK("unable to unmap" && 0);
+ }
+ DecreaseTotalMmap(size);
+}
+
+void *MmapOrDieOnFatalError(uptr size, const char *mem_type) {
+ size = RoundUpTo(size, GetPageSizeCached());
+ uptr res = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON, mem_type);
+ int reserrno;
+ if (UNLIKELY(internal_iserror(res, &reserrno))) {
+ if (reserrno == ENOMEM)
+ return nullptr;
+ ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno);
+ }
+ IncreaseTotalMmap(size);
+ return (void *)res;
+}
+
+// We want to map a chunk of address space aligned to 'alignment'.
+// We do it by mapping a bit more and then unmapping redundant pieces.
+// We probably can do it with fewer syscalls in some OS-dependent way.
+void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
+ const char *mem_type) {
+ CHECK(IsPowerOfTwo(size));
+ CHECK(IsPowerOfTwo(alignment));
+ uptr map_size = size + alignment;
+ // mmap maps entire pages and rounds up map_size needs to be a an integral
+ // number of pages.
+ // We need to be aware of this size for calculating end and for unmapping
+ // fragments before and after the alignment region.
+ map_size = RoundUpTo(map_size, GetPageSizeCached());
+ uptr map_res = (uptr)MmapOrDieOnFatalError(map_size, mem_type);
+ if (UNLIKELY(!map_res))
+ return nullptr;
+ uptr res = map_res;
+ if (!IsAligned(res, alignment)) {
+ res = (map_res + alignment - 1) & ~(alignment - 1);
+ UnmapOrDie((void*)map_res, res - map_res);
+ }
+ uptr map_end = map_res + map_size;
+ uptr end = res + size;
+ end = RoundUpTo(end, GetPageSizeCached());
+ if (end != map_end) {
+ CHECK_LT(end, map_end);
+ UnmapOrDie((void*)end, map_end - end);
+ }
+ return (void*)res;
+}
+
+void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
+ size = RoundUpTo(size, GetPageSizeCached());
+ uptr p = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, mem_type);
+ int reserrno;
+ if (UNLIKELY(internal_iserror(p, &reserrno)))
+ ReportMmapFailureAndDie(size, mem_type, "allocate noreserve", reserrno);
+ IncreaseTotalMmap(size);
+ return (void *)p;
+}
+
+static void *MmapFixedImpl(uptr fixed_addr, uptr size, bool tolerate_enomem,
+ const char *name) {
+ size = RoundUpTo(size, GetPageSizeCached());
+ fixed_addr = RoundDownTo(fixed_addr, GetPageSizeCached());
+ uptr p = MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, name);
+ int reserrno;
+ if (UNLIKELY(internal_iserror(p, &reserrno))) {
+ if (tolerate_enomem && reserrno == ENOMEM)
+ return nullptr;
+ char mem_type[40];
+ internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
+ fixed_addr);
+ ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno);
+ }
+ IncreaseTotalMmap(size);
+ return (void *)p;
+}
+
+void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) {
+ return MmapFixedImpl(fixed_addr, size, false /*tolerate_enomem*/, name);
+}
+
+void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size, const char *name) {
+ return MmapFixedImpl(fixed_addr, size, true /*tolerate_enomem*/, name);
+}
+
+bool MprotectNoAccess(uptr addr, uptr size) {
+ return 0 == internal_mprotect((void*)addr, size, PROT_NONE);
+}
+
+bool MprotectReadOnly(uptr addr, uptr size) {
+ return 0 == internal_mprotect((void *)addr, size, PROT_READ);
+}
+
+#if !SANITIZER_APPLE
+void MprotectMallocZones(void *addr, int prot) {}
+#endif
+
+fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) {
+ if (ShouldMockFailureToOpen(filename))
+ return kInvalidFd;
+ int flags;
+ switch (mode) {
+ case RdOnly: flags = O_RDONLY; break;
+ case WrOnly: flags = O_WRONLY | O_CREAT | O_TRUNC; break;
+ case RdWr: flags = O_RDWR | O_CREAT; break;
+ }
+ fd_t res = internal_open(filename, flags, 0660);
+ if (internal_iserror(res, errno_p))
+ return kInvalidFd;
+ return ReserveStandardFds(res);
+}
+
+void CloseFile(fd_t fd) {
+ internal_close(fd);
+}
+
+bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read,
+ error_t *error_p) {
+ uptr res = internal_read(fd, buff, buff_size);
+ if (internal_iserror(res, error_p))
+ return false;
+ if (bytes_read)
+ *bytes_read = res;
+ return true;
+}
+
+bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written,
+ error_t *error_p) {
+ uptr res = internal_write(fd, buff, buff_size);
+ if (internal_iserror(res, error_p))
+ return false;
+ if (bytes_written)
+ *bytes_written = res;
+ return true;
+}
+
+void *MapFileToMemory(const char *file_name, uptr *buff_size) {
+ fd_t fd = OpenFile(file_name, RdOnly);
+ CHECK(fd != kInvalidFd);
+ uptr fsize = internal_filesize(fd);
+ CHECK_NE(fsize, (uptr)-1);
+ CHECK_GT(fsize, 0);
+ *buff_size = RoundUpTo(fsize, GetPageSizeCached());
+ uptr map = internal_mmap(nullptr, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ return internal_iserror(map) ? nullptr : (void *)map;
+}
+
+void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset) {
+ uptr flags = MAP_SHARED;
+ if (addr) flags |= MAP_FIXED;
+ uptr p = internal_mmap(addr, size, PROT_READ | PROT_WRITE, flags, fd, offset);
+ int mmap_errno = 0;
+ if (internal_iserror(p, &mmap_errno)) {
+ Printf("could not map writable file (%d, %lld, %zu): %zd, errno: %d\n",
+ fd, (long long)offset, size, p, mmap_errno);
+ return nullptr;
+ }
+ return (void *)p;
+}
+
+static inline bool IntervalsAreSeparate(uptr start1, uptr end1,
+ uptr start2, uptr end2) {
+ CHECK(start1 <= end1);
+ CHECK(start2 <= end2);
+ return (end1 < start2) || (end2 < start1);
+}
+
+// FIXME: this is thread-unsafe, but should not cause problems most of the time.
+// When the shadow is mapped only a single thread usually exists (plus maybe
+// several worker threads on Mac, which aren't expected to map big chunks of
+// memory).
+bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+ if (proc_maps.Error())
+ return true; // and hope for the best
+ MemoryMappedSegment segment;
+ while (proc_maps.Next(&segment)) {
+ if (segment.start == segment.end) continue; // Empty range.
+ CHECK_NE(0, segment.end);
+ if (!IntervalsAreSeparate(segment.start, segment.end - 1, range_start,
+ range_end))
+ return false;
+ }
+ return true;
+}
+
+#if !SANITIZER_APPLE
+void DumpProcessMap() {
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+ const sptr kBufSize = 4095;
+ char *filename = (char*)MmapOrDie(kBufSize, __func__);
+ MemoryMappedSegment segment(filename, kBufSize);
+ Report("Process memory map follows:\n");
+ while (proc_maps.Next(&segment)) {
+ Printf("\t%p-%p\t%s\n", (void *)segment.start, (void *)segment.end,
+ segment.filename);
+ }
+ Report("End of process memory map.\n");
+ UnmapOrDie(filename, kBufSize);
+}
+#endif
+
+const char *GetPwd() {
+ return GetEnv("PWD");
+}
+
+bool IsPathSeparator(const char c) {
+ return c == '/';
+}
+
+bool IsAbsolutePath(const char *path) {
+ return path != nullptr && IsPathSeparator(path[0]);
+}
+
+void ReportFile::Write(const char *buffer, uptr length) {
+ SpinMutexLock l(mu);
+ ReopenIfNecessary();
+ internal_write(fd, buffer, length);
+}
+
+bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) {
+ MemoryMappingLayout proc_maps(/*cache_enabled*/false);
+ InternalMmapVector<char> buff(kMaxPathLength);
+ MemoryMappedSegment segment(buff.data(), buff.size());
+ while (proc_maps.Next(&segment)) {
+ if (segment.IsExecutable() &&
+ internal_strcmp(module, segment.filename) == 0) {
+ *start = segment.start;
+ *end = segment.end;
+ return true;
+ }
+ }
+ return false;
+}
+
+uptr SignalContext::GetAddress() const {
+ auto si = static_cast<const siginfo_t *>(siginfo);
+ return (uptr)si->si_addr;
+}
+
+bool SignalContext::IsMemoryAccess() const {
+ auto si = static_cast<const siginfo_t *>(siginfo);
+ return si->si_signo == SIGSEGV || si->si_signo == SIGBUS;
+}
+
+int SignalContext::GetType() const {
+ return static_cast<const siginfo_t *>(siginfo)->si_signo;
+}
+
+const char *SignalContext::Describe() const {
+ switch (GetType()) {
+ case SIGFPE:
+ return "FPE";
+ case SIGILL:
+ return "ILL";
+ case SIGABRT:
+ return "ABRT";
+ case SIGSEGV:
+ return "SEGV";
+ case SIGBUS:
+ return "BUS";
+ case SIGTRAP:
+ return "TRAP";
+ }
+ return "UNKNOWN SIGNAL";
+}
+
+fd_t ReserveStandardFds(fd_t fd) {
+ CHECK_GE(fd, 0);
+ if (fd > 2)
+ return fd;
+ bool used[3];
+ internal_memset(used, 0, sizeof(used));
+ while (fd <= 2) {
+ used[fd] = true;
+ fd = internal_dup(fd);
+ }
+ for (int i = 0; i <= 2; ++i)
+ if (used[i])
+ internal_close(i);
+ return fd;
+}
+
+bool ShouldMockFailureToOpen(const char *path) {
+ return common_flags()->test_only_emulate_no_memorymap &&
+ internal_strncmp(path, "/proc/", 6) == 0;
+}
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO
+int GetNamedMappingFd(const char *name, uptr size, int *flags) {
+ if (!common_flags()->decorate_proc_maps || !name)
+ return -1;
+ char shmname[200];
+ CHECK(internal_strlen(name) < sizeof(shmname) - 10);
+ internal_snprintf(shmname, sizeof(shmname), "/dev/shm/%zu [%s]",
+ internal_getpid(), name);
+ int o_cloexec = 0;
+#if defined(O_CLOEXEC)
+ o_cloexec = O_CLOEXEC;
+#endif
+ int fd = ReserveStandardFds(
+ internal_open(shmname, O_RDWR | O_CREAT | O_TRUNC | o_cloexec, S_IRWXU));
+ CHECK_GE(fd, 0);
+ int res = internal_ftruncate(fd, size);
+#if !defined(O_CLOEXEC)
+ res = fcntl(fd, F_SETFD, FD_CLOEXEC);
+ CHECK_EQ(0, res);
+#endif
+ CHECK_EQ(0, res);
+ res = internal_unlink(shmname);
+ CHECK_EQ(0, res);
+ *flags &= ~(MAP_ANON | MAP_ANONYMOUS);
+ return fd;
+}
+#else
+int GetNamedMappingFd(const char *name, uptr size, int *flags) {
+ return -1;
+}
+#endif
+
+#if SANITIZER_ANDROID
+#define PR_SET_VMA 0x53564d41
+#define PR_SET_VMA_ANON_NAME 0
+void DecorateMapping(uptr addr, uptr size, const char *name) {
+ if (!common_flags()->decorate_proc_maps || !name)
+ return;
+ internal_prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, addr, size, (uptr)name);
+}
+#else
+void DecorateMapping(uptr addr, uptr size, const char *name) {
+}
+#endif
+
+uptr MmapNamed(void *addr, uptr length, int prot, int flags, const char *name) {
+ int fd = GetNamedMappingFd(name, length, &flags);
+ uptr res = internal_mmap(addr, length, prot, flags, fd, 0);
+ if (!internal_iserror(res))
+ DecorateMapping(res, length, name);
+ return res;
+}
+
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_POSIX
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_posix.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_posix.h
new file mode 100644
index 00000000000..f91e26e74b8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_posix.h
@@ -0,0 +1,128 @@
+//===-- sanitizer_posix.h -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries and declares some useful POSIX-specific functions.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_POSIX_H
+#define SANITIZER_POSIX_H
+
+// ----------- ATTENTION -------------
+// This header should NOT include any other headers from sanitizer runtime.
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform_limits_freebsd.h"
+#include "sanitizer_platform_limits_netbsd.h"
+#include "sanitizer_platform_limits_posix.h"
+#include "sanitizer_platform_limits_solaris.h"
+
+#if SANITIZER_POSIX
+
+namespace __sanitizer {
+
+// I/O
+// Don't use directly, use __sanitizer::OpenFile() instead.
+uptr internal_open(const char *filename, int flags);
+uptr internal_open(const char *filename, int flags, u32 mode);
+uptr internal_close(fd_t fd);
+
+uptr internal_read(fd_t fd, void *buf, uptr count);
+uptr internal_write(fd_t fd, const void *buf, uptr count);
+
+// Memory
+uptr internal_mmap(void *addr, uptr length, int prot, int flags,
+ int fd, u64 offset);
+uptr internal_munmap(void *addr, uptr length);
+#if SANITIZER_LINUX
+uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags,
+ void *new_address);
+#endif
+int internal_mprotect(void *addr, uptr length, int prot);
+int internal_madvise(uptr addr, uptr length, int advice);
+
+// OS
+uptr internal_filesize(fd_t fd); // -1 on error.
+uptr internal_stat(const char *path, void *buf);
+uptr internal_lstat(const char *path, void *buf);
+uptr internal_fstat(fd_t fd, void *buf);
+uptr internal_dup(int oldfd);
+uptr internal_dup2(int oldfd, int newfd);
+uptr internal_readlink(const char *path, char *buf, uptr bufsize);
+uptr internal_unlink(const char *path);
+uptr internal_rename(const char *oldpath, const char *newpath);
+uptr internal_lseek(fd_t fd, OFF_T offset, int whence);
+
+#if SANITIZER_NETBSD
+uptr internal_ptrace(int request, int pid, void *addr, int data);
+#else
+uptr internal_ptrace(int request, int pid, void *addr, void *data);
+#endif
+uptr internal_waitpid(int pid, int *status, int options);
+
+int internal_fork();
+fd_t internal_spawn(const char *argv[], const char *envp[], pid_t *pid);
+
+int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
+ uptr *oldlenp, const void *newp, uptr newlen);
+int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
+ const void *newp, uptr newlen);
+
+// These functions call appropriate pthread_ functions directly, bypassing
+// the interceptor. They are weak and may not be present in some tools.
+SANITIZER_WEAK_ATTRIBUTE
+int real_pthread_create(void *th, void *attr, void *(*callback)(void *),
+ void *param);
+SANITIZER_WEAK_ATTRIBUTE
+int real_pthread_join(void *th, void **ret);
+
+#define DEFINE_REAL_PTHREAD_FUNCTIONS \
+ namespace __sanitizer { \
+ int real_pthread_create(void *th, void *attr, void *(*callback)(void *), \
+ void *param) { \
+ return REAL(pthread_create)(th, attr, callback, param); \
+ } \
+ int real_pthread_join(void *th, void **ret) { \
+ return REAL(pthread_join(th, ret)); \
+ } \
+ } // namespace __sanitizer
+
+int my_pthread_attr_getstack(void *attr, void **addr, uptr *size);
+
+// A routine named real_sigaction() must be implemented by each sanitizer in
+// order for internal_sigaction() to bypass interceptors.
+int internal_sigaction(int signum, const void *act, void *oldact);
+void internal_sigfillset(__sanitizer_sigset_t *set);
+void internal_sigemptyset(__sanitizer_sigset_t *set);
+bool internal_sigismember(__sanitizer_sigset_t *set, int signum);
+
+uptr internal_execve(const char *filename, char *const argv[],
+ char *const envp[]);
+
+bool IsStateDetached(int state);
+
+// Move the fd out of {0, 1, 2} range.
+fd_t ReserveStandardFds(fd_t fd);
+
+bool ShouldMockFailureToOpen(const char *path);
+
+// Create a non-file mapping with a given /proc/self/maps name.
+uptr MmapNamed(void *addr, uptr length, int prot, int flags, const char *name);
+
+// Platforms should implement at most one of these.
+// 1. Provide a pre-decorated file descriptor to use instead of an anonymous
+// mapping.
+int GetNamedMappingFd(const char *name, uptr size, int *flags);
+// 2. Add name to an existing anonymous mapping. The caller must keep *name
+// alive at least as long as the mapping exists.
+void DecorateMapping(uptr addr, uptr size, const char *name);
+
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_POSIX
+
+#endif // SANITIZER_POSIX_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
new file mode 100644
index 00000000000..46e41c66973
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
@@ -0,0 +1,503 @@
+//===-- sanitizer_posix_libcdep.cpp ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries and implements libc-dependent POSIX-specific functions
+// from sanitizer_libc.h.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_POSIX
+
+#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_platform_limits_netbsd.h"
+#include "sanitizer_platform_limits_posix.h"
+#include "sanitizer_platform_limits_solaris.h"
+#include "sanitizer_posix.h"
+#include "sanitizer_procmaps.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#if SANITIZER_FREEBSD
+// The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
+// that, it was never implemented. So just define it to zero.
+#undef MAP_NORESERVE
+#define MAP_NORESERVE 0
+#endif
+
+typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
+
+namespace __sanitizer {
+
+u32 GetUid() {
+ return getuid();
+}
+
+uptr GetThreadSelf() {
+ return (uptr)pthread_self();
+}
+
+void ReleaseMemoryPagesToOS(uptr beg, uptr end) {
+ uptr page_size = GetPageSizeCached();
+ uptr beg_aligned = RoundUpTo(beg, page_size);
+ uptr end_aligned = RoundDownTo(end, page_size);
+ if (beg_aligned < end_aligned)
+ internal_madvise(beg_aligned, end_aligned - beg_aligned,
+ SANITIZER_MADVISE_DONTNEED);
+}
+
+void SetShadowRegionHugePageMode(uptr addr, uptr size) {
+#ifdef MADV_NOHUGEPAGE // May not be defined on old systems.
+ if (common_flags()->no_huge_pages_for_shadow)
+ internal_madvise(addr, size, MADV_NOHUGEPAGE);
+ else
+ internal_madvise(addr, size, MADV_HUGEPAGE);
+#endif // MADV_NOHUGEPAGE
+}
+
+bool DontDumpShadowMemory(uptr addr, uptr length) {
+#if defined(MADV_DONTDUMP)
+ return internal_madvise(addr, length, MADV_DONTDUMP) == 0;
+#elif defined(MADV_NOCORE)
+ return internal_madvise(addr, length, MADV_NOCORE) == 0;
+#else
+ return true;
+#endif // MADV_DONTDUMP
+}
+
+static rlim_t getlim(int res) {
+ rlimit rlim;
+ CHECK_EQ(0, getrlimit(res, &rlim));
+ return rlim.rlim_cur;
+}
+
+static void setlim(int res, rlim_t lim) {
+ struct rlimit rlim;
+ if (getrlimit(res, const_cast<struct rlimit *>(&rlim))) {
+ Report("ERROR: %s getrlimit() failed %d\n", SanitizerToolName, errno);
+ Die();
+ }
+ rlim.rlim_cur = lim;
+ if (setrlimit(res, const_cast<struct rlimit *>(&rlim))) {
+ Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno);
+ Die();
+ }
+}
+
+void DisableCoreDumperIfNecessary() {
+ if (common_flags()->disable_coredump) {
+ setlim(RLIMIT_CORE, 0);
+ }
+}
+
+bool StackSizeIsUnlimited() {
+ rlim_t stack_size = getlim(RLIMIT_STACK);
+ return (stack_size == RLIM_INFINITY);
+}
+
+void SetStackSizeLimitInBytes(uptr limit) {
+ setlim(RLIMIT_STACK, (rlim_t)limit);
+ CHECK(!StackSizeIsUnlimited());
+}
+
+bool AddressSpaceIsUnlimited() {
+ rlim_t as_size = getlim(RLIMIT_AS);
+ return (as_size == RLIM_INFINITY);
+}
+
+void SetAddressSpaceUnlimited() {
+ setlim(RLIMIT_AS, RLIM_INFINITY);
+ CHECK(AddressSpaceIsUnlimited());
+}
+
+void Abort() {
+#if !SANITIZER_GO
+ // If we are handling SIGABRT, unhandle it first.
+ // TODO(vitalybuka): Check if handler belongs to sanitizer.
+ if (GetHandleSignalMode(SIGABRT) != kHandleSignalNo) {
+ struct sigaction sigact;
+ internal_memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = SIG_DFL;
+ internal_sigaction(SIGABRT, &sigact, nullptr);
+ }
+#endif
+
+ abort();
+}
+
+int Atexit(void (*function)(void)) {
+#if !SANITIZER_GO
+ return atexit(function);
+#else
+ return 0;
+#endif
+}
+
+bool CreateDir(const char *pathname) { return mkdir(pathname, 0755) == 0; }
+
+bool SupportsColoredOutput(fd_t fd) {
+ return isatty(fd) != 0;
+}
+
+#if !SANITIZER_GO
+// TODO(glider): different tools may require different altstack size.
+static uptr GetAltStackSize() {
+ // Note: since GLIBC_2.31, SIGSTKSZ may be a function call, so this may be
+ // more costly that you think. However GetAltStackSize is only call 2-3 times
+ // per thread so don't cache the evaluation.
+ return SIGSTKSZ * 4;
+}
+
+void SetAlternateSignalStack() {
+ stack_t altstack, oldstack;
+ CHECK_EQ(0, sigaltstack(nullptr, &oldstack));
+ // If the alternate stack is already in place, do nothing.
+ // Android always sets an alternate stack, but it's too small for us.
+ if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) return;
+ // TODO(glider): the mapped stack should have the MAP_STACK flag in the
+ // future. It is not required by man 2 sigaltstack now (they're using
+ // malloc()).
+ altstack.ss_size = GetAltStackSize();
+ altstack.ss_sp = (char *)MmapOrDie(altstack.ss_size, __func__);
+ altstack.ss_flags = 0;
+ CHECK_EQ(0, sigaltstack(&altstack, nullptr));
+}
+
+void UnsetAlternateSignalStack() {
+ stack_t altstack, oldstack;
+ altstack.ss_sp = nullptr;
+ altstack.ss_flags = SS_DISABLE;
+ altstack.ss_size = GetAltStackSize(); // Some sane value required on Darwin.
+ CHECK_EQ(0, sigaltstack(&altstack, &oldstack));
+ UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
+}
+
+static void MaybeInstallSigaction(int signum,
+ SignalHandlerType handler) {
+ if (GetHandleSignalMode(signum) == kHandleSignalNo) return;
+
+ struct sigaction sigact;
+ internal_memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_sigaction = (sa_sigaction_t)handler;
+ // Do not block the signal from being received in that signal's handler.
+ // Clients are responsible for handling this correctly.
+ sigact.sa_flags = SA_SIGINFO | SA_NODEFER;
+ if (common_flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;
+ CHECK_EQ(0, internal_sigaction(signum, &sigact, nullptr));
+ VReport(1, "Installed the sigaction for signal %d\n", signum);
+}
+
+void InstallDeadlySignalHandlers(SignalHandlerType handler) {
+ // Set the alternate signal stack for the main thread.
+ // This will cause SetAlternateSignalStack to be called twice, but the stack
+ // will be actually set only once.
+ if (common_flags()->use_sigaltstack) SetAlternateSignalStack();
+ MaybeInstallSigaction(SIGSEGV, handler);
+ MaybeInstallSigaction(SIGBUS, handler);
+ MaybeInstallSigaction(SIGABRT, handler);
+ MaybeInstallSigaction(SIGFPE, handler);
+ MaybeInstallSigaction(SIGILL, handler);
+ MaybeInstallSigaction(SIGTRAP, handler);
+}
+
+bool SignalContext::IsStackOverflow() const {
+ // Access at a reasonable offset above SP, or slightly below it (to account
+ // for x86_64 or PowerPC redzone, ARM push of multiple registers, etc) is
+ // probably a stack overflow.
+#ifdef __s390__
+ // On s390, the fault address in siginfo points to start of the page, not
+ // to the precise word that was accessed. Mask off the low bits of sp to
+ // take it into account.
+ bool IsStackAccess = addr >= (sp & ~0xFFF) && addr < sp + 0xFFFF;
+#else
+ // Let's accept up to a page size away from top of stack. Things like stack
+ // probing can trigger accesses with such large offsets.
+ bool IsStackAccess = addr + GetPageSizeCached() > sp && addr < sp + 0xFFFF;
+#endif
+
+#if __powerpc__
+ // Large stack frames can be allocated with e.g.
+ // lis r0,-10000
+ // stdux r1,r1,r0 # store sp to [sp-10000] and update sp by -10000
+ // If the store faults then sp will not have been updated, so test above
+ // will not work, because the fault address will be more than just "slightly"
+ // below sp.
+ if (!IsStackAccess && IsAccessibleMemoryRange(pc, 4)) {
+ u32 inst = *(unsigned *)pc;
+ u32 ra = (inst >> 16) & 0x1F;
+ u32 opcd = inst >> 26;
+ u32 xo = (inst >> 1) & 0x3FF;
+ // Check for store-with-update to sp. The instructions we accept are:
+ // stbu rs,d(ra) stbux rs,ra,rb
+ // sthu rs,d(ra) sthux rs,ra,rb
+ // stwu rs,d(ra) stwux rs,ra,rb
+ // stdu rs,ds(ra) stdux rs,ra,rb
+ // where ra is r1 (the stack pointer).
+ if (ra == 1 &&
+ (opcd == 39 || opcd == 45 || opcd == 37 || opcd == 62 ||
+ (opcd == 31 && (xo == 247 || xo == 439 || xo == 183 || xo == 181))))
+ IsStackAccess = true;
+ }
+#endif // __powerpc__
+
+ // We also check si_code to filter out SEGV caused by something else other
+ // then hitting the guard page or unmapped memory, like, for example,
+ // unaligned memory access.
+ auto si = static_cast<const siginfo_t *>(siginfo);
+ return IsStackAccess &&
+ (si->si_code == si_SEGV_MAPERR || si->si_code == si_SEGV_ACCERR);
+}
+
+#endif // SANITIZER_GO
+
+bool IsAccessibleMemoryRange(uptr beg, uptr size) {
+ uptr page_size = GetPageSizeCached();
+ // Checking too large memory ranges is slow.
+ CHECK_LT(size, page_size * 10);
+ int sock_pair[2];
+ if (pipe(sock_pair))
+ return false;
+ uptr bytes_written =
+ internal_write(sock_pair[1], reinterpret_cast<void *>(beg), size);
+ int write_errno;
+ bool result;
+ if (internal_iserror(bytes_written, &write_errno)) {
+ CHECK_EQ(EFAULT, write_errno);
+ result = false;
+ } else {
+ result = (bytes_written == size);
+ }
+ internal_close(sock_pair[0]);
+ internal_close(sock_pair[1]);
+ return result;
+}
+
+void PlatformPrepareForSandboxing(void *args) {
+ // Some kinds of sandboxes may forbid filesystem access, so we won't be able
+ // to read the file mappings from /proc/self/maps. Luckily, neither the
+ // process will be able to load additional libraries, so it's fine to use the
+ // cached mappings.
+ MemoryMappingLayout::CacheMemoryMappings();
+}
+
+static bool MmapFixed(uptr fixed_addr, uptr size, int additional_flags,
+ const char *name) {
+ size = RoundUpTo(size, GetPageSizeCached());
+ fixed_addr = RoundDownTo(fixed_addr, GetPageSizeCached());
+ uptr p =
+ MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED | additional_flags | MAP_ANON, name);
+ int reserrno;
+ if (internal_iserror(p, &reserrno)) {
+ Report("ERROR: %s failed to "
+ "allocate 0x%zx (%zd) bytes at address %zx (errno: %d)\n",
+ SanitizerToolName, size, size, fixed_addr, reserrno);
+ return false;
+ }
+ IncreaseTotalMmap(size);
+ return true;
+}
+
+bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
+ return MmapFixed(fixed_addr, size, MAP_NORESERVE, name);
+}
+
+bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name) {
+#if SANITIZER_FREEBSD
+ if (common_flags()->no_huge_pages_for_shadow)
+ return MmapFixedNoReserve(fixed_addr, size, name);
+ // MAP_NORESERVE is implicit with FreeBSD
+ return MmapFixed(fixed_addr, size, MAP_ALIGNED_SUPER, name);
+#else
+ bool r = MmapFixedNoReserve(fixed_addr, size, name);
+ if (r)
+ SetShadowRegionHugePageMode(fixed_addr, size);
+ return r;
+#endif
+}
+
+uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) {
+ base_ = fixed_addr ? MmapFixedNoAccess(fixed_addr, size, name)
+ : MmapNoAccess(size);
+ size_ = size;
+ name_ = name;
+ (void)os_handle_; // unsupported
+ return reinterpret_cast<uptr>(base_);
+}
+
+// Uses fixed_addr for now.
+// Will use offset instead once we've implemented this function for real.
+uptr ReservedAddressRange::Map(uptr fixed_addr, uptr size, const char *name) {
+ return reinterpret_cast<uptr>(
+ MmapFixedOrDieOnFatalError(fixed_addr, size, name));
+}
+
+uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr size,
+ const char *name) {
+ return reinterpret_cast<uptr>(MmapFixedOrDie(fixed_addr, size, name));
+}
+
+void ReservedAddressRange::Unmap(uptr addr, uptr size) {
+ CHECK_LE(size, size_);
+ if (addr == reinterpret_cast<uptr>(base_))
+ // If we unmap the whole range, just null out the base.
+ base_ = (size == size_) ? nullptr : reinterpret_cast<void*>(addr + size);
+ else
+ CHECK_EQ(addr + size, reinterpret_cast<uptr>(base_) + size_);
+ size_ -= size;
+ UnmapOrDie(reinterpret_cast<void*>(addr), size);
+}
+
+void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) {
+ return (void *)MmapNamed((void *)fixed_addr, size, PROT_NONE,
+ MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANON,
+ name);
+}
+
+void *MmapNoAccess(uptr size) {
+ unsigned flags = MAP_PRIVATE | MAP_ANON | MAP_NORESERVE;
+ return (void *)internal_mmap(nullptr, size, PROT_NONE, flags, -1, 0);
+}
+
+// This function is defined elsewhere if we intercepted pthread_attr_getstack.
+extern "C" {
+SANITIZER_WEAK_ATTRIBUTE int
+real_pthread_attr_getstack(void *attr, void **addr, size_t *size);
+} // extern "C"
+
+int my_pthread_attr_getstack(void *attr, void **addr, uptr *size) {
+#if !SANITIZER_GO && !SANITIZER_APPLE
+ if (&real_pthread_attr_getstack)
+ return real_pthread_attr_getstack((pthread_attr_t *)attr, addr,
+ (size_t *)size);
+#endif
+ return pthread_attr_getstack((pthread_attr_t *)attr, addr, (size_t *)size);
+}
+
+#if !SANITIZER_GO
+void AdjustStackSize(void *attr_) {
+ pthread_attr_t *attr = (pthread_attr_t *)attr_;
+ uptr stackaddr = 0;
+ uptr stacksize = 0;
+ my_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize);
+ // GLibC will return (0 - stacksize) as the stack address in the case when
+ // stacksize is set, but stackaddr is not.
+ bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0);
+ // We place a lot of tool data into TLS, account for that.
+ const uptr minstacksize = GetTlsSize() + 128*1024;
+ if (stacksize < minstacksize) {
+ if (!stack_set) {
+ if (stacksize != 0) {
+ VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize,
+ minstacksize);
+ pthread_attr_setstacksize(attr, minstacksize);
+ }
+ } else {
+ Printf("Sanitizer: pre-allocated stack size is insufficient: "
+ "%zu < %zu\n", stacksize, minstacksize);
+ Printf("Sanitizer: pthread_create is likely to fail.\n");
+ }
+ }
+}
+#endif // !SANITIZER_GO
+
+pid_t StartSubprocess(const char *program, const char *const argv[],
+ const char *const envp[], fd_t stdin_fd, fd_t stdout_fd,
+ fd_t stderr_fd) {
+ auto file_closer = at_scope_exit([&] {
+ if (stdin_fd != kInvalidFd) {
+ internal_close(stdin_fd);
+ }
+ if (stdout_fd != kInvalidFd) {
+ internal_close(stdout_fd);
+ }
+ if (stderr_fd != kInvalidFd) {
+ internal_close(stderr_fd);
+ }
+ });
+
+ int pid = internal_fork();
+
+ if (pid < 0) {
+ int rverrno;
+ if (internal_iserror(pid, &rverrno)) {
+ Report("WARNING: failed to fork (errno %d)\n", rverrno);
+ }
+ return pid;
+ }
+
+ if (pid == 0) {
+ // Child subprocess
+ if (stdin_fd != kInvalidFd) {
+ internal_close(STDIN_FILENO);
+ internal_dup2(stdin_fd, STDIN_FILENO);
+ internal_close(stdin_fd);
+ }
+ if (stdout_fd != kInvalidFd) {
+ internal_close(STDOUT_FILENO);
+ internal_dup2(stdout_fd, STDOUT_FILENO);
+ internal_close(stdout_fd);
+ }
+ if (stderr_fd != kInvalidFd) {
+ internal_close(STDERR_FILENO);
+ internal_dup2(stderr_fd, STDERR_FILENO);
+ internal_close(stderr_fd);
+ }
+
+ for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--) internal_close(fd);
+
+ internal_execve(program, const_cast<char **>(&argv[0]),
+ const_cast<char *const *>(envp));
+ internal__exit(1);
+ }
+
+ return pid;
+}
+
+bool IsProcessRunning(pid_t pid) {
+ int process_status;
+ uptr waitpid_status = internal_waitpid(pid, &process_status, WNOHANG);
+ int local_errno;
+ if (internal_iserror(waitpid_status, &local_errno)) {
+ VReport(1, "Waiting on the process failed (errno %d).\n", local_errno);
+ return false;
+ }
+ return waitpid_status == 0;
+}
+
+int WaitForProcess(pid_t pid) {
+ int process_status;
+ uptr waitpid_status = internal_waitpid(pid, &process_status, 0);
+ int local_errno;
+ if (internal_iserror(waitpid_status, &local_errno)) {
+ VReport(1, "Waiting on the process failed (errno %d).\n", local_errno);
+ return -1;
+ }
+ return process_status;
+}
+
+bool IsStateDetached(int state) {
+ return state == PTHREAD_CREATE_DETACHED;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_POSIX
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_printf.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_printf.cpp
new file mode 100644
index 00000000000..3a9e366d2df
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_printf.cpp
@@ -0,0 +1,361 @@
+//===-- sanitizer_printf.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer.
+//
+// Internal printf function, used inside run-time libraries.
+// We can't use libc printf because we intercept some of the functions used
+// inside it.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_libc.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#if SANITIZER_WINDOWS && defined(_MSC_VER) && _MSC_VER < 1800 && \
+ !defined(va_copy)
+# define va_copy(dst, src) ((dst) = (src))
+#endif
+
+namespace __sanitizer {
+
+static int AppendChar(char **buff, const char *buff_end, char c) {
+ if (*buff < buff_end) {
+ **buff = c;
+ (*buff)++;
+ }
+ return 1;
+}
+
+// Appends number in a given base to buffer. If its length is less than
+// |minimal_num_length|, it is padded with leading zeroes or spaces, depending
+// on the value of |pad_with_zero|.
+static int AppendNumber(char **buff, const char *buff_end, u64 absolute_value,
+ u8 base, u8 minimal_num_length, bool pad_with_zero,
+ bool negative, bool uppercase) {
+ uptr const kMaxLen = 30;
+ RAW_CHECK(base == 10 || base == 16);
+ RAW_CHECK(base == 10 || !negative);
+ RAW_CHECK(absolute_value || !negative);
+ RAW_CHECK(minimal_num_length < kMaxLen);
+ int result = 0;
+ if (negative && minimal_num_length)
+ --minimal_num_length;
+ if (negative && pad_with_zero)
+ result += AppendChar(buff, buff_end, '-');
+ uptr num_buffer[kMaxLen];
+ int pos = 0;
+ do {
+ RAW_CHECK_MSG((uptr)pos < kMaxLen, "AppendNumber buffer overflow");
+ num_buffer[pos++] = absolute_value % base;
+ absolute_value /= base;
+ } while (absolute_value > 0);
+ if (pos < minimal_num_length) {
+ // Make sure compiler doesn't insert call to memset here.
+ internal_memset(&num_buffer[pos], 0,
+ sizeof(num_buffer[0]) * (minimal_num_length - pos));
+ pos = minimal_num_length;
+ }
+ RAW_CHECK(pos > 0);
+ pos--;
+ for (; pos >= 0 && num_buffer[pos] == 0; pos--) {
+ char c = (pad_with_zero || pos == 0) ? '0' : ' ';
+ result += AppendChar(buff, buff_end, c);
+ }
+ if (negative && !pad_with_zero) result += AppendChar(buff, buff_end, '-');
+ for (; pos >= 0; pos--) {
+ char digit = static_cast<char>(num_buffer[pos]);
+ digit = (digit < 10) ? '0' + digit : (uppercase ? 'A' : 'a') + digit - 10;
+ result += AppendChar(buff, buff_end, digit);
+ }
+ return result;
+}
+
+static int AppendUnsigned(char **buff, const char *buff_end, u64 num, u8 base,
+ u8 minimal_num_length, bool pad_with_zero,
+ bool uppercase) {
+ return AppendNumber(buff, buff_end, num, base, minimal_num_length,
+ pad_with_zero, false /* negative */, uppercase);
+}
+
+static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num,
+ u8 minimal_num_length, bool pad_with_zero) {
+ bool negative = (num < 0);
+ return AppendNumber(buff, buff_end, (u64)(negative ? -num : num), 10,
+ minimal_num_length, pad_with_zero, negative,
+ false /* uppercase */);
+}
+
+
+// Use the fact that explicitly requesting 0 width (%0s) results in UB and
+// interpret width == 0 as "no width requested":
+// width == 0 - no width requested
+// width < 0 - left-justify s within and pad it to -width chars, if necessary
+// width > 0 - right-justify s, not implemented yet
+static int AppendString(char **buff, const char *buff_end, int width,
+ int max_chars, const char *s) {
+ if (!s)
+ s = "<null>";
+ int result = 0;
+ for (; *s; s++) {
+ if (max_chars >= 0 && result >= max_chars)
+ break;
+ result += AppendChar(buff, buff_end, *s);
+ }
+ // Only the left justified strings are supported.
+ while (width < -result)
+ result += AppendChar(buff, buff_end, ' ');
+ return result;
+}
+
+static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
+ int result = 0;
+ result += AppendString(buff, buff_end, 0, -1, "0x");
+ result += AppendUnsigned(buff, buff_end, ptr_value, 16,
+ SANITIZER_POINTER_FORMAT_LENGTH,
+ true /* pad_with_zero */, false /* uppercase */);
+ return result;
+}
+
+int VSNPrintf(char *buff, int buff_length,
+ const char *format, va_list args) {
+ static const char *kPrintfFormatsHelp =
+ "Supported Printf formats: %([0-9]*)?(z|l|ll)?{d,u,x,X}; %p; "
+ "%[-]([0-9]*)?(\\.\\*)?s; %c\nProvided format: ";
+ RAW_CHECK(format);
+ RAW_CHECK(buff_length > 0);
+ const char *buff_end = &buff[buff_length - 1];
+ const char *cur = format;
+ int result = 0;
+ for (; *cur; cur++) {
+ if (*cur != '%') {
+ result += AppendChar(&buff, buff_end, *cur);
+ continue;
+ }
+ cur++;
+ bool left_justified = *cur == '-';
+ if (left_justified)
+ cur++;
+ bool have_width = (*cur >= '0' && *cur <= '9');
+ bool pad_with_zero = (*cur == '0');
+ int width = 0;
+ if (have_width) {
+ while (*cur >= '0' && *cur <= '9') {
+ width = width * 10 + *cur++ - '0';
+ }
+ }
+ bool have_precision = (cur[0] == '.' && cur[1] == '*');
+ int precision = -1;
+ if (have_precision) {
+ cur += 2;
+ precision = va_arg(args, int);
+ }
+ bool have_z = (*cur == 'z');
+ cur += have_z;
+ bool have_l = cur[0] == 'l' && cur[1] != 'l';
+ cur += have_l;
+ bool have_ll = cur[0] == 'l' && cur[1] == 'l';
+ cur += have_ll * 2;
+ const bool have_length = have_z || have_l || have_ll;
+ const bool have_flags = have_width || have_length;
+ // At the moment only %s supports precision and left-justification.
+ CHECK(!((precision >= 0 || left_justified) && *cur != 's'));
+ switch (*cur) {
+ case 'd': {
+ s64 dval = have_ll ? va_arg(args, s64)
+ : have_z ? va_arg(args, sptr)
+ : have_l ? va_arg(args, long)
+ : va_arg(args, int);
+ result += AppendSignedDecimal(&buff, buff_end, dval, width,
+ pad_with_zero);
+ break;
+ }
+ case 'u':
+ case 'x':
+ case 'X': {
+ u64 uval = have_ll ? va_arg(args, u64)
+ : have_z ? va_arg(args, uptr)
+ : have_l ? va_arg(args, unsigned long)
+ : va_arg(args, unsigned);
+ bool uppercase = (*cur == 'X');
+ result += AppendUnsigned(&buff, buff_end, uval, (*cur == 'u') ? 10 : 16,
+ width, pad_with_zero, uppercase);
+ break;
+ }
+ case 'p': {
+ RAW_CHECK_VA(!have_flags, kPrintfFormatsHelp, format);
+ result += AppendPointer(&buff, buff_end, va_arg(args, uptr));
+ break;
+ }
+ case 's': {
+ RAW_CHECK_VA(!have_length, kPrintfFormatsHelp, format);
+ // Only left-justified width is supported.
+ CHECK(!have_width || left_justified);
+ result += AppendString(&buff, buff_end, left_justified ? -width : width,
+ precision, va_arg(args, char*));
+ break;
+ }
+ case 'c': {
+ RAW_CHECK_VA(!have_flags, kPrintfFormatsHelp, format);
+ result += AppendChar(&buff, buff_end, va_arg(args, int));
+ break;
+ }
+ case '%' : {
+ RAW_CHECK_VA(!have_flags, kPrintfFormatsHelp, format);
+ result += AppendChar(&buff, buff_end, '%');
+ break;
+ }
+ default: {
+ RAW_CHECK_VA(false, kPrintfFormatsHelp, format);
+ }
+ }
+ }
+ RAW_CHECK(buff <= buff_end);
+ AppendChar(&buff, buff_end + 1, '\0');
+ return result;
+}
+
+static void (*PrintfAndReportCallback)(const char *);
+void SetPrintfAndReportCallback(void (*callback)(const char *)) {
+ PrintfAndReportCallback = callback;
+}
+
+// Can be overriden in frontend.
+#if SANITIZER_GO && defined(TSAN_EXTERNAL_HOOKS)
+// Implementation must be defined in frontend.
+extern "C" void __sanitizer_on_print(const char *str);
+#else
+SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_on_print, const char *str) {
+ (void)str;
+}
+#endif
+
+static void CallPrintfAndReportCallback(const char *str) {
+ __sanitizer_on_print(str);
+ if (PrintfAndReportCallback)
+ PrintfAndReportCallback(str);
+}
+
+static void NOINLINE SharedPrintfCodeNoBuffer(bool append_pid,
+ char *local_buffer,
+ int buffer_size,
+ const char *format,
+ va_list args) {
+ va_list args2;
+ va_copy(args2, args);
+ InternalMmapVector<char> v;
+ int needed_length = 0;
+ char *buffer = local_buffer;
+ // First try to print a message using a local buffer, and then fall back to
+ // mmaped buffer.
+ for (int use_mmap = 0;; use_mmap++) {
+ if (use_mmap) {
+ va_end(args);
+ va_copy(args, args2);
+ v.resize(needed_length + 1);
+ buffer_size = v.capacity();
+ v.resize(buffer_size);
+ buffer = &v[0];
+ }
+ needed_length = 0;
+ // Fuchsia's logging infrastructure always keeps track of the logging
+ // process, thread, and timestamp, so never prepend such information.
+ if (!SANITIZER_FUCHSIA && append_pid) {
+ int pid = internal_getpid();
+ const char *exe_name = GetProcessName();
+ if (common_flags()->log_exe_name && exe_name) {
+ needed_length += internal_snprintf(buffer, buffer_size,
+ "==%s", exe_name);
+ if (needed_length >= buffer_size)
+ continue;
+ }
+ needed_length += internal_snprintf(
+ buffer + needed_length, buffer_size - needed_length, "==%d==", pid);
+ if (needed_length >= buffer_size)
+ continue;
+ }
+ needed_length += VSNPrintf(buffer + needed_length,
+ buffer_size - needed_length, format, args);
+ if (needed_length >= buffer_size)
+ continue;
+ // If the message fit into the buffer, print it and exit.
+ break;
+ }
+ RawWrite(buffer);
+
+ // Remove color sequences from the message.
+ RemoveANSIEscapeSequencesFromString(buffer);
+ CallPrintfAndReportCallback(buffer);
+ LogMessageOnPrintf(buffer);
+
+ va_end(args2);
+}
+
+static void NOINLINE SharedPrintfCode(bool append_pid, const char *format,
+ va_list args) {
+ // |local_buffer| is small enough not to overflow the stack and/or violate
+ // the stack limit enforced by TSan (-Wframe-larger-than=512). On the other
+ // hand, the bigger the buffer is, the more the chance the error report will
+ // fit into it.
+ char local_buffer[400];
+ SharedPrintfCodeNoBuffer(append_pid, local_buffer, ARRAY_SIZE(local_buffer),
+ format, args);
+}
+
+void Printf(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ SharedPrintfCode(false, format, args);
+ va_end(args);
+}
+
+// Like Printf, but prints the current PID before the output string.
+void Report(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ SharedPrintfCode(true, format, args);
+ va_end(args);
+}
+
+// Writes at most "length" symbols to "buffer" (including trailing '\0').
+// Returns the number of symbols that should have been written to buffer
+// (not including trailing '\0'). Thus, the string is truncated
+// iff return value is not less than "length".
+int internal_snprintf(char *buffer, uptr length, const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ int needed_length = VSNPrintf(buffer, length, format, args);
+ va_end(args);
+ return needed_length;
+}
+
+void InternalScopedString::append(const char *format, ...) {
+ uptr prev_len = length();
+
+ while (true) {
+ buffer_.resize(buffer_.capacity());
+
+ va_list args;
+ va_start(args, format);
+ uptr sz = VSNPrintf(buffer_.data() + prev_len, buffer_.size() - prev_len,
+ format, args);
+ va_end(args);
+ if (sz < buffer_.size() - prev_len) {
+ buffer_.resize(prev_len + sz + 1);
+ break;
+ }
+
+ buffer_.reserve(buffer_.capacity() * 2);
+ }
+ CHECK_EQ(buffer_[length()], '\0');
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps.h
new file mode 100644
index 00000000000..19bad158387
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps.h
@@ -0,0 +1,110 @@
+//===-- sanitizer_procmaps.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer.
+//
+// Information about the process mappings.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_PROCMAPS_H
+#define SANITIZER_PROCMAPS_H
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
+ SANITIZER_APPLE || SANITIZER_SOLARIS || \
+ SANITIZER_FUCHSIA
+
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_fuchsia.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_mac.h"
+#include "sanitizer_mutex.h"
+
+namespace __sanitizer {
+
+// Memory protection masks.
+static const uptr kProtectionRead = 1;
+static const uptr kProtectionWrite = 2;
+static const uptr kProtectionExecute = 4;
+static const uptr kProtectionShared = 8;
+
+struct MemoryMappedSegmentData;
+
+class MemoryMappedSegment {
+ public:
+ explicit MemoryMappedSegment(char *buff = nullptr, uptr size = 0)
+ : filename(buff), filename_size(size), data_(nullptr) {}
+ ~MemoryMappedSegment() {}
+
+ bool IsReadable() const { return protection & kProtectionRead; }
+ bool IsWritable() const { return protection & kProtectionWrite; }
+ bool IsExecutable() const { return protection & kProtectionExecute; }
+ bool IsShared() const { return protection & kProtectionShared; }
+
+ void AddAddressRanges(LoadedModule *module);
+
+ uptr start;
+ uptr end;
+ uptr offset;
+ char *filename; // owned by caller
+ uptr filename_size;
+ uptr protection;
+ ModuleArch arch;
+ u8 uuid[kModuleUUIDSize];
+
+ private:
+ friend class MemoryMappingLayout;
+
+ // This field is assigned and owned by MemoryMappingLayout if needed
+ MemoryMappedSegmentData *data_;
+};
+
+class MemoryMappingLayoutBase {
+ public:
+ virtual bool Next(MemoryMappedSegment *segment) { UNIMPLEMENTED(); }
+ virtual bool Error() const { UNIMPLEMENTED(); };
+ virtual void Reset() { UNIMPLEMENTED(); }
+
+ protected:
+ ~MemoryMappingLayoutBase() {}
+};
+
+class MemoryMappingLayout final : public MemoryMappingLayoutBase {
+ public:
+ explicit MemoryMappingLayout(bool cache_enabled);
+ ~MemoryMappingLayout();
+ virtual bool Next(MemoryMappedSegment *segment) override;
+ virtual bool Error() const override;
+ virtual void Reset() override;
+ // In some cases, e.g. when running under a sandbox on Linux, ASan is unable
+ // to obtain the memory mappings. It should fall back to pre-cached data
+ // instead of aborting.
+ static void CacheMemoryMappings();
+
+ // Adds all mapped objects into a vector.
+ void DumpListOfModules(InternalMmapVectorNoCtor<LoadedModule> *modules);
+
+ private:
+ void LoadFromCache();
+
+ MemoryMappingLayoutData data_;
+};
+
+// Returns code range for the specified module.
+bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end);
+
+bool IsDecimal(char c);
+uptr ParseDecimal(const char **p);
+bool IsHex(char c);
+uptr ParseHex(const char **p);
+
+} // namespace __sanitizer
+
+#endif
+#endif // SANITIZER_PROCMAPS_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp
new file mode 100644
index 00000000000..36a82c4ac96
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp
@@ -0,0 +1,128 @@
+//===-- sanitizer_procmaps_bsd.cpp ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Information about the process mappings
+// (FreeBSD and NetBSD-specific parts).
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_FREEBSD || SANITIZER_NETBSD
+#include "sanitizer_common.h"
+#if SANITIZER_FREEBSD
+#include "sanitizer_freebsd.h"
+#endif
+#include "sanitizer_procmaps.h"
+
+// clang-format off
+#include <sys/types.h>
+#include <sys/sysctl.h>
+// clang-format on
+#include <unistd.h>
+#if SANITIZER_FREEBSD
+#include <sys/user.h>
+#endif
+
+#include <limits.h>
+
+// Fix 'kinfo_vmentry' definition on FreeBSD prior v9.2 in 32-bit mode.
+#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
+#include <osreldate.h>
+#if __FreeBSD_version <= 902001 // v9.2
+#define kinfo_vmentry xkinfo_vmentry
+#endif
+#endif
+
+namespace __sanitizer {
+
+#if SANITIZER_FREEBSD
+void GetMemoryProfile(fill_profile_f cb, uptr *stats) {
+ const int Mib[] = {
+ CTL_KERN,
+ KERN_PROC,
+ KERN_PROC_PID,
+ getpid()
+ };
+
+ struct kinfo_proc InfoProc;
+ uptr Len = sizeof(InfoProc);
+ CHECK_EQ(internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)&InfoProc, &Len, 0), 0);
+ cb(0, InfoProc.ki_rssize * GetPageSizeCached(), false, stats);
+}
+#endif
+
+void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
+ const int Mib[] = {
+#if SANITIZER_FREEBSD
+ CTL_KERN,
+ KERN_PROC,
+ KERN_PROC_VMMAP,
+ getpid()
+#elif SANITIZER_NETBSD
+ CTL_VM,
+ VM_PROC,
+ VM_PROC_MAP,
+ getpid(),
+ sizeof(struct kinfo_vmentry)
+#else
+#error "not supported"
+#endif
+ };
+
+ uptr Size = 0;
+ int Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), NULL, &Size, NULL, 0);
+ CHECK_EQ(Err, 0);
+ CHECK_GT(Size, 0);
+
+ size_t MmapedSize = Size * 4 / 3;
+ void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()");
+ Size = MmapedSize;
+ Err = internal_sysctl(Mib, ARRAY_SIZE(Mib), VmMap, &Size, NULL, 0);
+ CHECK_EQ(Err, 0);
+ proc_maps->data = (char *)VmMap;
+ proc_maps->mmaped_size = MmapedSize;
+ proc_maps->len = Size;
+}
+
+bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
+ CHECK(!Error()); // can not fail
+ char *last = data_.proc_self_maps.data + data_.proc_self_maps.len;
+ if (data_.current >= last)
+ return false;
+ const struct kinfo_vmentry *VmEntry =
+ (const struct kinfo_vmentry *)data_.current;
+
+ segment->start = (uptr)VmEntry->kve_start;
+ segment->end = (uptr)VmEntry->kve_end;
+ segment->offset = (uptr)VmEntry->kve_offset;
+
+ segment->protection = 0;
+ if ((VmEntry->kve_protection & KVME_PROT_READ) != 0)
+ segment->protection |= kProtectionRead;
+ if ((VmEntry->kve_protection & KVME_PROT_WRITE) != 0)
+ segment->protection |= kProtectionWrite;
+ if ((VmEntry->kve_protection & KVME_PROT_EXEC) != 0)
+ segment->protection |= kProtectionExecute;
+
+ if (segment->filename != NULL && segment->filename_size > 0) {
+ internal_snprintf(segment->filename,
+ Min(segment->filename_size, (uptr)PATH_MAX), "%s",
+ VmEntry->kve_path);
+ }
+
+#if SANITIZER_FREEBSD
+ data_.current += VmEntry->kve_structsize;
+#else
+ data_.current += sizeof(*VmEntry);
+#endif
+
+ return true;
+}
+
+} // namespace __sanitizer
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_common.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_common.cpp
new file mode 100644
index 00000000000..a7805ad1b08
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_common.cpp
@@ -0,0 +1,192 @@
+//===-- sanitizer_procmaps_common.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Information about the process mappings (common parts).
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
+ SANITIZER_SOLARIS
+
+#include "sanitizer_common.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_procmaps.h"
+
+namespace __sanitizer {
+
+static ProcSelfMapsBuff cached_proc_self_maps;
+static StaticSpinMutex cache_lock;
+
+static int TranslateDigit(char c) {
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+}
+
+// Parse a number and promote 'p' up to the first non-digit character.
+static uptr ParseNumber(const char **p, int base) {
+ uptr n = 0;
+ int d;
+ CHECK(base >= 2 && base <= 16);
+ while ((d = TranslateDigit(**p)) >= 0 && d < base) {
+ n = n * base + d;
+ (*p)++;
+ }
+ return n;
+}
+
+bool IsDecimal(char c) {
+ int d = TranslateDigit(c);
+ return d >= 0 && d < 10;
+}
+
+uptr ParseDecimal(const char **p) {
+ return ParseNumber(p, 10);
+}
+
+bool IsHex(char c) {
+ int d = TranslateDigit(c);
+ return d >= 0 && d < 16;
+}
+
+uptr ParseHex(const char **p) {
+ return ParseNumber(p, 16);
+}
+
+void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
+ // data_ should be unused on this platform
+ CHECK(!data_);
+ module->addAddressRange(start, end, IsExecutable(), IsWritable());
+}
+
+MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
+ // FIXME: in the future we may want to cache the mappings on demand only.
+ if (cache_enabled)
+ CacheMemoryMappings();
+
+ // Read maps after the cache update to capture the maps/unmaps happening in
+ // the process of updating.
+ ReadProcMaps(&data_.proc_self_maps);
+ if (cache_enabled && data_.proc_self_maps.mmaped_size == 0)
+ LoadFromCache();
+
+ Reset();
+}
+
+bool MemoryMappingLayout::Error() const {
+ return data_.current == nullptr;
+}
+
+MemoryMappingLayout::~MemoryMappingLayout() {
+ // Only unmap the buffer if it is different from the cached one. Otherwise
+ // it will be unmapped when the cache is refreshed.
+ if (data_.proc_self_maps.data != cached_proc_self_maps.data)
+ UnmapOrDie(data_.proc_self_maps.data, data_.proc_self_maps.mmaped_size);
+}
+
+void MemoryMappingLayout::Reset() {
+ data_.current = data_.proc_self_maps.data;
+}
+
+// static
+void MemoryMappingLayout::CacheMemoryMappings() {
+ ProcSelfMapsBuff new_proc_self_maps;
+ ReadProcMaps(&new_proc_self_maps);
+ // Don't invalidate the cache if the mappings are unavailable.
+ if (new_proc_self_maps.mmaped_size == 0)
+ return;
+ SpinMutexLock l(&cache_lock);
+ if (cached_proc_self_maps.mmaped_size)
+ UnmapOrDie(cached_proc_self_maps.data, cached_proc_self_maps.mmaped_size);
+ cached_proc_self_maps = new_proc_self_maps;
+}
+
+void MemoryMappingLayout::LoadFromCache() {
+ SpinMutexLock l(&cache_lock);
+ if (cached_proc_self_maps.data)
+ data_.proc_self_maps = cached_proc_self_maps;
+}
+
+void MemoryMappingLayout::DumpListOfModules(
+ InternalMmapVectorNoCtor<LoadedModule> *modules) {
+ Reset();
+ InternalMmapVector<char> module_name(kMaxPathLength);
+ MemoryMappedSegment segment(module_name.data(), module_name.size());
+ for (uptr i = 0; Next(&segment); i++) {
+ const char *cur_name = segment.filename;
+ if (cur_name[0] == '\0')
+ continue;
+ // Don't subtract 'cur_beg' from the first entry:
+ // * If a binary is compiled w/o -pie, then the first entry in
+ // process maps is likely the binary itself (all dynamic libs
+ // are mapped higher in address space). For such a binary,
+ // instruction offset in binary coincides with the actual
+ // instruction address in virtual memory (as code section
+ // is mapped to a fixed memory range).
+ // * If a binary is compiled with -pie, all the modules are
+ // mapped high at address space (in particular, higher than
+ // shadow memory of the tool), so the module can't be the
+ // first entry.
+ uptr base_address = (i ? segment.start : 0) - segment.offset;
+ LoadedModule cur_module;
+ cur_module.set(cur_name, base_address);
+ segment.AddAddressRanges(&cur_module);
+ modules->push_back(cur_module);
+ }
+}
+
+#if SANITIZER_LINUX || SANITIZER_ANDROID || SANITIZER_SOLARIS || SANITIZER_NETBSD
+void GetMemoryProfile(fill_profile_f cb, uptr *stats) {
+ char *smaps = nullptr;
+ uptr smaps_cap = 0;
+ uptr smaps_len = 0;
+ if (!ReadFileToBuffer("/proc/self/smaps", &smaps, &smaps_cap, &smaps_len))
+ return;
+ ParseUnixMemoryProfile(cb, stats, smaps, smaps_len);
+ UnmapOrDie(smaps, smaps_cap);
+}
+
+void ParseUnixMemoryProfile(fill_profile_f cb, uptr *stats, char *smaps,
+ uptr smaps_len) {
+ uptr start = 0;
+ bool file = false;
+ const char *pos = smaps;
+ char *end = smaps + smaps_len;
+ if (smaps_len < 2)
+ return;
+ // The following parsing can crash on almost every line
+ // in the case of malformed/truncated input.
+ // Fixing that is hard b/c e.g. ParseDecimal does not
+ // even accept end of the buffer and assumes well-formed input.
+ // So instead we patch end of the input a bit,
+ // it does not affect well-formed complete inputs.
+ *--end = 0;
+ *--end = '\n';
+ while (pos < end) {
+ if (IsHex(pos[0])) {
+ start = ParseHex(&pos);
+ for (; *pos != '/' && *pos > '\n'; pos++) {}
+ file = *pos == '/';
+ } else if (internal_strncmp(pos, "Rss:", 4) == 0) {
+ while (pos < end && !IsDecimal(*pos)) pos++;
+ uptr rss = ParseDecimal(&pos) * 1024;
+ cb(start, rss, file, stats);
+ }
+ while (*pos++ != '\n') {}
+ }
+}
+#endif
+
+} // namespace __sanitizer
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_fuchsia.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_fuchsia.cpp
new file mode 100644
index 00000000000..815de7e6c71
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_fuchsia.cpp
@@ -0,0 +1,80 @@
+//===-- sanitizer_procmaps_fuchsia.cpp
+//----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Information about the process mappings (Fuchsia-specific parts).
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_FUCHSIA
+#error #include <zircon/process.h>
+#error #include <zircon/syscalls.h>
+
+#include "sanitizer_common.h"
+#include "sanitizer_procmaps.h"
+
+namespace __sanitizer {
+
+// The cache flag is ignored on Fuchsia because a process can always get this
+// information via its process-self handle.
+MemoryMappingLayout::MemoryMappingLayout(bool) { Reset(); }
+
+void MemoryMappingLayout::Reset() {
+ data_.data.clear();
+ data_.current = 0;
+
+ size_t count;
+ zx_status_t status = _zx_object_get_info(
+ _zx_process_self(), ZX_INFO_PROCESS_MAPS, nullptr, 0, nullptr, &count);
+ if (status != ZX_OK) {
+ return;
+ }
+
+ size_t filled;
+ do {
+ data_.data.resize(count);
+ status = _zx_object_get_info(
+ _zx_process_self(), ZX_INFO_PROCESS_MAPS, data_.data.data(),
+ count * sizeof(zx_info_maps_t), &filled, &count);
+ if (status != ZX_OK) {
+ data_.data.clear();
+ return;
+ }
+ } while (filled < count);
+}
+
+MemoryMappingLayout::~MemoryMappingLayout() {}
+
+bool MemoryMappingLayout::Error() const { return data_.data.empty(); }
+
+bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
+ while (data_.current < data_.data.size()) {
+ const auto &entry = data_.data[data_.current++];
+ if (entry.type == ZX_INFO_MAPS_TYPE_MAPPING) {
+ segment->start = entry.base;
+ segment->end = entry.base + entry.size;
+ segment->offset = entry.u.mapping.vmo_offset;
+ const auto flags = entry.u.mapping.mmu_flags;
+ segment->protection =
+ ((flags & ZX_VM_PERM_READ) ? kProtectionRead : 0) |
+ ((flags & ZX_VM_PERM_WRITE) ? kProtectionWrite : 0) |
+ ((flags & ZX_VM_PERM_EXECUTE) ? kProtectionExecute : 0);
+ if (segment->filename && segment->filename_size > 0) {
+ uptr len = Min(sizeof(entry.name), segment->filename_size) - 1;
+ internal_strncpy(segment->filename, entry.name, len);
+ segment->filename[len] = 0;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cpp
new file mode 100644
index 00000000000..c7af57355b9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cpp
@@ -0,0 +1,81 @@
+//===-- sanitizer_procmaps_linux.cpp --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Information about the process mappings (Linux-specific parts).
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_LINUX
+#include "sanitizer_common.h"
+#include "sanitizer_procmaps.h"
+
+namespace __sanitizer {
+
+void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
+ if (!ReadFileToBuffer("/proc/self/maps", &proc_maps->data,
+ &proc_maps->mmaped_size, &proc_maps->len)) {
+ proc_maps->data = nullptr;
+ proc_maps->mmaped_size = 0;
+ proc_maps->len = 0;
+ }
+}
+
+static bool IsOneOf(char c, char c1, char c2) {
+ return c == c1 || c == c2;
+}
+
+bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
+ if (Error()) return false; // simulate empty maps
+ char *last = data_.proc_self_maps.data + data_.proc_self_maps.len;
+ if (data_.current >= last) return false;
+ char *next_line =
+ (char *)internal_memchr(data_.current, '\n', last - data_.current);
+ if (next_line == 0)
+ next_line = last;
+ // Example: 08048000-08056000 r-xp 00000000 03:0c 64593 /foo/bar
+ segment->start = ParseHex(&data_.current);
+ CHECK_EQ(*data_.current++, '-');
+ segment->end = ParseHex(&data_.current);
+ CHECK_EQ(*data_.current++, ' ');
+ CHECK(IsOneOf(*data_.current, '-', 'r'));
+ segment->protection = 0;
+ if (*data_.current++ == 'r') segment->protection |= kProtectionRead;
+ CHECK(IsOneOf(*data_.current, '-', 'w'));
+ if (*data_.current++ == 'w') segment->protection |= kProtectionWrite;
+ CHECK(IsOneOf(*data_.current, '-', 'x'));
+ if (*data_.current++ == 'x') segment->protection |= kProtectionExecute;
+ CHECK(IsOneOf(*data_.current, 's', 'p'));
+ if (*data_.current++ == 's') segment->protection |= kProtectionShared;
+ CHECK_EQ(*data_.current++, ' ');
+ segment->offset = ParseHex(&data_.current);
+ CHECK_EQ(*data_.current++, ' ');
+ ParseHex(&data_.current);
+ CHECK_EQ(*data_.current++, ':');
+ ParseHex(&data_.current);
+ CHECK_EQ(*data_.current++, ' ');
+ while (IsDecimal(*data_.current)) data_.current++;
+ // Qemu may lack the trailing space.
+ // https://github.com/google/sanitizers/issues/160
+ // CHECK_EQ(*data_.current++, ' ');
+ // Skip spaces.
+ while (data_.current < next_line && *data_.current == ' ') data_.current++;
+ // Fill in the filename.
+ if (segment->filename) {
+ uptr len =
+ Min((uptr)(next_line - data_.current), segment->filename_size - 1);
+ internal_strncpy(segment->filename, data_.current, len);
+ segment->filename[len] = 0;
+ }
+
+ data_.current = next_line + 1;
+ return true;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_LINUX
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cpp
new file mode 100644
index 00000000000..4b0e6781976
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cpp
@@ -0,0 +1,445 @@
+//===-- sanitizer_procmaps_mac.cpp ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Information about the process mappings (Mac-specific parts).
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_APPLE
+#include "sanitizer_common.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_procmaps.h"
+
+#include <mach-o/dyld.h>
+#include <mach-o/loader.h>
+#include <mach/mach.h>
+
+// These are not available in older macOS SDKs.
+#ifndef CPU_SUBTYPE_X86_64_H
+#define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) /* Haswell */
+#endif
+#ifndef CPU_SUBTYPE_ARM_V7S
+#define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t)11) /* Swift */
+#endif
+#ifndef CPU_SUBTYPE_ARM_V7K
+#define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t)12)
+#endif
+#ifndef CPU_TYPE_ARM64
+#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
+#endif
+
+namespace __sanitizer {
+
+// Contains information used to iterate through sections.
+struct MemoryMappedSegmentData {
+ char name[kMaxSegName];
+ uptr nsects;
+ const char *current_load_cmd_addr;
+ u32 lc_type;
+ uptr base_virt_addr;
+ uptr addr_mask;
+};
+
+template <typename Section>
+static void NextSectionLoad(LoadedModule *module, MemoryMappedSegmentData *data,
+ bool isWritable) {
+ const Section *sc = (const Section *)data->current_load_cmd_addr;
+ data->current_load_cmd_addr += sizeof(Section);
+
+ uptr sec_start = (sc->addr & data->addr_mask) + data->base_virt_addr;
+ uptr sec_end = sec_start + sc->size;
+ module->addAddressRange(sec_start, sec_end, /*executable=*/false, isWritable,
+ sc->sectname);
+}
+
+void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
+ // Don't iterate over sections when the caller hasn't set up the
+ // data pointer, when there are no sections, or when the segment
+ // is executable. Avoid iterating over executable sections because
+ // it will confuse libignore, and because the extra granularity
+ // of information is not needed by any sanitizers.
+ if (!data_ || !data_->nsects || IsExecutable()) {
+ module->addAddressRange(start, end, IsExecutable(), IsWritable(),
+ data_ ? data_->name : nullptr);
+ return;
+ }
+
+ do {
+ if (data_->lc_type == LC_SEGMENT) {
+ NextSectionLoad<struct section>(module, data_, IsWritable());
+#ifdef MH_MAGIC_64
+ } else if (data_->lc_type == LC_SEGMENT_64) {
+ NextSectionLoad<struct section_64>(module, data_, IsWritable());
+#endif
+ }
+ } while (--data_->nsects);
+}
+
+MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
+ Reset();
+}
+
+MemoryMappingLayout::~MemoryMappingLayout() {
+}
+
+bool MemoryMappingLayout::Error() const {
+ return false;
+}
+
+// More information about Mach-O headers can be found in mach-o/loader.h
+// Each Mach-O image has a header (mach_header or mach_header_64) starting with
+// a magic number, and a list of linker load commands directly following the
+// header.
+// A load command is at least two 32-bit words: the command type and the
+// command size in bytes. We're interested only in segment load commands
+// (LC_SEGMENT and LC_SEGMENT_64), which tell that a part of the file is mapped
+// into the task's address space.
+// The |vmaddr|, |vmsize| and |fileoff| fields of segment_command or
+// segment_command_64 correspond to the memory address, memory size and the
+// file offset of the current memory segment.
+// Because these fields are taken from the images as is, one needs to add
+// _dyld_get_image_vmaddr_slide() to get the actual addresses at runtime.
+
+void MemoryMappingLayout::Reset() {
+ // Count down from the top.
+ // TODO(glider): as per man 3 dyld, iterating over the headers with
+ // _dyld_image_count is thread-unsafe. We need to register callbacks for
+ // adding and removing images which will invalidate the MemoryMappingLayout
+ // state.
+ data_.current_image = _dyld_image_count();
+ data_.current_load_cmd_count = -1;
+ data_.current_load_cmd_addr = 0;
+ data_.current_magic = 0;
+ data_.current_filetype = 0;
+ data_.current_arch = kModuleArchUnknown;
+ internal_memset(data_.current_uuid, 0, kModuleUUIDSize);
+}
+
+// The dyld load address should be unchanged throughout process execution,
+// and it is expensive to compute once many libraries have been loaded,
+// so cache it here and do not reset.
+static mach_header *dyld_hdr = 0;
+static const char kDyldPath[] = "/usr/lib/dyld";
+static const int kDyldImageIdx = -1;
+
+// static
+void MemoryMappingLayout::CacheMemoryMappings() {
+ // No-op on Mac for now.
+}
+
+void MemoryMappingLayout::LoadFromCache() {
+ // No-op on Mac for now.
+}
+
+static bool IsDyldHdr(const mach_header *hdr) {
+ return (hdr->magic == MH_MAGIC || hdr->magic == MH_MAGIC_64) &&
+ hdr->filetype == MH_DYLINKER;
+}
+
+// _dyld_get_image_header() and related APIs don't report dyld itself.
+// We work around this by manually recursing through the memory map
+// until we hit a Mach header matching dyld instead. These recurse
+// calls are expensive, but the first memory map generation occurs
+// early in the process, when dyld is one of the only images loaded,
+// so it will be hit after only a few iterations. These assumptions don't hold
+// on macOS 13+ anymore (dyld itself has moved into the shared cache).
+static mach_header *GetDyldImageHeaderViaVMRegion() {
+ vm_address_t address = 0;
+
+ while (true) {
+ vm_size_t size = 0;
+ unsigned depth = 1;
+ struct vm_region_submap_info_64 info;
+ mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
+ kern_return_t err =
+ vm_region_recurse_64(mach_task_self(), &address, &size, &depth,
+ (vm_region_info_t)&info, &count);
+ if (err != KERN_SUCCESS) return nullptr;
+
+ if (size >= sizeof(mach_header) && info.protection & kProtectionRead) {
+ mach_header *hdr = (mach_header *)address;
+ if (IsDyldHdr(hdr)) {
+ return hdr;
+ }
+ }
+ address += size;
+ }
+}
+
+extern "C" {
+struct dyld_shared_cache_dylib_text_info {
+ uint64_t version; // current version 2
+ // following fields all exist in version 1
+ uint64_t loadAddressUnslid;
+ uint64_t textSegmentSize;
+ uuid_t dylibUuid;
+ const char *path; // pointer invalid at end of iterations
+ // following fields all exist in version 2
+ uint64_t textSegmentOffset; // offset from start of cache
+};
+typedef struct dyld_shared_cache_dylib_text_info
+ dyld_shared_cache_dylib_text_info;
+
+extern bool _dyld_get_shared_cache_uuid(uuid_t uuid);
+extern const void *_dyld_get_shared_cache_range(size_t *length);
+extern int dyld_shared_cache_iterate_text(
+ const uuid_t cacheUuid,
+ void (^callback)(const dyld_shared_cache_dylib_text_info *info));
+} // extern "C"
+
+static mach_header *GetDyldImageHeaderViaSharedCache() {
+ uuid_t uuid;
+ bool hasCache = _dyld_get_shared_cache_uuid(uuid);
+ if (!hasCache)
+ return nullptr;
+
+ size_t cacheLength;
+ __block uptr cacheStart = (uptr)_dyld_get_shared_cache_range(&cacheLength);
+ CHECK(cacheStart && cacheLength);
+
+ __block mach_header *dyldHdr = nullptr;
+ int res = dyld_shared_cache_iterate_text(
+ uuid, ^(const dyld_shared_cache_dylib_text_info *info) {
+ CHECK_GE(info->version, 2);
+ mach_header *hdr =
+ (mach_header *)(cacheStart + info->textSegmentOffset);
+ if (IsDyldHdr(hdr))
+ dyldHdr = hdr;
+ });
+ CHECK_EQ(res, 0);
+
+ return dyldHdr;
+}
+
+const mach_header *get_dyld_hdr() {
+ if (!dyld_hdr) {
+ // On macOS 13+, dyld itself has moved into the shared cache. Looking it up
+ // via vm_region_recurse_64() causes spins/hangs/crashes.
+ if (GetMacosAlignedVersion() >= MacosVersion(13, 0)) {
+ dyld_hdr = GetDyldImageHeaderViaSharedCache();
+ if (!dyld_hdr) {
+ VReport(1,
+ "Failed to lookup the dyld image header in the shared cache on "
+ "macOS 13+ (or no shared cache in use). Falling back to "
+ "lookup via vm_region_recurse_64().\n");
+ dyld_hdr = GetDyldImageHeaderViaVMRegion();
+ }
+ } else {
+ dyld_hdr = GetDyldImageHeaderViaVMRegion();
+ }
+ CHECK(dyld_hdr);
+ }
+
+ return dyld_hdr;
+}
+
+// Next and NextSegmentLoad were inspired by base/sysinfo.cc in
+// Google Perftools, https://github.com/gperftools/gperftools.
+
+// NextSegmentLoad scans the current image for the next segment load command
+// and returns the start and end addresses and file offset of the corresponding
+// segment.
+// Note that the segment addresses are not necessarily sorted.
+template <u32 kLCSegment, typename SegmentCommand>
+static bool NextSegmentLoad(MemoryMappedSegment *segment,
+ MemoryMappedSegmentData *seg_data,
+ MemoryMappingLayoutData *layout_data) {
+ const char *lc = layout_data->current_load_cmd_addr;
+ layout_data->current_load_cmd_addr += ((const load_command *)lc)->cmdsize;
+ if (((const load_command *)lc)->cmd == kLCSegment) {
+ const SegmentCommand* sc = (const SegmentCommand *)lc;
+ uptr base_virt_addr, addr_mask;
+ if (layout_data->current_image == kDyldImageIdx) {
+ base_virt_addr = (uptr)get_dyld_hdr();
+ // vmaddr is masked with 0xfffff because on macOS versions < 10.12,
+ // it contains an absolute address rather than an offset for dyld.
+ // To make matters even more complicated, this absolute address
+ // isn't actually the absolute segment address, but the offset portion
+ // of the address is accurate when combined with the dyld base address,
+ // and the mask will give just this offset.
+ addr_mask = 0xfffff;
+ } else {
+ base_virt_addr =
+ (uptr)_dyld_get_image_vmaddr_slide(layout_data->current_image);
+ addr_mask = ~0;
+ }
+
+ segment->start = (sc->vmaddr & addr_mask) + base_virt_addr;
+ segment->end = segment->start + sc->vmsize;
+ // Most callers don't need section information, so only fill this struct
+ // when required.
+ if (seg_data) {
+ seg_data->nsects = sc->nsects;
+ seg_data->current_load_cmd_addr =
+ (const char *)lc + sizeof(SegmentCommand);
+ seg_data->lc_type = kLCSegment;
+ seg_data->base_virt_addr = base_virt_addr;
+ seg_data->addr_mask = addr_mask;
+ internal_strncpy(seg_data->name, sc->segname,
+ ARRAY_SIZE(seg_data->name));
+ }
+
+ // Return the initial protection.
+ segment->protection = sc->initprot;
+ segment->offset = (layout_data->current_filetype ==
+ /*MH_EXECUTE*/ 0x2)
+ ? sc->vmaddr
+ : sc->fileoff;
+ if (segment->filename) {
+ const char *src = (layout_data->current_image == kDyldImageIdx)
+ ? kDyldPath
+ : _dyld_get_image_name(layout_data->current_image);
+ internal_strncpy(segment->filename, src, segment->filename_size);
+ }
+ segment->arch = layout_data->current_arch;
+ internal_memcpy(segment->uuid, layout_data->current_uuid, kModuleUUIDSize);
+ return true;
+ }
+ return false;
+}
+
+ModuleArch ModuleArchFromCpuType(cpu_type_t cputype, cpu_subtype_t cpusubtype) {
+ cpusubtype = cpusubtype & ~CPU_SUBTYPE_MASK;
+ switch (cputype) {
+ case CPU_TYPE_I386:
+ return kModuleArchI386;
+ case CPU_TYPE_X86_64:
+ if (cpusubtype == CPU_SUBTYPE_X86_64_ALL) return kModuleArchX86_64;
+ if (cpusubtype == CPU_SUBTYPE_X86_64_H) return kModuleArchX86_64H;
+ CHECK(0 && "Invalid subtype of x86_64");
+ return kModuleArchUnknown;
+ case CPU_TYPE_ARM:
+ if (cpusubtype == CPU_SUBTYPE_ARM_V6) return kModuleArchARMV6;
+ if (cpusubtype == CPU_SUBTYPE_ARM_V7) return kModuleArchARMV7;
+ if (cpusubtype == CPU_SUBTYPE_ARM_V7S) return kModuleArchARMV7S;
+ if (cpusubtype == CPU_SUBTYPE_ARM_V7K) return kModuleArchARMV7K;
+ CHECK(0 && "Invalid subtype of ARM");
+ return kModuleArchUnknown;
+ case CPU_TYPE_ARM64:
+ return kModuleArchARM64;
+ default:
+ CHECK(0 && "Invalid CPU type");
+ return kModuleArchUnknown;
+ }
+}
+
+static const load_command *NextCommand(const load_command *lc) {
+ return (const load_command *)((const char *)lc + lc->cmdsize);
+}
+
+static void FindUUID(const load_command *first_lc, u8 *uuid_output) {
+ for (const load_command *lc = first_lc; lc->cmd != 0; lc = NextCommand(lc)) {
+ if (lc->cmd != LC_UUID) continue;
+
+ const uuid_command *uuid_lc = (const uuid_command *)lc;
+ const uint8_t *uuid = &uuid_lc->uuid[0];
+ internal_memcpy(uuid_output, uuid, kModuleUUIDSize);
+ return;
+ }
+}
+
+static bool IsModuleInstrumented(const load_command *first_lc) {
+ for (const load_command *lc = first_lc; lc->cmd != 0; lc = NextCommand(lc)) {
+ if (lc->cmd != LC_LOAD_DYLIB) continue;
+
+ const dylib_command *dylib_lc = (const dylib_command *)lc;
+ uint32_t dylib_name_offset = dylib_lc->dylib.name.offset;
+ const char *dylib_name = ((const char *)dylib_lc) + dylib_name_offset;
+ dylib_name = StripModuleName(dylib_name);
+ if (dylib_name != 0 && (internal_strstr(dylib_name, "libclang_rt."))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
+ for (; data_.current_image >= kDyldImageIdx; data_.current_image--) {
+ const mach_header *hdr = (data_.current_image == kDyldImageIdx)
+ ? get_dyld_hdr()
+ : _dyld_get_image_header(data_.current_image);
+ if (!hdr) continue;
+ if (data_.current_load_cmd_count < 0) {
+ // Set up for this image;
+ data_.current_load_cmd_count = hdr->ncmds;
+ data_.current_magic = hdr->magic;
+ data_.current_filetype = hdr->filetype;
+ data_.current_arch = ModuleArchFromCpuType(hdr->cputype, hdr->cpusubtype);
+ switch (data_.current_magic) {
+#ifdef MH_MAGIC_64
+ case MH_MAGIC_64: {
+ data_.current_load_cmd_addr =
+ (const char *)hdr + sizeof(mach_header_64);
+ break;
+ }
+#endif
+ case MH_MAGIC: {
+ data_.current_load_cmd_addr = (const char *)hdr + sizeof(mach_header);
+ break;
+ }
+ default: {
+ continue;
+ }
+ }
+ FindUUID((const load_command *)data_.current_load_cmd_addr,
+ data_.current_uuid);
+ data_.current_instrumented = IsModuleInstrumented(
+ (const load_command *)data_.current_load_cmd_addr);
+ }
+
+ for (; data_.current_load_cmd_count >= 0; data_.current_load_cmd_count--) {
+ switch (data_.current_magic) {
+ // data_.current_magic may be only one of MH_MAGIC, MH_MAGIC_64.
+#ifdef MH_MAGIC_64
+ case MH_MAGIC_64: {
+ if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
+ segment, segment->data_, &data_))
+ return true;
+ break;
+ }
+#endif
+ case MH_MAGIC: {
+ if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
+ segment, segment->data_, &data_))
+ return true;
+ break;
+ }
+ }
+ }
+ // If we get here, no more load_cmd's in this image talk about
+ // segments. Go on to the next image.
+ }
+ return false;
+}
+
+void MemoryMappingLayout::DumpListOfModules(
+ InternalMmapVectorNoCtor<LoadedModule> *modules) {
+ Reset();
+ InternalMmapVector<char> module_name(kMaxPathLength);
+ MemoryMappedSegment segment(module_name.data(), module_name.size());
+ MemoryMappedSegmentData data;
+ segment.data_ = &data;
+ while (Next(&segment)) {
+ if (segment.filename[0] == '\0') continue;
+ LoadedModule *cur_module = nullptr;
+ if (!modules->empty() &&
+ 0 == internal_strcmp(segment.filename, modules->back().full_name())) {
+ cur_module = &modules->back();
+ } else {
+ modules->push_back(LoadedModule());
+ cur_module = &modules->back();
+ cur_module->set(segment.filename, segment.start, segment.arch,
+ segment.uuid, data_.current_instrumented);
+ }
+ segment.AddAddressRanges(cur_module);
+ }
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp
new file mode 100644
index 00000000000..eeb49e2afe3
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp
@@ -0,0 +1,92 @@
+//===-- sanitizer_procmaps_solaris.cpp ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Information about the process mappings (Solaris-specific parts).
+//===----------------------------------------------------------------------===//
+
+// Before Solaris 11.4, <procfs.h> doesn't work in a largefile environment.
+#undef _FILE_OFFSET_BITS
+#include "sanitizer_platform.h"
+#if SANITIZER_SOLARIS
+# include <fcntl.h>
+# include <limits.h>
+# include <procfs.h>
+
+# include "sanitizer_common.h"
+# include "sanitizer_procmaps.h"
+
+namespace __sanitizer {
+
+void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
+ uptr fd = internal_open("/proc/self/xmap", O_RDONLY);
+ CHECK_NE(fd, -1);
+ uptr Size = internal_filesize(fd);
+ CHECK_GT(Size, 0);
+
+ // Allow for additional entries by following mmap.
+ size_t MmapedSize = Size * 4 / 3;
+ void *VmMap = MmapOrDie(MmapedSize, "ReadProcMaps()");
+ Size = internal_read(fd, VmMap, MmapedSize);
+ CHECK_NE(Size, -1);
+ internal_close(fd);
+ proc_maps->data = (char *)VmMap;
+ proc_maps->mmaped_size = MmapedSize;
+ proc_maps->len = Size;
+}
+
+bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
+ if (Error()) return false; // simulate empty maps
+ char *last = data_.proc_self_maps.data + data_.proc_self_maps.len;
+ if (data_.current >= last) return false;
+
+ prxmap_t *xmapentry =
+ const_cast<prxmap_t *>(reinterpret_cast<const prxmap_t *>(data_.current));
+
+ segment->start = (uptr)xmapentry->pr_vaddr;
+ segment->end = (uptr)(xmapentry->pr_vaddr + xmapentry->pr_size);
+ segment->offset = (uptr)xmapentry->pr_offset;
+
+ segment->protection = 0;
+ if ((xmapentry->pr_mflags & MA_READ) != 0)
+ segment->protection |= kProtectionRead;
+ if ((xmapentry->pr_mflags & MA_WRITE) != 0)
+ segment->protection |= kProtectionWrite;
+ if ((xmapentry->pr_mflags & MA_EXEC) != 0)
+ segment->protection |= kProtectionExecute;
+ if ((xmapentry->pr_mflags & MA_SHARED) != 0)
+ segment->protection |= kProtectionShared;
+
+ if (segment->filename != NULL && segment->filename_size > 0) {
+ char proc_path[PATH_MAX + 1];
+
+ // Avoid unnecessary readlink on unnamed entires.
+ if (xmapentry->pr_mapname[0] == '\0')
+ segment->filename[0] = '\0';
+ else {
+ internal_snprintf(proc_path, sizeof(proc_path), "/proc/self/path/%s",
+ xmapentry->pr_mapname);
+ ssize_t sz = internal_readlink(proc_path, segment->filename,
+ segment->filename_size - 1);
+
+ // If readlink failed, the map is anonymous.
+ if (sz == -1)
+ segment->filename[0] = '\0';
+ else if ((size_t)sz < segment->filename_size)
+ // readlink doesn't NUL-terminate.
+ segment->filename[sz] = '\0';
+ }
+ }
+
+ data_.current += sizeof(prxmap_t);
+
+ return true;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SOLARIS
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_ptrauth.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_ptrauth.h
new file mode 100644
index 00000000000..cb1e5366f99
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_ptrauth.h
@@ -0,0 +1,41 @@
+//===-- sanitizer_ptrauth.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_PTRAUTH_H
+#define SANITIZER_PTRAUTH_H
+
+#if __has_feature(ptrauth_calls)
+#error #include <ptrauth.h>
+#elif defined(__ARM_FEATURE_PAC_DEFAULT) && !defined(__APPLE__)
+inline unsigned long ptrauth_strip(void* __value, unsigned int __key) {
+ // On the stack the link register is protected with Pointer
+ // Authentication Code when compiled with -mbranch-protection.
+ // Let's stripping the PAC unconditionally because xpaclri is in
+ // the NOP space so will do nothing when it is not enabled or not available.
+ unsigned long ret;
+ asm volatile(
+ "mov x30, %1\n\t"
+ "hint #7\n\t" // xpaclri
+ "mov %0, x30\n\t"
+ : "=r"(ret)
+ : "r"(__value)
+ : "x30");
+ return ret;
+}
+#define ptrauth_auth_data(__value, __old_key, __old_data) __value
+#define ptrauth_string_discriminator(__string) ((int)0)
+#else
+// Copied from <ptrauth.h>
+#define ptrauth_strip(__value, __key) __value
+#define ptrauth_auth_data(__value, __old_key, __old_data) __value
+#define ptrauth_string_discriminator(__string) ((int)0)
+#endif
+
+#define STRIP_PAC_PC(pc) ((uptr)ptrauth_strip(pc, 0))
+
+#endif // SANITIZER_PTRAUTH_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_quarantine.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_quarantine.h
new file mode 100644
index 00000000000..4aa60548516
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_quarantine.h
@@ -0,0 +1,318 @@
+//===-- sanitizer_quarantine.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Memory quarantine for AddressSanitizer and potentially other tools.
+// Quarantine caches some specified amount of memory in per-thread caches,
+// then evicts to global FIFO queue. When the queue reaches specified threshold,
+// oldest memory is recycled.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_QUARANTINE_H
+#define SANITIZER_QUARANTINE_H
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_mutex.h"
+#include "sanitizer_list.h"
+
+namespace __sanitizer {
+
+template<typename Node> class QuarantineCache;
+
+struct QuarantineBatch {
+ static const uptr kSize = 1021;
+ QuarantineBatch *next;
+ uptr size;
+ uptr count;
+ void *batch[kSize];
+
+ void init(void *ptr, uptr size) {
+ count = 1;
+ batch[0] = ptr;
+ this->size = size + sizeof(QuarantineBatch); // Account for the batch size.
+ }
+
+ // The total size of quarantined nodes recorded in this batch.
+ uptr quarantined_size() const {
+ return size - sizeof(QuarantineBatch);
+ }
+
+ void push_back(void *ptr, uptr size) {
+ CHECK_LT(count, kSize);
+ batch[count++] = ptr;
+ this->size += size;
+ }
+
+ bool can_merge(const QuarantineBatch* const from) const {
+ return count + from->count <= kSize;
+ }
+
+ void merge(QuarantineBatch* const from) {
+ CHECK_LE(count + from->count, kSize);
+ CHECK_GE(size, sizeof(QuarantineBatch));
+
+ for (uptr i = 0; i < from->count; ++i)
+ batch[count + i] = from->batch[i];
+ count += from->count;
+ size += from->quarantined_size();
+
+ from->count = 0;
+ from->size = sizeof(QuarantineBatch);
+ }
+};
+
+COMPILER_CHECK(sizeof(QuarantineBatch) <= (1 << 13)); // 8Kb.
+
+// The callback interface is:
+// void Callback::Recycle(Node *ptr);
+// void *cb.Allocate(uptr size);
+// void cb.Deallocate(void *ptr);
+template<typename Callback, typename Node>
+class Quarantine {
+ public:
+ typedef QuarantineCache<Callback> Cache;
+
+ explicit Quarantine(LinkerInitialized)
+ : cache_(LINKER_INITIALIZED) {
+ }
+
+ void Init(uptr size, uptr cache_size) {
+ // Thread local quarantine size can be zero only when global quarantine size
+ // is zero (it allows us to perform just one atomic read per Put() call).
+ CHECK((size == 0 && cache_size == 0) || cache_size != 0);
+
+ atomic_store_relaxed(&max_size_, size);
+ atomic_store_relaxed(&min_size_, size / 10 * 9); // 90% of max size.
+ atomic_store_relaxed(&max_cache_size_, cache_size);
+
+ cache_mutex_.Init();
+ recycle_mutex_.Init();
+ }
+
+ uptr GetSize() const { return atomic_load_relaxed(&max_size_); }
+ uptr GetCacheSize() const {
+ return atomic_load_relaxed(&max_cache_size_);
+ }
+
+ void Put(Cache *c, Callback cb, Node *ptr, uptr size) {
+ uptr cache_size = GetCacheSize();
+ if (cache_size) {
+ c->Enqueue(cb, ptr, size);
+ } else {
+ // GetCacheSize() == 0 only when GetSize() == 0 (see Init).
+ cb.Recycle(ptr);
+ }
+ // Check cache size anyway to accommodate for runtime cache_size change.
+ if (c->Size() > cache_size)
+ Drain(c, cb);
+ }
+
+ void NOINLINE Drain(Cache *c, Callback cb) {
+ {
+ SpinMutexLock l(&cache_mutex_);
+ cache_.Transfer(c);
+ }
+ if (cache_.Size() > GetSize() && recycle_mutex_.TryLock())
+ Recycle(atomic_load_relaxed(&min_size_), cb);
+ }
+
+ void NOINLINE DrainAndRecycle(Cache *c, Callback cb) {
+ {
+ SpinMutexLock l(&cache_mutex_);
+ cache_.Transfer(c);
+ }
+ recycle_mutex_.Lock();
+ Recycle(0, cb);
+ }
+
+ void PrintStats() const {
+ // It assumes that the world is stopped, just as the allocator's PrintStats.
+ Printf("Quarantine limits: global: %zdMb; thread local: %zdKb\n",
+ GetSize() >> 20, GetCacheSize() >> 10);
+ cache_.PrintStats();
+ }
+
+ private:
+ // Read-only data.
+ char pad0_[kCacheLineSize];
+ atomic_uintptr_t max_size_;
+ atomic_uintptr_t min_size_;
+ atomic_uintptr_t max_cache_size_;
+ char pad1_[kCacheLineSize];
+ StaticSpinMutex cache_mutex_;
+ StaticSpinMutex recycle_mutex_;
+ Cache cache_;
+ char pad2_[kCacheLineSize];
+
+ void NOINLINE Recycle(uptr min_size, Callback cb)
+ SANITIZER_REQUIRES(recycle_mutex_) SANITIZER_RELEASE(recycle_mutex_) {
+ Cache tmp;
+ {
+ SpinMutexLock l(&cache_mutex_);
+ // Go over the batches and merge partially filled ones to
+ // save some memory, otherwise batches themselves (since the memory used
+ // by them is counted against quarantine limit) can overcome the actual
+ // user's quarantined chunks, which diminishes the purpose of the
+ // quarantine.
+ uptr cache_size = cache_.Size();
+ uptr overhead_size = cache_.OverheadSize();
+ CHECK_GE(cache_size, overhead_size);
+ // Do the merge only when overhead exceeds this predefined limit (might
+ // require some tuning). It saves us merge attempt when the batch list
+ // quarantine is unlikely to contain batches suitable for merge.
+ const uptr kOverheadThresholdPercents = 100;
+ if (cache_size > overhead_size &&
+ overhead_size * (100 + kOverheadThresholdPercents) >
+ cache_size * kOverheadThresholdPercents) {
+ cache_.MergeBatches(&tmp);
+ }
+ // Extract enough chunks from the quarantine to get below the max
+ // quarantine size and leave some leeway for the newly quarantined chunks.
+ while (cache_.Size() > min_size) {
+ tmp.EnqueueBatch(cache_.DequeueBatch());
+ }
+ }
+ recycle_mutex_.Unlock();
+ DoRecycle(&tmp, cb);
+ }
+
+ void NOINLINE DoRecycle(Cache *c, Callback cb) {
+ while (QuarantineBatch *b = c->DequeueBatch()) {
+ const uptr kPrefetch = 16;
+ CHECK(kPrefetch <= ARRAY_SIZE(b->batch));
+ for (uptr i = 0; i < kPrefetch; i++)
+ PREFETCH(b->batch[i]);
+ for (uptr i = 0, count = b->count; i < count; i++) {
+ if (i + kPrefetch < count)
+ PREFETCH(b->batch[i + kPrefetch]);
+ cb.Recycle((Node*)b->batch[i]);
+ }
+ cb.Deallocate(b);
+ }
+ }
+};
+
+// Per-thread cache of memory blocks.
+template<typename Callback>
+class QuarantineCache {
+ public:
+ explicit QuarantineCache(LinkerInitialized) {
+ }
+
+ QuarantineCache()
+ : size_() {
+ list_.clear();
+ }
+
+ // Total memory used, including internal accounting.
+ uptr Size() const {
+ return atomic_load_relaxed(&size_);
+ }
+
+ // Memory used for internal accounting.
+ uptr OverheadSize() const {
+ return list_.size() * sizeof(QuarantineBatch);
+ }
+
+ void Enqueue(Callback cb, void *ptr, uptr size) {
+ if (list_.empty() || list_.back()->count == QuarantineBatch::kSize) {
+ QuarantineBatch *b = (QuarantineBatch *)cb.Allocate(sizeof(*b));
+ CHECK(b);
+ b->init(ptr, size);
+ EnqueueBatch(b);
+ } else {
+ list_.back()->push_back(ptr, size);
+ SizeAdd(size);
+ }
+ }
+
+ void Transfer(QuarantineCache *from_cache) {
+ list_.append_back(&from_cache->list_);
+ SizeAdd(from_cache->Size());
+
+ atomic_store_relaxed(&from_cache->size_, 0);
+ }
+
+ void EnqueueBatch(QuarantineBatch *b) {
+ list_.push_back(b);
+ SizeAdd(b->size);
+ }
+
+ QuarantineBatch *DequeueBatch() {
+ if (list_.empty())
+ return nullptr;
+ QuarantineBatch *b = list_.front();
+ list_.pop_front();
+ SizeSub(b->size);
+ return b;
+ }
+
+ void MergeBatches(QuarantineCache *to_deallocate) {
+ uptr extracted_size = 0;
+ QuarantineBatch *current = list_.front();
+ while (current && current->next) {
+ if (current->can_merge(current->next)) {
+ QuarantineBatch *extracted = current->next;
+ // Move all the chunks into the current batch.
+ current->merge(extracted);
+ CHECK_EQ(extracted->count, 0);
+ CHECK_EQ(extracted->size, sizeof(QuarantineBatch));
+ // Remove the next batch from the list and account for its size.
+ list_.extract(current, extracted);
+ extracted_size += extracted->size;
+ // Add it to deallocation list.
+ to_deallocate->EnqueueBatch(extracted);
+ } else {
+ current = current->next;
+ }
+ }
+ SizeSub(extracted_size);
+ }
+
+ void PrintStats() const {
+ uptr batch_count = 0;
+ uptr total_overhead_bytes = 0;
+ uptr total_bytes = 0;
+ uptr total_quarantine_chunks = 0;
+ for (List::ConstIterator it = list_.begin(); it != list_.end(); ++it) {
+ batch_count++;
+ total_bytes += (*it).size;
+ total_overhead_bytes += (*it).size - (*it).quarantined_size();
+ total_quarantine_chunks += (*it).count;
+ }
+ uptr quarantine_chunks_capacity = batch_count * QuarantineBatch::kSize;
+ int chunks_usage_percent = quarantine_chunks_capacity == 0 ?
+ 0 : total_quarantine_chunks * 100 / quarantine_chunks_capacity;
+ uptr total_quarantined_bytes = total_bytes - total_overhead_bytes;
+ int memory_overhead_percent = total_quarantined_bytes == 0 ?
+ 0 : total_overhead_bytes * 100 / total_quarantined_bytes;
+ Printf("Global quarantine stats: batches: %zd; bytes: %zd (user: %zd); "
+ "chunks: %zd (capacity: %zd); %d%% chunks used; %d%% memory overhead"
+ "\n",
+ batch_count, total_bytes, total_quarantined_bytes,
+ total_quarantine_chunks, quarantine_chunks_capacity,
+ chunks_usage_percent, memory_overhead_percent);
+ }
+
+ private:
+ typedef IntrusiveList<QuarantineBatch> List;
+
+ List list_;
+ atomic_uintptr_t size_;
+
+ void SizeAdd(uptr add) {
+ atomic_store_relaxed(&size_, Size() + add);
+ }
+ void SizeSub(uptr sub) {
+ atomic_store_relaxed(&size_, Size() - sub);
+ }
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_QUARANTINE_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_report_decorator.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_report_decorator.h
new file mode 100644
index 00000000000..d276c2cdd84
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_report_decorator.h
@@ -0,0 +1,48 @@
+//===-- sanitizer_report_decorator.h ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Tags to decorate the sanitizer reports.
+// Currently supported tags:
+// * None.
+// * ANSI color sequences.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_REPORT_DECORATOR_H
+#define SANITIZER_REPORT_DECORATOR_H
+
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+class SanitizerCommonDecorator {
+ // FIXME: This is not portable. It assumes the special strings are printed to
+ // stdout, which is not the case on Windows (see SetConsoleTextAttribute()).
+ public:
+ SanitizerCommonDecorator() : ansi_(ColorizeReports()) {}
+ const char *Bold() const { return ansi_ ? "\033[1m" : ""; }
+ const char *Default() const { return ansi_ ? "\033[1m\033[0m" : ""; }
+ const char *Warning() const { return Red(); }
+ const char *Error() const { return Red(); }
+ const char *MemoryByte() const { return Magenta(); }
+
+ protected:
+ const char *Black() const { return ansi_ ? "\033[1m\033[30m" : ""; }
+ const char *Red() const { return ansi_ ? "\033[1m\033[31m" : ""; }
+ const char *Green() const { return ansi_ ? "\033[1m\033[32m" : ""; }
+ const char *Yellow() const { return ansi_ ? "\033[1m\033[33m" : ""; }
+ const char *Blue() const { return ansi_ ? "\033[1m\033[34m" : ""; }
+ const char *Magenta() const { return ansi_ ? "\033[1m\033[35m" : ""; }
+ const char *Cyan() const { return ansi_ ? "\033[1m\033[36m" : ""; }
+ const char *White() const { return ansi_ ? "\033[1m\033[37m" : ""; }
+ private:
+ bool ansi_;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_REPORT_DECORATOR_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_ring_buffer.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_ring_buffer.h
new file mode 100644
index 00000000000..f22e40cac28
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_ring_buffer.h
@@ -0,0 +1,166 @@
+//===-- sanitizer_ring_buffer.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Simple ring buffer.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_RING_BUFFER_H
+#define SANITIZER_RING_BUFFER_H
+
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+// RingBuffer<T>: fixed-size ring buffer optimized for speed of push().
+// T should be a POD type and sizeof(T) should be divisible by sizeof(void*).
+// At creation, all elements are zero.
+template<class T>
+class RingBuffer {
+ public:
+ COMPILER_CHECK(sizeof(T) % sizeof(void *) == 0);
+ static RingBuffer *New(uptr Size) {
+ void *Ptr = MmapOrDie(SizeInBytes(Size), "RingBuffer");
+ RingBuffer *RB = reinterpret_cast<RingBuffer*>(Ptr);
+ uptr End = reinterpret_cast<uptr>(Ptr) + SizeInBytes(Size);
+ RB->last_ = RB->next_ = reinterpret_cast<T*>(End - sizeof(T));
+ return RB;
+ }
+ void Delete() {
+ UnmapOrDie(this, SizeInBytes(size()));
+ }
+ uptr size() const {
+ return last_ + 1 -
+ reinterpret_cast<T *>(reinterpret_cast<uptr>(this) +
+ 2 * sizeof(T *));
+ }
+
+ static uptr SizeInBytes(uptr Size) {
+ return Size * sizeof(T) + 2 * sizeof(T*);
+ }
+
+ uptr SizeInBytes() { return SizeInBytes(size()); }
+
+ void push(T t) {
+ *next_ = t;
+ next_--;
+ // The condition below works only if sizeof(T) is divisible by sizeof(T*).
+ if (next_ <= reinterpret_cast<T*>(&next_))
+ next_ = last_;
+ }
+
+ T operator[](uptr Idx) const {
+ CHECK_LT(Idx, size());
+ sptr IdxNext = Idx + 1;
+ if (IdxNext > last_ - next_)
+ IdxNext -= size();
+ return next_[IdxNext];
+ }
+
+ private:
+ RingBuffer() {}
+ ~RingBuffer() {}
+ RingBuffer(const RingBuffer&) = delete;
+
+ // Data layout:
+ // LNDDDDDDDD
+ // D: data elements.
+ // L: last_, always points to the last data element.
+ // N: next_, initially equals to last_, is decremented on every push,
+ // wraps around if it's less or equal than its own address.
+ T *last_;
+ T *next_;
+ T data_[1]; // flexible array.
+};
+
+// A ring buffer with externally provided storage that encodes its state in 8
+// bytes. Has significant constraints on size and alignment of storage.
+// See a comment in hwasan/hwasan_thread_list.h for the motivation behind this.
+#if SANITIZER_WORDSIZE == 64
+template <class T>
+class CompactRingBuffer {
+ // Top byte of long_ stores the buffer size in pages.
+ // Lower bytes store the address of the next buffer element.
+ static constexpr int kPageSizeBits = 12;
+ static constexpr int kSizeShift = 56;
+ static constexpr int kSizeBits = 64 - kSizeShift;
+ static constexpr uptr kNextMask = (1ULL << kSizeShift) - 1;
+
+ uptr GetStorageSize() const { return (long_ >> kSizeShift) << kPageSizeBits; }
+
+ static uptr SignExtend(uptr x) { return ((sptr)x) << kSizeBits >> kSizeBits; }
+
+ void Init(void *storage, uptr size) {
+ CHECK_EQ(sizeof(CompactRingBuffer<T>), sizeof(void *));
+ CHECK(IsPowerOfTwo(size));
+ CHECK_GE(size, 1 << kPageSizeBits);
+ CHECK_LE(size, 128 << kPageSizeBits);
+ CHECK_EQ(size % 4096, 0);
+ CHECK_EQ(size % sizeof(T), 0);
+ uptr st = (uptr)storage;
+ CHECK_EQ(st % (size * 2), 0);
+ CHECK_EQ(st, SignExtend(st & kNextMask));
+ long_ = (st & kNextMask) | ((size >> kPageSizeBits) << kSizeShift);
+ }
+
+ void SetNext(const T *next) {
+ long_ = (long_ & ~kNextMask) | ((uptr)next & kNextMask);
+ }
+
+ public:
+ CompactRingBuffer(void *storage, uptr size) {
+ Init(storage, size);
+ }
+
+ // A copy constructor of sorts.
+ CompactRingBuffer(const CompactRingBuffer &other, void *storage) {
+ uptr size = other.GetStorageSize();
+ internal_memcpy(storage, other.StartOfStorage(), size);
+ Init(storage, size);
+ uptr Idx = other.Next() - (const T *)other.StartOfStorage();
+ SetNext((const T *)storage + Idx);
+ }
+
+ T *Next() const { return (T *)(SignExtend(long_ & kNextMask)); }
+
+ void *StartOfStorage() const {
+ return (void *)((uptr)Next() & ~(GetStorageSize() - 1));
+ }
+
+ void *EndOfStorage() const {
+ return (void *)((uptr)StartOfStorage() + GetStorageSize());
+ }
+
+ uptr size() const { return GetStorageSize() / sizeof(T); }
+
+ void push(T t) {
+ T *next = Next();
+ *next = t;
+ next++;
+ next = (T *)((uptr)next & ~GetStorageSize());
+ SetNext(next);
+ }
+
+ const T &operator[](uptr Idx) const {
+ CHECK_LT(Idx, size());
+ const T *Begin = (const T *)StartOfStorage();
+ sptr StorageIdx = Next() - Begin;
+ StorageIdx -= (sptr)(Idx + 1);
+ if (StorageIdx < 0)
+ StorageIdx += size();
+ return Begin[StorageIdx];
+ }
+
+ public:
+ ~CompactRingBuffer() {}
+ CompactRingBuffer(const CompactRingBuffer &) = delete;
+
+ uptr long_;
+};
+#endif
+} // namespace __sanitizer
+
+#endif // SANITIZER_RING_BUFFER_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_signal_interceptors.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_signal_interceptors.inc
new file mode 100644
index 00000000000..475e577d998
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_signal_interceptors.inc
@@ -0,0 +1,97 @@
+//===-- sanitizer_signal_interceptors.inc -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Signal interceptors for sanitizers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "interception/interception.h"
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform_interceptors.h"
+
+using namespace __sanitizer;
+
+#if SANITIZER_NETBSD
+#define sigaction_symname __sigaction14
+#else
+#define sigaction_symname sigaction
+#endif
+
+#ifndef SIGNAL_INTERCEPTOR_SIGNAL_IMPL
+#define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signum, handler) \
+ { return REAL(func)(signum, handler); }
+#endif
+
+#ifndef SIGNAL_INTERCEPTOR_SIGACTION_IMPL
+# define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact) \
+ { \
+ if (!REAL(sigaction_symname)) { \
+ Printf( \
+ "Warning: REAL(sigaction_symname) == nullptr. This may happen " \
+ "if you link with ubsan statically. Sigaction will not work.\n"); \
+ return -1; \
+ } \
+ return REAL(sigaction_symname)(signum, act, oldact); \
+ }
+#endif
+
+#if SANITIZER_INTERCEPT_BSD_SIGNAL
+INTERCEPTOR(uptr, bsd_signal, int signum, uptr handler) {
+ if (GetHandleSignalMode(signum) == kHandleSignalExclusive) return 0;
+ SIGNAL_INTERCEPTOR_SIGNAL_IMPL(bsd_signal, signum, handler);
+}
+#define INIT_BSD_SIGNAL COMMON_INTERCEPT_FUNCTION(bsd_signal)
+#else // SANITIZER_INTERCEPT_BSD_SIGNAL
+#define INIT_BSD_SIGNAL
+#endif // SANITIZER_INTERCEPT_BSD_SIGNAL
+
+#if SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION
+INTERCEPTOR(uptr, signal, int signum, uptr handler) {
+ if (GetHandleSignalMode(signum) == kHandleSignalExclusive)
+ return (uptr) nullptr;
+ SIGNAL_INTERCEPTOR_SIGNAL_IMPL(signal, signum, handler);
+}
+#define INIT_SIGNAL COMMON_INTERCEPT_FUNCTION(signal)
+
+INTERCEPTOR(int, sigaction_symname, int signum,
+ const __sanitizer_sigaction *act, __sanitizer_sigaction *oldact) {
+ if (GetHandleSignalMode(signum) == kHandleSignalExclusive) {
+ if (!oldact) return 0;
+ act = nullptr;
+ }
+ SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact);
+}
+#define INIT_SIGACTION COMMON_INTERCEPT_FUNCTION(sigaction_symname)
+
+namespace __sanitizer {
+int real_sigaction(int signum, const void *act, void *oldact) {
+ return REAL(sigaction_symname)(signum, (const __sanitizer_sigaction *)act,
+ (__sanitizer_sigaction *)oldact);
+}
+} // namespace __sanitizer
+#else // SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION
+#define INIT_SIGNAL
+#define INIT_SIGACTION
+// We need to have defined REAL(sigaction) on other systems.
+namespace __sanitizer {
+struct __sanitizer_sigaction;
+}
+DEFINE_REAL(int, sigaction, int signum, const __sanitizer_sigaction *act,
+ __sanitizer_sigaction *oldact)
+#endif // SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION
+
+static void InitializeSignalInterceptors() {
+ static bool was_called_once;
+ CHECK(!was_called_once);
+ was_called_once = true;
+
+ INIT_BSD_SIGNAL;
+ INIT_SIGNAL;
+ INIT_SIGACTION;
+}
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_solaris.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_solaris.cpp
new file mode 100644
index 00000000000..62c40affc9a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_solaris.cpp
@@ -0,0 +1,230 @@
+//===-- sanitizer_solaris.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between various sanitizers' runtime libraries and
+// implements Solaris-specific functions.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_SOLARIS
+
+#include <stdio.h>
+
+#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_platform_limits_posix.h"
+#include "sanitizer_procmaps.h"
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <sched.h>
+#include <thread.h>
+#include <synch.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+namespace __sanitizer {
+
+//#include "sanitizer_syscall_generic.inc"
+
+#define _REAL(func) _ ## func
+#define DECLARE__REAL(ret_type, func, ...) \
+ extern "C" ret_type _REAL(func)(__VA_ARGS__)
+#define DECLARE__REAL_AND_INTERNAL(ret_type, func, ...) \
+ DECLARE__REAL(ret_type, func, __VA_ARGS__); \
+ ret_type internal_ ## func(__VA_ARGS__)
+
+#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
+#define _REAL64(func) _ ## func ## 64
+#else
+#define _REAL64(func) _REAL(func)
+#endif
+#define DECLARE__REAL64(ret_type, func, ...) \
+ extern "C" ret_type _REAL64(func)(__VA_ARGS__)
+#define DECLARE__REAL_AND_INTERNAL64(ret_type, func, ...) \
+ DECLARE__REAL64(ret_type, func, __VA_ARGS__); \
+ ret_type internal_ ## func(__VA_ARGS__)
+
+// ---------------------- sanitizer_libc.h
+DECLARE__REAL_AND_INTERNAL64(uptr, mmap, void *addr, uptr /*size_t*/ length,
+ int prot, int flags, int fd, OFF_T offset) {
+ return (uptr)_REAL64(mmap)(addr, length, prot, flags, fd, offset);
+}
+
+DECLARE__REAL_AND_INTERNAL(uptr, munmap, void *addr, uptr length) {
+ return _REAL(munmap)(addr, length);
+}
+
+DECLARE__REAL_AND_INTERNAL(int, mprotect, void *addr, uptr length, int prot) {
+ return _REAL(mprotect)(addr, length, prot);
+}
+
+// Illumos' declaration of madvise cannot be made visible if _XOPEN_SOURCE
+// is defined as g++ does on Solaris.
+//
+// This declaration is consistent with Solaris 11.4. Both Illumos and Solaris
+// versions older than 11.4 declared madvise with a caddr_t as the first
+// argument, but we don't currently support Solaris versions older than 11.4,
+// and as mentioned above the declaration is not visible on Illumos so we can
+// use any declaration we like on Illumos.
+extern "C" int madvise(void *, size_t, int);
+
+int internal_madvise(uptr addr, uptr length, int advice) {
+ return madvise((void *)addr, length, advice);
+}
+
+DECLARE__REAL_AND_INTERNAL(uptr, close, fd_t fd) {
+ return _REAL(close)(fd);
+}
+
+extern "C" int _REAL64(open)(const char *, int, ...);
+
+uptr internal_open(const char *filename, int flags) {
+ return _REAL64(open)(filename, flags);
+}
+
+uptr internal_open(const char *filename, int flags, u32 mode) {
+ return _REAL64(open)(filename, flags, mode);
+}
+
+DECLARE__REAL_AND_INTERNAL(uptr, read, fd_t fd, void *buf, uptr count) {
+ return _REAL(read)(fd, buf, count);
+}
+
+DECLARE__REAL_AND_INTERNAL(uptr, write, fd_t fd, const void *buf, uptr count) {
+ return _REAL(write)(fd, buf, count);
+}
+
+// FIXME: There's only _ftruncate64 beginning with Solaris 11.
+DECLARE__REAL_AND_INTERNAL(uptr, ftruncate, fd_t fd, uptr size) {
+ return ftruncate(fd, size);
+}
+
+DECLARE__REAL_AND_INTERNAL64(uptr, stat, const char *path, void *buf) {
+ return _REAL64(stat)(path, (struct stat *)buf);
+}
+
+DECLARE__REAL_AND_INTERNAL64(uptr, lstat, const char *path, void *buf) {
+ return _REAL64(lstat)(path, (struct stat *)buf);
+}
+
+DECLARE__REAL_AND_INTERNAL64(uptr, fstat, fd_t fd, void *buf) {
+ return _REAL64(fstat)(fd, (struct stat *)buf);
+}
+
+uptr internal_filesize(fd_t fd) {
+ struct stat st;
+ if (internal_fstat(fd, &st))
+ return -1;
+ return (uptr)st.st_size;
+}
+
+DECLARE__REAL_AND_INTERNAL(uptr, dup, int oldfd) {
+ return _REAL(dup)(oldfd);
+}
+
+DECLARE__REAL_AND_INTERNAL(uptr, dup2, int oldfd, int newfd) {
+ return _REAL(dup2)(oldfd, newfd);
+}
+
+DECLARE__REAL_AND_INTERNAL(uptr, readlink, const char *path, char *buf,
+ uptr bufsize) {
+ return _REAL(readlink)(path, buf, bufsize);
+}
+
+DECLARE__REAL_AND_INTERNAL(uptr, unlink, const char *path) {
+ return _REAL(unlink)(path);
+}
+
+DECLARE__REAL_AND_INTERNAL(uptr, rename, const char *oldpath,
+ const char *newpath) {
+ return _REAL(rename)(oldpath, newpath);
+}
+
+DECLARE__REAL_AND_INTERNAL(uptr, sched_yield, void) {
+ return sched_yield();
+}
+
+DECLARE__REAL_AND_INTERNAL(void, usleep, u64 useconds) {
+ struct timespec ts;
+ ts.tv_sec = useconds / 1000000;
+ ts.tv_nsec = (useconds % 1000000) * 1000;
+ nanosleep(&ts, nullptr);
+}
+
+DECLARE__REAL_AND_INTERNAL(uptr, execve, const char *filename,
+ char *const argv[], char *const envp[]) {
+ return _REAL(execve)(filename, argv, envp);
+}
+
+DECLARE__REAL_AND_INTERNAL(uptr, waitpid, int pid, int *status, int options) {
+ return _REAL(waitpid)(pid, status, options);
+}
+
+DECLARE__REAL_AND_INTERNAL(uptr, getpid, void) {
+ return _REAL(getpid)();
+}
+
+// FIXME: This might be wrong: _getdents doesn't take a struct linux_dirent *.
+DECLARE__REAL_AND_INTERNAL64(uptr, getdents, fd_t fd, struct linux_dirent *dirp,
+ unsigned int count) {
+ return _REAL64(getdents)(fd, dirp, count);
+}
+
+DECLARE__REAL_AND_INTERNAL64(uptr, lseek, fd_t fd, OFF_T offset, int whence) {
+ return _REAL64(lseek)(fd, offset, whence);
+}
+
+// FIXME: This might be wrong: _sigfillset doesn't take a
+// __sanitizer_sigset_t *.
+DECLARE__REAL_AND_INTERNAL(void, sigfillset, __sanitizer_sigset_t *set) {
+ _REAL(sigfillset)(set);
+}
+
+// FIXME: This might be wrong: _sigprocmask doesn't take __sanitizer_sigset_t *.
+DECLARE__REAL_AND_INTERNAL(uptr, sigprocmask, int how,
+ __sanitizer_sigset_t *set,
+ __sanitizer_sigset_t *oldset) {
+ return _REAL(sigprocmask)(how, set, oldset);
+}
+
+DECLARE__REAL_AND_INTERNAL(int, fork, void) {
+ // TODO(glider): this may call user's pthread_atfork() handlers which is bad.
+ return _REAL(fork)();
+}
+
+u64 NanoTime() {
+ return gethrtime();
+}
+
+uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) {
+ // FIXME: No internal variant.
+ return clock_gettime(clk_id, (timespec *)tp);
+}
+
+// ----------------- sanitizer_common.h
+void FutexWait(atomic_uint32_t *p, u32 cmp) {
+ // FIXME: implement actual blocking.
+ sched_yield();
+}
+
+void FutexWake(atomic_uint32_t *p, u32 count) {}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SOLARIS
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_solaris.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_solaris.h
new file mode 100644
index 00000000000..2a21693efbf
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_solaris.h
@@ -0,0 +1,56 @@
+//===-- sanitizer_solaris.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer runtime. It contains Solaris-specific
+// definitions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_SOLARIS_H
+#define SANITIZER_SOLARIS_H
+
+#include "sanitizer_internal_defs.h"
+
+#if SANITIZER_SOLARIS
+
+#include <link.h>
+
+namespace __sanitizer {
+
+// Beginning of declaration from OpenSolaris/Illumos
+// $SRC/cmd/sgs/include/rtld.h.
+struct Rt_map {
+ Link_map rt_public;
+ const char *rt_pathname;
+ ulong_t rt_padstart;
+ ulong_t rt_padimlen;
+ ulong_t rt_msize;
+ uint_t rt_flags;
+ uint_t rt_flags1;
+ ulong_t rt_tlsmodid;
+};
+
+// Structure matching the Solaris 11.4 struct dl_phdr_info used to determine
+// presence of dlpi_tls_modid field at runtime. Cf. Solaris 11.4
+// dl_iterate_phdr(3C), Example 2.
+struct dl_phdr_info_test {
+ ElfW(Addr) dlpi_addr;
+ const char *dlpi_name;
+ const ElfW(Phdr) * dlpi_phdr;
+ ElfW(Half) dlpi_phnum;
+ u_longlong_t dlpi_adds;
+ u_longlong_t dlpi_subs;
+ size_t dlpi_tls_modid;
+ void *dlpi_tls_data;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SOLARIS
+
+#endif // SANITIZER_SOLARIS_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stack_store.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stack_store.cpp
new file mode 100644
index 00000000000..148470943b4
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stack_store.cpp
@@ -0,0 +1,379 @@
+//===-- sanitizer_stack_store.cpp -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_stack_store.h"
+
+#include "sanitizer_atomic.h"
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_leb128.h"
+#include "sanitizer_lzw.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_stacktrace.h"
+
+namespace __sanitizer {
+
+namespace {
+struct StackTraceHeader {
+ static constexpr u32 kStackSizeBits = 8;
+
+ u8 size;
+ u8 tag;
+ explicit StackTraceHeader(const StackTrace &trace)
+ : size(Min<uptr>(trace.size, (1u << 8) - 1)), tag(trace.tag) {
+ CHECK_EQ(trace.tag, static_cast<uptr>(tag));
+ }
+ explicit StackTraceHeader(uptr h)
+ : size(h & ((1 << kStackSizeBits) - 1)), tag(h >> kStackSizeBits) {}
+
+ uptr ToUptr() const {
+ return static_cast<uptr>(size) | (static_cast<uptr>(tag) << kStackSizeBits);
+ }
+};
+} // namespace
+
+StackStore::Id StackStore::Store(const StackTrace &trace, uptr *pack) {
+ if (!trace.size && !trace.tag)
+ return 0;
+ StackTraceHeader h(trace);
+ uptr idx = 0;
+ *pack = 0;
+ uptr *stack_trace = Alloc(h.size + 1, &idx, pack);
+ *stack_trace = h.ToUptr();
+ internal_memcpy(stack_trace + 1, trace.trace, h.size * sizeof(uptr));
+ *pack += blocks_[GetBlockIdx(idx)].Stored(h.size + 1);
+ return OffsetToId(idx);
+}
+
+StackTrace StackStore::Load(Id id) {
+ if (!id)
+ return {};
+ uptr idx = IdToOffset(id);
+ uptr block_idx = GetBlockIdx(idx);
+ CHECK_LT(block_idx, ARRAY_SIZE(blocks_));
+ const uptr *stack_trace = blocks_[block_idx].GetOrUnpack(this);
+ if (!stack_trace)
+ return {};
+ stack_trace += GetInBlockIdx(idx);
+ StackTraceHeader h(*stack_trace);
+ return StackTrace(stack_trace + 1, h.size, h.tag);
+}
+
+uptr StackStore::Allocated() const {
+ return atomic_load_relaxed(&allocated_) + sizeof(*this);
+}
+
+uptr *StackStore::Alloc(uptr count, uptr *idx, uptr *pack) {
+ for (;;) {
+ // Optimisic lock-free allocation, essentially try to bump the
+ // total_frames_.
+ uptr start = atomic_fetch_add(&total_frames_, count, memory_order_relaxed);
+ uptr block_idx = GetBlockIdx(start);
+ uptr last_idx = GetBlockIdx(start + count - 1);
+ if (LIKELY(block_idx == last_idx)) {
+ // Fits into the a single block.
+ CHECK_LT(block_idx, ARRAY_SIZE(blocks_));
+ *idx = start;
+ return blocks_[block_idx].GetOrCreate(this) + GetInBlockIdx(start);
+ }
+
+ // Retry. We can't use range allocated in two different blocks.
+ CHECK_LE(count, kBlockSizeFrames);
+ uptr in_first = kBlockSizeFrames - GetInBlockIdx(start);
+ // Mark tail/head of these blocks as "stored".to avoid waiting before we can
+ // Pack().
+ *pack += blocks_[block_idx].Stored(in_first);
+ *pack += blocks_[last_idx].Stored(count - in_first);
+ }
+}
+
+void *StackStore::Map(uptr size, const char *mem_type) {
+ atomic_fetch_add(&allocated_, size, memory_order_relaxed);
+ return MmapNoReserveOrDie(size, mem_type);
+}
+
+void StackStore::Unmap(void *addr, uptr size) {
+ atomic_fetch_sub(&allocated_, size, memory_order_relaxed);
+ UnmapOrDie(addr, size);
+}
+
+uptr StackStore::Pack(Compression type) {
+ uptr res = 0;
+ for (BlockInfo &b : blocks_) res += b.Pack(type, this);
+ return res;
+}
+
+void StackStore::LockAll() {
+ for (BlockInfo &b : blocks_) b.Lock();
+}
+
+void StackStore::UnlockAll() {
+ for (BlockInfo &b : blocks_) b.Unlock();
+}
+
+void StackStore::TestOnlyUnmap() {
+ for (BlockInfo &b : blocks_) b.TestOnlyUnmap(this);
+ internal_memset(this, 0, sizeof(*this));
+}
+
+uptr *StackStore::BlockInfo::Get() const {
+ // Idiomatic double-checked locking uses memory_order_acquire here. But
+ // relaxed is fine for us, justification is similar to
+ // TwoLevelMap::GetOrCreate.
+ return reinterpret_cast<uptr *>(atomic_load_relaxed(&data_));
+}
+
+uptr *StackStore::BlockInfo::Create(StackStore *store) {
+ SpinMutexLock l(&mtx_);
+ uptr *ptr = Get();
+ if (!ptr) {
+ ptr = reinterpret_cast<uptr *>(store->Map(kBlockSizeBytes, "StackStore"));
+ atomic_store(&data_, reinterpret_cast<uptr>(ptr), memory_order_release);
+ }
+ return ptr;
+}
+
+uptr *StackStore::BlockInfo::GetOrCreate(StackStore *store) {
+ uptr *ptr = Get();
+ if (LIKELY(ptr))
+ return ptr;
+ return Create(store);
+}
+
+class SLeb128Encoder {
+ public:
+ SLeb128Encoder(u8 *begin, u8 *end) : begin(begin), end(end) {}
+
+ bool operator==(const SLeb128Encoder &other) const {
+ return begin == other.begin;
+ }
+
+ bool operator!=(const SLeb128Encoder &other) const {
+ return begin != other.begin;
+ }
+
+ SLeb128Encoder &operator=(uptr v) {
+ sptr diff = v - previous;
+ begin = EncodeSLEB128(diff, begin, end);
+ previous = v;
+ return *this;
+ }
+ SLeb128Encoder &operator*() { return *this; }
+ SLeb128Encoder &operator++() { return *this; }
+
+ u8 *base() const { return begin; }
+
+ private:
+ u8 *begin;
+ u8 *end;
+ uptr previous = 0;
+};
+
+class SLeb128Decoder {
+ public:
+ SLeb128Decoder(const u8 *begin, const u8 *end) : begin(begin), end(end) {}
+
+ bool operator==(const SLeb128Decoder &other) const {
+ return begin == other.begin;
+ }
+
+ bool operator!=(const SLeb128Decoder &other) const {
+ return begin != other.begin;
+ }
+
+ uptr operator*() {
+ sptr diff;
+ begin = DecodeSLEB128(begin, end, &diff);
+ previous += diff;
+ return previous;
+ }
+ SLeb128Decoder &operator++() { return *this; }
+
+ SLeb128Decoder operator++(int) { return *this; }
+
+ private:
+ const u8 *begin;
+ const u8 *end;
+ uptr previous = 0;
+};
+
+static u8 *CompressDelta(const uptr *from, const uptr *from_end, u8 *to,
+ u8 *to_end) {
+ SLeb128Encoder encoder(to, to_end);
+ for (; from != from_end; ++from, ++encoder) *encoder = *from;
+ return encoder.base();
+}
+
+static uptr *UncompressDelta(const u8 *from, const u8 *from_end, uptr *to,
+ uptr *to_end) {
+ SLeb128Decoder decoder(from, from_end);
+ SLeb128Decoder end(from_end, from_end);
+ for (; decoder != end; ++to, ++decoder) *to = *decoder;
+ CHECK_EQ(to, to_end);
+ return to;
+}
+
+static u8 *CompressLzw(const uptr *from, const uptr *from_end, u8 *to,
+ u8 *to_end) {
+ SLeb128Encoder encoder(to, to_end);
+ encoder = LzwEncode<uptr>(from, from_end, encoder);
+ return encoder.base();
+}
+
+static uptr *UncompressLzw(const u8 *from, const u8 *from_end, uptr *to,
+ uptr *to_end) {
+ SLeb128Decoder decoder(from, from_end);
+ SLeb128Decoder end(from_end, from_end);
+ to = LzwDecode<uptr>(decoder, end, to);
+ CHECK_EQ(to, to_end);
+ return to;
+}
+
+#if defined(_MSC_VER) && !defined(__clang__)
+# pragma warning(push)
+// Disable 'nonstandard extension used: zero-sized array in struct/union'.
+# pragma warning(disable : 4200)
+#endif
+namespace {
+struct PackedHeader {
+ uptr size;
+ StackStore::Compression type;
+ u8 data[];
+};
+} // namespace
+#if defined(_MSC_VER) && !defined(__clang__)
+# pragma warning(pop)
+#endif
+
+uptr *StackStore::BlockInfo::GetOrUnpack(StackStore *store) {
+ SpinMutexLock l(&mtx_);
+ switch (state) {
+ case State::Storing:
+ state = State::Unpacked;
+ FALLTHROUGH;
+ case State::Unpacked:
+ return Get();
+ case State::Packed:
+ break;
+ }
+
+ u8 *ptr = reinterpret_cast<u8 *>(Get());
+ CHECK_NE(nullptr, ptr);
+ const PackedHeader *header = reinterpret_cast<const PackedHeader *>(ptr);
+ CHECK_LE(header->size, kBlockSizeBytes);
+ CHECK_GE(header->size, sizeof(PackedHeader));
+
+ uptr packed_size_aligned = RoundUpTo(header->size, GetPageSizeCached());
+
+ uptr *unpacked =
+ reinterpret_cast<uptr *>(store->Map(kBlockSizeBytes, "StackStoreUnpack"));
+
+ uptr *unpacked_end;
+ switch (header->type) {
+ case Compression::Delta:
+ unpacked_end = UncompressDelta(header->data, ptr + header->size, unpacked,
+ unpacked + kBlockSizeFrames);
+ break;
+ case Compression::LZW:
+ unpacked_end = UncompressLzw(header->data, ptr + header->size, unpacked,
+ unpacked + kBlockSizeFrames);
+ break;
+ default:
+ UNREACHABLE("Unexpected type");
+ break;
+ }
+
+ CHECK_EQ(kBlockSizeFrames, unpacked_end - unpacked);
+
+ MprotectReadOnly(reinterpret_cast<uptr>(unpacked), kBlockSizeBytes);
+ atomic_store(&data_, reinterpret_cast<uptr>(unpacked), memory_order_release);
+ store->Unmap(ptr, packed_size_aligned);
+
+ state = State::Unpacked;
+ return Get();
+}
+
+uptr StackStore::BlockInfo::Pack(Compression type, StackStore *store) {
+ if (type == Compression::None)
+ return 0;
+
+ SpinMutexLock l(&mtx_);
+ switch (state) {
+ case State::Unpacked:
+ case State::Packed:
+ return 0;
+ case State::Storing:
+ break;
+ }
+
+ uptr *ptr = Get();
+ if (!ptr || !Stored(0))
+ return 0;
+
+ u8 *packed =
+ reinterpret_cast<u8 *>(store->Map(kBlockSizeBytes, "StackStorePack"));
+ PackedHeader *header = reinterpret_cast<PackedHeader *>(packed);
+ u8 *alloc_end = packed + kBlockSizeBytes;
+
+ u8 *packed_end = nullptr;
+ switch (type) {
+ case Compression::Delta:
+ packed_end =
+ CompressDelta(ptr, ptr + kBlockSizeFrames, header->data, alloc_end);
+ break;
+ case Compression::LZW:
+ packed_end =
+ CompressLzw(ptr, ptr + kBlockSizeFrames, header->data, alloc_end);
+ break;
+ default:
+ UNREACHABLE("Unexpected type");
+ break;
+ }
+
+ header->type = type;
+ header->size = packed_end - packed;
+
+ VPrintf(1, "Packed block of %zu KiB to %zu KiB\n", kBlockSizeBytes >> 10,
+ header->size >> 10);
+
+ if (kBlockSizeBytes - header->size < kBlockSizeBytes / 8) {
+ VPrintf(1, "Undo and keep block unpacked\n");
+ MprotectReadOnly(reinterpret_cast<uptr>(ptr), kBlockSizeBytes);
+ store->Unmap(packed, kBlockSizeBytes);
+ state = State::Unpacked;
+ return 0;
+ }
+
+ uptr packed_size_aligned = RoundUpTo(header->size, GetPageSizeCached());
+ store->Unmap(packed + packed_size_aligned,
+ kBlockSizeBytes - packed_size_aligned);
+ MprotectReadOnly(reinterpret_cast<uptr>(packed), packed_size_aligned);
+
+ atomic_store(&data_, reinterpret_cast<uptr>(packed), memory_order_release);
+ store->Unmap(ptr, kBlockSizeBytes);
+
+ state = State::Packed;
+ return kBlockSizeBytes - packed_size_aligned;
+}
+
+void StackStore::BlockInfo::TestOnlyUnmap(StackStore *store) {
+ if (uptr *ptr = Get())
+ store->Unmap(ptr, kBlockSizeBytes);
+}
+
+bool StackStore::BlockInfo::Stored(uptr n) {
+ return n + atomic_fetch_add(&stored_, n, memory_order_release) ==
+ kBlockSizeFrames;
+}
+
+bool StackStore::BlockInfo::IsPacked() const {
+ SpinMutexLock l(&mtx_);
+ return state == State::Packed;
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stack_store.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stack_store.h
new file mode 100644
index 00000000000..4f1a8caac6e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stack_store.h
@@ -0,0 +1,121 @@
+//===-- sanitizer_stack_store.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_STACK_STORE_H
+#define SANITIZER_STACK_STORE_H
+
+#include "sanitizer_atomic.h"
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_mutex.h"
+#include "sanitizer_stacktrace.h"
+
+namespace __sanitizer {
+
+class StackStore {
+ static constexpr uptr kBlockSizeFrames = 0x100000;
+ static constexpr uptr kBlockCount = 0x1000;
+ static constexpr uptr kBlockSizeBytes = kBlockSizeFrames * sizeof(uptr);
+
+ public:
+ enum class Compression : u8 {
+ None = 0,
+ Delta,
+ LZW,
+ };
+
+ constexpr StackStore() = default;
+
+ using Id = u32; // Enough for 2^32 * sizeof(uptr) bytes of traces.
+ static_assert(u64(kBlockCount) * kBlockSizeFrames == 1ull << (sizeof(Id) * 8),
+ "");
+
+ Id Store(const StackTrace &trace,
+ uptr *pack /* number of blocks completed by this call */);
+ StackTrace Load(Id id);
+ uptr Allocated() const;
+
+ // Packs all blocks which don't expect any more writes. A block is going to be
+ // packed once. As soon trace from that block was requested, it will unpack
+ // and stay unpacked after that.
+ // Returns the number of released bytes.
+ uptr Pack(Compression type);
+
+ void LockAll();
+ void UnlockAll();
+
+ void TestOnlyUnmap();
+
+ private:
+ friend class StackStoreTest;
+ static constexpr uptr GetBlockIdx(uptr frame_idx) {
+ return frame_idx / kBlockSizeFrames;
+ }
+
+ static constexpr uptr GetInBlockIdx(uptr frame_idx) {
+ return frame_idx % kBlockSizeFrames;
+ }
+
+ static constexpr uptr IdToOffset(Id id) {
+ CHECK_NE(id, 0);
+ return id - 1; // Avoid zero as id.
+ }
+
+ static constexpr uptr OffsetToId(Id id) {
+ // This makes UINT32_MAX to 0 and it will be retrived as and empty stack.
+ // But this is not a problem as we will not be able to store anything after
+ // that anyway.
+ return id + 1; // Avoid zero as id.
+ }
+
+ uptr *Alloc(uptr count, uptr *idx, uptr *pack);
+
+ void *Map(uptr size, const char *mem_type);
+ void Unmap(void *addr, uptr size);
+
+ // Total number of allocated frames.
+ atomic_uintptr_t total_frames_ = {};
+
+ // Tracks total allocated memory in bytes.
+ atomic_uintptr_t allocated_ = {};
+
+ // Each block will hold pointer to exactly kBlockSizeFrames.
+ class BlockInfo {
+ atomic_uintptr_t data_;
+ // Counter to track store progress to know when we can Pack() the block.
+ atomic_uint32_t stored_;
+ // Protects alloc of new blocks.
+ mutable StaticSpinMutex mtx_;
+
+ enum class State : u8 {
+ Storing = 0,
+ Packed,
+ Unpacked,
+ };
+ State state SANITIZER_GUARDED_BY(mtx_);
+
+ uptr *Create(StackStore *store);
+
+ public:
+ uptr *Get() const;
+ uptr *GetOrCreate(StackStore *store);
+ uptr *GetOrUnpack(StackStore *store);
+ uptr Pack(Compression type, StackStore *store);
+ void TestOnlyUnmap(StackStore *store);
+ bool Stored(uptr n);
+ bool IsPacked() const;
+ void Lock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS { mtx_.Lock(); }
+ void Unlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS { mtx_.Unlock(); }
+ };
+
+ BlockInfo blocks_[kBlockCount] = {};
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_STACK_STORE_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp
new file mode 100644
index 00000000000..a746d462193
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp
@@ -0,0 +1,247 @@
+//===-- sanitizer_stackdepot.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_stackdepot.h"
+
+#include "sanitizer_atomic.h"
+#include "sanitizer_common.h"
+#include "sanitizer_hash.h"
+#include "sanitizer_mutex.h"
+#include "sanitizer_stack_store.h"
+#include "sanitizer_stackdepotbase.h"
+
+namespace __sanitizer {
+
+struct StackDepotNode {
+ using hash_type = u64;
+ hash_type stack_hash;
+ u32 link;
+ StackStore::Id store_id;
+
+ static const u32 kTabSizeLog = SANITIZER_ANDROID ? 16 : 20;
+
+ typedef StackTrace args_type;
+ bool eq(hash_type hash, const args_type &args) const {
+ return hash == stack_hash;
+ }
+ static uptr allocated();
+ static hash_type hash(const args_type &args) {
+ MurMur2Hash64Builder H(args.size * sizeof(uptr));
+ for (uptr i = 0; i < args.size; i++) H.add(args.trace[i]);
+ H.add(args.tag);
+ return H.get();
+ }
+ static bool is_valid(const args_type &args) {
+ return args.size > 0 && args.trace;
+ }
+ void store(u32 id, const args_type &args, hash_type hash);
+ args_type load(u32 id) const;
+ static StackDepotHandle get_handle(u32 id);
+
+ typedef StackDepotHandle handle_type;
+};
+
+static StackStore stackStore;
+
+// FIXME(dvyukov): this single reserved bit is used in TSan.
+typedef StackDepotBase<StackDepotNode, 1, StackDepotNode::kTabSizeLog>
+ StackDepot;
+static StackDepot theDepot;
+// Keep mutable data out of frequently access nodes to improve caching
+// efficiency.
+static TwoLevelMap<atomic_uint32_t, StackDepot::kNodesSize1,
+ StackDepot::kNodesSize2>
+ useCounts;
+
+int StackDepotHandle::use_count() const {
+ return atomic_load_relaxed(&useCounts[id_]);
+}
+
+void StackDepotHandle::inc_use_count_unsafe() {
+ atomic_fetch_add(&useCounts[id_], 1, memory_order_relaxed);
+}
+
+uptr StackDepotNode::allocated() {
+ return stackStore.Allocated() + useCounts.MemoryUsage();
+}
+
+static void CompressStackStore() {
+ u64 start = Verbosity() >= 1 ? MonotonicNanoTime() : 0;
+ uptr diff = stackStore.Pack(static_cast<StackStore::Compression>(
+ Abs(common_flags()->compress_stack_depot)));
+ if (!diff)
+ return;
+ if (Verbosity() >= 1) {
+ u64 finish = MonotonicNanoTime();
+ uptr total_before = theDepot.GetStats().allocated + diff;
+ VPrintf(1, "%s: StackDepot released %zu KiB out of %zu KiB in %llu ms\n",
+ SanitizerToolName, diff >> 10, total_before >> 10,
+ (finish - start) / 1000000);
+ }
+}
+
+namespace {
+
+class CompressThread {
+ public:
+ constexpr CompressThread() = default;
+ void NewWorkNotify();
+ void Stop();
+ void LockAndStop() SANITIZER_NO_THREAD_SAFETY_ANALYSIS;
+ void Unlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS;
+
+ private:
+ enum class State {
+ NotStarted = 0,
+ Started,
+ Failed,
+ Stopped,
+ };
+
+ void Run();
+
+ bool WaitForWork() {
+ semaphore_.Wait();
+ return atomic_load(&run_, memory_order_acquire);
+ }
+
+ Semaphore semaphore_ = {};
+ StaticSpinMutex mutex_ = {};
+ State state_ SANITIZER_GUARDED_BY(mutex_) = State::NotStarted;
+ void *thread_ SANITIZER_GUARDED_BY(mutex_) = nullptr;
+ atomic_uint8_t run_ = {};
+};
+
+static CompressThread compress_thread;
+
+void CompressThread::NewWorkNotify() {
+ int compress = common_flags()->compress_stack_depot;
+ if (!compress)
+ return;
+ if (compress > 0 /* for testing or debugging */) {
+ SpinMutexLock l(&mutex_);
+ if (state_ == State::NotStarted) {
+ atomic_store(&run_, 1, memory_order_release);
+ CHECK_EQ(nullptr, thread_);
+ thread_ = internal_start_thread(
+ [](void *arg) -> void * {
+ reinterpret_cast<CompressThread *>(arg)->Run();
+ return nullptr;
+ },
+ this);
+ state_ = thread_ ? State::Started : State::Failed;
+ }
+ if (state_ == State::Started) {
+ semaphore_.Post();
+ return;
+ }
+ }
+ CompressStackStore();
+}
+
+void CompressThread::Run() {
+ VPrintf(1, "%s: StackDepot compression thread started\n", SanitizerToolName);
+ while (WaitForWork()) CompressStackStore();
+ VPrintf(1, "%s: StackDepot compression thread stopped\n", SanitizerToolName);
+}
+
+void CompressThread::Stop() {
+ void *t = nullptr;
+ {
+ SpinMutexLock l(&mutex_);
+ if (state_ != State::Started)
+ return;
+ state_ = State::Stopped;
+ CHECK_NE(nullptr, thread_);
+ t = thread_;
+ thread_ = nullptr;
+ }
+ atomic_store(&run_, 0, memory_order_release);
+ semaphore_.Post();
+ internal_join_thread(t);
+}
+
+void CompressThread::LockAndStop() {
+ mutex_.Lock();
+ if (state_ != State::Started)
+ return;
+ CHECK_NE(nullptr, thread_);
+
+ atomic_store(&run_, 0, memory_order_release);
+ semaphore_.Post();
+ internal_join_thread(thread_);
+ // Allow to restart after Unlock() if needed.
+ state_ = State::NotStarted;
+ thread_ = nullptr;
+}
+
+void CompressThread::Unlock() { mutex_.Unlock(); }
+
+} // namespace
+
+void StackDepotNode::store(u32 id, const args_type &args, hash_type hash) {
+ stack_hash = hash;
+ uptr pack = 0;
+ store_id = stackStore.Store(args, &pack);
+ if (LIKELY(!pack))
+ return;
+ compress_thread.NewWorkNotify();
+}
+
+StackDepotNode::args_type StackDepotNode::load(u32 id) const {
+ if (!store_id)
+ return {};
+ return stackStore.Load(store_id);
+}
+
+StackDepotStats StackDepotGetStats() { return theDepot.GetStats(); }
+
+u32 StackDepotPut(StackTrace stack) { return theDepot.Put(stack); }
+
+StackDepotHandle StackDepotPut_WithHandle(StackTrace stack) {
+ return StackDepotNode::get_handle(theDepot.Put(stack));
+}
+
+StackTrace StackDepotGet(u32 id) {
+ return theDepot.Get(id);
+}
+
+void StackDepotLockAll() {
+ theDepot.LockAll();
+ compress_thread.LockAndStop();
+ stackStore.LockAll();
+}
+
+void StackDepotUnlockAll() {
+ stackStore.UnlockAll();
+ compress_thread.Unlock();
+ theDepot.UnlockAll();
+}
+
+void StackDepotPrintAll() {
+#if !SANITIZER_GO
+ theDepot.PrintAll();
+#endif
+}
+
+void StackDepotStopBackgroundThread() { compress_thread.Stop(); }
+
+StackDepotHandle StackDepotNode::get_handle(u32 id) {
+ return StackDepotHandle(&theDepot.nodes[id], id);
+}
+
+void StackDepotTestOnlyUnmap() {
+ theDepot.TestOnlyUnmap();
+ stackStore.TestOnlyUnmap();
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stackdepot.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stackdepot.h
new file mode 100644
index 00000000000..cca6fd53468
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stackdepot.h
@@ -0,0 +1,51 @@
+//===-- sanitizer_stackdepot.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_STACKDEPOT_H
+#define SANITIZER_STACKDEPOT_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_stacktrace.h"
+
+namespace __sanitizer {
+
+// StackDepot efficiently stores huge amounts of stack traces.
+struct StackDepotNode;
+struct StackDepotHandle {
+ StackDepotNode *node_ = nullptr;
+ u32 id_ = 0;
+ StackDepotHandle(StackDepotNode *node, u32 id) : node_(node), id_(id) {}
+ bool valid() const { return node_; }
+ u32 id() const { return id_; }
+ int use_count() const;
+ void inc_use_count_unsafe();
+};
+
+const int kStackDepotMaxUseCount = 1U << (SANITIZER_ANDROID ? 16 : 20);
+
+StackDepotStats StackDepotGetStats();
+u32 StackDepotPut(StackTrace stack);
+StackDepotHandle StackDepotPut_WithHandle(StackTrace stack);
+// Retrieves a stored stack trace by the id.
+StackTrace StackDepotGet(u32 id);
+
+void StackDepotLockAll();
+void StackDepotUnlockAll();
+void StackDepotPrintAll();
+void StackDepotStopBackgroundThread();
+
+void StackDepotTestOnlyUnmap();
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_STACKDEPOT_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h
new file mode 100644
index 00000000000..96d1ddc87fd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h
@@ -0,0 +1,194 @@
+//===-- sanitizer_stackdepotbase.h ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of a mapping from arbitrary values to unique 32-bit
+// identifiers.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_STACKDEPOTBASE_H
+#define SANITIZER_STACKDEPOTBASE_H
+
+#include <stdio.h>
+
+#include "sanitizer_atomic.h"
+#include "sanitizer_flat_map.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_mutex.h"
+
+namespace __sanitizer {
+
+template <class Node, int kReservedBits, int kTabSizeLog>
+class StackDepotBase {
+ static constexpr u32 kIdSizeLog =
+ sizeof(u32) * 8 - Max(kReservedBits, 1 /* At least 1 bit for locking. */);
+ static constexpr u32 kNodesSize1Log = kIdSizeLog / 2;
+ static constexpr u32 kNodesSize2Log = kIdSizeLog - kNodesSize1Log;
+ static constexpr int kTabSize = 1 << kTabSizeLog; // Hash table size.
+ static constexpr u32 kUnlockMask = (1ull << kIdSizeLog) - 1;
+ static constexpr u32 kLockMask = ~kUnlockMask;
+
+ public:
+ typedef typename Node::args_type args_type;
+ typedef typename Node::handle_type handle_type;
+ typedef typename Node::hash_type hash_type;
+
+ static constexpr u64 kNodesSize1 = 1ull << kNodesSize1Log;
+ static constexpr u64 kNodesSize2 = 1ull << kNodesSize2Log;
+
+ // Maps stack trace to an unique id.
+ u32 Put(args_type args, bool *inserted = nullptr);
+ // Retrieves a stored stack trace by the id.
+ args_type Get(u32 id);
+
+ StackDepotStats GetStats() const {
+ return {
+ atomic_load_relaxed(&n_uniq_ids),
+ nodes.MemoryUsage() + Node::allocated(),
+ };
+ }
+
+ void LockAll();
+ void UnlockAll();
+ void PrintAll();
+
+ void TestOnlyUnmap() {
+ nodes.TestOnlyUnmap();
+ internal_memset(this, 0, sizeof(*this));
+ }
+
+ private:
+ friend Node;
+ u32 find(u32 s, args_type args, hash_type hash) const;
+ static u32 lock(atomic_uint32_t *p);
+ static void unlock(atomic_uint32_t *p, u32 s);
+ atomic_uint32_t tab[kTabSize]; // Hash table of Node's.
+
+ atomic_uint32_t n_uniq_ids;
+
+ TwoLevelMap<Node, kNodesSize1, kNodesSize2> nodes;
+
+ friend class StackDepotReverseMap;
+};
+
+template <class Node, int kReservedBits, int kTabSizeLog>
+u32 StackDepotBase<Node, kReservedBits, kTabSizeLog>::find(
+ u32 s, args_type args, hash_type hash) const {
+ // Searches linked list s for the stack, returns its id.
+ for (; s;) {
+ const Node &node = nodes[s];
+ if (node.eq(hash, args))
+ return s;
+ s = node.link;
+ }
+ return 0;
+}
+
+template <class Node, int kReservedBits, int kTabSizeLog>
+u32 StackDepotBase<Node, kReservedBits, kTabSizeLog>::lock(atomic_uint32_t *p) {
+ // Uses the pointer lsb as mutex.
+ for (int i = 0;; i++) {
+ u32 cmp = atomic_load(p, memory_order_relaxed);
+ if ((cmp & kLockMask) == 0 &&
+ atomic_compare_exchange_weak(p, &cmp, cmp | kLockMask,
+ memory_order_acquire))
+ return cmp;
+ if (i < 10)
+ proc_yield(10);
+ else
+ internal_sched_yield();
+ }
+}
+
+template <class Node, int kReservedBits, int kTabSizeLog>
+void StackDepotBase<Node, kReservedBits, kTabSizeLog>::unlock(
+ atomic_uint32_t *p, u32 s) {
+ DCHECK_EQ(s & kLockMask, 0);
+ atomic_store(p, s, memory_order_release);
+}
+
+template <class Node, int kReservedBits, int kTabSizeLog>
+u32 StackDepotBase<Node, kReservedBits, kTabSizeLog>::Put(args_type args,
+ bool *inserted) {
+ if (inserted)
+ *inserted = false;
+ if (!LIKELY(Node::is_valid(args)))
+ return 0;
+ hash_type h = Node::hash(args);
+ atomic_uint32_t *p = &tab[h % kTabSize];
+ u32 v = atomic_load(p, memory_order_consume);
+ u32 s = v & kUnlockMask;
+ // First, try to find the existing stack.
+ u32 node = find(s, args, h);
+ if (LIKELY(node))
+ return node;
+
+ // If failed, lock, retry and insert new.
+ u32 s2 = lock(p);
+ if (s2 != s) {
+ node = find(s2, args, h);
+ if (node) {
+ unlock(p, s2);
+ return node;
+ }
+ }
+ s = atomic_fetch_add(&n_uniq_ids, 1, memory_order_relaxed) + 1;
+ CHECK_EQ(s & kUnlockMask, s);
+ CHECK_EQ(s & (((u32)-1) >> kReservedBits), s);
+ Node &new_node = nodes[s];
+ new_node.store(s, args, h);
+ new_node.link = s2;
+ unlock(p, s);
+ if (inserted) *inserted = true;
+ return s;
+}
+
+template <class Node, int kReservedBits, int kTabSizeLog>
+typename StackDepotBase<Node, kReservedBits, kTabSizeLog>::args_type
+StackDepotBase<Node, kReservedBits, kTabSizeLog>::Get(u32 id) {
+ if (id == 0)
+ return args_type();
+ CHECK_EQ(id & (((u32)-1) >> kReservedBits), id);
+ if (!nodes.contains(id))
+ return args_type();
+ const Node &node = nodes[id];
+ return node.load(id);
+}
+
+template <class Node, int kReservedBits, int kTabSizeLog>
+void StackDepotBase<Node, kReservedBits, kTabSizeLog>::LockAll() {
+ for (int i = 0; i < kTabSize; ++i) {
+ lock(&tab[i]);
+ }
+}
+
+template <class Node, int kReservedBits, int kTabSizeLog>
+void StackDepotBase<Node, kReservedBits, kTabSizeLog>::UnlockAll() {
+ for (int i = 0; i < kTabSize; ++i) {
+ atomic_uint32_t *p = &tab[i];
+ uptr s = atomic_load(p, memory_order_relaxed);
+ unlock(p, s & kUnlockMask);
+ }
+}
+
+template <class Node, int kReservedBits, int kTabSizeLog>
+void StackDepotBase<Node, kReservedBits, kTabSizeLog>::PrintAll() {
+ for (int i = 0; i < kTabSize; ++i) {
+ atomic_uint32_t *p = &tab[i];
+ u32 s = atomic_load(p, memory_order_consume) & kUnlockMask;
+ for (; s;) {
+ const Node &node = nodes[s];
+ Printf("Stack for id %u:\n", s);
+ node.load(s).Print();
+ s = node.link;
+ }
+ }
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_STACKDEPOTBASE_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp
new file mode 100644
index 00000000000..d24fae98213
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp
@@ -0,0 +1,169 @@
+//===-- sanitizer_stacktrace.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_stacktrace.h"
+
+#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_platform.h"
+#include "sanitizer_ptrauth.h"
+
+namespace __sanitizer {
+
+uptr StackTrace::GetNextInstructionPc(uptr pc) {
+#if defined(__aarch64__)
+ return STRIP_PAC_PC((void *)pc) + 4;
+#elif defined(__sparc__) || defined(__mips__)
+ return pc + 8;
+#elif SANITIZER_RISCV64
+ // Current check order is 4 -> 2 -> 6 -> 8
+ u8 InsnByte = *(u8 *)(pc);
+ if (((InsnByte & 0x3) == 0x3) && ((InsnByte & 0x1c) != 0x1c)) {
+ // xxxxxxxxxxxbbb11 | 32 bit | bbb != 111
+ return pc + 4;
+ }
+ if ((InsnByte & 0x3) != 0x3) {
+ // xxxxxxxxxxxxxxaa | 16 bit | aa != 11
+ return pc + 2;
+ }
+ // RISC-V encoding allows instructions to be up to 8 bytes long
+ if ((InsnByte & 0x3f) == 0x1f) {
+ // xxxxxxxxxx011111 | 48 bit |
+ return pc + 6;
+ }
+ if ((InsnByte & 0x7f) == 0x3f) {
+ // xxxxxxxxx0111111 | 64 bit |
+ return pc + 8;
+ }
+ // bail-out if could not figure out the instruction size
+ return 0;
+#elif SANITIZER_S390 || SANITIZER_I386 || SANITIZER_X32 || SANITIZER_X64
+ return pc + 1;
+#else
+ return pc + 4;
+#endif
+}
+
+uptr StackTrace::GetCurrentPc() {
+ return GET_CALLER_PC();
+}
+
+void BufferedStackTrace::Init(const uptr *pcs, uptr cnt, uptr extra_top_pc) {
+ size = cnt + !!extra_top_pc;
+ CHECK_LE(size, kStackTraceMax);
+ internal_memcpy(trace_buffer, pcs, cnt * sizeof(trace_buffer[0]));
+ if (extra_top_pc)
+ trace_buffer[cnt] = extra_top_pc;
+ top_frame_bp = 0;
+}
+
+// Sparc implementation is in its own file.
+#if !defined(__sparc__)
+
+// In GCC on ARM bp points to saved lr, not fp, so we should check the next
+// cell in stack to be a saved frame pointer. GetCanonicFrame returns the
+// pointer to saved frame pointer in any case.
+static inline uhwptr *GetCanonicFrame(uptr bp,
+ uptr stack_top,
+ uptr stack_bottom) {
+ CHECK_GT(stack_top, stack_bottom);
+#ifdef __arm__
+ if (!IsValidFrame(bp, stack_top, stack_bottom)) return 0;
+ uhwptr *bp_prev = (uhwptr *)bp;
+ if (IsValidFrame((uptr)bp_prev[0], stack_top, stack_bottom)) return bp_prev;
+ // The next frame pointer does not look right. This could be a GCC frame, step
+ // back by 1 word and try again.
+ if (IsValidFrame((uptr)bp_prev[-1], stack_top, stack_bottom))
+ return bp_prev - 1;
+ // Nope, this does not look right either. This means the frame after next does
+ // not have a valid frame pointer, but we can still extract the caller PC.
+ // Unfortunately, there is no way to decide between GCC and LLVM frame
+ // layouts. Assume LLVM.
+ return bp_prev;
+#else
+ return (uhwptr*)bp;
+#endif
+}
+
+void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
+ uptr stack_bottom, u32 max_depth) {
+ // TODO(yln): add arg sanity check for stack_top/stack_bottom
+ CHECK_GE(max_depth, 2);
+ const uptr kPageSize = GetPageSizeCached();
+ trace_buffer[0] = pc;
+ size = 1;
+ if (stack_top < 4096) return; // Sanity check for stack top.
+ uhwptr *frame = GetCanonicFrame(bp, stack_top, stack_bottom);
+ // Lowest possible address that makes sense as the next frame pointer.
+ // Goes up as we walk the stack.
+ uptr bottom = stack_bottom;
+ // Avoid infinite loop when frame == frame[0] by using frame > prev_frame.
+ while (IsValidFrame((uptr)frame, stack_top, bottom) &&
+ IsAligned((uptr)frame, sizeof(*frame)) &&
+ size < max_depth) {
+#ifdef __powerpc__
+ // PowerPC ABIs specify that the return address is saved at offset
+ // 16 of the *caller's* stack frame. Thus we must dereference the
+ // back chain to find the caller frame before extracting it.
+ uhwptr *caller_frame = (uhwptr*)frame[0];
+ if (!IsValidFrame((uptr)caller_frame, stack_top, bottom) ||
+ !IsAligned((uptr)caller_frame, sizeof(uhwptr)))
+ break;
+ uhwptr pc1 = caller_frame[2];
+#elif defined(__s390__)
+ uhwptr pc1 = frame[14];
+#elif defined(__loongarch__) || defined(__riscv)
+ // frame[-1] contains the return address
+ uhwptr pc1 = frame[-1];
+#else
+ uhwptr pc1 = STRIP_PAC_PC((void *)frame[1]);
+#endif
+ // Let's assume that any pointer in the 0th page (i.e. <0x1000 on i386 and
+ // x86_64) is invalid and stop unwinding here. If we're adding support for
+ // a platform where this isn't true, we need to reconsider this check.
+ if (pc1 < kPageSize)
+ break;
+ if (pc1 != pc) {
+ trace_buffer[size++] = (uptr) pc1;
+ }
+ bottom = (uptr)frame;
+#if defined(__loongarch__) || defined(__riscv)
+ // frame[-2] contain fp of the previous frame
+ uptr new_bp = (uptr)frame[-2];
+#else
+ uptr new_bp = (uptr)frame[0];
+#endif
+ frame = GetCanonicFrame(new_bp, stack_top, bottom);
+ }
+}
+
+#endif // !defined(__sparc__)
+
+void BufferedStackTrace::PopStackFrames(uptr count) {
+ CHECK_LT(count, size);
+ size -= count;
+ for (uptr i = 0; i < size; ++i) {
+ trace_buffer[i] = trace_buffer[i + count];
+ }
+}
+
+static uptr Distance(uptr a, uptr b) { return a < b ? b - a : a - b; }
+
+uptr BufferedStackTrace::LocatePcInTrace(uptr pc) {
+ uptr best = 0;
+ for (uptr i = 1; i < size; ++i) {
+ if (Distance(trace[i], pc) < Distance(trace[best], pc)) best = i;
+ }
+ return best;
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace.h
new file mode 100644
index 00000000000..ee996c3e07e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace.h
@@ -0,0 +1,220 @@
+//===-- sanitizer_stacktrace.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_STACKTRACE_H
+#define SANITIZER_STACKTRACE_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform.h"
+
+namespace __sanitizer {
+
+struct BufferedStackTrace;
+
+static const u32 kStackTraceMax = 255;
+
+#if SANITIZER_LINUX && defined(__mips__)
+# define SANITIZER_CAN_FAST_UNWIND 0
+#elif SANITIZER_WINDOWS
+# define SANITIZER_CAN_FAST_UNWIND 0
+#else
+# define SANITIZER_CAN_FAST_UNWIND 1
+#endif
+
+// Fast unwind is the only option on Mac for now; we will need to
+// revisit this macro when slow unwind works on Mac, see
+// https://github.com/google/sanitizers/issues/137
+#if SANITIZER_APPLE
+# define SANITIZER_CAN_SLOW_UNWIND 0
+#else
+# define SANITIZER_CAN_SLOW_UNWIND 1
+#endif
+
+struct StackTrace {
+ const uptr *trace;
+ u32 size;
+ u32 tag;
+
+ static const int TAG_UNKNOWN = 0;
+ static const int TAG_ALLOC = 1;
+ static const int TAG_DEALLOC = 2;
+ static const int TAG_CUSTOM = 100; // Tool specific tags start here.
+
+ StackTrace() : trace(nullptr), size(0), tag(0) {}
+ StackTrace(const uptr *trace, u32 size) : trace(trace), size(size), tag(0) {}
+ StackTrace(const uptr *trace, u32 size, u32 tag)
+ : trace(trace), size(size), tag(tag) {}
+
+ // Prints a symbolized stacktrace, followed by an empty line.
+ void Print() const;
+
+ // Prints a symbolized stacktrace to the output string, followed by an empty
+ // line.
+ void PrintTo(InternalScopedString *output) const;
+
+ // Prints a symbolized stacktrace to the output buffer, followed by an empty
+ // line. Returns the number of symbols that should have been written to buffer
+ // (not including trailing '\0'). Thus, the string is truncated iff return
+ // value is not less than "out_buf_size".
+ uptr PrintTo(char *out_buf, uptr out_buf_size) const;
+
+ static bool WillUseFastUnwind(bool request_fast_unwind) {
+ if (!SANITIZER_CAN_FAST_UNWIND)
+ return false;
+ if (!SANITIZER_CAN_SLOW_UNWIND)
+ return true;
+ return request_fast_unwind;
+ }
+
+ static uptr GetCurrentPc();
+ static inline uptr GetPreviousInstructionPc(uptr pc);
+ static uptr GetNextInstructionPc(uptr pc);
+};
+
+// Performance-critical, must be in the header.
+ALWAYS_INLINE
+uptr StackTrace::GetPreviousInstructionPc(uptr pc) {
+#if defined(__arm__)
+ // T32 (Thumb) branch instructions might be 16 or 32 bit long,
+ // so we return (pc-2) in that case in order to be safe.
+ // For A32 mode we return (pc-4) because all instructions are 32 bit long.
+ return (pc - 3) & (~1);
+#elif defined(__sparc__) || defined(__mips__)
+ return pc - 8;
+#elif SANITIZER_RISCV64
+ // RV-64 has variable instruciton length...
+ // C extentions gives us 2-byte instructoins
+ // RV-64 has 4-byte instructions
+ // + RISCV architecture allows instructions up to 8 bytes
+ // It seems difficult to figure out the exact instruction length -
+ // pc - 2 seems like a safe option for the purposes of stack tracing
+ return pc - 2;
+#elif SANITIZER_S390 || SANITIZER_I386 || SANITIZER_X32 || SANITIZER_X64
+ return pc - 1;
+#else
+ return pc - 4;
+#endif
+}
+
+// StackTrace that owns the buffer used to store the addresses.
+struct BufferedStackTrace : public StackTrace {
+ uptr trace_buffer[kStackTraceMax];
+ uptr top_frame_bp; // Optional bp of a top frame.
+
+ BufferedStackTrace() : StackTrace(trace_buffer, 0), top_frame_bp(0) {}
+
+ void Init(const uptr *pcs, uptr cnt, uptr extra_top_pc = 0);
+
+ // Get the stack trace with the given pc and bp.
+ // The pc will be in the position 0 of the resulting stack trace.
+ // The bp may refer to the current frame or to the caller's frame.
+ void Unwind(uptr pc, uptr bp, void *context, bool request_fast,
+ u32 max_depth = kStackTraceMax) {
+ top_frame_bp = (max_depth > 0) ? bp : 0;
+ // Small max_depth optimization
+ if (max_depth <= 1) {
+ if (max_depth == 1)
+ trace_buffer[0] = pc;
+ size = max_depth;
+ return;
+ }
+ UnwindImpl(pc, bp, context, request_fast, max_depth);
+ }
+
+ void Unwind(u32 max_depth, uptr pc, uptr bp, void *context, uptr stack_top,
+ uptr stack_bottom, bool request_fast_unwind);
+
+ void Reset() {
+ *static_cast<StackTrace *>(this) = StackTrace(trace_buffer, 0);
+ top_frame_bp = 0;
+ }
+
+ private:
+ // Every runtime defines its own implementation of this method
+ void UnwindImpl(uptr pc, uptr bp, void *context, bool request_fast,
+ u32 max_depth);
+
+ // UnwindFast/Slow have platform-specific implementations
+ void UnwindFast(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom,
+ u32 max_depth);
+ void UnwindSlow(uptr pc, u32 max_depth);
+ void UnwindSlow(uptr pc, void *context, u32 max_depth);
+
+ void PopStackFrames(uptr count);
+ uptr LocatePcInTrace(uptr pc);
+
+ BufferedStackTrace(const BufferedStackTrace &) = delete;
+ void operator=(const BufferedStackTrace &) = delete;
+
+ friend class FastUnwindTest;
+};
+
+#if defined(__s390x__)
+static const uptr kFrameSize = 160;
+#elif defined(__s390__)
+static const uptr kFrameSize = 96;
+#else
+static const uptr kFrameSize = 2 * sizeof(uhwptr);
+#endif
+
+// Check if given pointer points into allocated stack area.
+static inline bool IsValidFrame(uptr frame, uptr stack_top, uptr stack_bottom) {
+ return frame > stack_bottom && frame < stack_top - kFrameSize;
+}
+
+} // namespace __sanitizer
+
+// Use this macro if you want to print stack trace with the caller
+// of the current function in the top frame.
+#define GET_CALLER_PC_BP \
+ uptr bp = GET_CURRENT_FRAME(); \
+ uptr pc = GET_CALLER_PC();
+
+#define GET_CALLER_PC_BP_SP \
+ GET_CALLER_PC_BP; \
+ uptr local_stack; \
+ uptr sp = (uptr)&local_stack
+
+// Use this macro if you want to print stack trace with the current
+// function in the top frame.
+#define GET_CURRENT_PC_BP \
+ uptr bp = GET_CURRENT_FRAME(); \
+ uptr pc = StackTrace::GetCurrentPc()
+
+#define GET_CURRENT_PC_BP_SP \
+ GET_CURRENT_PC_BP; \
+ uptr local_stack; \
+ uptr sp = (uptr)&local_stack
+
+// GET_CURRENT_PC() is equivalent to StackTrace::GetCurrentPc().
+// Optimized x86 version is faster than GetCurrentPc because
+// it does not involve a function call, instead it reads RIP register.
+// Reads of RIP by an instruction return RIP pointing to the next
+// instruction, which is exactly what we want here, thus 0 offset.
+// It needs to be a macro because otherwise we will get the name
+// of this function on the top of most stacks. Attribute artificial
+// does not do what it claims to do, unfortunatley. And attribute
+// __nodebug__ is clang-only. If we would have an attribute that
+// would remove this function from debug info, we could simply make
+// StackTrace::GetCurrentPc() faster.
+#if defined(__x86_64__)
+# define GET_CURRENT_PC() \
+ (__extension__({ \
+ uptr pc; \
+ asm("lea 0(%%rip), %0" : "=r"(pc)); \
+ pc; \
+ }))
+#else
+# define GET_CURRENT_PC() StackTrace::GetCurrentPc()
+#endif
+
+#endif // SANITIZER_STACKTRACE_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp
new file mode 100644
index 00000000000..47983ee7ec7
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp
@@ -0,0 +1,226 @@
+//===-- sanitizer_stacktrace_libcdep.cpp ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_stacktrace.h"
+#include "sanitizer_stacktrace_printer.h"
+#include "sanitizer_symbolizer.h"
+
+namespace __sanitizer {
+
+namespace {
+
+class StackTraceTextPrinter {
+ public:
+ StackTraceTextPrinter(const char *stack_trace_fmt, char frame_delimiter,
+ InternalScopedString *output,
+ InternalScopedString *dedup_token)
+ : stack_trace_fmt_(stack_trace_fmt),
+ frame_delimiter_(frame_delimiter),
+ output_(output),
+ dedup_token_(dedup_token),
+ symbolize_(RenderNeedsSymbolization(stack_trace_fmt)) {}
+
+ bool ProcessAddressFrames(uptr pc) {
+ SymbolizedStack *frames = symbolize_
+ ? Symbolizer::GetOrInit()->SymbolizePC(pc)
+ : SymbolizedStack::New(pc);
+ if (!frames)
+ return false;
+
+ for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
+ uptr prev_len = output_->length();
+ RenderFrame(output_, stack_trace_fmt_, frame_num_++, cur->info.address,
+ symbolize_ ? &cur->info : nullptr,
+ common_flags()->symbolize_vs_style,
+ common_flags()->strip_path_prefix);
+
+ if (prev_len != output_->length())
+ output_->append("%c", frame_delimiter_);
+
+ ExtendDedupToken(cur);
+ }
+ frames->ClearAll();
+ return true;
+ }
+
+ private:
+ // Extend the dedup token by appending a new frame.
+ void ExtendDedupToken(SymbolizedStack *stack) {
+ if (!dedup_token_)
+ return;
+
+ if (dedup_frames_-- > 0) {
+ if (dedup_token_->length())
+ dedup_token_->append("--");
+ if (stack->info.function != nullptr)
+ dedup_token_->append("%s", stack->info.function);
+ }
+ }
+
+ const char *stack_trace_fmt_;
+ const char frame_delimiter_;
+ int dedup_frames_ = common_flags()->dedup_token_length;
+ uptr frame_num_ = 0;
+ InternalScopedString *output_;
+ InternalScopedString *dedup_token_;
+ const bool symbolize_ = false;
+};
+
+static void CopyStringToBuffer(const InternalScopedString &str, char *out_buf,
+ uptr out_buf_size) {
+ if (!out_buf_size)
+ return;
+
+ CHECK_GT(out_buf_size, 0);
+ uptr copy_size = Min(str.length(), out_buf_size - 1);
+ internal_memcpy(out_buf, str.data(), copy_size);
+ out_buf[copy_size] = '\0';
+}
+
+} // namespace
+
+void StackTrace::PrintTo(InternalScopedString *output) const {
+ CHECK(output);
+
+ InternalScopedString dedup_token;
+ StackTraceTextPrinter printer(common_flags()->stack_trace_format, '\n',
+ output, &dedup_token);
+
+ if (trace == nullptr || size == 0) {
+ output->append(" <empty stack>\n\n");
+ return;
+ }
+
+ for (uptr i = 0; i < size && trace[i]; i++) {
+ // PCs in stack traces are actually the return addresses, that is,
+ // addresses of the next instructions after the call.
+ uptr pc = GetPreviousInstructionPc(trace[i]);
+ CHECK(printer.ProcessAddressFrames(pc));
+ }
+
+ // Always add a trailing empty line after stack trace.
+ output->append("\n");
+
+ // Append deduplication token, if non-empty.
+ if (dedup_token.length())
+ output->append("DEDUP_TOKEN: %s\n", dedup_token.data());
+}
+
+uptr StackTrace::PrintTo(char *out_buf, uptr out_buf_size) const {
+ CHECK(out_buf);
+
+ InternalScopedString output;
+ PrintTo(&output);
+ CopyStringToBuffer(output, out_buf, out_buf_size);
+
+ return output.length();
+}
+
+void StackTrace::Print() const {
+ InternalScopedString output;
+ PrintTo(&output);
+ Printf("%s", output.data());
+}
+
+void BufferedStackTrace::Unwind(u32 max_depth, uptr pc, uptr bp, void *context,
+ uptr stack_top, uptr stack_bottom,
+ bool request_fast_unwind) {
+ // Ensures all call sites get what they requested.
+ CHECK_EQ(request_fast_unwind, WillUseFastUnwind(request_fast_unwind));
+ top_frame_bp = (max_depth > 0) ? bp : 0;
+ // Avoid doing any work for small max_depth.
+ if (max_depth == 0) {
+ size = 0;
+ return;
+ }
+ if (max_depth == 1) {
+ size = 1;
+ trace_buffer[0] = pc;
+ return;
+ }
+ if (!WillUseFastUnwind(request_fast_unwind)) {
+#if SANITIZER_CAN_SLOW_UNWIND
+ if (context)
+ UnwindSlow(pc, context, max_depth);
+ else
+ UnwindSlow(pc, max_depth);
+ // If there are too few frames, the program may be built with
+ // -fno-asynchronous-unwind-tables. Fall back to fast unwinder below.
+ if (size > 2 || size >= max_depth)
+ return;
+#else
+ UNREACHABLE("slow unwind requested but not available");
+#endif
+ }
+ UnwindFast(pc, bp, stack_top, stack_bottom, max_depth);
+}
+
+int GetModuleAndOffsetForPc(uptr pc, char *module_name, uptr module_name_len,
+ uptr *pc_offset) {
+ const char *found_module_name = nullptr;
+ bool ok = Symbolizer::GetOrInit()->GetModuleNameAndOffsetForPC(
+ pc, &found_module_name, pc_offset);
+
+ if (!ok) return false;
+
+ if (module_name && module_name_len) {
+ internal_strncpy(module_name, found_module_name, module_name_len);
+ module_name[module_name_len - 1] = '\x00';
+ }
+ return true;
+}
+
+} // namespace __sanitizer
+using namespace __sanitizer;
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_symbolize_pc(uptr pc, const char *fmt, char *out_buf,
+ uptr out_buf_size) {
+ if (!out_buf_size)
+ return;
+
+ pc = StackTrace::GetPreviousInstructionPc(pc);
+
+ InternalScopedString output;
+ StackTraceTextPrinter printer(fmt, '\0', &output, nullptr);
+ if (!printer.ProcessAddressFrames(pc)) {
+ output.clear();
+ output.append("<can't symbolize>");
+ }
+ CopyStringToBuffer(output, out_buf, out_buf_size);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_symbolize_global(uptr data_addr, const char *fmt,
+ char *out_buf, uptr out_buf_size) {
+ if (!out_buf_size) return;
+ out_buf[0] = 0;
+ DataInfo DI;
+ if (!Symbolizer::GetOrInit()->SymbolizeData(data_addr, &DI)) return;
+ InternalScopedString data_desc;
+ RenderData(&data_desc, fmt, &DI, common_flags()->strip_path_prefix);
+ internal_strncpy(out_buf, data_desc.data(), out_buf_size);
+ out_buf[out_buf_size - 1] = 0;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __sanitizer_get_module_and_offset_for_pc(void *pc, char *module_name,
+ uptr module_name_len,
+ void **pc_offset) {
+ return __sanitizer::GetModuleAndOffsetForPc(
+ reinterpret_cast<uptr>(pc), module_name, module_name_len,
+ reinterpret_cast<uptr *>(pc_offset));
+}
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp
new file mode 100644
index 00000000000..2d0eccc1602
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp
@@ -0,0 +1,310 @@
+//===-- sanitizer_common.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between sanitizers' run-time libraries.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_stacktrace_printer.h"
+#include "sanitizer_file.h"
+#include "sanitizer_fuchsia.h"
+
+namespace __sanitizer {
+
+// sanitizer_symbolizer_markup.cpp implements these differently.
+#if !SANITIZER_SYMBOLIZER_MARKUP
+
+static const char *StripFunctionName(const char *function, const char *prefix) {
+ if (!function) return nullptr;
+ if (!prefix) return function;
+ uptr prefix_len = internal_strlen(prefix);
+ if (0 == internal_strncmp(function, prefix, prefix_len))
+ return function + prefix_len;
+ return function;
+}
+
+static const char *DemangleFunctionName(const char *function) {
+ if (!function) return nullptr;
+
+ // NetBSD uses indirection for old threading functions for historical reasons
+ // The mangled names are internal implementation detail and should not be
+ // exposed even in backtraces.
+#if SANITIZER_NETBSD
+ if (!internal_strcmp(function, "__libc_mutex_init"))
+ return "pthread_mutex_init";
+ if (!internal_strcmp(function, "__libc_mutex_lock"))
+ return "pthread_mutex_lock";
+ if (!internal_strcmp(function, "__libc_mutex_trylock"))
+ return "pthread_mutex_trylock";
+ if (!internal_strcmp(function, "__libc_mutex_unlock"))
+ return "pthread_mutex_unlock";
+ if (!internal_strcmp(function, "__libc_mutex_destroy"))
+ return "pthread_mutex_destroy";
+ if (!internal_strcmp(function, "__libc_mutexattr_init"))
+ return "pthread_mutexattr_init";
+ if (!internal_strcmp(function, "__libc_mutexattr_settype"))
+ return "pthread_mutexattr_settype";
+ if (!internal_strcmp(function, "__libc_mutexattr_destroy"))
+ return "pthread_mutexattr_destroy";
+ if (!internal_strcmp(function, "__libc_cond_init"))
+ return "pthread_cond_init";
+ if (!internal_strcmp(function, "__libc_cond_signal"))
+ return "pthread_cond_signal";
+ if (!internal_strcmp(function, "__libc_cond_broadcast"))
+ return "pthread_cond_broadcast";
+ if (!internal_strcmp(function, "__libc_cond_wait"))
+ return "pthread_cond_wait";
+ if (!internal_strcmp(function, "__libc_cond_timedwait"))
+ return "pthread_cond_timedwait";
+ if (!internal_strcmp(function, "__libc_cond_destroy"))
+ return "pthread_cond_destroy";
+ if (!internal_strcmp(function, "__libc_rwlock_init"))
+ return "pthread_rwlock_init";
+ if (!internal_strcmp(function, "__libc_rwlock_rdlock"))
+ return "pthread_rwlock_rdlock";
+ if (!internal_strcmp(function, "__libc_rwlock_wrlock"))
+ return "pthread_rwlock_wrlock";
+ if (!internal_strcmp(function, "__libc_rwlock_tryrdlock"))
+ return "pthread_rwlock_tryrdlock";
+ if (!internal_strcmp(function, "__libc_rwlock_trywrlock"))
+ return "pthread_rwlock_trywrlock";
+ if (!internal_strcmp(function, "__libc_rwlock_unlock"))
+ return "pthread_rwlock_unlock";
+ if (!internal_strcmp(function, "__libc_rwlock_destroy"))
+ return "pthread_rwlock_destroy";
+ if (!internal_strcmp(function, "__libc_thr_keycreate"))
+ return "pthread_key_create";
+ if (!internal_strcmp(function, "__libc_thr_setspecific"))
+ return "pthread_setspecific";
+ if (!internal_strcmp(function, "__libc_thr_getspecific"))
+ return "pthread_getspecific";
+ if (!internal_strcmp(function, "__libc_thr_keydelete"))
+ return "pthread_key_delete";
+ if (!internal_strcmp(function, "__libc_thr_once"))
+ return "pthread_once";
+ if (!internal_strcmp(function, "__libc_thr_self"))
+ return "pthread_self";
+ if (!internal_strcmp(function, "__libc_thr_exit"))
+ return "pthread_exit";
+ if (!internal_strcmp(function, "__libc_thr_setcancelstate"))
+ return "pthread_setcancelstate";
+ if (!internal_strcmp(function, "__libc_thr_equal"))
+ return "pthread_equal";
+ if (!internal_strcmp(function, "__libc_thr_curcpu"))
+ return "pthread_curcpu_np";
+ if (!internal_strcmp(function, "__libc_thr_sigsetmask"))
+ return "pthread_sigmask";
+#endif
+
+ return function;
+}
+
+static void MaybeBuildIdToBuffer(const AddressInfo &info, bool PrefixSpace,
+ InternalScopedString *buffer) {
+ if (info.uuid_size) {
+ if (PrefixSpace)
+ buffer->append(" ");
+ buffer->append("(BuildId: ");
+ for (uptr i = 0; i < info.uuid_size; ++i) {
+ buffer->append("%02x", info.uuid[i]);
+ }
+ buffer->append(")");
+ }
+}
+
+static const char kDefaultFormat[] = " #%n %p %F %L";
+
+void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
+ uptr address, const AddressInfo *info, bool vs_style,
+ const char *strip_path_prefix, const char *strip_func_prefix) {
+ // info will be null in the case where symbolization is not needed for the
+ // given format. This ensures that the code below will get a hard failure
+ // rather than print incorrect information in case RenderNeedsSymbolization
+ // ever ends up out of sync with this function. If non-null, the addresses
+ // should match.
+ CHECK(!info || address == info->address);
+ if (0 == internal_strcmp(format, "DEFAULT"))
+ format = kDefaultFormat;
+ for (const char *p = format; *p != '\0'; p++) {
+ if (*p != '%') {
+ buffer->append("%c", *p);
+ continue;
+ }
+ p++;
+ switch (*p) {
+ case '%':
+ buffer->append("%%");
+ break;
+ // Frame number and all fields of AddressInfo structure.
+ case 'n':
+ buffer->append("%u", frame_no);
+ break;
+ case 'p':
+ buffer->append("0x%zx", address);
+ break;
+ case 'm':
+ buffer->append("%s", StripPathPrefix(info->module, strip_path_prefix));
+ break;
+ case 'o':
+ buffer->append("0x%zx", info->module_offset);
+ break;
+ case 'b':
+ MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/false, buffer);
+ break;
+ case 'f':
+ buffer->append("%s", DemangleFunctionName(StripFunctionName(
+ info->function, strip_func_prefix)));
+ break;
+ case 'q':
+ buffer->append("0x%zx", info->function_offset != AddressInfo::kUnknown
+ ? info->function_offset
+ : 0x0);
+ break;
+ case 's':
+ buffer->append("%s", StripPathPrefix(info->file, strip_path_prefix));
+ break;
+ case 'l':
+ buffer->append("%d", info->line);
+ break;
+ case 'c':
+ buffer->append("%d", info->column);
+ break;
+ // Smarter special cases.
+ case 'F':
+ // Function name and offset, if file is unknown.
+ if (info->function) {
+ buffer->append("in %s", DemangleFunctionName(StripFunctionName(
+ info->function, strip_func_prefix)));
+ if (!info->file && info->function_offset != AddressInfo::kUnknown)
+ buffer->append("+0x%zx", info->function_offset);
+ }
+ break;
+ case 'S':
+ // File/line information.
+ RenderSourceLocation(buffer, info->file, info->line, info->column,
+ vs_style, strip_path_prefix);
+ break;
+ case 'L':
+ // Source location, or module location.
+ if (info->file) {
+ RenderSourceLocation(buffer, info->file, info->line, info->column,
+ vs_style, strip_path_prefix);
+ } else if (info->module) {
+ RenderModuleLocation(buffer, info->module, info->module_offset,
+ info->module_arch, strip_path_prefix);
+
+ MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
+ } else {
+ buffer->append("(<unknown module>)");
+ }
+ break;
+ case 'M':
+ // Module basename and offset, or PC.
+ if (address & kExternalPCBit) {
+ // There PCs are not meaningful.
+ } else if (info->module) {
+ // Always strip the module name for %M.
+ RenderModuleLocation(buffer, StripModuleName(info->module),
+ info->module_offset, info->module_arch, "");
+ MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
+ } else {
+ buffer->append("(%p)", (void *)address);
+ }
+ break;
+ default:
+ Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p,
+ (void *)p);
+ Die();
+ }
+ }
+}
+
+bool RenderNeedsSymbolization(const char *format) {
+ if (0 == internal_strcmp(format, "DEFAULT"))
+ format = kDefaultFormat;
+ for (const char *p = format; *p != '\0'; p++) {
+ if (*p != '%')
+ continue;
+ p++;
+ switch (*p) {
+ case '%':
+ break;
+ case 'n':
+ // frame_no
+ break;
+ case 'p':
+ // address
+ break;
+ default:
+ return true;
+ }
+ }
+ return false;
+}
+
+void RenderData(InternalScopedString *buffer, const char *format,
+ const DataInfo *DI, const char *strip_path_prefix) {
+ for (const char *p = format; *p != '\0'; p++) {
+ if (*p != '%') {
+ buffer->append("%c", *p);
+ continue;
+ }
+ p++;
+ switch (*p) {
+ case '%':
+ buffer->append("%%");
+ break;
+ case 's':
+ buffer->append("%s", StripPathPrefix(DI->file, strip_path_prefix));
+ break;
+ case 'l':
+ buffer->append("%zu", DI->line);
+ break;
+ case 'g':
+ buffer->append("%s", DI->name);
+ break;
+ default:
+ Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p,
+ (void *)p);
+ Die();
+ }
+ }
+}
+
+#endif // !SANITIZER_SYMBOLIZER_MARKUP
+
+void RenderSourceLocation(InternalScopedString *buffer, const char *file,
+ int line, int column, bool vs_style,
+ const char *strip_path_prefix) {
+ if (vs_style && line > 0) {
+ buffer->append("%s(%d", StripPathPrefix(file, strip_path_prefix), line);
+ if (column > 0)
+ buffer->append(",%d", column);
+ buffer->append(")");
+ return;
+ }
+
+ buffer->append("%s", StripPathPrefix(file, strip_path_prefix));
+ if (line > 0) {
+ buffer->append(":%d", line);
+ if (column > 0)
+ buffer->append(":%d", column);
+ }
+}
+
+void RenderModuleLocation(InternalScopedString *buffer, const char *module,
+ uptr offset, ModuleArch arch,
+ const char *strip_path_prefix) {
+ buffer->append("(%s", StripPathPrefix(module, strip_path_prefix));
+ if (arch != kModuleArchUnknown) {
+ buffer->append(":%s", ModuleArchToString(arch));
+ }
+ buffer->append("+0x%zx)", offset);
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h
new file mode 100644
index 00000000000..96119b2ee9e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h
@@ -0,0 +1,73 @@
+//===-- sanitizer_stacktrace_printer.h --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between sanitizers' run-time libraries.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_STACKTRACE_PRINTER_H
+#define SANITIZER_STACKTRACE_PRINTER_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_symbolizer.h"
+
+namespace __sanitizer {
+
+// Render the contents of "info" structure, which represents the contents of
+// stack frame "frame_no" and appends it to the "buffer". "format" is a
+// string with placeholders, which is copied to the output with
+// placeholders substituted with the contents of "info". For example,
+// format string
+// " frame %n: function %F at %S"
+// will be turned into
+// " frame 10: function foo::bar() at my/file.cc:10"
+// You may additionally pass "strip_path_prefix" to strip prefixes of paths to
+// source files and modules, and "strip_func_prefix" to strip prefixes of
+// function names.
+// Here's the full list of available placeholders:
+// %% - represents a '%' character;
+// %n - frame number (copy of frame_no);
+// %p - PC in hex format;
+// %m - path to module (binary or shared object);
+// %o - offset in the module in hex format;
+// %f - function name;
+// %q - offset in the function in hex format (*if available*);
+// %s - path to source file;
+// %l - line in the source file;
+// %c - column in the source file;
+// %F - if function is known to be <foo>, prints "in <foo>", possibly
+// followed by the offset in this function, but only if source file
+// is unknown;
+// %S - prints file/line/column information;
+// %L - prints location information: file/line/column, if it is known, or
+// module+offset if it is known, or (<unknown module>) string.
+// %M - prints module basename and offset, if it is known, or PC.
+void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
+ uptr address, const AddressInfo *info, bool vs_style,
+ const char *strip_path_prefix = "",
+ const char *strip_func_prefix = "");
+
+bool RenderNeedsSymbolization(const char *format);
+
+void RenderSourceLocation(InternalScopedString *buffer, const char *file,
+ int line, int column, bool vs_style,
+ const char *strip_path_prefix);
+
+void RenderModuleLocation(InternalScopedString *buffer, const char *module,
+ uptr offset, ModuleArch arch,
+ const char *strip_path_prefix);
+
+// Same as RenderFrame, but for data section (global variables).
+// Accepts %s, %l from above.
+// Also accepts:
+// %g - name of the global variable.
+void RenderData(InternalScopedString *buffer, const char *format,
+ const DataInfo *DI, const char *strip_path_prefix = "");
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_STACKTRACE_PRINTER_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_sparc.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_sparc.cpp
new file mode 100644
index 00000000000..1e635a66978
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stacktrace_sparc.cpp
@@ -0,0 +1,85 @@
+//===-- sanitizer_stacktrace_sparc.cpp ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+//
+// Implementation of fast stack unwinding for Sparc.
+//===----------------------------------------------------------------------===//
+
+#if defined(__sparc__)
+
+#if defined(__arch64__) || defined(__sparcv9)
+#define STACK_BIAS 2047
+#else
+#define STACK_BIAS 0
+#endif
+
+#include "sanitizer_common.h"
+#include "sanitizer_stacktrace.h"
+
+namespace __sanitizer {
+
+void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
+ uptr stack_bottom, u32 max_depth) {
+ // TODO(yln): add arg sanity check for stack_top/stack_bottom
+ CHECK_GE(max_depth, 2);
+ const uptr kPageSize = GetPageSizeCached();
+#if defined(__GNUC__)
+ // __builtin_return_address returns the address of the call instruction
+ // on the SPARC and not the return address, so we need to compensate.
+ trace_buffer[0] = GetNextInstructionPc(pc);
+#else
+ trace_buffer[0] = pc;
+#endif
+ size = 1;
+ if (stack_top < 4096) return; // Sanity check for stack top.
+ // Flush register windows to memory
+#if defined(__sparc_v9__) || defined(__sparcv9__) || defined(__sparcv9)
+ asm volatile("flushw" ::: "memory");
+#else
+ asm volatile("ta 3" ::: "memory");
+#endif
+ // On the SPARC, the return address is not in the frame, it is in a
+ // register. There is no way to access it off of the current frame
+ // pointer, but it can be accessed off the previous frame pointer by
+ // reading the value from the register window save area.
+ uptr prev_bp = GET_CURRENT_FRAME();
+ uptr next_bp = prev_bp;
+ unsigned int i = 0;
+ while (next_bp != bp && IsAligned(next_bp, sizeof(uhwptr)) && i++ < 8) {
+ prev_bp = next_bp;
+ next_bp = (uptr)((uhwptr *)next_bp)[14] + STACK_BIAS;
+ }
+ if (next_bp == bp)
+ bp = prev_bp;
+ // Lowest possible address that makes sense as the next frame pointer.
+ // Goes up as we walk the stack.
+ uptr bottom = stack_bottom;
+ // Avoid infinite loop when frame == frame[0] by using frame > prev_frame.
+ while (IsValidFrame(bp, stack_top, bottom) && IsAligned(bp, sizeof(uhwptr)) &&
+ size < max_depth) {
+ uhwptr pc1 = ((uhwptr *)bp)[15];
+ // Let's assume that any pointer in the 0th page is invalid and
+ // stop unwinding here. If we're adding support for a platform
+ // where this isn't true, we need to reconsider this check.
+ if (pc1 < kPageSize)
+ break;
+ if (pc1 != pc) {
+ // %o7 contains the address of the call instruction and not the
+ // return address, so we need to compensate.
+ trace_buffer[size++] = GetNextInstructionPc((uptr)pc1);
+ }
+ bottom = bp;
+ bp = (uptr)((uhwptr *)bp)[14] + STACK_BIAS;
+ }
+}
+
+} // namespace __sanitizer
+
+#endif // !defined(__sparc__)
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld.h
new file mode 100644
index 00000000000..7891c1081fe
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld.h
@@ -0,0 +1,65 @@
+//===-- sanitizer_stoptheworld.h --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the StopTheWorld function which suspends the execution of the current
+// process and runs the user-supplied callback in the same address space.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_STOPTHEWORLD_H
+#define SANITIZER_STOPTHEWORLD_H
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+
+enum PtraceRegistersStatus {
+ REGISTERS_UNAVAILABLE_FATAL = -1,
+ REGISTERS_UNAVAILABLE = 0,
+ REGISTERS_AVAILABLE = 1
+};
+
+// Holds the list of suspended threads and provides an interface to dump their
+// register contexts.
+class SuspendedThreadsList {
+ public:
+ SuspendedThreadsList() = default;
+
+ // Can't declare pure virtual functions in sanitizer runtimes:
+ // __cxa_pure_virtual might be unavailable. Use UNIMPLEMENTED() instead.
+ virtual PtraceRegistersStatus GetRegistersAndSP(
+ uptr index, InternalMmapVector<uptr> *buffer, uptr *sp) const {
+ UNIMPLEMENTED();
+ }
+
+ virtual uptr ThreadCount() const { UNIMPLEMENTED(); }
+ virtual tid_t GetThreadID(uptr index) const { UNIMPLEMENTED(); }
+
+ protected:
+ ~SuspendedThreadsList() {}
+
+ private:
+ // Prohibit copy and assign.
+ SuspendedThreadsList(const SuspendedThreadsList &) = delete;
+ void operator=(const SuspendedThreadsList &) = delete;
+};
+
+typedef void (*StopTheWorldCallback)(
+ const SuspendedThreadsList &suspended_threads_list,
+ void *argument);
+
+// Suspend all threads in the current process and run the callback on the list
+// of suspended threads. This function will resume the threads before returning.
+// The callback should not call any libc functions. The callback must not call
+// exit() nor _exit() and instead return to the caller.
+// This function should NOT be called from multiple threads simultaneously.
+void StopTheWorld(StopTheWorldCallback callback, void *argument);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_STOPTHEWORLD_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
new file mode 100644
index 00000000000..4cc67200767
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
@@ -0,0 +1,43 @@
+//===-- sanitizer_stoptheworld_fuchsia.cpp -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// See sanitizer_stoptheworld.h for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_FUCHSIA
+
+#error #include <zircon/sanitizer.h>
+
+#include "sanitizer_stoptheworld.h"
+#include "sanitizer_stoptheworld_fuchsia.h"
+
+namespace __sanitizer {
+
+// The Fuchsia implementation stops the world but doesn't offer a real
+// SuspendedThreadsList argument. This is enough for ASan's use case,
+// and LSan does not use this API on Fuchsia.
+void StopTheWorld(StopTheWorldCallback callback, void *argument) {
+ struct Params {
+ StopTheWorldCallback callback;
+ void *argument;
+ } params = {callback, argument};
+ __sanitizer_memory_snapshot(
+ nullptr, nullptr, nullptr, nullptr,
+ [](zx_status_t, void *data) {
+ auto params = reinterpret_cast<Params *>(data);
+ params->callback(SuspendedThreadsListFuchsia(), params->argument);
+ },
+ &params);
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.h
new file mode 100644
index 00000000000..6d9ead60508
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_fuchsia.h
@@ -0,0 +1,20 @@
+//===-- sanitizer_stoptheworld_fuchsia.h ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_STOPTHEWORLD_FUCHSIA_H
+#define SANITIZER_STOPTHEWORLD_FUCHSIA_H
+
+#include "sanitizer_stoptheworld.h"
+
+namespace __sanitizer {
+
+class SuspendedThreadsListFuchsia final : public SuspendedThreadsList {};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_STOPTHEWORLD_FUCHSIA_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
new file mode 100644
index 00000000000..28861e5edbd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
@@ -0,0 +1,631 @@
+//===-- sanitizer_stoptheworld_linux_libcdep.cpp --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// See sanitizer_stoptheworld.h for details.
+// This implementation was inspired by Markus Gutschke's linuxthreads.cc.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_LINUX && \
+ (defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \
+ defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \
+ defined(__arm__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64)
+
+#include "sanitizer_stoptheworld.h"
+
+#include "sanitizer_platform_limits_posix.h"
+#include "sanitizer_atomic.h"
+
+#include <errno.h>
+#include <sched.h> // for CLONE_* definitions
+#include <stddef.h>
+#include <sys/prctl.h> // for PR_* definitions
+#include <sys/ptrace.h> // for PTRACE_* definitions
+#include <sys/types.h> // for pid_t
+#include <sys/uio.h> // for iovec
+#include <elf.h> // for NT_PRSTATUS
+#if (defined(__aarch64__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64) && \
+ !SANITIZER_ANDROID
+// GLIBC 2.20+ sys/user does not include asm/ptrace.h
+# include <asm/ptrace.h>
+#endif
+#include <sys/user.h> // for user_regs_struct
+#if SANITIZER_ANDROID && SANITIZER_MIPS
+# error #include <asm/reg.h> // for mips SP register in sys/user.h
+#endif
+#include <sys/wait.h> // for signal-related stuff
+
+#ifdef sa_handler
+# undef sa_handler
+#endif
+
+#ifdef sa_sigaction
+# undef sa_sigaction
+#endif
+
+#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_mutex.h"
+#include "sanitizer_placement_new.h"
+
+// Sufficiently old kernel headers don't provide this value, but we can still
+// call prctl with it. If the runtime kernel is new enough, the prctl call will
+// have the desired effect; if the kernel is too old, the call will error and we
+// can ignore said error.
+#ifndef PR_SET_PTRACER
+#define PR_SET_PTRACER 0x59616d61
+#endif
+
+// This module works by spawning a Linux task which then attaches to every
+// thread in the caller process with ptrace. This suspends the threads, and
+// PTRACE_GETREGS can then be used to obtain their register state. The callback
+// supplied to StopTheWorld() is run in the tracer task while the threads are
+// suspended.
+// The tracer task must be placed in a different thread group for ptrace to
+// work, so it cannot be spawned as a pthread. Instead, we use the low-level
+// clone() interface (we want to share the address space with the caller
+// process, so we prefer clone() over fork()).
+//
+// We don't use any libc functions, relying instead on direct syscalls. There
+// are two reasons for this:
+// 1. calling a library function while threads are suspended could cause a
+// deadlock, if one of the treads happens to be holding a libc lock;
+// 2. it's generally not safe to call libc functions from the tracer task,
+// because clone() does not set up a thread-local storage for it. Any
+// thread-local variables used by libc will be shared between the tracer task
+// and the thread which spawned it.
+
+namespace __sanitizer {
+
+class SuspendedThreadsListLinux final : public SuspendedThreadsList {
+ public:
+ SuspendedThreadsListLinux() { thread_ids_.reserve(1024); }
+
+ tid_t GetThreadID(uptr index) const override;
+ uptr ThreadCount() const override;
+ bool ContainsTid(tid_t thread_id) const;
+ void Append(tid_t tid);
+
+ PtraceRegistersStatus GetRegistersAndSP(uptr index,
+ InternalMmapVector<uptr> *buffer,
+ uptr *sp) const override;
+
+ private:
+ InternalMmapVector<tid_t> thread_ids_;
+};
+
+// Structure for passing arguments into the tracer thread.
+struct TracerThreadArgument {
+ StopTheWorldCallback callback;
+ void *callback_argument;
+ // The tracer thread waits on this mutex while the parent finishes its
+ // preparations.
+ Mutex mutex;
+ // Tracer thread signals its completion by setting done.
+ atomic_uintptr_t done;
+ uptr parent_pid;
+};
+
+// This class handles thread suspending/unsuspending in the tracer thread.
+class ThreadSuspender {
+ public:
+ explicit ThreadSuspender(pid_t pid, TracerThreadArgument *arg)
+ : arg(arg)
+ , pid_(pid) {
+ CHECK_GE(pid, 0);
+ }
+ bool SuspendAllThreads();
+ void ResumeAllThreads();
+ void KillAllThreads();
+ SuspendedThreadsListLinux &suspended_threads_list() {
+ return suspended_threads_list_;
+ }
+ TracerThreadArgument *arg;
+ private:
+ SuspendedThreadsListLinux suspended_threads_list_;
+ pid_t pid_;
+ bool SuspendThread(tid_t thread_id);
+};
+
+bool ThreadSuspender::SuspendThread(tid_t tid) {
+ // Are we already attached to this thread?
+ // Currently this check takes linear time, however the number of threads is
+ // usually small.
+ if (suspended_threads_list_.ContainsTid(tid)) return false;
+ int pterrno;
+ if (internal_iserror(internal_ptrace(PTRACE_ATTACH, tid, nullptr, nullptr),
+ &pterrno)) {
+ // Either the thread is dead, or something prevented us from attaching.
+ // Log this event and move on.
+ VReport(1, "Could not attach to thread %zu (errno %d).\n", (uptr)tid,
+ pterrno);
+ return false;
+ } else {
+ VReport(2, "Attached to thread %zu.\n", (uptr)tid);
+ // The thread is not guaranteed to stop before ptrace returns, so we must
+ // wait on it. Note: if the thread receives a signal concurrently,
+ // we can get notification about the signal before notification about stop.
+ // In such case we need to forward the signal to the thread, otherwise
+ // the signal will be missed (as we do PTRACE_DETACH with arg=0) and
+ // any logic relying on signals will break. After forwarding we need to
+ // continue to wait for stopping, because the thread is not stopped yet.
+ // We do ignore delivery of SIGSTOP, because we want to make stop-the-world
+ // as invisible as possible.
+ for (;;) {
+ int status;
+ uptr waitpid_status;
+ HANDLE_EINTR(waitpid_status, internal_waitpid(tid, &status, __WALL));
+ int wperrno;
+ if (internal_iserror(waitpid_status, &wperrno)) {
+ // Got a ECHILD error. I don't think this situation is possible, but it
+ // doesn't hurt to report it.
+ VReport(1, "Waiting on thread %zu failed, detaching (errno %d).\n",
+ (uptr)tid, wperrno);
+ internal_ptrace(PTRACE_DETACH, tid, nullptr, nullptr);
+ return false;
+ }
+ if (WIFSTOPPED(status) && WSTOPSIG(status) != SIGSTOP) {
+ internal_ptrace(PTRACE_CONT, tid, nullptr,
+ (void*)(uptr)WSTOPSIG(status));
+ continue;
+ }
+ break;
+ }
+ suspended_threads_list_.Append(tid);
+ return true;
+ }
+}
+
+void ThreadSuspender::ResumeAllThreads() {
+ for (uptr i = 0; i < suspended_threads_list_.ThreadCount(); i++) {
+ pid_t tid = suspended_threads_list_.GetThreadID(i);
+ int pterrno;
+ if (!internal_iserror(internal_ptrace(PTRACE_DETACH, tid, nullptr, nullptr),
+ &pterrno)) {
+ VReport(2, "Detached from thread %d.\n", tid);
+ } else {
+ // Either the thread is dead, or we are already detached.
+ // The latter case is possible, for instance, if this function was called
+ // from a signal handler.
+ VReport(1, "Could not detach from thread %d (errno %d).\n", tid, pterrno);
+ }
+ }
+}
+
+void ThreadSuspender::KillAllThreads() {
+ for (uptr i = 0; i < suspended_threads_list_.ThreadCount(); i++)
+ internal_ptrace(PTRACE_KILL, suspended_threads_list_.GetThreadID(i),
+ nullptr, nullptr);
+}
+
+bool ThreadSuspender::SuspendAllThreads() {
+ ThreadLister thread_lister(pid_);
+ bool retry = true;
+ InternalMmapVector<tid_t> threads;
+ threads.reserve(128);
+ for (int i = 0; i < 30 && retry; ++i) {
+ retry = false;
+ switch (thread_lister.ListThreads(&threads)) {
+ case ThreadLister::Error:
+ ResumeAllThreads();
+ return false;
+ case ThreadLister::Incomplete:
+ retry = true;
+ break;
+ case ThreadLister::Ok:
+ break;
+ }
+ for (tid_t tid : threads) {
+ if (SuspendThread(tid))
+ retry = true;
+ }
+ }
+ return suspended_threads_list_.ThreadCount();
+}
+
+// Pointer to the ThreadSuspender instance for use in signal handler.
+static ThreadSuspender *thread_suspender_instance = nullptr;
+
+// Synchronous signals that should not be blocked.
+static const int kSyncSignals[] = { SIGABRT, SIGILL, SIGFPE, SIGSEGV, SIGBUS,
+ SIGXCPU, SIGXFSZ };
+
+static void TracerThreadDieCallback() {
+ // Generally a call to Die() in the tracer thread should be fatal to the
+ // parent process as well, because they share the address space.
+ // This really only works correctly if all the threads are suspended at this
+ // point. So we correctly handle calls to Die() from within the callback, but
+ // not those that happen before or after the callback. Hopefully there aren't
+ // a lot of opportunities for that to happen...
+ ThreadSuspender *inst = thread_suspender_instance;
+ if (inst && stoptheworld_tracer_pid == internal_getpid()) {
+ inst->KillAllThreads();
+ thread_suspender_instance = nullptr;
+ }
+}
+
+// Signal handler to wake up suspended threads when the tracer thread dies.
+static void TracerThreadSignalHandler(int signum, __sanitizer_siginfo *siginfo,
+ void *uctx) {
+ SignalContext ctx(siginfo, uctx);
+ Printf("Tracer caught signal %d: addr=0x%zx pc=0x%zx sp=0x%zx\n", signum,
+ ctx.addr, ctx.pc, ctx.sp);
+ ThreadSuspender *inst = thread_suspender_instance;
+ if (inst) {
+ if (signum == SIGABRT)
+ inst->KillAllThreads();
+ else
+ inst->ResumeAllThreads();
+ RAW_CHECK(RemoveDieCallback(TracerThreadDieCallback));
+ thread_suspender_instance = nullptr;
+ atomic_store(&inst->arg->done, 1, memory_order_relaxed);
+ }
+ internal__exit((signum == SIGABRT) ? 1 : 2);
+}
+
+// Size of alternative stack for signal handlers in the tracer thread.
+static const int kHandlerStackSize = 8192;
+
+// This function will be run as a cloned task.
+static int TracerThread(void* argument) {
+ TracerThreadArgument *tracer_thread_argument =
+ (TracerThreadArgument *)argument;
+
+ internal_prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
+ // Check if parent is already dead.
+ if (internal_getppid() != tracer_thread_argument->parent_pid)
+ internal__exit(4);
+
+ // Wait for the parent thread to finish preparations.
+ tracer_thread_argument->mutex.Lock();
+ tracer_thread_argument->mutex.Unlock();
+
+ RAW_CHECK(AddDieCallback(TracerThreadDieCallback));
+
+ ThreadSuspender thread_suspender(internal_getppid(), tracer_thread_argument);
+ // Global pointer for the signal handler.
+ thread_suspender_instance = &thread_suspender;
+
+ // Alternate stack for signal handling.
+ InternalMmapVector<char> handler_stack_memory(kHandlerStackSize);
+ stack_t handler_stack;
+ internal_memset(&handler_stack, 0, sizeof(handler_stack));
+ handler_stack.ss_sp = handler_stack_memory.data();
+ handler_stack.ss_size = kHandlerStackSize;
+ internal_sigaltstack(&handler_stack, nullptr);
+
+ // Install our handler for synchronous signals. Other signals should be
+ // blocked by the mask we inherited from the parent thread.
+ for (uptr i = 0; i < ARRAY_SIZE(kSyncSignals); i++) {
+ __sanitizer_sigaction act;
+ internal_memset(&act, 0, sizeof(act));
+ act.sigaction = TracerThreadSignalHandler;
+ act.sa_flags = SA_ONSTACK | SA_SIGINFO;
+ internal_sigaction_norestorer(kSyncSignals[i], &act, 0);
+ }
+
+ int exit_code = 0;
+ if (!thread_suspender.SuspendAllThreads()) {
+ VReport(1, "Failed suspending threads.\n");
+ exit_code = 3;
+ } else {
+ tracer_thread_argument->callback(thread_suspender.suspended_threads_list(),
+ tracer_thread_argument->callback_argument);
+ thread_suspender.ResumeAllThreads();
+ exit_code = 0;
+ }
+ RAW_CHECK(RemoveDieCallback(TracerThreadDieCallback));
+ thread_suspender_instance = nullptr;
+ atomic_store(&tracer_thread_argument->done, 1, memory_order_relaxed);
+ return exit_code;
+}
+
+class ScopedStackSpaceWithGuard {
+ public:
+ explicit ScopedStackSpaceWithGuard(uptr stack_size) {
+ stack_size_ = stack_size;
+ guard_size_ = GetPageSizeCached();
+ // FIXME: Omitting MAP_STACK here works in current kernels but might break
+ // in the future.
+ guard_start_ = (uptr)MmapOrDie(stack_size_ + guard_size_,
+ "ScopedStackWithGuard");
+ CHECK(MprotectNoAccess((uptr)guard_start_, guard_size_));
+ }
+ ~ScopedStackSpaceWithGuard() {
+ UnmapOrDie((void *)guard_start_, stack_size_ + guard_size_);
+ }
+ void *Bottom() const {
+ return (void *)(guard_start_ + stack_size_ + guard_size_);
+ }
+
+ private:
+ uptr stack_size_;
+ uptr guard_size_;
+ uptr guard_start_;
+};
+
+// We have a limitation on the stack frame size, so some stuff had to be moved
+// into globals.
+static __sanitizer_sigset_t blocked_sigset;
+static __sanitizer_sigset_t old_sigset;
+
+class StopTheWorldScope {
+ public:
+ StopTheWorldScope() {
+ // Make this process dumpable. Processes that are not dumpable cannot be
+ // attached to.
+ process_was_dumpable_ = internal_prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
+ if (!process_was_dumpable_)
+ internal_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
+ }
+
+ ~StopTheWorldScope() {
+ // Restore the dumpable flag.
+ if (!process_was_dumpable_)
+ internal_prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
+ }
+
+ private:
+ int process_was_dumpable_;
+};
+
+// When sanitizer output is being redirected to file (i.e. by using log_path),
+// the tracer should write to the parent's log instead of trying to open a new
+// file. Alert the logging code to the fact that we have a tracer.
+struct ScopedSetTracerPID {
+ explicit ScopedSetTracerPID(uptr tracer_pid) {
+ stoptheworld_tracer_pid = tracer_pid;
+ stoptheworld_tracer_ppid = internal_getpid();
+ }
+ ~ScopedSetTracerPID() {
+ stoptheworld_tracer_pid = 0;
+ stoptheworld_tracer_ppid = 0;
+ }
+};
+
+void StopTheWorld(StopTheWorldCallback callback, void *argument) {
+ StopTheWorldScope in_stoptheworld;
+ // Prepare the arguments for TracerThread.
+ struct TracerThreadArgument tracer_thread_argument;
+ tracer_thread_argument.callback = callback;
+ tracer_thread_argument.callback_argument = argument;
+ tracer_thread_argument.parent_pid = internal_getpid();
+ atomic_store(&tracer_thread_argument.done, 0, memory_order_relaxed);
+ const uptr kTracerStackSize = 2 * 1024 * 1024;
+ ScopedStackSpaceWithGuard tracer_stack(kTracerStackSize);
+ // Block the execution of TracerThread until after we have set ptrace
+ // permissions.
+ tracer_thread_argument.mutex.Lock();
+ // Signal handling story.
+ // We don't want async signals to be delivered to the tracer thread,
+ // so we block all async signals before creating the thread. An async signal
+ // handler can temporary modify errno, which is shared with this thread.
+ // We ought to use pthread_sigmask here, because sigprocmask has undefined
+ // behavior in multithreaded programs. However, on linux sigprocmask is
+ // equivalent to pthread_sigmask with the exception that pthread_sigmask
+ // does not allow to block some signals used internally in pthread
+ // implementation. We are fine with blocking them here, we are really not
+ // going to pthread_cancel the thread.
+ // The tracer thread should not raise any synchronous signals. But in case it
+ // does, we setup a special handler for sync signals that properly kills the
+ // parent as well. Note: we don't pass CLONE_SIGHAND to clone, so handlers
+ // in the tracer thread won't interfere with user program. Double note: if a
+ // user does something along the lines of 'kill -11 pid', that can kill the
+ // process even if user setup own handler for SEGV.
+ // Thing to watch out for: this code should not change behavior of user code
+ // in any observable way. In particular it should not override user signal
+ // handlers.
+ internal_sigfillset(&blocked_sigset);
+ for (uptr i = 0; i < ARRAY_SIZE(kSyncSignals); i++)
+ internal_sigdelset(&blocked_sigset, kSyncSignals[i]);
+ int rv = internal_sigprocmask(SIG_BLOCK, &blocked_sigset, &old_sigset);
+ CHECK_EQ(rv, 0);
+ uptr tracer_pid = internal_clone(
+ TracerThread, tracer_stack.Bottom(),
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_UNTRACED,
+ &tracer_thread_argument, nullptr /* parent_tidptr */,
+ nullptr /* newtls */, nullptr /* child_tidptr */);
+ internal_sigprocmask(SIG_SETMASK, &old_sigset, 0);
+ int local_errno = 0;
+ if (internal_iserror(tracer_pid, &local_errno)) {
+ VReport(1, "Failed spawning a tracer thread (errno %d).\n", local_errno);
+ tracer_thread_argument.mutex.Unlock();
+ } else {
+ ScopedSetTracerPID scoped_set_tracer_pid(tracer_pid);
+ // On some systems we have to explicitly declare that we want to be traced
+ // by the tracer thread.
+ internal_prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);
+ // Allow the tracer thread to start.
+ tracer_thread_argument.mutex.Unlock();
+ // NOTE: errno is shared between this thread and the tracer thread.
+ // internal_waitpid() may call syscall() which can access/spoil errno,
+ // so we can't call it now. Instead we for the tracer thread to finish using
+ // the spin loop below. Man page for sched_yield() says "In the Linux
+ // implementation, sched_yield() always succeeds", so let's hope it does not
+ // spoil errno. Note that this spin loop runs only for brief periods before
+ // the tracer thread has suspended us and when it starts unblocking threads.
+ while (atomic_load(&tracer_thread_argument.done, memory_order_relaxed) == 0)
+ sched_yield();
+ // Now the tracer thread is about to exit and does not touch errno,
+ // wait for it.
+ for (;;) {
+ uptr waitpid_status = internal_waitpid(tracer_pid, nullptr, __WALL);
+ if (!internal_iserror(waitpid_status, &local_errno))
+ break;
+ if (local_errno == EINTR)
+ continue;
+ VReport(1, "Waiting on the tracer thread failed (errno %d).\n",
+ local_errno);
+ break;
+ }
+ }
+}
+
+// Platform-specific methods from SuspendedThreadsList.
+#if SANITIZER_ANDROID && defined(__arm__)
+typedef pt_regs regs_struct;
+#define REG_SP ARM_sp
+
+#elif SANITIZER_LINUX && defined(__arm__)
+typedef user_regs regs_struct;
+#define REG_SP uregs[13]
+
+#elif defined(__i386__) || defined(__x86_64__)
+typedef user_regs_struct regs_struct;
+#if defined(__i386__)
+#define REG_SP esp
+#else
+#define REG_SP rsp
+#endif
+#define ARCH_IOVEC_FOR_GETREGSET
+// Support ptrace extensions even when compiled without required kernel support
+#ifndef NT_X86_XSTATE
+#define NT_X86_XSTATE 0x202
+#endif
+#ifndef PTRACE_GETREGSET
+#define PTRACE_GETREGSET 0x4204
+#endif
+// Compiler may use FP registers to store pointers.
+static constexpr uptr kExtraRegs[] = {NT_X86_XSTATE, NT_FPREGSET};
+
+#elif defined(__powerpc__) || defined(__powerpc64__)
+typedef pt_regs regs_struct;
+#define REG_SP gpr[PT_R1]
+
+#elif defined(__mips__)
+typedef struct user regs_struct;
+# if SANITIZER_ANDROID
+# define REG_SP regs[EF_R29]
+# else
+# define REG_SP regs[EF_REG29]
+# endif
+
+#elif defined(__aarch64__)
+typedef struct user_pt_regs regs_struct;
+#define REG_SP sp
+static constexpr uptr kExtraRegs[] = {0};
+#define ARCH_IOVEC_FOR_GETREGSET
+
+#elif defined(__loongarch__)
+typedef struct user_pt_regs regs_struct;
+#define REG_SP regs[3]
+static constexpr uptr kExtraRegs[] = {0};
+#define ARCH_IOVEC_FOR_GETREGSET
+
+#elif SANITIZER_RISCV64
+typedef struct user_regs_struct regs_struct;
+// sys/ucontext.h already defines REG_SP as 2. Undefine it first.
+#undef REG_SP
+#define REG_SP sp
+static constexpr uptr kExtraRegs[] = {0};
+#define ARCH_IOVEC_FOR_GETREGSET
+
+#elif defined(__s390__)
+typedef _user_regs_struct regs_struct;
+#define REG_SP gprs[15]
+static constexpr uptr kExtraRegs[] = {0};
+#define ARCH_IOVEC_FOR_GETREGSET
+
+#else
+#error "Unsupported architecture"
+#endif // SANITIZER_ANDROID && defined(__arm__)
+
+tid_t SuspendedThreadsListLinux::GetThreadID(uptr index) const {
+ CHECK_LT(index, thread_ids_.size());
+ return thread_ids_[index];
+}
+
+uptr SuspendedThreadsListLinux::ThreadCount() const {
+ return thread_ids_.size();
+}
+
+bool SuspendedThreadsListLinux::ContainsTid(tid_t thread_id) const {
+ for (uptr i = 0; i < thread_ids_.size(); i++) {
+ if (thread_ids_[i] == thread_id) return true;
+ }
+ return false;
+}
+
+void SuspendedThreadsListLinux::Append(tid_t tid) {
+ thread_ids_.push_back(tid);
+}
+
+PtraceRegistersStatus SuspendedThreadsListLinux::GetRegistersAndSP(
+ uptr index, InternalMmapVector<uptr> *buffer, uptr *sp) const {
+ pid_t tid = GetThreadID(index);
+ constexpr uptr uptr_sz = sizeof(uptr);
+ int pterrno;
+#ifdef ARCH_IOVEC_FOR_GETREGSET
+ auto append = [&](uptr regset) {
+ uptr size = buffer->size();
+ // NT_X86_XSTATE requires 64bit alignment.
+ uptr size_up = RoundUpTo(size, 8 / uptr_sz);
+ buffer->reserve(Max<uptr>(1024, size_up));
+ struct iovec regset_io;
+ for (;; buffer->resize(buffer->capacity() * 2)) {
+ buffer->resize(buffer->capacity());
+ uptr available_bytes = (buffer->size() - size_up) * uptr_sz;
+ regset_io.iov_base = buffer->data() + size_up;
+ regset_io.iov_len = available_bytes;
+ bool fail =
+ internal_iserror(internal_ptrace(PTRACE_GETREGSET, tid,
+ (void *)regset, (void *)&regset_io),
+ &pterrno);
+ if (fail) {
+ VReport(1, "Could not get regset %p from thread %d (errno %d).\n",
+ (void *)regset, tid, pterrno);
+ buffer->resize(size);
+ return false;
+ }
+
+ // Far enough from the buffer size, no need to resize and repeat.
+ if (regset_io.iov_len + 64 < available_bytes)
+ break;
+ }
+ buffer->resize(size_up + RoundUpTo(regset_io.iov_len, uptr_sz) / uptr_sz);
+ return true;
+ };
+
+ buffer->clear();
+ bool fail = !append(NT_PRSTATUS);
+ if (!fail) {
+ // Accept the first available and do not report errors.
+ for (uptr regs : kExtraRegs)
+ if (regs && append(regs))
+ break;
+ }
+#else
+ buffer->resize(RoundUpTo(sizeof(regs_struct), uptr_sz) / uptr_sz);
+ bool fail = internal_iserror(
+ internal_ptrace(PTRACE_GETREGS, tid, nullptr, buffer->data()), &pterrno);
+ if (fail)
+ VReport(1, "Could not get registers from thread %d (errno %d).\n", tid,
+ pterrno);
+#endif
+ if (fail) {
+ // ESRCH means that the given thread is not suspended or already dead.
+ // Therefore it's unsafe to inspect its data (e.g. walk through stack) and
+ // we should notify caller about this.
+ return pterrno == ESRCH ? REGISTERS_UNAVAILABLE_FATAL
+ : REGISTERS_UNAVAILABLE;
+ }
+
+ *sp = reinterpret_cast<regs_struct *>(buffer->data())[0].REG_SP;
+ return REGISTERS_AVAILABLE;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__)
+ // || defined(__aarch64__) || defined(__powerpc64__)
+ // || defined(__s390__) || defined(__i386__) || defined(__arm__)
+ // || SANITIZER_LOONGARCH64
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_mac.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_mac.cpp
new file mode 100644
index 00000000000..3ebeac52280
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_mac.cpp
@@ -0,0 +1,183 @@
+//===-- sanitizer_stoptheworld_mac.cpp ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// See sanitizer_stoptheworld.h for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_APPLE && (defined(__x86_64__) || defined(__aarch64__) || \
+ defined(__i386))
+
+#include <mach/mach.h>
+#include <mach/thread_info.h>
+#include <pthread.h>
+
+#include "sanitizer_stoptheworld.h"
+
+namespace __sanitizer {
+typedef struct {
+ tid_t tid;
+ thread_t thread;
+} SuspendedThreadInfo;
+
+class SuspendedThreadsListMac final : public SuspendedThreadsList {
+ public:
+ SuspendedThreadsListMac() = default;
+
+ tid_t GetThreadID(uptr index) const override;
+ thread_t GetThread(uptr index) const;
+ uptr ThreadCount() const override;
+ bool ContainsThread(thread_t thread) const;
+ void Append(thread_t thread);
+
+ PtraceRegistersStatus GetRegistersAndSP(uptr index,
+ InternalMmapVector<uptr> *buffer,
+ uptr *sp) const override;
+
+ private:
+ InternalMmapVector<SuspendedThreadInfo> threads_;
+};
+
+struct RunThreadArgs {
+ StopTheWorldCallback callback;
+ void *argument;
+};
+
+void *RunThread(void *arg) {
+ struct RunThreadArgs *run_args = (struct RunThreadArgs *)arg;
+ SuspendedThreadsListMac suspended_threads_list;
+
+ thread_array_t threads;
+ mach_msg_type_number_t num_threads;
+ kern_return_t err = task_threads(mach_task_self(), &threads, &num_threads);
+ if (err != KERN_SUCCESS) {
+ VReport(1, "Failed to get threads for task (errno %d).\n", err);
+ return nullptr;
+ }
+
+ thread_t thread_self = mach_thread_self();
+ for (unsigned int i = 0; i < num_threads; ++i) {
+ if (threads[i] == thread_self) continue;
+
+ thread_suspend(threads[i]);
+ suspended_threads_list.Append(threads[i]);
+ }
+
+ run_args->callback(suspended_threads_list, run_args->argument);
+
+ uptr num_suspended = suspended_threads_list.ThreadCount();
+ for (unsigned int i = 0; i < num_suspended; ++i) {
+ thread_resume(suspended_threads_list.GetThread(i));
+ }
+ return nullptr;
+}
+
+void StopTheWorld(StopTheWorldCallback callback, void *argument) {
+ struct RunThreadArgs arg = {callback, argument};
+ pthread_t run_thread = (pthread_t)internal_start_thread(RunThread, &arg);
+ internal_join_thread(run_thread);
+}
+
+#if defined(__x86_64__)
+typedef x86_thread_state64_t regs_struct;
+#define regs_flavor x86_THREAD_STATE64
+
+#define SP_REG __rsp
+
+#elif defined(__aarch64__)
+typedef arm_thread_state64_t regs_struct;
+#define regs_flavor ARM_THREAD_STATE64
+
+# if __DARWIN_UNIX03
+# define SP_REG __sp
+# else
+# define SP_REG sp
+# endif
+
+#elif defined(__i386)
+typedef x86_thread_state32_t regs_struct;
+#define regs_flavor x86_THREAD_STATE32
+
+#define SP_REG __esp
+
+#else
+#error "Unsupported architecture"
+#endif
+
+tid_t SuspendedThreadsListMac::GetThreadID(uptr index) const {
+ CHECK_LT(index, threads_.size());
+ return threads_[index].tid;
+}
+
+thread_t SuspendedThreadsListMac::GetThread(uptr index) const {
+ CHECK_LT(index, threads_.size());
+ return threads_[index].thread;
+}
+
+uptr SuspendedThreadsListMac::ThreadCount() const {
+ return threads_.size();
+}
+
+bool SuspendedThreadsListMac::ContainsThread(thread_t thread) const {
+ for (uptr i = 0; i < threads_.size(); i++) {
+ if (threads_[i].thread == thread) return true;
+ }
+ return false;
+}
+
+void SuspendedThreadsListMac::Append(thread_t thread) {
+ thread_identifier_info_data_t info;
+ mach_msg_type_number_t info_count = THREAD_IDENTIFIER_INFO_COUNT;
+ kern_return_t err = thread_info(thread, THREAD_IDENTIFIER_INFO,
+ (thread_info_t)&info, &info_count);
+ if (err != KERN_SUCCESS) {
+ VReport(1, "Error - unable to get thread ident for a thread\n");
+ return;
+ }
+ threads_.push_back({info.thread_id, thread});
+}
+
+PtraceRegistersStatus SuspendedThreadsListMac::GetRegistersAndSP(
+ uptr index, InternalMmapVector<uptr> *buffer, uptr *sp) const {
+ thread_t thread = GetThread(index);
+ regs_struct regs;
+ int err;
+ mach_msg_type_number_t reg_count = sizeof(regs) / sizeof(natural_t);
+ err = thread_get_state(thread, regs_flavor, (thread_state_t)&regs,
+ &reg_count);
+ if (err != KERN_SUCCESS) {
+ VReport(1, "Error - unable to get registers for a thread\n");
+ // KERN_INVALID_ARGUMENT indicates that either the flavor is invalid,
+ // or the thread does not exist. The other possible error case,
+ // MIG_ARRAY_TOO_LARGE, means that the state is too large, but it's
+ // still safe to proceed.
+ return err == KERN_INVALID_ARGUMENT ? REGISTERS_UNAVAILABLE_FATAL
+ : REGISTERS_UNAVAILABLE;
+ }
+
+ buffer->resize(RoundUpTo(sizeof(regs), sizeof(uptr)) / sizeof(uptr));
+ internal_memcpy(buffer->data(), &regs, sizeof(regs));
+#if defined(__aarch64__) && defined(arm_thread_state64_get_sp)
+ *sp = arm_thread_state64_get_sp(regs);
+#else
+ *sp = regs.SP_REG;
+#endif
+
+ // On x86_64 and aarch64, we must account for the stack redzone, which is 128
+ // bytes.
+ if (SANITIZER_WORDSIZE == 64) *sp -= 128;
+
+ return REGISTERS_AVAILABLE;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_APPLE && (defined(__x86_64__) || defined(__aarch64__)) ||
+ // defined(__i386))
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
new file mode 100644
index 00000000000..77102174792
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
@@ -0,0 +1,362 @@
+//===-- sanitizer_stoptheworld_netbsd_libcdep.cpp -------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// See sanitizer_stoptheworld.h for details.
+// This implementation was inspired by Markus Gutschke's linuxthreads.cc.
+//
+// This is a NetBSD variation of Linux stoptheworld implementation
+// See sanitizer_stoptheworld_linux_libcdep.cpp for code comments.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_NETBSD
+
+#include "sanitizer_stoptheworld.h"
+
+#include "sanitizer_atomic.h"
+#include "sanitizer_platform_limits_posix.h"
+
+#include <sys/types.h>
+
+#include <sys/ptrace.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+
+#error #include <machine/reg.h>
+
+#include <elf.h>
+#include <errno.h>
+#include <sched.h>
+#include <signal.h>
+#include <stddef.h>
+
+#define internal_sigaction_norestorer internal_sigaction
+
+#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_mutex.h"
+#include "sanitizer_placement_new.h"
+
+namespace __sanitizer {
+
+class SuspendedThreadsListNetBSD final : public SuspendedThreadsList {
+ public:
+ SuspendedThreadsListNetBSD() { thread_ids_.reserve(1024); }
+
+ tid_t GetThreadID(uptr index) const;
+ uptr ThreadCount() const;
+ bool ContainsTid(tid_t thread_id) const;
+ void Append(tid_t tid);
+
+ PtraceRegistersStatus GetRegistersAndSP(uptr index,
+ InternalMmapVector<uptr> *buffer,
+ uptr *sp) const;
+
+ private:
+ InternalMmapVector<tid_t> thread_ids_;
+};
+
+struct TracerThreadArgument {
+ StopTheWorldCallback callback;
+ void *callback_argument;
+ Mutex mutex;
+ atomic_uintptr_t done;
+ uptr parent_pid;
+};
+
+class ThreadSuspender {
+ public:
+ explicit ThreadSuspender(pid_t pid, TracerThreadArgument *arg)
+ : arg(arg), pid_(pid) {
+ CHECK_GE(pid, 0);
+ }
+ bool SuspendAllThreads();
+ void ResumeAllThreads();
+ void KillAllThreads();
+ SuspendedThreadsListNetBSD &suspended_threads_list() {
+ return suspended_threads_list_;
+ }
+ TracerThreadArgument *arg;
+
+ private:
+ SuspendedThreadsListNetBSD suspended_threads_list_;
+ pid_t pid_;
+};
+
+void ThreadSuspender::ResumeAllThreads() {
+ int pterrno;
+ if (!internal_iserror(internal_ptrace(PT_DETACH, pid_, (void *)(uptr)1, 0),
+ &pterrno)) {
+ VReport(2, "Detached from process %d.\n", pid_);
+ } else {
+ VReport(1, "Could not detach from process %d (errno %d).\n", pid_, pterrno);
+ }
+}
+
+void ThreadSuspender::KillAllThreads() {
+ internal_ptrace(PT_KILL, pid_, nullptr, 0);
+}
+
+bool ThreadSuspender::SuspendAllThreads() {
+ int pterrno;
+ if (internal_iserror(internal_ptrace(PT_ATTACH, pid_, nullptr, 0),
+ &pterrno)) {
+ Printf("Could not attach to process %d (errno %d).\n", pid_, pterrno);
+ return false;
+ }
+
+ int status;
+ uptr waitpid_status;
+ HANDLE_EINTR(waitpid_status, internal_waitpid(pid_, &status, 0));
+
+ VReport(2, "Attached to process %d.\n", pid_);
+
+#ifdef PT_LWPNEXT
+ struct ptrace_lwpstatus pl;
+ int op = PT_LWPNEXT;
+#else
+ struct ptrace_lwpinfo pl;
+ int op = PT_LWPINFO;
+#endif
+
+ pl.pl_lwpid = 0;
+
+ int val;
+ while ((val = internal_ptrace(op, pid_, (void *)&pl, sizeof(pl))) != -1 &&
+ pl.pl_lwpid != 0) {
+ suspended_threads_list_.Append(pl.pl_lwpid);
+ VReport(2, "Appended thread %d in process %d.\n", pl.pl_lwpid, pid_);
+ }
+ return true;
+}
+
+// Pointer to the ThreadSuspender instance for use in signal handler.
+static ThreadSuspender *thread_suspender_instance = nullptr;
+
+// Synchronous signals that should not be blocked.
+static const int kSyncSignals[] = {SIGABRT, SIGILL, SIGFPE, SIGSEGV,
+ SIGBUS, SIGXCPU, SIGXFSZ};
+
+static void TracerThreadDieCallback() {
+ ThreadSuspender *inst = thread_suspender_instance;
+ if (inst && stoptheworld_tracer_pid == internal_getpid()) {
+ inst->KillAllThreads();
+ thread_suspender_instance = nullptr;
+ }
+}
+
+// Signal handler to wake up suspended threads when the tracer thread dies.
+static void TracerThreadSignalHandler(int signum, __sanitizer_siginfo *siginfo,
+ void *uctx) {
+ SignalContext ctx(siginfo, uctx);
+ Printf("Tracer caught signal %d: addr=0x%zx pc=0x%zx sp=0x%zx\n", signum,
+ ctx.addr, ctx.pc, ctx.sp);
+ ThreadSuspender *inst = thread_suspender_instance;
+ if (inst) {
+ if (signum == SIGABRT)
+ inst->KillAllThreads();
+ else
+ inst->ResumeAllThreads();
+ RAW_CHECK(RemoveDieCallback(TracerThreadDieCallback));
+ thread_suspender_instance = nullptr;
+ atomic_store(&inst->arg->done, 1, memory_order_relaxed);
+ }
+ internal__exit((signum == SIGABRT) ? 1 : 2);
+}
+
+// Size of alternative stack for signal handlers in the tracer thread.
+static const int kHandlerStackSize = 8192;
+
+// This function will be run as a cloned task.
+static int TracerThread(void *argument) {
+ TracerThreadArgument *tracer_thread_argument =
+ (TracerThreadArgument *)argument;
+
+ // Check if parent is already dead.
+ if (internal_getppid() != tracer_thread_argument->parent_pid)
+ internal__exit(4);
+
+ // Wait for the parent thread to finish preparations.
+ tracer_thread_argument->mutex.Lock();
+ tracer_thread_argument->mutex.Unlock();
+
+ RAW_CHECK(AddDieCallback(TracerThreadDieCallback));
+
+ ThreadSuspender thread_suspender(internal_getppid(), tracer_thread_argument);
+ // Global pointer for the signal handler.
+ thread_suspender_instance = &thread_suspender;
+
+ // Alternate stack for signal handling.
+ InternalMmapVector<char> handler_stack_memory(kHandlerStackSize);
+ stack_t handler_stack;
+ internal_memset(&handler_stack, 0, sizeof(handler_stack));
+ handler_stack.ss_sp = handler_stack_memory.data();
+ handler_stack.ss_size = kHandlerStackSize;
+ internal_sigaltstack(&handler_stack, nullptr);
+
+ // Install our handler for synchronous signals. Other signals should be
+ // blocked by the mask we inherited from the parent thread.
+ for (uptr i = 0; i < ARRAY_SIZE(kSyncSignals); i++) {
+ __sanitizer_sigaction act;
+ internal_memset(&act, 0, sizeof(act));
+ act.sigaction = TracerThreadSignalHandler;
+ act.sa_flags = SA_ONSTACK | SA_SIGINFO;
+ internal_sigaction_norestorer(kSyncSignals[i], &act, 0);
+ }
+
+ int exit_code = 0;
+ if (!thread_suspender.SuspendAllThreads()) {
+ VReport(1, "Failed suspending threads.\n");
+ exit_code = 3;
+ } else {
+ tracer_thread_argument->callback(thread_suspender.suspended_threads_list(),
+ tracer_thread_argument->callback_argument);
+ thread_suspender.ResumeAllThreads();
+ exit_code = 0;
+ }
+ RAW_CHECK(RemoveDieCallback(TracerThreadDieCallback));
+ thread_suspender_instance = nullptr;
+ atomic_store(&tracer_thread_argument->done, 1, memory_order_relaxed);
+ return exit_code;
+}
+
+class ScopedStackSpaceWithGuard {
+ public:
+ explicit ScopedStackSpaceWithGuard(uptr stack_size) {
+ stack_size_ = stack_size;
+ guard_size_ = GetPageSizeCached();
+ // FIXME: Omitting MAP_STACK here works in current kernels but might break
+ // in the future.
+ guard_start_ =
+ (uptr)MmapOrDie(stack_size_ + guard_size_, "ScopedStackWithGuard");
+ CHECK(MprotectNoAccess((uptr)guard_start_, guard_size_));
+ }
+ ~ScopedStackSpaceWithGuard() {
+ UnmapOrDie((void *)guard_start_, stack_size_ + guard_size_);
+ }
+ void *Bottom() const {
+ return (void *)(guard_start_ + stack_size_ + guard_size_);
+ }
+
+ private:
+ uptr stack_size_;
+ uptr guard_size_;
+ uptr guard_start_;
+};
+
+static __sanitizer_sigset_t blocked_sigset;
+static __sanitizer_sigset_t old_sigset;
+
+struct ScopedSetTracerPID {
+ explicit ScopedSetTracerPID(uptr tracer_pid) {
+ stoptheworld_tracer_pid = tracer_pid;
+ stoptheworld_tracer_ppid = internal_getpid();
+ }
+ ~ScopedSetTracerPID() {
+ stoptheworld_tracer_pid = 0;
+ stoptheworld_tracer_ppid = 0;
+ }
+};
+
+void StopTheWorld(StopTheWorldCallback callback, void *argument) {
+ // Prepare the arguments for TracerThread.
+ struct TracerThreadArgument tracer_thread_argument;
+ tracer_thread_argument.callback = callback;
+ tracer_thread_argument.callback_argument = argument;
+ tracer_thread_argument.parent_pid = internal_getpid();
+ atomic_store(&tracer_thread_argument.done, 0, memory_order_relaxed);
+ const uptr kTracerStackSize = 2 * 1024 * 1024;
+ ScopedStackSpaceWithGuard tracer_stack(kTracerStackSize);
+
+ tracer_thread_argument.mutex.Lock();
+
+ internal_sigfillset(&blocked_sigset);
+ for (uptr i = 0; i < ARRAY_SIZE(kSyncSignals); i++)
+ internal_sigdelset(&blocked_sigset, kSyncSignals[i]);
+ int rv = internal_sigprocmask(SIG_BLOCK, &blocked_sigset, &old_sigset);
+ CHECK_EQ(rv, 0);
+ uptr tracer_pid = internal_clone(TracerThread, tracer_stack.Bottom(),
+ CLONE_VM | CLONE_FS | CLONE_FILES,
+ &tracer_thread_argument);
+ internal_sigprocmask(SIG_SETMASK, &old_sigset, 0);
+ int local_errno = 0;
+ if (internal_iserror(tracer_pid, &local_errno)) {
+ VReport(1, "Failed spawning a tracer thread (errno %d).\n", local_errno);
+ tracer_thread_argument.mutex.Unlock();
+ } else {
+ ScopedSetTracerPID scoped_set_tracer_pid(tracer_pid);
+
+ tracer_thread_argument.mutex.Unlock();
+
+ while (atomic_load(&tracer_thread_argument.done, memory_order_relaxed) == 0)
+ sched_yield();
+
+ for (;;) {
+ uptr waitpid_status = internal_waitpid(tracer_pid, nullptr, __WALL);
+ if (!internal_iserror(waitpid_status, &local_errno))
+ break;
+ if (local_errno == EINTR)
+ continue;
+ VReport(1, "Waiting on the tracer thread failed (errno %d).\n",
+ local_errno);
+ break;
+ }
+ }
+}
+
+tid_t SuspendedThreadsListNetBSD::GetThreadID(uptr index) const {
+ CHECK_LT(index, thread_ids_.size());
+ return thread_ids_[index];
+}
+
+uptr SuspendedThreadsListNetBSD::ThreadCount() const {
+ return thread_ids_.size();
+}
+
+bool SuspendedThreadsListNetBSD::ContainsTid(tid_t thread_id) const {
+ for (uptr i = 0; i < thread_ids_.size(); i++) {
+ if (thread_ids_[i] == thread_id)
+ return true;
+ }
+ return false;
+}
+
+void SuspendedThreadsListNetBSD::Append(tid_t tid) {
+ thread_ids_.push_back(tid);
+}
+
+PtraceRegistersStatus SuspendedThreadsListNetBSD::GetRegistersAndSP(
+ uptr index, InternalMmapVector<uptr> *buffer, uptr *sp) const {
+ lwpid_t tid = GetThreadID(index);
+ pid_t ppid = internal_getppid();
+ struct reg regs;
+ int pterrno;
+ bool isErr =
+ internal_iserror(internal_ptrace(PT_GETREGS, ppid, &regs, tid), &pterrno);
+ if (isErr) {
+ VReport(1,
+ "Could not get registers from process %d thread %d (errno %d).\n",
+ ppid, tid, pterrno);
+ return pterrno == ESRCH ? REGISTERS_UNAVAILABLE_FATAL
+ : REGISTERS_UNAVAILABLE;
+ }
+
+ *sp = PTRACE_REG_SP(&regs);
+ buffer->resize(RoundUpTo(sizeof(regs), sizeof(uptr)) / sizeof(uptr));
+ internal_memcpy(buffer->data(), &regs, sizeof(regs));
+
+ return REGISTERS_AVAILABLE;
+}
+
+} // namespace __sanitizer
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp
new file mode 100644
index 00000000000..f114acea79c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp
@@ -0,0 +1,175 @@
+//===-- sanitizer_stoptheworld_win.cpp ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// See sanitizer_stoptheworld.h for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_WINDOWS
+
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+// windows.h needs to be included before tlhelp32.h
+# include <tlhelp32.h>
+
+# include "sanitizer_stoptheworld.h"
+
+namespace __sanitizer {
+
+namespace {
+
+struct SuspendedThreadsListWindows final : public SuspendedThreadsList {
+ InternalMmapVector<HANDLE> threadHandles;
+ InternalMmapVector<DWORD> threadIds;
+
+ SuspendedThreadsListWindows() {
+ threadIds.reserve(1024);
+ threadHandles.reserve(1024);
+ }
+
+ PtraceRegistersStatus GetRegistersAndSP(uptr index,
+ InternalMmapVector<uptr> *buffer,
+ uptr *sp) const override;
+
+ tid_t GetThreadID(uptr index) const override;
+ uptr ThreadCount() const override;
+};
+
+// Stack Pointer register names on different architectures
+# if SANITIZER_X64
+# define SP_REG Rsp
+# elif SANITIZER_I386
+# define SP_REG Esp
+# elif SANITIZER_ARM | SANITIZER_ARM64
+# define SP_REG Sp
+# else
+# error Architecture not supported!
+# endif
+
+PtraceRegistersStatus SuspendedThreadsListWindows::GetRegistersAndSP(
+ uptr index, InternalMmapVector<uptr> *buffer, uptr *sp) const {
+ CHECK_LT(index, threadHandles.size());
+
+ buffer->resize(RoundUpTo(sizeof(CONTEXT), sizeof(uptr)) / sizeof(uptr));
+ CONTEXT *thread_context = reinterpret_cast<CONTEXT *>(buffer->data());
+ thread_context->ContextFlags = CONTEXT_ALL;
+ CHECK(GetThreadContext(threadHandles[index], thread_context));
+ *sp = thread_context->SP_REG;
+
+ return REGISTERS_AVAILABLE;
+}
+
+tid_t SuspendedThreadsListWindows::GetThreadID(uptr index) const {
+ CHECK_LT(index, threadIds.size());
+ return threadIds[index];
+}
+
+uptr SuspendedThreadsListWindows::ThreadCount() const {
+ return threadIds.size();
+}
+
+struct RunThreadArgs {
+ StopTheWorldCallback callback;
+ void *argument;
+};
+
+DWORD WINAPI RunThread(void *argument) {
+ RunThreadArgs *run_args = (RunThreadArgs *)argument;
+
+ const DWORD this_thread = GetCurrentThreadId();
+ const DWORD this_process = GetCurrentProcessId();
+
+ SuspendedThreadsListWindows suspended_threads_list;
+ bool new_thread_found;
+
+ do {
+ // Take a snapshot of all Threads
+ const HANDLE threads = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+ CHECK(threads != INVALID_HANDLE_VALUE);
+
+ THREADENTRY32 thread_entry;
+ thread_entry.dwSize = sizeof(thread_entry);
+ new_thread_found = false;
+
+ if (!Thread32First(threads, &thread_entry))
+ break;
+
+ do {
+ if (thread_entry.th32ThreadID == this_thread ||
+ thread_entry.th32OwnerProcessID != this_process)
+ continue;
+
+ bool suspended_thread = false;
+ for (const auto thread_id : suspended_threads_list.threadIds) {
+ if (thread_id == thread_entry.th32ThreadID) {
+ suspended_thread = true;
+ break;
+ }
+ }
+
+ // Skip the Thread if it was already suspended
+ if (suspended_thread)
+ continue;
+
+ const HANDLE thread =
+ OpenThread(THREAD_ALL_ACCESS, FALSE, thread_entry.th32ThreadID);
+ CHECK(thread);
+
+ if (SuspendThread(thread) == (DWORD)-1) {
+ DWORD last_error = GetLastError();
+
+ VPrintf(1, "Could not suspend thread %lu (error %lu)",
+ thread_entry.th32ThreadID, last_error);
+ continue;
+ }
+
+ suspended_threads_list.threadIds.push_back(thread_entry.th32ThreadID);
+ suspended_threads_list.threadHandles.push_back(thread);
+ new_thread_found = true;
+ } while (Thread32Next(threads, &thread_entry));
+
+ CloseHandle(threads);
+
+ // Between the call to `CreateToolhelp32Snapshot` and suspending the
+ // relevant Threads, new Threads could have potentially been created. So
+ // continue to find and suspend new Threads until we don't find any.
+ } while (new_thread_found);
+
+ // Now all Threads of this Process except of this Thread should be suspended.
+ // Execute the callback function.
+ run_args->callback(suspended_threads_list, run_args->argument);
+
+ // Resume all Threads
+ for (const auto suspended_thread_handle :
+ suspended_threads_list.threadHandles) {
+ CHECK_NE(ResumeThread(suspended_thread_handle), -1);
+ CloseHandle(suspended_thread_handle);
+ }
+
+ return 0;
+}
+
+} // namespace
+
+void StopTheWorld(StopTheWorldCallback callback, void *argument) {
+ struct RunThreadArgs arg = {callback, argument};
+ DWORD trace_thread_id;
+
+ auto trace_thread =
+ CreateThread(nullptr, 0, RunThread, &arg, 0, &trace_thread_id);
+ CHECK(trace_thread);
+
+ WaitForSingleObject(trace_thread, INFINITE);
+ CloseHandle(trace_thread);
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_WINDOWS
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_suppressions.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_suppressions.cpp
new file mode 100644
index 00000000000..a674034b8e2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_suppressions.cpp
@@ -0,0 +1,181 @@
+//===-- sanitizer_suppressions.cpp ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Suppression parsing/matching code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_suppressions.h"
+
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_file.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_placement_new.h"
+
+namespace __sanitizer {
+
+SuppressionContext::SuppressionContext(const char *suppression_types[],
+ int suppression_types_num)
+ : suppression_types_(suppression_types),
+ suppression_types_num_(suppression_types_num),
+ can_parse_(true) {
+ CHECK_LE(suppression_types_num_, kMaxSuppressionTypes);
+ internal_memset(has_suppression_type_, 0, suppression_types_num_);
+}
+
+#if !SANITIZER_FUCHSIA
+static bool GetPathAssumingFileIsRelativeToExec(const char *file_path,
+ /*out*/char *new_file_path,
+ uptr new_file_path_size) {
+ InternalMmapVector<char> exec(kMaxPathLength);
+ if (ReadBinaryNameCached(exec.data(), exec.size())) {
+ const char *file_name_pos = StripModuleName(exec.data());
+ uptr path_to_exec_len = file_name_pos - exec.data();
+ internal_strncat(new_file_path, exec.data(),
+ Min(path_to_exec_len, new_file_path_size - 1));
+ internal_strncat(new_file_path, file_path,
+ new_file_path_size - internal_strlen(new_file_path) - 1);
+ return true;
+ }
+ return false;
+}
+
+static const char *FindFile(const char *file_path,
+ /*out*/char *new_file_path,
+ uptr new_file_path_size) {
+ // If we cannot find the file, check if its location is relative to
+ // the location of the executable.
+ if (!FileExists(file_path) && !IsAbsolutePath(file_path) &&
+ GetPathAssumingFileIsRelativeToExec(file_path, new_file_path,
+ new_file_path_size)) {
+ return new_file_path;
+ }
+ return file_path;
+}
+#else
+static const char *FindFile(const char *file_path, char *, uptr) {
+ return file_path;
+}
+#endif
+
+void SuppressionContext::ParseFromFile(const char *filename) {
+ if (filename[0] == '\0')
+ return;
+
+ InternalMmapVector<char> new_file_path(kMaxPathLength);
+ filename = FindFile(filename, new_file_path.data(), new_file_path.size());
+
+ // Read the file.
+ VPrintf(1, "%s: reading suppressions file at %s\n",
+ SanitizerToolName, filename);
+ char *file_contents;
+ uptr buffer_size;
+ uptr contents_size;
+ if (!ReadFileToBuffer(filename, &file_contents, &buffer_size,
+ &contents_size)) {
+ Printf("%s: failed to read suppressions file '%s'\n", SanitizerToolName,
+ filename);
+ Die();
+ }
+
+ Parse(file_contents);
+}
+
+bool SuppressionContext::Match(const char *str, const char *type,
+ Suppression **s) {
+ can_parse_ = false;
+ if (!HasSuppressionType(type))
+ return false;
+ for (uptr i = 0; i < suppressions_.size(); i++) {
+ Suppression &cur = suppressions_[i];
+ if (0 == internal_strcmp(cur.type, type) && TemplateMatch(cur.templ, str)) {
+ *s = &cur;
+ return true;
+ }
+ }
+ return false;
+}
+
+static const char *StripPrefix(const char *str, const char *prefix) {
+ while (*str && *str == *prefix) {
+ str++;
+ prefix++;
+ }
+ if (!*prefix)
+ return str;
+ return 0;
+}
+
+void SuppressionContext::Parse(const char *str) {
+ // Context must not mutate once Match has been called.
+ CHECK(can_parse_);
+ const char *line = str;
+ while (line) {
+ while (line[0] == ' ' || line[0] == '\t')
+ line++;
+ const char *end = internal_strchr(line, '\n');
+ if (end == 0)
+ end = line + internal_strlen(line);
+ if (line != end && line[0] != '#') {
+ const char *end2 = end;
+ while (line != end2 &&
+ (end2[-1] == ' ' || end2[-1] == '\t' || end2[-1] == '\r'))
+ end2--;
+ int type;
+ for (type = 0; type < suppression_types_num_; type++) {
+ const char *next_char = StripPrefix(line, suppression_types_[type]);
+ if (next_char && *next_char == ':') {
+ line = ++next_char;
+ break;
+ }
+ }
+ if (type == suppression_types_num_) {
+ Printf("%s: failed to parse suppressions\n", SanitizerToolName);
+ Die();
+ }
+ Suppression s;
+ s.type = suppression_types_[type];
+ s.templ = (char*)InternalAlloc(end2 - line + 1);
+ internal_memcpy(s.templ, line, end2 - line);
+ s.templ[end2 - line] = 0;
+ suppressions_.push_back(s);
+ has_suppression_type_[type] = true;
+ }
+ if (end[0] == 0)
+ break;
+ line = end + 1;
+ }
+}
+
+uptr SuppressionContext::SuppressionCount() const {
+ return suppressions_.size();
+}
+
+bool SuppressionContext::HasSuppressionType(const char *type) const {
+ for (int i = 0; i < suppression_types_num_; i++) {
+ if (0 == internal_strcmp(type, suppression_types_[i]))
+ return has_suppression_type_[i];
+ }
+ return false;
+}
+
+const Suppression *SuppressionContext::SuppressionAt(uptr i) const {
+ CHECK_LT(i, suppressions_.size());
+ return &suppressions_[i];
+}
+
+void SuppressionContext::GetMatched(
+ InternalMmapVector<Suppression *> *matched) {
+ for (uptr i = 0; i < suppressions_.size(); i++)
+ if (atomic_load_relaxed(&suppressions_[i].hit_count))
+ matched->push_back(&suppressions_[i]);
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_suppressions.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_suppressions.h
new file mode 100644
index 00000000000..2d88b1f72fa
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_suppressions.h
@@ -0,0 +1,56 @@
+//===-- sanitizer_suppressions.h --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Suppression parsing/matching code.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SUPPRESSIONS_H
+#define SANITIZER_SUPPRESSIONS_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_atomic.h"
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+struct Suppression {
+ Suppression() { internal_memset(this, 0, sizeof(*this)); }
+ const char *type;
+ char *templ;
+ atomic_uint32_t hit_count;
+ uptr weight;
+};
+
+class SuppressionContext {
+ public:
+ // Create new SuppressionContext capable of parsing given suppression types.
+ SuppressionContext(const char *supprression_types[],
+ int suppression_types_num);
+
+ void ParseFromFile(const char *filename);
+ void Parse(const char *str);
+
+ bool Match(const char *str, const char *type, Suppression **s);
+ uptr SuppressionCount() const;
+ bool HasSuppressionType(const char *type) const;
+ const Suppression *SuppressionAt(uptr i) const;
+ void GetMatched(InternalMmapVector<Suppression *> *matched);
+
+ private:
+ static const int kMaxSuppressionTypes = 64;
+ const char **const suppression_types_;
+ const int suppression_types_num_;
+
+ InternalMmapVector<Suppression> suppressions_;
+ bool has_suppression_type_[kMaxSuppressionTypes];
+ bool can_parse_;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SUPPRESSIONS_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer.cpp
new file mode 100644
index 00000000000..d3cffaa6eef
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer.cpp
@@ -0,0 +1,141 @@
+//===-- sanitizer_symbolizer.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_platform.h"
+#include "sanitizer_symbolizer_internal.h"
+
+namespace __sanitizer {
+
+AddressInfo::AddressInfo() {
+ internal_memset(this, 0, sizeof(AddressInfo));
+ function_offset = kUnknown;
+}
+
+void AddressInfo::Clear() {
+ InternalFree(module);
+ InternalFree(function);
+ InternalFree(file);
+ internal_memset(this, 0, sizeof(AddressInfo));
+ function_offset = kUnknown;
+ uuid_size = 0;
+}
+
+void AddressInfo::FillModuleInfo(const char *mod_name, uptr mod_offset,
+ ModuleArch mod_arch) {
+ module = internal_strdup(mod_name);
+ module_offset = mod_offset;
+ module_arch = mod_arch;
+ uuid_size = 0;
+}
+
+void AddressInfo::FillModuleInfo(const LoadedModule &mod) {
+ module = internal_strdup(mod.full_name());
+ module_offset = address - mod.base_address();
+ module_arch = mod.arch();
+ if (mod.uuid_size())
+ internal_memcpy(uuid, mod.uuid(), mod.uuid_size());
+ uuid_size = mod.uuid_size();
+}
+
+SymbolizedStack::SymbolizedStack() : next(nullptr), info() {}
+
+SymbolizedStack *SymbolizedStack::New(uptr addr) {
+ void *mem = InternalAlloc(sizeof(SymbolizedStack));
+ SymbolizedStack *res = new(mem) SymbolizedStack();
+ res->info.address = addr;
+ return res;
+}
+
+void SymbolizedStack::ClearAll() {
+ info.Clear();
+ if (next)
+ next->ClearAll();
+ InternalFree(this);
+}
+
+DataInfo::DataInfo() {
+ internal_memset(this, 0, sizeof(DataInfo));
+}
+
+void DataInfo::Clear() {
+ InternalFree(module);
+ InternalFree(file);
+ InternalFree(name);
+ internal_memset(this, 0, sizeof(DataInfo));
+}
+
+void FrameInfo::Clear() {
+ InternalFree(module);
+ for (LocalInfo &local : locals) {
+ InternalFree(local.function_name);
+ InternalFree(local.name);
+ InternalFree(local.decl_file);
+ }
+ locals.clear();
+}
+
+Symbolizer *Symbolizer::symbolizer_;
+StaticSpinMutex Symbolizer::init_mu_;
+LowLevelAllocator Symbolizer::symbolizer_allocator_;
+
+void Symbolizer::InvalidateModuleList() {
+ modules_fresh_ = false;
+}
+
+void Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook,
+ Symbolizer::EndSymbolizationHook end_hook) {
+ CHECK(start_hook_ == 0 && end_hook_ == 0);
+ start_hook_ = start_hook;
+ end_hook_ = end_hook;
+}
+
+const char *Symbolizer::ModuleNameOwner::GetOwnedCopy(const char *str) {
+ mu_->CheckLocked();
+
+ // 'str' will be the same string multiple times in a row, optimize this case.
+ if (last_match_ && !internal_strcmp(last_match_, str))
+ return last_match_;
+
+ // FIXME: this is linear search.
+ // We should optimize this further if this turns out to be a bottleneck later.
+ for (uptr i = 0; i < storage_.size(); ++i) {
+ if (!internal_strcmp(storage_[i], str)) {
+ last_match_ = storage_[i];
+ return last_match_;
+ }
+ }
+ last_match_ = internal_strdup(str);
+ storage_.push_back(last_match_);
+ return last_match_;
+}
+
+Symbolizer::Symbolizer(IntrusiveList<SymbolizerTool> tools)
+ : module_names_(&mu_), modules_(), modules_fresh_(false), tools_(tools),
+ start_hook_(0), end_hook_(0) {}
+
+Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym)
+ : sym_(sym) {
+ if (sym_->start_hook_)
+ sym_->start_hook_();
+}
+
+Symbolizer::SymbolizerScope::~SymbolizerScope() {
+ if (sym_->end_hook_)
+ sym_->end_hook_();
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer.h
new file mode 100644
index 00000000000..bad4761e345
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer.h
@@ -0,0 +1,224 @@
+//===-- sanitizer_symbolizer.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Symbolizer is used by sanitizers to map instruction address to a location in
+// source code at run-time. Symbolizer either uses __sanitizer_symbolize_*
+// defined in the program, or (if they are missing) tries to find and
+// launch "llvm-symbolizer" commandline tool in a separate process and
+// communicate with it.
+//
+// Generally we should try to avoid calling system library functions during
+// symbolization (and use their replacements from sanitizer_libc.h instead).
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SYMBOLIZER_H
+#define SANITIZER_SYMBOLIZER_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_mutex.h"
+#include "sanitizer_vector.h"
+
+namespace __sanitizer {
+
+struct AddressInfo {
+ // Owns all the string members. Storage for them is
+ // (de)allocated using sanitizer internal allocator.
+ uptr address;
+
+ char *module;
+ uptr module_offset;
+ ModuleArch module_arch;
+ u8 uuid[kModuleUUIDSize];
+ uptr uuid_size;
+
+ static const uptr kUnknown = ~(uptr)0;
+ char *function;
+ uptr function_offset;
+
+ char *file;
+ int line;
+ int column;
+
+ AddressInfo();
+ // Deletes all strings and resets all fields.
+ void Clear();
+ void FillModuleInfo(const char *mod_name, uptr mod_offset, ModuleArch arch);
+ void FillModuleInfo(const LoadedModule &mod);
+ uptr module_base() const { return address - module_offset; }
+};
+
+// Linked list of symbolized frames (each frame is described by AddressInfo).
+struct SymbolizedStack {
+ SymbolizedStack *next;
+ AddressInfo info;
+ static SymbolizedStack *New(uptr addr);
+ // Deletes current, and all subsequent frames in the linked list.
+ // The object cannot be accessed after the call to this function.
+ void ClearAll();
+
+ private:
+ SymbolizedStack();
+};
+
+// For now, DataInfo is used to describe global variable.
+struct DataInfo {
+ // Owns all the string members. Storage for them is
+ // (de)allocated using sanitizer internal allocator.
+ char *module;
+ uptr module_offset;
+ ModuleArch module_arch;
+
+ char *file;
+ uptr line;
+ char *name;
+ uptr start;
+ uptr size;
+
+ DataInfo();
+ void Clear();
+};
+
+struct LocalInfo {
+ char *function_name = nullptr;
+ char *name = nullptr;
+ char *decl_file = nullptr;
+ unsigned decl_line = 0;
+
+ bool has_frame_offset = false;
+ bool has_size = false;
+ bool has_tag_offset = false;
+
+ sptr frame_offset;
+ uptr size;
+ uptr tag_offset;
+
+ void Clear();
+};
+
+struct FrameInfo {
+ char *module;
+ uptr module_offset;
+ ModuleArch module_arch;
+
+ InternalMmapVector<LocalInfo> locals;
+ void Clear();
+};
+
+class SymbolizerTool;
+
+class Symbolizer final {
+ public:
+ /// Initialize and return platform-specific implementation of symbolizer
+ /// (if it wasn't already initialized).
+ static Symbolizer *GetOrInit();
+ static void LateInitialize();
+ // Returns a list of symbolized frames for a given address (containing
+ // all inlined functions, if necessary).
+ SymbolizedStack *SymbolizePC(uptr address);
+ bool SymbolizeData(uptr address, DataInfo *info);
+ bool SymbolizeFrame(uptr address, FrameInfo *info);
+
+ // The module names Symbolizer returns are stable and unique for every given
+ // module. It is safe to store and compare them as pointers.
+ bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
+ uptr *module_address);
+ const char *GetModuleNameForPc(uptr pc) {
+ const char *module_name = nullptr;
+ uptr unused;
+ if (GetModuleNameAndOffsetForPC(pc, &module_name, &unused))
+ return module_name;
+ return nullptr;
+ }
+
+ // Release internal caches (if any).
+ void Flush();
+ // Attempts to demangle the provided C++ mangled name.
+ const char *Demangle(const char *name);
+
+ // Allow user to install hooks that would be called before/after Symbolizer
+ // does the actual file/line info fetching. Specific sanitizers may need this
+ // to distinguish system library calls made in user code from calls made
+ // during in-process symbolization.
+ typedef void (*StartSymbolizationHook)();
+ typedef void (*EndSymbolizationHook)();
+ // May be called at most once.
+ void AddHooks(StartSymbolizationHook start_hook,
+ EndSymbolizationHook end_hook);
+
+ void RefreshModules();
+ const LoadedModule *FindModuleForAddress(uptr address);
+
+ void InvalidateModuleList();
+
+ private:
+ // GetModuleNameAndOffsetForPC has to return a string to the caller.
+ // Since the corresponding module might get unloaded later, we should create
+ // our owned copies of the strings that we can safely return.
+ // ModuleNameOwner does not provide any synchronization, thus calls to
+ // its method should be protected by |mu_|.
+ class ModuleNameOwner {
+ public:
+ explicit ModuleNameOwner(Mutex *synchronized_by)
+ : last_match_(nullptr), mu_(synchronized_by) {
+ storage_.reserve(kInitialCapacity);
+ }
+ const char *GetOwnedCopy(const char *str);
+
+ private:
+ static const uptr kInitialCapacity = 1000;
+ InternalMmapVector<const char*> storage_;
+ const char *last_match_;
+
+ Mutex *mu_;
+ } module_names_;
+
+ /// Platform-specific function for creating a Symbolizer object.
+ static Symbolizer *PlatformInit();
+
+ bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name,
+ uptr *module_offset,
+ ModuleArch *module_arch);
+ ListOfModules modules_;
+ ListOfModules fallback_modules_;
+ // If stale, need to reload the modules before looking up addresses.
+ bool modules_fresh_;
+
+ // Platform-specific default demangler, must not return nullptr.
+ const char *PlatformDemangle(const char *name);
+
+ static Symbolizer *symbolizer_;
+ static StaticSpinMutex init_mu_;
+
+ // Mutex locked from public methods of |Symbolizer|, so that the internals
+ // (including individual symbolizer tools and platform-specific methods) are
+ // always synchronized.
+ Mutex mu_;
+
+ IntrusiveList<SymbolizerTool> tools_;
+
+ explicit Symbolizer(IntrusiveList<SymbolizerTool> tools);
+
+ static LowLevelAllocator symbolizer_allocator_;
+
+ StartSymbolizationHook start_hook_;
+ EndSymbolizationHook end_hook_;
+ class SymbolizerScope {
+ public:
+ explicit SymbolizerScope(const Symbolizer *sym);
+ ~SymbolizerScope();
+ private:
+ const Symbolizer *sym_;
+ };
+};
+
+#ifdef SANITIZER_WINDOWS
+void InitializeDbgHelpIfNeeded();
+#endif
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SYMBOLIZER_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_fuchsia.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_fuchsia.h
new file mode 100644
index 00000000000..c4061e38c6a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_fuchsia.h
@@ -0,0 +1,42 @@
+//===-- sanitizer_symbolizer_fuchsia.h -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between various sanitizers' runtime libraries.
+//
+// Define Fuchsia's string formats and limits for the markup symbolizer.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SYMBOLIZER_FUCHSIA_H
+#define SANITIZER_SYMBOLIZER_FUCHSIA_H
+
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+// See the spec at:
+// https://fuchsia.googlesource.com/zircon/+/master/docs/symbolizer_markup.md
+
+// This is used by UBSan for type names, and by ASan for global variable names.
+constexpr const char *kFormatDemangle = "{{{symbol:%s}}}";
+constexpr uptr kFormatDemangleMax = 1024; // Arbitrary.
+
+// Function name or equivalent from PC location.
+constexpr const char *kFormatFunction = "{{{pc:%p}}}";
+constexpr uptr kFormatFunctionMax = 64; // More than big enough for 64-bit hex.
+
+// Global variable name or equivalent from data memory address.
+constexpr const char *kFormatData = "{{{data:%p}}}";
+
+// One frame in a backtrace (printed on a line by itself).
+constexpr const char *kFormatFrame = "{{{bt:%u:%p}}}";
+
+// Dump trigger element.
+#define FORMAT_DUMPFILE "{{{dumpfile:%s:%s}}}"
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SYMBOLIZER_FUCHSIA_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h
new file mode 100644
index 00000000000..29a08386d0b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h
@@ -0,0 +1,165 @@
+//===-- sanitizer_symbolizer_internal.h -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Header for internal classes and functions to be used by implementations of
+// symbolizers.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SYMBOLIZER_INTERNAL_H
+#define SANITIZER_SYMBOLIZER_INTERNAL_H
+
+#include "sanitizer_symbolizer.h"
+#include "sanitizer_file.h"
+#include "sanitizer_vector.h"
+
+namespace __sanitizer {
+
+// Parsing helpers, 'str' is searched for delimiter(s) and a string or uptr
+// is extracted. When extracting a string, a newly allocated (using
+// InternalAlloc) and null-terminated buffer is returned. They return a pointer
+// to the next characted after the found delimiter.
+const char *ExtractToken(const char *str, const char *delims, char **result);
+const char *ExtractInt(const char *str, const char *delims, int *result);
+const char *ExtractUptr(const char *str, const char *delims, uptr *result);
+const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
+ char **result);
+
+const char *DemangleSwiftAndCXX(const char *name);
+
+// SymbolizerTool is an interface that is implemented by individual "tools"
+// that can perform symbolication (external llvm-symbolizer, libbacktrace,
+// Windows DbgHelp symbolizer, etc.).
+class SymbolizerTool {
+ public:
+ // The main |Symbolizer| class implements a "fallback chain" of symbolizer
+ // tools. In a request to symbolize an address, if one tool returns false,
+ // the next tool in the chain will be tried.
+ SymbolizerTool *next;
+
+ SymbolizerTool() : next(nullptr) { }
+
+ // Can't declare pure virtual functions in sanitizer runtimes:
+ // __cxa_pure_virtual might be unavailable.
+
+ // The |stack| parameter is inout. It is pre-filled with the address,
+ // module base and module offset values and is to be used to construct
+ // other stack frames.
+ virtual bool SymbolizePC(uptr addr, SymbolizedStack *stack) {
+ UNIMPLEMENTED();
+ }
+
+ // The |info| parameter is inout. It is pre-filled with the module base
+ // and module offset values.
+ virtual bool SymbolizeData(uptr addr, DataInfo *info) {
+ UNIMPLEMENTED();
+ }
+
+ virtual bool SymbolizeFrame(uptr addr, FrameInfo *info) {
+ return false;
+ }
+
+ virtual void Flush() {}
+
+ // Return nullptr to fallback to the default platform-specific demangler.
+ virtual const char *Demangle(const char *name) {
+ return nullptr;
+ }
+
+ protected:
+ ~SymbolizerTool() {}
+};
+
+// SymbolizerProcess encapsulates communication between the tool and
+// external symbolizer program, running in a different subprocess.
+// SymbolizerProcess may not be used from two threads simultaneously.
+class SymbolizerProcess {
+ public:
+ explicit SymbolizerProcess(const char *path, bool use_posix_spawn = false);
+ const char *SendCommand(const char *command);
+
+ protected:
+ ~SymbolizerProcess() {}
+
+ /// The maximum number of arguments required to invoke a tool process.
+ static const unsigned kArgVMax = 16;
+
+ // Customizable by subclasses.
+ virtual bool StartSymbolizerSubprocess();
+ virtual bool ReadFromSymbolizer();
+ // Return the environment to run the symbolizer in.
+ virtual char **GetEnvP() { return GetEnviron(); }
+ InternalMmapVector<char> &GetBuff() { return buffer_; }
+
+ private:
+ virtual bool ReachedEndOfOutput(const char *buffer, uptr length) const {
+ UNIMPLEMENTED();
+ }
+
+ /// Fill in an argv array to invoke the child process.
+ virtual void GetArgV(const char *path_to_binary,
+ const char *(&argv)[kArgVMax]) const {
+ UNIMPLEMENTED();
+ }
+
+ bool Restart();
+ const char *SendCommandImpl(const char *command);
+ bool WriteToSymbolizer(const char *buffer, uptr length);
+
+ const char *path_;
+ fd_t input_fd_;
+ fd_t output_fd_;
+
+ InternalMmapVector<char> buffer_;
+
+ static const uptr kMaxTimesRestarted = 5;
+ static const int kSymbolizerStartupTimeMillis = 10;
+ uptr times_restarted_;
+ bool failed_to_start_;
+ bool reported_invalid_path_;
+ bool use_posix_spawn_;
+};
+
+class LLVMSymbolizerProcess;
+
+// This tool invokes llvm-symbolizer in a subprocess. It should be as portable
+// as the llvm-symbolizer tool is.
+class LLVMSymbolizer final : public SymbolizerTool {
+ public:
+ explicit LLVMSymbolizer(const char *path, LowLevelAllocator *allocator);
+
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
+ bool SymbolizeData(uptr addr, DataInfo *info) override;
+ bool SymbolizeFrame(uptr addr, FrameInfo *info) override;
+
+ private:
+ const char *FormatAndSendCommand(const char *command_prefix,
+ const char *module_name, uptr module_offset,
+ ModuleArch arch);
+
+ LLVMSymbolizerProcess *symbolizer_process_;
+ static const uptr kBufferSize = 16 * 1024;
+ char buffer_[kBufferSize];
+};
+
+// Parses one or more two-line strings in the following format:
+// <function_name>
+// <file_name>:<line_number>[:<column_number>]
+// Used by LLVMSymbolizer, Addr2LinePool and InternalSymbolizer, since all of
+// them use the same output format. Returns true if any useful debug
+// information was found.
+void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res);
+
+// Parses a two-line string in the following format:
+// <symbol_name>
+// <start_address> <size>
+// Used by LLVMSymbolizer and InternalSymbolizer.
+void ParseSymbolizeDataOutput(const char *str, DataInfo *info);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SYMBOLIZER_INTERNAL_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
new file mode 100644
index 00000000000..c3b27992616
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
@@ -0,0 +1,209 @@
+//===-- sanitizer_symbolizer_libbacktrace.cpp -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+// Libbacktrace implementation of symbolizer parts.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_symbolizer.h"
+#include "sanitizer_symbolizer_libbacktrace.h"
+
+#if SANITIZER_LIBBACKTRACE
+# error #include "backtrace-supported.h"
+# if SANITIZER_POSIX && BACKTRACE_SUPPORTED && !BACKTRACE_USES_MALLOC
+# error #include "backtrace.h"
+# if SANITIZER_CP_DEMANGLE
+# undef ARRAY_SIZE
+# error #include "demangle.h"
+# endif
+# else
+# define SANITIZER_LIBBACKTRACE 0
+# endif
+#endif
+
+namespace __sanitizer {
+
+static char *DemangleAlloc(const char *name, bool always_alloc);
+
+#if SANITIZER_LIBBACKTRACE
+
+namespace {
+
+# if SANITIZER_CP_DEMANGLE
+struct CplusV3DemangleData {
+ char *buf;
+ uptr size, allocated;
+};
+
+extern "C" {
+static void CplusV3DemangleCallback(const char *s, size_t l, void *vdata) {
+ CplusV3DemangleData *data = (CplusV3DemangleData *)vdata;
+ uptr needed = data->size + l + 1;
+ if (needed > data->allocated) {
+ data->allocated *= 2;
+ if (needed > data->allocated)
+ data->allocated = needed;
+ char *buf = (char *)InternalAlloc(data->allocated);
+ if (data->buf) {
+ internal_memcpy(buf, data->buf, data->size);
+ InternalFree(data->buf);
+ }
+ data->buf = buf;
+ }
+ internal_memcpy(data->buf + data->size, s, l);
+ data->buf[data->size + l] = '\0';
+ data->size += l;
+}
+} // extern "C"
+
+char *CplusV3Demangle(const char *name) {
+ CplusV3DemangleData data;
+ data.buf = 0;
+ data.size = 0;
+ data.allocated = 0;
+ if (cplus_demangle_v3_callback(name, DMGL_PARAMS | DMGL_ANSI,
+ CplusV3DemangleCallback, &data)) {
+ if (data.size + 64 > data.allocated)
+ return data.buf;
+ char *buf = internal_strdup(data.buf);
+ InternalFree(data.buf);
+ return buf;
+ }
+ if (data.buf)
+ InternalFree(data.buf);
+ return 0;
+}
+# endif // SANITIZER_CP_DEMANGLE
+
+struct SymbolizeCodeCallbackArg {
+ SymbolizedStack *first;
+ SymbolizedStack *last;
+ uptr frames_symbolized;
+
+ AddressInfo *get_new_frame(uintptr_t addr) {
+ CHECK(last);
+ if (frames_symbolized > 0) {
+ SymbolizedStack *cur = SymbolizedStack::New(addr);
+ AddressInfo *info = &cur->info;
+ info->FillModuleInfo(first->info.module, first->info.module_offset,
+ first->info.module_arch);
+ last->next = cur;
+ last = cur;
+ }
+ CHECK_EQ(addr, first->info.address);
+ CHECK_EQ(addr, last->info.address);
+ return &last->info;
+ }
+};
+
+extern "C" {
+static int SymbolizeCodePCInfoCallback(void *vdata, uintptr_t addr,
+ const char *filename, int lineno,
+ const char *function) {
+ SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata;
+ if (function) {
+ AddressInfo *info = cdata->get_new_frame(addr);
+ info->function = DemangleAlloc(function, /*always_alloc*/ true);
+ if (filename)
+ info->file = internal_strdup(filename);
+ info->line = lineno;
+ cdata->frames_symbolized++;
+ }
+ return 0;
+}
+
+static void SymbolizeCodeCallback(void *vdata, uintptr_t addr,
+ const char *symname, uintptr_t, uintptr_t) {
+ SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata;
+ if (symname) {
+ AddressInfo *info = cdata->get_new_frame(addr);
+ info->function = DemangleAlloc(symname, /*always_alloc*/ true);
+ cdata->frames_symbolized++;
+ }
+}
+
+static void SymbolizeDataCallback(void *vdata, uintptr_t, const char *symname,
+ uintptr_t symval, uintptr_t symsize) {
+ DataInfo *info = (DataInfo *)vdata;
+ if (symname && symval) {
+ info->name = DemangleAlloc(symname, /*always_alloc*/ true);
+ info->start = symval;
+ info->size = symsize;
+ }
+}
+
+static void ErrorCallback(void *, const char *, int) {}
+} // extern "C"
+
+} // namespace
+
+LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
+ // State created in backtrace_create_state is leaked.
+ void *state = (void *)(backtrace_create_state("/proc/self/exe", 0,
+ ErrorCallback, NULL));
+ if (!state)
+ return 0;
+ return new(*alloc) LibbacktraceSymbolizer(state);
+}
+
+bool LibbacktraceSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
+ SymbolizeCodeCallbackArg data;
+ data.first = stack;
+ data.last = stack;
+ data.frames_symbolized = 0;
+ backtrace_pcinfo((backtrace_state *)state_, addr, SymbolizeCodePCInfoCallback,
+ ErrorCallback, &data);
+ if (data.frames_symbolized > 0)
+ return true;
+ backtrace_syminfo((backtrace_state *)state_, addr, SymbolizeCodeCallback,
+ ErrorCallback, &data);
+ return (data.frames_symbolized > 0);
+}
+
+bool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
+ backtrace_syminfo((backtrace_state *)state_, addr, SymbolizeDataCallback,
+ ErrorCallback, info);
+ return true;
+}
+
+#else // SANITIZER_LIBBACKTRACE
+
+LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
+ return 0;
+}
+
+bool LibbacktraceSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
+ (void)state_;
+ return false;
+}
+
+bool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
+ return false;
+}
+
+#endif // SANITIZER_LIBBACKTRACE
+
+static char *DemangleAlloc(const char *name, bool always_alloc) {
+#if SANITIZER_LIBBACKTRACE && SANITIZER_CP_DEMANGLE
+ if (char *demangled = CplusV3Demangle(name))
+ return demangled;
+#endif
+ if (always_alloc)
+ return internal_strdup(name);
+ return 0;
+}
+
+const char *LibbacktraceSymbolizer::Demangle(const char *name) {
+ return DemangleAlloc(name, /*always_alloc*/ false);
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
new file mode 100644
index 00000000000..7b039b894b3
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
@@ -0,0 +1,49 @@
+//===-- sanitizer_symbolizer_libbacktrace.h ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+// Header for libbacktrace symbolizer.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SYMBOLIZER_LIBBACKTRACE_H
+#define SANITIZER_SYMBOLIZER_LIBBACKTRACE_H
+
+#include "sanitizer_platform.h"
+#include "sanitizer_common.h"
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_symbolizer_internal.h"
+
+#ifndef SANITIZER_LIBBACKTRACE
+# define SANITIZER_LIBBACKTRACE 0
+#endif
+
+#ifndef SANITIZER_CP_DEMANGLE
+# define SANITIZER_CP_DEMANGLE 0
+#endif
+
+namespace __sanitizer {
+
+class LibbacktraceSymbolizer final : public SymbolizerTool {
+ public:
+ static LibbacktraceSymbolizer *get(LowLevelAllocator *alloc);
+
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
+
+ bool SymbolizeData(uptr addr, DataInfo *info) override;
+
+ // May return NULL if demangling failed.
+ const char *Demangle(const char *name) override;
+
+ private:
+ explicit LibbacktraceSymbolizer(void *state) : state_(state) {}
+
+ void *state_; // Leaked.
+};
+
+} // namespace __sanitizer
+#endif // SANITIZER_SYMBOLIZER_LIBBACKTRACE_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
new file mode 100644
index 00000000000..a6f82ced203
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
@@ -0,0 +1,568 @@
+//===-- sanitizer_symbolizer_libcdep.cpp ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform.h"
+#include "sanitizer_symbolizer_internal.h"
+
+namespace __sanitizer {
+
+Symbolizer *Symbolizer::GetOrInit() {
+ SpinMutexLock l(&init_mu_);
+ if (symbolizer_)
+ return symbolizer_;
+ symbolizer_ = PlatformInit();
+ CHECK(symbolizer_);
+ return symbolizer_;
+}
+
+// See sanitizer_symbolizer_markup.cpp.
+#if !SANITIZER_SYMBOLIZER_MARKUP
+
+const char *ExtractToken(const char *str, const char *delims, char **result) {
+ uptr prefix_len = internal_strcspn(str, delims);
+ *result = (char*)InternalAlloc(prefix_len + 1);
+ internal_memcpy(*result, str, prefix_len);
+ (*result)[prefix_len] = '\0';
+ const char *prefix_end = str + prefix_len;
+ if (*prefix_end != '\0') prefix_end++;
+ return prefix_end;
+}
+
+const char *ExtractInt(const char *str, const char *delims, int *result) {
+ char *buff = nullptr;
+ const char *ret = ExtractToken(str, delims, &buff);
+ if (buff) {
+ *result = (int)internal_atoll(buff);
+ }
+ InternalFree(buff);
+ return ret;
+}
+
+const char *ExtractUptr(const char *str, const char *delims, uptr *result) {
+ char *buff = nullptr;
+ const char *ret = ExtractToken(str, delims, &buff);
+ if (buff) {
+ *result = (uptr)internal_atoll(buff);
+ }
+ InternalFree(buff);
+ return ret;
+}
+
+const char *ExtractSptr(const char *str, const char *delims, sptr *result) {
+ char *buff = nullptr;
+ const char *ret = ExtractToken(str, delims, &buff);
+ if (buff) {
+ *result = (sptr)internal_atoll(buff);
+ }
+ InternalFree(buff);
+ return ret;
+}
+
+const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter,
+ char **result) {
+ const char *found_delimiter = internal_strstr(str, delimiter);
+ uptr prefix_len =
+ found_delimiter ? found_delimiter - str : internal_strlen(str);
+ *result = (char *)InternalAlloc(prefix_len + 1);
+ internal_memcpy(*result, str, prefix_len);
+ (*result)[prefix_len] = '\0';
+ const char *prefix_end = str + prefix_len;
+ if (*prefix_end != '\0') prefix_end += internal_strlen(delimiter);
+ return prefix_end;
+}
+
+SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
+ Lock l(&mu_);
+ SymbolizedStack *res = SymbolizedStack::New(addr);
+ auto *mod = FindModuleForAddress(addr);
+ if (!mod)
+ return res;
+ // Always fill data about module name and offset.
+ res->info.FillModuleInfo(*mod);
+ for (auto &tool : tools_) {
+ SymbolizerScope sym_scope(this);
+ if (tool.SymbolizePC(addr, res)) {
+ return res;
+ }
+ }
+ return res;
+}
+
+bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
+ Lock l(&mu_);
+ const char *module_name = nullptr;
+ uptr module_offset;
+ ModuleArch arch;
+ if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset,
+ &arch))
+ return false;
+ info->Clear();
+ info->module = internal_strdup(module_name);
+ info->module_offset = module_offset;
+ info->module_arch = arch;
+ for (auto &tool : tools_) {
+ SymbolizerScope sym_scope(this);
+ if (tool.SymbolizeData(addr, info)) {
+ return true;
+ }
+ }
+ return true;
+}
+
+bool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) {
+ Lock l(&mu_);
+ const char *module_name = nullptr;
+ if (!FindModuleNameAndOffsetForAddress(
+ addr, &module_name, &info->module_offset, &info->module_arch))
+ return false;
+ info->module = internal_strdup(module_name);
+ for (auto &tool : tools_) {
+ SymbolizerScope sym_scope(this);
+ if (tool.SymbolizeFrame(addr, info)) {
+ return true;
+ }
+ }
+ return true;
+}
+
+bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
+ uptr *module_address) {
+ Lock l(&mu_);
+ const char *internal_module_name = nullptr;
+ ModuleArch arch;
+ if (!FindModuleNameAndOffsetForAddress(pc, &internal_module_name,
+ module_address, &arch))
+ return false;
+
+ if (module_name)
+ *module_name = module_names_.GetOwnedCopy(internal_module_name);
+ return true;
+}
+
+void Symbolizer::Flush() {
+ Lock l(&mu_);
+ for (auto &tool : tools_) {
+ SymbolizerScope sym_scope(this);
+ tool.Flush();
+ }
+}
+
+const char *Symbolizer::Demangle(const char *name) {
+ Lock l(&mu_);
+ for (auto &tool : tools_) {
+ SymbolizerScope sym_scope(this);
+ if (const char *demangled = tool.Demangle(name))
+ return demangled;
+ }
+ return PlatformDemangle(name);
+}
+
+bool Symbolizer::FindModuleNameAndOffsetForAddress(uptr address,
+ const char **module_name,
+ uptr *module_offset,
+ ModuleArch *module_arch) {
+ const LoadedModule *module = FindModuleForAddress(address);
+ if (!module)
+ return false;
+ *module_name = module->full_name();
+ *module_offset = address - module->base_address();
+ *module_arch = module->arch();
+ return true;
+}
+
+void Symbolizer::RefreshModules() {
+ modules_.init();
+ fallback_modules_.fallbackInit();
+ RAW_CHECK(modules_.size() > 0);
+ modules_fresh_ = true;
+}
+
+static const LoadedModule *SearchForModule(const ListOfModules &modules,
+ uptr address) {
+ for (uptr i = 0; i < modules.size(); i++) {
+ if (modules[i].containsAddress(address)) {
+ return &modules[i];
+ }
+ }
+ return nullptr;
+}
+
+const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) {
+ bool modules_were_reloaded = false;
+ if (!modules_fresh_) {
+ RefreshModules();
+ modules_were_reloaded = true;
+ }
+ const LoadedModule *module = SearchForModule(modules_, address);
+ if (module) return module;
+
+ // dlopen/dlclose interceptors invalidate the module list, but when
+ // interception is disabled, we need to retry if the lookup fails in
+ // case the module list changed.
+#if !SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
+ if (!modules_were_reloaded) {
+ RefreshModules();
+ module = SearchForModule(modules_, address);
+ if (module) return module;
+ }
+#endif
+
+ if (fallback_modules_.size()) {
+ module = SearchForModule(fallback_modules_, address);
+ }
+ return module;
+}
+
+// For now we assume the following protocol:
+// For each request of the form
+// <module_name> <module_offset>
+// passed to STDIN, external symbolizer prints to STDOUT response:
+// <function_name>
+// <file_name>:<line_number>:<column_number>
+// <function_name>
+// <file_name>:<line_number>:<column_number>
+// ...
+// <empty line>
+class LLVMSymbolizerProcess final : public SymbolizerProcess {
+ public:
+ explicit LLVMSymbolizerProcess(const char *path)
+ : SymbolizerProcess(path, /*use_posix_spawn=*/SANITIZER_APPLE) {}
+
+ private:
+ bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
+ // Empty line marks the end of llvm-symbolizer output.
+ return length >= 2 && buffer[length - 1] == '\n' &&
+ buffer[length - 2] == '\n';
+ }
+
+ // When adding a new architecture, don't forget to also update
+ // script/asan_symbolize.py and sanitizer_common.h.
+ void GetArgV(const char *path_to_binary,
+ const char *(&argv)[kArgVMax]) const override {
+#if defined(__x86_64h__)
+ const char* const kSymbolizerArch = "--default-arch=x86_64h";
+#elif defined(__x86_64__)
+ const char* const kSymbolizerArch = "--default-arch=x86_64";
+#elif defined(__i386__)
+ const char* const kSymbolizerArch = "--default-arch=i386";
+#elif SANITIZER_LOONGARCH64
+ const char *const kSymbolizerArch = "--default-arch=loongarch64";
+#elif SANITIZER_RISCV64
+ const char *const kSymbolizerArch = "--default-arch=riscv64";
+#elif defined(__aarch64__)
+ const char* const kSymbolizerArch = "--default-arch=arm64";
+#elif defined(__arm__)
+ const char* const kSymbolizerArch = "--default-arch=arm";
+#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ const char* const kSymbolizerArch = "--default-arch=powerpc64";
+#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ const char* const kSymbolizerArch = "--default-arch=powerpc64le";
+#elif defined(__s390x__)
+ const char* const kSymbolizerArch = "--default-arch=s390x";
+#elif defined(__s390__)
+ const char* const kSymbolizerArch = "--default-arch=s390";
+#else
+ const char* const kSymbolizerArch = "--default-arch=unknown";
+#endif
+
+ const char *const demangle_flag =
+ common_flags()->demangle ? "--demangle" : "--no-demangle";
+ const char *const inline_flag =
+ common_flags()->symbolize_inline_frames ? "--inlines" : "--no-inlines";
+ int i = 0;
+ argv[i++] = path_to_binary;
+ argv[i++] = demangle_flag;
+ argv[i++] = inline_flag;
+ argv[i++] = kSymbolizerArch;
+ argv[i++] = nullptr;
+ CHECK_LE(i, kArgVMax);
+ }
+};
+
+LLVMSymbolizer::LLVMSymbolizer(const char *path, LowLevelAllocator *allocator)
+ : symbolizer_process_(new(*allocator) LLVMSymbolizerProcess(path)) {}
+
+// Parse a <file>:<line>[:<column>] buffer. The file path may contain colons on
+// Windows, so extract tokens from the right hand side first. The column info is
+// also optional.
+static const char *ParseFileLineInfo(AddressInfo *info, const char *str) {
+ char *file_line_info = nullptr;
+ str = ExtractToken(str, "\n", &file_line_info);
+ CHECK(file_line_info);
+
+ if (uptr size = internal_strlen(file_line_info)) {
+ char *back = file_line_info + size - 1;
+ for (int i = 0; i < 2; ++i) {
+ while (back > file_line_info && IsDigit(*back)) --back;
+ if (*back != ':' || !IsDigit(back[1])) break;
+ info->column = info->line;
+ info->line = internal_atoll(back + 1);
+ // Truncate the string at the colon to keep only filename.
+ *back = '\0';
+ --back;
+ }
+ ExtractToken(file_line_info, "", &info->file);
+ }
+
+ InternalFree(file_line_info);
+ return str;
+}
+
+// Parses one or more two-line strings in the following format:
+// <function_name>
+// <file_name>:<line_number>[:<column_number>]
+// Used by LLVMSymbolizer, Addr2LinePool and InternalSymbolizer, since all of
+// them use the same output format.
+void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res) {
+ bool top_frame = true;
+ SymbolizedStack *last = res;
+ while (true) {
+ char *function_name = nullptr;
+ str = ExtractToken(str, "\n", &function_name);
+ CHECK(function_name);
+ if (function_name[0] == '\0') {
+ // There are no more frames.
+ InternalFree(function_name);
+ break;
+ }
+ SymbolizedStack *cur;
+ if (top_frame) {
+ cur = res;
+ top_frame = false;
+ } else {
+ cur = SymbolizedStack::New(res->info.address);
+ cur->info.FillModuleInfo(res->info.module, res->info.module_offset,
+ res->info.module_arch);
+ last->next = cur;
+ last = cur;
+ }
+
+ AddressInfo *info = &cur->info;
+ info->function = function_name;
+ str = ParseFileLineInfo(info, str);
+
+ // Functions and filenames can be "??", in which case we write 0
+ // to address info to mark that names are unknown.
+ if (0 == internal_strcmp(info->function, "??")) {
+ InternalFree(info->function);
+ info->function = 0;
+ }
+ if (info->file && 0 == internal_strcmp(info->file, "??")) {
+ InternalFree(info->file);
+ info->file = 0;
+ }
+ }
+}
+
+// Parses a two- or three-line string in the following format:
+// <symbol_name>
+// <start_address> <size>
+// <filename>:<column>
+// Used by LLVMSymbolizer and InternalSymbolizer. LLVMSymbolizer added support
+// for symbolizing the third line in D123538, but we support the older two-line
+// information as well.
+void ParseSymbolizeDataOutput(const char *str, DataInfo *info) {
+ str = ExtractToken(str, "\n", &info->name);
+ str = ExtractUptr(str, " ", &info->start);
+ str = ExtractUptr(str, "\n", &info->size);
+ // Note: If the third line isn't present, these calls will set info.{file,
+ // line} to empty strings.
+ str = ExtractToken(str, ":", &info->file);
+ str = ExtractUptr(str, "\n", &info->line);
+}
+
+static void ParseSymbolizeFrameOutput(const char *str,
+ InternalMmapVector<LocalInfo> *locals) {
+ if (internal_strncmp(str, "??", 2) == 0)
+ return;
+
+ while (*str) {
+ LocalInfo local;
+ str = ExtractToken(str, "\n", &local.function_name);
+ str = ExtractToken(str, "\n", &local.name);
+
+ AddressInfo addr;
+ str = ParseFileLineInfo(&addr, str);
+ local.decl_file = addr.file;
+ local.decl_line = addr.line;
+
+ local.has_frame_offset = internal_strncmp(str, "??", 2) != 0;
+ str = ExtractSptr(str, " ", &local.frame_offset);
+
+ local.has_size = internal_strncmp(str, "??", 2) != 0;
+ str = ExtractUptr(str, " ", &local.size);
+
+ local.has_tag_offset = internal_strncmp(str, "??", 2) != 0;
+ str = ExtractUptr(str, "\n", &local.tag_offset);
+
+ locals->push_back(local);
+ }
+}
+
+bool LLVMSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
+ AddressInfo *info = &stack->info;
+ const char *buf = FormatAndSendCommand(
+ "CODE", info->module, info->module_offset, info->module_arch);
+ if (!buf)
+ return false;
+ ParseSymbolizePCOutput(buf, stack);
+ return true;
+}
+
+bool LLVMSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
+ const char *buf = FormatAndSendCommand(
+ "DATA", info->module, info->module_offset, info->module_arch);
+ if (!buf)
+ return false;
+ ParseSymbolizeDataOutput(buf, info);
+ info->start += (addr - info->module_offset); // Add the base address.
+ return true;
+}
+
+bool LLVMSymbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) {
+ const char *buf = FormatAndSendCommand(
+ "FRAME", info->module, info->module_offset, info->module_arch);
+ if (!buf)
+ return false;
+ ParseSymbolizeFrameOutput(buf, &info->locals);
+ return true;
+}
+
+const char *LLVMSymbolizer::FormatAndSendCommand(const char *command_prefix,
+ const char *module_name,
+ uptr module_offset,
+ ModuleArch arch) {
+ CHECK(module_name);
+ int size_needed = 0;
+ if (arch == kModuleArchUnknown)
+ size_needed = internal_snprintf(buffer_, kBufferSize, "%s \"%s\" 0x%zx\n",
+ command_prefix, module_name, module_offset);
+ else
+ size_needed = internal_snprintf(buffer_, kBufferSize,
+ "%s \"%s:%s\" 0x%zx\n", command_prefix,
+ module_name, ModuleArchToString(arch),
+ module_offset);
+
+ if (size_needed >= static_cast<int>(kBufferSize)) {
+ Report("WARNING: Command buffer too small");
+ return nullptr;
+ }
+
+ return symbolizer_process_->SendCommand(buffer_);
+}
+
+SymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn)
+ : path_(path),
+ input_fd_(kInvalidFd),
+ output_fd_(kInvalidFd),
+ times_restarted_(0),
+ failed_to_start_(false),
+ reported_invalid_path_(false),
+ use_posix_spawn_(use_posix_spawn) {
+ CHECK(path_);
+ CHECK_NE(path_[0], '\0');
+}
+
+static bool IsSameModule(const char* path) {
+ if (const char* ProcessName = GetProcessName()) {
+ if (const char* SymbolizerName = StripModuleName(path)) {
+ return !internal_strcmp(ProcessName, SymbolizerName);
+ }
+ }
+ return false;
+}
+
+const char *SymbolizerProcess::SendCommand(const char *command) {
+ if (failed_to_start_)
+ return nullptr;
+ if (IsSameModule(path_)) {
+ Report("WARNING: Symbolizer was blocked from starting itself!\n");
+ failed_to_start_ = true;
+ return nullptr;
+ }
+ for (; times_restarted_ < kMaxTimesRestarted; times_restarted_++) {
+ // Start or restart symbolizer if we failed to send command to it.
+ if (const char *res = SendCommandImpl(command))
+ return res;
+ Restart();
+ }
+ if (!failed_to_start_) {
+ Report("WARNING: Failed to use and restart external symbolizer!\n");
+ failed_to_start_ = true;
+ }
+ return nullptr;
+}
+
+const char *SymbolizerProcess::SendCommandImpl(const char *command) {
+ if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd)
+ return nullptr;
+ if (!WriteToSymbolizer(command, internal_strlen(command)))
+ return nullptr;
+ if (!ReadFromSymbolizer())
+ return nullptr;
+ return buffer_.data();
+}
+
+bool SymbolizerProcess::Restart() {
+ if (input_fd_ != kInvalidFd)
+ CloseFile(input_fd_);
+ if (output_fd_ != kInvalidFd)
+ CloseFile(output_fd_);
+ return StartSymbolizerSubprocess();
+}
+
+bool SymbolizerProcess::ReadFromSymbolizer() {
+ buffer_.clear();
+ constexpr uptr max_length = 1024;
+ bool ret = true;
+ do {
+ uptr just_read = 0;
+ uptr size_before = buffer_.size();
+ buffer_.resize(size_before + max_length);
+ buffer_.resize(buffer_.capacity());
+ bool ret = ReadFromFile(input_fd_, &buffer_[size_before],
+ buffer_.size() - size_before, &just_read);
+
+ if (!ret)
+ just_read = 0;
+
+ buffer_.resize(size_before + just_read);
+
+ // We can't read 0 bytes, as we don't expect external symbolizer to close
+ // its stdout.
+ if (just_read == 0) {
+ Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);
+ ret = false;
+ break;
+ }
+ } while (!ReachedEndOfOutput(buffer_.data(), buffer_.size()));
+ buffer_.push_back('\0');
+ return ret;
+}
+
+bool SymbolizerProcess::WriteToSymbolizer(const char *buffer, uptr length) {
+ if (length == 0)
+ return true;
+ uptr write_len = 0;
+ bool success = WriteToFile(output_fd_, buffer, length, &write_len);
+ if (!success || write_len != length) {
+ Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_);
+ return false;
+ }
+ return true;
+}
+
+#endif // !SANITIZER_SYMBOLIZER_MARKUP
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp
new file mode 100644
index 00000000000..f4f2a036a1e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp
@@ -0,0 +1,205 @@
+//===-- sanitizer_symbolizer_mac.cpp --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between various sanitizers' runtime libraries.
+//
+// Implementation of Mac-specific "atos" symbolizer.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_APPLE
+
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_mac.h"
+#include "sanitizer_symbolizer_mac.h"
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <util.h>
+
+namespace __sanitizer {
+
+bool DlAddrSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
+ Dl_info info;
+ int result = dladdr((const void *)addr, &info);
+ if (!result) return false;
+
+ // Compute offset if possible. `dladdr()` doesn't always ensure that `addr >=
+ // sym_addr` so only compute the offset when this holds. Failure to find the
+ // function offset is not treated as a failure because it might still be
+ // possible to get the symbol name.
+ uptr sym_addr = reinterpret_cast<uptr>(info.dli_saddr);
+ if (addr >= sym_addr) {
+ stack->info.function_offset = addr - sym_addr;
+ }
+
+ const char *demangled = DemangleSwiftAndCXX(info.dli_sname);
+ if (!demangled) return false;
+ stack->info.function = internal_strdup(demangled);
+ return true;
+}
+
+bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) {
+ Dl_info info;
+ int result = dladdr((const void *)addr, &info);
+ if (!result) return false;
+ const char *demangled = DemangleSwiftAndCXX(info.dli_sname);
+ datainfo->name = internal_strdup(demangled);
+ datainfo->start = (uptr)info.dli_saddr;
+ return true;
+}
+
+class AtosSymbolizerProcess final : public SymbolizerProcess {
+ public:
+ explicit AtosSymbolizerProcess(const char *path)
+ : SymbolizerProcess(path, /*use_posix_spawn*/ true) {
+ pid_str_[0] = '\0';
+ }
+
+ private:
+ bool StartSymbolizerSubprocess() override {
+ // Put the string command line argument in the object so that it outlives
+ // the call to GetArgV.
+ internal_snprintf(pid_str_, sizeof(pid_str_), "%d", (int)internal_getpid());
+
+ // Configure sandbox before starting atos process.
+ return SymbolizerProcess::StartSymbolizerSubprocess();
+ }
+
+ bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
+ return (length >= 1 && buffer[length - 1] == '\n');
+ }
+
+ void GetArgV(const char *path_to_binary,
+ const char *(&argv)[kArgVMax]) const override {
+ int i = 0;
+ argv[i++] = path_to_binary;
+ argv[i++] = "-p";
+ argv[i++] = &pid_str_[0];
+ if (GetMacosAlignedVersion() == MacosVersion(10, 9)) {
+ // On Mavericks atos prints a deprecation warning which we suppress by
+ // passing -d. The warning isn't present on other OSX versions, even the
+ // newer ones.
+ argv[i++] = "-d";
+ }
+ argv[i++] = nullptr;
+ CHECK_LE(i, kArgVMax);
+ }
+
+ char pid_str_[16];
+};
+
+#undef K_ATOS_ENV_VAR
+
+static bool ParseCommandOutput(const char *str, uptr addr, char **out_name,
+ char **out_module, char **out_file, uptr *line,
+ uptr *start_address) {
+ // Trim ending newlines.
+ char *trim;
+ ExtractTokenUpToDelimiter(str, "\n", &trim);
+
+ // The line from `atos` is in one of these formats:
+ // myfunction (in library.dylib) (sourcefile.c:17)
+ // myfunction (in library.dylib) + 0x1fe
+ // myfunction (in library.dylib) + 15
+ // 0xdeadbeef (in library.dylib) + 0x1fe
+ // 0xdeadbeef (in library.dylib) + 15
+ // 0xdeadbeef (in library.dylib)
+ // 0xdeadbeef
+
+ const char *rest = trim;
+ char *symbol_name;
+ rest = ExtractTokenUpToDelimiter(rest, " (in ", &symbol_name);
+ if (rest[0] == '\0') {
+ InternalFree(symbol_name);
+ InternalFree(trim);
+ return false;
+ }
+
+ if (internal_strncmp(symbol_name, "0x", 2) != 0)
+ *out_name = symbol_name;
+ else
+ InternalFree(symbol_name);
+ rest = ExtractTokenUpToDelimiter(rest, ") ", out_module);
+
+ if (rest[0] == '(') {
+ if (out_file) {
+ rest++;
+ rest = ExtractTokenUpToDelimiter(rest, ":", out_file);
+ char *extracted_line_number;
+ rest = ExtractTokenUpToDelimiter(rest, ")", &extracted_line_number);
+ if (line) *line = (uptr)internal_atoll(extracted_line_number);
+ InternalFree(extracted_line_number);
+ }
+ } else if (rest[0] == '+') {
+ rest += 2;
+ uptr offset = internal_atoll(rest);
+ if (start_address) *start_address = addr - offset;
+ }
+
+ InternalFree(trim);
+ return true;
+}
+
+AtosSymbolizer::AtosSymbolizer(const char *path, LowLevelAllocator *allocator)
+ : process_(new (*allocator) AtosSymbolizerProcess(path)) {}
+
+bool AtosSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
+ if (!process_) return false;
+ if (addr == 0) return false;
+ char command[32];
+ internal_snprintf(command, sizeof(command), "0x%zx\n", addr);
+ const char *buf = process_->SendCommand(command);
+ if (!buf) return false;
+ uptr line;
+ uptr start_address = AddressInfo::kUnknown;
+ if (!ParseCommandOutput(buf, addr, &stack->info.function, &stack->info.module,
+ &stack->info.file, &line, &start_address)) {
+ process_ = nullptr;
+ return false;
+ }
+ stack->info.line = (int)line;
+
+ if (start_address == AddressInfo::kUnknown) {
+ // Fallback to dladdr() to get function start address if atos doesn't report
+ // it.
+ Dl_info info;
+ int result = dladdr((const void *)addr, &info);
+ if (result)
+ start_address = reinterpret_cast<uptr>(info.dli_saddr);
+ }
+
+ // Only assign to `function_offset` if we were able to get the function's
+ // start address and we got a sensible `start_address` (dladdr doesn't always
+ // ensure that `addr >= sym_addr`).
+ if (start_address != AddressInfo::kUnknown && addr >= start_address) {
+ stack->info.function_offset = addr - start_address;
+ }
+ return true;
+}
+
+bool AtosSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
+ if (!process_) return false;
+ char command[32];
+ internal_snprintf(command, sizeof(command), "0x%zx\n", addr);
+ const char *buf = process_->SendCommand(command);
+ if (!buf) return false;
+ if (!ParseCommandOutput(buf, addr, &info->name, &info->module, nullptr,
+ nullptr, &info->start)) {
+ process_ = nullptr;
+ return false;
+ }
+ return true;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.h
new file mode 100644
index 00000000000..cea24418290
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.h
@@ -0,0 +1,47 @@
+//===-- sanitizer_symbolizer_mac.h ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between various sanitizers' runtime libraries.
+//
+// Header for Mac-specific "atos" symbolizer.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_SYMBOLIZER_MAC_H
+#define SANITIZER_SYMBOLIZER_MAC_H
+
+#include "sanitizer_platform.h"
+#if SANITIZER_APPLE
+
+#include "sanitizer_symbolizer_internal.h"
+
+namespace __sanitizer {
+
+class DlAddrSymbolizer final : public SymbolizerTool {
+ public:
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
+ bool SymbolizeData(uptr addr, DataInfo *info) override;
+};
+
+class AtosSymbolizerProcess;
+
+class AtosSymbolizer final : public SymbolizerTool {
+ public:
+ explicit AtosSymbolizer(const char *path, LowLevelAllocator *allocator);
+
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
+ bool SymbolizeData(uptr addr, DataInfo *info) override;
+
+ private:
+ AtosSymbolizerProcess *process_;
+};
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_APPLE
+
+#endif // SANITIZER_SYMBOLIZER_MAC_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_markup.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_markup.cpp
new file mode 100644
index 00000000000..1ec0c5cad7a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_markup.cpp
@@ -0,0 +1,150 @@
+//===-- sanitizer_symbolizer_markup.cpp -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between various sanitizers' runtime libraries.
+//
+// Implementation of offline markup symbolizer.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_SYMBOLIZER_MARKUP
+
+#if SANITIZER_FUCHSIA
+#include "sanitizer_symbolizer_fuchsia.h"
+# endif
+
+# include <limits.h>
+# include <unwind.h>
+
+# include "sanitizer_stacktrace.h"
+# include "sanitizer_symbolizer.h"
+
+namespace __sanitizer {
+
+// This generic support for offline symbolizing is based on the
+// Fuchsia port. We don't do any actual symbolization per se.
+// Instead, we emit text containing raw addresses and raw linkage
+// symbol names, embedded in Fuchsia's symbolization markup format.
+// Fuchsia's logging infrastructure emits enough information about
+// process memory layout that a post-processing filter can do the
+// symbolization and pretty-print the markup. See the spec at:
+// https://fuchsia.googlesource.com/zircon/+/master/docs/symbolizer_markup.md
+
+// This is used by UBSan for type names, and by ASan for global variable names.
+// It's expected to return a static buffer that will be reused on each call.
+const char *Symbolizer::Demangle(const char *name) {
+ static char buffer[kFormatDemangleMax];
+ internal_snprintf(buffer, sizeof(buffer), kFormatDemangle, name);
+ return buffer;
+}
+
+// This is used mostly for suppression matching. Making it work
+// would enable "interceptor_via_lib" suppressions. It's also used
+// once in UBSan to say "in module ..." in a message that also
+// includes an address in the module, so post-processing can already
+// pretty-print that so as to indicate the module.
+bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
+ uptr *module_address) {
+ return false;
+}
+
+// This is mainly used by hwasan for online symbolization. This isn't needed
+// since hwasan can always just dump stack frames for offline symbolization.
+bool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) { return false; }
+
+// This is used in some places for suppression checking, which we
+// don't really support for Fuchsia. It's also used in UBSan to
+// identify a PC location to a function name, so we always fill in
+// the function member with a string containing markup around the PC
+// value.
+// TODO(mcgrathr): Under SANITIZER_GO, it's currently used by TSan
+// to render stack frames, but that should be changed to use
+// RenderStackFrame.
+SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
+ SymbolizedStack *s = SymbolizedStack::New(addr);
+ char buffer[kFormatFunctionMax];
+ internal_snprintf(buffer, sizeof(buffer), kFormatFunction, addr);
+ s->info.function = internal_strdup(buffer);
+ return s;
+}
+
+// Always claim we succeeded, so that RenderDataInfo will be called.
+bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
+ info->Clear();
+ info->start = addr;
+ return true;
+}
+
+// We ignore the format argument to __sanitizer_symbolize_global.
+void RenderData(InternalScopedString *buffer, const char *format,
+ const DataInfo *DI, const char *strip_path_prefix) {
+ buffer->append(kFormatData, DI->start);
+}
+
+bool RenderNeedsSymbolization(const char *format) { return false; }
+
+// We don't support the stack_trace_format flag at all.
+void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
+ uptr address, const AddressInfo *info, bool vs_style,
+ const char *strip_path_prefix, const char *strip_func_prefix) {
+ CHECK(!RenderNeedsSymbolization(format));
+ buffer->append(kFormatFrame, frame_no, address);
+}
+
+Symbolizer *Symbolizer::PlatformInit() {
+ return new (symbolizer_allocator_) Symbolizer({});
+}
+
+void Symbolizer::LateInitialize() { Symbolizer::GetOrInit(); }
+
+void StartReportDeadlySignal() {}
+void ReportDeadlySignal(const SignalContext &sig, u32 tid,
+ UnwindSignalStackCallbackType unwind,
+ const void *unwind_context) {}
+
+#if SANITIZER_CAN_SLOW_UNWIND
+struct UnwindTraceArg {
+ BufferedStackTrace *stack;
+ u32 max_depth;
+};
+
+_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
+ UnwindTraceArg *arg = static_cast<UnwindTraceArg *>(param);
+ CHECK_LT(arg->stack->size, arg->max_depth);
+ uptr pc = _Unwind_GetIP(ctx);
+ if (pc < PAGE_SIZE) return _URC_NORMAL_STOP;
+ arg->stack->trace_buffer[arg->stack->size++] = pc;
+ return (arg->stack->size == arg->max_depth ? _URC_NORMAL_STOP
+ : _URC_NO_REASON);
+}
+
+void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
+ CHECK_GE(max_depth, 2);
+ size = 0;
+ UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)};
+ _Unwind_Backtrace(Unwind_Trace, &arg);
+ CHECK_GT(size, 0);
+ // We need to pop a few frames so that pc is on top.
+ uptr to_pop = LocatePcInTrace(pc);
+ // trace_buffer[0] belongs to the current function so we always pop it,
+ // unless there is only 1 frame in the stack trace (1 frame is always better
+ // than 0!).
+ PopStackFrames(Min(to_pop, static_cast<uptr>(1)));
+ trace_buffer[0] = pc;
+}
+
+void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
+ CHECK(context);
+ CHECK_GE(max_depth, 2);
+ UNREACHABLE("signal context doesn't exist");
+}
+#endif // SANITIZER_CAN_SLOW_UNWIND
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SYMBOLIZER_MARKUP
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
new file mode 100644
index 00000000000..b223f6cd01e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
@@ -0,0 +1,510 @@
+//===-- sanitizer_symbolizer_posix_libcdep.cpp ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+// POSIX-specific implementation of symbolizer parts.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_POSIX
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_common.h"
+#include "sanitizer_file.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_posix.h"
+#include "sanitizer_procmaps.h"
+#include "sanitizer_symbolizer_internal.h"
+#include "sanitizer_symbolizer_libbacktrace.h"
+#include "sanitizer_symbolizer_mac.h"
+
+#include <dlfcn.h> // for dlsym()
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+// C++ demangling function, as required by Itanium C++ ABI. This is weak,
+// because we do not require a C++ ABI library to be linked to a program
+// using sanitizers; if it's not present, we'll just use the mangled name.
+namespace __cxxabiv1 {
+ extern "C" SANITIZER_WEAK_ATTRIBUTE
+ char *__cxa_demangle(const char *mangled, char *buffer,
+ size_t *length, int *status);
+}
+
+namespace __sanitizer {
+
+// Attempts to demangle the name via __cxa_demangle from __cxxabiv1.
+const char *DemangleCXXABI(const char *name) {
+ // FIXME: __cxa_demangle aggressively insists on allocating memory.
+ // There's not much we can do about that, short of providing our
+ // own demangler (libc++abi's implementation could be adapted so that
+ // it does not allocate). For now, we just call it anyway, and we leak
+ // the returned value.
+ if (&__cxxabiv1::__cxa_demangle)
+ if (const char *demangled_name =
+ __cxxabiv1::__cxa_demangle(name, 0, 0, 0))
+ return demangled_name;
+
+ return name;
+}
+
+// As of now, there are no headers for the Swift runtime. Once they are
+// present, we will weakly link since we do not require Swift runtime to be
+// linked.
+typedef char *(*swift_demangle_ft)(const char *mangledName,
+ size_t mangledNameLength, char *outputBuffer,
+ size_t *outputBufferSize, uint32_t flags);
+static swift_demangle_ft swift_demangle_f;
+
+// This must not happen lazily at symbolication time, because dlsym uses
+// malloc and thread-local storage, which is not a good thing to do during
+// symbolication.
+static void InitializeSwiftDemangler() {
+ swift_demangle_f = (swift_demangle_ft)dlsym(RTLD_DEFAULT, "swift_demangle");
+}
+
+// Attempts to demangle a Swift name. The demangler will return nullptr if a
+// non-Swift name is passed in.
+const char *DemangleSwift(const char *name) {
+ if (swift_demangle_f)
+ return swift_demangle_f(name, internal_strlen(name), 0, 0, 0);
+
+ return nullptr;
+}
+
+const char *DemangleSwiftAndCXX(const char *name) {
+ if (!name) return nullptr;
+ if (const char *swift_demangled_name = DemangleSwift(name))
+ return swift_demangled_name;
+ return DemangleCXXABI(name);
+}
+
+static bool CreateTwoHighNumberedPipes(int *infd_, int *outfd_) {
+ int *infd = NULL;
+ int *outfd = NULL;
+ // The client program may close its stdin and/or stdout and/or stderr
+ // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
+ // In this case the communication between the forked processes may be
+ // broken if either the parent or the child tries to close or duplicate
+ // these descriptors. The loop below produces two pairs of file
+ // descriptors, each greater than 2 (stderr).
+ int sock_pair[5][2];
+ for (int i = 0; i < 5; i++) {
+ if (pipe(sock_pair[i]) == -1) {
+ for (int j = 0; j < i; j++) {
+ internal_close(sock_pair[j][0]);
+ internal_close(sock_pair[j][1]);
+ }
+ return false;
+ } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {
+ if (infd == NULL) {
+ infd = sock_pair[i];
+ } else {
+ outfd = sock_pair[i];
+ for (int j = 0; j < i; j++) {
+ if (sock_pair[j] == infd) continue;
+ internal_close(sock_pair[j][0]);
+ internal_close(sock_pair[j][1]);
+ }
+ break;
+ }
+ }
+ }
+ CHECK(infd);
+ CHECK(outfd);
+ infd_[0] = infd[0];
+ infd_[1] = infd[1];
+ outfd_[0] = outfd[0];
+ outfd_[1] = outfd[1];
+ return true;
+}
+
+bool SymbolizerProcess::StartSymbolizerSubprocess() {
+ if (!FileExists(path_)) {
+ if (!reported_invalid_path_) {
+ Report("WARNING: invalid path to external symbolizer!\n");
+ reported_invalid_path_ = true;
+ }
+ return false;
+ }
+
+ const char *argv[kArgVMax];
+ GetArgV(path_, argv);
+ pid_t pid;
+
+ // Report how symbolizer is being launched for debugging purposes.
+ if (Verbosity() >= 3) {
+ // Only use `Report` for first line so subsequent prints don't get prefixed
+ // with current PID.
+ Report("Launching Symbolizer process: ");
+ for (unsigned index = 0; index < kArgVMax && argv[index]; ++index)
+ Printf("%s ", argv[index]);
+ Printf("\n");
+ }
+
+ if (use_posix_spawn_) {
+#if SANITIZER_APPLE
+ fd_t fd = internal_spawn(argv, const_cast<const char **>(GetEnvP()), &pid);
+ if (fd == kInvalidFd) {
+ Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
+ errno);
+ return false;
+ }
+
+ input_fd_ = fd;
+ output_fd_ = fd;
+#else // SANITIZER_APPLE
+ UNIMPLEMENTED();
+#endif // SANITIZER_APPLE
+ } else {
+ fd_t infd[2] = {}, outfd[2] = {};
+ if (!CreateTwoHighNumberedPipes(infd, outfd)) {
+ Report("WARNING: Can't create a socket pair to start "
+ "external symbolizer (errno: %d)\n", errno);
+ return false;
+ }
+
+ pid = StartSubprocess(path_, argv, GetEnvP(), /* stdin */ outfd[0],
+ /* stdout */ infd[1]);
+ if (pid < 0) {
+ internal_close(infd[0]);
+ internal_close(outfd[1]);
+ return false;
+ }
+
+ input_fd_ = infd[0];
+ output_fd_ = outfd[1];
+ }
+
+ CHECK_GT(pid, 0);
+
+ // Check that symbolizer subprocess started successfully.
+ SleepForMillis(kSymbolizerStartupTimeMillis);
+ if (!IsProcessRunning(pid)) {
+ // Either waitpid failed, or child has already exited.
+ Report("WARNING: external symbolizer didn't start up correctly!\n");
+ return false;
+ }
+
+ return true;
+}
+
+class Addr2LineProcess final : public SymbolizerProcess {
+ public:
+ Addr2LineProcess(const char *path, const char *module_name)
+ : SymbolizerProcess(path), module_name_(internal_strdup(module_name)) {}
+
+ const char *module_name() const { return module_name_; }
+
+ private:
+ void GetArgV(const char *path_to_binary,
+ const char *(&argv)[kArgVMax]) const override {
+ int i = 0;
+ argv[i++] = path_to_binary;
+ if (common_flags()->demangle)
+ argv[i++] = "-C";
+ if (common_flags()->symbolize_inline_frames)
+ argv[i++] = "-i";
+ argv[i++] = "-fe";
+ argv[i++] = module_name_;
+ argv[i++] = nullptr;
+ CHECK_LE(i, kArgVMax);
+ }
+
+ bool ReachedEndOfOutput(const char *buffer, uptr length) const override;
+
+ bool ReadFromSymbolizer() override {
+ if (!SymbolizerProcess::ReadFromSymbolizer())
+ return false;
+ auto &buff = GetBuff();
+ // We should cut out output_terminator_ at the end of given buffer,
+ // appended by addr2line to mark the end of its meaningful output.
+ // We cannot scan buffer from it's beginning, because it is legal for it
+ // to start with output_terminator_ in case given offset is invalid. So,
+ // scanning from second character.
+ char *garbage = internal_strstr(buff.data() + 1, output_terminator_);
+ // This should never be NULL since buffer must end up with
+ // output_terminator_.
+ CHECK(garbage);
+
+ // Trim the buffer.
+ uintptr_t new_size = garbage - buff.data();
+ GetBuff().resize(new_size);
+ GetBuff().push_back('\0');
+ return true;
+ }
+
+ const char *module_name_; // Owned, leaked.
+ static const char output_terminator_[];
+};
+
+const char Addr2LineProcess::output_terminator_[] = "??\n??:0\n";
+
+bool Addr2LineProcess::ReachedEndOfOutput(const char *buffer,
+ uptr length) const {
+ const size_t kTerminatorLen = sizeof(output_terminator_) - 1;
+ // Skip, if we read just kTerminatorLen bytes, because Addr2Line output
+ // should consist at least of two pairs of lines:
+ // 1. First one, corresponding to given offset to be symbolized
+ // (may be equal to output_terminator_, if offset is not valid).
+ // 2. Second one for output_terminator_, itself to mark the end of output.
+ if (length <= kTerminatorLen) return false;
+ // Addr2Line output should end up with output_terminator_.
+ return !internal_memcmp(buffer + length - kTerminatorLen,
+ output_terminator_, kTerminatorLen);
+}
+
+class Addr2LinePool final : public SymbolizerTool {
+ public:
+ explicit Addr2LinePool(const char *addr2line_path,
+ LowLevelAllocator *allocator)
+ : addr2line_path_(addr2line_path), allocator_(allocator) {
+ addr2line_pool_.reserve(16);
+ }
+
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
+ if (const char *buf =
+ SendCommand(stack->info.module, stack->info.module_offset)) {
+ ParseSymbolizePCOutput(buf, stack);
+ return true;
+ }
+ return false;
+ }
+
+ bool SymbolizeData(uptr addr, DataInfo *info) override {
+ return false;
+ }
+
+ private:
+ const char *SendCommand(const char *module_name, uptr module_offset) {
+ Addr2LineProcess *addr2line = 0;
+ for (uptr i = 0; i < addr2line_pool_.size(); ++i) {
+ if (0 ==
+ internal_strcmp(module_name, addr2line_pool_[i]->module_name())) {
+ addr2line = addr2line_pool_[i];
+ break;
+ }
+ }
+ if (!addr2line) {
+ addr2line =
+ new(*allocator_) Addr2LineProcess(addr2line_path_, module_name);
+ addr2line_pool_.push_back(addr2line);
+ }
+ CHECK_EQ(0, internal_strcmp(module_name, addr2line->module_name()));
+ char buffer[kBufferSize];
+ internal_snprintf(buffer, kBufferSize, "0x%zx\n0x%zx\n",
+ module_offset, dummy_address_);
+ return addr2line->SendCommand(buffer);
+ }
+
+ static const uptr kBufferSize = 64;
+ const char *addr2line_path_;
+ LowLevelAllocator *allocator_;
+ InternalMmapVector<Addr2LineProcess*> addr2line_pool_;
+ static const uptr dummy_address_ =
+ FIRST_32_SECOND_64(UINT32_MAX, UINT64_MAX);
+};
+
+# if SANITIZER_SUPPORTS_WEAK_HOOKS
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
+__sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset,
+ char *Buffer, int MaxLength);
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
+__sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
+ char *Buffer, int MaxLength);
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
+__sanitizer_symbolize_flush();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE int
+__sanitizer_symbolize_demangle(const char *Name, char *Buffer, int MaxLength);
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
+__sanitizer_symbolize_set_demangle(bool Demangle);
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
+__sanitizer_symbolize_set_inline_frames(bool InlineFrames);
+} // extern "C"
+
+class InternalSymbolizer final : public SymbolizerTool {
+ public:
+ static InternalSymbolizer *get(LowLevelAllocator *alloc) {
+ if (__sanitizer_symbolize_set_demangle)
+ CHECK(__sanitizer_symbolize_set_demangle(common_flags()->demangle));
+ if (__sanitizer_symbolize_set_inline_frames)
+ CHECK(__sanitizer_symbolize_set_inline_frames(
+ common_flags()->symbolize_inline_frames));
+ if (__sanitizer_symbolize_code && __sanitizer_symbolize_data)
+ return new (*alloc) InternalSymbolizer();
+ return 0;
+ }
+
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override {
+ bool result = __sanitizer_symbolize_code(
+ stack->info.module, stack->info.module_offset, buffer_, kBufferSize);
+ if (result)
+ ParseSymbolizePCOutput(buffer_, stack);
+ return result;
+ }
+
+ bool SymbolizeData(uptr addr, DataInfo *info) override {
+ bool result = __sanitizer_symbolize_data(info->module, info->module_offset,
+ buffer_, kBufferSize);
+ if (result) {
+ ParseSymbolizeDataOutput(buffer_, info);
+ info->start += (addr - info->module_offset); // Add the base address.
+ }
+ return result;
+ }
+
+ void Flush() override {
+ if (__sanitizer_symbolize_flush)
+ __sanitizer_symbolize_flush();
+ }
+
+ const char *Demangle(const char *name) override {
+ if (__sanitizer_symbolize_demangle) {
+ for (uptr res_length = 1024;
+ res_length <= InternalSizeClassMap::kMaxSize;) {
+ char *res_buff = static_cast<char *>(InternalAlloc(res_length));
+ uptr req_length =
+ __sanitizer_symbolize_demangle(name, res_buff, res_length);
+ if (req_length > res_length) {
+ res_length = req_length + 1;
+ InternalFree(res_buff);
+ continue;
+ }
+ return res_buff;
+ }
+ }
+ return name;
+ }
+
+ private:
+ InternalSymbolizer() {}
+
+ static const int kBufferSize = 16 * 1024;
+ char buffer_[kBufferSize];
+};
+# else // SANITIZER_SUPPORTS_WEAK_HOOKS
+
+class InternalSymbolizer final : public SymbolizerTool {
+ public:
+ static InternalSymbolizer *get(LowLevelAllocator *alloc) { return 0; }
+};
+
+# endif // SANITIZER_SUPPORTS_WEAK_HOOKS
+
+const char *Symbolizer::PlatformDemangle(const char *name) {
+ return DemangleSwiftAndCXX(name);
+}
+
+static SymbolizerTool *ChooseExternalSymbolizer(LowLevelAllocator *allocator) {
+ const char *path = common_flags()->external_symbolizer_path;
+
+ if (path && internal_strchr(path, '%')) {
+ char *new_path = (char *)InternalAlloc(kMaxPathLength);
+ SubstituteForFlagValue(path, new_path, kMaxPathLength);
+ path = new_path;
+ }
+
+ const char *binary_name = path ? StripModuleName(path) : "";
+ static const char kLLVMSymbolizerPrefix[] = "llvm-symbolizer";
+ if (path && path[0] == '\0') {
+ VReport(2, "External symbolizer is explicitly disabled.\n");
+ return nullptr;
+ } else if (!internal_strncmp(binary_name, kLLVMSymbolizerPrefix,
+ internal_strlen(kLLVMSymbolizerPrefix))) {
+ VReport(2, "Using llvm-symbolizer at user-specified path: %s\n", path);
+ return new(*allocator) LLVMSymbolizer(path, allocator);
+ } else if (!internal_strcmp(binary_name, "atos")) {
+#if SANITIZER_APPLE
+ VReport(2, "Using atos at user-specified path: %s\n", path);
+ return new(*allocator) AtosSymbolizer(path, allocator);
+#else // SANITIZER_APPLE
+ Report("ERROR: Using `atos` is only supported on Darwin.\n");
+ Die();
+#endif // SANITIZER_APPLE
+ } else if (!internal_strcmp(binary_name, "addr2line")) {
+ VReport(2, "Using addr2line at user-specified path: %s\n", path);
+ return new(*allocator) Addr2LinePool(path, allocator);
+ } else if (path) {
+ Report("ERROR: External symbolizer path is set to '%s' which isn't "
+ "a known symbolizer. Please set the path to the llvm-symbolizer "
+ "binary or other known tool.\n", path);
+ Die();
+ }
+
+ // Otherwise symbolizer program is unknown, let's search $PATH
+ CHECK(path == nullptr);
+#if SANITIZER_APPLE
+ if (const char *found_path = FindPathToBinary("atos")) {
+ VReport(2, "Using atos found at: %s\n", found_path);
+ return new(*allocator) AtosSymbolizer(found_path, allocator);
+ }
+#endif // SANITIZER_APPLE
+ if (const char *found_path = FindPathToBinary("llvm-symbolizer")) {
+ VReport(2, "Using llvm-symbolizer found at: %s\n", found_path);
+ return new(*allocator) LLVMSymbolizer(found_path, allocator);
+ }
+ if (common_flags()->allow_addr2line) {
+ if (const char *found_path = FindPathToBinary("addr2line")) {
+ VReport(2, "Using addr2line found at: %s\n", found_path);
+ return new(*allocator) Addr2LinePool(found_path, allocator);
+ }
+ }
+ return nullptr;
+}
+
+static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
+ LowLevelAllocator *allocator) {
+ if (!common_flags()->symbolize) {
+ VReport(2, "Symbolizer is disabled.\n");
+ return;
+ }
+ if (IsAllocatorOutOfMemory()) {
+ VReport(2, "Cannot use internal symbolizer: out of memory\n");
+ } else if (SymbolizerTool *tool = InternalSymbolizer::get(allocator)) {
+ VReport(2, "Using internal symbolizer.\n");
+ list->push_back(tool);
+ return;
+ }
+ if (SymbolizerTool *tool = LibbacktraceSymbolizer::get(allocator)) {
+ VReport(2, "Using libbacktrace symbolizer.\n");
+ list->push_back(tool);
+ return;
+ }
+
+ if (SymbolizerTool *tool = ChooseExternalSymbolizer(allocator)) {
+ list->push_back(tool);
+ }
+
+#if SANITIZER_APPLE
+ VReport(2, "Using dladdr symbolizer.\n");
+ list->push_back(new(*allocator) DlAddrSymbolizer());
+#endif // SANITIZER_APPLE
+}
+
+Symbolizer *Symbolizer::PlatformInit() {
+ IntrusiveList<SymbolizerTool> list;
+ list.clear();
+ ChooseSymbolizerTools(&list, &symbolizer_allocator_);
+ return new(symbolizer_allocator_) Symbolizer(list);
+}
+
+void Symbolizer::LateInitialize() {
+ Symbolizer::GetOrInit();
+ InitializeSwiftDemangler();
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_POSIX
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp
new file mode 100644
index 00000000000..d5c028e3640
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp
@@ -0,0 +1,298 @@
+//===-- sanitizer_symbolizer_report.cpp -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// This file is shared between AddressSanitizer and other sanitizer run-time
+/// libraries and implements symbolized reports related functions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common.h"
+#include "sanitizer_file.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_procmaps.h"
+#include "sanitizer_report_decorator.h"
+#include "sanitizer_stacktrace.h"
+#include "sanitizer_stacktrace_printer.h"
+#include "sanitizer_symbolizer.h"
+
+#if SANITIZER_POSIX
+# include "sanitizer_posix.h"
+# include <sys/mman.h>
+#endif
+
+namespace __sanitizer {
+
+#if !SANITIZER_GO
+void ReportErrorSummary(const char *error_type, const AddressInfo &info,
+ const char *alt_tool_name) {
+ if (!common_flags()->print_summary) return;
+ InternalScopedString buff;
+ buff.append("%s ", error_type);
+ RenderFrame(&buff, "%L %F", 0, info.address, &info,
+ common_flags()->symbolize_vs_style,
+ common_flags()->strip_path_prefix);
+ ReportErrorSummary(buff.data(), alt_tool_name);
+}
+#endif
+
+#if !SANITIZER_FUCHSIA
+
+bool ReportFile::SupportsColors() {
+ SpinMutexLock l(mu);
+ ReopenIfNecessary();
+ return SupportsColoredOutput(fd);
+}
+
+static inline bool ReportSupportsColors() {
+ return report_file.SupportsColors();
+}
+
+#else // SANITIZER_FUCHSIA
+
+// Fuchsia's logs always go through post-processing that handles colorization.
+static inline bool ReportSupportsColors() { return true; }
+
+#endif // !SANITIZER_FUCHSIA
+
+bool ColorizeReports() {
+ // FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color
+ // printing on Windows.
+ if (SANITIZER_WINDOWS)
+ return false;
+
+ const char *flag = common_flags()->color;
+ return internal_strcmp(flag, "always") == 0 ||
+ (internal_strcmp(flag, "auto") == 0 && ReportSupportsColors());
+}
+
+void ReportErrorSummary(const char *error_type, const StackTrace *stack,
+ const char *alt_tool_name) {
+#if !SANITIZER_GO
+ if (!common_flags()->print_summary)
+ return;
+ if (stack->size == 0) {
+ ReportErrorSummary(error_type);
+ return;
+ }
+ // Currently, we include the first stack frame into the report summary.
+ // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
+ uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
+ SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
+ ReportErrorSummary(error_type, frame->info, alt_tool_name);
+ frame->ClearAll();
+#endif
+}
+
+void ReportMmapWriteExec(int prot, int flags) {
+#if SANITIZER_POSIX && (!SANITIZER_GO && !SANITIZER_ANDROID)
+ int pflags = (PROT_WRITE | PROT_EXEC);
+ if ((prot & pflags) != pflags)
+ return;
+
+# if SANITIZER_APPLE && defined(MAP_JIT)
+ if ((flags & MAP_JIT) == MAP_JIT)
+ return;
+# endif
+
+ ScopedErrorReportLock l;
+ SanitizerCommonDecorator d;
+
+ InternalMmapVector<BufferedStackTrace> stack_buffer(1);
+ BufferedStackTrace *stack = stack_buffer.data();
+ stack->Reset();
+ uptr top = 0;
+ uptr bottom = 0;
+ GET_CALLER_PC_BP_SP;
+ (void)sp;
+ bool fast = common_flags()->fast_unwind_on_fatal;
+ if (StackTrace::WillUseFastUnwind(fast)) {
+ GetThreadStackTopAndBottom(false, &top, &bottom);
+ stack->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, true);
+ } else {
+ stack->Unwind(kStackTraceMax, pc, 0, nullptr, 0, 0, false);
+ }
+
+ Printf("%s", d.Warning());
+ Report("WARNING: %s: writable-executable page usage\n", SanitizerToolName);
+ Printf("%s", d.Default());
+
+ stack->Print();
+ ReportErrorSummary("w-and-x-usage", stack);
+#endif
+}
+
+#if !SANITIZER_FUCHSIA && !SANITIZER_GO
+void StartReportDeadlySignal() {
+ // Write the first message using fd=2, just in case.
+ // It may actually fail to write in case stderr is closed.
+ CatastrophicErrorWrite(SanitizerToolName, internal_strlen(SanitizerToolName));
+ static const char kDeadlySignal[] = ":DEADLYSIGNAL\n";
+ CatastrophicErrorWrite(kDeadlySignal, sizeof(kDeadlySignal) - 1);
+}
+
+static void MaybeReportNonExecRegion(uptr pc) {
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
+ MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
+ MemoryMappedSegment segment;
+ while (proc_maps.Next(&segment)) {
+ if (pc >= segment.start && pc < segment.end && !segment.IsExecutable())
+ Report("Hint: PC is at a non-executable region. Maybe a wild jump?\n");
+ }
+#endif
+}
+
+static void PrintMemoryByte(InternalScopedString *str, const char *before,
+ u8 byte) {
+ SanitizerCommonDecorator d;
+ str->append("%s%s%x%x%s ", before, d.MemoryByte(), byte >> 4, byte & 15,
+ d.Default());
+}
+
+static void MaybeDumpInstructionBytes(uptr pc) {
+ if (!common_flags()->dump_instruction_bytes || (pc < GetPageSizeCached()))
+ return;
+ InternalScopedString str;
+ str.append("First 16 instruction bytes at pc: ");
+ if (IsAccessibleMemoryRange(pc, 16)) {
+ for (int i = 0; i < 16; ++i) {
+ PrintMemoryByte(&str, "", ((u8 *)pc)[i]);
+ }
+ str.append("\n");
+ } else {
+ str.append("unaccessible\n");
+ }
+ Report("%s", str.data());
+}
+
+static void MaybeDumpRegisters(void *context) {
+ if (!common_flags()->dump_registers) return;
+ SignalContext::DumpAllRegisters(context);
+}
+
+static void ReportStackOverflowImpl(const SignalContext &sig, u32 tid,
+ UnwindSignalStackCallbackType unwind,
+ const void *unwind_context) {
+ SanitizerCommonDecorator d;
+ Printf("%s", d.Warning());
+ static const char kDescription[] = "stack-overflow";
+ Report("ERROR: %s: %s on address %p (pc %p bp %p sp %p T%d)\n",
+ SanitizerToolName, kDescription, (void *)sig.addr, (void *)sig.pc,
+ (void *)sig.bp, (void *)sig.sp, tid);
+ Printf("%s", d.Default());
+ InternalMmapVector<BufferedStackTrace> stack_buffer(1);
+ BufferedStackTrace *stack = stack_buffer.data();
+ stack->Reset();
+ unwind(sig, unwind_context, stack);
+ stack->Print();
+ ReportErrorSummary(kDescription, stack);
+}
+
+static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
+ UnwindSignalStackCallbackType unwind,
+ const void *unwind_context) {
+ SanitizerCommonDecorator d;
+ Printf("%s", d.Warning());
+ const char *description = sig.Describe();
+ if (sig.is_memory_access && !sig.is_true_faulting_addr)
+ Report("ERROR: %s: %s on unknown address (pc %p bp %p sp %p T%d)\n",
+ SanitizerToolName, description, (void *)sig.pc, (void *)sig.bp,
+ (void *)sig.sp, tid);
+ else
+ Report("ERROR: %s: %s on unknown address %p (pc %p bp %p sp %p T%d)\n",
+ SanitizerToolName, description, (void *)sig.addr, (void *)sig.pc,
+ (void *)sig.bp, (void *)sig.sp, tid);
+ Printf("%s", d.Default());
+ if (sig.pc < GetPageSizeCached())
+ Report("Hint: pc points to the zero page.\n");
+ if (sig.is_memory_access) {
+ const char *access_type =
+ sig.write_flag == SignalContext::Write
+ ? "WRITE"
+ : (sig.write_flag == SignalContext::Read ? "READ" : "UNKNOWN");
+ Report("The signal is caused by a %s memory access.\n", access_type);
+ if (!sig.is_true_faulting_addr)
+ Report("Hint: this fault was caused by a dereference of a high value "
+ "address (see register values below). Disassemble the provided "
+ "pc to learn which register was used.\n");
+ else if (sig.addr < GetPageSizeCached())
+ Report("Hint: address points to the zero page.\n");
+ }
+ MaybeReportNonExecRegion(sig.pc);
+ InternalMmapVector<BufferedStackTrace> stack_buffer(1);
+ BufferedStackTrace *stack = stack_buffer.data();
+ stack->Reset();
+ unwind(sig, unwind_context, stack);
+ stack->Print();
+ MaybeDumpInstructionBytes(sig.pc);
+ MaybeDumpRegisters(sig.context);
+ Printf("%s can not provide additional info.\n", SanitizerToolName);
+ ReportErrorSummary(description, stack);
+}
+
+void ReportDeadlySignal(const SignalContext &sig, u32 tid,
+ UnwindSignalStackCallbackType unwind,
+ const void *unwind_context) {
+ if (sig.IsStackOverflow())
+ ReportStackOverflowImpl(sig, tid, unwind, unwind_context);
+ else
+ ReportDeadlySignalImpl(sig, tid, unwind, unwind_context);
+}
+
+void HandleDeadlySignal(void *siginfo, void *context, u32 tid,
+ UnwindSignalStackCallbackType unwind,
+ const void *unwind_context) {
+ StartReportDeadlySignal();
+ ScopedErrorReportLock rl;
+ SignalContext sig(siginfo, context);
+ ReportDeadlySignal(sig, tid, unwind, unwind_context);
+ Report("ABORTING\n");
+ Die();
+}
+
+#endif // !SANITIZER_FUCHSIA && !SANITIZER_GO
+
+atomic_uintptr_t ScopedErrorReportLock::reporting_thread_ = {0};
+StaticSpinMutex ScopedErrorReportLock::mutex_;
+
+void ScopedErrorReportLock::Lock() {
+ uptr current = GetThreadSelf();
+ for (;;) {
+ uptr expected = 0;
+ if (atomic_compare_exchange_strong(&reporting_thread_, &expected, current,
+ memory_order_relaxed)) {
+ // We've claimed reporting_thread so proceed.
+ mutex_.Lock();
+ return;
+ }
+
+ if (expected == current) {
+ // This is either asynch signal or nested error during error reporting.
+ // Fail simple to avoid deadlocks in Report().
+
+ // Can't use Report() here because of potential deadlocks in nested
+ // signal handlers.
+ CatastrophicErrorWrite(SanitizerToolName,
+ internal_strlen(SanitizerToolName));
+ static const char msg[] = ": nested bug in the same thread, aborting.\n";
+ CatastrophicErrorWrite(msg, sizeof(msg) - 1);
+
+ internal__exit(common_flags()->exitcode);
+ }
+
+ internal_sched_yield();
+ }
+}
+
+void ScopedErrorReportLock::Unlock() {
+ mutex_.Unlock();
+ atomic_store_relaxed(&reporting_thread_, 0);
+}
+
+void ScopedErrorReportLock::CheckLocked() { mutex_.CheckLocked(); }
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp
new file mode 100644
index 00000000000..ac2afe42e26
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_symbolizer_win.cpp
@@ -0,0 +1,324 @@
+//===-- sanitizer_symbolizer_win.cpp --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+// Windows-specific implementation of symbolizer parts.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_WINDOWS
+
+#include "sanitizer_dbghelp.h"
+#include "sanitizer_symbolizer_internal.h"
+
+namespace __sanitizer {
+
+decltype(::StackWalk64) *StackWalk64;
+decltype(::SymCleanup) *SymCleanup;
+decltype(::SymFromAddr) *SymFromAddr;
+decltype(::SymFunctionTableAccess64) *SymFunctionTableAccess64;
+decltype(::SymGetLineFromAddr64) *SymGetLineFromAddr64;
+decltype(::SymGetModuleBase64) *SymGetModuleBase64;
+decltype(::SymGetSearchPathW) *SymGetSearchPathW;
+decltype(::SymInitialize) *SymInitialize;
+decltype(::SymSetOptions) *SymSetOptions;
+decltype(::SymSetSearchPathW) *SymSetSearchPathW;
+decltype(::UnDecorateSymbolName) *UnDecorateSymbolName;
+
+namespace {
+
+class WinSymbolizerTool final : public SymbolizerTool {
+ public:
+ // The constructor is provided to avoid synthesized memsets.
+ WinSymbolizerTool() {}
+
+ bool SymbolizePC(uptr addr, SymbolizedStack *stack) override;
+ bool SymbolizeData(uptr addr, DataInfo *info) override {
+ return false;
+ }
+ const char *Demangle(const char *name) override;
+};
+
+bool is_dbghelp_initialized = false;
+
+bool TrySymInitialize() {
+ SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
+ return SymInitialize(GetCurrentProcess(), 0, TRUE);
+ // FIXME: We don't call SymCleanup() on exit yet - should we?
+}
+
+} // namespace
+
+// Initializes DbgHelp library, if it's not yet initialized. Calls to this
+// function should be synchronized with respect to other calls to DbgHelp API
+// (e.g. from WinSymbolizerTool).
+void InitializeDbgHelpIfNeeded() {
+ if (is_dbghelp_initialized)
+ return;
+
+ HMODULE dbghelp = LoadLibraryA("dbghelp.dll");
+ CHECK(dbghelp && "failed to load dbghelp.dll");
+
+#define DBGHELP_IMPORT(name) \
+ do { \
+ name = \
+ reinterpret_cast<decltype(::name) *>(GetProcAddress(dbghelp, #name)); \
+ CHECK(name != nullptr); \
+ } while (0)
+ DBGHELP_IMPORT(StackWalk64);
+ DBGHELP_IMPORT(SymCleanup);
+ DBGHELP_IMPORT(SymFromAddr);
+ DBGHELP_IMPORT(SymFunctionTableAccess64);
+ DBGHELP_IMPORT(SymGetLineFromAddr64);
+ DBGHELP_IMPORT(SymGetModuleBase64);
+ DBGHELP_IMPORT(SymGetSearchPathW);
+ DBGHELP_IMPORT(SymInitialize);
+ DBGHELP_IMPORT(SymSetOptions);
+ DBGHELP_IMPORT(SymSetSearchPathW);
+ DBGHELP_IMPORT(UnDecorateSymbolName);
+#undef DBGHELP_IMPORT
+
+ if (!TrySymInitialize()) {
+ // OK, maybe the client app has called SymInitialize already.
+ // That's a bit unfortunate for us as all the DbgHelp functions are
+ // single-threaded and we can't coordinate with the app.
+ // FIXME: Can we stop the other threads at this point?
+ // Anyways, we have to reconfigure stuff to make sure that SymInitialize
+ // has all the appropriate options set.
+ // Cross our fingers and reinitialize DbgHelp.
+ Report("*** WARNING: Failed to initialize DbgHelp! ***\n");
+ Report("*** Most likely this means that the app is already ***\n");
+ Report("*** using DbgHelp, possibly with incompatible flags. ***\n");
+ Report("*** Due to technical reasons, symbolization might crash ***\n");
+ Report("*** or produce wrong results. ***\n");
+ SymCleanup(GetCurrentProcess());
+ TrySymInitialize();
+ }
+ is_dbghelp_initialized = true;
+
+ // When an executable is run from a location different from the one where it
+ // was originally built, we may not see the nearby PDB files.
+ // To work around this, let's append the directory of the main module
+ // to the symbol search path. All the failures below are not fatal.
+ const size_t kSymPathSize = 2048;
+ static wchar_t path_buffer[kSymPathSize + 1 + MAX_PATH];
+ if (!SymGetSearchPathW(GetCurrentProcess(), path_buffer, kSymPathSize)) {
+ Report("*** WARNING: Failed to SymGetSearchPathW ***\n");
+ return;
+ }
+ size_t sz = wcslen(path_buffer);
+ if (sz) {
+ CHECK_EQ(0, wcscat_s(path_buffer, L";"));
+ sz++;
+ }
+ DWORD res = GetModuleFileNameW(NULL, path_buffer + sz, MAX_PATH);
+ if (res == 0 || res == MAX_PATH) {
+ Report("*** WARNING: Failed to getting the EXE directory ***\n");
+ return;
+ }
+ // Write the zero character in place of the last backslash to get the
+ // directory of the main module at the end of path_buffer.
+ wchar_t *last_bslash = wcsrchr(path_buffer + sz, L'\\');
+ CHECK_NE(last_bslash, 0);
+ *last_bslash = L'\0';
+ if (!SymSetSearchPathW(GetCurrentProcess(), path_buffer)) {
+ Report("*** WARNING: Failed to SymSetSearchPathW\n");
+ return;
+ }
+}
+
+bool WinSymbolizerTool::SymbolizePC(uptr addr, SymbolizedStack *frame) {
+ InitializeDbgHelpIfNeeded();
+
+ // See https://docs.microsoft.com/en-us/windows/win32/debug/retrieving-symbol-information-by-address
+ InternalMmapVector<char> buffer(sizeof(SYMBOL_INFO) +
+ MAX_SYM_NAME * sizeof(CHAR));
+ PSYMBOL_INFO symbol = (PSYMBOL_INFO)&buffer[0];
+ symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ symbol->MaxNameLen = MAX_SYM_NAME;
+ DWORD64 offset = 0;
+ BOOL got_objname = SymFromAddr(GetCurrentProcess(),
+ (DWORD64)addr, &offset, symbol);
+ if (!got_objname)
+ return false;
+
+ DWORD unused;
+ IMAGEHLP_LINE64 line_info;
+ line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+ BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)addr,
+ &unused, &line_info);
+ frame->info.function = internal_strdup(symbol->Name);
+ frame->info.function_offset = (uptr)offset;
+ if (got_fileline) {
+ frame->info.file = internal_strdup(line_info.FileName);
+ frame->info.line = line_info.LineNumber;
+ }
+ // Only consider this a successful symbolization attempt if we got file info.
+ // Otherwise, try llvm-symbolizer.
+ return got_fileline;
+}
+
+const char *WinSymbolizerTool::Demangle(const char *name) {
+ CHECK(is_dbghelp_initialized);
+ static char demangle_buffer[1000];
+ if (name[0] == '\01' &&
+ UnDecorateSymbolName(name + 1, demangle_buffer, sizeof(demangle_buffer),
+ UNDNAME_NAME_ONLY))
+ return demangle_buffer;
+ else
+ return name;
+}
+
+const char *Symbolizer::PlatformDemangle(const char *name) {
+ return name;
+}
+
+namespace {
+struct ScopedHandle {
+ ScopedHandle() : h_(nullptr) {}
+ explicit ScopedHandle(HANDLE h) : h_(h) {}
+ ~ScopedHandle() {
+ if (h_)
+ ::CloseHandle(h_);
+ }
+ HANDLE get() { return h_; }
+ HANDLE *receive() { return &h_; }
+ HANDLE release() {
+ HANDLE h = h_;
+ h_ = nullptr;
+ return h;
+ }
+ HANDLE h_;
+};
+} // namespace
+
+bool SymbolizerProcess::StartSymbolizerSubprocess() {
+ // Create inherited pipes for stdin and stdout.
+ ScopedHandle stdin_read, stdin_write;
+ ScopedHandle stdout_read, stdout_write;
+ SECURITY_ATTRIBUTES attrs;
+ attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
+ attrs.bInheritHandle = TRUE;
+ attrs.lpSecurityDescriptor = nullptr;
+ if (!::CreatePipe(stdin_read.receive(), stdin_write.receive(), &attrs, 0) ||
+ !::CreatePipe(stdout_read.receive(), stdout_write.receive(), &attrs, 0)) {
+ VReport(2, "WARNING: %s CreatePipe failed (error code: %d)\n",
+ SanitizerToolName, path_, GetLastError());
+ return false;
+ }
+
+ // Don't inherit the writing end of stdin or the reading end of stdout.
+ if (!SetHandleInformation(stdin_write.get(), HANDLE_FLAG_INHERIT, 0) ||
+ !SetHandleInformation(stdout_read.get(), HANDLE_FLAG_INHERIT, 0)) {
+ VReport(2, "WARNING: %s SetHandleInformation failed (error code: %d)\n",
+ SanitizerToolName, path_, GetLastError());
+ return false;
+ }
+
+ // Compute the command line. Wrap double quotes around everything.
+ const char *argv[kArgVMax];
+ GetArgV(path_, argv);
+ InternalScopedString command_line;
+ for (int i = 0; argv[i]; i++) {
+ const char *arg = argv[i];
+ int arglen = internal_strlen(arg);
+ // Check that tool command lines are simple and that complete escaping is
+ // unnecessary.
+ CHECK(!internal_strchr(arg, '"') && "quotes in args unsupported");
+ CHECK(arglen > 0 && arg[arglen - 1] != '\\' &&
+ "args ending in backslash and empty args unsupported");
+ command_line.append("\"%s\" ", arg);
+ }
+ VReport(3, "Launching symbolizer command: %s\n", command_line.data());
+
+ // Launch llvm-symbolizer with stdin and stdout redirected.
+ STARTUPINFOA si;
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ si.dwFlags |= STARTF_USESTDHANDLES;
+ si.hStdInput = stdin_read.get();
+ si.hStdOutput = stdout_write.get();
+ PROCESS_INFORMATION pi;
+ memset(&pi, 0, sizeof(pi));
+ if (!CreateProcessA(path_, // Executable
+ command_line.data(), // Command line
+ nullptr, // Process handle not inheritable
+ nullptr, // Thread handle not inheritable
+ TRUE, // Set handle inheritance to TRUE
+ 0, // Creation flags
+ nullptr, // Use parent's environment block
+ nullptr, // Use parent's starting directory
+ &si, &pi)) {
+ VReport(2, "WARNING: %s failed to create process for %s (error code: %d)\n",
+ SanitizerToolName, path_, GetLastError());
+ return false;
+ }
+
+ // Process creation succeeded, so transfer handle ownership into the fields.
+ input_fd_ = stdout_read.release();
+ output_fd_ = stdin_write.release();
+
+ // The llvm-symbolizer process is responsible for quitting itself when the
+ // stdin pipe is closed, so we don't need these handles. Close them to prevent
+ // leaks. If we ever want to try to kill the symbolizer process from the
+ // parent, we'll want to hang on to these handles.
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ return true;
+}
+
+static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
+ LowLevelAllocator *allocator) {
+ if (!common_flags()->symbolize) {
+ VReport(2, "Symbolizer is disabled.\n");
+ return;
+ }
+
+ // Add llvm-symbolizer.
+ const char *user_path = common_flags()->external_symbolizer_path;
+
+ if (user_path && internal_strchr(user_path, '%')) {
+ char *new_path = (char *)InternalAlloc(kMaxPathLength);
+ SubstituteForFlagValue(user_path, new_path, kMaxPathLength);
+ user_path = new_path;
+ }
+
+ const char *path =
+ user_path ? user_path : FindPathToBinary("llvm-symbolizer.exe");
+ if (path) {
+ VReport(2, "Using llvm-symbolizer at %spath: %s\n",
+ user_path ? "user-specified " : "", path);
+ list->push_back(new(*allocator) LLVMSymbolizer(path, allocator));
+ } else {
+ if (user_path && user_path[0] == '\0') {
+ VReport(2, "External symbolizer is explicitly disabled.\n");
+ } else {
+ VReport(2, "External symbolizer is not present.\n");
+ }
+ }
+
+ // Add the dbghelp based symbolizer.
+ list->push_back(new(*allocator) WinSymbolizerTool());
+}
+
+Symbolizer *Symbolizer::PlatformInit() {
+ IntrusiveList<SymbolizerTool> list;
+ list.clear();
+ ChooseSymbolizerTools(&list, &symbolizer_allocator_);
+
+ return new(symbolizer_allocator_) Symbolizer(list);
+}
+
+void Symbolizer::LateInitialize() {
+ Symbolizer::GetOrInit();
+}
+
+} // namespace __sanitizer
+
+#endif // _WIN32
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc
new file mode 100644
index 00000000000..e7f95d33ad0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc
@@ -0,0 +1,39 @@
+//===-- sanitizer_syscall_generic.inc ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic implementations of internal_syscall* and internal_iserror.
+//
+//===----------------------------------------------------------------------===//
+
+// NetBSD uses libc calls directly
+#if !SANITIZER_NETBSD
+
+#if SANITIZER_FREEBSD || SANITIZER_APPLE || SANITIZER_SOLARIS
+# define SYSCALL(name) SYS_ ## name
+#else
+# define SYSCALL(name) __NR_ ## name
+#endif
+
+#if (defined(__x86_64__) && (SANITIZER_FREEBSD || SANITIZER_APPLE)) || \
+ (defined(__aarch64__) && SANITIZER_FREEBSD)
+# define internal_syscall __syscall
+# else
+# define internal_syscall syscall
+#endif
+
+#endif
+
+bool internal_iserror(uptr retval, int *rverrno) {
+ if (retval == (uptr)-1) {
+ if (rverrno)
+ *rverrno = errno;
+ return true;
+ } else {
+ return false;
+ }
+}
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_aarch64.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_aarch64.inc
new file mode 100644
index 00000000000..56c5e99220c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_aarch64.inc
@@ -0,0 +1,137 @@
+//===-- sanitizer_syscall_linux_aarch64.inc --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementations of internal_syscall and internal_iserror for Linux/aarch64.
+//
+//===----------------------------------------------------------------------===//
+
+#define SYSCALL(name) __NR_ ## name
+
+static uptr __internal_syscall(u64 nr) {
+ register u64 x8 asm("x8") = nr;
+ register u64 x0 asm("x0");
+ asm volatile("svc 0"
+ : "=r"(x0)
+ : "r"(x8)
+ : "memory", "cc");
+ return x0;
+}
+#define __internal_syscall0(n) \
+ (__internal_syscall)(n)
+
+static uptr __internal_syscall(u64 nr, u64 arg1) {
+ register u64 x8 asm("x8") = nr;
+ register u64 x0 asm("x0") = arg1;
+ asm volatile("svc 0"
+ : "=r"(x0)
+ : "r"(x8), "0"(x0)
+ : "memory", "cc");
+ return x0;
+}
+#define __internal_syscall1(n, a1) \
+ (__internal_syscall)(n, (u64)(a1))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2) {
+ register u64 x8 asm("x8") = nr;
+ register u64 x0 asm("x0") = arg1;
+ register u64 x1 asm("x1") = arg2;
+ asm volatile("svc 0"
+ : "=r"(x0)
+ : "r"(x8), "0"(x0), "r"(x1)
+ : "memory", "cc");
+ return x0;
+}
+#define __internal_syscall2(n, a1, a2) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3) {
+ register u64 x8 asm("x8") = nr;
+ register u64 x0 asm("x0") = arg1;
+ register u64 x1 asm("x1") = arg2;
+ register u64 x2 asm("x2") = arg3;
+ asm volatile("svc 0"
+ : "=r"(x0)
+ : "r"(x8), "0"(x0), "r"(x1), "r"(x2)
+ : "memory", "cc");
+ return x0;
+}
+#define __internal_syscall3(n, a1, a2, a3) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3,
+ u64 arg4) {
+ register u64 x8 asm("x8") = nr;
+ register u64 x0 asm("x0") = arg1;
+ register u64 x1 asm("x1") = arg2;
+ register u64 x2 asm("x2") = arg3;
+ register u64 x3 asm("x3") = arg4;
+ asm volatile("svc 0"
+ : "=r"(x0)
+ : "r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3)
+ : "memory", "cc");
+ return x0;
+}
+#define __internal_syscall4(n, a1, a2, a3, a4) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3,
+ u64 arg4, long arg5) {
+ register u64 x8 asm("x8") = nr;
+ register u64 x0 asm("x0") = arg1;
+ register u64 x1 asm("x1") = arg2;
+ register u64 x2 asm("x2") = arg3;
+ register u64 x3 asm("x3") = arg4;
+ register u64 x4 asm("x4") = arg5;
+ asm volatile("svc 0"
+ : "=r"(x0)
+ : "r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4)
+ : "memory", "cc");
+ return x0;
+}
+#define __internal_syscall5(n, a1, a2, a3, a4, a5) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (u64)(a5))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3,
+ u64 arg4, long arg5, long arg6) {
+ register u64 x8 asm("x8") = nr;
+ register u64 x0 asm("x0") = arg1;
+ register u64 x1 asm("x1") = arg2;
+ register u64 x2 asm("x2") = arg3;
+ register u64 x3 asm("x3") = arg4;
+ register u64 x4 asm("x4") = arg5;
+ register u64 x5 asm("x5") = arg6;
+ asm volatile("svc 0"
+ : "=r"(x0)
+ : "r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5)
+ : "memory", "cc");
+ return x0;
+}
+#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (u64)(a5), (long)(a6))
+
+#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n
+#define __SYSCALL_NARGS(...) \
+ __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, )
+#define __SYSCALL_CONCAT_X(a, b) a##b
+#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b)
+#define __SYSCALL_DISP(b, ...) \
+ __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
+
+#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__)
+
+// Helper function used to avoid cobbler errno.
+bool internal_iserror(uptr retval, int *rverrno) {
+ if (retval >= (uptr)-4095) {
+ if (rverrno)
+ *rverrno = -retval;
+ return true;
+ }
+ return false;
+}
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_arm.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_arm.inc
new file mode 100644
index 00000000000..121a9445b41
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_arm.inc
@@ -0,0 +1,137 @@
+//===-- sanitizer_syscall_linux_arm.inc -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementations of internal_syscall and internal_iserror for Linux/arm.
+//
+//===----------------------------------------------------------------------===//
+
+#define SYSCALL(name) __NR_ ## name
+
+static uptr __internal_syscall(u32 nr) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0");
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall0(n) \
+ (__internal_syscall)(n)
+
+static uptr __internal_syscall(u32 nr, u32 arg1) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0") = arg1;
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8), "0"(r0)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall1(n, a1) \
+ (__internal_syscall)(n, (u32)(a1))
+
+static uptr __internal_syscall(u32 nr, u32 arg1, long arg2) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0") = arg1;
+ register u32 r1 asm("r1") = arg2;
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8), "0"(r0), "r"(r1)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall2(n, a1, a2) \
+ (__internal_syscall)(n, (u32)(a1), (long)(a2))
+
+static uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0") = arg1;
+ register u32 r1 asm("r1") = arg2;
+ register u32 r2 asm("r2") = arg3;
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8), "0"(r0), "r"(r1), "r"(r2)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall3(n, a1, a2, a3) \
+ (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3))
+
+static uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3,
+ u32 arg4) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0") = arg1;
+ register u32 r1 asm("r1") = arg2;
+ register u32 r2 asm("r2") = arg3;
+ register u32 r3 asm("r3") = arg4;
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8), "0"(r0), "r"(r1), "r"(r2), "r"(r3)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall4(n, a1, a2, a3, a4) \
+ (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3), (long)(a4))
+
+static uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3,
+ u32 arg4, long arg5) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0") = arg1;
+ register u32 r1 asm("r1") = arg2;
+ register u32 r2 asm("r2") = arg3;
+ register u32 r3 asm("r3") = arg4;
+ register u32 r4 asm("r4") = arg5;
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall5(n, a1, a2, a3, a4, a5) \
+ (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (u32)(a5))
+
+static uptr __internal_syscall(u32 nr, u32 arg1, long arg2, long arg3,
+ u32 arg4, long arg5, long arg6) {
+ register u32 r8 asm("r7") = nr;
+ register u32 r0 asm("r0") = arg1;
+ register u32 r1 asm("r1") = arg2;
+ register u32 r2 asm("r2") = arg3;
+ register u32 r3 asm("r3") = arg4;
+ register u32 r4 asm("r4") = arg5;
+ register u32 r5 asm("r5") = arg6;
+ asm volatile("swi #0"
+ : "=r"(r0)
+ : "r"(r8), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)
+ : "memory", "cc");
+ return r0;
+}
+#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \
+ (__internal_syscall)(n, (u32)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (u32)(a5), (long)(a6))
+
+#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n
+#define __SYSCALL_NARGS(...) \
+ __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, )
+#define __SYSCALL_CONCAT_X(a, b) a##b
+#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b)
+#define __SYSCALL_DISP(b, ...) \
+ __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
+
+#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__)
+
+// Helper function used to avoid cobbler errno.
+bool internal_iserror(uptr retval, int *rverrno) {
+ if (retval >= (uptr)-4095) {
+ if (rverrno)
+ *rverrno = -retval;
+ return true;
+ }
+ return false;
+}
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_hexagon.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_hexagon.inc
new file mode 100644
index 00000000000..553bff7503b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_hexagon.inc
@@ -0,0 +1,131 @@
+//===-- sanitizer_syscall_linux_hexagon.inc ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementations of internal_syscall and internal_iserror for Linux/hexagon.
+//
+//===----------------------------------------------------------------------===//
+
+#define SYSCALL(name) __NR_##name
+
+#define __internal_syscall_LL_E(x) \
+ ((union { \
+ long long ll; \
+ long l[2]; \
+ }){.ll = x}) \
+ .l[0], \
+ ((union { \
+ long long ll; \
+ long l[2]; \
+ }){.ll = x}) \
+ .l[1]
+#define __internal_syscall_LL_O(x) 0, __SYSCALL_LL_E((x))
+
+#define __asm_syscall(...) \
+ do { \
+ __asm__ __volatile__("trap0(#1)" : "=r"(r0) : __VA_ARGS__ : "memory"); \
+ return r0; \
+ } while (0)
+
+#define __internal_syscall0(n) (__internal_syscall)(n)
+
+static uptr __internal_syscall(long n) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0");
+ __asm_syscall("r"(r6));
+}
+
+#define __internal_syscall1(n, a1) (__internal_syscall)(n, (long)(a1))
+
+static uptr __internal_syscall(long n, long a) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0") = a;
+ __asm_syscall("r"(r6), "0"(r0));
+}
+
+#define __internal_syscall2(n, a1, a2) \
+ (__internal_syscall)(n, (long)(a1), (long)(a2))
+
+static uptr __internal_syscall(long n, long a, long b) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0") = a;
+ register u32 r1 __asm__("r1") = b;
+ __asm_syscall("r"(r6), "0"(r0), "r"(r1));
+}
+
+#define __internal_syscall3(n, a1, a2, a3) \
+ (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3))
+
+static uptr __internal_syscall(long n, long a, long b, long c) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0") = a;
+ register u32 r1 __asm__("r1") = b;
+ register u32 r2 __asm__("r2") = c;
+ __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2));
+}
+
+#define __internal_syscall4(n, a1, a2, a3, a4) \
+ (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4))
+
+static uptr __internal_syscall(long n, long a, long b, long c, long d) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0") = a;
+ register u32 r1 __asm__("r1") = b;
+ register u32 r2 __asm__("r2") = c;
+ register u32 r3 __asm__("r3") = d;
+ __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3));
+}
+
+#define __internal_syscall5(n, a1, a2, a3, a4, a5) \
+ (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (long)(a5))
+
+static uptr __internal_syscall(long n, long a, long b, long c, long d, long e) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0") = a;
+ register u32 r1 __asm__("r1") = b;
+ register u32 r2 __asm__("r2") = c;
+ register u32 r3 __asm__("r3") = d;
+ register u32 r4 __asm__("r4") = e;
+ __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4));
+}
+
+#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \
+ (__internal_syscall)(n, (long)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (long)(a5), (long)(a6))
+
+static uptr __internal_syscall(long n, long a, long b, long c, long d, long e,
+ long f) {
+ register u32 r6 __asm__("r6") = n;
+ register u32 r0 __asm__("r0") = a;
+ register u32 r1 __asm__("r1") = b;
+ register u32 r2 __asm__("r2") = c;
+ register u32 r3 __asm__("r3") = d;
+ register u32 r4 __asm__("r4") = e;
+ register u32 r5 __asm__("r5") = f;
+ __asm_syscall("r"(r6), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5));
+}
+
+#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n
+#define __SYSCALL_NARGS(...) \
+ __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, )
+#define __SYSCALL_CONCAT_X(a, b) a##b
+#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b)
+#define __SYSCALL_DISP(b, ...) \
+ __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
+
+#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__)
+
+// Helper function used to avoid clobbering of errno.
+bool internal_iserror(uptr retval, int *rverrno) {
+ if (retval >= (uptr)-4095) {
+ if (rverrno)
+ *rverrno = -retval;
+ return true;
+ }
+ return false;
+}
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_loongarch64.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_loongarch64.inc
new file mode 100644
index 00000000000..80f5e6be8ad
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_loongarch64.inc
@@ -0,0 +1,171 @@
+//===-- sanitizer_syscall_linux_loongarch64.inc -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementations of internal_syscall and internal_iserror for
+// Linux/loongarch64.
+//
+//===----------------------------------------------------------------------===//
+
+// About local register variables:
+// https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html#Local-Register-Variables
+//
+// Kernel ABI:
+// https://lore.kernel.org/loongarch/1f353678-3398-e30b-1c87-6edb278f74db@xen0n.name/T/#m1613bc86c2d7bf5f6da92bd62984302bfd699a2f
+// syscall number is placed in a7
+// parameters, if present, are placed in a0-a6
+// upon return:
+// the return value is placed in a0
+// t0-t8 should be considered clobbered
+// all other registers are preserved
+#define SYSCALL(name) __NR_##name
+
+#define INTERNAL_SYSCALL_CLOBBERS \
+ "memory", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8"
+
+static uptr __internal_syscall(u64 nr) {
+ register u64 a7 asm("$a7") = nr;
+ register u64 a0 asm("$a0");
+ __asm__ volatile("syscall 0\n\t"
+ : "=r"(a0)
+ : "r"(a7)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall0(n) (__internal_syscall)(n)
+
+static uptr __internal_syscall(u64 nr, u64 arg1) {
+ register u64 a7 asm("$a7") = nr;
+ register u64 a0 asm("$a0") = arg1;
+ __asm__ volatile("syscall 0\n\t"
+ : "+r"(a0)
+ : "r"(a7)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall1(n, a1) (__internal_syscall)(n, (u64)(a1))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2) {
+ register u64 a7 asm("$a7") = nr;
+ register u64 a0 asm("$a0") = arg1;
+ register u64 a1 asm("$a1") = arg2;
+ __asm__ volatile("syscall 0\n\t"
+ : "+r"(a0)
+ : "r"(a7), "r"(a1)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall2(n, a1, a2) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3) {
+ register u64 a7 asm("$a7") = nr;
+ register u64 a0 asm("$a0") = arg1;
+ register u64 a1 asm("$a1") = arg2;
+ register u64 a2 asm("$a2") = arg3;
+ __asm__ volatile("syscall 0\n\t"
+ : "+r"(a0)
+ : "r"(a7), "r"(a1), "r"(a2)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall3(n, a1, a2, a3) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3,
+ u64 arg4) {
+ register u64 a7 asm("$a7") = nr;
+ register u64 a0 asm("$a0") = arg1;
+ register u64 a1 asm("$a1") = arg2;
+ register u64 a2 asm("$a2") = arg3;
+ register u64 a3 asm("$a3") = arg4;
+ __asm__ volatile("syscall 0\n\t"
+ : "+r"(a0)
+ : "r"(a7), "r"(a1), "r"(a2), "r"(a3)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall4(n, a1, a2, a3, a4) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3, u64 arg4,
+ long arg5) {
+ register u64 a7 asm("$a7") = nr;
+ register u64 a0 asm("$a0") = arg1;
+ register u64 a1 asm("$a1") = arg2;
+ register u64 a2 asm("$a2") = arg3;
+ register u64 a3 asm("$a3") = arg4;
+ register u64 a4 asm("$a4") = arg5;
+ __asm__ volatile("syscall 0\n\t"
+ : "+r"(a0)
+ : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall5(n, a1, a2, a3, a4, a5) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (u64)(a5))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3, u64 arg4,
+ long arg5, long arg6) {
+ register u64 a7 asm("$a7") = nr;
+ register u64 a0 asm("$a0") = arg1;
+ register u64 a1 asm("$a1") = arg2;
+ register u64 a2 asm("$a2") = arg3;
+ register u64 a3 asm("$a3") = arg4;
+ register u64 a4 asm("$a4") = arg5;
+ register u64 a5 asm("$a5") = arg6;
+ __asm__ volatile("syscall 0\n\t"
+ : "+r"(a0)
+ : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (u64)(a5), (long)(a6))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3, u64 arg4,
+ long arg5, long arg6, long arg7) {
+ register u64 a7 asm("$a7") = nr;
+ register u64 a0 asm("$a0") = arg1;
+ register u64 a1 asm("$a1") = arg2;
+ register u64 a2 asm("$a2") = arg3;
+ register u64 a3 asm("$a3") = arg4;
+ register u64 a4 asm("$a4") = arg5;
+ register u64 a5 asm("$a5") = arg6;
+ register u64 a6 asm("$a6") = arg7;
+ __asm__ volatile("syscall 0\n\t"
+ : "+r"(a0)
+ : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5),
+ "r"(a6)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall7(n, a1, a2, a3, a4, a5, a6, a7) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (u64)(a5), (long)(a6), (long)(a7))
+
+#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n
+#define __SYSCALL_NARGS(...) \
+ __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, )
+#define __SYSCALL_CONCAT_X(a, b) a##b
+#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b)
+#define __SYSCALL_DISP(b, ...) \
+ __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
+
+#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__)
+
+// Helper function used to avoid clobbering of errno.
+bool internal_iserror(uptr retval, int *internal_errno) {
+ if (retval >= (uptr)-4095) {
+ if (internal_errno)
+ *internal_errno = -retval;
+ return true;
+ }
+ return false;
+}
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_riscv64.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_riscv64.inc
new file mode 100644
index 00000000000..89c12602057
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_riscv64.inc
@@ -0,0 +1,174 @@
+//===-- sanitizer_syscall_linux_riscv64.inc ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementations of internal_syscall and internal_iserror for Linux/riscv64.
+//
+//===----------------------------------------------------------------------===//
+
+// About local register variables:
+// https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html#Local-Register-Variables
+//
+// Kernel ABI...
+// To my surprise I haven't found much information regarding it.
+// Kernel source and internet browsing shows that:
+// syscall number is passed in a7
+// (http://man7.org/linux/man-pages/man2/syscall.2.html) results are return in
+// a0 and a1 (http://man7.org/linux/man-pages/man2/syscall.2.html) arguments
+// are passed in: a0-a7 (see below)
+//
+// Regarding the arguments. The only "documentation" I could find is
+// this comment (!!!) by Bruce Hold on google forums (!!!):
+// https://groups.google.com/a/groups.riscv.org/forum/#!topic/sw-dev/exbrzM3GZDQ
+// Confirmed by inspecting glibc sources.
+// Great way to document things.
+#define SYSCALL(name) __NR_##name
+
+#define INTERNAL_SYSCALL_CLOBBERS "memory"
+
+static uptr __internal_syscall(u64 nr) {
+ register u64 a7 asm("a7") = nr;
+ register u64 a0 asm("a0");
+ __asm__ volatile("ecall\n\t"
+ : "=r"(a0)
+ : "r"(a7)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall0(n) (__internal_syscall)(n)
+
+static uptr __internal_syscall(u64 nr, u64 arg1) {
+ register u64 a7 asm("a7") = nr;
+ register u64 a0 asm("a0") = arg1;
+ __asm__ volatile("ecall\n\t"
+ : "+r"(a0)
+ : "r"(a7)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall1(n, a1) (__internal_syscall)(n, (u64)(a1))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2) {
+ register u64 a7 asm("a7") = nr;
+ register u64 a0 asm("a0") = arg1;
+ register u64 a1 asm("a1") = arg2;
+ __asm__ volatile("ecall\n\t"
+ : "+r"(a0)
+ : "r"(a7), "r"(a1)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall2(n, a1, a2) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3) {
+ register u64 a7 asm("a7") = nr;
+ register u64 a0 asm("a0") = arg1;
+ register u64 a1 asm("a1") = arg2;
+ register u64 a2 asm("a2") = arg3;
+ __asm__ volatile("ecall\n\t"
+ : "+r"(a0)
+ : "r"(a7), "r"(a1), "r"(a2)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall3(n, a1, a2, a3) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3,
+ u64 arg4) {
+ register u64 a7 asm("a7") = nr;
+ register u64 a0 asm("a0") = arg1;
+ register u64 a1 asm("a1") = arg2;
+ register u64 a2 asm("a2") = arg3;
+ register u64 a3 asm("a3") = arg4;
+ __asm__ volatile("ecall\n\t"
+ : "+r"(a0)
+ : "r"(a7), "r"(a1), "r"(a2), "r"(a3)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall4(n, a1, a2, a3, a4) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3, u64 arg4,
+ long arg5) {
+ register u64 a7 asm("a7") = nr;
+ register u64 a0 asm("a0") = arg1;
+ register u64 a1 asm("a1") = arg2;
+ register u64 a2 asm("a2") = arg3;
+ register u64 a3 asm("a3") = arg4;
+ register u64 a4 asm("a4") = arg5;
+ __asm__ volatile("ecall\n\t"
+ : "+r"(a0)
+ : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall5(n, a1, a2, a3, a4, a5) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (u64)(a5))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3, u64 arg4,
+ long arg5, long arg6) {
+ register u64 a7 asm("a7") = nr;
+ register u64 a0 asm("a0") = arg1;
+ register u64 a1 asm("a1") = arg2;
+ register u64 a2 asm("a2") = arg3;
+ register u64 a3 asm("a3") = arg4;
+ register u64 a4 asm("a4") = arg5;
+ register u64 a5 asm("a5") = arg6;
+ __asm__ volatile("ecall\n\t"
+ : "+r"(a0)
+ : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall6(n, a1, a2, a3, a4, a5, a6) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (u64)(a5), (long)(a6))
+
+static uptr __internal_syscall(u64 nr, u64 arg1, long arg2, long arg3, u64 arg4,
+ long arg5, long arg6, long arg7) {
+ register u64 a7 asm("a7") = nr;
+ register u64 a0 asm("a0") = arg1;
+ register u64 a1 asm("a1") = arg2;
+ register u64 a2 asm("a2") = arg3;
+ register u64 a3 asm("a3") = arg4;
+ register u64 a4 asm("a4") = arg5;
+ register u64 a5 asm("a5") = arg6;
+ register u64 a6 asm("a6") = arg7;
+ __asm__ volatile("ecall\n\t"
+ : "+r"(a0)
+ : "r"(a7), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5),
+ "r"(a6)
+ : INTERNAL_SYSCALL_CLOBBERS);
+ return a0;
+}
+#define __internal_syscall7(n, a1, a2, a3, a4, a5, a6, a7) \
+ (__internal_syscall)(n, (u64)(a1), (long)(a2), (long)(a3), (long)(a4), \
+ (u64)(a5), (long)(a6), (long)(a7))
+
+#define __SYSCALL_NARGS_X(a1, a2, a3, a4, a5, a6, a7, a8, n, ...) n
+#define __SYSCALL_NARGS(...) \
+ __SYSCALL_NARGS_X(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0, )
+#define __SYSCALL_CONCAT_X(a, b) a##b
+#define __SYSCALL_CONCAT(a, b) __SYSCALL_CONCAT_X(a, b)
+#define __SYSCALL_DISP(b, ...) \
+ __SYSCALL_CONCAT(b, __SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
+
+#define internal_syscall(...) __SYSCALL_DISP(__internal_syscall, __VA_ARGS__)
+
+// Helper function used to avoid clobbering of errno.
+bool internal_iserror(uptr retval, int *rverrno) {
+ if (retval >= (uptr)-4095) {
+ if (rverrno)
+ *rverrno = -retval;
+ return true;
+ }
+ return false;
+}
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc
new file mode 100644
index 00000000000..67e8686d12c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc
@@ -0,0 +1,90 @@
+//===-- sanitizer_syscall_linux_x86_64.inc ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementations of internal_syscall and internal_iserror for Linux/x86_64.
+//
+//===----------------------------------------------------------------------===//
+
+#define SYSCALL(name) __NR_ ## name
+
+static uptr internal_syscall(u64 nr) {
+ u64 retval;
+ asm volatile("syscall" : "=a"(retval) : "a"(nr) : "rcx", "r11",
+ "memory", "cc");
+ return retval;
+}
+
+template <typename T1>
+static uptr internal_syscall(u64 nr, T1 arg1) {
+ u64 retval;
+ asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1) :
+ "rcx", "r11", "memory", "cc");
+ return retval;
+}
+
+template <typename T1, typename T2>
+static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2) {
+ u64 retval;
+ asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
+ "S"((u64)arg2) : "rcx", "r11", "memory", "cc");
+ return retval;
+}
+
+template <typename T1, typename T2, typename T3>
+static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3) {
+ u64 retval;
+ asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
+ "S"((u64)arg2), "d"((u64)arg3) : "rcx", "r11", "memory", "cc");
+ return retval;
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4) {
+ u64 retval;
+ asm volatile("mov %5, %%r10;"
+ "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
+ "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4) :
+ "rcx", "r11", "r10", "memory", "cc");
+ return retval;
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
+ T5 arg5) {
+ u64 retval;
+ asm volatile("mov %5, %%r10;"
+ "mov %6, %%r8;"
+ "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
+ "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5) :
+ "rcx", "r11", "r10", "r8", "memory", "cc");
+ return retval;
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
+ T5 arg5, T6 arg6) {
+ u64 retval;
+ asm volatile("mov %5, %%r10;"
+ "mov %6, %%r8;"
+ "mov %7, %%r9;"
+ "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
+ "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5),
+ "r"((u64)arg6) : "rcx", "r11", "r10", "r8", "r9",
+ "memory", "cc");
+ return retval;
+}
+
+bool internal_iserror(uptr retval, int *rverrno) {
+ if (retval >= (uptr)-4095) {
+ if (rverrno)
+ *rverrno = -retval;
+ return true;
+ }
+ return false;
+}
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscalls_netbsd.inc b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscalls_netbsd.inc
new file mode 100644
index 00000000000..4ce5de06275
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_syscalls_netbsd.inc
@@ -0,0 +1,3944 @@
+//===-- sanitizer_syscalls_netbsd.inc ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Common syscalls handlers for tools like AddressSanitizer,
+// ThreadSanitizer, MemorySanitizer, etc.
+//
+// This file should be included into the tool's interceptor file,
+// which has to define it's own macros:
+// COMMON_SYSCALL_PRE_READ_RANGE
+// Called in prehook for regions that will be read by the kernel and
+// must be initialized.
+// COMMON_SYSCALL_PRE_WRITE_RANGE
+// Called in prehook for regions that will be written to by the kernel
+// and must be addressable. The actual write range may be smaller than
+// reported in the prehook. See POST_WRITE_RANGE.
+// COMMON_SYSCALL_POST_READ_RANGE
+// Called in posthook for regions that were read by the kernel. Does
+// not make much sense.
+// COMMON_SYSCALL_POST_WRITE_RANGE
+// Called in posthook for regions that were written to by the kernel
+// and are now initialized.
+// COMMON_SYSCALL_ACQUIRE(addr)
+// Acquire memory visibility from addr.
+// COMMON_SYSCALL_RELEASE(addr)
+// Release memory visibility to addr.
+// COMMON_SYSCALL_FD_CLOSE(fd)
+// Called before closing file descriptor fd.
+// COMMON_SYSCALL_FD_ACQUIRE(fd)
+// Acquire memory visibility from fd.
+// COMMON_SYSCALL_FD_RELEASE(fd)
+// Release memory visibility to fd.
+// COMMON_SYSCALL_PRE_FORK()
+// Called before fork syscall.
+// COMMON_SYSCALL_POST_FORK(long long res)
+// Called after fork syscall.
+//
+// DO NOT EDIT! THIS FILE HAS BEEN GENERATED!
+//
+// Generated with: generate_netbsd_syscalls.awk
+// Generated date: 2020-09-10
+// Generated from: syscalls.master,v 1.306 2020/08/14 00:53:16 riastradh Exp
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_NETBSD
+
+#include "sanitizer_libc.h"
+
+#define PRE_SYSCALL(name) \
+ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_impl_##name
+#define PRE_READ(p, s) COMMON_SYSCALL_PRE_READ_RANGE(p, s)
+#define PRE_WRITE(p, s) COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
+
+#define POST_SYSCALL(name) \
+ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_post_impl_##name
+#define POST_READ(p, s) COMMON_SYSCALL_POST_READ_RANGE(p, s)
+#define POST_WRITE(p, s) COMMON_SYSCALL_POST_WRITE_RANGE(p, s)
+
+#ifndef COMMON_SYSCALL_ACQUIRE
+#define COMMON_SYSCALL_ACQUIRE(addr) ((void)(addr))
+#endif
+
+#ifndef COMMON_SYSCALL_RELEASE
+#define COMMON_SYSCALL_RELEASE(addr) ((void)(addr))
+#endif
+
+#ifndef COMMON_SYSCALL_FD_CLOSE
+#define COMMON_SYSCALL_FD_CLOSE(fd) ((void)(fd))
+#endif
+
+#ifndef COMMON_SYSCALL_FD_ACQUIRE
+#define COMMON_SYSCALL_FD_ACQUIRE(fd) ((void)(fd))
+#endif
+
+#ifndef COMMON_SYSCALL_FD_RELEASE
+#define COMMON_SYSCALL_FD_RELEASE(fd) ((void)(fd))
+#endif
+
+#ifndef COMMON_SYSCALL_PRE_FORK
+#define COMMON_SYSCALL_PRE_FORK() \
+ {}
+#endif
+
+#ifndef COMMON_SYSCALL_POST_FORK
+#define COMMON_SYSCALL_POST_FORK(res) \
+ {}
+#endif
+
+// FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such).
+
+extern "C" {
+#define SYS_MAXSYSARGS 8
+PRE_SYSCALL(syscall)(long long code_, long long args_[SYS_MAXSYSARGS]) {
+ /* Nothing to do */
+}
+POST_SYSCALL(syscall)
+(long long res, long long code_, long long args_[SYS_MAXSYSARGS]) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(exit)(long long rval_) { /* Nothing to do */ }
+POST_SYSCALL(exit)(long long res, long long rval_) { /* Nothing to do */ }
+PRE_SYSCALL(fork)(void) { COMMON_SYSCALL_PRE_FORK(); }
+POST_SYSCALL(fork)(long long res) { COMMON_SYSCALL_POST_FORK(res); }
+PRE_SYSCALL(read)(long long fd_, void *buf_, long long nbyte_) {
+ if (buf_) {
+ PRE_WRITE(buf_, nbyte_);
+ }
+}
+POST_SYSCALL(read)(long long res, long long fd_, void *buf_, long long nbyte_) {
+ if (res > 0) {
+ POST_WRITE(buf_, res);
+ }
+}
+PRE_SYSCALL(write)(long long fd_, void *buf_, long long nbyte_) {
+ if (buf_) {
+ PRE_READ(buf_, nbyte_);
+ }
+}
+POST_SYSCALL(write)
+(long long res, long long fd_, void *buf_, long long nbyte_) {
+ if (res > 0) {
+ POST_READ(buf_, res);
+ }
+}
+PRE_SYSCALL(open)(void *path_, long long flags_, long long mode_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(open)
+(long long res, void *path_, long long flags_, long long mode_) {
+ if (res > 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(close)(long long fd_) { COMMON_SYSCALL_FD_CLOSE((int)fd_); }
+POST_SYSCALL(close)(long long res, long long fd_) { /* Nothing to do */ }
+PRE_SYSCALL(compat_50_wait4)
+(long long pid_, void *status_, long long options_, void *rusage_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_wait4)
+(long long res, long long pid_, void *status_, long long options_,
+ void *rusage_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_ocreat)(void *path_, long long mode_) { /* TODO */ }
+POST_SYSCALL(compat_43_ocreat)(long long res, void *path_, long long mode_) {
+ /* TODO */
+}
+PRE_SYSCALL(link)(void *path_, void *link_) {
+ const char *path = (const char *)path_;
+ const char *link = (const char *)link_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (link) {
+ PRE_READ(path, __sanitizer::internal_strlen(link) + 1);
+ }
+}
+POST_SYSCALL(link)(long long res, void *path_, void *link_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ const char *link = (const char *)link_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (link) {
+ POST_READ(path, __sanitizer::internal_strlen(link) + 1);
+ }
+ }
+}
+PRE_SYSCALL(unlink)(void *path_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(unlink)(long long res, void *path_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+/* syscall 11 has been skipped */
+PRE_SYSCALL(chdir)(void *path_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(chdir)(long long res, void *path_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(fchdir)(long long fd_) { /* Nothing to do */ }
+POST_SYSCALL(fchdir)(long long res, long long fd_) { /* Nothing to do */ }
+PRE_SYSCALL(compat_50_mknod)(void *path_, long long mode_, long long dev_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_mknod)
+(long long res, void *path_, long long mode_, long long dev_) {
+ /* TODO */
+}
+PRE_SYSCALL(chmod)(void *path_, long long mode_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(chmod)(long long res, void *path_, long long mode_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(chown)(void *path_, long long uid_, long long gid_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(chown)
+(long long res, void *path_, long long uid_, long long gid_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(break)(void *nsize_) { /* Nothing to do */ }
+POST_SYSCALL(break)(long long res, void *nsize_) { /* Nothing to do */ }
+PRE_SYSCALL(compat_20_getfsstat)
+(void *buf_, long long bufsize_, long long flags_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_20_getfsstat)
+(long long res, void *buf_, long long bufsize_, long long flags_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_olseek)
+(long long fd_, long long offset_, long long whence_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_olseek)
+(long long res, long long fd_, long long offset_, long long whence_) {
+ /* TODO */
+}
+PRE_SYSCALL(getpid)(void) { /* Nothing to do */ }
+POST_SYSCALL(getpid)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(compat_40_mount)
+(void *type_, void *path_, long long flags_, void *data_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_40_mount)
+(long long res, void *type_, void *path_, long long flags_, void *data_) {
+ /* TODO */
+}
+PRE_SYSCALL(unmount)(void *path_, long long flags_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(unmount)(long long res, void *path_, long long flags_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(setuid)(long long uid_) { /* Nothing to do */ }
+POST_SYSCALL(setuid)(long long res, long long uid_) { /* Nothing to do */ }
+PRE_SYSCALL(getuid)(void) { /* Nothing to do */ }
+POST_SYSCALL(getuid)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(geteuid)(void) { /* Nothing to do */ }
+POST_SYSCALL(geteuid)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(ptrace)
+(long long req_, long long pid_, void *addr_, long long data_) {
+ if (req_ == ptrace_pt_io) {
+ struct __sanitizer_ptrace_io_desc *addr =
+ (struct __sanitizer_ptrace_io_desc *)addr_;
+ PRE_READ(addr, struct_ptrace_ptrace_io_desc_struct_sz);
+ if (addr->piod_op == ptrace_piod_write_d ||
+ addr->piod_op == ptrace_piod_write_i) {
+ PRE_READ(addr->piod_addr, addr->piod_len);
+ }
+ if (addr->piod_op == ptrace_piod_read_d ||
+ addr->piod_op == ptrace_piod_read_i ||
+ addr->piod_op == ptrace_piod_read_auxv) {
+ PRE_WRITE(addr->piod_addr, addr->piod_len);
+ }
+ } else if (req_ == ptrace_pt_lwpinfo) {
+ struct __sanitizer_ptrace_lwpinfo *addr =
+ (struct __sanitizer_ptrace_lwpinfo *)addr_;
+ PRE_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t));
+ PRE_WRITE(addr, struct_ptrace_ptrace_lwpinfo_struct_sz);
+ } else if (req_ == ptrace_pt_set_event_mask) {
+ PRE_READ(addr_, struct_ptrace_ptrace_event_struct_sz);
+ } else if (req_ == ptrace_pt_get_event_mask) {
+ PRE_WRITE(addr_, struct_ptrace_ptrace_event_struct_sz);
+ } else if (req_ == ptrace_pt_set_siginfo) {
+ PRE_READ(addr_, struct_ptrace_ptrace_siginfo_struct_sz);
+ } else if (req_ == ptrace_pt_get_siginfo) {
+ PRE_WRITE(addr_, struct_ptrace_ptrace_siginfo_struct_sz);
+ } else if (req_ == ptrace_pt_lwpstatus) {
+ struct __sanitizer_ptrace_lwpstatus *addr =
+ (struct __sanitizer_ptrace_lwpstatus *)addr_;
+ PRE_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t));
+ PRE_WRITE(addr, struct_ptrace_ptrace_lwpstatus_struct_sz);
+ } else if (req_ == ptrace_pt_lwpnext) {
+ struct __sanitizer_ptrace_lwpstatus *addr =
+ (struct __sanitizer_ptrace_lwpstatus *)addr_;
+ PRE_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t));
+ PRE_WRITE(addr, struct_ptrace_ptrace_lwpstatus_struct_sz);
+ } else if (req_ == ptrace_pt_setregs) {
+ PRE_READ(addr_, struct_ptrace_reg_struct_sz);
+ } else if (req_ == ptrace_pt_getregs) {
+ PRE_WRITE(addr_, struct_ptrace_reg_struct_sz);
+ } else if (req_ == ptrace_pt_setfpregs) {
+ PRE_READ(addr_, struct_ptrace_fpreg_struct_sz);
+ } else if (req_ == ptrace_pt_getfpregs) {
+ PRE_WRITE(addr_, struct_ptrace_fpreg_struct_sz);
+ } else if (req_ == ptrace_pt_setdbregs) {
+ PRE_READ(addr_, struct_ptrace_dbreg_struct_sz);
+ } else if (req_ == ptrace_pt_getdbregs) {
+ PRE_WRITE(addr_, struct_ptrace_dbreg_struct_sz);
+ }
+}
+POST_SYSCALL(ptrace)
+(long long res, long long req_, long long pid_, void *addr_, long long data_) {
+ if (res == 0) {
+ if (req_ == ptrace_pt_io) {
+ struct __sanitizer_ptrace_io_desc *addr =
+ (struct __sanitizer_ptrace_io_desc *)addr_;
+ POST_READ(addr, struct_ptrace_ptrace_io_desc_struct_sz);
+ if (addr->piod_op == ptrace_piod_write_d ||
+ addr->piod_op == ptrace_piod_write_i) {
+ POST_READ(addr->piod_addr, addr->piod_len);
+ }
+ if (addr->piod_op == ptrace_piod_read_d ||
+ addr->piod_op == ptrace_piod_read_i ||
+ addr->piod_op == ptrace_piod_read_auxv) {
+ POST_WRITE(addr->piod_addr, addr->piod_len);
+ }
+ } else if (req_ == ptrace_pt_lwpinfo) {
+ struct __sanitizer_ptrace_lwpinfo *addr =
+ (struct __sanitizer_ptrace_lwpinfo *)addr_;
+ POST_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t));
+ POST_WRITE(addr, struct_ptrace_ptrace_lwpinfo_struct_sz);
+ } else if (req_ == ptrace_pt_set_event_mask) {
+ POST_READ(addr_, struct_ptrace_ptrace_event_struct_sz);
+ } else if (req_ == ptrace_pt_get_event_mask) {
+ POST_WRITE(addr_, struct_ptrace_ptrace_event_struct_sz);
+ } else if (req_ == ptrace_pt_set_siginfo) {
+ POST_READ(addr_, struct_ptrace_ptrace_siginfo_struct_sz);
+ } else if (req_ == ptrace_pt_get_siginfo) {
+ POST_WRITE(addr_, struct_ptrace_ptrace_siginfo_struct_sz);
+ } else if (req_ == ptrace_pt_lwpstatus) {
+ struct __sanitizer_ptrace_lwpstatus *addr =
+ (struct __sanitizer_ptrace_lwpstatus *)addr_;
+ POST_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t));
+ POST_WRITE(addr, struct_ptrace_ptrace_lwpstatus_struct_sz);
+ } else if (req_ == ptrace_pt_lwpnext) {
+ struct __sanitizer_ptrace_lwpstatus *addr =
+ (struct __sanitizer_ptrace_lwpstatus *)addr_;
+ POST_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t));
+ POST_WRITE(addr, struct_ptrace_ptrace_lwpstatus_struct_sz);
+ } else if (req_ == ptrace_pt_setregs) {
+ POST_READ(addr_, struct_ptrace_reg_struct_sz);
+ } else if (req_ == ptrace_pt_getregs) {
+ POST_WRITE(addr_, struct_ptrace_reg_struct_sz);
+ } else if (req_ == ptrace_pt_setfpregs) {
+ POST_READ(addr_, struct_ptrace_fpreg_struct_sz);
+ } else if (req_ == ptrace_pt_getfpregs) {
+ POST_WRITE(addr_, struct_ptrace_fpreg_struct_sz);
+ } else if (req_ == ptrace_pt_setdbregs) {
+ POST_READ(addr_, struct_ptrace_dbreg_struct_sz);
+ } else if (req_ == ptrace_pt_getdbregs) {
+ POST_WRITE(addr_, struct_ptrace_dbreg_struct_sz);
+ }
+ }
+}
+PRE_SYSCALL(recvmsg)(long long s_, void *msg_, long long flags_) {
+ PRE_WRITE(msg_, sizeof(__sanitizer_msghdr));
+}
+POST_SYSCALL(recvmsg)
+(long long res, long long s_, void *msg_, long long flags_) {
+ if (res > 0) {
+ POST_WRITE(msg_, sizeof(__sanitizer_msghdr));
+ }
+}
+PRE_SYSCALL(sendmsg)(long long s_, void *msg_, long long flags_) {
+ PRE_READ(msg_, sizeof(__sanitizer_msghdr));
+}
+POST_SYSCALL(sendmsg)
+(long long res, long long s_, void *msg_, long long flags_) {
+ if (res > 0) {
+ POST_READ(msg_, sizeof(__sanitizer_msghdr));
+ }
+}
+PRE_SYSCALL(recvfrom)
+(long long s_, void *buf_, long long len_, long long flags_, void *from_,
+ void *fromlenaddr_) {
+ PRE_WRITE(buf_, len_);
+ PRE_WRITE(from_, struct_sockaddr_sz);
+ PRE_WRITE(fromlenaddr_, sizeof(__sanitizer_socklen_t));
+}
+POST_SYSCALL(recvfrom)
+(long long res, long long s_, void *buf_, long long len_, long long flags_,
+ void *from_, void *fromlenaddr_) {
+ if (res >= 0) {
+ POST_WRITE(buf_, res);
+ POST_WRITE(from_, struct_sockaddr_sz);
+ POST_WRITE(fromlenaddr_, sizeof(__sanitizer_socklen_t));
+ }
+}
+PRE_SYSCALL(accept)(long long s_, void *name_, void *anamelen_) {
+ PRE_WRITE(name_, struct_sockaddr_sz);
+ PRE_WRITE(anamelen_, sizeof(__sanitizer_socklen_t));
+}
+POST_SYSCALL(accept)
+(long long res, long long s_, void *name_, void *anamelen_) {
+ if (res == 0) {
+ POST_WRITE(name_, struct_sockaddr_sz);
+ POST_WRITE(anamelen_, sizeof(__sanitizer_socklen_t));
+ }
+}
+PRE_SYSCALL(getpeername)(long long fdes_, void *asa_, void *alen_) {
+ PRE_WRITE(asa_, struct_sockaddr_sz);
+ PRE_WRITE(alen_, sizeof(__sanitizer_socklen_t));
+}
+POST_SYSCALL(getpeername)
+(long long res, long long fdes_, void *asa_, void *alen_) {
+ if (res == 0) {
+ POST_WRITE(asa_, struct_sockaddr_sz);
+ POST_WRITE(alen_, sizeof(__sanitizer_socklen_t));
+ }
+}
+PRE_SYSCALL(getsockname)(long long fdes_, void *asa_, void *alen_) {
+ PRE_WRITE(asa_, struct_sockaddr_sz);
+ PRE_WRITE(alen_, sizeof(__sanitizer_socklen_t));
+}
+POST_SYSCALL(getsockname)
+(long long res, long long fdes_, void *asa_, void *alen_) {
+ if (res == 0) {
+ POST_WRITE(asa_, struct_sockaddr_sz);
+ POST_WRITE(alen_, sizeof(__sanitizer_socklen_t));
+ }
+}
+PRE_SYSCALL(access)(void *path_, long long flags_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(access)(long long res, void *path_, long long flags_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(chflags)(void *path_, long long flags_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(chflags)(long long res, void *path_, long long flags_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(fchflags)(long long fd_, long long flags_) { /* Nothing to do */ }
+POST_SYSCALL(fchflags)(long long res, long long fd_, long long flags_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(sync)(void) { /* Nothing to do */ }
+POST_SYSCALL(sync)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(kill)(long long pid_, long long signum_) { /* Nothing to do */ }
+POST_SYSCALL(kill)(long long res, long long pid_, long long signum_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_43_stat43)(void *path_, void *ub_) { /* TODO */ }
+POST_SYSCALL(compat_43_stat43)(long long res, void *path_, void *ub_) {
+ /* TODO */
+}
+PRE_SYSCALL(getppid)(void) { /* Nothing to do */ }
+POST_SYSCALL(getppid)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(compat_43_lstat43)(void *path_, void *ub_) { /* TODO */ }
+POST_SYSCALL(compat_43_lstat43)(long long res, void *path_, void *ub_) {
+ /* TODO */
+}
+PRE_SYSCALL(dup)(long long fd_) { /* Nothing to do */ }
+POST_SYSCALL(dup)(long long res, long long fd_) { /* Nothing to do */ }
+PRE_SYSCALL(pipe)(void) {
+ /* pipe returns two descriptors through two returned values */
+}
+POST_SYSCALL(pipe)(long long res) {
+ /* pipe returns two descriptors through two returned values */
+}
+PRE_SYSCALL(getegid)(void) { /* Nothing to do */ }
+POST_SYSCALL(getegid)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(profil)
+(void *samples_, long long size_, long long offset_, long long scale_) {
+ if (samples_) {
+ PRE_WRITE(samples_, size_);
+ }
+}
+POST_SYSCALL(profil)
+(long long res, void *samples_, long long size_, long long offset_,
+ long long scale_) {
+ if (res == 0) {
+ if (samples_) {
+ POST_WRITE(samples_, size_);
+ }
+ }
+}
+PRE_SYSCALL(ktrace)
+(void *fname_, long long ops_, long long facs_, long long pid_) {
+ const char *fname = (const char *)fname_;
+ if (fname) {
+ PRE_READ(fname, __sanitizer::internal_strlen(fname) + 1);
+ }
+}
+POST_SYSCALL(ktrace)
+(long long res, void *fname_, long long ops_, long long facs_, long long pid_) {
+ const char *fname = (const char *)fname_;
+ if (res == 0) {
+ if (fname) {
+ POST_READ(fname, __sanitizer::internal_strlen(fname) + 1);
+ }
+ }
+}
+PRE_SYSCALL(compat_13_sigaction13)(long long signum_, void *nsa_, void *osa_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_13_sigaction13)
+(long long res, long long signum_, void *nsa_, void *osa_) {
+ /* TODO */
+}
+PRE_SYSCALL(getgid)(void) { /* Nothing to do */ }
+POST_SYSCALL(getgid)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(compat_13_sigprocmask13)(long long how_, long long mask_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_13_sigprocmask13)
+(long long res, long long how_, long long mask_) {
+ /* TODO */
+}
+PRE_SYSCALL(__getlogin)(void *namebuf_, long long namelen_) {
+ if (namebuf_) {
+ PRE_WRITE(namebuf_, namelen_);
+ }
+}
+POST_SYSCALL(__getlogin)(long long res, void *namebuf_, long long namelen_) {
+ if (res == 0) {
+ if (namebuf_) {
+ POST_WRITE(namebuf_, namelen_);
+ }
+ }
+}
+PRE_SYSCALL(__setlogin)(void *namebuf_) {
+ const char *namebuf = (const char *)namebuf_;
+ if (namebuf) {
+ PRE_READ(namebuf, __sanitizer::internal_strlen(namebuf) + 1);
+ }
+}
+POST_SYSCALL(__setlogin)(long long res, void *namebuf_) {
+ if (res == 0) {
+ const char *namebuf = (const char *)namebuf_;
+ if (namebuf) {
+ POST_READ(namebuf, __sanitizer::internal_strlen(namebuf) + 1);
+ }
+ }
+}
+PRE_SYSCALL(acct)(void *path_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(acct)(long long res, void *path_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(compat_13_sigpending13)(void) { /* TODO */ }
+POST_SYSCALL(compat_13_sigpending13)(long long res) { /* TODO */ }
+PRE_SYSCALL(compat_13_sigaltstack13)(void *nss_, void *oss_) { /* TODO */ }
+POST_SYSCALL(compat_13_sigaltstack13)(long long res, void *nss_, void *oss_) {
+ /* TODO */
+}
+PRE_SYSCALL(ioctl)(long long fd_, long long com_, void *data_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(ioctl)(long long res, long long fd_, long long com_, void *data_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_12_oreboot)(long long opt_) { /* TODO */ }
+POST_SYSCALL(compat_12_oreboot)(long long res, long long opt_) { /* TODO */ }
+PRE_SYSCALL(revoke)(void *path_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(revoke)(long long res, void *path_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(symlink)(void *path_, void *link_) {
+ const char *path = (const char *)path_;
+ const char *link = (const char *)link_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (link) {
+ PRE_READ(link, __sanitizer::internal_strlen(link) + 1);
+ }
+}
+POST_SYSCALL(symlink)(long long res, void *path_, void *link_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ const char *link = (const char *)link_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (link) {
+ POST_READ(link, __sanitizer::internal_strlen(link) + 1);
+ }
+ }
+}
+PRE_SYSCALL(readlink)(void *path_, void *buf_, long long count_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (buf_) {
+ PRE_WRITE(buf_, count_);
+ }
+}
+POST_SYSCALL(readlink)
+(long long res, void *path_, void *buf_, long long count_) {
+ if (res > 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (buf_) {
+ PRE_WRITE(buf_, res);
+ }
+ }
+}
+PRE_SYSCALL(execve)(void *path_, void *argp_, void *envp_) {
+ const char *path = (const char *)path_;
+ char **argp = (char **)argp_;
+ char **envp = (char **)envp_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (argp && argp[0]) {
+ char *a = argp[0];
+ while (a++) {
+ PRE_READ(a, __sanitizer::internal_strlen(a) + 1);
+ }
+ }
+ if (envp && envp[0]) {
+ char *e = envp[0];
+ while (e++) {
+ PRE_READ(e, __sanitizer::internal_strlen(e) + 1);
+ }
+ }
+}
+POST_SYSCALL(execve)(long long res, void *path_, void *argp_, void *envp_) {
+ /* If we are here, something went wrong */
+ const char *path = (const char *)path_;
+ char **argp = (char **)argp_;
+ char **envp = (char **)envp_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (argp && argp[0]) {
+ char *a = argp[0];
+ while (a++) {
+ POST_READ(a, __sanitizer::internal_strlen(a) + 1);
+ }
+ }
+ if (envp && envp[0]) {
+ char *e = envp[0];
+ while (e++) {
+ POST_READ(e, __sanitizer::internal_strlen(e) + 1);
+ }
+ }
+}
+PRE_SYSCALL(umask)(long long newmask_) { /* Nothing to do */ }
+POST_SYSCALL(umask)(long long res, long long newmask_) { /* Nothing to do */ }
+PRE_SYSCALL(chroot)(void *path_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(chroot)(long long res, void *path_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(compat_43_fstat43)(long long fd_, void *sb_) { /* TODO */ }
+POST_SYSCALL(compat_43_fstat43)(long long res, long long fd_, void *sb_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_ogetkerninfo)
+(long long op_, void *where_, void *size_, long long arg_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_ogetkerninfo)
+(long long res, long long op_, void *where_, void *size_, long long arg_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_ogetpagesize)(void) { /* TODO */ }
+POST_SYSCALL(compat_43_ogetpagesize)(long long res) { /* TODO */ }
+PRE_SYSCALL(compat_12_msync)(void *addr_, long long len_) { /* TODO */ }
+POST_SYSCALL(compat_12_msync)(long long res, void *addr_, long long len_) {
+ /* TODO */
+}
+PRE_SYSCALL(vfork)(void) { /* Nothing to do */ }
+POST_SYSCALL(vfork)(long long res) { /* Nothing to do */ }
+/* syscall 67 has been skipped */
+/* syscall 68 has been skipped */
+/* syscall 69 has been skipped */
+/* syscall 70 has been skipped */
+PRE_SYSCALL(compat_43_ommap)
+(void *addr_, long long len_, long long prot_, long long flags_, long long fd_,
+ long long pos_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_ommap)
+(long long res, void *addr_, long long len_, long long prot_, long long flags_,
+ long long fd_, long long pos_) {
+ /* TODO */
+}
+PRE_SYSCALL(vadvise)(long long anom_) { /* Nothing to do */ }
+POST_SYSCALL(vadvise)(long long res, long long anom_) { /* Nothing to do */ }
+PRE_SYSCALL(munmap)(void *addr_, long long len_) { /* Nothing to do */ }
+POST_SYSCALL(munmap)(long long res, void *addr_, long long len_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(mprotect)(void *addr_, long long len_, long long prot_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(mprotect)
+(long long res, void *addr_, long long len_, long long prot_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(madvise)(void *addr_, long long len_, long long behav_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(madvise)
+(long long res, void *addr_, long long len_, long long behav_) {
+ /* Nothing to do */
+}
+/* syscall 76 has been skipped */
+/* syscall 77 has been skipped */
+PRE_SYSCALL(mincore)(void *addr_, long long len_, void *vec_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(mincore)(long long res, void *addr_, long long len_, void *vec_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(getgroups)(long long gidsetsize_, void *gidset_) {
+ unsigned int *gidset = (unsigned int *)gidset_;
+ if (gidset) {
+ PRE_WRITE(gidset, sizeof(*gidset) * gidsetsize_);
+ }
+}
+POST_SYSCALL(getgroups)(long long res, long long gidsetsize_, void *gidset_) {
+ if (res == 0) {
+ unsigned int *gidset = (unsigned int *)gidset_;
+ if (gidset) {
+ POST_WRITE(gidset, sizeof(*gidset) * gidsetsize_);
+ }
+ }
+}
+PRE_SYSCALL(setgroups)(long long gidsetsize_, void *gidset_) {
+ unsigned int *gidset = (unsigned int *)gidset_;
+ if (gidset) {
+ PRE_READ(gidset, sizeof(*gidset) * gidsetsize_);
+ }
+}
+POST_SYSCALL(setgroups)(long long res, long long gidsetsize_, void *gidset_) {
+ if (res == 0) {
+ unsigned int *gidset = (unsigned int *)gidset_;
+ if (gidset) {
+ POST_READ(gidset, sizeof(*gidset) * gidsetsize_);
+ }
+ }
+}
+PRE_SYSCALL(getpgrp)(void) { /* Nothing to do */ }
+POST_SYSCALL(getpgrp)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(setpgid)(long long pid_, long long pgid_) { /* Nothing to do */ }
+POST_SYSCALL(setpgid)(long long res, long long pid_, long long pgid_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_50_setitimer)(long long which_, void *itv_, void *oitv_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_setitimer)
+(long long res, long long which_, void *itv_, void *oitv_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_owait)(void) { /* TODO */ }
+POST_SYSCALL(compat_43_owait)(long long res) { /* TODO */ }
+PRE_SYSCALL(compat_12_oswapon)(void *name_) { /* TODO */ }
+POST_SYSCALL(compat_12_oswapon)(long long res, void *name_) { /* TODO */ }
+PRE_SYSCALL(compat_50_getitimer)(long long which_, void *itv_) { /* TODO */ }
+POST_SYSCALL(compat_50_getitimer)(long long res, long long which_, void *itv_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_ogethostname)(void *hostname_, long long len_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_ogethostname)
+(long long res, void *hostname_, long long len_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_osethostname)(void *hostname_, long long len_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_osethostname)
+(long long res, void *hostname_, long long len_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_ogetdtablesize)(void) { /* TODO */ }
+POST_SYSCALL(compat_43_ogetdtablesize)(long long res) { /* TODO */ }
+PRE_SYSCALL(dup2)(long long from_, long long to_) { /* Nothing to do */ }
+POST_SYSCALL(dup2)(long long res, long long from_, long long to_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(getrandom)(void *buf_, long long buflen_, long long flags_) {
+ /* TODO */
+}
+POST_SYSCALL(getrandom)
+(long long res, void *buf_, long long buflen_, long long flags_) {
+ /* TODO */
+}
+PRE_SYSCALL(fcntl)(long long fd_, long long cmd_, void *arg_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(fcntl)(long long res, long long fd_, long long cmd_, void *arg_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_50_select)
+(long long nd_, void *in_, void *ou_, void *ex_, void *tv_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_select)
+(long long res, long long nd_, void *in_, void *ou_, void *ex_, void *tv_) {
+ /* TODO */
+}
+/* syscall 94 has been skipped */
+PRE_SYSCALL(fsync)(long long fd_) { /* Nothing to do */ }
+POST_SYSCALL(fsync)(long long res, long long fd_) { /* Nothing to do */ }
+PRE_SYSCALL(setpriority)(long long which_, long long who_, long long prio_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(setpriority)
+(long long res, long long which_, long long who_, long long prio_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_30_socket)
+(long long domain_, long long type_, long long protocol_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_30_socket)
+(long long res, long long domain_, long long type_, long long protocol_) {
+ /* TODO */
+}
+PRE_SYSCALL(connect)(long long s_, void *name_, long long namelen_) {
+ PRE_READ(name_, namelen_);
+}
+POST_SYSCALL(connect)
+(long long res, long long s_, void *name_, long long namelen_) {
+ if (res == 0) {
+ POST_READ(name_, namelen_);
+ }
+}
+PRE_SYSCALL(compat_43_oaccept)(long long s_, void *name_, void *anamelen_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_oaccept)
+(long long res, long long s_, void *name_, void *anamelen_) {
+ /* TODO */
+}
+PRE_SYSCALL(getpriority)(long long which_, long long who_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(getpriority)(long long res, long long which_, long long who_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_43_osend)
+(long long s_, void *buf_, long long len_, long long flags_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_osend)
+(long long res, long long s_, void *buf_, long long len_, long long flags_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_orecv)
+(long long s_, void *buf_, long long len_, long long flags_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_orecv)
+(long long res, long long s_, void *buf_, long long len_, long long flags_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_13_sigreturn13)(void *sigcntxp_) { /* TODO */ }
+POST_SYSCALL(compat_13_sigreturn13)(long long res, void *sigcntxp_) {
+ /* TODO */
+}
+PRE_SYSCALL(bind)(long long s_, void *name_, long long namelen_) {
+ PRE_READ(name_, namelen_);
+}
+POST_SYSCALL(bind)
+(long long res, long long s_, void *name_, long long namelen_) {
+ if (res == 0) {
+ PRE_READ(name_, namelen_);
+ }
+}
+PRE_SYSCALL(setsockopt)
+(long long s_, long long level_, long long name_, void *val_,
+ long long valsize_) {
+ if (val_) {
+ PRE_READ(val_, valsize_);
+ }
+}
+POST_SYSCALL(setsockopt)
+(long long res, long long s_, long long level_, long long name_, void *val_,
+ long long valsize_) {
+ if (res == 0) {
+ if (val_) {
+ POST_READ(val_, valsize_);
+ }
+ }
+}
+PRE_SYSCALL(listen)(long long s_, long long backlog_) { /* Nothing to do */ }
+POST_SYSCALL(listen)(long long res, long long s_, long long backlog_) {
+ /* Nothing to do */
+}
+/* syscall 107 has been skipped */
+PRE_SYSCALL(compat_43_osigvec)(long long signum_, void *nsv_, void *osv_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_osigvec)
+(long long res, long long signum_, void *nsv_, void *osv_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_osigblock)(long long mask_) { /* TODO */ }
+POST_SYSCALL(compat_43_osigblock)(long long res, long long mask_) { /* TODO */ }
+PRE_SYSCALL(compat_43_osigsetmask)(long long mask_) { /* TODO */ }
+POST_SYSCALL(compat_43_osigsetmask)(long long res, long long mask_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_13_sigsuspend13)(long long mask_) { /* TODO */ }
+POST_SYSCALL(compat_13_sigsuspend13)(long long res, long long mask_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_osigstack)(void *nss_, void *oss_) { /* TODO */ }
+POST_SYSCALL(compat_43_osigstack)(long long res, void *nss_, void *oss_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_orecvmsg)(long long s_, void *msg_, long long flags_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_orecvmsg)
+(long long res, long long s_, void *msg_, long long flags_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_osendmsg)(long long s_, void *msg_, long long flags_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_osendmsg)
+(long long res, long long s_, void *msg_, long long flags_) {
+ /* TODO */
+}
+/* syscall 115 has been skipped */
+PRE_SYSCALL(compat_50_gettimeofday)(void *tp_, void *tzp_) { /* TODO */ }
+POST_SYSCALL(compat_50_gettimeofday)(long long res, void *tp_, void *tzp_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50_getrusage)(long long who_, void *rusage_) { /* TODO */ }
+POST_SYSCALL(compat_50_getrusage)
+(long long res, long long who_, void *rusage_) {
+ /* TODO */
+}
+PRE_SYSCALL(getsockopt)
+(long long s_, long long level_, long long name_, void *val_, void *avalsize_) {
+ /* TODO */
+}
+POST_SYSCALL(getsockopt)
+(long long res, long long s_, long long level_, long long name_, void *val_,
+ void *avalsize_) {
+ /* TODO */
+}
+/* syscall 119 has been skipped */
+PRE_SYSCALL(readv)(long long fd_, void *iovp_, long long iovcnt_) {
+ struct __sanitizer_iovec *iovp = (struct __sanitizer_iovec *)iovp_;
+ int i;
+ if (iovp) {
+ PRE_READ(iovp, sizeof(struct __sanitizer_iovec) * iovcnt_);
+ for (i = 0; i < iovcnt_; i++) {
+ PRE_WRITE(iovp[i].iov_base, iovp[i].iov_len);
+ }
+ }
+}
+POST_SYSCALL(readv)
+(long long res, long long fd_, void *iovp_, long long iovcnt_) {
+ struct __sanitizer_iovec *iovp = (struct __sanitizer_iovec *)iovp_;
+ int i;
+ uptr m, n = res;
+ if (res > 0) {
+ if (iovp) {
+ POST_READ(iovp, sizeof(struct __sanitizer_iovec) * iovcnt_);
+ for (i = 0; i < iovcnt_ && n > 0; i++) {
+ m = n > iovp[i].iov_len ? iovp[i].iov_len : n;
+ POST_WRITE(iovp[i].iov_base, m);
+ n -= m;
+ }
+ }
+ }
+}
+PRE_SYSCALL(writev)(long long fd_, void *iovp_, long long iovcnt_) {
+ struct __sanitizer_iovec *iovp = (struct __sanitizer_iovec *)iovp_;
+ int i;
+ if (iovp) {
+ PRE_READ(iovp, sizeof(struct __sanitizer_iovec) * iovcnt_);
+ for (i = 0; i < iovcnt_; i++) {
+ PRE_READ(iovp[i].iov_base, iovp[i].iov_len);
+ }
+ }
+}
+POST_SYSCALL(writev)
+(long long res, long long fd_, void *iovp_, long long iovcnt_) {
+ struct __sanitizer_iovec *iovp = (struct __sanitizer_iovec *)iovp_;
+ int i;
+ uptr m, n = res;
+ if (res > 0) {
+ if (iovp) {
+ POST_READ(iovp, sizeof(struct __sanitizer_iovec) * iovcnt_);
+ for (i = 0; i < iovcnt_ && n > 0; i++) {
+ m = n > iovp[i].iov_len ? iovp[i].iov_len : n;
+ POST_READ(iovp[i].iov_base, m);
+ n -= m;
+ }
+ }
+ }
+}
+PRE_SYSCALL(compat_50_settimeofday)(void *tv_, void *tzp_) { /* TODO */ }
+POST_SYSCALL(compat_50_settimeofday)(long long res, void *tv_, void *tzp_) {
+ /* TODO */
+}
+PRE_SYSCALL(fchown)(long long fd_, long long uid_, long long gid_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(fchown)
+(long long res, long long fd_, long long uid_, long long gid_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(fchmod)(long long fd_, long long mode_) { /* Nothing to do */ }
+POST_SYSCALL(fchmod)(long long res, long long fd_, long long mode_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_43_orecvfrom)
+(long long s_, void *buf_, long long len_, long long flags_, void *from_,
+ void *fromlenaddr_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_orecvfrom)
+(long long res, long long s_, void *buf_, long long len_, long long flags_,
+ void *from_, void *fromlenaddr_) {
+ /* TODO */
+}
+PRE_SYSCALL(setreuid)(long long ruid_, long long euid_) { /* Nothing to do */ }
+POST_SYSCALL(setreuid)(long long res, long long ruid_, long long euid_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(setregid)(long long rgid_, long long egid_) { /* Nothing to do */ }
+POST_SYSCALL(setregid)(long long res, long long rgid_, long long egid_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(rename)(void *from_, void *to_) {
+ const char *from = (const char *)from_;
+ const char *to = (const char *)to_;
+ if (from) {
+ PRE_READ(from, __sanitizer::internal_strlen(from) + 1);
+ }
+ if (to) {
+ PRE_READ(to, __sanitizer::internal_strlen(to) + 1);
+ }
+}
+POST_SYSCALL(rename)(long long res, void *from_, void *to_) {
+ if (res == 0) {
+ const char *from = (const char *)from_;
+ const char *to = (const char *)to_;
+ if (from) {
+ POST_READ(from, __sanitizer::internal_strlen(from) + 1);
+ }
+ if (to) {
+ POST_READ(to, __sanitizer::internal_strlen(to) + 1);
+ }
+ }
+}
+PRE_SYSCALL(compat_43_otruncate)(void *path_, long long length_) { /* TODO */ }
+POST_SYSCALL(compat_43_otruncate)
+(long long res, void *path_, long long length_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_oftruncate)(long long fd_, long long length_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_oftruncate)
+(long long res, long long fd_, long long length_) {
+ /* TODO */
+}
+PRE_SYSCALL(flock)(long long fd_, long long how_) { /* Nothing to do */ }
+POST_SYSCALL(flock)(long long res, long long fd_, long long how_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(mkfifo)(void *path_, long long mode_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(mkfifo)(long long res, void *path_, long long mode_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(sendto)
+(long long s_, void *buf_, long long len_, long long flags_, void *to_,
+ long long tolen_) {
+ PRE_READ(buf_, len_);
+ PRE_READ(to_, tolen_);
+}
+POST_SYSCALL(sendto)
+(long long res, long long s_, void *buf_, long long len_, long long flags_,
+ void *to_, long long tolen_) {
+ if (res >= 0) {
+ POST_READ(buf_, len_);
+ POST_READ(to_, tolen_);
+ }
+}
+PRE_SYSCALL(shutdown)(long long s_, long long how_) { /* Nothing to do */ }
+POST_SYSCALL(shutdown)(long long res, long long s_, long long how_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(socketpair)
+(long long domain_, long long type_, long long protocol_, void *rsv_) {
+ PRE_WRITE(rsv_, 2 * sizeof(int));
+}
+POST_SYSCALL(socketpair)
+(long long res, long long domain_, long long type_, long long protocol_,
+ void *rsv_) {
+ if (res == 0) {
+ POST_WRITE(rsv_, 2 * sizeof(int));
+ }
+}
+PRE_SYSCALL(mkdir)(void *path_, long long mode_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(mkdir)(long long res, void *path_, long long mode_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(rmdir)(void *path_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(rmdir)(long long res, void *path_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(compat_50_utimes)(void *path_, void *tptr_) { /* TODO */ }
+POST_SYSCALL(compat_50_utimes)(long long res, void *path_, void *tptr_) {
+ /* TODO */
+}
+/* syscall 139 has been skipped */
+PRE_SYSCALL(compat_50_adjtime)(void *delta_, void *olddelta_) { /* TODO */ }
+POST_SYSCALL(compat_50_adjtime)(long long res, void *delta_, void *olddelta_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_ogetpeername)(long long fdes_, void *asa_, void *alen_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_ogetpeername)
+(long long res, long long fdes_, void *asa_, void *alen_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_ogethostid)(void) { /* TODO */ }
+POST_SYSCALL(compat_43_ogethostid)(long long res) { /* TODO */ }
+PRE_SYSCALL(compat_43_osethostid)(long long hostid_) { /* TODO */ }
+POST_SYSCALL(compat_43_osethostid)(long long res, long long hostid_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_ogetrlimit)(long long which_, void *rlp_) { /* TODO */ }
+POST_SYSCALL(compat_43_ogetrlimit)
+(long long res, long long which_, void *rlp_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_osetrlimit)(long long which_, void *rlp_) { /* TODO */ }
+POST_SYSCALL(compat_43_osetrlimit)
+(long long res, long long which_, void *rlp_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_okillpg)(long long pgid_, long long signum_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_okillpg)
+(long long res, long long pgid_, long long signum_) {
+ /* TODO */
+}
+PRE_SYSCALL(setsid)(void) { /* Nothing to do */ }
+POST_SYSCALL(setsid)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(compat_50_quotactl)
+(void *path_, long long cmd_, long long uid_, void *arg_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_quotactl)
+(long long res, void *path_, long long cmd_, long long uid_, void *arg_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_43_oquota)(void) { /* TODO */ }
+POST_SYSCALL(compat_43_oquota)(long long res) { /* TODO */ }
+PRE_SYSCALL(compat_43_ogetsockname)(long long fdec_, void *asa_, void *alen_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_ogetsockname)
+(long long res, long long fdec_, void *asa_, void *alen_) {
+ /* TODO */
+}
+/* syscall 151 has been skipped */
+/* syscall 152 has been skipped */
+/* syscall 153 has been skipped */
+/* syscall 154 has been skipped */
+PRE_SYSCALL(nfssvc)(long long flag_, void *argp_) { /* Nothing to do */ }
+POST_SYSCALL(nfssvc)(long long res, long long flag_, void *argp_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_43_ogetdirentries)
+(long long fd_, void *buf_, long long count_, void *basep_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_43_ogetdirentries)
+(long long res, long long fd_, void *buf_, long long count_, void *basep_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_20_statfs)(void *path_, void *buf_) { /* TODO */ }
+POST_SYSCALL(compat_20_statfs)(long long res, void *path_, void *buf_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_20_fstatfs)(long long fd_, void *buf_) { /* TODO */ }
+POST_SYSCALL(compat_20_fstatfs)(long long res, long long fd_, void *buf_) {
+ /* TODO */
+}
+/* syscall 159 has been skipped */
+/* syscall 160 has been skipped */
+PRE_SYSCALL(compat_30_getfh)(void *fname_, void *fhp_) { /* TODO */ }
+POST_SYSCALL(compat_30_getfh)(long long res, void *fname_, void *fhp_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_09_ogetdomainname)(void *domainname_, long long len_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_09_ogetdomainname)
+(long long res, void *domainname_, long long len_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_09_osetdomainname)(void *domainname_, long long len_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_09_osetdomainname)
+(long long res, void *domainname_, long long len_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_09_ouname)(void *name_) { /* TODO */ }
+POST_SYSCALL(compat_09_ouname)(long long res, void *name_) { /* TODO */ }
+PRE_SYSCALL(sysarch)(long long op_, void *parms_) { /* TODO */ }
+POST_SYSCALL(sysarch)(long long res, long long op_, void *parms_) { /* TODO */ }
+PRE_SYSCALL(__futex)
+(void *uaddr_, long long op_, long long val_, void *timeout_, void *uaddr2_,
+ long long val2_, long long val3_) {
+ /* TODO */
+}
+POST_SYSCALL(__futex)
+(long long res, void *uaddr_, long long op_, long long val_, void *timeout_,
+ void *uaddr2_, long long val2_, long long val3_) {
+ /* TODO */
+}
+PRE_SYSCALL(__futex_set_robust_list)(void *head_, long long len_) { /* TODO */ }
+POST_SYSCALL(__futex_set_robust_list)
+(long long res, void *head_, long long len_) {
+ /* TODO */
+}
+PRE_SYSCALL(__futex_get_robust_list)
+(long long lwpid_, void **headp_, void *lenp_) {
+ /* TODO */
+}
+POST_SYSCALL(__futex_get_robust_list)
+(long long res, long long lwpid_, void **headp_, void *lenp_) {
+ /* TODO */
+}
+#if !defined(_LP64)
+PRE_SYSCALL(compat_10_osemsys)
+(long long which_, long long a2_, long long a3_, long long a4_, long long a5_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_10_osemsys)
+(long long res, long long which_, long long a2_, long long a3_, long long a4_,
+ long long a5_) {
+ /* TODO */
+}
+#else
+/* syscall 169 has been skipped */
+#endif
+#if !defined(_LP64)
+PRE_SYSCALL(compat_10_omsgsys)
+(long long which_, long long a2_, long long a3_, long long a4_, long long a5_,
+ long long a6_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_10_omsgsys)
+(long long res, long long which_, long long a2_, long long a3_, long long a4_,
+ long long a5_, long long a6_) {
+ /* TODO */
+}
+#else
+/* syscall 170 has been skipped */
+#endif
+#if !defined(_LP64)
+PRE_SYSCALL(compat_10_oshmsys)
+(long long which_, long long a2_, long long a3_, long long a4_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_10_oshmsys)
+(long long res, long long which_, long long a2_, long long a3_, long long a4_) {
+ /* TODO */
+}
+#else
+/* syscall 171 has been skipped */
+#endif
+/* syscall 172 has been skipped */
+PRE_SYSCALL(pread)
+(long long fd_, void *buf_, long long nbyte_, long long PAD_,
+ long long offset_) {
+ if (buf_) {
+ PRE_WRITE(buf_, nbyte_);
+ }
+}
+POST_SYSCALL(pread)
+(long long res, long long fd_, void *buf_, long long nbyte_, long long PAD_,
+ long long offset_) {
+ if (res > 0) {
+ POST_WRITE(buf_, res);
+ }
+}
+PRE_SYSCALL(pwrite)
+(long long fd_, void *buf_, long long nbyte_, long long PAD_,
+ long long offset_) {
+ if (buf_) {
+ PRE_READ(buf_, nbyte_);
+ }
+}
+POST_SYSCALL(pwrite)
+(long long res, long long fd_, void *buf_, long long nbyte_, long long PAD_,
+ long long offset_) {
+ if (res > 0) {
+ POST_READ(buf_, res);
+ }
+}
+PRE_SYSCALL(compat_30_ntp_gettime)(void *ntvp_) { /* TODO */ }
+POST_SYSCALL(compat_30_ntp_gettime)(long long res, void *ntvp_) { /* TODO */ }
+#if defined(NTP) || !defined(_KERNEL_OPT)
+PRE_SYSCALL(ntp_adjtime)(void *tp_) { /* Nothing to do */ }
+POST_SYSCALL(ntp_adjtime)(long long res, void *tp_) { /* Nothing to do */ }
+#else
+/* syscall 176 has been skipped */
+#endif
+/* syscall 177 has been skipped */
+/* syscall 178 has been skipped */
+/* syscall 179 has been skipped */
+/* syscall 180 has been skipped */
+PRE_SYSCALL(setgid)(long long gid_) { /* Nothing to do */ }
+POST_SYSCALL(setgid)(long long res, long long gid_) { /* Nothing to do */ }
+PRE_SYSCALL(setegid)(long long egid_) { /* Nothing to do */ }
+POST_SYSCALL(setegid)(long long res, long long egid_) { /* Nothing to do */ }
+PRE_SYSCALL(seteuid)(long long euid_) { /* Nothing to do */ }
+POST_SYSCALL(seteuid)(long long res, long long euid_) { /* Nothing to do */ }
+PRE_SYSCALL(lfs_bmapv)(void *fsidp_, void *blkiov_, long long blkcnt_) {
+ /* TODO */
+}
+POST_SYSCALL(lfs_bmapv)
+(long long res, void *fsidp_, void *blkiov_, long long blkcnt_) {
+ /* TODO */
+}
+PRE_SYSCALL(lfs_markv)(void *fsidp_, void *blkiov_, long long blkcnt_) {
+ /* TODO */
+}
+POST_SYSCALL(lfs_markv)
+(long long res, void *fsidp_, void *blkiov_, long long blkcnt_) {
+ /* TODO */
+}
+PRE_SYSCALL(lfs_segclean)(void *fsidp_, long long segment_) { /* TODO */ }
+POST_SYSCALL(lfs_segclean)(long long res, void *fsidp_, long long segment_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50_lfs_segwait)(void *fsidp_, void *tv_) { /* TODO */ }
+POST_SYSCALL(compat_50_lfs_segwait)(long long res, void *fsidp_, void *tv_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_12_stat12)(void *path_, void *ub_) { /* TODO */ }
+POST_SYSCALL(compat_12_stat12)(long long res, void *path_, void *ub_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_12_fstat12)(long long fd_, void *sb_) { /* TODO */ }
+POST_SYSCALL(compat_12_fstat12)(long long res, long long fd_, void *sb_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_12_lstat12)(void *path_, void *ub_) { /* TODO */ }
+POST_SYSCALL(compat_12_lstat12)(long long res, void *path_, void *ub_) {
+ /* TODO */
+}
+PRE_SYSCALL(pathconf)(void *path_, long long name_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(pathconf)(long long res, void *path_, long long name_) {
+ if (res != -1) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(fpathconf)(long long fd_, long long name_) { /* Nothing to do */ }
+POST_SYSCALL(fpathconf)(long long res, long long fd_, long long name_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(getsockopt2)
+(long long s_, long long level_, long long name_, void *val_, void *avalsize_) {
+ /* TODO */
+}
+POST_SYSCALL(getsockopt2)
+(long long res, long long s_, long long level_, long long name_, void *val_,
+ void *avalsize_) {
+ /* TODO */
+}
+PRE_SYSCALL(getrlimit)(long long which_, void *rlp_) {
+ PRE_WRITE(rlp_, struct_rlimit_sz);
+}
+POST_SYSCALL(getrlimit)(long long res, long long which_, void *rlp_) {
+ if (res == 0) {
+ POST_WRITE(rlp_, struct_rlimit_sz);
+ }
+}
+PRE_SYSCALL(setrlimit)(long long which_, void *rlp_) {
+ PRE_READ(rlp_, struct_rlimit_sz);
+}
+POST_SYSCALL(setrlimit)(long long res, long long which_, void *rlp_) {
+ if (res == 0) {
+ POST_READ(rlp_, struct_rlimit_sz);
+ }
+}
+PRE_SYSCALL(compat_12_getdirentries)
+(long long fd_, void *buf_, long long count_, void *basep_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_12_getdirentries)
+(long long res, long long fd_, void *buf_, long long count_, void *basep_) {
+ /* TODO */
+}
+PRE_SYSCALL(mmap)
+(void *addr_, long long len_, long long prot_, long long flags_, long long fd_,
+ long long PAD_, long long pos_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(mmap)
+(long long res, void *addr_, long long len_, long long prot_, long long flags_,
+ long long fd_, long long PAD_, long long pos_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__syscall)(long long code_, long long args_[SYS_MAXSYSARGS]) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__syscall)
+(long long res, long long code_, long long args_[SYS_MAXSYSARGS]) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(lseek)
+(long long fd_, long long PAD_, long long offset_, long long whence_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(lseek)
+(long long res, long long fd_, long long PAD_, long long offset_,
+ long long whence_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(truncate)(void *path_, long long PAD_, long long length_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(truncate)
+(long long res, void *path_, long long PAD_, long long length_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(ftruncate)(long long fd_, long long PAD_, long long length_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(ftruncate)
+(long long res, long long fd_, long long PAD_, long long length_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__sysctl)
+(void *name_, long long namelen_, void *oldv_, void *oldlenp_, void *newv_,
+ long long newlen_) {
+ const int *name = (const int *)name_;
+ if (name) {
+ PRE_READ(name, namelen_ * sizeof(*name));
+ }
+ if (newv_) {
+ PRE_READ(name, newlen_);
+ }
+}
+POST_SYSCALL(__sysctl)
+(long long res, void *name_, long long namelen_, void *oldv_, void *oldlenp_,
+ void *newv_, long long newlen_) {
+ if (res == 0) {
+ const int *name = (const int *)name_;
+ if (name) {
+ POST_READ(name, namelen_ * sizeof(*name));
+ }
+ if (newv_) {
+ POST_READ(name, newlen_);
+ }
+ }
+}
+PRE_SYSCALL(mlock)(void *addr_, long long len_) { /* Nothing to do */ }
+POST_SYSCALL(mlock)(long long res, void *addr_, long long len_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(munlock)(void *addr_, long long len_) { /* Nothing to do */ }
+POST_SYSCALL(munlock)(long long res, void *addr_, long long len_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(undelete)(void *path_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(undelete)(long long res, void *path_) {
+ if (res == 0) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(compat_50_futimes)(long long fd_, void *tptr_) { /* TODO */ }
+POST_SYSCALL(compat_50_futimes)(long long res, long long fd_, void *tptr_) {
+ /* TODO */
+}
+PRE_SYSCALL(getpgid)(long long pid_) { /* Nothing to do */ }
+POST_SYSCALL(getpgid)(long long res, long long pid_) { /* Nothing to do */ }
+PRE_SYSCALL(reboot)(long long opt_, void *bootstr_) {
+ const char *bootstr = (const char *)bootstr_;
+ if (bootstr) {
+ PRE_READ(bootstr, __sanitizer::internal_strlen(bootstr) + 1);
+ }
+}
+POST_SYSCALL(reboot)(long long res, long long opt_, void *bootstr_) {
+ /* This call should never return */
+ const char *bootstr = (const char *)bootstr_;
+ if (bootstr) {
+ POST_READ(bootstr, __sanitizer::internal_strlen(bootstr) + 1);
+ }
+}
+PRE_SYSCALL(poll)(void *fds_, long long nfds_, long long timeout_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(poll)
+(long long res, void *fds_, long long nfds_, long long timeout_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(afssys)
+(long long id_, long long a1_, long long a2_, long long a3_, long long a4_,
+ long long a5_, long long a6_) {
+ /* TODO */
+}
+POST_SYSCALL(afssys)
+(long long res, long long id_, long long a1_, long long a2_, long long a3_,
+ long long a4_, long long a5_, long long a6_) {
+ /* TODO */
+}
+/* syscall 211 has been skipped */
+/* syscall 212 has been skipped */
+/* syscall 213 has been skipped */
+/* syscall 214 has been skipped */
+/* syscall 215 has been skipped */
+/* syscall 216 has been skipped */
+/* syscall 217 has been skipped */
+/* syscall 218 has been skipped */
+/* syscall 219 has been skipped */
+PRE_SYSCALL(compat_14___semctl)
+(long long semid_, long long semnum_, long long cmd_, void *arg_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_14___semctl)
+(long long res, long long semid_, long long semnum_, long long cmd_,
+ void *arg_) {
+ /* TODO */
+}
+PRE_SYSCALL(semget)(long long key_, long long nsems_, long long semflg_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(semget)
+(long long res, long long key_, long long nsems_, long long semflg_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(semop)(long long semid_, void *sops_, long long nsops_) {
+ if (sops_) {
+ PRE_READ(sops_, nsops_ * struct_sembuf_sz);
+ }
+}
+POST_SYSCALL(semop)
+(long long res, long long semid_, void *sops_, long long nsops_) {
+ if (res == 0) {
+ if (sops_) {
+ POST_READ(sops_, nsops_ * struct_sembuf_sz);
+ }
+ }
+}
+PRE_SYSCALL(semconfig)(long long flag_) { /* Nothing to do */ }
+POST_SYSCALL(semconfig)(long long res, long long flag_) { /* Nothing to do */ }
+PRE_SYSCALL(compat_14_msgctl)(long long msqid_, long long cmd_, void *buf_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_14_msgctl)
+(long long res, long long msqid_, long long cmd_, void *buf_) {
+ /* TODO */
+}
+PRE_SYSCALL(msgget)(long long key_, long long msgflg_) { /* Nothing to do */ }
+POST_SYSCALL(msgget)(long long res, long long key_, long long msgflg_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(msgsnd)
+(long long msqid_, void *msgp_, long long msgsz_, long long msgflg_) {
+ if (msgp_) {
+ PRE_READ(msgp_, msgsz_);
+ }
+}
+POST_SYSCALL(msgsnd)
+(long long res, long long msqid_, void *msgp_, long long msgsz_,
+ long long msgflg_) {
+ if (res == 0) {
+ if (msgp_) {
+ POST_READ(msgp_, msgsz_);
+ }
+ }
+}
+PRE_SYSCALL(msgrcv)
+(long long msqid_, void *msgp_, long long msgsz_, long long msgtyp_,
+ long long msgflg_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(msgrcv)
+(long long res, long long msqid_, void *msgp_, long long msgsz_,
+ long long msgtyp_, long long msgflg_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(shmat)(long long shmid_, void *shmaddr_, long long shmflg_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(shmat)
+(long long res, long long shmid_, void *shmaddr_, long long shmflg_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_14_shmctl)(long long shmid_, long long cmd_, void *buf_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_14_shmctl)
+(long long res, long long shmid_, long long cmd_, void *buf_) {
+ /* TODO */
+}
+PRE_SYSCALL(shmdt)(void *shmaddr_) { /* Nothing to do */ }
+POST_SYSCALL(shmdt)(long long res, void *shmaddr_) { /* Nothing to do */ }
+PRE_SYSCALL(shmget)(long long key_, long long size_, long long shmflg_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(shmget)
+(long long res, long long key_, long long size_, long long shmflg_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_50_clock_gettime)(long long clock_id_, void *tp_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_clock_gettime)
+(long long res, long long clock_id_, void *tp_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50_clock_settime)(long long clock_id_, void *tp_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_clock_settime)
+(long long res, long long clock_id_, void *tp_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50_clock_getres)(long long clock_id_, void *tp_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_clock_getres)
+(long long res, long long clock_id_, void *tp_) {
+ /* TODO */
+}
+PRE_SYSCALL(timer_create)(long long clock_id_, void *evp_, void *timerid_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(timer_create)
+(long long res, long long clock_id_, void *evp_, void *timerid_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(timer_delete)(long long timerid_) { /* Nothing to do */ }
+POST_SYSCALL(timer_delete)(long long res, long long timerid_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_50_timer_settime)
+(long long timerid_, long long flags_, void *value_, void *ovalue_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_timer_settime)
+(long long res, long long timerid_, long long flags_, void *value_,
+ void *ovalue_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50_timer_gettime)(long long timerid_, void *value_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_timer_gettime)
+(long long res, long long timerid_, void *value_) {
+ /* TODO */
+}
+PRE_SYSCALL(timer_getoverrun)(long long timerid_) { /* Nothing to do */ }
+POST_SYSCALL(timer_getoverrun)(long long res, long long timerid_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_50_nanosleep)(void *rqtp_, void *rmtp_) { /* TODO */ }
+POST_SYSCALL(compat_50_nanosleep)(long long res, void *rqtp_, void *rmtp_) {
+ /* TODO */
+}
+PRE_SYSCALL(fdatasync)(long long fd_) { /* Nothing to do */ }
+POST_SYSCALL(fdatasync)(long long res, long long fd_) { /* Nothing to do */ }
+PRE_SYSCALL(mlockall)(long long flags_) { /* Nothing to do */ }
+POST_SYSCALL(mlockall)(long long res, long long flags_) { /* Nothing to do */ }
+PRE_SYSCALL(munlockall)(void) { /* Nothing to do */ }
+POST_SYSCALL(munlockall)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(compat_50___sigtimedwait)(void *set_, void *info_, void *timeout_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50___sigtimedwait)
+(long long res, void *set_, void *info_, void *timeout_) {
+ /* TODO */
+}
+PRE_SYSCALL(sigqueueinfo)(long long pid_, void *info_) {
+ if (info_) {
+ PRE_READ(info_, siginfo_t_sz);
+ }
+}
+POST_SYSCALL(sigqueueinfo)(long long res, long long pid_, void *info_) {}
+PRE_SYSCALL(modctl)(long long cmd_, void *arg_) { /* TODO */ }
+POST_SYSCALL(modctl)(long long res, long long cmd_, void *arg_) { /* TODO */ }
+PRE_SYSCALL(_ksem_init)(long long value_, void *idp_) { /* Nothing to do */ }
+POST_SYSCALL(_ksem_init)(long long res, long long value_, void *idp_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(_ksem_open)
+(void *name_, long long oflag_, long long mode_, long long value_, void *idp_) {
+ const char *name = (const char *)name_;
+ if (name) {
+ PRE_READ(name, __sanitizer::internal_strlen(name) + 1);
+ }
+}
+POST_SYSCALL(_ksem_open)
+(long long res, void *name_, long long oflag_, long long mode_,
+ long long value_, void *idp_) {
+ const char *name = (const char *)name_;
+ if (name) {
+ POST_READ(name, __sanitizer::internal_strlen(name) + 1);
+ }
+}
+PRE_SYSCALL(_ksem_unlink)(void *name_) {
+ const char *name = (const char *)name_;
+ if (name) {
+ PRE_READ(name, __sanitizer::internal_strlen(name) + 1);
+ }
+}
+POST_SYSCALL(_ksem_unlink)(long long res, void *name_) {
+ const char *name = (const char *)name_;
+ if (name) {
+ POST_READ(name, __sanitizer::internal_strlen(name) + 1);
+ }
+}
+PRE_SYSCALL(_ksem_close)(long long id_) { /* Nothing to do */ }
+POST_SYSCALL(_ksem_close)(long long res, long long id_) { /* Nothing to do */ }
+PRE_SYSCALL(_ksem_post)(long long id_) { /* Nothing to do */ }
+POST_SYSCALL(_ksem_post)(long long res, long long id_) { /* Nothing to do */ }
+PRE_SYSCALL(_ksem_wait)(long long id_) { /* Nothing to do */ }
+POST_SYSCALL(_ksem_wait)(long long res, long long id_) { /* Nothing to do */ }
+PRE_SYSCALL(_ksem_trywait)(long long id_) { /* Nothing to do */ }
+POST_SYSCALL(_ksem_trywait)(long long res, long long id_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(_ksem_getvalue)(long long id_, void *value_) { /* Nothing to do */ }
+POST_SYSCALL(_ksem_getvalue)(long long res, long long id_, void *value_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(_ksem_destroy)(long long id_) { /* Nothing to do */ }
+POST_SYSCALL(_ksem_destroy)(long long res, long long id_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(_ksem_timedwait)(long long id_, void *abstime_) {
+ if (abstime_) {
+ PRE_READ(abstime_, struct_timespec_sz);
+ }
+}
+POST_SYSCALL(_ksem_timedwait)(long long res, long long id_, void *abstime_) {}
+PRE_SYSCALL(mq_open)
+(void *name_, long long oflag_, long long mode_, void *attr_) {
+ const char *name = (const char *)name_;
+ if (name) {
+ PRE_READ(name, __sanitizer::internal_strlen(name) + 1);
+ }
+}
+POST_SYSCALL(mq_open)
+(long long res, void *name_, long long oflag_, long long mode_, void *attr_) {
+ const char *name = (const char *)name_;
+ if (name) {
+ POST_READ(name, __sanitizer::internal_strlen(name) + 1);
+ }
+}
+PRE_SYSCALL(mq_close)(long long mqdes_) { /* Nothing to do */ }
+POST_SYSCALL(mq_close)(long long res, long long mqdes_) { /* Nothing to do */ }
+PRE_SYSCALL(mq_unlink)(void *name_) {
+ const char *name = (const char *)name_;
+ if (name) {
+ PRE_READ(name, __sanitizer::internal_strlen(name) + 1);
+ }
+}
+POST_SYSCALL(mq_unlink)(long long res, void *name_) {
+ const char *name = (const char *)name_;
+ if (name) {
+ POST_READ(name, __sanitizer::internal_strlen(name) + 1);
+ }
+}
+PRE_SYSCALL(mq_getattr)(long long mqdes_, void *mqstat_) { /* Nothing to do */ }
+POST_SYSCALL(mq_getattr)(long long res, long long mqdes_, void *mqstat_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(mq_setattr)(long long mqdes_, void *mqstat_, void *omqstat_) {
+ if (mqstat_) {
+ PRE_READ(mqstat_, struct_mq_attr_sz);
+ }
+}
+POST_SYSCALL(mq_setattr)
+(long long res, long long mqdes_, void *mqstat_, void *omqstat_) {}
+PRE_SYSCALL(mq_notify)(long long mqdes_, void *notification_) {
+ if (notification_) {
+ PRE_READ(notification_, struct_sigevent_sz);
+ }
+}
+POST_SYSCALL(mq_notify)(long long res, long long mqdes_, void *notification_) {}
+PRE_SYSCALL(mq_send)
+(long long mqdes_, void *msg_ptr_, long long msg_len_, long long msg_prio_) {
+ if (msg_ptr_) {
+ PRE_READ(msg_ptr_, msg_len_);
+ }
+}
+POST_SYSCALL(mq_send)
+(long long res, long long mqdes_, void *msg_ptr_, long long msg_len_,
+ long long msg_prio_) {}
+PRE_SYSCALL(mq_receive)
+(long long mqdes_, void *msg_ptr_, long long msg_len_, void *msg_prio_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(mq_receive)
+(long long res, long long mqdes_, void *msg_ptr_, long long msg_len_,
+ void *msg_prio_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_50_mq_timedsend)
+(long long mqdes_, void *msg_ptr_, long long msg_len_, long long msg_prio_,
+ void *abs_timeout_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_mq_timedsend)
+(long long res, long long mqdes_, void *msg_ptr_, long long msg_len_,
+ long long msg_prio_, void *abs_timeout_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50_mq_timedreceive)
+(long long mqdes_, void *msg_ptr_, long long msg_len_, void *msg_prio_,
+ void *abs_timeout_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_mq_timedreceive)
+(long long res, long long mqdes_, void *msg_ptr_, long long msg_len_,
+ void *msg_prio_, void *abs_timeout_) {
+ /* TODO */
+}
+/* syscall 267 has been skipped */
+/* syscall 268 has been skipped */
+/* syscall 269 has been skipped */
+PRE_SYSCALL(__posix_rename)(void *from_, void *to_) {
+ const char *from = (const char *)from_;
+ const char *to = (const char *)to_;
+ if (from_) {
+ PRE_READ(from, __sanitizer::internal_strlen(from) + 1);
+ }
+ if (to) {
+ PRE_READ(to, __sanitizer::internal_strlen(to) + 1);
+ }
+}
+POST_SYSCALL(__posix_rename)(long long res, void *from_, void *to_) {
+ const char *from = (const char *)from_;
+ const char *to = (const char *)to_;
+ if (from) {
+ POST_READ(from, __sanitizer::internal_strlen(from) + 1);
+ }
+ if (to) {
+ POST_READ(to, __sanitizer::internal_strlen(to) + 1);
+ }
+}
+PRE_SYSCALL(swapctl)(long long cmd_, void *arg_, long long misc_) { /* TODO */ }
+POST_SYSCALL(swapctl)
+(long long res, long long cmd_, void *arg_, long long misc_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_30_getdents)(long long fd_, void *buf_, long long count_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_30_getdents)
+(long long res, long long fd_, void *buf_, long long count_) {
+ /* TODO */
+}
+PRE_SYSCALL(minherit)(void *addr_, long long len_, long long inherit_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(minherit)
+(long long res, void *addr_, long long len_, long long inherit_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(lchmod)(void *path_, long long mode_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(lchmod)(long long res, void *path_, long long mode_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(lchown)(void *path_, long long uid_, long long gid_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(lchown)
+(long long res, void *path_, long long uid_, long long gid_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(compat_50_lutimes)(void *path_, void *tptr_) { /* TODO */ }
+POST_SYSCALL(compat_50_lutimes)(long long res, void *path_, void *tptr_) {
+ /* TODO */
+}
+PRE_SYSCALL(__msync13)(void *addr_, long long len_, long long flags_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__msync13)
+(long long res, void *addr_, long long len_, long long flags_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_30___stat13)(void *path_, void *ub_) { /* TODO */ }
+POST_SYSCALL(compat_30___stat13)(long long res, void *path_, void *ub_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_30___fstat13)(long long fd_, void *sb_) { /* TODO */ }
+POST_SYSCALL(compat_30___fstat13)(long long res, long long fd_, void *sb_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_30___lstat13)(void *path_, void *ub_) { /* TODO */ }
+POST_SYSCALL(compat_30___lstat13)(long long res, void *path_, void *ub_) {
+ /* TODO */
+}
+PRE_SYSCALL(__sigaltstack14)(void *nss_, void *oss_) {
+ if (nss_) {
+ PRE_READ(nss_, struct_sigaltstack_sz);
+ }
+ if (oss_) {
+ PRE_READ(oss_, struct_sigaltstack_sz);
+ }
+}
+POST_SYSCALL(__sigaltstack14)(long long res, void *nss_, void *oss_) {}
+PRE_SYSCALL(__vfork14)(void) { /* Nothing to do */ }
+POST_SYSCALL(__vfork14)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(__posix_chown)(void *path_, long long uid_, long long gid_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(__posix_chown)
+(long long res, void *path_, long long uid_, long long gid_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(__posix_fchown)(long long fd_, long long uid_, long long gid_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__posix_fchown)
+(long long res, long long fd_, long long uid_, long long gid_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__posix_lchown)(void *path_, long long uid_, long long gid_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(__posix_lchown)
+(long long res, void *path_, long long uid_, long long gid_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(getsid)(long long pid_) { /* Nothing to do */ }
+POST_SYSCALL(getsid)(long long res, long long pid_) { /* Nothing to do */ }
+PRE_SYSCALL(__clone)(long long flags_, void *stack_) { /* Nothing to do */ }
+POST_SYSCALL(__clone)(long long res, long long flags_, void *stack_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(fktrace)
+(long long fd_, long long ops_, long long facs_, long long pid_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(fktrace)
+(long long res, long long fd_, long long ops_, long long facs_,
+ long long pid_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(preadv)
+(long long fd_, void *iovp_, long long iovcnt_, long long PAD_,
+ long long offset_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(preadv)
+(long long res, long long fd_, void *iovp_, long long iovcnt_, long long PAD_,
+ long long offset_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(pwritev)
+(long long fd_, void *iovp_, long long iovcnt_, long long PAD_,
+ long long offset_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(pwritev)
+(long long res, long long fd_, void *iovp_, long long iovcnt_, long long PAD_,
+ long long offset_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_16___sigaction14)
+(long long signum_, void *nsa_, void *osa_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_16___sigaction14)
+(long long res, long long signum_, void *nsa_, void *osa_) {
+ /* TODO */
+}
+PRE_SYSCALL(__sigpending14)(void *set_) { /* Nothing to do */ }
+POST_SYSCALL(__sigpending14)(long long res, void *set_) { /* Nothing to do */ }
+PRE_SYSCALL(__sigprocmask14)(long long how_, void *set_, void *oset_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__sigprocmask14)
+(long long res, long long how_, void *set_, void *oset_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__sigsuspend14)(void *set_) {
+ if (set_) {
+ PRE_READ(set_, sizeof(__sanitizer_sigset_t));
+ }
+}
+POST_SYSCALL(__sigsuspend14)(long long res, void *set_) {
+ if (set_) {
+ PRE_READ(set_, sizeof(__sanitizer_sigset_t));
+ }
+}
+PRE_SYSCALL(compat_16___sigreturn14)(void *sigcntxp_) { /* TODO */ }
+POST_SYSCALL(compat_16___sigreturn14)(long long res, void *sigcntxp_) {
+ /* TODO */
+}
+PRE_SYSCALL(__getcwd)(void *bufp_, long long length_) { /* Nothing to do */ }
+POST_SYSCALL(__getcwd)(long long res, void *bufp_, long long length_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(fchroot)(long long fd_) { /* Nothing to do */ }
+POST_SYSCALL(fchroot)(long long res, long long fd_) { /* Nothing to do */ }
+PRE_SYSCALL(compat_30_fhopen)(void *fhp_, long long flags_) { /* TODO */ }
+POST_SYSCALL(compat_30_fhopen)(long long res, void *fhp_, long long flags_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_30_fhstat)(void *fhp_, void *sb_) { /* TODO */ }
+POST_SYSCALL(compat_30_fhstat)(long long res, void *fhp_, void *sb_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_20_fhstatfs)(void *fhp_, void *buf_) { /* TODO */ }
+POST_SYSCALL(compat_20_fhstatfs)(long long res, void *fhp_, void *buf_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50_____semctl13)
+(long long semid_, long long semnum_, long long cmd_, void *arg_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_____semctl13)
+(long long res, long long semid_, long long semnum_, long long cmd_,
+ void *arg_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50___msgctl13)
+(long long msqid_, long long cmd_, void *buf_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50___msgctl13)
+(long long res, long long msqid_, long long cmd_, void *buf_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50___shmctl13)
+(long long shmid_, long long cmd_, void *buf_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50___shmctl13)
+(long long res, long long shmid_, long long cmd_, void *buf_) {
+ /* TODO */
+}
+PRE_SYSCALL(lchflags)(void *path_, long long flags_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(lchflags)(long long res, void *path_, long long flags_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(issetugid)(void) { /* Nothing to do */ }
+POST_SYSCALL(issetugid)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(utrace)(void *label_, void *addr_, long long len_) {
+ const char *label = (const char *)label_;
+ if (label) {
+ PRE_READ(label, __sanitizer::internal_strlen(label) + 1);
+ }
+ if (addr_) {
+ PRE_READ(addr_, len_);
+ }
+}
+POST_SYSCALL(utrace)(long long res, void *label_, void *addr_, long long len_) {
+ const char *label = (const char *)label_;
+ if (label) {
+ POST_READ(label, __sanitizer::internal_strlen(label) + 1);
+ }
+ if (addr_) {
+ POST_READ(addr_, len_);
+ }
+}
+PRE_SYSCALL(getcontext)(void *ucp_) { /* Nothing to do */ }
+POST_SYSCALL(getcontext)(long long res, void *ucp_) { /* Nothing to do */ }
+PRE_SYSCALL(setcontext)(void *ucp_) {
+ if (ucp_) {
+ PRE_READ(ucp_, ucontext_t_sz(ucp_));
+ }
+}
+POST_SYSCALL(setcontext)(long long res, void *ucp_) {}
+PRE_SYSCALL(_lwp_create)(void *ucp_, long long flags_, void *new_lwp_) {
+ if (ucp_) {
+ PRE_READ(ucp_, ucontext_t_sz(ucp_));
+ }
+}
+POST_SYSCALL(_lwp_create)
+(long long res, void *ucp_, long long flags_, void *new_lwp_) {}
+PRE_SYSCALL(_lwp_exit)(void) { /* Nothing to do */ }
+POST_SYSCALL(_lwp_exit)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(_lwp_self)(void) { /* Nothing to do */ }
+POST_SYSCALL(_lwp_self)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(_lwp_wait)(long long wait_for_, void *departed_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(_lwp_wait)(long long res, long long wait_for_, void *departed_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(_lwp_suspend)(long long target_) { /* Nothing to do */ }
+POST_SYSCALL(_lwp_suspend)(long long res, long long target_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(_lwp_continue)(long long target_) { /* Nothing to do */ }
+POST_SYSCALL(_lwp_continue)(long long res, long long target_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(_lwp_wakeup)(long long target_) { /* Nothing to do */ }
+POST_SYSCALL(_lwp_wakeup)(long long res, long long target_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(_lwp_getprivate)(void) { /* Nothing to do */ }
+POST_SYSCALL(_lwp_getprivate)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(_lwp_setprivate)(void *ptr_) { /* Nothing to do */ }
+POST_SYSCALL(_lwp_setprivate)(long long res, void *ptr_) { /* Nothing to do */ }
+PRE_SYSCALL(_lwp_kill)(long long target_, long long signo_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(_lwp_kill)(long long res, long long target_, long long signo_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(_lwp_detach)(long long target_) { /* Nothing to do */ }
+POST_SYSCALL(_lwp_detach)(long long res, long long target_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_50__lwp_park)
+(void *ts_, long long unpark_, void *hint_, void *unparkhint_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50__lwp_park)
+(long long res, void *ts_, long long unpark_, void *hint_, void *unparkhint_) {
+ /* TODO */
+}
+PRE_SYSCALL(_lwp_unpark)(long long target_, void *hint_) { /* Nothing to do */ }
+POST_SYSCALL(_lwp_unpark)(long long res, long long target_, void *hint_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(_lwp_unpark_all)(void *targets_, long long ntargets_, void *hint_) {
+ if (targets_) {
+ PRE_READ(targets_, ntargets_ * sizeof(__sanitizer_lwpid_t));
+ }
+}
+POST_SYSCALL(_lwp_unpark_all)
+(long long res, void *targets_, long long ntargets_, void *hint_) {}
+PRE_SYSCALL(_lwp_setname)(long long target_, void *name_) {
+ const char *name = (const char *)name_;
+ if (name) {
+ PRE_READ(name, __sanitizer::internal_strlen(name) + 1);
+ }
+}
+POST_SYSCALL(_lwp_setname)(long long res, long long target_, void *name_) {
+ const char *name = (const char *)name_;
+ if (name) {
+ POST_READ(name, __sanitizer::internal_strlen(name) + 1);
+ }
+}
+PRE_SYSCALL(_lwp_getname)(long long target_, void *name_, long long len_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(_lwp_getname)
+(long long res, long long target_, void *name_, long long len_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(_lwp_ctl)(long long features_, void **address_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(_lwp_ctl)(long long res, long long features_, void **address_) {
+ /* Nothing to do */
+}
+/* syscall 326 has been skipped */
+/* syscall 327 has been skipped */
+/* syscall 328 has been skipped */
+/* syscall 329 has been skipped */
+PRE_SYSCALL(compat_60_sa_register)
+(void *newv_, void **oldv_, long long flags_, long long stackinfo_offset_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_60_sa_register)
+(long long res, void *newv_, void **oldv_, long long flags_,
+ long long stackinfo_offset_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_60_sa_stacks)(long long num_, void *stacks_) { /* TODO */ }
+POST_SYSCALL(compat_60_sa_stacks)
+(long long res, long long num_, void *stacks_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_60_sa_enable)(void) { /* TODO */ }
+POST_SYSCALL(compat_60_sa_enable)(long long res) { /* TODO */ }
+PRE_SYSCALL(compat_60_sa_setconcurrency)(long long concurrency_) { /* TODO */ }
+POST_SYSCALL(compat_60_sa_setconcurrency)
+(long long res, long long concurrency_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_60_sa_yield)(void) { /* TODO */ }
+POST_SYSCALL(compat_60_sa_yield)(long long res) { /* TODO */ }
+PRE_SYSCALL(compat_60_sa_preempt)(long long sa_id_) { /* TODO */ }
+POST_SYSCALL(compat_60_sa_preempt)(long long res, long long sa_id_) {
+ /* TODO */
+}
+/* syscall 336 has been skipped */
+/* syscall 337 has been skipped */
+/* syscall 338 has been skipped */
+/* syscall 339 has been skipped */
+PRE_SYSCALL(__sigaction_sigtramp)
+(long long signum_, void *nsa_, void *osa_, void *tramp_, long long vers_) {
+ if (nsa_) {
+ PRE_READ(nsa_, sizeof(__sanitizer_sigaction));
+ }
+}
+POST_SYSCALL(__sigaction_sigtramp)
+(long long res, long long signum_, void *nsa_, void *osa_, void *tramp_,
+ long long vers_) {
+ if (nsa_) {
+ PRE_READ(nsa_, sizeof(__sanitizer_sigaction));
+ }
+}
+/* syscall 341 has been skipped */
+/* syscall 342 has been skipped */
+PRE_SYSCALL(rasctl)(void *addr_, long long len_, long long op_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(rasctl)
+(long long res, void *addr_, long long len_, long long op_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(kqueue)(void) { /* Nothing to do */ }
+POST_SYSCALL(kqueue)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(compat_50_kevent)
+(long long fd_, void *changelist_, long long nchanges_, void *eventlist_,
+ long long nevents_, void *timeout_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_kevent)
+(long long res, long long fd_, void *changelist_, long long nchanges_,
+ void *eventlist_, long long nevents_, void *timeout_) {
+ /* TODO */
+}
+PRE_SYSCALL(_sched_setparam)
+(long long pid_, long long lid_, long long policy_, void *params_) {
+ if (params_) {
+ PRE_READ(params_, struct_sched_param_sz);
+ }
+}
+POST_SYSCALL(_sched_setparam)
+(long long res, long long pid_, long long lid_, long long policy_,
+ void *params_) {
+ if (params_) {
+ PRE_READ(params_, struct_sched_param_sz);
+ }
+}
+PRE_SYSCALL(_sched_getparam)
+(long long pid_, long long lid_, void *policy_, void *params_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(_sched_getparam)
+(long long res, long long pid_, long long lid_, void *policy_, void *params_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(_sched_setaffinity)
+(long long pid_, long long lid_, long long size_, void *cpuset_) {
+ if (cpuset_) {
+ PRE_READ(cpuset_, size_);
+ }
+}
+POST_SYSCALL(_sched_setaffinity)
+(long long res, long long pid_, long long lid_, long long size_,
+ void *cpuset_) {
+ if (cpuset_) {
+ PRE_READ(cpuset_, size_);
+ }
+}
+PRE_SYSCALL(_sched_getaffinity)
+(long long pid_, long long lid_, long long size_, void *cpuset_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(_sched_getaffinity)
+(long long res, long long pid_, long long lid_, long long size_,
+ void *cpuset_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(sched_yield)(void) { /* Nothing to do */ }
+POST_SYSCALL(sched_yield)(long long res) { /* Nothing to do */ }
+PRE_SYSCALL(_sched_protect)(long long priority_) { /* Nothing to do */ }
+POST_SYSCALL(_sched_protect)(long long res, long long priority_) {
+ /* Nothing to do */
+}
+/* syscall 352 has been skipped */
+/* syscall 353 has been skipped */
+PRE_SYSCALL(fsync_range)
+(long long fd_, long long flags_, long long start_, long long length_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(fsync_range)
+(long long res, long long fd_, long long flags_, long long start_,
+ long long length_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(uuidgen)(void *store_, long long count_) { /* Nothing to do */ }
+POST_SYSCALL(uuidgen)(long long res, void *store_, long long count_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_90_getvfsstat)
+(void *buf_, long long bufsize_, long long flags_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(compat_90_getvfsstat)
+(long long res, void *buf_, long long bufsize_, long long flags_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_90_statvfs1)(void *path_, void *buf_, long long flags_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(compat_90_statvfs1)
+(long long res, void *path_, void *buf_, long long flags_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(compat_90_fstatvfs1)(long long fd_, void *buf_, long long flags_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(compat_90_fstatvfs1)
+(long long res, long long fd_, void *buf_, long long flags_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(compat_30_fhstatvfs1)(void *fhp_, void *buf_, long long flags_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_30_fhstatvfs1)
+(long long res, void *fhp_, void *buf_, long long flags_) {
+ /* TODO */
+}
+PRE_SYSCALL(extattrctl)
+(void *path_, long long cmd_, void *filename_, long long attrnamespace_,
+ void *attrname_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(extattrctl)
+(long long res, void *path_, long long cmd_, void *filename_,
+ long long attrnamespace_, void *attrname_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(extattr_set_file)
+(void *path_, long long attrnamespace_, void *attrname_, void *data_,
+ long long nbytes_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(extattr_set_file)
+(long long res, void *path_, long long attrnamespace_, void *attrname_,
+ void *data_, long long nbytes_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(extattr_get_file)
+(void *path_, long long attrnamespace_, void *attrname_, void *data_,
+ long long nbytes_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(extattr_get_file)
+(long long res, void *path_, long long attrnamespace_, void *attrname_,
+ void *data_, long long nbytes_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(extattr_delete_file)
+(void *path_, long long attrnamespace_, void *attrname_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(extattr_delete_file)
+(long long res, void *path_, long long attrnamespace_, void *attrname_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(extattr_set_fd)
+(long long fd_, long long attrnamespace_, void *attrname_, void *data_,
+ long long nbytes_) {
+ /* TODO */
+}
+POST_SYSCALL(extattr_set_fd)
+(long long res, long long fd_, long long attrnamespace_, void *attrname_,
+ void *data_, long long nbytes_) {
+ /* TODO */
+}
+PRE_SYSCALL(extattr_get_fd)
+(long long fd_, long long attrnamespace_, void *attrname_, void *data_,
+ long long nbytes_) {
+ /* TODO */
+}
+POST_SYSCALL(extattr_get_fd)
+(long long res, long long fd_, long long attrnamespace_, void *attrname_,
+ void *data_, long long nbytes_) {
+ /* TODO */
+}
+PRE_SYSCALL(extattr_delete_fd)
+(long long fd_, long long attrnamespace_, void *attrname_) {
+ /* TODO */
+}
+POST_SYSCALL(extattr_delete_fd)
+(long long res, long long fd_, long long attrnamespace_, void *attrname_) {
+ /* TODO */
+}
+PRE_SYSCALL(extattr_set_link)
+(void *path_, long long attrnamespace_, void *attrname_, void *data_,
+ long long nbytes_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(extattr_set_link)
+(long long res, void *path_, long long attrnamespace_, void *attrname_,
+ void *data_, long long nbytes_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(extattr_get_link)
+(void *path_, long long attrnamespace_, void *attrname_, void *data_,
+ long long nbytes_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(extattr_get_link)
+(long long res, void *path_, long long attrnamespace_, void *attrname_,
+ void *data_, long long nbytes_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(extattr_delete_link)
+(void *path_, long long attrnamespace_, void *attrname_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(extattr_delete_link)
+(long long res, void *path_, long long attrnamespace_, void *attrname_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(extattr_list_fd)
+(long long fd_, long long attrnamespace_, void *data_, long long nbytes_) {
+ /* TODO */
+}
+POST_SYSCALL(extattr_list_fd)
+(long long res, long long fd_, long long attrnamespace_, void *data_,
+ long long nbytes_) {
+ /* TODO */
+}
+PRE_SYSCALL(extattr_list_file)
+(void *path_, long long attrnamespace_, void *data_, long long nbytes_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(extattr_list_file)
+(long long res, void *path_, long long attrnamespace_, void *data_,
+ long long nbytes_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(extattr_list_link)
+(void *path_, long long attrnamespace_, void *data_, long long nbytes_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(extattr_list_link)
+(long long res, void *path_, long long attrnamespace_, void *data_,
+ long long nbytes_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(compat_50_pselect)
+(long long nd_, void *in_, void *ou_, void *ex_, void *ts_, void *mask_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_pselect)
+(long long res, long long nd_, void *in_, void *ou_, void *ex_, void *ts_,
+ void *mask_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50_pollts)
+(void *fds_, long long nfds_, void *ts_, void *mask_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_pollts)
+(long long res, void *fds_, long long nfds_, void *ts_, void *mask_) {
+ /* TODO */
+}
+PRE_SYSCALL(setxattr)
+(void *path_, void *name_, void *value_, long long size_, long long flags_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(setxattr)
+(long long res, void *path_, void *name_, void *value_, long long size_,
+ long long flags_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(lsetxattr)
+(void *path_, void *name_, void *value_, long long size_, long long flags_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(lsetxattr)
+(long long res, void *path_, void *name_, void *value_, long long size_,
+ long long flags_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(fsetxattr)
+(long long fd_, void *name_, void *value_, long long size_, long long flags_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(fsetxattr)
+(long long res, long long fd_, void *name_, void *value_, long long size_,
+ long long flags_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(getxattr)(void *path_, void *name_, void *value_, long long size_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(getxattr)
+(long long res, void *path_, void *name_, void *value_, long long size_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(lgetxattr)
+(void *path_, void *name_, void *value_, long long size_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(lgetxattr)
+(long long res, void *path_, void *name_, void *value_, long long size_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(fgetxattr)
+(long long fd_, void *name_, void *value_, long long size_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(fgetxattr)
+(long long res, long long fd_, void *name_, void *value_, long long size_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(listxattr)(void *path_, void *list_, long long size_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(listxattr)
+(long long res, void *path_, void *list_, long long size_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(llistxattr)(void *path_, void *list_, long long size_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(llistxattr)
+(long long res, void *path_, void *list_, long long size_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(flistxattr)(long long fd_, void *list_, long long size_) {
+ /* TODO */
+}
+POST_SYSCALL(flistxattr)
+(long long res, long long fd_, void *list_, long long size_) {
+ /* TODO */
+}
+PRE_SYSCALL(removexattr)(void *path_, void *name_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(removexattr)(long long res, void *path_, void *name_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(lremovexattr)(void *path_, void *name_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(lremovexattr)(long long res, void *path_, void *name_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(fremovexattr)(long long fd_, void *name_) { /* TODO */ }
+POST_SYSCALL(fremovexattr)(long long res, long long fd_, void *name_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50___stat30)(void *path_, void *ub_) { /* TODO */ }
+POST_SYSCALL(compat_50___stat30)(long long res, void *path_, void *ub_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50___fstat30)(long long fd_, void *sb_) { /* TODO */ }
+POST_SYSCALL(compat_50___fstat30)(long long res, long long fd_, void *sb_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50___lstat30)(void *path_, void *ub_) { /* TODO */ }
+POST_SYSCALL(compat_50___lstat30)(long long res, void *path_, void *ub_) {
+ /* TODO */
+}
+PRE_SYSCALL(__getdents30)(long long fd_, void *buf_, long long count_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__getdents30)
+(long long res, long long fd_, void *buf_, long long count_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(posix_fadvise)(long long) { /* Nothing to do */ }
+POST_SYSCALL(posix_fadvise)(long long res, long long) { /* Nothing to do */ }
+PRE_SYSCALL(compat_30___fhstat30)(void *fhp_, void *sb_) { /* TODO */ }
+POST_SYSCALL(compat_30___fhstat30)(long long res, void *fhp_, void *sb_) {
+ /* TODO */
+}
+PRE_SYSCALL(compat_50___ntp_gettime30)(void *ntvp_) { /* TODO */ }
+POST_SYSCALL(compat_50___ntp_gettime30)(long long res, void *ntvp_) {
+ /* TODO */
+}
+PRE_SYSCALL(__socket30)
+(long long domain_, long long type_, long long protocol_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__socket30)
+(long long res, long long domain_, long long type_, long long protocol_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__getfh30)(void *fname_, void *fhp_, void *fh_size_) {
+ const char *fname = (const char *)fname_;
+ if (fname) {
+ PRE_READ(fname, __sanitizer::internal_strlen(fname) + 1);
+ }
+}
+POST_SYSCALL(__getfh30)
+(long long res, void *fname_, void *fhp_, void *fh_size_) {
+ const char *fname = (const char *)fname_;
+ if (res == 0) {
+ if (fname) {
+ POST_READ(fname, __sanitizer::internal_strlen(fname) + 1);
+ }
+ }
+}
+PRE_SYSCALL(__fhopen40)(void *fhp_, long long fh_size_, long long flags_) {
+ if (fhp_) {
+ PRE_READ(fhp_, fh_size_);
+ }
+}
+POST_SYSCALL(__fhopen40)
+(long long res, void *fhp_, long long fh_size_, long long flags_) {}
+PRE_SYSCALL(compat_90_fhstatvfs1)
+(void *fhp_, long long fh_size_, void *buf_, long long flags_) {
+ if (fhp_) {
+ PRE_READ(fhp_, fh_size_);
+ }
+}
+POST_SYSCALL(compat_90_fhstatvfs1)
+(long long res, void *fhp_, long long fh_size_, void *buf_, long long flags_) {}
+PRE_SYSCALL(compat_50___fhstat40)(void *fhp_, long long fh_size_, void *sb_) {
+ if (fhp_) {
+ PRE_READ(fhp_, fh_size_);
+ }
+}
+POST_SYSCALL(compat_50___fhstat40)
+(long long res, void *fhp_, long long fh_size_, void *sb_) {}
+PRE_SYSCALL(aio_cancel)(long long fildes_, void *aiocbp_) {
+ if (aiocbp_) {
+ PRE_READ(aiocbp_, sizeof(struct __sanitizer_aiocb));
+ }
+}
+POST_SYSCALL(aio_cancel)(long long res, long long fildes_, void *aiocbp_) {}
+PRE_SYSCALL(aio_error)(void *aiocbp_) {
+ if (aiocbp_) {
+ PRE_READ(aiocbp_, sizeof(struct __sanitizer_aiocb));
+ }
+}
+POST_SYSCALL(aio_error)(long long res, void *aiocbp_) {}
+PRE_SYSCALL(aio_fsync)(long long op_, void *aiocbp_) {
+ if (aiocbp_) {
+ PRE_READ(aiocbp_, sizeof(struct __sanitizer_aiocb));
+ }
+}
+POST_SYSCALL(aio_fsync)(long long res, long long op_, void *aiocbp_) {}
+PRE_SYSCALL(aio_read)(void *aiocbp_) {
+ if (aiocbp_) {
+ PRE_READ(aiocbp_, sizeof(struct __sanitizer_aiocb));
+ }
+}
+POST_SYSCALL(aio_read)(long long res, void *aiocbp_) {}
+PRE_SYSCALL(aio_return)(void *aiocbp_) {
+ if (aiocbp_) {
+ PRE_READ(aiocbp_, sizeof(struct __sanitizer_aiocb));
+ }
+}
+POST_SYSCALL(aio_return)(long long res, void *aiocbp_) {}
+PRE_SYSCALL(compat_50_aio_suspend)
+(void *list_, long long nent_, void *timeout_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_50_aio_suspend)
+(long long res, void *list_, long long nent_, void *timeout_) {
+ /* TODO */
+}
+PRE_SYSCALL(aio_write)(void *aiocbp_) {
+ if (aiocbp_) {
+ PRE_READ(aiocbp_, sizeof(struct __sanitizer_aiocb));
+ }
+}
+POST_SYSCALL(aio_write)(long long res, void *aiocbp_) {}
+PRE_SYSCALL(lio_listio)
+(long long mode_, void *list_, long long nent_, void *sig_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(lio_listio)
+(long long res, long long mode_, void *list_, long long nent_, void *sig_) {
+ /* Nothing to do */
+}
+/* syscall 407 has been skipped */
+/* syscall 408 has been skipped */
+/* syscall 409 has been skipped */
+PRE_SYSCALL(__mount50)
+(void *type_, void *path_, long long flags_, void *data_, long long data_len_) {
+ const char *type = (const char *)type_;
+ const char *path = (const char *)path_;
+ if (type) {
+ PRE_READ(type, __sanitizer::internal_strlen(type) + 1);
+ }
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (data_) {
+ PRE_READ(data_, data_len_);
+ }
+}
+POST_SYSCALL(__mount50)
+(long long res, void *type_, void *path_, long long flags_, void *data_,
+ long long data_len_) {
+ const char *type = (const char *)type_;
+ const char *path = (const char *)path_;
+ if (type) {
+ POST_READ(type, __sanitizer::internal_strlen(type) + 1);
+ }
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (data_) {
+ POST_READ(data_, data_len_);
+ }
+}
+PRE_SYSCALL(mremap)
+(void *old_address_, long long old_size_, void *new_address_,
+ long long new_size_, long long flags_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(mremap)
+(long long res, void *old_address_, long long old_size_, void *new_address_,
+ long long new_size_, long long flags_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(pset_create)(void *psid_) { /* Nothing to do */ }
+POST_SYSCALL(pset_create)(long long res, void *psid_) { /* Nothing to do */ }
+PRE_SYSCALL(pset_destroy)(long long psid_) { /* Nothing to do */ }
+POST_SYSCALL(pset_destroy)(long long res, long long psid_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(pset_assign)(long long psid_, long long cpuid_, void *opsid_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(pset_assign)
+(long long res, long long psid_, long long cpuid_, void *opsid_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(_pset_bind)
+(long long idtype_, long long first_id_, long long second_id_, long long psid_,
+ void *opsid_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(_pset_bind)
+(long long res, long long idtype_, long long first_id_, long long second_id_,
+ long long psid_, void *opsid_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__posix_fadvise50)
+(long long fd_, long long PAD_, long long offset_, long long len_,
+ long long advice_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__posix_fadvise50)
+(long long res, long long fd_, long long PAD_, long long offset_,
+ long long len_, long long advice_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__select50)
+(long long nd_, void *in_, void *ou_, void *ex_, void *tv_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__select50)
+(long long res, long long nd_, void *in_, void *ou_, void *ex_, void *tv_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__gettimeofday50)(void *tp_, void *tzp_) { /* Nothing to do */ }
+POST_SYSCALL(__gettimeofday50)(long long res, void *tp_, void *tzp_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__settimeofday50)(void *tv_, void *tzp_) {
+ if (tv_) {
+ PRE_READ(tv_, timeval_sz);
+ }
+ if (tzp_) {
+ PRE_READ(tzp_, struct_timezone_sz);
+ }
+}
+POST_SYSCALL(__settimeofday50)(long long res, void *tv_, void *tzp_) {}
+PRE_SYSCALL(__utimes50)(void *path_, void *tptr_) {
+ struct __sanitizer_timespec **tptr = (struct __sanitizer_timespec **)tptr_;
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (tptr) {
+ PRE_READ(tptr[0], struct_timespec_sz);
+ PRE_READ(tptr[1], struct_timespec_sz);
+ }
+}
+POST_SYSCALL(__utimes50)(long long res, void *path_, void *tptr_) {}
+PRE_SYSCALL(__adjtime50)(void *delta_, void *olddelta_) {
+ if (delta_) {
+ PRE_READ(delta_, timeval_sz);
+ }
+}
+POST_SYSCALL(__adjtime50)(long long res, void *delta_, void *olddelta_) {}
+PRE_SYSCALL(__lfs_segwait50)(void *fsidp_, void *tv_) { /* TODO */ }
+POST_SYSCALL(__lfs_segwait50)(long long res, void *fsidp_, void *tv_) {
+ /* TODO */
+}
+PRE_SYSCALL(__futimes50)(long long fd_, void *tptr_) {
+ struct __sanitizer_timespec **tptr = (struct __sanitizer_timespec **)tptr_;
+ if (tptr) {
+ PRE_READ(tptr[0], struct_timespec_sz);
+ PRE_READ(tptr[1], struct_timespec_sz);
+ }
+}
+POST_SYSCALL(__futimes50)(long long res, long long fd_, void *tptr_) {}
+PRE_SYSCALL(__lutimes50)(void *path_, void *tptr_) {
+ struct __sanitizer_timespec **tptr = (struct __sanitizer_timespec **)tptr_;
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (tptr) {
+ PRE_READ(tptr[0], struct_timespec_sz);
+ PRE_READ(tptr[1], struct_timespec_sz);
+ }
+}
+POST_SYSCALL(__lutimes50)(long long res, void *path_, void *tptr_) {
+ struct __sanitizer_timespec **tptr = (struct __sanitizer_timespec **)tptr_;
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (tptr) {
+ POST_READ(tptr[0], struct_timespec_sz);
+ POST_READ(tptr[1], struct_timespec_sz);
+ }
+}
+PRE_SYSCALL(__setitimer50)(long long which_, void *itv_, void *oitv_) {
+ struct __sanitizer_itimerval *itv = (struct __sanitizer_itimerval *)itv_;
+ if (itv) {
+ PRE_READ(&itv->it_interval.tv_sec, sizeof(__sanitizer_time_t));
+ PRE_READ(&itv->it_interval.tv_usec, sizeof(__sanitizer_suseconds_t));
+ PRE_READ(&itv->it_value.tv_sec, sizeof(__sanitizer_time_t));
+ PRE_READ(&itv->it_value.tv_usec, sizeof(__sanitizer_suseconds_t));
+ }
+}
+POST_SYSCALL(__setitimer50)
+(long long res, long long which_, void *itv_, void *oitv_) {}
+PRE_SYSCALL(__getitimer50)(long long which_, void *itv_) { /* Nothing to do */ }
+POST_SYSCALL(__getitimer50)(long long res, long long which_, void *itv_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__clock_gettime50)(long long clock_id_, void *tp_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__clock_gettime50)(long long res, long long clock_id_, void *tp_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__clock_settime50)(long long clock_id_, void *tp_) {
+ if (tp_) {
+ PRE_READ(tp_, struct_timespec_sz);
+ }
+}
+POST_SYSCALL(__clock_settime50)
+(long long res, long long clock_id_, void *tp_) {}
+PRE_SYSCALL(__clock_getres50)(long long clock_id_, void *tp_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__clock_getres50)(long long res, long long clock_id_, void *tp_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__nanosleep50)(void *rqtp_, void *rmtp_) {
+ if (rqtp_) {
+ PRE_READ(rqtp_, struct_timespec_sz);
+ }
+}
+POST_SYSCALL(__nanosleep50)(long long res, void *rqtp_, void *rmtp_) {}
+PRE_SYSCALL(____sigtimedwait50)(void *set_, void *info_, void *timeout_) {
+ if (set_) {
+ PRE_READ(set_, sizeof(__sanitizer_sigset_t));
+ }
+ if (timeout_) {
+ PRE_READ(timeout_, struct_timespec_sz);
+ }
+}
+POST_SYSCALL(____sigtimedwait50)
+(long long res, void *set_, void *info_, void *timeout_) {}
+PRE_SYSCALL(__mq_timedsend50)
+(long long mqdes_, void *msg_ptr_, long long msg_len_, long long msg_prio_,
+ void *abs_timeout_) {
+ if (msg_ptr_) {
+ PRE_READ(msg_ptr_, msg_len_);
+ }
+ if (abs_timeout_) {
+ PRE_READ(abs_timeout_, struct_timespec_sz);
+ }
+}
+POST_SYSCALL(__mq_timedsend50)
+(long long res, long long mqdes_, void *msg_ptr_, long long msg_len_,
+ long long msg_prio_, void *abs_timeout_) {}
+PRE_SYSCALL(__mq_timedreceive50)
+(long long mqdes_, void *msg_ptr_, long long msg_len_, void *msg_prio_,
+ void *abs_timeout_) {
+ if (msg_ptr_) {
+ PRE_READ(msg_ptr_, msg_len_);
+ }
+ if (abs_timeout_) {
+ PRE_READ(abs_timeout_, struct_timespec_sz);
+ }
+}
+POST_SYSCALL(__mq_timedreceive50)
+(long long res, long long mqdes_, void *msg_ptr_, long long msg_len_,
+ void *msg_prio_, void *abs_timeout_) {}
+PRE_SYSCALL(compat_60__lwp_park)
+(void *ts_, long long unpark_, void *hint_, void *unparkhint_) {
+ /* TODO */
+}
+POST_SYSCALL(compat_60__lwp_park)
+(long long res, void *ts_, long long unpark_, void *hint_, void *unparkhint_) {
+ /* TODO */
+}
+PRE_SYSCALL(__kevent50)
+(long long fd_, void *changelist_, long long nchanges_, void *eventlist_,
+ long long nevents_, void *timeout_) {
+ if (changelist_) {
+ PRE_READ(changelist_, nchanges_ * struct_kevent_sz);
+ }
+ if (timeout_) {
+ PRE_READ(timeout_, struct_timespec_sz);
+ }
+}
+POST_SYSCALL(__kevent50)
+(long long res, long long fd_, void *changelist_, long long nchanges_,
+ void *eventlist_, long long nevents_, void *timeout_) {}
+PRE_SYSCALL(__pselect50)
+(long long nd_, void *in_, void *ou_, void *ex_, void *ts_, void *mask_) {
+ if (ts_) {
+ PRE_READ(ts_, struct_timespec_sz);
+ }
+ if (mask_) {
+ PRE_READ(mask_, sizeof(struct __sanitizer_sigset_t));
+ }
+}
+POST_SYSCALL(__pselect50)
+(long long res, long long nd_, void *in_, void *ou_, void *ex_, void *ts_,
+ void *mask_) {}
+PRE_SYSCALL(__pollts50)(void *fds_, long long nfds_, void *ts_, void *mask_) {
+ if (ts_) {
+ PRE_READ(ts_, struct_timespec_sz);
+ }
+ if (mask_) {
+ PRE_READ(mask_, sizeof(struct __sanitizer_sigset_t));
+ }
+}
+POST_SYSCALL(__pollts50)
+(long long res, void *fds_, long long nfds_, void *ts_, void *mask_) {}
+PRE_SYSCALL(__aio_suspend50)(void *list_, long long nent_, void *timeout_) {
+ int i;
+ const struct aiocb *const *list = (const struct aiocb *const *)list_;
+ if (list) {
+ for (i = 0; i < nent_; i++) {
+ if (list[i]) {
+ PRE_READ(list[i], sizeof(struct __sanitizer_aiocb));
+ }
+ }
+ }
+ if (timeout_) {
+ PRE_READ(timeout_, struct_timespec_sz);
+ }
+}
+POST_SYSCALL(__aio_suspend50)
+(long long res, void *list_, long long nent_, void *timeout_) {}
+PRE_SYSCALL(__stat50)(void *path_, void *ub_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(__stat50)(long long res, void *path_, void *ub_) {
+ const char *path = (const char *)path_;
+ if (res == 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(__fstat50)(long long fd_, void *sb_) { /* Nothing to do */ }
+POST_SYSCALL(__fstat50)(long long res, long long fd_, void *sb_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__lstat50)(void *path_, void *ub_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(__lstat50)(long long res, void *path_, void *ub_) {
+ const char *path = (const char *)path_;
+ if (res == 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(____semctl50)
+(long long semid_, long long semnum_, long long cmd_, void *arg_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(____semctl50)
+(long long res, long long semid_, long long semnum_, long long cmd_,
+ void *arg_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__shmctl50)(long long shmid_, long long cmd_, void *buf_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__shmctl50)
+(long long res, long long shmid_, long long cmd_, void *buf_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__msgctl50)(long long msqid_, long long cmd_, void *buf_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__msgctl50)
+(long long res, long long msqid_, long long cmd_, void *buf_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__getrusage50)(long long who_, void *rusage_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__getrusage50)(long long res, long long who_, void *rusage_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__timer_settime50)
+(long long timerid_, long long flags_, void *value_, void *ovalue_) {
+ struct __sanitizer_itimerval *value = (struct __sanitizer_itimerval *)value_;
+ if (value) {
+ PRE_READ(&value->it_interval.tv_sec, sizeof(__sanitizer_time_t));
+ PRE_READ(&value->it_interval.tv_usec, sizeof(__sanitizer_suseconds_t));
+ PRE_READ(&value->it_value.tv_sec, sizeof(__sanitizer_time_t));
+ PRE_READ(&value->it_value.tv_usec, sizeof(__sanitizer_suseconds_t));
+ }
+}
+POST_SYSCALL(__timer_settime50)
+(long long res, long long timerid_, long long flags_, void *value_,
+ void *ovalue_) {
+ struct __sanitizer_itimerval *value = (struct __sanitizer_itimerval *)value_;
+ if (res == 0) {
+ if (value) {
+ POST_READ(&value->it_interval.tv_sec, sizeof(__sanitizer_time_t));
+ POST_READ(&value->it_interval.tv_usec, sizeof(__sanitizer_suseconds_t));
+ POST_READ(&value->it_value.tv_sec, sizeof(__sanitizer_time_t));
+ POST_READ(&value->it_value.tv_usec, sizeof(__sanitizer_suseconds_t));
+ }
+ }
+}
+PRE_SYSCALL(__timer_gettime50)(long long timerid_, void *value_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__timer_gettime50)
+(long long res, long long timerid_, void *value_) {
+ /* Nothing to do */
+}
+#if defined(NTP) || !defined(_KERNEL_OPT)
+PRE_SYSCALL(__ntp_gettime50)(void *ntvp_) { /* Nothing to do */ }
+POST_SYSCALL(__ntp_gettime50)(long long res, void *ntvp_) {
+ /* Nothing to do */
+}
+#else
+/* syscall 448 has been skipped */
+#endif
+PRE_SYSCALL(__wait450)
+(long long pid_, void *status_, long long options_, void *rusage_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__wait450)
+(long long res, long long pid_, void *status_, long long options_,
+ void *rusage_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__mknod50)(void *path_, long long mode_, long long dev_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(__mknod50)
+(long long res, void *path_, long long mode_, long long dev_) {
+ const char *path = (const char *)path_;
+ if (res == 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(__fhstat50)(void *fhp_, long long fh_size_, void *sb_) {
+ if (fhp_) {
+ PRE_READ(fhp_, fh_size_);
+ }
+}
+POST_SYSCALL(__fhstat50)
+(long long res, void *fhp_, long long fh_size_, void *sb_) {
+ if (res == 0) {
+ if (fhp_) {
+ POST_READ(fhp_, fh_size_);
+ }
+ }
+}
+/* syscall 452 has been skipped */
+PRE_SYSCALL(pipe2)(void *fildes_, long long flags_) { /* Nothing to do */ }
+POST_SYSCALL(pipe2)(long long res, void *fildes_, long long flags_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(dup3)(long long from_, long long to_, long long flags_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(dup3)
+(long long res, long long from_, long long to_, long long flags_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(kqueue1)(long long flags_) { /* Nothing to do */ }
+POST_SYSCALL(kqueue1)(long long res, long long flags_) { /* Nothing to do */ }
+PRE_SYSCALL(paccept)
+(long long s_, void *name_, void *anamelen_, void *mask_, long long flags_) {
+ if (mask_) {
+ PRE_READ(mask_, sizeof(__sanitizer_sigset_t));
+ }
+}
+POST_SYSCALL(paccept)
+(long long res, long long s_, void *name_, void *anamelen_, void *mask_,
+ long long flags_) {
+ if (res >= 0) {
+ if (mask_) {
+ PRE_READ(mask_, sizeof(__sanitizer_sigset_t));
+ }
+ }
+}
+PRE_SYSCALL(linkat)
+(long long fd1_, void *name1_, long long fd2_, void *name2_, long long flags_) {
+ const char *name1 = (const char *)name1_;
+ const char *name2 = (const char *)name2_;
+ if (name1) {
+ PRE_READ(name1, __sanitizer::internal_strlen(name1) + 1);
+ }
+ if (name2) {
+ PRE_READ(name2, __sanitizer::internal_strlen(name2) + 1);
+ }
+}
+POST_SYSCALL(linkat)
+(long long res, long long fd1_, void *name1_, long long fd2_, void *name2_,
+ long long flags_) {
+ const char *name1 = (const char *)name1_;
+ const char *name2 = (const char *)name2_;
+ if (res == 0) {
+ if (name1) {
+ POST_READ(name1, __sanitizer::internal_strlen(name1) + 1);
+ }
+ if (name2) {
+ POST_READ(name2, __sanitizer::internal_strlen(name2) + 1);
+ }
+ }
+}
+PRE_SYSCALL(renameat)
+(long long fromfd_, void *from_, long long tofd_, void *to_) {
+ const char *from = (const char *)from_;
+ const char *to = (const char *)to_;
+ if (from) {
+ PRE_READ(from, __sanitizer::internal_strlen(from) + 1);
+ }
+ if (to) {
+ PRE_READ(to, __sanitizer::internal_strlen(to) + 1);
+ }
+}
+POST_SYSCALL(renameat)
+(long long res, long long fromfd_, void *from_, long long tofd_, void *to_) {
+ const char *from = (const char *)from_;
+ const char *to = (const char *)to_;
+ if (res == 0) {
+ if (from) {
+ POST_READ(from, __sanitizer::internal_strlen(from) + 1);
+ }
+ if (to) {
+ POST_READ(to, __sanitizer::internal_strlen(to) + 1);
+ }
+ }
+}
+PRE_SYSCALL(mkfifoat)(long long fd_, void *path_, long long mode_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(mkfifoat)
+(long long res, long long fd_, void *path_, long long mode_) {
+ const char *path = (const char *)path_;
+ if (res == 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(mknodat)
+(long long fd_, void *path_, long long mode_, long long PAD_, long long dev_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(mknodat)
+(long long res, long long fd_, void *path_, long long mode_, long long PAD_,
+ long long dev_) {
+ const char *path = (const char *)path_;
+ if (res == 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(mkdirat)(long long fd_, void *path_, long long mode_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(mkdirat)
+(long long res, long long fd_, void *path_, long long mode_) {
+ const char *path = (const char *)path_;
+ if (res == 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(faccessat)
+(long long fd_, void *path_, long long amode_, long long flag_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(faccessat)
+(long long res, long long fd_, void *path_, long long amode_, long long flag_) {
+ const char *path = (const char *)path_;
+ if (res == 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(fchmodat)
+(long long fd_, void *path_, long long mode_, long long flag_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(fchmodat)
+(long long res, long long fd_, void *path_, long long mode_, long long flag_) {
+ const char *path = (const char *)path_;
+ if (res == 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(fchownat)
+(long long fd_, void *path_, long long owner_, long long group_,
+ long long flag_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(fchownat)
+(long long res, long long fd_, void *path_, long long owner_, long long group_,
+ long long flag_) {
+ const char *path = (const char *)path_;
+ if (res == 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(fexecve)(long long fd_, void *argp_, void *envp_) { /* TODO */ }
+POST_SYSCALL(fexecve)(long long res, long long fd_, void *argp_, void *envp_) {
+ /* TODO */
+}
+PRE_SYSCALL(fstatat)(long long fd_, void *path_, void *buf_, long long flag_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(fstatat)
+(long long res, long long fd_, void *path_, void *buf_, long long flag_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(utimensat)
+(long long fd_, void *path_, void *tptr_, long long flag_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (tptr_) {
+ PRE_READ(tptr_, struct_timespec_sz);
+ }
+}
+POST_SYSCALL(utimensat)
+(long long res, long long fd_, void *path_, void *tptr_, long long flag_) {
+ const char *path = (const char *)path_;
+ if (res > 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ if (tptr_) {
+ POST_READ(tptr_, struct_timespec_sz);
+ }
+ }
+}
+PRE_SYSCALL(openat)
+(long long fd_, void *path_, long long oflags_, long long mode_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(openat)
+(long long res, long long fd_, void *path_, long long oflags_,
+ long long mode_) {
+ const char *path = (const char *)path_;
+ if (res > 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(readlinkat)
+(long long fd_, void *path_, void *buf_, long long bufsize_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(readlinkat)
+(long long res, long long fd_, void *path_, void *buf_, long long bufsize_) {
+ const char *path = (const char *)path_;
+ if (res > 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(symlinkat)(void *path1_, long long fd_, void *path2_) {
+ const char *path1 = (const char *)path1_;
+ const char *path2 = (const char *)path2_;
+ if (path1) {
+ PRE_READ(path1, __sanitizer::internal_strlen(path1) + 1);
+ }
+ if (path2) {
+ PRE_READ(path2, __sanitizer::internal_strlen(path2) + 1);
+ }
+}
+POST_SYSCALL(symlinkat)
+(long long res, void *path1_, long long fd_, void *path2_) {
+ const char *path1 = (const char *)path1_;
+ const char *path2 = (const char *)path2_;
+ if (res == 0) {
+ if (path1) {
+ POST_READ(path1, __sanitizer::internal_strlen(path1) + 1);
+ }
+ if (path2) {
+ POST_READ(path2, __sanitizer::internal_strlen(path2) + 1);
+ }
+ }
+}
+PRE_SYSCALL(unlinkat)(long long fd_, void *path_, long long flag_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(unlinkat)
+(long long res, long long fd_, void *path_, long long flag_) {
+ const char *path = (const char *)path_;
+ if (res == 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(futimens)(long long fd_, void *tptr_) {
+ struct __sanitizer_timespec **tptr = (struct __sanitizer_timespec **)tptr_;
+ if (tptr) {
+ PRE_READ(tptr[0], struct_timespec_sz);
+ PRE_READ(tptr[1], struct_timespec_sz);
+ }
+}
+POST_SYSCALL(futimens)(long long res, long long fd_, void *tptr_) {
+ struct __sanitizer_timespec **tptr = (struct __sanitizer_timespec **)tptr_;
+ if (res == 0) {
+ if (tptr) {
+ POST_READ(tptr[0], struct_timespec_sz);
+ POST_READ(tptr[1], struct_timespec_sz);
+ }
+ }
+}
+PRE_SYSCALL(__quotactl)(void *path_, void *args_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(__quotactl)(long long res, void *path_, void *args_) {
+ const char *path = (const char *)path_;
+ if (res == 0) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(posix_spawn)
+(void *pid_, void *path_, void *file_actions_, void *attrp_, void *argv_,
+ void *envp_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(posix_spawn)
+(long long res, void *pid_, void *path_, void *file_actions_, void *attrp_,
+ void *argv_, void *envp_) {
+ const char *path = (const char *)path_;
+ if (pid_) {
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+ }
+}
+PRE_SYSCALL(recvmmsg)
+(long long s_, void *mmsg_, long long vlen_, long long flags_, void *timeout_) {
+ if (timeout_) {
+ PRE_READ(timeout_, struct_timespec_sz);
+ }
+}
+POST_SYSCALL(recvmmsg)
+(long long res, long long s_, void *mmsg_, long long vlen_, long long flags_,
+ void *timeout_) {
+ if (res >= 0) {
+ if (timeout_) {
+ POST_READ(timeout_, struct_timespec_sz);
+ }
+ }
+}
+PRE_SYSCALL(sendmmsg)
+(long long s_, void *mmsg_, long long vlen_, long long flags_) {
+ struct __sanitizer_mmsghdr *mmsg = (struct __sanitizer_mmsghdr *)mmsg_;
+ if (mmsg) {
+ PRE_READ(mmsg, sizeof(struct __sanitizer_mmsghdr) *
+ (vlen_ > 1024 ? 1024 : vlen_));
+ }
+}
+POST_SYSCALL(sendmmsg)
+(long long res, long long s_, void *mmsg_, long long vlen_, long long flags_) {
+ struct __sanitizer_mmsghdr *mmsg = (struct __sanitizer_mmsghdr *)mmsg_;
+ if (res >= 0) {
+ if (mmsg) {
+ POST_READ(mmsg, sizeof(struct __sanitizer_mmsghdr) *
+ (vlen_ > 1024 ? 1024 : vlen_));
+ }
+ }
+}
+PRE_SYSCALL(clock_nanosleep)
+(long long clock_id_, long long flags_, void *rqtp_, void *rmtp_) {
+ if (rqtp_) {
+ PRE_READ(rqtp_, struct_timespec_sz);
+ }
+}
+POST_SYSCALL(clock_nanosleep)
+(long long res, long long clock_id_, long long flags_, void *rqtp_,
+ void *rmtp_) {
+ if (rqtp_) {
+ POST_READ(rqtp_, struct_timespec_sz);
+ }
+}
+PRE_SYSCALL(___lwp_park60)
+(long long clock_id_, long long flags_, void *ts_, long long unpark_,
+ void *hint_, void *unparkhint_) {
+ if (ts_) {
+ PRE_READ(ts_, struct_timespec_sz);
+ }
+}
+POST_SYSCALL(___lwp_park60)
+(long long res, long long clock_id_, long long flags_, void *ts_,
+ long long unpark_, void *hint_, void *unparkhint_) {
+ if (res == 0) {
+ if (ts_) {
+ POST_READ(ts_, struct_timespec_sz);
+ }
+ }
+}
+PRE_SYSCALL(posix_fallocate)
+(long long fd_, long long PAD_, long long pos_, long long len_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(posix_fallocate)
+(long long res, long long fd_, long long PAD_, long long pos_, long long len_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(fdiscard)
+(long long fd_, long long PAD_, long long pos_, long long len_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(fdiscard)
+(long long res, long long fd_, long long PAD_, long long pos_, long long len_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(wait6)
+(long long idtype_, long long id_, void *status_, long long options_,
+ void *wru_, void *info_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(wait6)
+(long long res, long long idtype_, long long id_, void *status_,
+ long long options_, void *wru_, void *info_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(clock_getcpuclockid2)
+(long long idtype_, long long id_, void *clock_id_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(clock_getcpuclockid2)
+(long long res, long long idtype_, long long id_, void *clock_id_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__getvfsstat90)(void *buf_, long long bufsize_, long long flags_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__getvfsstat90)
+(long long res, void *buf_, long long bufsize_, long long flags_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__statvfs190)(void *path_, void *buf_, long long flags_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ PRE_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+POST_SYSCALL(__statvfs190)
+(long long res, void *path_, void *buf_, long long flags_) {
+ const char *path = (const char *)path_;
+ if (path) {
+ POST_READ(path, __sanitizer::internal_strlen(path) + 1);
+ }
+}
+PRE_SYSCALL(__fstatvfs190)(long long fd_, void *buf_, long long flags_) {
+ /* Nothing to do */
+}
+POST_SYSCALL(__fstatvfs190)
+(long long res, long long fd_, void *buf_, long long flags_) {
+ /* Nothing to do */
+}
+PRE_SYSCALL(__fhstatvfs190)
+(void *fhp_, long long fh_size_, void *buf_, long long flags_) {
+ if (fhp_) {
+ PRE_READ(fhp_, fh_size_);
+ }
+}
+POST_SYSCALL(__fhstatvfs190)
+(long long res, void *fhp_, long long fh_size_, void *buf_, long long flags_) {}
+PRE_SYSCALL(__acl_get_link)(void *path_, long long type_, void *aclp_) {
+ /* TODO */
+}
+POST_SYSCALL(__acl_get_link)
+(long long res, void *path_, long long type_, void *aclp_) {
+ /* TODO */
+}
+PRE_SYSCALL(__acl_set_link)(void *path_, long long type_, void *aclp_) {
+ /* TODO */
+}
+POST_SYSCALL(__acl_set_link)
+(long long res, void *path_, long long type_, void *aclp_) {
+ /* TODO */
+}
+PRE_SYSCALL(__acl_delete_link)(void *path_, long long type_) { /* TODO */ }
+POST_SYSCALL(__acl_delete_link)(long long res, void *path_, long long type_) {
+ /* TODO */
+}
+PRE_SYSCALL(__acl_aclcheck_link)(void *path_, long long type_, void *aclp_) {
+ /* TODO */
+}
+POST_SYSCALL(__acl_aclcheck_link)
+(long long res, void *path_, long long type_, void *aclp_) {
+ /* TODO */
+}
+PRE_SYSCALL(__acl_get_file)(void *path_, long long type_, void *aclp_) {
+ /* TODO */
+}
+POST_SYSCALL(__acl_get_file)
+(long long res, void *path_, long long type_, void *aclp_) {
+ /* TODO */
+}
+PRE_SYSCALL(__acl_set_file)(void *path_, long long type_, void *aclp_) {
+ /* TODO */
+}
+POST_SYSCALL(__acl_set_file)
+(long long res, void *path_, long long type_, void *aclp_) {
+ /* TODO */
+}
+PRE_SYSCALL(__acl_get_fd)(long long filedes_, long long type_, void *aclp_) {
+ /* TODO */
+}
+POST_SYSCALL(__acl_get_fd)
+(long long res, long long filedes_, long long type_, void *aclp_) {
+ /* TODO */
+}
+PRE_SYSCALL(__acl_set_fd)(long long filedes_, long long type_, void *aclp_) {
+ /* TODO */
+}
+POST_SYSCALL(__acl_set_fd)
+(long long res, long long filedes_, long long type_, void *aclp_) {
+ /* TODO */
+}
+PRE_SYSCALL(__acl_delete_file)(void *path_, long long type_) { /* TODO */ }
+POST_SYSCALL(__acl_delete_file)(long long res, void *path_, long long type_) {
+ /* TODO */
+}
+PRE_SYSCALL(__acl_delete_fd)(long long filedes_, long long type_) { /* TODO */ }
+POST_SYSCALL(__acl_delete_fd)
+(long long res, long long filedes_, long long type_) {
+ /* TODO */
+}
+PRE_SYSCALL(__acl_aclcheck_file)(void *path_, long long type_, void *aclp_) {
+ /* TODO */
+}
+POST_SYSCALL(__acl_aclcheck_file)
+(long long res, void *path_, long long type_, void *aclp_) {
+ /* TODO */
+}
+PRE_SYSCALL(__acl_aclcheck_fd)
+(long long filedes_, long long type_, void *aclp_) {
+ /* TODO */
+}
+POST_SYSCALL(__acl_aclcheck_fd)
+(long long res, long long filedes_, long long type_, void *aclp_) {
+ /* TODO */
+}
+PRE_SYSCALL(lpathconf)(void *path_, long long name_) { /* TODO */ }
+POST_SYSCALL(lpathconf)(long long res, void *path_, long long name_) {
+ /* TODO */
+}
+#undef SYS_MAXSYSARGS
+} // extern "C"
+
+#undef PRE_SYSCALL
+#undef PRE_READ
+#undef PRE_WRITE
+#undef POST_SYSCALL
+#undef POST_READ
+#undef POST_WRITE
+
+#endif // SANITIZER_NETBSD
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_termination.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_termination.cpp
new file mode 100644
index 00000000000..6a54734353c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_termination.cpp
@@ -0,0 +1,99 @@
+//===-- sanitizer_termination.cpp -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// This file contains the Sanitizer termination functions CheckFailed and Die,
+/// and the callback functionalities associated with them.
+///
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common.h"
+#include "sanitizer_libc.h"
+
+namespace __sanitizer {
+
+static const int kMaxNumOfInternalDieCallbacks = 5;
+static DieCallbackType InternalDieCallbacks[kMaxNumOfInternalDieCallbacks];
+
+bool AddDieCallback(DieCallbackType callback) {
+ for (int i = 0; i < kMaxNumOfInternalDieCallbacks; i++) {
+ if (InternalDieCallbacks[i] == nullptr) {
+ InternalDieCallbacks[i] = callback;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool RemoveDieCallback(DieCallbackType callback) {
+ for (int i = 0; i < kMaxNumOfInternalDieCallbacks; i++) {
+ if (InternalDieCallbacks[i] == callback) {
+ internal_memmove(&InternalDieCallbacks[i], &InternalDieCallbacks[i + 1],
+ sizeof(InternalDieCallbacks[0]) *
+ (kMaxNumOfInternalDieCallbacks - i - 1));
+ InternalDieCallbacks[kMaxNumOfInternalDieCallbacks - 1] = nullptr;
+ return true;
+ }
+ }
+ return false;
+}
+
+static DieCallbackType UserDieCallback;
+void SetUserDieCallback(DieCallbackType callback) {
+ UserDieCallback = callback;
+}
+
+void NORETURN Die() {
+ if (UserDieCallback)
+ UserDieCallback();
+ for (int i = kMaxNumOfInternalDieCallbacks - 1; i >= 0; i--) {
+ if (InternalDieCallbacks[i])
+ InternalDieCallbacks[i]();
+ }
+ if (common_flags()->abort_on_error)
+ Abort();
+ internal__exit(common_flags()->exitcode);
+}
+
+static void (*CheckUnwindCallback)();
+void SetCheckUnwindCallback(void (*callback)()) {
+ CheckUnwindCallback = callback;
+}
+
+void NORETURN CheckFailed(const char *file, int line, const char *cond,
+ u64 v1, u64 v2) {
+ u32 tid = GetTid();
+ Printf("%s: CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx) (tid=%u)\n",
+ SanitizerToolName, StripModuleName(file), line, cond, (uptr)v1,
+ (uptr)v2, tid);
+ static atomic_uint32_t first_tid;
+ u32 cmp = 0;
+ if (!atomic_compare_exchange_strong(&first_tid, &cmp, tid,
+ memory_order_relaxed)) {
+ if (cmp == tid) {
+ // Recursing into CheckFailed.
+ } else {
+ // Another thread fails already, let it print the stack and terminate.
+ SleepForSeconds(2);
+ }
+ Trap();
+ }
+ if (CheckUnwindCallback)
+ CheckUnwindCallback();
+ Die();
+}
+
+} // namespace __sanitizer
+
+using namespace __sanitizer;
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_set_death_callback(void (*callback)(void)) {
+ SetUserDieCallback(callback);
+}
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_thread_registry.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_thread_registry.cpp
new file mode 100644
index 00000000000..278f6defca9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_thread_registry.cpp
@@ -0,0 +1,384 @@
+//===-- sanitizer_thread_registry.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between sanitizer tools.
+//
+// General thread bookkeeping functionality.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_thread_registry.h"
+
+#include "sanitizer_placement_new.h"
+
+namespace __sanitizer {
+
+ThreadContextBase::ThreadContextBase(u32 tid)
+ : tid(tid), unique_id(0), reuse_count(), os_id(0), user_id(0),
+ status(ThreadStatusInvalid), detached(false),
+ thread_type(ThreadType::Regular), parent_tid(0), next(0) {
+ name[0] = '\0';
+ atomic_store(&thread_destroyed, 0, memory_order_release);
+}
+
+ThreadContextBase::~ThreadContextBase() {
+ // ThreadContextBase should never be deleted.
+ CHECK(0);
+}
+
+void ThreadContextBase::SetName(const char *new_name) {
+ name[0] = '\0';
+ if (new_name) {
+ internal_strncpy(name, new_name, sizeof(name));
+ name[sizeof(name) - 1] = '\0';
+ }
+}
+
+void ThreadContextBase::SetDead() {
+ CHECK(status == ThreadStatusRunning ||
+ status == ThreadStatusFinished);
+ status = ThreadStatusDead;
+ user_id = 0;
+ OnDead();
+}
+
+void ThreadContextBase::SetDestroyed() {
+ atomic_store(&thread_destroyed, 1, memory_order_release);
+}
+
+bool ThreadContextBase::GetDestroyed() {
+ return !!atomic_load(&thread_destroyed, memory_order_acquire);
+}
+
+void ThreadContextBase::SetJoined(void *arg) {
+ // FIXME(dvyukov): print message and continue (it's user error).
+ CHECK_EQ(false, detached);
+ CHECK_EQ(ThreadStatusFinished, status);
+ status = ThreadStatusDead;
+ user_id = 0;
+ OnJoined(arg);
+}
+
+void ThreadContextBase::SetFinished() {
+ // ThreadRegistry::FinishThread calls here in ThreadStatusCreated state
+ // for a thread that never actually started. In that case the thread
+ // should go to ThreadStatusFinished regardless of whether it was created
+ // as detached.
+ if (!detached || status == ThreadStatusCreated) status = ThreadStatusFinished;
+ OnFinished();
+}
+
+void ThreadContextBase::SetStarted(tid_t _os_id, ThreadType _thread_type,
+ void *arg) {
+ status = ThreadStatusRunning;
+ os_id = _os_id;
+ thread_type = _thread_type;
+ OnStarted(arg);
+}
+
+void ThreadContextBase::SetCreated(uptr _user_id, u64 _unique_id,
+ bool _detached, u32 _parent_tid, void *arg) {
+ status = ThreadStatusCreated;
+ user_id = _user_id;
+ unique_id = _unique_id;
+ detached = _detached;
+ // Parent tid makes no sense for the main thread.
+ if (tid != kMainTid)
+ parent_tid = _parent_tid;
+ OnCreated(arg);
+}
+
+void ThreadContextBase::Reset() {
+ status = ThreadStatusInvalid;
+ SetName(0);
+ atomic_store(&thread_destroyed, 0, memory_order_release);
+ OnReset();
+}
+
+// ThreadRegistry implementation.
+
+ThreadRegistry::ThreadRegistry(ThreadContextFactory factory)
+ : ThreadRegistry(factory, UINT32_MAX, UINT32_MAX, 0) {}
+
+ThreadRegistry::ThreadRegistry(ThreadContextFactory factory, u32 max_threads,
+ u32 thread_quarantine_size, u32 max_reuse)
+ : context_factory_(factory),
+ max_threads_(max_threads),
+ thread_quarantine_size_(thread_quarantine_size),
+ max_reuse_(max_reuse),
+ mtx_(MutexThreadRegistry),
+ total_threads_(0),
+ alive_threads_(0),
+ max_alive_threads_(0),
+ running_threads_(0) {
+ dead_threads_.clear();
+ invalid_threads_.clear();
+}
+
+void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running,
+ uptr *alive) {
+ ThreadRegistryLock l(this);
+ if (total)
+ *total = threads_.size();
+ if (running) *running = running_threads_;
+ if (alive) *alive = alive_threads_;
+}
+
+uptr ThreadRegistry::GetMaxAliveThreads() {
+ ThreadRegistryLock l(this);
+ return max_alive_threads_;
+}
+
+u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,
+ void *arg) {
+ ThreadRegistryLock l(this);
+ u32 tid = kInvalidTid;
+ ThreadContextBase *tctx = QuarantinePop();
+ if (tctx) {
+ tid = tctx->tid;
+ } else if (threads_.size() < max_threads_) {
+ // Allocate new thread context and tid.
+ tid = threads_.size();
+ tctx = context_factory_(tid);
+ threads_.push_back(tctx);
+ } else {
+#if !SANITIZER_GO
+ Report("%s: Thread limit (%u threads) exceeded. Dying.\n",
+ SanitizerToolName, max_threads_);
+#else
+ Printf("race: limit on %u simultaneously alive goroutines is exceeded,"
+ " dying\n", max_threads_);
+#endif
+ Die();
+ }
+ CHECK_NE(tctx, 0);
+ CHECK_NE(tid, kInvalidTid);
+ CHECK_LT(tid, max_threads_);
+ CHECK_EQ(tctx->status, ThreadStatusInvalid);
+ alive_threads_++;
+ if (max_alive_threads_ < alive_threads_) {
+ max_alive_threads_++;
+ CHECK_EQ(alive_threads_, max_alive_threads_);
+ }
+ if (user_id) {
+ // Ensure that user_id is unique. If it's not the case we are screwed.
+ // Ignoring this situation may lead to very hard to debug false
+ // positives later (e.g. if we join a wrong thread).
+ CHECK(live_.try_emplace(user_id, tid).second);
+ }
+ tctx->SetCreated(user_id, total_threads_++, detached,
+ parent_tid, arg);
+ return tid;
+}
+
+void ThreadRegistry::RunCallbackForEachThreadLocked(ThreadCallback cb,
+ void *arg) {
+ CheckLocked();
+ for (u32 tid = 0; tid < threads_.size(); tid++) {
+ ThreadContextBase *tctx = threads_[tid];
+ if (tctx == 0)
+ continue;
+ cb(tctx, arg);
+ }
+}
+
+u32 ThreadRegistry::FindThread(FindThreadCallback cb, void *arg) {
+ ThreadRegistryLock l(this);
+ for (u32 tid = 0; tid < threads_.size(); tid++) {
+ ThreadContextBase *tctx = threads_[tid];
+ if (tctx != 0 && cb(tctx, arg))
+ return tctx->tid;
+ }
+ return kInvalidTid;
+}
+
+ThreadContextBase *
+ThreadRegistry::FindThreadContextLocked(FindThreadCallback cb, void *arg) {
+ CheckLocked();
+ for (u32 tid = 0; tid < threads_.size(); tid++) {
+ ThreadContextBase *tctx = threads_[tid];
+ if (tctx != 0 && cb(tctx, arg))
+ return tctx;
+ }
+ return 0;
+}
+
+static bool FindThreadContextByOsIdCallback(ThreadContextBase *tctx,
+ void *arg) {
+ return (tctx->os_id == (uptr)arg && tctx->status != ThreadStatusInvalid &&
+ tctx->status != ThreadStatusDead);
+}
+
+ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(tid_t os_id) {
+ return FindThreadContextLocked(FindThreadContextByOsIdCallback,
+ (void *)os_id);
+}
+
+void ThreadRegistry::SetThreadName(u32 tid, const char *name) {
+ ThreadRegistryLock l(this);
+ ThreadContextBase *tctx = threads_[tid];
+ CHECK_NE(tctx, 0);
+ CHECK_EQ(SANITIZER_FUCHSIA ? ThreadStatusCreated : ThreadStatusRunning,
+ tctx->status);
+ tctx->SetName(name);
+}
+
+void ThreadRegistry::SetThreadNameByUserId(uptr user_id, const char *name) {
+ ThreadRegistryLock l(this);
+ if (const auto *tid = live_.find(user_id))
+ threads_[tid->second]->SetName(name);
+}
+
+void ThreadRegistry::DetachThread(u32 tid, void *arg) {
+ ThreadRegistryLock l(this);
+ ThreadContextBase *tctx = threads_[tid];
+ CHECK_NE(tctx, 0);
+ if (tctx->status == ThreadStatusInvalid) {
+ Report("%s: Detach of non-existent thread\n", SanitizerToolName);
+ return;
+ }
+ tctx->OnDetached(arg);
+ if (tctx->status == ThreadStatusFinished) {
+ if (tctx->user_id)
+ live_.erase(tctx->user_id);
+ tctx->SetDead();
+ QuarantinePush(tctx);
+ } else {
+ tctx->detached = true;
+ }
+}
+
+void ThreadRegistry::JoinThread(u32 tid, void *arg) {
+ bool destroyed = false;
+ do {
+ {
+ ThreadRegistryLock l(this);
+ ThreadContextBase *tctx = threads_[tid];
+ CHECK_NE(tctx, 0);
+ if (tctx->status == ThreadStatusInvalid) {
+ Report("%s: Join of non-existent thread\n", SanitizerToolName);
+ return;
+ }
+ if ((destroyed = tctx->GetDestroyed())) {
+ if (tctx->user_id)
+ live_.erase(tctx->user_id);
+ tctx->SetJoined(arg);
+ QuarantinePush(tctx);
+ }
+ }
+ if (!destroyed)
+ internal_sched_yield();
+ } while (!destroyed);
+}
+
+// Normally this is called when the thread is about to exit. If
+// called in ThreadStatusCreated state, then this thread was never
+// really started. We just did CreateThread for a prospective new
+// thread before trying to create it, and then failed to actually
+// create it, and so never called StartThread.
+ThreadStatus ThreadRegistry::FinishThread(u32 tid) {
+ ThreadRegistryLock l(this);
+ CHECK_GT(alive_threads_, 0);
+ alive_threads_--;
+ ThreadContextBase *tctx = threads_[tid];
+ CHECK_NE(tctx, 0);
+ bool dead = tctx->detached;
+ ThreadStatus prev_status = tctx->status;
+ if (tctx->status == ThreadStatusRunning) {
+ CHECK_GT(running_threads_, 0);
+ running_threads_--;
+ } else {
+ // The thread never really existed.
+ CHECK_EQ(tctx->status, ThreadStatusCreated);
+ dead = true;
+ }
+ tctx->SetFinished();
+ if (dead) {
+ if (tctx->user_id)
+ live_.erase(tctx->user_id);
+ tctx->SetDead();
+ QuarantinePush(tctx);
+ }
+ tctx->SetDestroyed();
+ return prev_status;
+}
+
+void ThreadRegistry::StartThread(u32 tid, tid_t os_id, ThreadType thread_type,
+ void *arg) {
+ ThreadRegistryLock l(this);
+ running_threads_++;
+ ThreadContextBase *tctx = threads_[tid];
+ CHECK_NE(tctx, 0);
+ CHECK_EQ(ThreadStatusCreated, tctx->status);
+ tctx->SetStarted(os_id, thread_type, arg);
+}
+
+void ThreadRegistry::QuarantinePush(ThreadContextBase *tctx) {
+ if (tctx->tid == 0)
+ return; // Don't reuse the main thread. It's a special snowflake.
+ dead_threads_.push_back(tctx);
+ if (dead_threads_.size() <= thread_quarantine_size_)
+ return;
+ tctx = dead_threads_.front();
+ dead_threads_.pop_front();
+ CHECK_EQ(tctx->status, ThreadStatusDead);
+ tctx->Reset();
+ tctx->reuse_count++;
+ if (max_reuse_ > 0 && tctx->reuse_count >= max_reuse_)
+ return;
+ invalid_threads_.push_back(tctx);
+}
+
+ThreadContextBase *ThreadRegistry::QuarantinePop() {
+ if (invalid_threads_.size() == 0)
+ return 0;
+ ThreadContextBase *tctx = invalid_threads_.front();
+ invalid_threads_.pop_front();
+ return tctx;
+}
+
+u32 ThreadRegistry::ConsumeThreadUserId(uptr user_id) {
+ ThreadRegistryLock l(this);
+ u32 tid;
+ auto *t = live_.find(user_id);
+ CHECK(t);
+ tid = t->second;
+ live_.erase(t);
+ auto *tctx = threads_[tid];
+ CHECK_EQ(tctx->user_id, user_id);
+ tctx->user_id = 0;
+ return tid;
+}
+
+void ThreadRegistry::SetThreadUserId(u32 tid, uptr user_id) {
+ ThreadRegistryLock l(this);
+ ThreadContextBase *tctx = threads_[tid];
+ CHECK_NE(tctx, 0);
+ CHECK_NE(tctx->status, ThreadStatusInvalid);
+ CHECK_NE(tctx->status, ThreadStatusDead);
+ CHECK_EQ(tctx->user_id, 0);
+ tctx->user_id = user_id;
+ CHECK(live_.try_emplace(user_id, tctx->tid).second);
+}
+
+u32 ThreadRegistry::OnFork(u32 tid) {
+ ThreadRegistryLock l(this);
+ // We only purge user_id (pthread_t) of live threads because
+ // they cause CHECK failures if new threads with matching pthread_t
+ // created after fork.
+ // Potentially we could purge more info (ThreadContextBase themselves),
+ // but it's hard to test and easy to introduce new issues by doing this.
+ for (auto *tctx : threads_) {
+ if (tctx->tid == tid || !tctx->user_id)
+ continue;
+ CHECK(live_.erase(tctx->user_id));
+ tctx->user_id = 0;
+ }
+ return alive_threads_;
+}
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_thread_registry.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_thread_registry.h
new file mode 100644
index 00000000000..2c7e5c276fa
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_thread_registry.h
@@ -0,0 +1,168 @@
+//===-- sanitizer_thread_registry.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between sanitizer tools.
+//
+// General thread bookkeeping functionality.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_THREAD_REGISTRY_H
+#define SANITIZER_THREAD_REGISTRY_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_dense_map.h"
+#include "sanitizer_list.h"
+#include "sanitizer_mutex.h"
+
+namespace __sanitizer {
+
+enum ThreadStatus {
+ ThreadStatusInvalid, // Non-existent thread, data is invalid.
+ ThreadStatusCreated, // Created but not yet running.
+ ThreadStatusRunning, // The thread is currently running.
+ ThreadStatusFinished, // Joinable thread is finished but not yet joined.
+ ThreadStatusDead // Joined, but some info is still available.
+};
+
+enum class ThreadType {
+ Regular, // Normal thread
+ Worker, // macOS Grand Central Dispatch (GCD) worker thread
+ Fiber, // Fiber
+};
+
+// Generic thread context. Specific sanitizer tools may inherit from it.
+// If thread is dead, context may optionally be reused for a new thread.
+class ThreadContextBase {
+ public:
+ explicit ThreadContextBase(u32 tid);
+ const u32 tid; // Thread ID. Main thread should have tid = 0.
+ u64 unique_id; // Unique thread ID.
+ u32 reuse_count; // Number of times this tid was reused.
+ tid_t os_id; // PID (used for reporting).
+ uptr user_id; // Some opaque user thread id (e.g. pthread_t).
+ char name[64]; // As annotated by user.
+
+ ThreadStatus status;
+ bool detached;
+ ThreadType thread_type;
+
+ u32 parent_tid;
+ ThreadContextBase *next; // For storing thread contexts in a list.
+
+ atomic_uint32_t thread_destroyed; // To address race of Joined vs Finished
+
+ void SetName(const char *new_name);
+
+ void SetDead();
+ void SetJoined(void *arg);
+ void SetFinished();
+ void SetStarted(tid_t _os_id, ThreadType _thread_type, void *arg);
+ void SetCreated(uptr _user_id, u64 _unique_id, bool _detached,
+ u32 _parent_tid, void *arg);
+ void Reset();
+
+ void SetDestroyed();
+ bool GetDestroyed();
+
+ // The following methods may be overriden by subclasses.
+ // Some of them take opaque arg that may be optionally be used
+ // by subclasses.
+ virtual void OnDead() {}
+ virtual void OnJoined(void *arg) {}
+ virtual void OnFinished() {}
+ virtual void OnStarted(void *arg) {}
+ virtual void OnCreated(void *arg) {}
+ virtual void OnReset() {}
+ virtual void OnDetached(void *arg) {}
+
+ protected:
+ ~ThreadContextBase();
+};
+
+typedef ThreadContextBase* (*ThreadContextFactory)(u32 tid);
+
+class SANITIZER_MUTEX ThreadRegistry {
+ public:
+ ThreadRegistry(ThreadContextFactory factory);
+ ThreadRegistry(ThreadContextFactory factory, u32 max_threads,
+ u32 thread_quarantine_size, u32 max_reuse);
+ void GetNumberOfThreads(uptr *total = nullptr, uptr *running = nullptr,
+ uptr *alive = nullptr);
+ uptr GetMaxAliveThreads();
+
+ void Lock() SANITIZER_ACQUIRE() { mtx_.Lock(); }
+ void CheckLocked() const SANITIZER_CHECK_LOCKED() { mtx_.CheckLocked(); }
+ void Unlock() SANITIZER_RELEASE() { mtx_.Unlock(); }
+
+ // Should be guarded by ThreadRegistryLock.
+ ThreadContextBase *GetThreadLocked(u32 tid) {
+ return threads_.empty() ? nullptr : threads_[tid];
+ }
+
+ u32 NumThreadsLocked() const { return threads_.size(); }
+
+ u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg);
+
+ typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg);
+ // Invokes callback with a specified arg for each thread context.
+ // Should be guarded by ThreadRegistryLock.
+ void RunCallbackForEachThreadLocked(ThreadCallback cb, void *arg);
+
+ typedef bool (*FindThreadCallback)(ThreadContextBase *tctx, void *arg);
+ // Finds a thread using the provided callback. Returns kInvalidTid if no
+ // thread is found.
+ u32 FindThread(FindThreadCallback cb, void *arg);
+ // Should be guarded by ThreadRegistryLock. Return 0 if no thread
+ // is found.
+ ThreadContextBase *FindThreadContextLocked(FindThreadCallback cb,
+ void *arg);
+ ThreadContextBase *FindThreadContextByOsIDLocked(tid_t os_id);
+
+ void SetThreadName(u32 tid, const char *name);
+ void SetThreadNameByUserId(uptr user_id, const char *name);
+ void DetachThread(u32 tid, void *arg);
+ void JoinThread(u32 tid, void *arg);
+ // Finishes thread and returns previous status.
+ ThreadStatus FinishThread(u32 tid);
+ void StartThread(u32 tid, tid_t os_id, ThreadType thread_type, void *arg);
+ u32 ConsumeThreadUserId(uptr user_id);
+ void SetThreadUserId(u32 tid, uptr user_id);
+
+ // OnFork must be called in the child process after fork to purge old
+ // threads that don't exist anymore (except for the current thread tid).
+ // Returns number of alive threads before fork.
+ u32 OnFork(u32 tid);
+
+ private:
+ const ThreadContextFactory context_factory_;
+ const u32 max_threads_;
+ const u32 thread_quarantine_size_;
+ const u32 max_reuse_;
+
+ Mutex mtx_;
+
+ u64 total_threads_; // Total number of created threads. May be greater than
+ // max_threads_ if contexts were reused.
+ uptr alive_threads_; // Created or running.
+ uptr max_alive_threads_;
+ uptr running_threads_;
+
+ InternalMmapVector<ThreadContextBase *> threads_;
+ IntrusiveList<ThreadContextBase> dead_threads_;
+ IntrusiveList<ThreadContextBase> invalid_threads_;
+ DenseMap<uptr, Tid> live_;
+
+ void QuarantinePush(ThreadContextBase *tctx);
+ ThreadContextBase *QuarantinePop();
+};
+
+typedef GenericScopedLock<ThreadRegistry> ThreadRegistryLock;
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_THREAD_REGISTRY_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_thread_safety.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_thread_safety.h
new file mode 100644
index 00000000000..c34ea804da2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_thread_safety.h
@@ -0,0 +1,49 @@
+//===-- sanitizer_thread_safety.h -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between sanitizer tools.
+//
+// Wrappers around thread safety annotations.
+// https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_THREAD_SAFETY_H
+#define SANITIZER_THREAD_SAFETY_H
+
+#if defined(__clang__)
+# define SANITIZER_THREAD_ANNOTATION(x) __attribute__((x))
+#else
+# define SANITIZER_THREAD_ANNOTATION(x)
+#endif
+
+#define SANITIZER_MUTEX SANITIZER_THREAD_ANNOTATION(capability("mutex"))
+#define SANITIZER_SCOPED_LOCK SANITIZER_THREAD_ANNOTATION(scoped_lockable)
+#define SANITIZER_GUARDED_BY(x) SANITIZER_THREAD_ANNOTATION(guarded_by(x))
+#define SANITIZER_PT_GUARDED_BY(x) SANITIZER_THREAD_ANNOTATION(pt_guarded_by(x))
+#define SANITIZER_REQUIRES(...) \
+ SANITIZER_THREAD_ANNOTATION(requires_capability(__VA_ARGS__))
+#define SANITIZER_REQUIRES_SHARED(...) \
+ SANITIZER_THREAD_ANNOTATION(requires_shared_capability(__VA_ARGS__))
+#define SANITIZER_ACQUIRE(...) \
+ SANITIZER_THREAD_ANNOTATION(acquire_capability(__VA_ARGS__))
+#define SANITIZER_ACQUIRE_SHARED(...) \
+ SANITIZER_THREAD_ANNOTATION(acquire_shared_capability(__VA_ARGS__))
+#define SANITIZER_TRY_ACQUIRE(...) \
+ SANITIZER_THREAD_ANNOTATION(try_acquire_capability(__VA_ARGS__))
+#define SANITIZER_RELEASE(...) \
+ SANITIZER_THREAD_ANNOTATION(release_capability(__VA_ARGS__))
+#define SANITIZER_RELEASE_SHARED(...) \
+ SANITIZER_THREAD_ANNOTATION(release_shared_capability(__VA_ARGS__))
+#define SANITIZER_EXCLUDES(...) \
+ SANITIZER_THREAD_ANNOTATION(locks_excluded(__VA_ARGS__))
+#define SANITIZER_CHECK_LOCKED(...) \
+ SANITIZER_THREAD_ANNOTATION(assert_capability(__VA_ARGS__))
+#define SANITIZER_NO_THREAD_SAFETY_ANALYSIS \
+ SANITIZER_THREAD_ANNOTATION(no_thread_safety_analysis)
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp
new file mode 100644
index 00000000000..b13e2dc9e33
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_tls_get_addr.cpp
@@ -0,0 +1,178 @@
+//===-- sanitizer_tls_get_addr.cpp ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Handle the __tls_get_addr call.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_tls_get_addr.h"
+
+#include "sanitizer_atomic.h"
+#include "sanitizer_flags.h"
+#include "sanitizer_platform_interceptors.h"
+
+namespace __sanitizer {
+#if SANITIZER_INTERCEPT_TLS_GET_ADDR
+
+// The actual parameter that comes to __tls_get_addr
+// is a pointer to a struct with two words in it:
+struct TlsGetAddrParam {
+ uptr dso_id;
+ uptr offset;
+};
+
+// Glibc starting from 2.19 allocates tls using __signal_safe_memalign,
+// which has such header.
+struct Glibc_2_19_tls_header {
+ uptr size;
+ uptr start;
+};
+
+// This must be static TLS
+__attribute__((tls_model("initial-exec")))
+static __thread DTLS dtls;
+
+// Make sure we properly destroy the DTLS objects:
+// this counter should never get too large.
+static atomic_uintptr_t number_of_live_dtls;
+
+static const uptr kDestroyedThread = -1;
+
+static void DTLS_Deallocate(DTLS::DTVBlock *block) {
+ VReport(2, "__tls_get_addr: DTLS_Deallocate %p\n", (void *)block);
+ UnmapOrDie(block, sizeof(DTLS::DTVBlock));
+ atomic_fetch_sub(&number_of_live_dtls, 1, memory_order_relaxed);
+}
+
+static DTLS::DTVBlock *DTLS_NextBlock(atomic_uintptr_t *cur) {
+ uptr v = atomic_load(cur, memory_order_acquire);
+ if (v == kDestroyedThread)
+ return nullptr;
+ DTLS::DTVBlock *next = (DTLS::DTVBlock *)v;
+ if (next)
+ return next;
+ DTLS::DTVBlock *new_dtv =
+ (DTLS::DTVBlock *)MmapOrDie(sizeof(DTLS::DTVBlock), "DTLS_NextBlock");
+ uptr prev = 0;
+ if (!atomic_compare_exchange_strong(cur, &prev, (uptr)new_dtv,
+ memory_order_seq_cst)) {
+ UnmapOrDie(new_dtv, sizeof(DTLS::DTVBlock));
+ return (DTLS::DTVBlock *)prev;
+ }
+ uptr num_live_dtls =
+ atomic_fetch_add(&number_of_live_dtls, 1, memory_order_relaxed);
+ VReport(2, "__tls_get_addr: DTLS_NextBlock %p %zd\n", (void *)&dtls,
+ num_live_dtls);
+ return new_dtv;
+}
+
+static DTLS::DTV *DTLS_Find(uptr id) {
+ VReport(2, "__tls_get_addr: DTLS_Find %p %zd\n", (void *)&dtls, id);
+ static constexpr uptr kPerBlock = ARRAY_SIZE(DTLS::DTVBlock::dtvs);
+ DTLS::DTVBlock *cur = DTLS_NextBlock(&dtls.dtv_block);
+ if (!cur)
+ return nullptr;
+ for (; id >= kPerBlock; id -= kPerBlock) cur = DTLS_NextBlock(&cur->next);
+ return cur->dtvs + id;
+}
+
+void DTLS_Destroy() {
+ if (!common_flags()->intercept_tls_get_addr) return;
+ VReport(2, "__tls_get_addr: DTLS_Destroy %p\n", (void *)&dtls);
+ DTLS::DTVBlock *block = (DTLS::DTVBlock *)atomic_exchange(
+ &dtls.dtv_block, kDestroyedThread, memory_order_release);
+ while (block) {
+ DTLS::DTVBlock *next =
+ (DTLS::DTVBlock *)atomic_load(&block->next, memory_order_acquire);
+ DTLS_Deallocate(block);
+ block = next;
+ }
+}
+
+#if defined(__powerpc64__) || defined(__mips__)
+// This is glibc's TLS_DTV_OFFSET:
+// "Dynamic thread vector pointers point 0x8000 past the start of each
+// TLS block." (sysdeps/<arch>/dl-tls.h)
+static const uptr kDtvOffset = 0x8000;
+#elif defined(__riscv)
+// This is glibc's TLS_DTV_OFFSET:
+// "Dynamic thread vector pointers point 0x800 past the start of each
+// TLS block." (sysdeps/riscv/dl-tls.h)
+static const uptr kDtvOffset = 0x800;
+#else
+static const uptr kDtvOffset = 0;
+#endif
+
+DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
+ uptr static_tls_begin, uptr static_tls_end) {
+ if (!common_flags()->intercept_tls_get_addr) return 0;
+ TlsGetAddrParam *arg = reinterpret_cast<TlsGetAddrParam *>(arg_void);
+ uptr dso_id = arg->dso_id;
+ DTLS::DTV *dtv = DTLS_Find(dso_id);
+ if (!dtv || dtv->beg)
+ return 0;
+ uptr tls_size = 0;
+ uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset - kDtvOffset;
+ VReport(2,
+ "__tls_get_addr: %p {0x%zx,0x%zx} => %p; tls_beg: 0x%zx; sp: %p "
+ "num_live_dtls %zd\n",
+ (void *)arg, arg->dso_id, arg->offset, res, tls_beg, (void *)&tls_beg,
+ atomic_load(&number_of_live_dtls, memory_order_relaxed));
+ if (dtls.last_memalign_ptr == tls_beg) {
+ tls_size = dtls.last_memalign_size;
+ VReport(2, "__tls_get_addr: glibc <=2.18 suspected; tls={0x%zx,0x%zx}\n",
+ tls_beg, tls_size);
+ } else if (tls_beg >= static_tls_begin && tls_beg < static_tls_end) {
+ // This is the static TLS block which was initialized / unpoisoned at thread
+ // creation.
+ VReport(2, "__tls_get_addr: static tls: 0x%zx\n", tls_beg);
+ tls_size = 0;
+ } else if ((tls_beg % 4096) == sizeof(Glibc_2_19_tls_header)) {
+ // We may want to check gnu_get_libc_version().
+ Glibc_2_19_tls_header *header = (Glibc_2_19_tls_header *)tls_beg - 1;
+ tls_size = header->size;
+ tls_beg = header->start;
+ VReport(2, "__tls_get_addr: glibc >=2.19 suspected; tls={0x%zx 0x%zx}\n",
+ tls_beg, tls_size);
+ } else {
+ VReport(2, "__tls_get_addr: Can't guess glibc version\n");
+ // This may happen inside the DTOR of main thread, so just ignore it.
+ tls_size = 0;
+ }
+ dtv->beg = tls_beg;
+ dtv->size = tls_size;
+ return dtv;
+}
+
+void DTLS_on_libc_memalign(void *ptr, uptr size) {
+ if (!common_flags()->intercept_tls_get_addr) return;
+ VReport(2, "DTLS_on_libc_memalign: %p 0x%zx\n", ptr, size);
+ dtls.last_memalign_ptr = reinterpret_cast<uptr>(ptr);
+ dtls.last_memalign_size = size;
+}
+
+DTLS *DTLS_Get() { return &dtls; }
+
+bool DTLSInDestruction(DTLS *dtls) {
+ return atomic_load(&dtls->dtv_block, memory_order_relaxed) ==
+ kDestroyedThread;
+}
+
+#else
+void DTLS_on_libc_memalign(void *ptr, uptr size) {}
+DTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res,
+ unsigned long, unsigned long) { return 0; }
+DTLS *DTLS_Get() { return 0; }
+void DTLS_Destroy() {}
+bool DTLSInDestruction(DTLS *dtls) {
+ UNREACHABLE("dtls is unsupported on this platform!");
+}
+
+#endif // SANITIZER_INTERCEPT_TLS_GET_ADDR
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h
new file mode 100644
index 00000000000..a599c0bbc75
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_tls_get_addr.h
@@ -0,0 +1,79 @@
+//===-- sanitizer_tls_get_addr.h --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Handle the __tls_get_addr call.
+//
+// All this magic is specific to glibc and is required to workaround
+// the lack of interface that would tell us about the Dynamic TLS (DTLS).
+// https://sourceware.org/bugzilla/show_bug.cgi?id=16291
+//
+// The matters get worse because the glibc implementation changed between
+// 2.18 and 2.19:
+// https://groups.google.com/forum/#!topic/address-sanitizer/BfwYD8HMxTM
+//
+// Before 2.19, every DTLS chunk is allocated with __libc_memalign,
+// which we intercept and thus know where is the DTLS.
+// Since 2.19, DTLS chunks are allocated with __signal_safe_memalign,
+// which is an internal function that wraps a mmap call, neither of which
+// we can intercept. Luckily, __signal_safe_memalign has a simple parseable
+// header which we can use.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_TLS_GET_ADDR_H
+#define SANITIZER_TLS_GET_ADDR_H
+
+#include "sanitizer_atomic.h"
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+
+struct DTLS {
+ // Array of DTLS chunks for the current Thread.
+ // If beg == 0, the chunk is unused.
+ struct DTV {
+ uptr beg, size;
+ };
+ struct DTVBlock {
+ atomic_uintptr_t next;
+ DTV dtvs[(4096UL - sizeof(next)) / sizeof(DTLS::DTV)];
+ };
+
+ static_assert(sizeof(DTVBlock) <= 4096UL, "Unexpected block size");
+
+ atomic_uintptr_t dtv_block;
+
+ // Auxiliary fields, don't access them outside sanitizer_tls_get_addr.cpp
+ uptr last_memalign_size;
+ uptr last_memalign_ptr;
+};
+
+template <typename Fn>
+void ForEachDVT(DTLS *dtls, const Fn &fn) {
+ DTLS::DTVBlock *block =
+ (DTLS::DTVBlock *)atomic_load(&dtls->dtv_block, memory_order_acquire);
+ while (block) {
+ int id = 0;
+ for (auto &d : block->dtvs) fn(d, id++);
+ block = (DTLS::DTVBlock *)atomic_load(&block->next, memory_order_acquire);
+ }
+}
+
+// Returns pointer and size of a linker-allocated TLS block.
+// Each block is returned exactly once.
+DTLS::DTV *DTLS_on_tls_get_addr(void *arg, void *res, uptr static_tls_begin,
+ uptr static_tls_end);
+void DTLS_on_libc_memalign(void *ptr, uptr size);
+DTLS *DTLS_Get();
+void DTLS_Destroy(); // Make sure to call this before the thread is destroyed.
+// Returns true if DTLS of suspended thread is in destruction process.
+bool DTLSInDestruction(DTLS *dtls);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_TLS_GET_ADDR_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_type_traits.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_type_traits.cpp
new file mode 100644
index 00000000000..5ee37d7376f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_type_traits.cpp
@@ -0,0 +1,20 @@
+//===-- sanitizer_type_traits.cpp -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements a subset of C++ type traits. This is so we can avoid depending
+// on system C++ headers.
+//
+//===----------------------------------------------------------------------===//
+#include "sanitizer_type_traits.h"
+
+namespace __sanitizer {
+
+const bool true_type::value;
+const bool false_type::value;
+
+} // namespace __sanitizer
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_type_traits.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_type_traits.h
new file mode 100644
index 00000000000..06a44d1b5c7
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_type_traits.h
@@ -0,0 +1,141 @@
+//===-- sanitizer_type_traits.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements a subset of C++ type traits. This is so we can avoid depending
+// on system C++ headers.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_TYPE_TRAITS_H
+#define SANITIZER_TYPE_TRAITS_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+struct true_type {
+ static const bool value = true;
+};
+
+struct false_type {
+ static const bool value = false;
+};
+
+// is_same<T, U>
+//
+// Type trait to compare if types are the same.
+// E.g.
+//
+// ```
+// is_same<int,int>::value - True
+// is_same<int,char>::value - False
+// ```
+template <typename T, typename U>
+struct is_same : public false_type {};
+
+template <typename T>
+struct is_same<T, T> : public true_type {};
+
+// conditional<B, T, F>
+//
+// Defines type as T if B is true or as F otherwise.
+// E.g. the following is true
+//
+// ```
+// is_same<int, conditional<true, int, double>::type>::value
+// is_same<double, conditional<false, int, double>::type>::value
+// ```
+template <bool B, class T, class F>
+struct conditional {
+ using type = T;
+};
+
+template <class T, class F>
+struct conditional<false, T, F> {
+ using type = F;
+};
+
+template <class T>
+struct remove_reference {
+ using type = T;
+};
+template <class T>
+struct remove_reference<T&> {
+ using type = T;
+};
+template <class T>
+struct remove_reference<T&&> {
+ using type = T;
+};
+
+template <class T>
+WARN_UNUSED_RESULT inline typename remove_reference<T>::type&& move(T&& t) {
+ return static_cast<typename remove_reference<T>::type&&>(t);
+}
+
+template <class T>
+WARN_UNUSED_RESULT inline constexpr T&& forward(
+ typename remove_reference<T>::type& t) {
+ return static_cast<T&&>(t);
+}
+
+template <class T>
+WARN_UNUSED_RESULT inline constexpr T&& forward(
+ typename remove_reference<T>::type&& t) {
+ return static_cast<T&&>(t);
+}
+
+template <class T, T v>
+struct integral_constant {
+ static constexpr const T value = v;
+ typedef T value_type;
+ typedef integral_constant type;
+ constexpr operator value_type() const { return value; }
+ constexpr value_type operator()() const { return value; }
+};
+
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+#if __has_builtin(__is_trivially_destructible)
+
+template <class T>
+struct is_trivially_destructible
+ : public integral_constant<bool, __is_trivially_destructible(T)> {};
+
+#elif __has_builtin(__has_trivial_destructor)
+
+template <class T>
+struct is_trivially_destructible
+ : public integral_constant<bool, __has_trivial_destructor(T)> {};
+
+#else
+
+template <class T>
+struct is_trivially_destructible
+ : public integral_constant<bool, /* less efficient fallback */ false> {};
+
+#endif
+
+#if __has_builtin(__is_trivially_copyable)
+
+template <class T>
+struct is_trivially_copyable
+ : public integral_constant<bool, __is_trivially_copyable(T)> {};
+
+#else
+
+template <class T>
+struct is_trivially_copyable
+ : public integral_constant<bool, /* less efficient fallback */ false> {};
+
+#endif
+
+} // namespace __sanitizer
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
new file mode 100644
index 00000000000..72f025a7d30
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
@@ -0,0 +1,180 @@
+//===-- sanitizer_unwind_linux_libcdep.cpp --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the unwind.h-based (aka "slow") stack unwinding routines
+// available to the tools on Linux, Android, NetBSD, FreeBSD, and Solaris.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
+ SANITIZER_SOLARIS
+#include "sanitizer_common.h"
+#include "sanitizer_stacktrace.h"
+
+#if SANITIZER_ANDROID
+#include <dlfcn.h> // for dlopen()
+#endif
+
+#if SANITIZER_FREEBSD
+#define _GNU_SOURCE // to declare _Unwind_Backtrace() from <unwind.h>
+#endif
+#include <unwind.h>
+
+namespace __sanitizer {
+
+namespace {
+
+//---------------------------- UnwindSlow --------------------------------------
+
+typedef struct {
+ uptr absolute_pc;
+ uptr stack_top;
+ uptr stack_size;
+} backtrace_frame_t;
+
+extern "C" {
+typedef void *(*acquire_my_map_info_list_func)();
+typedef void (*release_my_map_info_list_func)(void *map);
+typedef sptr (*unwind_backtrace_signal_arch_func)(
+ void *siginfo, void *sigcontext, void *map_info_list,
+ backtrace_frame_t *backtrace, uptr ignore_depth, uptr max_depth);
+acquire_my_map_info_list_func acquire_my_map_info_list;
+release_my_map_info_list_func release_my_map_info_list;
+unwind_backtrace_signal_arch_func unwind_backtrace_signal_arch;
+} // extern "C"
+
+#if defined(__arm__) && !SANITIZER_NETBSD
+// NetBSD uses dwarf EH
+#define UNWIND_STOP _URC_END_OF_STACK
+#define UNWIND_CONTINUE _URC_NO_REASON
+#else
+#define UNWIND_STOP _URC_NORMAL_STOP
+#define UNWIND_CONTINUE _URC_NO_REASON
+#endif
+
+uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
+#if defined(__arm__) && !SANITIZER_APPLE
+ uptr val;
+ _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
+ 15 /* r15 = PC */, _UVRSD_UINT32, &val);
+ CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
+ // Clear the Thumb bit.
+ return val & ~(uptr)1;
+#else
+ return (uptr)_Unwind_GetIP(ctx);
+#endif
+}
+
+struct UnwindTraceArg {
+ BufferedStackTrace *stack;
+ u32 max_depth;
+};
+
+_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
+ UnwindTraceArg *arg = (UnwindTraceArg*)param;
+ CHECK_LT(arg->stack->size, arg->max_depth);
+ uptr pc = Unwind_GetIP(ctx);
+ const uptr kPageSize = GetPageSizeCached();
+ // Let's assume that any pointer in the 0th page (i.e. <0x1000 on i386 and
+ // x86_64) is invalid and stop unwinding here. If we're adding support for
+ // a platform where this isn't true, we need to reconsider this check.
+ if (pc < kPageSize) return UNWIND_STOP;
+ arg->stack->trace_buffer[arg->stack->size++] = pc;
+ if (arg->stack->size == arg->max_depth) return UNWIND_STOP;
+ return UNWIND_CONTINUE;
+}
+
+} // namespace
+
+#if SANITIZER_ANDROID
+void SanitizerInitializeUnwinder() {
+ if (AndroidGetApiLevel() >= ANDROID_LOLLIPOP_MR1) return;
+
+ // Pre-lollipop Android can not unwind through signal handler frames with
+ // libgcc unwinder, but it has a libcorkscrew.so library with the necessary
+ // workarounds.
+ void *p = dlopen("libcorkscrew.so", RTLD_LAZY);
+ if (!p) {
+ VReport(1,
+ "Failed to open libcorkscrew.so. You may see broken stack traces "
+ "in SEGV reports.");
+ return;
+ }
+ acquire_my_map_info_list =
+ (acquire_my_map_info_list_func)(uptr)dlsym(p, "acquire_my_map_info_list");
+ release_my_map_info_list =
+ (release_my_map_info_list_func)(uptr)dlsym(p, "release_my_map_info_list");
+ unwind_backtrace_signal_arch = (unwind_backtrace_signal_arch_func)(uptr)dlsym(
+ p, "unwind_backtrace_signal_arch");
+ if (!acquire_my_map_info_list || !release_my_map_info_list ||
+ !unwind_backtrace_signal_arch) {
+ VReport(1,
+ "Failed to find one of the required symbols in libcorkscrew.so. "
+ "You may see broken stack traces in SEGV reports.");
+ acquire_my_map_info_list = 0;
+ unwind_backtrace_signal_arch = 0;
+ release_my_map_info_list = 0;
+ }
+}
+#endif
+
+void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
+ CHECK_GE(max_depth, 2);
+ size = 0;
+ UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)};
+ _Unwind_Backtrace(Unwind_Trace, &arg);
+ // We need to pop a few frames so that pc is on top.
+ uptr to_pop = LocatePcInTrace(pc);
+ // trace_buffer[0] belongs to the current function so we always pop it,
+ // unless there is only 1 frame in the stack trace (1 frame is always better
+ // than 0!).
+ // 1-frame stacks don't normally happen, but this depends on the actual
+ // unwinder implementation (libgcc, libunwind, etc) which is outside of our
+ // control.
+ if (to_pop == 0 && size > 1)
+ to_pop = 1;
+ PopStackFrames(to_pop);
+#if defined(__GNUC__) && defined(__sparc__)
+ // __builtin_return_address returns the address of the call instruction
+ // on the SPARC and not the return address, so we need to compensate.
+ trace_buffer[0] = GetNextInstructionPc(pc);
+#else
+ trace_buffer[0] = pc;
+#endif
+}
+
+void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
+ CHECK(context);
+ CHECK_GE(max_depth, 2);
+ if (!unwind_backtrace_signal_arch) {
+ UnwindSlow(pc, max_depth);
+ return;
+ }
+
+ void *map = acquire_my_map_info_list();
+ CHECK(map);
+ InternalMmapVector<backtrace_frame_t> frames(kStackTraceMax);
+ // siginfo argument appears to be unused.
+ sptr res = unwind_backtrace_signal_arch(/* siginfo */ 0, context, map,
+ frames.data(),
+ /* ignore_depth */ 0, max_depth);
+ release_my_map_info_list(map);
+ if (res < 0) return;
+ CHECK_LE((uptr)res, kStackTraceMax);
+
+ size = 0;
+ // +2 compensate for libcorkscrew unwinder returning addresses of call
+ // instructions instead of raw return addresses.
+ for (sptr i = 0; i < res; ++i)
+ trace_buffer[size++] = frames[i].absolute_pc + 2;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
+ // SANITIZER_SOLARIS
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_unwind_win.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_unwind_win.cpp
new file mode 100644
index 00000000000..afcd01dae0b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_unwind_win.cpp
@@ -0,0 +1,93 @@
+//===-- sanitizer_unwind_win.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// Sanitizer unwind Windows specific functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_WINDOWS
+
+#define WIN32_LEAN_AND_MEAN
+#define NOGDI
+#include <windows.h>
+
+#include "sanitizer_dbghelp.h" // for StackWalk64
+#include "sanitizer_stacktrace.h"
+#include "sanitizer_symbolizer.h" // for InitializeDbgHelpIfNeeded
+
+using namespace __sanitizer;
+
+#if !SANITIZER_GO
+void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
+ CHECK_GE(max_depth, 2);
+ // FIXME: CaptureStackBackTrace might be too slow for us.
+ // FIXME: Compare with StackWalk64.
+ // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
+ size = CaptureStackBackTrace(1, Min(max_depth, kStackTraceMax),
+ (void **)&trace_buffer[0], 0);
+ if (size == 0)
+ return;
+
+ // Skip the RTL frames by searching for the PC in the stacktrace.
+ uptr pc_location = LocatePcInTrace(pc);
+ PopStackFrames(pc_location);
+
+ // Replace the first frame with the PC because the frame in the
+ // stacktrace might be incorrect.
+ trace_buffer[0] = pc;
+}
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wframe-larger-than="
+#endif
+void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
+ CHECK(context);
+ CHECK_GE(max_depth, 2);
+ CONTEXT ctx = *(CONTEXT *)context;
+ STACKFRAME64 stack_frame;
+ memset(&stack_frame, 0, sizeof(stack_frame));
+
+ InitializeDbgHelpIfNeeded();
+
+ size = 0;
+# if SANITIZER_WINDOWS64
+# if SANITIZER_ARM64
+ int machine_type = IMAGE_FILE_MACHINE_ARM64;
+ stack_frame.AddrPC.Offset = ctx.Pc;
+ stack_frame.AddrFrame.Offset = ctx.Fp;
+ stack_frame.AddrStack.Offset = ctx.Sp;
+# else
+ int machine_type = IMAGE_FILE_MACHINE_AMD64;
+ stack_frame.AddrPC.Offset = ctx.Rip;
+ stack_frame.AddrFrame.Offset = ctx.Rbp;
+ stack_frame.AddrStack.Offset = ctx.Rsp;
+# endif
+# else
+ int machine_type = IMAGE_FILE_MACHINE_I386;
+ stack_frame.AddrPC.Offset = ctx.Eip;
+ stack_frame.AddrFrame.Offset = ctx.Ebp;
+ stack_frame.AddrStack.Offset = ctx.Esp;
+# endif
+ stack_frame.AddrPC.Mode = AddrModeFlat;
+ stack_frame.AddrFrame.Mode = AddrModeFlat;
+ stack_frame.AddrStack.Mode = AddrModeFlat;
+ while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(),
+ &stack_frame, &ctx, NULL, SymFunctionTableAccess64,
+ SymGetModuleBase64, NULL) &&
+ size < Min(max_depth, kStackTraceMax)) {
+ trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset;
+ }
+}
+# ifdef __clang__
+# pragma clang diagnostic pop
+# endif
+# endif // #if !SANITIZER_GO
+
+#endif // SANITIZER_WINDOWS
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_vector.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_vector.h
new file mode 100644
index 00000000000..79ff275660d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_vector.h
@@ -0,0 +1,124 @@
+//===-- sanitizer_vector.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between sanitizers run-time libraries.
+//
+//===----------------------------------------------------------------------===//
+
+// Low-fat STL-like vector container.
+
+#ifndef SANITIZER_VECTOR_H
+#define SANITIZER_VECTOR_H
+
+#include "sanitizer_common/sanitizer_allocator_internal.h"
+#include "sanitizer_common/sanitizer_libc.h"
+
+namespace __sanitizer {
+
+template<typename T>
+class Vector {
+ public:
+ Vector() : begin_(), end_(), last_() {}
+
+ ~Vector() {
+ if (begin_)
+ InternalFree(begin_);
+ }
+
+ void Reset() {
+ if (begin_)
+ InternalFree(begin_);
+ begin_ = 0;
+ end_ = 0;
+ last_ = 0;
+ }
+
+ uptr Size() const {
+ return end_ - begin_;
+ }
+
+ T &operator[](uptr i) {
+ DCHECK_LT(i, end_ - begin_);
+ return begin_[i];
+ }
+
+ const T &operator[](uptr i) const {
+ DCHECK_LT(i, end_ - begin_);
+ return begin_[i];
+ }
+
+ T *PushBack() {
+ EnsureSize(Size() + 1);
+ T *p = &end_[-1];
+ internal_memset(p, 0, sizeof(*p));
+ return p;
+ }
+
+ T *PushBack(const T& v) {
+ EnsureSize(Size() + 1);
+ T *p = &end_[-1];
+ internal_memcpy(p, &v, sizeof(*p));
+ return p;
+ }
+
+ void PopBack() {
+ DCHECK_GT(end_, begin_);
+ end_--;
+ }
+
+ void Resize(uptr size) {
+ if (size == 0) {
+ end_ = begin_;
+ return;
+ }
+ uptr old_size = Size();
+ if (size <= old_size) {
+ end_ = begin_ + size;
+ return;
+ }
+ EnsureSize(size);
+ if (old_size < size) {
+ internal_memset(&begin_[old_size], 0,
+ sizeof(begin_[old_size]) * (size - old_size));
+ }
+ }
+
+ private:
+ T *begin_;
+ T *end_;
+ T *last_;
+
+ void EnsureSize(uptr size) {
+ if (size <= Size())
+ return;
+ if (size <= (uptr)(last_ - begin_)) {
+ end_ = begin_ + size;
+ return;
+ }
+ uptr cap0 = last_ - begin_;
+ uptr cap = cap0 * 5 / 4; // 25% growth
+ if (cap == 0)
+ cap = 16;
+ if (cap < size)
+ cap = size;
+ T *p = (T*)InternalAlloc(cap * sizeof(T));
+ if (cap0) {
+ internal_memcpy(p, begin_, cap0 * sizeof(T));
+ InternalFree(begin_);
+ }
+ begin_ = p;
+ end_ = begin_ + size;
+ last_ = begin_ + cap;
+ }
+
+ Vector(const Vector&);
+ void operator=(const Vector&);
+};
+} // namespace __sanitizer
+
+#endif // #ifndef SANITIZER_VECTOR_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win.cpp b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win.cpp
new file mode 100644
index 00000000000..34884fee715
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win.cpp
@@ -0,0 +1,1191 @@
+//===-- sanitizer_win.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries and implements windows-specific functions from
+// sanitizer_libc.h.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_WINDOWS
+
+#define WIN32_LEAN_AND_MEAN
+#define NOGDI
+#include <windows.h>
+#include <io.h>
+#include <psapi.h>
+#include <stdlib.h>
+
+#include "sanitizer_common.h"
+#include "sanitizer_file.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_mutex.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_win_defs.h"
+
+#if defined(PSAPI_VERSION) && PSAPI_VERSION == 1
+#pragma comment(lib, "psapi")
+#endif
+#if SANITIZER_WIN_TRACE
+#error #include <traceloggingprovider.h>
+// Windows trace logging provider init
+#pragma comment(lib, "advapi32.lib")
+TRACELOGGING_DECLARE_PROVIDER(g_asan_provider);
+// GUID must be the same in utils/AddressSanitizerLoggingProvider.wprp
+TRACELOGGING_DEFINE_PROVIDER(g_asan_provider, "AddressSanitizerLoggingProvider",
+ (0x6c6c766d, 0x3846, 0x4e6a, 0xa4, 0xfb, 0x5b,
+ 0x53, 0x0b, 0xd0, 0xf3, 0xfa));
+#else
+#define TraceLoggingUnregister(x)
+#endif
+
+// For WaitOnAddress
+# pragma comment(lib, "synchronization.lib")
+
+// A macro to tell the compiler that this part of the code cannot be reached,
+// if the compiler supports this feature. Since we're using this in
+// code that is called when terminating the process, the expansion of the
+// macro should not terminate the process to avoid infinite recursion.
+#if defined(__clang__)
+# define BUILTIN_UNREACHABLE() __builtin_unreachable()
+#elif defined(__GNUC__) && \
+ (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+# define BUILTIN_UNREACHABLE() __builtin_unreachable()
+#elif defined(_MSC_VER)
+# define BUILTIN_UNREACHABLE() __assume(0)
+#else
+# define BUILTIN_UNREACHABLE()
+#endif
+
+namespace __sanitizer {
+
+#include "sanitizer_syscall_generic.inc"
+
+// --------------------- sanitizer_common.h
+uptr GetPageSize() {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return si.dwPageSize;
+}
+
+uptr GetMmapGranularity() {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return si.dwAllocationGranularity;
+}
+
+uptr GetMaxUserVirtualAddress() {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return (uptr)si.lpMaximumApplicationAddress;
+}
+
+uptr GetMaxVirtualAddress() {
+ return GetMaxUserVirtualAddress();
+}
+
+bool FileExists(const char *filename) {
+ return ::GetFileAttributesA(filename) != INVALID_FILE_ATTRIBUTES;
+}
+
+bool DirExists(const char *path) {
+ auto attr = ::GetFileAttributesA(path);
+ return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
+}
+
+uptr internal_getpid() {
+ return GetProcessId(GetCurrentProcess());
+}
+
+int internal_dlinfo(void *handle, int request, void *p) {
+ UNIMPLEMENTED();
+}
+
+// In contrast to POSIX, on Windows GetCurrentThreadId()
+// returns a system-unique identifier.
+tid_t GetTid() {
+ return GetCurrentThreadId();
+}
+
+uptr GetThreadSelf() {
+ return GetTid();
+}
+
+#if !SANITIZER_GO
+void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
+ uptr *stack_bottom) {
+ CHECK(stack_top);
+ CHECK(stack_bottom);
+ MEMORY_BASIC_INFORMATION mbi;
+ CHECK_NE(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)), 0);
+ // FIXME: is it possible for the stack to not be a single allocation?
+ // Are these values what ASan expects to get (reserved, not committed;
+ // including stack guard page) ?
+ *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize;
+ *stack_bottom = (uptr)mbi.AllocationBase;
+}
+#endif // #if !SANITIZER_GO
+
+bool ErrorIsOOM(error_t err) {
+ // TODO: This should check which `err`s correspond to OOM.
+ return false;
+}
+
+void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
+ void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ if (rv == 0)
+ ReportMmapFailureAndDie(size, mem_type, "allocate",
+ GetLastError(), raw_report);
+ return rv;
+}
+
+void UnmapOrDie(void *addr, uptr size) {
+ if (!size || !addr)
+ return;
+
+ MEMORY_BASIC_INFORMATION mbi;
+ CHECK(VirtualQuery(addr, &mbi, sizeof(mbi)));
+
+ // MEM_RELEASE can only be used to unmap whole regions previously mapped with
+ // VirtualAlloc. So we first try MEM_RELEASE since it is better, and if that
+ // fails try MEM_DECOMMIT.
+ if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
+ if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) {
+ Report("ERROR: %s failed to "
+ "deallocate 0x%zx (%zd) bytes at address %p (error code: %d)\n",
+ SanitizerToolName, size, size, addr, GetLastError());
+ CHECK("unable to unmap" && 0);
+ }
+ }
+}
+
+static void *ReturnNullptrOnOOMOrDie(uptr size, const char *mem_type,
+ const char *mmap_type) {
+ error_t last_error = GetLastError();
+ if (last_error == ERROR_NOT_ENOUGH_MEMORY)
+ return nullptr;
+ ReportMmapFailureAndDie(size, mem_type, mmap_type, last_error);
+}
+
+void *MmapOrDieOnFatalError(uptr size, const char *mem_type) {
+ void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ if (rv == 0)
+ return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate");
+ return rv;
+}
+
+// We want to map a chunk of address space aligned to 'alignment'.
+void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
+ const char *mem_type) {
+ CHECK(IsPowerOfTwo(size));
+ CHECK(IsPowerOfTwo(alignment));
+
+ // Windows will align our allocations to at least 64K.
+ alignment = Max(alignment, GetMmapGranularity());
+
+ uptr mapped_addr =
+ (uptr)VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ if (!mapped_addr)
+ return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate aligned");
+
+ // If we got it right on the first try, return. Otherwise, unmap it and go to
+ // the slow path.
+ if (IsAligned(mapped_addr, alignment))
+ return (void*)mapped_addr;
+ if (VirtualFree((void *)mapped_addr, 0, MEM_RELEASE) == 0)
+ ReportMmapFailureAndDie(size, mem_type, "deallocate", GetLastError());
+
+ // If we didn't get an aligned address, overallocate, find an aligned address,
+ // unmap, and try to allocate at that aligned address.
+ int retries = 0;
+ const int kMaxRetries = 10;
+ for (; retries < kMaxRetries &&
+ (mapped_addr == 0 || !IsAligned(mapped_addr, alignment));
+ retries++) {
+ // Overallocate size + alignment bytes.
+ mapped_addr =
+ (uptr)VirtualAlloc(0, size + alignment, MEM_RESERVE, PAGE_NOACCESS);
+ if (!mapped_addr)
+ return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate aligned");
+
+ // Find the aligned address.
+ uptr aligned_addr = RoundUpTo(mapped_addr, alignment);
+
+ // Free the overallocation.
+ if (VirtualFree((void *)mapped_addr, 0, MEM_RELEASE) == 0)
+ ReportMmapFailureAndDie(size, mem_type, "deallocate", GetLastError());
+
+ // Attempt to allocate exactly the number of bytes we need at the aligned
+ // address. This may fail for a number of reasons, in which case we continue
+ // the loop.
+ mapped_addr = (uptr)VirtualAlloc((void *)aligned_addr, size,
+ MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ }
+
+ // Fail if we can't make this work quickly.
+ if (retries == kMaxRetries && mapped_addr == 0)
+ return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate aligned");
+
+ return (void *)mapped_addr;
+}
+
+// ZeroMmapFixedRegion zero's out a region of memory previously returned from a
+// call to one of the MmapFixed* helpers. On non-windows systems this would be
+// done with another mmap, but on windows remapping is not an option.
+// VirtualFree(DECOMMIT)+VirtualAlloc(RECOMMIT) would also be a way to zero the
+// memory, but we can't do this atomically, so instead we fall back to using
+// internal_memset.
+bool ZeroMmapFixedRegion(uptr fixed_addr, uptr size) {
+ internal_memset((void*) fixed_addr, 0, size);
+ return true;
+}
+
+bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
+ // FIXME: is this really "NoReserve"? On Win32 this does not matter much,
+ // but on Win64 it does.
+ (void)name; // unsupported
+#if !SANITIZER_GO && SANITIZER_WINDOWS64
+ // On asan/Windows64, use MEM_COMMIT would result in error
+ // 1455:ERROR_COMMITMENT_LIMIT.
+ // Asan uses exception handler to commit page on demand.
+ void *p = VirtualAlloc((LPVOID)fixed_addr, size, MEM_RESERVE, PAGE_READWRITE);
+#else
+ void *p = VirtualAlloc((LPVOID)fixed_addr, size, MEM_RESERVE | MEM_COMMIT,
+ PAGE_READWRITE);
+#endif
+ if (p == 0) {
+ Report("ERROR: %s failed to "
+ "allocate %p (%zd) bytes at %p (error code: %d)\n",
+ SanitizerToolName, size, size, fixed_addr, GetLastError());
+ return false;
+ }
+ return true;
+}
+
+bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name) {
+ // FIXME: Windows support large pages too. Might be worth checking
+ return MmapFixedNoReserve(fixed_addr, size, name);
+}
+
+// Memory space mapped by 'MmapFixedOrDie' must have been reserved by
+// 'MmapFixedNoAccess'.
+void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) {
+ void *p = VirtualAlloc((LPVOID)fixed_addr, size,
+ MEM_COMMIT, PAGE_READWRITE);
+ if (p == 0) {
+ char mem_type[30];
+ internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
+ fixed_addr);
+ ReportMmapFailureAndDie(size, mem_type, "allocate", GetLastError());
+ }
+ return p;
+}
+
+// Uses fixed_addr for now.
+// Will use offset instead once we've implemented this function for real.
+uptr ReservedAddressRange::Map(uptr fixed_addr, uptr size, const char *name) {
+ return reinterpret_cast<uptr>(MmapFixedOrDieOnFatalError(fixed_addr, size));
+}
+
+uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr size,
+ const char *name) {
+ return reinterpret_cast<uptr>(MmapFixedOrDie(fixed_addr, size));
+}
+
+void ReservedAddressRange::Unmap(uptr addr, uptr size) {
+ // Only unmap if it covers the entire range.
+ CHECK((addr == reinterpret_cast<uptr>(base_)) && (size == size_));
+ // We unmap the whole range, just null out the base.
+ base_ = nullptr;
+ size_ = 0;
+ UnmapOrDie(reinterpret_cast<void*>(addr), size);
+}
+
+void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size, const char *name) {
+ void *p = VirtualAlloc((LPVOID)fixed_addr, size,
+ MEM_COMMIT, PAGE_READWRITE);
+ if (p == 0) {
+ char mem_type[30];
+ internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
+ fixed_addr);
+ return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate");
+ }
+ return p;
+}
+
+void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
+ // FIXME: make this really NoReserve?
+ return MmapOrDie(size, mem_type);
+}
+
+uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) {
+ base_ = fixed_addr ? MmapFixedNoAccess(fixed_addr, size) : MmapNoAccess(size);
+ size_ = size;
+ name_ = name;
+ (void)os_handle_; // unsupported
+ return reinterpret_cast<uptr>(base_);
+}
+
+
+void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) {
+ (void)name; // unsupported
+ void *res = VirtualAlloc((LPVOID)fixed_addr, size,
+ MEM_RESERVE, PAGE_NOACCESS);
+ if (res == 0)
+ Report("WARNING: %s failed to "
+ "mprotect %p (%zd) bytes at %p (error code: %d)\n",
+ SanitizerToolName, size, size, fixed_addr, GetLastError());
+ return res;
+}
+
+void *MmapNoAccess(uptr size) {
+ void *res = VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_NOACCESS);
+ if (res == 0)
+ Report("WARNING: %s failed to "
+ "mprotect %p (%zd) bytes (error code: %d)\n",
+ SanitizerToolName, size, size, GetLastError());
+ return res;
+}
+
+bool MprotectNoAccess(uptr addr, uptr size) {
+ DWORD old_protection;
+ return VirtualProtect((LPVOID)addr, size, PAGE_NOACCESS, &old_protection);
+}
+
+bool MprotectReadOnly(uptr addr, uptr size) {
+ DWORD old_protection;
+ return VirtualProtect((LPVOID)addr, size, PAGE_READONLY, &old_protection);
+}
+
+void ReleaseMemoryPagesToOS(uptr beg, uptr end) {
+ uptr beg_aligned = RoundDownTo(beg, GetPageSizeCached()),
+ end_aligned = RoundDownTo(end, GetPageSizeCached());
+ CHECK(beg < end); // make sure the region is sane
+ if (beg_aligned == end_aligned) // make sure we're freeing at least 1 page;
+ return;
+ UnmapOrDie((void *)beg, end_aligned - beg_aligned);
+}
+
+void SetShadowRegionHugePageMode(uptr addr, uptr size) {
+ // FIXME: probably similar to ReleaseMemoryToOS.
+}
+
+bool DontDumpShadowMemory(uptr addr, uptr length) {
+ // This is almost useless on 32-bits.
+ // FIXME: add madvise-analog when we move to 64-bits.
+ return true;
+}
+
+uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
+ uptr min_shadow_base_alignment,
+ UNUSED uptr &high_mem_end) {
+ const uptr granularity = GetMmapGranularity();
+ const uptr alignment =
+ Max<uptr>(granularity << shadow_scale, 1ULL << min_shadow_base_alignment);
+ const uptr left_padding =
+ Max<uptr>(granularity, 1ULL << min_shadow_base_alignment);
+ uptr space_size = shadow_size_bytes + left_padding;
+ uptr shadow_start = FindAvailableMemoryRange(space_size, alignment,
+ granularity, nullptr, nullptr);
+ CHECK_NE((uptr)0, shadow_start);
+ CHECK(IsAligned(shadow_start, alignment));
+ return shadow_start;
+}
+
+uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
+ uptr *largest_gap_found,
+ uptr *max_occupied_addr) {
+ uptr address = 0;
+ while (true) {
+ MEMORY_BASIC_INFORMATION info;
+ if (!::VirtualQuery((void*)address, &info, sizeof(info)))
+ return 0;
+
+ if (info.State == MEM_FREE) {
+ uptr shadow_address = RoundUpTo((uptr)info.BaseAddress + left_padding,
+ alignment);
+ if (shadow_address + size < (uptr)info.BaseAddress + info.RegionSize)
+ return shadow_address;
+ }
+
+ // Move to the next region.
+ address = (uptr)info.BaseAddress + info.RegionSize;
+ }
+ return 0;
+}
+
+uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,
+ uptr num_aliases, uptr ring_buffer_size) {
+ CHECK(false && "HWASan aliasing is unimplemented on Windows");
+ return 0;
+}
+
+bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
+ MEMORY_BASIC_INFORMATION mbi;
+ CHECK(VirtualQuery((void *)range_start, &mbi, sizeof(mbi)));
+ return mbi.Protect == PAGE_NOACCESS &&
+ (uptr)mbi.BaseAddress + mbi.RegionSize >= range_end;
+}
+
+void *MapFileToMemory(const char *file_name, uptr *buff_size) {
+ UNIMPLEMENTED();
+}
+
+void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset) {
+ UNIMPLEMENTED();
+}
+
+static const int kMaxEnvNameLength = 128;
+static const DWORD kMaxEnvValueLength = 32767;
+
+namespace {
+
+struct EnvVariable {
+ char name[kMaxEnvNameLength];
+ char value[kMaxEnvValueLength];
+};
+
+} // namespace
+
+static const int kEnvVariables = 5;
+static EnvVariable env_vars[kEnvVariables];
+static int num_env_vars;
+
+const char *GetEnv(const char *name) {
+ // Note: this implementation caches the values of the environment variables
+ // and limits their quantity.
+ for (int i = 0; i < num_env_vars; i++) {
+ if (0 == internal_strcmp(name, env_vars[i].name))
+ return env_vars[i].value;
+ }
+ CHECK_LT(num_env_vars, kEnvVariables);
+ DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value,
+ kMaxEnvValueLength);
+ if (rv > 0 && rv < kMaxEnvValueLength) {
+ CHECK_LT(internal_strlen(name), kMaxEnvNameLength);
+ internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength);
+ num_env_vars++;
+ return env_vars[num_env_vars - 1].value;
+ }
+ return 0;
+}
+
+const char *GetPwd() {
+ UNIMPLEMENTED();
+}
+
+u32 GetUid() {
+ UNIMPLEMENTED();
+}
+
+namespace {
+struct ModuleInfo {
+ const char *filepath;
+ uptr base_address;
+ uptr end_address;
+};
+
+#if !SANITIZER_GO
+int CompareModulesBase(const void *pl, const void *pr) {
+ const ModuleInfo *l = (const ModuleInfo *)pl, *r = (const ModuleInfo *)pr;
+ if (l->base_address < r->base_address)
+ return -1;
+ return l->base_address > r->base_address;
+}
+#endif
+} // namespace
+
+#if !SANITIZER_GO
+void DumpProcessMap() {
+ Report("Dumping process modules:\n");
+ ListOfModules modules;
+ modules.init();
+ uptr num_modules = modules.size();
+
+ InternalMmapVector<ModuleInfo> module_infos(num_modules);
+ for (size_t i = 0; i < num_modules; ++i) {
+ module_infos[i].filepath = modules[i].full_name();
+ module_infos[i].base_address = modules[i].ranges().front()->beg;
+ module_infos[i].end_address = modules[i].ranges().back()->end;
+ }
+ qsort(module_infos.data(), num_modules, sizeof(ModuleInfo),
+ CompareModulesBase);
+
+ for (size_t i = 0; i < num_modules; ++i) {
+ const ModuleInfo &mi = module_infos[i];
+ if (mi.end_address != 0) {
+ Printf("\t%p-%p %s\n", mi.base_address, mi.end_address,
+ mi.filepath[0] ? mi.filepath : "[no name]");
+ } else if (mi.filepath[0]) {
+ Printf("\t??\?-??? %s\n", mi.filepath);
+ } else {
+ Printf("\t???\n");
+ }
+ }
+}
+#endif
+
+void DisableCoreDumperIfNecessary() {
+ // Do nothing.
+}
+
+void ReExec() {
+ UNIMPLEMENTED();
+}
+
+void PlatformPrepareForSandboxing(void *args) {}
+
+bool StackSizeIsUnlimited() {
+ UNIMPLEMENTED();
+}
+
+void SetStackSizeLimitInBytes(uptr limit) {
+ UNIMPLEMENTED();
+}
+
+bool AddressSpaceIsUnlimited() {
+ UNIMPLEMENTED();
+}
+
+void SetAddressSpaceUnlimited() {
+ UNIMPLEMENTED();
+}
+
+bool IsPathSeparator(const char c) {
+ return c == '\\' || c == '/';
+}
+
+static bool IsAlpha(char c) {
+ c = ToLower(c);
+ return c >= 'a' && c <= 'z';
+}
+
+bool IsAbsolutePath(const char *path) {
+ return path != nullptr && IsAlpha(path[0]) && path[1] == ':' &&
+ IsPathSeparator(path[2]);
+}
+
+void internal_usleep(u64 useconds) { Sleep(useconds / 1000); }
+
+u64 NanoTime() {
+ static LARGE_INTEGER frequency = {};
+ LARGE_INTEGER counter;
+ if (UNLIKELY(frequency.QuadPart == 0)) {
+ QueryPerformanceFrequency(&frequency);
+ CHECK_NE(frequency.QuadPart, 0);
+ }
+ QueryPerformanceCounter(&counter);
+ counter.QuadPart *= 1000ULL * 1000000ULL;
+ counter.QuadPart /= frequency.QuadPart;
+ return counter.QuadPart;
+}
+
+u64 MonotonicNanoTime() { return NanoTime(); }
+
+void Abort() {
+ internal__exit(3);
+}
+
+bool CreateDir(const char *pathname) {
+ return CreateDirectoryA(pathname, nullptr) != 0;
+}
+
+#if !SANITIZER_GO
+// Read the file to extract the ImageBase field from the PE header. If ASLR is
+// disabled and this virtual address is available, the loader will typically
+// load the image at this address. Therefore, we call it the preferred base. Any
+// addresses in the DWARF typically assume that the object has been loaded at
+// this address.
+static uptr GetPreferredBase(const char *modname, char *buf, size_t buf_size) {
+ fd_t fd = OpenFile(modname, RdOnly, nullptr);
+ if (fd == kInvalidFd)
+ return 0;
+ FileCloser closer(fd);
+
+ // Read just the DOS header.
+ IMAGE_DOS_HEADER dos_header;
+ uptr bytes_read;
+ if (!ReadFromFile(fd, &dos_header, sizeof(dos_header), &bytes_read) ||
+ bytes_read != sizeof(dos_header))
+ return 0;
+
+ // The file should start with the right signature.
+ if (dos_header.e_magic != IMAGE_DOS_SIGNATURE)
+ return 0;
+
+ // The layout at e_lfanew is:
+ // "PE\0\0"
+ // IMAGE_FILE_HEADER
+ // IMAGE_OPTIONAL_HEADER
+ // Seek to e_lfanew and read all that data.
+ if (::SetFilePointer(fd, dos_header.e_lfanew, nullptr, FILE_BEGIN) ==
+ INVALID_SET_FILE_POINTER)
+ return 0;
+ if (!ReadFromFile(fd, buf, buf_size, &bytes_read) || bytes_read != buf_size)
+ return 0;
+
+ // Check for "PE\0\0" before the PE header.
+ char *pe_sig = &buf[0];
+ if (internal_memcmp(pe_sig, "PE\0\0", 4) != 0)
+ return 0;
+
+ // Skip over IMAGE_FILE_HEADER. We could do more validation here if we wanted.
+ IMAGE_OPTIONAL_HEADER *pe_header =
+ (IMAGE_OPTIONAL_HEADER *)(pe_sig + 4 + sizeof(IMAGE_FILE_HEADER));
+
+ // Check for more magic in the PE header.
+ if (pe_header->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
+ return 0;
+
+ // Finally, return the ImageBase.
+ return (uptr)pe_header->ImageBase;
+}
+
+void ListOfModules::init() {
+ clearOrInit();
+ HANDLE cur_process = GetCurrentProcess();
+
+ // Query the list of modules. Start by assuming there are no more than 256
+ // modules and retry if that's not sufficient.
+ HMODULE *hmodules = 0;
+ uptr modules_buffer_size = sizeof(HMODULE) * 256;
+ DWORD bytes_required;
+ while (!hmodules) {
+ hmodules = (HMODULE *)MmapOrDie(modules_buffer_size, __FUNCTION__);
+ CHECK(EnumProcessModules(cur_process, hmodules, modules_buffer_size,
+ &bytes_required));
+ if (bytes_required > modules_buffer_size) {
+ // Either there turned out to be more than 256 hmodules, or new hmodules
+ // could have loaded since the last try. Retry.
+ UnmapOrDie(hmodules, modules_buffer_size);
+ hmodules = 0;
+ modules_buffer_size = bytes_required;
+ }
+ }
+
+ InternalMmapVector<char> buf(4 + sizeof(IMAGE_FILE_HEADER) +
+ sizeof(IMAGE_OPTIONAL_HEADER));
+ InternalMmapVector<wchar_t> modname_utf16(kMaxPathLength);
+ InternalMmapVector<char> module_name(kMaxPathLength);
+ // |num_modules| is the number of modules actually present,
+ size_t num_modules = bytes_required / sizeof(HMODULE);
+ for (size_t i = 0; i < num_modules; ++i) {
+ HMODULE handle = hmodules[i];
+ MODULEINFO mi;
+ if (!GetModuleInformation(cur_process, handle, &mi, sizeof(mi)))
+ continue;
+
+ // Get the UTF-16 path and convert to UTF-8.
+ int modname_utf16_len =
+ GetModuleFileNameW(handle, &modname_utf16[0], kMaxPathLength);
+ if (modname_utf16_len == 0)
+ modname_utf16[0] = '\0';
+ int module_name_len = ::WideCharToMultiByte(
+ CP_UTF8, 0, &modname_utf16[0], modname_utf16_len + 1, &module_name[0],
+ kMaxPathLength, NULL, NULL);
+ module_name[module_name_len] = '\0';
+
+ uptr base_address = (uptr)mi.lpBaseOfDll;
+ uptr end_address = (uptr)mi.lpBaseOfDll + mi.SizeOfImage;
+
+ // Adjust the base address of the module so that we get a VA instead of an
+ // RVA when computing the module offset. This helps llvm-symbolizer find the
+ // right DWARF CU. In the common case that the image is loaded at it's
+ // preferred address, we will now print normal virtual addresses.
+ uptr preferred_base =
+ GetPreferredBase(&module_name[0], &buf[0], buf.size());
+ uptr adjusted_base = base_address - preferred_base;
+
+ modules_.push_back(LoadedModule());
+ LoadedModule &cur_module = modules_.back();
+ cur_module.set(&module_name[0], adjusted_base);
+ // We add the whole module as one single address range.
+ cur_module.addAddressRange(base_address, end_address, /*executable*/ true,
+ /*writable*/ true);
+ }
+ UnmapOrDie(hmodules, modules_buffer_size);
+}
+
+void ListOfModules::fallbackInit() { clear(); }
+
+// We can't use atexit() directly at __asan_init time as the CRT is not fully
+// initialized at this point. Place the functions into a vector and use
+// atexit() as soon as it is ready for use (i.e. after .CRT$XIC initializers).
+InternalMmapVectorNoCtor<void (*)(void)> atexit_functions;
+
+int Atexit(void (*function)(void)) {
+ atexit_functions.push_back(function);
+ return 0;
+}
+
+static int RunAtexit() {
+ TraceLoggingUnregister(g_asan_provider);
+ int ret = 0;
+ for (uptr i = 0; i < atexit_functions.size(); ++i) {
+ ret |= atexit(atexit_functions[i]);
+ }
+ return ret;
+}
+
+#pragma section(".CRT$XID", long, read)
+__declspec(allocate(".CRT$XID")) int (*__run_atexit)() = RunAtexit;
+#endif
+
+// ------------------ sanitizer_libc.h
+fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *last_error) {
+ // FIXME: Use the wide variants to handle Unicode filenames.
+ fd_t res;
+ if (mode == RdOnly) {
+ res = CreateFileA(filename, GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
+ } else if (mode == WrOnly) {
+ res = CreateFileA(filename, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, nullptr);
+ } else {
+ UNIMPLEMENTED();
+ }
+ CHECK(res != kStdoutFd || kStdoutFd == kInvalidFd);
+ CHECK(res != kStderrFd || kStderrFd == kInvalidFd);
+ if (res == kInvalidFd && last_error)
+ *last_error = GetLastError();
+ return res;
+}
+
+void CloseFile(fd_t fd) {
+ CloseHandle(fd);
+}
+
+bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read,
+ error_t *error_p) {
+ CHECK(fd != kInvalidFd);
+
+ // bytes_read can't be passed directly to ReadFile:
+ // uptr is unsigned long long on 64-bit Windows.
+ unsigned long num_read_long;
+
+ bool success = ::ReadFile(fd, buff, buff_size, &num_read_long, nullptr);
+ if (!success && error_p)
+ *error_p = GetLastError();
+ if (bytes_read)
+ *bytes_read = num_read_long;
+ return success;
+}
+
+bool SupportsColoredOutput(fd_t fd) {
+ // FIXME: support colored output.
+ return false;
+}
+
+bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written,
+ error_t *error_p) {
+ CHECK(fd != kInvalidFd);
+
+ // Handle null optional parameters.
+ error_t dummy_error;
+ error_p = error_p ? error_p : &dummy_error;
+ uptr dummy_bytes_written;
+ bytes_written = bytes_written ? bytes_written : &dummy_bytes_written;
+
+ // Initialize output parameters in case we fail.
+ *error_p = 0;
+ *bytes_written = 0;
+
+ // Map the conventional Unix fds 1 and 2 to Windows handles. They might be
+ // closed, in which case this will fail.
+ if (fd == kStdoutFd || fd == kStderrFd) {
+ fd = GetStdHandle(fd == kStdoutFd ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
+ if (fd == 0) {
+ *error_p = ERROR_INVALID_HANDLE;
+ return false;
+ }
+ }
+
+ DWORD bytes_written_32;
+ if (!WriteFile(fd, buff, buff_size, &bytes_written_32, 0)) {
+ *error_p = GetLastError();
+ return false;
+ } else {
+ *bytes_written = bytes_written_32;
+ return true;
+ }
+}
+
+uptr internal_sched_yield() {
+ Sleep(0);
+ return 0;
+}
+
+void internal__exit(int exitcode) {
+ TraceLoggingUnregister(g_asan_provider);
+ // ExitProcess runs some finalizers, so use TerminateProcess to avoid that.
+ // The debugger doesn't stop on TerminateProcess like it does on ExitProcess,
+ // so add our own breakpoint here.
+ if (::IsDebuggerPresent())
+ __debugbreak();
+ TerminateProcess(GetCurrentProcess(), exitcode);
+ BUILTIN_UNREACHABLE();
+}
+
+uptr internal_ftruncate(fd_t fd, uptr size) {
+ UNIMPLEMENTED();
+}
+
+uptr GetRSS() {
+ PROCESS_MEMORY_COUNTERS counters;
+ if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
+ return 0;
+ return counters.WorkingSetSize;
+}
+
+void *internal_start_thread(void *(*func)(void *arg), void *arg) { return 0; }
+void internal_join_thread(void *th) { }
+
+void FutexWait(atomic_uint32_t *p, u32 cmp) {
+ WaitOnAddress(p, &cmp, sizeof(cmp), INFINITE);
+}
+
+void FutexWake(atomic_uint32_t *p, u32 count) {
+ if (count == 1)
+ WakeByAddressSingle(p);
+ else
+ WakeByAddressAll(p);
+}
+
+uptr GetTlsSize() {
+ return 0;
+}
+
+void InitTlsSize() {
+}
+
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+ uptr *tls_addr, uptr *tls_size) {
+#if SANITIZER_GO
+ *stk_addr = 0;
+ *stk_size = 0;
+ *tls_addr = 0;
+ *tls_size = 0;
+#else
+ uptr stack_top, stack_bottom;
+ GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
+ *stk_addr = stack_bottom;
+ *stk_size = stack_top - stack_bottom;
+ *tls_addr = 0;
+ *tls_size = 0;
+#endif
+}
+
+void ReportFile::Write(const char *buffer, uptr length) {
+ SpinMutexLock l(mu);
+ ReopenIfNecessary();
+ if (!WriteToFile(fd, buffer, length)) {
+ // stderr may be closed, but we may be able to print to the debugger
+ // instead. This is the case when launching a program from Visual Studio,
+ // and the following routine should write to its console.
+ OutputDebugStringA(buffer);
+ }
+}
+
+void SetAlternateSignalStack() {
+ // FIXME: Decide what to do on Windows.
+}
+
+void UnsetAlternateSignalStack() {
+ // FIXME: Decide what to do on Windows.
+}
+
+void InstallDeadlySignalHandlers(SignalHandlerType handler) {
+ (void)handler;
+ // FIXME: Decide what to do on Windows.
+}
+
+HandleSignalMode GetHandleSignalMode(int signum) {
+ // FIXME: Decide what to do on Windows.
+ return kHandleSignalNo;
+}
+
+// Check based on flags if we should handle this exception.
+bool IsHandledDeadlyException(DWORD exceptionCode) {
+ switch (exceptionCode) {
+ case EXCEPTION_ACCESS_VIOLATION:
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ case EXCEPTION_STACK_OVERFLOW:
+ case EXCEPTION_DATATYPE_MISALIGNMENT:
+ case EXCEPTION_IN_PAGE_ERROR:
+ return common_flags()->handle_segv;
+ case EXCEPTION_ILLEGAL_INSTRUCTION:
+ case EXCEPTION_PRIV_INSTRUCTION:
+ case EXCEPTION_BREAKPOINT:
+ return common_flags()->handle_sigill;
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ case EXCEPTION_FLT_OVERFLOW:
+ case EXCEPTION_FLT_STACK_CHECK:
+ case EXCEPTION_FLT_UNDERFLOW:
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ case EXCEPTION_INT_OVERFLOW:
+ return common_flags()->handle_sigfpe;
+ }
+ return false;
+}
+
+bool IsAccessibleMemoryRange(uptr beg, uptr size) {
+ SYSTEM_INFO si;
+ GetNativeSystemInfo(&si);
+ uptr page_size = si.dwPageSize;
+ uptr page_mask = ~(page_size - 1);
+
+ for (uptr page = beg & page_mask, end = (beg + size - 1) & page_mask;
+ page <= end;) {
+ MEMORY_BASIC_INFORMATION info;
+ if (VirtualQuery((LPCVOID)page, &info, sizeof(info)) != sizeof(info))
+ return false;
+
+ if (info.Protect == 0 || info.Protect == PAGE_NOACCESS ||
+ info.Protect == PAGE_EXECUTE)
+ return false;
+
+ if (info.RegionSize == 0)
+ return false;
+
+ page += info.RegionSize;
+ }
+
+ return true;
+}
+
+bool SignalContext::IsStackOverflow() const {
+ return (DWORD)GetType() == EXCEPTION_STACK_OVERFLOW;
+}
+
+void SignalContext::InitPcSpBp() {
+ EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
+ CONTEXT *context_record = (CONTEXT *)context;
+
+ pc = (uptr)exception_record->ExceptionAddress;
+# if SANITIZER_WINDOWS64
+# if SANITIZER_ARM64
+ bp = (uptr)context_record->Fp;
+ sp = (uptr)context_record->Sp;
+# else
+ bp = (uptr)context_record->Rbp;
+ sp = (uptr)context_record->Rsp;
+# endif
+# else
+ bp = (uptr)context_record->Ebp;
+ sp = (uptr)context_record->Esp;
+# endif
+}
+
+uptr SignalContext::GetAddress() const {
+ EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
+ if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
+ return exception_record->ExceptionInformation[1];
+ return (uptr)exception_record->ExceptionAddress;
+}
+
+bool SignalContext::IsMemoryAccess() const {
+ return ((EXCEPTION_RECORD *)siginfo)->ExceptionCode ==
+ EXCEPTION_ACCESS_VIOLATION;
+}
+
+bool SignalContext::IsTrueFaultingAddress() const { return true; }
+
+SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
+ EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD *)siginfo;
+
+ // The write flag is only available for access violation exceptions.
+ if (exception_record->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
+ return SignalContext::Unknown;
+
+ // The contents of this array are documented at
+ // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_record
+ // The first element indicates read as 0, write as 1, or execute as 8. The
+ // second element is the faulting address.
+ switch (exception_record->ExceptionInformation[0]) {
+ case 0:
+ return SignalContext::Read;
+ case 1:
+ return SignalContext::Write;
+ case 8:
+ return SignalContext::Unknown;
+ }
+ return SignalContext::Unknown;
+}
+
+void SignalContext::DumpAllRegisters(void *context) {
+ // FIXME: Implement this.
+}
+
+int SignalContext::GetType() const {
+ return static_cast<const EXCEPTION_RECORD *>(siginfo)->ExceptionCode;
+}
+
+const char *SignalContext::Describe() const {
+ unsigned code = GetType();
+ // Get the string description of the exception if this is a known deadly
+ // exception.
+ switch (code) {
+ case EXCEPTION_ACCESS_VIOLATION:
+ return "access-violation";
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ return "array-bounds-exceeded";
+ case EXCEPTION_STACK_OVERFLOW:
+ return "stack-overflow";
+ case EXCEPTION_DATATYPE_MISALIGNMENT:
+ return "datatype-misalignment";
+ case EXCEPTION_IN_PAGE_ERROR:
+ return "in-page-error";
+ case EXCEPTION_ILLEGAL_INSTRUCTION:
+ return "illegal-instruction";
+ case EXCEPTION_PRIV_INSTRUCTION:
+ return "priv-instruction";
+ case EXCEPTION_BREAKPOINT:
+ return "breakpoint";
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ return "flt-denormal-operand";
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ return "flt-divide-by-zero";
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ return "flt-inexact-result";
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ return "flt-invalid-operation";
+ case EXCEPTION_FLT_OVERFLOW:
+ return "flt-overflow";
+ case EXCEPTION_FLT_STACK_CHECK:
+ return "flt-stack-check";
+ case EXCEPTION_FLT_UNDERFLOW:
+ return "flt-underflow";
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ return "int-divide-by-zero";
+ case EXCEPTION_INT_OVERFLOW:
+ return "int-overflow";
+ }
+ return "unknown exception";
+}
+
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
+ if (buf_len == 0)
+ return 0;
+
+ // Get the UTF-16 path and convert to UTF-8.
+ InternalMmapVector<wchar_t> binname_utf16(kMaxPathLength);
+ int binname_utf16_len =
+ GetModuleFileNameW(NULL, &binname_utf16[0], kMaxPathLength);
+ if (binname_utf16_len == 0) {
+ buf[0] = '\0';
+ return 0;
+ }
+ int binary_name_len =
+ ::WideCharToMultiByte(CP_UTF8, 0, &binname_utf16[0], binname_utf16_len,
+ buf, buf_len, NULL, NULL);
+ if ((unsigned)binary_name_len == buf_len)
+ --binary_name_len;
+ buf[binary_name_len] = '\0';
+ return binary_name_len;
+}
+
+uptr ReadLongProcessName(/*out*/char *buf, uptr buf_len) {
+ return ReadBinaryName(buf, buf_len);
+}
+
+void CheckVMASize() {
+ // Do nothing.
+}
+
+void InitializePlatformEarly() {
+ // Do nothing.
+}
+
+void CheckASLR() {
+ // Do nothing
+}
+
+void CheckMPROTECT() {
+ // Do nothing
+}
+
+char **GetArgv() {
+ // FIXME: Actually implement this function.
+ return 0;
+}
+
+char **GetEnviron() {
+ // FIXME: Actually implement this function.
+ return 0;
+}
+
+pid_t StartSubprocess(const char *program, const char *const argv[],
+ const char *const envp[], fd_t stdin_fd, fd_t stdout_fd,
+ fd_t stderr_fd) {
+ // FIXME: implement on this platform
+ // Should be implemented based on
+ // SymbolizerProcess::StarAtSymbolizerSubprocess
+ // from lib/sanitizer_common/sanitizer_symbolizer_win.cpp.
+ return -1;
+}
+
+bool IsProcessRunning(pid_t pid) {
+ // FIXME: implement on this platform.
+ return false;
+}
+
+int WaitForProcess(pid_t pid) { return -1; }
+
+// FIXME implement on this platform.
+void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
+
+void CheckNoDeepBind(const char *filename, int flag) {
+ // Do nothing.
+}
+
+// FIXME: implement on this platform.
+bool GetRandom(void *buffer, uptr length, bool blocking) {
+ UNIMPLEMENTED();
+}
+
+u32 GetNumberOfCPUs() {
+ SYSTEM_INFO sysinfo = {};
+ GetNativeSystemInfo(&sysinfo);
+ return sysinfo.dwNumberOfProcessors;
+}
+
+#if SANITIZER_WIN_TRACE
+// TODO(mcgov): Rename this project-wide to PlatformLogInit
+void AndroidLogInit(void) {
+ HRESULT hr = TraceLoggingRegister(g_asan_provider);
+ if (!SUCCEEDED(hr))
+ return;
+}
+
+void SetAbortMessage(const char *) {}
+
+void LogFullErrorReport(const char *buffer) {
+ if (common_flags()->log_to_syslog) {
+ InternalMmapVector<wchar_t> filename;
+ DWORD filename_length = 0;
+ do {
+ filename.resize(filename.size() + 0x100);
+ filename_length =
+ GetModuleFileNameW(NULL, filename.begin(), filename.size());
+ } while (filename_length >= filename.size());
+ TraceLoggingWrite(g_asan_provider, "AsanReportEvent",
+ TraceLoggingValue(filename.begin(), "ExecutableName"),
+ TraceLoggingValue(buffer, "AsanReportContents"));
+ }
+}
+#endif // SANITIZER_WIN_TRACE
+
+void InitializePlatformCommonFlags(CommonFlags *cf) {}
+
+} // namespace __sanitizer
+
+#endif // _WIN32
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win.h
new file mode 100644
index 00000000000..ff8939ca5e8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win.h
@@ -0,0 +1,25 @@
+//===-- sanitizer_win.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Windows-specific declarations.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_WIN_H
+#define SANITIZER_WIN_H
+
+#include "sanitizer_platform.h"
+#if SANITIZER_WINDOWS
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+// Check based on flags if we should handle the exception.
+bool IsHandledDeadlyException(DWORD exceptionCode);
+} // namespace __sanitizer
+
+#endif // SANITIZER_WINDOWS
+#endif // SANITIZER_WIN_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win_defs.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win_defs.h
new file mode 100644
index 00000000000..bfe38a33236
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win_defs.h
@@ -0,0 +1,174 @@
+//===-- sanitizer_win_defs.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Common definitions for Windows-specific code.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_WIN_DEFS_H
+#define SANITIZER_WIN_DEFS_H
+
+#include "sanitizer_platform.h"
+#if SANITIZER_WINDOWS
+
+#ifndef WINAPI
+#if defined(_M_IX86) || defined(__i386__)
+#define WINAPI __stdcall
+#else
+#define WINAPI
+#endif
+#endif
+
+#if defined(_M_IX86) || defined(__i386__)
+#define WIN_SYM_PREFIX "_"
+#else
+#define WIN_SYM_PREFIX
+#endif
+
+// For MinGW, the /export: directives contain undecorated symbols, contrary to
+// link/lld-link. The GNU linker doesn't support /alternatename and /include
+// though, thus lld-link in MinGW mode interprets them in the same way as
+// in the default mode.
+#ifdef __MINGW32__
+#define WIN_EXPORT_PREFIX
+#else
+#define WIN_EXPORT_PREFIX WIN_SYM_PREFIX
+#endif
+
+// Intermediate macro to ensure the parameter is expanded before stringified.
+#define STRINGIFY_(A) #A
+#define STRINGIFY(A) STRINGIFY_(A)
+
+#if !SANITIZER_GO
+
+// ----------------- A workaround for the absence of weak symbols --------------
+// We don't have a direct equivalent of weak symbols when using MSVC, but we can
+// use the /alternatename directive to tell the linker to default a specific
+// symbol to a specific value.
+// Take into account that this is a pragma directive for the linker, so it will
+// be ignored by the compiler and the function will be marked as UNDEF in the
+// symbol table of the resulting object file. The linker won't find the default
+// implementation until it links with that object file.
+// So, suppose we provide a default implementation "fundef" for "fun", and this
+// is compiled into the object file "test.obj" including the pragma directive.
+// If we have some code with references to "fun" and we link that code with
+// "test.obj", it will work because the linker always link object files.
+// But, if "test.obj" is included in a static library, like "test.lib", then the
+// liker will only link to "test.obj" if necessary. If we only included the
+// definition of "fun", it won't link to "test.obj" (from test.lib) because
+// "fun" appears as UNDEF, so it doesn't resolve the symbol "fun", and will
+// result in a link error (the linker doesn't find the pragma directive).
+// So, a workaround is to force linkage with the modules that include weak
+// definitions, with the following macro: WIN_FORCE_LINK()
+
+#define WIN_WEAK_ALIAS(Name, Default) \
+ __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY(Name) "="\
+ WIN_SYM_PREFIX STRINGIFY(Default)))
+
+#define WIN_FORCE_LINK(Name) \
+ __pragma(comment(linker, "/include:" WIN_SYM_PREFIX STRINGIFY(Name)))
+
+#define WIN_EXPORT(ExportedName, Name) \
+ __pragma(comment(linker, "/export:" WIN_EXPORT_PREFIX STRINGIFY(ExportedName)\
+ "=" WIN_EXPORT_PREFIX STRINGIFY(Name)))
+
+// We cannot define weak functions on Windows, but we can use WIN_WEAK_ALIAS()
+// which defines an alias to a default implementation, and only works when
+// linking statically.
+// So, to define a weak function "fun", we define a default implementation with
+// a different name "fun__def" and we create a "weak alias" fun = fun__def.
+// Then, users can override it just defining "fun".
+// We impose "extern "C"" because otherwise WIN_WEAK_ALIAS() will fail because
+// of name mangling.
+
+// Dummy name for default implementation of weak function.
+# define WEAK_DEFAULT_NAME(Name) Name##__def
+// Name for exported implementation of weak function.
+# define WEAK_EXPORT_NAME(Name) Name##__dll
+
+// Use this macro when you need to define and export a weak function from a
+// library. For example:
+// WIN_WEAK_EXPORT_DEF(bool, compare, int a, int b) { return a > b; }
+# define WIN_WEAK_EXPORT_DEF(ReturnType, Name, ...) \
+ WIN_WEAK_ALIAS(Name, WEAK_DEFAULT_NAME(Name)) \
+ WIN_EXPORT(WEAK_EXPORT_NAME(Name), Name) \
+ extern "C" ReturnType Name(__VA_ARGS__); \
+ extern "C" ReturnType WEAK_DEFAULT_NAME(Name)(__VA_ARGS__)
+
+// Use this macro when you need to import a weak function from a library. It
+// defines a weak alias to the imported function from the dll. For example:
+// WIN_WEAK_IMPORT_DEF(compare)
+# define WIN_WEAK_IMPORT_DEF(Name) \
+ WIN_WEAK_ALIAS(Name, WEAK_EXPORT_NAME(Name))
+
+// So, for Windows we provide something similar to weak symbols in Linux, with
+// some differences:
+// + A default implementation must always be provided.
+//
+// + When linking statically it works quite similarly. For example:
+//
+// // libExample.cc
+// WIN_WEAK_EXPORT_DEF(bool, compare, int a, int b) { return a > b; }
+//
+// // client.cc
+// // We can use the default implementation from the library:
+// compare(1, 2);
+// // Or we can override it:
+// extern "C" bool compare (int a, int b) { return a >= b; }
+//
+// And it will work fine. If we don't override the function, we need to ensure
+// that the linker includes the object file with the default implementation.
+// We can do so with the linker option "-wholearchive:".
+//
+// + When linking dynamically with a library (dll), weak functions are exported
+// with "__dll" suffix. Clients can use the macro WIN_WEAK_IMPORT_DEF(fun)
+// which defines a "weak alias" fun = fun__dll.
+//
+// // libExample.cc
+// WIN_WEAK_EXPORT_DEF(bool, compare, int a, int b) { return a > b; }
+//
+// // client.cc
+// WIN_WEAK_IMPORT_DEF(compare)
+// // We can use the default implementation from the library:
+// compare(1, 2);
+// // Or we can override it:
+// extern "C" bool compare (int a, int b) { return a >= b; }
+//
+// But if we override the function, the dlls don't have access to it (which
+// is different in linux). If that is desired, the strong definition must be
+// exported and interception can be used from the rest of the dlls.
+//
+// // libExample.cc
+// WIN_WEAK_EXPORT_DEF(bool, compare, int a, int b) { return a > b; }
+// // When initialized, check if the main executable defined "compare".
+// int libExample_init() {
+// uptr fnptr = __interception::InternalGetProcAddress(
+// (void *)GetModuleHandleA(0), "compare");
+// if (fnptr && !__interception::OverrideFunction((uptr)compare, fnptr, 0))
+// abort();
+// return 0;
+// }
+//
+// // client.cc
+// WIN_WEAK_IMPORT_DEF(compare)
+// // We override and export compare:
+// extern "C" __declspec(dllexport) bool compare (int a, int b) {
+// return a >= b;
+// }
+//
+
+#else // SANITIZER_GO
+
+// Go neither needs nor wants weak references.
+// The shenanigans above don't work for gcc.
+# define WIN_WEAK_EXPORT_DEF(ReturnType, Name, ...) \
+ extern "C" ReturnType Name(__VA_ARGS__)
+
+#endif // SANITIZER_GO
+
+#endif // SANITIZER_WINDOWS
+#endif // SANITIZER_WIN_DEFS_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.h
new file mode 100644
index 00000000000..48c73c4c98a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.h
@@ -0,0 +1,181 @@
+//===-- sanitizer_win_dll_thunk.h -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// This header provide helper macros to delegate calls to the shared runtime
+// that lives in the main executable. It should be included to dll_thunks that
+// will be linked to the dlls, when the sanitizer is a static library included
+// in the main executable.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_WIN_DLL_THUNK_H
+#define SANITIZER_WIN_DLL_THUNK_H
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+uptr dllThunkGetRealAddrOrDie(const char *name);
+
+int dllThunkIntercept(const char* main_function, uptr dll_function);
+
+int dllThunkInterceptWhenPossible(const char* main_function,
+ const char* default_function, uptr dll_function);
+}
+
+extern "C" int __dll_thunk_init();
+
+// ----------------- Function interception helper macros -------------------- //
+// Override dll_function with main_function from main executable.
+#define INTERCEPT_OR_DIE(main_function, dll_function) \
+ static int intercept_##dll_function() { \
+ return __sanitizer::dllThunkIntercept(main_function, (__sanitizer::uptr) \
+ dll_function); \
+ } \
+ __pragma(section(".DLLTH$M", long, read)) \
+ __declspec(allocate(".DLLTH$M")) int (*__dll_thunk_##dll_function)() = \
+ intercept_##dll_function;
+
+// Try to override dll_function with main_function from main executable.
+// If main_function is not present, override dll_function with default_function.
+#define INTERCEPT_WHEN_POSSIBLE(main_function, default_function, dll_function) \
+ static int intercept_##dll_function() { \
+ return __sanitizer::dllThunkInterceptWhenPossible(main_function, \
+ default_function, (__sanitizer::uptr)dll_function); \
+ } \
+ __pragma(section(".DLLTH$M", long, read)) \
+ __declspec(allocate(".DLLTH$M")) int (*__dll_thunk_##dll_function)() = \
+ intercept_##dll_function;
+
+// -------------------- Function interception macros ------------------------ //
+// Special case of hooks -- ASan own interface functions. Those are only called
+// after __asan_init, thus an empty implementation is sufficient.
+#define INTERCEPT_SANITIZER_FUNCTION(name) \
+ extern "C" __declspec(noinline) void name() { \
+ volatile int prevent_icf = (__LINE__ << 8) ^ __COUNTER__; \
+ static const char function_name[] = #name; \
+ for (const char* ptr = &function_name[0]; *ptr; ++ptr) \
+ prevent_icf ^= *ptr; \
+ (void)prevent_icf; \
+ __debugbreak(); \
+ } \
+ INTERCEPT_OR_DIE(#name, name)
+
+// Special case of hooks -- Weak functions, could be redefined in the main
+// executable, but that is not necessary, so we shouldn't die if we can not find
+// a reference. Instead, when the function is not present in the main executable
+// we consider the default impl provided by asan library.
+#define INTERCEPT_SANITIZER_WEAK_FUNCTION(name) \
+ extern "C" __declspec(noinline) void name() { \
+ volatile int prevent_icf = (__LINE__ << 8) ^ __COUNTER__; \
+ static const char function_name[] = #name; \
+ for (const char* ptr = &function_name[0]; *ptr; ++ptr) \
+ prevent_icf ^= *ptr; \
+ (void)prevent_icf; \
+ __debugbreak(); \
+ } \
+ INTERCEPT_WHEN_POSSIBLE(#name, STRINGIFY(WEAK_EXPORT_NAME(name)), name)
+
+// We can't define our own version of strlen etc. because that would lead to
+// link-time or even type mismatch errors. Instead, we can declare a function
+// just to be able to get its address. Me may miss the first few calls to the
+// functions since it can be called before __dll_thunk_init, but that would lead
+// to false negatives in the startup code before user's global initializers,
+// which isn't a big deal.
+#define INTERCEPT_LIBRARY_FUNCTION(name) \
+ extern "C" void name(); \
+ INTERCEPT_OR_DIE(WRAPPER_NAME(name), name)
+
+// Use these macros for functions that could be called before __dll_thunk_init()
+// is executed and don't lead to errors if defined (free, malloc, etc).
+#define INTERCEPT_WRAP_V_V(name) \
+ extern "C" void name() { \
+ typedef decltype(name) *fntype; \
+ static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
+ fn(); \
+ } \
+ INTERCEPT_OR_DIE(#name, name);
+
+#define INTERCEPT_WRAP_V_W(name) \
+ extern "C" void name(void *arg) { \
+ typedef decltype(name) *fntype; \
+ static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
+ fn(arg); \
+ } \
+ INTERCEPT_OR_DIE(#name, name);
+
+#define INTERCEPT_WRAP_V_WW(name) \
+ extern "C" void name(void *arg1, void *arg2) { \
+ typedef decltype(name) *fntype; \
+ static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
+ fn(arg1, arg2); \
+ } \
+ INTERCEPT_OR_DIE(#name, name);
+
+#define INTERCEPT_WRAP_V_WWW(name) \
+ extern "C" void name(void *arg1, void *arg2, void *arg3) { \
+ typedef decltype(name) *fntype; \
+ static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
+ fn(arg1, arg2, arg3); \
+ } \
+ INTERCEPT_OR_DIE(#name, name);
+
+#define INTERCEPT_WRAP_W_V(name) \
+ extern "C" void *name() { \
+ typedef decltype(name) *fntype; \
+ static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
+ return fn(); \
+ } \
+ INTERCEPT_OR_DIE(#name, name);
+
+#define INTERCEPT_WRAP_W_W(name) \
+ extern "C" void *name(void *arg) { \
+ typedef decltype(name) *fntype; \
+ static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
+ return fn(arg); \
+ } \
+ INTERCEPT_OR_DIE(#name, name);
+
+#define INTERCEPT_WRAP_W_WW(name) \
+ extern "C" void *name(void *arg1, void *arg2) { \
+ typedef decltype(name) *fntype; \
+ static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
+ return fn(arg1, arg2); \
+ } \
+ INTERCEPT_OR_DIE(#name, name);
+
+#define INTERCEPT_WRAP_W_WWW(name) \
+ extern "C" void *name(void *arg1, void *arg2, void *arg3) { \
+ typedef decltype(name) *fntype; \
+ static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
+ return fn(arg1, arg2, arg3); \
+ } \
+ INTERCEPT_OR_DIE(#name, name);
+
+#define INTERCEPT_WRAP_W_WWWW(name) \
+ extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) { \
+ typedef decltype(name) *fntype; \
+ static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
+ return fn(arg1, arg2, arg3, arg4); \
+ } \
+ INTERCEPT_OR_DIE(#name, name);
+
+#define INTERCEPT_WRAP_W_WWWWW(name) \
+ extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \
+ void *arg5) { \
+ typedef decltype(name) *fntype; \
+ static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
+ return fn(arg1, arg2, arg3, arg4, arg5); \
+ } \
+ INTERCEPT_OR_DIE(#name, name);
+
+#define INTERCEPT_WRAP_W_WWWWWW(name) \
+ extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \
+ void *arg5, void *arg6) { \
+ typedef decltype(name) *fntype; \
+ static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \
+ return fn(arg1, arg2, arg3, arg4, arg5, arg6); \
+ } \
+ INTERCEPT_OR_DIE(#name, name);
+
+#endif // SANITIZER_WIN_DLL_THUNK_H
diff --git a/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win_weak_interception.h b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win_weak_interception.h
new file mode 100644
index 00000000000..5e4d8b8def3
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/sanitizer_common/sanitizer_win_weak_interception.h
@@ -0,0 +1,32 @@
+//===-- sanitizer_win_weak_interception.h ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// This header provide helper macros to delegate calls of weak functions to the
+// implementation in the main executable when a strong definition is present.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_WIN_WEAK_INTERCEPTION_H
+#define SANITIZER_WIN_WEAK_INTERCEPTION_H
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+int interceptWhenPossible(uptr dll_function, const char *real_function);
+}
+
+// ----------------- Function interception helper macros -------------------- //
+// Weak functions, could be redefined in the main executable, but that is not
+// necessary, so we shouldn't die if we can not find a reference.
+#define INTERCEPT_WEAK(Name) interceptWhenPossible((uptr) Name, #Name);
+
+#define INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) \
+ static int intercept_##Name() { \
+ return __sanitizer::interceptWhenPossible((__sanitizer::uptr) Name, #Name);\
+ } \
+ __pragma(section(".WEAK$M", long, read)) \
+ __declspec(allocate(".WEAK$M")) int (*__weak_intercept_##Name)() = \
+ intercept_##Name;
+
+#endif // SANITIZER_WIN_WEAK_INTERCEPTION_H
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/allocator_config.h b/contrib/libs/clang16-rt/lib/scudo/standalone/allocator_config.h
new file mode 100644
index 00000000000..63eb325c9b8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/allocator_config.h
@@ -0,0 +1,220 @@
+//===-- allocator_config.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_ALLOCATOR_CONFIG_H_
+#define SCUDO_ALLOCATOR_CONFIG_H_
+
+#include "combined.h"
+#include "common.h"
+#include "flags.h"
+#include "primary32.h"
+#include "primary64.h"
+#include "secondary.h"
+#include "size_class_map.h"
+#include "tsd_exclusive.h"
+#include "tsd_shared.h"
+
+namespace scudo {
+
+// The combined allocator uses a structure as a template argument that
+// specifies the configuration options for the various subcomponents of the
+// allocator.
+//
+// struct ExampleConfig {
+// // SizeClasMmap to use with the Primary.
+// using SizeClassMap = DefaultSizeClassMap;
+// // Indicates possible support for Memory Tagging.
+// static const bool MaySupportMemoryTagging = false;
+// // Defines the Primary allocator to use.
+// typedef SizeClassAllocator64<ExampleConfig> Primary;
+// // Log2 of the size of a size class region, as used by the Primary.
+// static const uptr PrimaryRegionSizeLog = 30U;
+// // Log2 of the size of block group, as used by the Primary. Each group
+// // contains a range of memory addresses, blocks in the range will belong to
+// // the same group. In general, single region may have 1 or 2MB group size.
+// // Multiple regions will have the group size equal to the region size
+// // because the region size is usually smaller than 1 MB.
+// // Smaller value gives fine-grained control of memory usage but the trade
+// // off is that it may take longer time of deallocation.
+// static const uptr PrimaryGroupSizeLog = 20U;
+// // Defines the type and scale of a compact pointer. A compact pointer can
+// // be understood as the offset of a pointer within the region it belongs
+// // to, in increments of a power-of-2 scale.
+// // eg: Ptr = Base + (CompactPtr << Scale).
+// typedef u32 PrimaryCompactPtrT;
+// static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
+// // Indicates support for offsetting the start of a region by
+// // a random number of pages. Only used with primary64.
+// static const bool PrimaryEnableRandomOffset = true;
+// // Call map for user memory with at least this size. Only used with
+// // primary64.
+// static const uptr PrimaryMapSizeIncrement = 1UL << 18;
+// // Defines the minimal & maximal release interval that can be set.
+// static const s32 PrimaryMinReleaseToOsIntervalMs = INT32_MIN;
+// static const s32 PrimaryMaxReleaseToOsIntervalMs = INT32_MAX;
+// // Defines the type of cache used by the Secondary. Some additional
+// // configuration entries can be necessary depending on the Cache.
+// typedef MapAllocatorNoCache SecondaryCache;
+// // Thread-Specific Data Registry used, shared or exclusive.
+// template <class A> using TSDRegistryT = TSDRegistrySharedT<A, 8U, 4U>;
+// };
+
+// Default configurations for various platforms.
+
+struct DefaultConfig {
+ using SizeClassMap = DefaultSizeClassMap;
+ static const bool MaySupportMemoryTagging = true;
+
+#if SCUDO_CAN_USE_PRIMARY64
+ typedef SizeClassAllocator64<DefaultConfig> Primary;
+ static const uptr PrimaryRegionSizeLog = 32U;
+ static const uptr PrimaryGroupSizeLog = 21U;
+ typedef uptr PrimaryCompactPtrT;
+ static const uptr PrimaryCompactPtrScale = 0;
+ static const bool PrimaryEnableRandomOffset = true;
+ static const uptr PrimaryMapSizeIncrement = 1UL << 18;
+#else
+ typedef SizeClassAllocator32<DefaultConfig> Primary;
+ static const uptr PrimaryRegionSizeLog = 19U;
+ static const uptr PrimaryGroupSizeLog = 19U;
+ typedef uptr PrimaryCompactPtrT;
+#endif
+ static const s32 PrimaryMinReleaseToOsIntervalMs = INT32_MIN;
+ static const s32 PrimaryMaxReleaseToOsIntervalMs = INT32_MAX;
+
+ typedef MapAllocatorCache<DefaultConfig> SecondaryCache;
+ static const u32 SecondaryCacheEntriesArraySize = 32U;
+ static const u32 SecondaryCacheQuarantineSize = 0U;
+ static const u32 SecondaryCacheDefaultMaxEntriesCount = 32U;
+ static const uptr SecondaryCacheDefaultMaxEntrySize = 1UL << 19;
+ static const s32 SecondaryCacheMinReleaseToOsIntervalMs = INT32_MIN;
+ static const s32 SecondaryCacheMaxReleaseToOsIntervalMs = INT32_MAX;
+
+ template <class A> using TSDRegistryT = TSDRegistryExT<A>; // Exclusive
+};
+struct AndroidConfig {
+ using SizeClassMap = AndroidSizeClassMap;
+ static const bool MaySupportMemoryTagging = true;
+
+#if SCUDO_CAN_USE_PRIMARY64
+ typedef SizeClassAllocator64<AndroidConfig> Primary;
+ static const uptr PrimaryRegionSizeLog = 28U;
+ typedef u32 PrimaryCompactPtrT;
+ static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
+ static const uptr PrimaryGroupSizeLog = 20U;
+ static const bool PrimaryEnableRandomOffset = true;
+ static const uptr PrimaryMapSizeIncrement = 1UL << 18;
+#else
+ typedef SizeClassAllocator32<AndroidConfig> Primary;
+ static const uptr PrimaryRegionSizeLog = 18U;
+ static const uptr PrimaryGroupSizeLog = 18U;
+ typedef uptr PrimaryCompactPtrT;
+#endif
+ static const s32 PrimaryMinReleaseToOsIntervalMs = 1000;
+ static const s32 PrimaryMaxReleaseToOsIntervalMs = 1000;
+
+ typedef MapAllocatorCache<AndroidConfig> SecondaryCache;
+ static const u32 SecondaryCacheEntriesArraySize = 256U;
+ static const u32 SecondaryCacheQuarantineSize = 32U;
+ static const u32 SecondaryCacheDefaultMaxEntriesCount = 32U;
+ static const uptr SecondaryCacheDefaultMaxEntrySize = 2UL << 20;
+ static const s32 SecondaryCacheMinReleaseToOsIntervalMs = 0;
+ static const s32 SecondaryCacheMaxReleaseToOsIntervalMs = 1000;
+
+ template <class A>
+ using TSDRegistryT = TSDRegistrySharedT<A, 8U, 2U>; // Shared, max 8 TSDs.
+};
+
+struct AndroidSvelteConfig {
+ using SizeClassMap = SvelteSizeClassMap;
+ static const bool MaySupportMemoryTagging = false;
+
+#if SCUDO_CAN_USE_PRIMARY64
+ typedef SizeClassAllocator64<AndroidSvelteConfig> Primary;
+ static const uptr PrimaryRegionSizeLog = 27U;
+ typedef u32 PrimaryCompactPtrT;
+ static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
+ static const uptr PrimaryGroupSizeLog = 18U;
+ static const bool PrimaryEnableRandomOffset = true;
+ static const uptr PrimaryMapSizeIncrement = 1UL << 18;
+#else
+ typedef SizeClassAllocator32<AndroidSvelteConfig> Primary;
+ static const uptr PrimaryRegionSizeLog = 16U;
+ static const uptr PrimaryGroupSizeLog = 16U;
+ typedef uptr PrimaryCompactPtrT;
+#endif
+ static const s32 PrimaryMinReleaseToOsIntervalMs = 1000;
+ static const s32 PrimaryMaxReleaseToOsIntervalMs = 1000;
+
+ typedef MapAllocatorCache<AndroidSvelteConfig> SecondaryCache;
+ static const u32 SecondaryCacheEntriesArraySize = 16U;
+ static const u32 SecondaryCacheQuarantineSize = 32U;
+ static const u32 SecondaryCacheDefaultMaxEntriesCount = 4U;
+ static const uptr SecondaryCacheDefaultMaxEntrySize = 1UL << 18;
+ static const s32 SecondaryCacheMinReleaseToOsIntervalMs = 0;
+ static const s32 SecondaryCacheMaxReleaseToOsIntervalMs = 0;
+
+ template <class A>
+ using TSDRegistryT = TSDRegistrySharedT<A, 2U, 1U>; // Shared, max 2 TSDs.
+};
+
+#if SCUDO_CAN_USE_PRIMARY64
+struct FuchsiaConfig {
+ using SizeClassMap = FuchsiaSizeClassMap;
+ static const bool MaySupportMemoryTagging = false;
+
+ typedef SizeClassAllocator64<FuchsiaConfig> Primary;
+ static const uptr PrimaryRegionSizeLog = 30U;
+ static const uptr PrimaryGroupSizeLog = 21U;
+ typedef u32 PrimaryCompactPtrT;
+ static const bool PrimaryEnableRandomOffset = true;
+ static const uptr PrimaryMapSizeIncrement = 1UL << 18;
+ static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
+ static const s32 PrimaryMinReleaseToOsIntervalMs = INT32_MIN;
+ static const s32 PrimaryMaxReleaseToOsIntervalMs = INT32_MAX;
+
+ typedef MapAllocatorNoCache SecondaryCache;
+ template <class A>
+ using TSDRegistryT = TSDRegistrySharedT<A, 8U, 4U>; // Shared, max 8 TSDs.
+};
+
+struct TrustyConfig {
+ using SizeClassMap = TrustySizeClassMap;
+ static const bool MaySupportMemoryTagging = false;
+
+ typedef SizeClassAllocator64<TrustyConfig> Primary;
+ // Some apps have 1 page of heap total so small regions are necessary.
+ static const uptr PrimaryRegionSizeLog = 10U;
+ static const uptr PrimaryGroupSizeLog = 10U;
+ typedef u32 PrimaryCompactPtrT;
+ static const bool PrimaryEnableRandomOffset = false;
+ // Trusty is extremely memory-constrained so minimally round up map calls.
+ static const uptr PrimaryMapSizeIncrement = 1UL << 4;
+ static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
+ static const s32 PrimaryMinReleaseToOsIntervalMs = INT32_MIN;
+ static const s32 PrimaryMaxReleaseToOsIntervalMs = INT32_MAX;
+
+ typedef MapAllocatorNoCache SecondaryCache;
+ template <class A>
+ using TSDRegistryT = TSDRegistrySharedT<A, 1U, 1U>; // Shared, max 1 TSD.
+};
+#endif
+
+#if SCUDO_ANDROID
+typedef AndroidConfig Config;
+#elif SCUDO_FUCHSIA
+typedef FuchsiaConfig Config;
+#elif SCUDO_TRUSTY
+typedef TrustyConfig Config;
+#else
+typedef DefaultConfig Config;
+#endif
+
+} // namespace scudo
+
+#endif // SCUDO_ALLOCATOR_CONFIG_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/atomic_helpers.h b/contrib/libs/clang16-rt/lib/scudo/standalone/atomic_helpers.h
new file mode 100644
index 00000000000..d88f5d7be64
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/atomic_helpers.h
@@ -0,0 +1,145 @@
+//===-- atomic_helpers.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_ATOMIC_H_
+#define SCUDO_ATOMIC_H_
+
+#include "internal_defs.h"
+
+namespace scudo {
+
+enum memory_order {
+ memory_order_relaxed = 0,
+ memory_order_consume = 1,
+ memory_order_acquire = 2,
+ memory_order_release = 3,
+ memory_order_acq_rel = 4,
+ memory_order_seq_cst = 5
+};
+static_assert(memory_order_relaxed == __ATOMIC_RELAXED, "");
+static_assert(memory_order_consume == __ATOMIC_CONSUME, "");
+static_assert(memory_order_acquire == __ATOMIC_ACQUIRE, "");
+static_assert(memory_order_release == __ATOMIC_RELEASE, "");
+static_assert(memory_order_acq_rel == __ATOMIC_ACQ_REL, "");
+static_assert(memory_order_seq_cst == __ATOMIC_SEQ_CST, "");
+
+struct atomic_u8 {
+ typedef u8 Type;
+ volatile Type ValDoNotUse;
+};
+
+struct atomic_u16 {
+ typedef u16 Type;
+ volatile Type ValDoNotUse;
+};
+
+struct atomic_s32 {
+ typedef s32 Type;
+ volatile Type ValDoNotUse;
+};
+
+struct atomic_u32 {
+ typedef u32 Type;
+ volatile Type ValDoNotUse;
+};
+
+struct atomic_u64 {
+ typedef u64 Type;
+ // On 32-bit platforms u64 is not necessarily aligned on 8 bytes.
+ alignas(8) volatile Type ValDoNotUse;
+};
+
+struct atomic_uptr {
+ typedef uptr Type;
+ volatile Type ValDoNotUse;
+};
+
+template <typename T>
+inline typename T::Type atomic_load(const volatile T *A, memory_order MO) {
+ DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
+ typename T::Type V;
+ __atomic_load(&A->ValDoNotUse, &V, MO);
+ return V;
+}
+
+template <typename T>
+inline void atomic_store(volatile T *A, typename T::Type V, memory_order MO) {
+ DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
+ __atomic_store(&A->ValDoNotUse, &V, MO);
+}
+
+inline void atomic_thread_fence(memory_order) { __sync_synchronize(); }
+
+template <typename T>
+inline typename T::Type atomic_fetch_add(volatile T *A, typename T::Type V,
+ memory_order MO) {
+ DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
+ return __atomic_fetch_add(&A->ValDoNotUse, V, MO);
+}
+
+template <typename T>
+inline typename T::Type atomic_fetch_sub(volatile T *A, typename T::Type V,
+ memory_order MO) {
+ DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
+ return __atomic_fetch_sub(&A->ValDoNotUse, V, MO);
+}
+
+template <typename T>
+inline typename T::Type atomic_fetch_and(volatile T *A, typename T::Type V,
+ memory_order MO) {
+ DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
+ return __atomic_fetch_and(&A->ValDoNotUse, V, MO);
+}
+
+template <typename T>
+inline typename T::Type atomic_fetch_or(volatile T *A, typename T::Type V,
+ memory_order MO) {
+ DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
+ return __atomic_fetch_or(&A->ValDoNotUse, V, MO);
+}
+
+template <typename T>
+inline typename T::Type atomic_exchange(volatile T *A, typename T::Type V,
+ memory_order MO) {
+ DCHECK(!(reinterpret_cast<uptr>(A) % sizeof(*A)));
+ typename T::Type R;
+ __atomic_exchange(&A->ValDoNotUse, &V, &R, MO);
+ return R;
+}
+
+template <typename T>
+inline bool atomic_compare_exchange_strong(volatile T *A, typename T::Type *Cmp,
+ typename T::Type Xchg,
+ memory_order MO) {
+ return __atomic_compare_exchange(&A->ValDoNotUse, Cmp, &Xchg, false, MO,
+ __ATOMIC_RELAXED);
+}
+
+// Clutter-reducing helpers.
+
+template <typename T>
+inline typename T::Type atomic_load_relaxed(const volatile T *A) {
+ return atomic_load(A, memory_order_relaxed);
+}
+
+template <typename T>
+inline void atomic_store_relaxed(volatile T *A, typename T::Type V) {
+ atomic_store(A, V, memory_order_relaxed);
+}
+
+template <typename T>
+inline typename T::Type atomic_compare_exchange(volatile T *A,
+ typename T::Type Cmp,
+ typename T::Type Xchg) {
+ atomic_compare_exchange_strong(A, &Cmp, Xchg, memory_order_acquire);
+ return Cmp;
+}
+
+} // namespace scudo
+
+#endif // SCUDO_ATOMIC_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/bytemap.h b/contrib/libs/clang16-rt/lib/scudo/standalone/bytemap.h
new file mode 100644
index 00000000000..248e096d07b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/bytemap.h
@@ -0,0 +1,43 @@
+//===-- bytemap.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_BYTEMAP_H_
+#define SCUDO_BYTEMAP_H_
+
+#include "atomic_helpers.h"
+#include "common.h"
+#include "mutex.h"
+
+namespace scudo {
+
+template <uptr Size> class FlatByteMap {
+public:
+ void init() { DCHECK(Size == 0 || Map[0] == 0); }
+
+ void unmapTestOnly() { memset(Map, 0, Size); }
+
+ void set(uptr Index, u8 Value) {
+ DCHECK_LT(Index, Size);
+ DCHECK_EQ(0U, Map[Index]);
+ Map[Index] = Value;
+ }
+ u8 operator[](uptr Index) {
+ DCHECK_LT(Index, Size);
+ return Map[Index];
+ }
+
+ void disable() {}
+ void enable() {}
+
+private:
+ u8 Map[Size] = {};
+};
+
+} // namespace scudo
+
+#endif // SCUDO_BYTEMAP_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/checksum.cpp b/contrib/libs/clang16-rt/lib/scudo/standalone/checksum.cpp
new file mode 100644
index 00000000000..b40a9301f2e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/checksum.cpp
@@ -0,0 +1,83 @@
+//===-- checksum.cpp --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "checksum.h"
+#include "atomic_helpers.h"
+#include "chunk.h"
+
+#if defined(__x86_64__) || defined(__i386__)
+#include <cpuid.h>
+#elif defined(__arm__) || defined(__aarch64__)
+#if SCUDO_FUCHSIA
+#error #include <zircon/features.h>
+#error #include <zircon/syscalls.h>
+#else
+#include <sys/auxv.h>
+#endif
+#endif
+
+namespace scudo {
+
+Checksum HashAlgorithm = {Checksum::BSD};
+
+#if defined(__x86_64__) || defined(__i386__)
+// i386 and x86_64 specific code to detect CRC32 hardware support via CPUID.
+// CRC32 requires the SSE 4.2 instruction set.
+#ifndef bit_SSE4_2
+#define bit_SSE4_2 bit_SSE42 // clang and gcc have different defines.
+#endif
+
+#ifndef signature_HYGON_ebx // They are not defined in gcc.
+// HYGON: "HygonGenuine".
+#define signature_HYGON_ebx 0x6f677948
+#define signature_HYGON_edx 0x6e65476e
+#define signature_HYGON_ecx 0x656e6975
+#endif
+
+bool hasHardwareCRC32() {
+ u32 Eax, Ebx = 0, Ecx = 0, Edx = 0;
+ __get_cpuid(0, &Eax, &Ebx, &Ecx, &Edx);
+ const bool IsIntel = (Ebx == signature_INTEL_ebx) &&
+ (Edx == signature_INTEL_edx) &&
+ (Ecx == signature_INTEL_ecx);
+ const bool IsAMD = (Ebx == signature_AMD_ebx) && (Edx == signature_AMD_edx) &&
+ (Ecx == signature_AMD_ecx);
+ const bool IsHygon = (Ebx == signature_HYGON_ebx) &&
+ (Edx == signature_HYGON_edx) &&
+ (Ecx == signature_HYGON_ecx);
+ if (!IsIntel && !IsAMD && !IsHygon)
+ return false;
+ __get_cpuid(1, &Eax, &Ebx, &Ecx, &Edx);
+ return !!(Ecx & bit_SSE4_2);
+}
+#elif defined(__arm__) || defined(__aarch64__)
+#ifndef AT_HWCAP
+#define AT_HWCAP 16
+#endif
+#ifndef HWCAP_CRC32
+#define HWCAP_CRC32 (1U << 7) // HWCAP_CRC32 is missing on older platforms.
+#endif
+
+bool hasHardwareCRC32() {
+#if SCUDO_FUCHSIA
+ u32 HWCap;
+ const zx_status_t Status =
+ zx_system_get_features(ZX_FEATURE_KIND_CPU, &HWCap);
+ if (Status != ZX_OK)
+ return false;
+ return !!(HWCap & ZX_ARM64_FEATURE_ISA_CRC32);
+#else
+ return !!(getauxval(AT_HWCAP) & HWCAP_CRC32);
+#endif // SCUDO_FUCHSIA
+}
+#else
+// No hardware CRC32 implemented in Scudo for other architectures.
+bool hasHardwareCRC32() { return false; }
+#endif // defined(__x86_64__) || defined(__i386__)
+
+} // namespace scudo
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/checksum.h b/contrib/libs/clang16-rt/lib/scudo/standalone/checksum.h
new file mode 100644
index 00000000000..f8eda81fd91
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/checksum.h
@@ -0,0 +1,59 @@
+//===-- checksum.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_CHECKSUM_H_
+#define SCUDO_CHECKSUM_H_
+
+#include "internal_defs.h"
+
+// Hardware CRC32 is supported at compilation via the following:
+// - for i386 & x86_64: -mcrc32 (earlier: -msse4.2)
+// - for ARM & AArch64: -march=armv8-a+crc or -mcrc
+// An additional check must be performed at runtime as well to make sure the
+// emitted instructions are valid on the target host.
+
+#if defined(__CRC32__)
+// NB: clang has <crc32intrin.h> but GCC does not
+#include <smmintrin.h>
+#define CRC32_INTRINSIC \
+ FIRST_32_SECOND_64(__builtin_ia32_crc32si, __builtin_ia32_crc32di)
+#elif defined(__SSE4_2__)
+#include <smmintrin.h>
+#define CRC32_INTRINSIC FIRST_32_SECOND_64(_mm_crc32_u32, _mm_crc32_u64)
+#endif
+#ifdef __ARM_FEATURE_CRC32
+#include <arm_acle.h>
+#define CRC32_INTRINSIC FIRST_32_SECOND_64(__crc32cw, __crc32cd)
+#endif
+
+namespace scudo {
+
+enum class Checksum : u8 {
+ BSD = 0,
+ HardwareCRC32 = 1,
+};
+
+// BSD checksum, unlike a software CRC32, doesn't use any array lookup. We save
+// significantly on memory accesses, as well as 1K of CRC32 table, on platforms
+// that do no support hardware CRC32. The checksum itself is 16-bit, which is at
+// odds with CRC32, but enough for our needs.
+inline u16 computeBSDChecksum(u16 Sum, uptr Data) {
+ for (u8 I = 0; I < sizeof(Data); I++) {
+ Sum = static_cast<u16>((Sum >> 1) | ((Sum & 1) << 15));
+ Sum = static_cast<u16>(Sum + (Data & 0xff));
+ Data >>= 8;
+ }
+ return Sum;
+}
+
+bool hasHardwareCRC32();
+WEAK u32 computeHardwareCRC32(u32 Crc, uptr Data);
+
+} // namespace scudo
+
+#endif // SCUDO_CHECKSUM_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/chunk.h b/contrib/libs/clang16-rt/lib/scudo/standalone/chunk.h
new file mode 100644
index 00000000000..88bada8c2d1
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/chunk.h
@@ -0,0 +1,156 @@
+//===-- chunk.h -------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_CHUNK_H_
+#define SCUDO_CHUNK_H_
+
+#include "platform.h"
+
+#include "atomic_helpers.h"
+#include "checksum.h"
+#include "common.h"
+#include "report.h"
+
+namespace scudo {
+
+extern Checksum HashAlgorithm;
+
+inline u16 computeChecksum(u32 Seed, uptr Value, uptr *Array, uptr ArraySize) {
+ // If the hardware CRC32 feature is defined here, it was enabled everywhere,
+ // as opposed to only for crc32_hw.cpp. This means that other hardware
+ // specific instructions were likely emitted at other places, and as a result
+ // there is no reason to not use it here.
+#if defined(__CRC32__) || defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32)
+ u32 Crc = static_cast<u32>(CRC32_INTRINSIC(Seed, Value));
+ for (uptr I = 0; I < ArraySize; I++)
+ Crc = static_cast<u32>(CRC32_INTRINSIC(Crc, Array[I]));
+ return static_cast<u16>(Crc ^ (Crc >> 16));
+#else
+ if (HashAlgorithm == Checksum::HardwareCRC32) {
+ u32 Crc = computeHardwareCRC32(Seed, Value);
+ for (uptr I = 0; I < ArraySize; I++)
+ Crc = computeHardwareCRC32(Crc, Array[I]);
+ return static_cast<u16>(Crc ^ (Crc >> 16));
+ } else {
+ u16 Checksum = computeBSDChecksum(static_cast<u16>(Seed), Value);
+ for (uptr I = 0; I < ArraySize; I++)
+ Checksum = computeBSDChecksum(Checksum, Array[I]);
+ return Checksum;
+ }
+#endif // defined(__CRC32__) || defined(__SSE4_2__) ||
+ // defined(__ARM_FEATURE_CRC32)
+}
+
+namespace Chunk {
+
+// Note that in an ideal world, `State` and `Origin` should be `enum class`, and
+// the associated `UnpackedHeader` fields of their respective enum class type
+// but https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414 prevents it from
+// happening, as it will error, complaining the number of bits is not enough.
+enum Origin : u8 {
+ Malloc = 0,
+ New = 1,
+ NewArray = 2,
+ Memalign = 3,
+};
+
+enum State : u8 { Available = 0, Allocated = 1, Quarantined = 2 };
+
+typedef u64 PackedHeader;
+// Update the 'Mask' constants to reflect changes in this structure.
+struct UnpackedHeader {
+ uptr ClassId : 8;
+ u8 State : 2;
+ // Origin if State == Allocated, or WasZeroed otherwise.
+ u8 OriginOrWasZeroed : 2;
+ uptr SizeOrUnusedBytes : 20;
+ uptr Offset : 16;
+ uptr Checksum : 16;
+};
+typedef atomic_u64 AtomicPackedHeader;
+static_assert(sizeof(UnpackedHeader) == sizeof(PackedHeader), "");
+
+// Those constants are required to silence some -Werror=conversion errors when
+// assigning values to the related bitfield variables.
+constexpr uptr ClassIdMask = (1UL << 8) - 1;
+constexpr u8 StateMask = (1U << 2) - 1;
+constexpr u8 OriginMask = (1U << 2) - 1;
+constexpr uptr SizeOrUnusedBytesMask = (1UL << 20) - 1;
+constexpr uptr OffsetMask = (1UL << 16) - 1;
+constexpr uptr ChecksumMask = (1UL << 16) - 1;
+
+constexpr uptr getHeaderSize() {
+ return roundUpTo(sizeof(PackedHeader), 1U << SCUDO_MIN_ALIGNMENT_LOG);
+}
+
+inline AtomicPackedHeader *getAtomicHeader(void *Ptr) {
+ return reinterpret_cast<AtomicPackedHeader *>(reinterpret_cast<uptr>(Ptr) -
+ getHeaderSize());
+}
+
+inline const AtomicPackedHeader *getConstAtomicHeader(const void *Ptr) {
+ return reinterpret_cast<const AtomicPackedHeader *>(
+ reinterpret_cast<uptr>(Ptr) - getHeaderSize());
+}
+
+// We do not need a cryptographically strong hash for the checksum, but a CRC
+// type function that can alert us in the event a header is invalid or
+// corrupted. Ideally slightly better than a simple xor of all fields.
+static inline u16 computeHeaderChecksum(u32 Cookie, const void *Ptr,
+ UnpackedHeader *Header) {
+ UnpackedHeader ZeroChecksumHeader = *Header;
+ ZeroChecksumHeader.Checksum = 0;
+ uptr HeaderHolder[sizeof(UnpackedHeader) / sizeof(uptr)];
+ memcpy(&HeaderHolder, &ZeroChecksumHeader, sizeof(HeaderHolder));
+ return computeChecksum(Cookie, reinterpret_cast<uptr>(Ptr), HeaderHolder,
+ ARRAY_SIZE(HeaderHolder));
+}
+
+inline void storeHeader(u32 Cookie, void *Ptr,
+ UnpackedHeader *NewUnpackedHeader) {
+ NewUnpackedHeader->Checksum =
+ computeHeaderChecksum(Cookie, Ptr, NewUnpackedHeader);
+ PackedHeader NewPackedHeader = bit_cast<PackedHeader>(*NewUnpackedHeader);
+ atomic_store_relaxed(getAtomicHeader(Ptr), NewPackedHeader);
+}
+
+inline void loadHeader(u32 Cookie, const void *Ptr,
+ UnpackedHeader *NewUnpackedHeader) {
+ PackedHeader NewPackedHeader = atomic_load_relaxed(getConstAtomicHeader(Ptr));
+ *NewUnpackedHeader = bit_cast<UnpackedHeader>(NewPackedHeader);
+ if (UNLIKELY(NewUnpackedHeader->Checksum !=
+ computeHeaderChecksum(Cookie, Ptr, NewUnpackedHeader)))
+ reportHeaderCorruption(const_cast<void *>(Ptr));
+}
+
+inline void compareExchangeHeader(u32 Cookie, void *Ptr,
+ UnpackedHeader *NewUnpackedHeader,
+ UnpackedHeader *OldUnpackedHeader) {
+ NewUnpackedHeader->Checksum =
+ computeHeaderChecksum(Cookie, Ptr, NewUnpackedHeader);
+ PackedHeader NewPackedHeader = bit_cast<PackedHeader>(*NewUnpackedHeader);
+ PackedHeader OldPackedHeader = bit_cast<PackedHeader>(*OldUnpackedHeader);
+ if (UNLIKELY(!atomic_compare_exchange_strong(
+ getAtomicHeader(Ptr), &OldPackedHeader, NewPackedHeader,
+ memory_order_relaxed)))
+ reportHeaderRace(Ptr);
+}
+
+inline bool isValid(u32 Cookie, const void *Ptr,
+ UnpackedHeader *NewUnpackedHeader) {
+ PackedHeader NewPackedHeader = atomic_load_relaxed(getConstAtomicHeader(Ptr));
+ *NewUnpackedHeader = bit_cast<UnpackedHeader>(NewPackedHeader);
+ return NewUnpackedHeader->Checksum ==
+ computeHeaderChecksum(Cookie, Ptr, NewUnpackedHeader);
+}
+
+} // namespace Chunk
+
+} // namespace scudo
+
+#endif // SCUDO_CHUNK_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/combined.h b/contrib/libs/clang16-rt/lib/scudo/standalone/combined.h
new file mode 100644
index 00000000000..b6d74ab451b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/combined.h
@@ -0,0 +1,1531 @@
+//===-- combined.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_COMBINED_H_
+#define SCUDO_COMBINED_H_
+
+#include "chunk.h"
+#include "common.h"
+#include "flags.h"
+#include "flags_parser.h"
+#include "local_cache.h"
+#include "memtag.h"
+#include "options.h"
+#include "quarantine.h"
+#include "report.h"
+#include "rss_limit_checker.h"
+#include "secondary.h"
+#include "stack_depot.h"
+#include "string_utils.h"
+#include "tsd.h"
+
+#include "scudo/interface.h"
+
+#ifdef GWP_ASAN_HOOKS
+#include "gwp_asan/guarded_pool_allocator.h"
+#include "gwp_asan/optional/backtrace.h"
+#include "gwp_asan/optional/segv_handler.h"
+#endif // GWP_ASAN_HOOKS
+
+extern "C" inline void EmptyCallback() {}
+
+#ifdef HAVE_ANDROID_UNSAFE_FRAME_POINTER_CHASE
+// This function is not part of the NDK so it does not appear in any public
+// header files. We only declare/use it when targeting the platform.
+extern "C" size_t android_unsafe_frame_pointer_chase(scudo::uptr *buf,
+ size_t num_entries);
+#endif
+
+namespace scudo {
+
+template <class Params, void (*PostInitCallback)(void) = EmptyCallback>
+class Allocator {
+public:
+ using PrimaryT = typename Params::Primary;
+ using CacheT = typename PrimaryT::CacheT;
+ typedef Allocator<Params, PostInitCallback> ThisT;
+ typedef typename Params::template TSDRegistryT<ThisT> TSDRegistryT;
+
+ void callPostInitCallback() {
+ pthread_once(&PostInitNonce, PostInitCallback);
+ }
+
+ struct QuarantineCallback {
+ explicit QuarantineCallback(ThisT &Instance, CacheT &LocalCache)
+ : Allocator(Instance), Cache(LocalCache) {}
+
+ // Chunk recycling function, returns a quarantined chunk to the backend,
+ // first making sure it hasn't been tampered with.
+ void recycle(void *Ptr) {
+ Chunk::UnpackedHeader Header;
+ Chunk::loadHeader(Allocator.Cookie, Ptr, &Header);
+ if (UNLIKELY(Header.State != Chunk::State::Quarantined))
+ reportInvalidChunkState(AllocatorAction::Recycling, Ptr);
+
+ Chunk::UnpackedHeader NewHeader = Header;
+ NewHeader.State = Chunk::State::Available;
+ Chunk::compareExchangeHeader(Allocator.Cookie, Ptr, &NewHeader, &Header);
+
+ if (allocatorSupportsMemoryTagging<Params>())
+ Ptr = untagPointer(Ptr);
+ void *BlockBegin = Allocator::getBlockBegin(Ptr, &NewHeader);
+ Cache.deallocate(NewHeader.ClassId, BlockBegin);
+ }
+
+ // We take a shortcut when allocating a quarantine batch by working with the
+ // appropriate class ID instead of using Size. The compiler should optimize
+ // the class ID computation and work with the associated cache directly.
+ void *allocate(UNUSED uptr Size) {
+ const uptr QuarantineClassId = SizeClassMap::getClassIdBySize(
+ sizeof(QuarantineBatch) + Chunk::getHeaderSize());
+ void *Ptr = Cache.allocate(QuarantineClassId);
+ // Quarantine batch allocation failure is fatal.
+ if (UNLIKELY(!Ptr))
+ reportOutOfMemory(SizeClassMap::getSizeByClassId(QuarantineClassId));
+
+ Ptr = reinterpret_cast<void *>(reinterpret_cast<uptr>(Ptr) +
+ Chunk::getHeaderSize());
+ Chunk::UnpackedHeader Header = {};
+ Header.ClassId = QuarantineClassId & Chunk::ClassIdMask;
+ Header.SizeOrUnusedBytes = sizeof(QuarantineBatch);
+ Header.State = Chunk::State::Allocated;
+ Chunk::storeHeader(Allocator.Cookie, Ptr, &Header);
+
+ // Reset tag to 0 as this chunk may have been previously used for a tagged
+ // user allocation.
+ if (UNLIKELY(useMemoryTagging<Params>(Allocator.Primary.Options.load())))
+ storeTags(reinterpret_cast<uptr>(Ptr),
+ reinterpret_cast<uptr>(Ptr) + sizeof(QuarantineBatch));
+
+ return Ptr;
+ }
+
+ void deallocate(void *Ptr) {
+ const uptr QuarantineClassId = SizeClassMap::getClassIdBySize(
+ sizeof(QuarantineBatch) + Chunk::getHeaderSize());
+ Chunk::UnpackedHeader Header;
+ Chunk::loadHeader(Allocator.Cookie, Ptr, &Header);
+
+ if (UNLIKELY(Header.State != Chunk::State::Allocated))
+ reportInvalidChunkState(AllocatorAction::Deallocating, Ptr);
+ DCHECK_EQ(Header.ClassId, QuarantineClassId);
+ DCHECK_EQ(Header.Offset, 0);
+ DCHECK_EQ(Header.SizeOrUnusedBytes, sizeof(QuarantineBatch));
+
+ Chunk::UnpackedHeader NewHeader = Header;
+ NewHeader.State = Chunk::State::Available;
+ Chunk::compareExchangeHeader(Allocator.Cookie, Ptr, &NewHeader, &Header);
+ Cache.deallocate(QuarantineClassId,
+ reinterpret_cast<void *>(reinterpret_cast<uptr>(Ptr) -
+ Chunk::getHeaderSize()));
+ }
+
+ private:
+ ThisT &Allocator;
+ CacheT &Cache;
+ };
+
+ typedef GlobalQuarantine<QuarantineCallback, void> QuarantineT;
+ typedef typename QuarantineT::CacheT QuarantineCacheT;
+
+ void init() {
+ performSanityChecks();
+
+ // Check if hardware CRC32 is supported in the binary and by the platform,
+ // if so, opt for the CRC32 hardware version of the checksum.
+ if (&computeHardwareCRC32 && hasHardwareCRC32())
+ HashAlgorithm = Checksum::HardwareCRC32;
+
+ if (UNLIKELY(!getRandom(&Cookie, sizeof(Cookie))))
+ Cookie = static_cast<u32>(getMonotonicTime() ^
+ (reinterpret_cast<uptr>(this) >> 4));
+
+ initFlags();
+ reportUnrecognizedFlags();
+
+ RssChecker.init(scudo::getFlags()->soft_rss_limit_mb,
+ scudo::getFlags()->hard_rss_limit_mb);
+
+ // Store some flags locally.
+ if (getFlags()->may_return_null)
+ Primary.Options.set(OptionBit::MayReturnNull);
+ if (getFlags()->zero_contents)
+ Primary.Options.setFillContentsMode(ZeroFill);
+ else if (getFlags()->pattern_fill_contents)
+ Primary.Options.setFillContentsMode(PatternOrZeroFill);
+ if (getFlags()->dealloc_type_mismatch)
+ Primary.Options.set(OptionBit::DeallocTypeMismatch);
+ if (getFlags()->delete_size_mismatch)
+ Primary.Options.set(OptionBit::DeleteSizeMismatch);
+ if (allocatorSupportsMemoryTagging<Params>() &&
+ systemSupportsMemoryTagging())
+ Primary.Options.set(OptionBit::UseMemoryTagging);
+ Primary.Options.set(OptionBit::UseOddEvenTags);
+
+ QuarantineMaxChunkSize =
+ static_cast<u32>(getFlags()->quarantine_max_chunk_size);
+
+ Stats.init();
+ const s32 ReleaseToOsIntervalMs = getFlags()->release_to_os_interval_ms;
+ Primary.init(ReleaseToOsIntervalMs);
+ Secondary.init(&Stats, ReleaseToOsIntervalMs);
+ Quarantine.init(
+ static_cast<uptr>(getFlags()->quarantine_size_kb << 10),
+ static_cast<uptr>(getFlags()->thread_local_quarantine_size_kb << 10));
+
+ initRingBuffer();
+ }
+
+ // Initialize the embedded GWP-ASan instance. Requires the main allocator to
+ // be functional, best called from PostInitCallback.
+ void initGwpAsan() {
+#ifdef GWP_ASAN_HOOKS
+ gwp_asan::options::Options Opt;
+ Opt.Enabled = getFlags()->GWP_ASAN_Enabled;
+ Opt.MaxSimultaneousAllocations =
+ getFlags()->GWP_ASAN_MaxSimultaneousAllocations;
+ Opt.SampleRate = getFlags()->GWP_ASAN_SampleRate;
+ Opt.InstallSignalHandlers = getFlags()->GWP_ASAN_InstallSignalHandlers;
+ Opt.Recoverable = getFlags()->GWP_ASAN_Recoverable;
+ // Embedded GWP-ASan is locked through the Scudo atfork handler (via
+ // Allocator::disable calling GWPASan.disable). Disable GWP-ASan's atfork
+ // handler.
+ Opt.InstallForkHandlers = false;
+ Opt.Backtrace = gwp_asan::backtrace::getBacktraceFunction();
+ GuardedAlloc.init(Opt);
+
+ if (Opt.InstallSignalHandlers)
+ gwp_asan::segv_handler::installSignalHandlers(
+ &GuardedAlloc, Printf,
+ gwp_asan::backtrace::getPrintBacktraceFunction(),
+ gwp_asan::backtrace::getSegvBacktraceFunction(),
+ Opt.Recoverable);
+
+ GuardedAllocSlotSize =
+ GuardedAlloc.getAllocatorState()->maximumAllocationSize();
+ Stats.add(StatFree, static_cast<uptr>(Opt.MaxSimultaneousAllocations) *
+ GuardedAllocSlotSize);
+#endif // GWP_ASAN_HOOKS
+ }
+
+#ifdef GWP_ASAN_HOOKS
+ const gwp_asan::AllocationMetadata *getGwpAsanAllocationMetadata() {
+ return GuardedAlloc.getMetadataRegion();
+ }
+
+ const gwp_asan::AllocatorState *getGwpAsanAllocatorState() {
+ return GuardedAlloc.getAllocatorState();
+ }
+#endif // GWP_ASAN_HOOKS
+
+ ALWAYS_INLINE void initThreadMaybe(bool MinimalInit = false) {
+ TSDRegistry.initThreadMaybe(this, MinimalInit);
+ }
+
+ void unmapTestOnly() {
+ TSDRegistry.unmapTestOnly(this);
+ Primary.unmapTestOnly();
+ Secondary.unmapTestOnly();
+#ifdef GWP_ASAN_HOOKS
+ if (getFlags()->GWP_ASAN_InstallSignalHandlers)
+ gwp_asan::segv_handler::uninstallSignalHandlers();
+ GuardedAlloc.uninitTestOnly();
+#endif // GWP_ASAN_HOOKS
+ }
+
+ TSDRegistryT *getTSDRegistry() { return &TSDRegistry; }
+
+ // The Cache must be provided zero-initialized.
+ void initCache(CacheT *Cache) { Cache->init(&Stats, &Primary); }
+
+ // Release the resources used by a TSD, which involves:
+ // - draining the local quarantine cache to the global quarantine;
+ // - releasing the cached pointers back to the Primary;
+ // - unlinking the local stats from the global ones (destroying the cache does
+ // the last two items).
+ void commitBack(TSD<ThisT> *TSD) {
+ Quarantine.drain(&TSD->QuarantineCache,
+ QuarantineCallback(*this, TSD->Cache));
+ TSD->Cache.destroy(&Stats);
+ }
+
+ ALWAYS_INLINE void *getHeaderTaggedPointer(void *Ptr) {
+ if (!allocatorSupportsMemoryTagging<Params>())
+ return Ptr;
+ auto UntaggedPtr = untagPointer(Ptr);
+ if (UntaggedPtr != Ptr)
+ return UntaggedPtr;
+ // Secondary, or pointer allocated while memory tagging is unsupported or
+ // disabled. The tag mismatch is okay in the latter case because tags will
+ // not be checked.
+ return addHeaderTag(Ptr);
+ }
+
+ ALWAYS_INLINE uptr addHeaderTag(uptr Ptr) {
+ if (!allocatorSupportsMemoryTagging<Params>())
+ return Ptr;
+ return addFixedTag(Ptr, 2);
+ }
+
+ ALWAYS_INLINE void *addHeaderTag(void *Ptr) {
+ return reinterpret_cast<void *>(addHeaderTag(reinterpret_cast<uptr>(Ptr)));
+ }
+
+ NOINLINE u32 collectStackTrace() {
+#ifdef HAVE_ANDROID_UNSAFE_FRAME_POINTER_CHASE
+ // Discard collectStackTrace() frame and allocator function frame.
+ constexpr uptr DiscardFrames = 2;
+ uptr Stack[MaxTraceSize + DiscardFrames];
+ uptr Size =
+ android_unsafe_frame_pointer_chase(Stack, MaxTraceSize + DiscardFrames);
+ Size = Min<uptr>(Size, MaxTraceSize + DiscardFrames);
+ return Depot.insert(Stack + Min<uptr>(DiscardFrames, Size), Stack + Size);
+#else
+ return 0;
+#endif
+ }
+
+ uptr computeOddEvenMaskForPointerMaybe(Options Options, uptr Ptr,
+ uptr ClassId) {
+ if (!Options.get(OptionBit::UseOddEvenTags))
+ return 0;
+
+ // If a chunk's tag is odd, we want the tags of the surrounding blocks to be
+ // even, and vice versa. Blocks are laid out Size bytes apart, and adding
+ // Size to Ptr will flip the least significant set bit of Size in Ptr, so
+ // that bit will have the pattern 010101... for consecutive blocks, which we
+ // can use to determine which tag mask to use.
+ return 0x5555U << ((Ptr >> SizeClassMap::getSizeLSBByClassId(ClassId)) & 1);
+ }
+
+ NOINLINE void *allocate(uptr Size, Chunk::Origin Origin,
+ uptr Alignment = MinAlignment,
+ bool ZeroContents = false) {
+ initThreadMaybe();
+
+ const Options Options = Primary.Options.load();
+ if (UNLIKELY(Alignment > MaxAlignment)) {
+ if (Options.get(OptionBit::MayReturnNull))
+ return nullptr;
+ reportAlignmentTooBig(Alignment, MaxAlignment);
+ }
+ if (Alignment < MinAlignment)
+ Alignment = MinAlignment;
+
+#ifdef GWP_ASAN_HOOKS
+ if (UNLIKELY(GuardedAlloc.shouldSample())) {
+ if (void *Ptr = GuardedAlloc.allocate(Size, Alignment)) {
+ if (UNLIKELY(&__scudo_allocate_hook))
+ __scudo_allocate_hook(Ptr, Size);
+ Stats.lock();
+ Stats.add(StatAllocated, GuardedAllocSlotSize);
+ Stats.sub(StatFree, GuardedAllocSlotSize);
+ Stats.unlock();
+ return Ptr;
+ }
+ }
+#endif // GWP_ASAN_HOOKS
+
+ const FillContentsMode FillContents = ZeroContents ? ZeroFill
+ : TSDRegistry.getDisableMemInit()
+ ? NoFill
+ : Options.getFillContentsMode();
+
+ // If the requested size happens to be 0 (more common than you might think),
+ // allocate MinAlignment bytes on top of the header. Then add the extra
+ // bytes required to fulfill the alignment requirements: we allocate enough
+ // to be sure that there will be an address in the block that will satisfy
+ // the alignment.
+ const uptr NeededSize =
+ roundUpTo(Size, MinAlignment) +
+ ((Alignment > MinAlignment) ? Alignment : Chunk::getHeaderSize());
+
+ // Takes care of extravagantly large sizes as well as integer overflows.
+ static_assert(MaxAllowedMallocSize < UINTPTR_MAX - MaxAlignment, "");
+ if (UNLIKELY(Size >= MaxAllowedMallocSize)) {
+ if (Options.get(OptionBit::MayReturnNull))
+ return nullptr;
+ reportAllocationSizeTooBig(Size, NeededSize, MaxAllowedMallocSize);
+ }
+ DCHECK_LE(Size, NeededSize);
+
+ switch (RssChecker.getRssLimitExceeded()) {
+ case RssLimitChecker::Neither:
+ break;
+ case RssLimitChecker::Soft:
+ if (Options.get(OptionBit::MayReturnNull))
+ return nullptr;
+ reportSoftRSSLimit(RssChecker.getSoftRssLimit());
+ break;
+ case RssLimitChecker::Hard:
+ reportHardRSSLimit(RssChecker.getHardRssLimit());
+ break;
+ }
+
+ void *Block = nullptr;
+ uptr ClassId = 0;
+ uptr SecondaryBlockEnd = 0;
+ if (LIKELY(PrimaryT::canAllocate(NeededSize))) {
+ ClassId = SizeClassMap::getClassIdBySize(NeededSize);
+ DCHECK_NE(ClassId, 0U);
+ bool UnlockRequired;
+ auto *TSD = TSDRegistry.getTSDAndLock(&UnlockRequired);
+ Block = TSD->Cache.allocate(ClassId);
+ // If the allocation failed, the most likely reason with a 32-bit primary
+ // is the region being full. In that event, retry in each successively
+ // larger class until it fits. If it fails to fit in the largest class,
+ // fallback to the Secondary.
+ if (UNLIKELY(!Block)) {
+ while (ClassId < SizeClassMap::LargestClassId && !Block)
+ Block = TSD->Cache.allocate(++ClassId);
+ if (!Block)
+ ClassId = 0;
+ }
+ if (UnlockRequired)
+ TSD->unlock();
+ }
+ if (UNLIKELY(ClassId == 0))
+ Block = Secondary.allocate(Options, Size, Alignment, &SecondaryBlockEnd,
+ FillContents);
+
+ if (UNLIKELY(!Block)) {
+ if (Options.get(OptionBit::MayReturnNull))
+ return nullptr;
+ reportOutOfMemory(NeededSize);
+ }
+
+ const uptr BlockUptr = reinterpret_cast<uptr>(Block);
+ const uptr UnalignedUserPtr = BlockUptr + Chunk::getHeaderSize();
+ const uptr UserPtr = roundUpTo(UnalignedUserPtr, Alignment);
+
+ void *Ptr = reinterpret_cast<void *>(UserPtr);
+ void *TaggedPtr = Ptr;
+ if (LIKELY(ClassId)) {
+ // We only need to zero or tag the contents for Primary backed
+ // allocations. We only set tags for primary allocations in order to avoid
+ // faulting potentially large numbers of pages for large secondary
+ // allocations. We assume that guard pages are enough to protect these
+ // allocations.
+ //
+ // FIXME: When the kernel provides a way to set the background tag of a
+ // mapping, we should be able to tag secondary allocations as well.
+ //
+ // When memory tagging is enabled, zeroing the contents is done as part of
+ // setting the tag.
+ if (UNLIKELY(useMemoryTagging<Params>(Options))) {
+ uptr PrevUserPtr;
+ Chunk::UnpackedHeader Header;
+ const uptr BlockSize = PrimaryT::getSizeByClassId(ClassId);
+ const uptr BlockEnd = BlockUptr + BlockSize;
+ // If possible, try to reuse the UAF tag that was set by deallocate().
+ // For simplicity, only reuse tags if we have the same start address as
+ // the previous allocation. This handles the majority of cases since
+ // most allocations will not be more aligned than the minimum alignment.
+ //
+ // We need to handle situations involving reclaimed chunks, and retag
+ // the reclaimed portions if necessary. In the case where the chunk is
+ // fully reclaimed, the chunk's header will be zero, which will trigger
+ // the code path for new mappings and invalid chunks that prepares the
+ // chunk from scratch. There are three possibilities for partial
+ // reclaiming:
+ //
+ // (1) Header was reclaimed, data was partially reclaimed.
+ // (2) Header was not reclaimed, all data was reclaimed (e.g. because
+ // data started on a page boundary).
+ // (3) Header was not reclaimed, data was partially reclaimed.
+ //
+ // Case (1) will be handled in the same way as for full reclaiming,
+ // since the header will be zero.
+ //
+ // We can detect case (2) by loading the tag from the start
+ // of the chunk. If it is zero, it means that either all data was
+ // reclaimed (since we never use zero as the chunk tag), or that the
+ // previous allocation was of size zero. Either way, we need to prepare
+ // a new chunk from scratch.
+ //
+ // We can detect case (3) by moving to the next page (if covered by the
+ // chunk) and loading the tag of its first granule. If it is zero, it
+ // means that all following pages may need to be retagged. On the other
+ // hand, if it is nonzero, we can assume that all following pages are
+ // still tagged, according to the logic that if any of the pages
+ // following the next page were reclaimed, the next page would have been
+ // reclaimed as well.
+ uptr TaggedUserPtr;
+ if (getChunkFromBlock(BlockUptr, &PrevUserPtr, &Header) &&
+ PrevUserPtr == UserPtr &&
+ (TaggedUserPtr = loadTag(UserPtr)) != UserPtr) {
+ uptr PrevEnd = TaggedUserPtr + Header.SizeOrUnusedBytes;
+ const uptr NextPage = roundUpTo(TaggedUserPtr, getPageSizeCached());
+ if (NextPage < PrevEnd && loadTag(NextPage) != NextPage)
+ PrevEnd = NextPage;
+ TaggedPtr = reinterpret_cast<void *>(TaggedUserPtr);
+ resizeTaggedChunk(PrevEnd, TaggedUserPtr + Size, Size, BlockEnd);
+ if (UNLIKELY(FillContents != NoFill && !Header.OriginOrWasZeroed)) {
+ // If an allocation needs to be zeroed (i.e. calloc) we can normally
+ // avoid zeroing the memory now since we can rely on memory having
+ // been zeroed on free, as this is normally done while setting the
+ // UAF tag. But if tagging was disabled per-thread when the memory
+ // was freed, it would not have been retagged and thus zeroed, and
+ // therefore it needs to be zeroed now.
+ memset(TaggedPtr, 0,
+ Min(Size, roundUpTo(PrevEnd - TaggedUserPtr,
+ archMemoryTagGranuleSize())));
+ } else if (Size) {
+ // Clear any stack metadata that may have previously been stored in
+ // the chunk data.
+ memset(TaggedPtr, 0, archMemoryTagGranuleSize());
+ }
+ } else {
+ const uptr OddEvenMask =
+ computeOddEvenMaskForPointerMaybe(Options, BlockUptr, ClassId);
+ TaggedPtr = prepareTaggedChunk(Ptr, Size, OddEvenMask, BlockEnd);
+ }
+ storePrimaryAllocationStackMaybe(Options, Ptr);
+ } else {
+ Block = addHeaderTag(Block);
+ Ptr = addHeaderTag(Ptr);
+ if (UNLIKELY(FillContents != NoFill)) {
+ // This condition is not necessarily unlikely, but since memset is
+ // costly, we might as well mark it as such.
+ memset(Block, FillContents == ZeroFill ? 0 : PatternFillByte,
+ PrimaryT::getSizeByClassId(ClassId));
+ }
+ }
+ } else {
+ Block = addHeaderTag(Block);
+ Ptr = addHeaderTag(Ptr);
+ if (UNLIKELY(useMemoryTagging<Params>(Options))) {
+ storeTags(reinterpret_cast<uptr>(Block), reinterpret_cast<uptr>(Ptr));
+ storeSecondaryAllocationStackMaybe(Options, Ptr, Size);
+ }
+ }
+
+ Chunk::UnpackedHeader Header = {};
+ if (UNLIKELY(UnalignedUserPtr != UserPtr)) {
+ const uptr Offset = UserPtr - UnalignedUserPtr;
+ DCHECK_GE(Offset, 2 * sizeof(u32));
+ // The BlockMarker has no security purpose, but is specifically meant for
+ // the chunk iteration function that can be used in debugging situations.
+ // It is the only situation where we have to locate the start of a chunk
+ // based on its block address.
+ reinterpret_cast<u32 *>(Block)[0] = BlockMarker;
+ reinterpret_cast<u32 *>(Block)[1] = static_cast<u32>(Offset);
+ Header.Offset = (Offset >> MinAlignmentLog) & Chunk::OffsetMask;
+ }
+ Header.ClassId = ClassId & Chunk::ClassIdMask;
+ Header.State = Chunk::State::Allocated;
+ Header.OriginOrWasZeroed = Origin & Chunk::OriginMask;
+ Header.SizeOrUnusedBytes =
+ (ClassId ? Size : SecondaryBlockEnd - (UserPtr + Size)) &
+ Chunk::SizeOrUnusedBytesMask;
+ Chunk::storeHeader(Cookie, Ptr, &Header);
+
+ if (UNLIKELY(&__scudo_allocate_hook))
+ __scudo_allocate_hook(TaggedPtr, Size);
+
+ return TaggedPtr;
+ }
+
+ NOINLINE void deallocate(void *Ptr, Chunk::Origin Origin, uptr DeleteSize = 0,
+ UNUSED uptr Alignment = MinAlignment) {
+ // For a deallocation, we only ensure minimal initialization, meaning thread
+ // local data will be left uninitialized for now (when using ELF TLS). The
+ // fallback cache will be used instead. This is a workaround for a situation
+ // where the only heap operation performed in a thread would be a free past
+ // the TLS destructors, ending up in initialized thread specific data never
+ // being destroyed properly. Any other heap operation will do a full init.
+ initThreadMaybe(/*MinimalInit=*/true);
+
+ if (UNLIKELY(&__scudo_deallocate_hook))
+ __scudo_deallocate_hook(Ptr);
+
+ if (UNLIKELY(!Ptr))
+ return;
+
+#ifdef GWP_ASAN_HOOKS
+ if (UNLIKELY(GuardedAlloc.pointerIsMine(Ptr))) {
+ GuardedAlloc.deallocate(Ptr);
+ Stats.lock();
+ Stats.add(StatFree, GuardedAllocSlotSize);
+ Stats.sub(StatAllocated, GuardedAllocSlotSize);
+ Stats.unlock();
+ return;
+ }
+#endif // GWP_ASAN_HOOKS
+
+ if (UNLIKELY(!isAligned(reinterpret_cast<uptr>(Ptr), MinAlignment)))
+ reportMisalignedPointer(AllocatorAction::Deallocating, Ptr);
+
+ void *TaggedPtr = Ptr;
+ Ptr = getHeaderTaggedPointer(Ptr);
+
+ Chunk::UnpackedHeader Header;
+ Chunk::loadHeader(Cookie, Ptr, &Header);
+
+ if (UNLIKELY(Header.State != Chunk::State::Allocated))
+ reportInvalidChunkState(AllocatorAction::Deallocating, Ptr);
+
+ const Options Options = Primary.Options.load();
+ if (Options.get(OptionBit::DeallocTypeMismatch)) {
+ if (UNLIKELY(Header.OriginOrWasZeroed != Origin)) {
+ // With the exception of memalign'd chunks, that can be still be free'd.
+ if (Header.OriginOrWasZeroed != Chunk::Origin::Memalign ||
+ Origin != Chunk::Origin::Malloc)
+ reportDeallocTypeMismatch(AllocatorAction::Deallocating, Ptr,
+ Header.OriginOrWasZeroed, Origin);
+ }
+ }
+
+ const uptr Size = getSize(Ptr, &Header);
+ if (DeleteSize && Options.get(OptionBit::DeleteSizeMismatch)) {
+ if (UNLIKELY(DeleteSize != Size))
+ reportDeleteSizeMismatch(Ptr, DeleteSize, Size);
+ }
+
+ quarantineOrDeallocateChunk(Options, TaggedPtr, &Header, Size);
+ }
+
+ void *reallocate(void *OldPtr, uptr NewSize, uptr Alignment = MinAlignment) {
+ initThreadMaybe();
+
+ const Options Options = Primary.Options.load();
+ if (UNLIKELY(NewSize >= MaxAllowedMallocSize)) {
+ if (Options.get(OptionBit::MayReturnNull))
+ return nullptr;
+ reportAllocationSizeTooBig(NewSize, 0, MaxAllowedMallocSize);
+ }
+
+ // The following cases are handled by the C wrappers.
+ DCHECK_NE(OldPtr, nullptr);
+ DCHECK_NE(NewSize, 0);
+
+#ifdef GWP_ASAN_HOOKS
+ if (UNLIKELY(GuardedAlloc.pointerIsMine(OldPtr))) {
+ uptr OldSize = GuardedAlloc.getSize(OldPtr);
+ void *NewPtr = allocate(NewSize, Chunk::Origin::Malloc, Alignment);
+ if (NewPtr)
+ memcpy(NewPtr, OldPtr, (NewSize < OldSize) ? NewSize : OldSize);
+ GuardedAlloc.deallocate(OldPtr);
+ Stats.lock();
+ Stats.add(StatFree, GuardedAllocSlotSize);
+ Stats.sub(StatAllocated, GuardedAllocSlotSize);
+ Stats.unlock();
+ return NewPtr;
+ }
+#endif // GWP_ASAN_HOOKS
+
+ void *OldTaggedPtr = OldPtr;
+ OldPtr = getHeaderTaggedPointer(OldPtr);
+
+ if (UNLIKELY(!isAligned(reinterpret_cast<uptr>(OldPtr), MinAlignment)))
+ reportMisalignedPointer(AllocatorAction::Reallocating, OldPtr);
+
+ Chunk::UnpackedHeader OldHeader;
+ Chunk::loadHeader(Cookie, OldPtr, &OldHeader);
+
+ if (UNLIKELY(OldHeader.State != Chunk::State::Allocated))
+ reportInvalidChunkState(AllocatorAction::Reallocating, OldPtr);
+
+ // Pointer has to be allocated with a malloc-type function. Some
+ // applications think that it is OK to realloc a memalign'ed pointer, which
+ // will trigger this check. It really isn't.
+ if (Options.get(OptionBit::DeallocTypeMismatch)) {
+ if (UNLIKELY(OldHeader.OriginOrWasZeroed != Chunk::Origin::Malloc))
+ reportDeallocTypeMismatch(AllocatorAction::Reallocating, OldPtr,
+ OldHeader.OriginOrWasZeroed,
+ Chunk::Origin::Malloc);
+ }
+
+ void *BlockBegin = getBlockBegin(OldTaggedPtr, &OldHeader);
+ uptr BlockEnd;
+ uptr OldSize;
+ const uptr ClassId = OldHeader.ClassId;
+ if (LIKELY(ClassId)) {
+ BlockEnd = reinterpret_cast<uptr>(BlockBegin) +
+ SizeClassMap::getSizeByClassId(ClassId);
+ OldSize = OldHeader.SizeOrUnusedBytes;
+ } else {
+ BlockEnd = SecondaryT::getBlockEnd(BlockBegin);
+ OldSize = BlockEnd - (reinterpret_cast<uptr>(OldTaggedPtr) +
+ OldHeader.SizeOrUnusedBytes);
+ }
+ // If the new chunk still fits in the previously allocated block (with a
+ // reasonable delta), we just keep the old block, and update the chunk
+ // header to reflect the size change.
+ if (reinterpret_cast<uptr>(OldTaggedPtr) + NewSize <= BlockEnd) {
+ if (NewSize > OldSize || (OldSize - NewSize) < getPageSizeCached()) {
+ Chunk::UnpackedHeader NewHeader = OldHeader;
+ NewHeader.SizeOrUnusedBytes =
+ (ClassId ? NewSize
+ : BlockEnd -
+ (reinterpret_cast<uptr>(OldTaggedPtr) + NewSize)) &
+ Chunk::SizeOrUnusedBytesMask;
+ Chunk::compareExchangeHeader(Cookie, OldPtr, &NewHeader, &OldHeader);
+ if (UNLIKELY(useMemoryTagging<Params>(Options))) {
+ if (ClassId) {
+ resizeTaggedChunk(reinterpret_cast<uptr>(OldTaggedPtr) + OldSize,
+ reinterpret_cast<uptr>(OldTaggedPtr) + NewSize,
+ NewSize, untagPointer(BlockEnd));
+ storePrimaryAllocationStackMaybe(Options, OldPtr);
+ } else {
+ storeSecondaryAllocationStackMaybe(Options, OldPtr, NewSize);
+ }
+ }
+ return OldTaggedPtr;
+ }
+ }
+
+ // Otherwise we allocate a new one, and deallocate the old one. Some
+ // allocators will allocate an even larger chunk (by a fixed factor) to
+ // allow for potential further in-place realloc. The gains of such a trick
+ // are currently unclear.
+ void *NewPtr = allocate(NewSize, Chunk::Origin::Malloc, Alignment);
+ if (LIKELY(NewPtr)) {
+ memcpy(NewPtr, OldTaggedPtr, Min(NewSize, OldSize));
+ quarantineOrDeallocateChunk(Options, OldTaggedPtr, &OldHeader, OldSize);
+ }
+ return NewPtr;
+ }
+
+ // TODO(kostyak): disable() is currently best-effort. There are some small
+ // windows of time when an allocation could still succeed after
+ // this function finishes. We will revisit that later.
+ void disable() {
+ initThreadMaybe();
+#ifdef GWP_ASAN_HOOKS
+ GuardedAlloc.disable();
+#endif
+ TSDRegistry.disable();
+ Stats.disable();
+ Quarantine.disable();
+ Primary.disable();
+ Secondary.disable();
+ }
+
+ void enable() {
+ initThreadMaybe();
+ Secondary.enable();
+ Primary.enable();
+ Quarantine.enable();
+ Stats.enable();
+ TSDRegistry.enable();
+#ifdef GWP_ASAN_HOOKS
+ GuardedAlloc.enable();
+#endif
+ }
+
+ // The function returns the amount of bytes required to store the statistics,
+ // which might be larger than the amount of bytes provided. Note that the
+ // statistics buffer is not necessarily constant between calls to this
+ // function. This can be called with a null buffer or zero size for buffer
+ // sizing purposes.
+ uptr getStats(char *Buffer, uptr Size) {
+ ScopedString Str;
+ disable();
+ const uptr Length = getStats(&Str) + 1;
+ enable();
+ if (Length < Size)
+ Size = Length;
+ if (Buffer && Size) {
+ memcpy(Buffer, Str.data(), Size);
+ Buffer[Size - 1] = '\0';
+ }
+ return Length;
+ }
+
+ void printStats() {
+ ScopedString Str;
+ disable();
+ getStats(&Str);
+ enable();
+ Str.output();
+ }
+
+ void releaseToOS() {
+ initThreadMaybe();
+ Primary.releaseToOS();
+ Secondary.releaseToOS();
+ }
+
+ // Iterate over all chunks and call a callback for all busy chunks located
+ // within the provided memory range. Said callback must not use this allocator
+ // or a deadlock can ensue. This fits Android's malloc_iterate() needs.
+ void iterateOverChunks(uptr Base, uptr Size, iterate_callback Callback,
+ void *Arg) {
+ initThreadMaybe();
+ if (archSupportsMemoryTagging())
+ Base = untagPointer(Base);
+ const uptr From = Base;
+ const uptr To = Base + Size;
+ bool MayHaveTaggedPrimary = allocatorSupportsMemoryTagging<Params>() &&
+ systemSupportsMemoryTagging();
+ auto Lambda = [this, From, To, MayHaveTaggedPrimary, Callback,
+ Arg](uptr Block) {
+ if (Block < From || Block >= To)
+ return;
+ uptr Chunk;
+ Chunk::UnpackedHeader Header;
+ if (MayHaveTaggedPrimary) {
+ // A chunk header can either have a zero tag (tagged primary) or the
+ // header tag (secondary, or untagged primary). We don't know which so
+ // try both.
+ ScopedDisableMemoryTagChecks x;
+ if (!getChunkFromBlock(Block, &Chunk, &Header) &&
+ !getChunkFromBlock(addHeaderTag(Block), &Chunk, &Header))
+ return;
+ } else {
+ if (!getChunkFromBlock(addHeaderTag(Block), &Chunk, &Header))
+ return;
+ }
+ if (Header.State == Chunk::State::Allocated) {
+ uptr TaggedChunk = Chunk;
+ if (allocatorSupportsMemoryTagging<Params>())
+ TaggedChunk = untagPointer(TaggedChunk);
+ if (useMemoryTagging<Params>(Primary.Options.load()))
+ TaggedChunk = loadTag(Chunk);
+ Callback(TaggedChunk, getSize(reinterpret_cast<void *>(Chunk), &Header),
+ Arg);
+ }
+ };
+ Primary.iterateOverBlocks(Lambda);
+ Secondary.iterateOverBlocks(Lambda);
+#ifdef GWP_ASAN_HOOKS
+ GuardedAlloc.iterate(reinterpret_cast<void *>(Base), Size, Callback, Arg);
+#endif
+ }
+
+ bool canReturnNull() {
+ initThreadMaybe();
+ return Primary.Options.load().get(OptionBit::MayReturnNull);
+ }
+
+ bool setOption(Option O, sptr Value) {
+ initThreadMaybe();
+ if (O == Option::MemtagTuning) {
+ // Enabling odd/even tags involves a tradeoff between use-after-free
+ // detection and buffer overflow detection. Odd/even tags make it more
+ // likely for buffer overflows to be detected by increasing the size of
+ // the guaranteed "red zone" around the allocation, but on the other hand
+ // use-after-free is less likely to be detected because the tag space for
+ // any particular chunk is cut in half. Therefore we use this tuning
+ // setting to control whether odd/even tags are enabled.
+ if (Value == M_MEMTAG_TUNING_BUFFER_OVERFLOW)
+ Primary.Options.set(OptionBit::UseOddEvenTags);
+ else if (Value == M_MEMTAG_TUNING_UAF)
+ Primary.Options.clear(OptionBit::UseOddEvenTags);
+ return true;
+ } else {
+ // We leave it to the various sub-components to decide whether or not they
+ // want to handle the option, but we do not want to short-circuit
+ // execution if one of the setOption was to return false.
+ const bool PrimaryResult = Primary.setOption(O, Value);
+ const bool SecondaryResult = Secondary.setOption(O, Value);
+ const bool RegistryResult = TSDRegistry.setOption(O, Value);
+ return PrimaryResult && SecondaryResult && RegistryResult;
+ }
+ return false;
+ }
+
+ // Return the usable size for a given chunk. Technically we lie, as we just
+ // report the actual size of a chunk. This is done to counteract code actively
+ // writing past the end of a chunk (like sqlite3) when the usable size allows
+ // for it, which then forces realloc to copy the usable size of a chunk as
+ // opposed to its actual size.
+ uptr getUsableSize(const void *Ptr) {
+ initThreadMaybe();
+ if (UNLIKELY(!Ptr))
+ return 0;
+
+#ifdef GWP_ASAN_HOOKS
+ if (UNLIKELY(GuardedAlloc.pointerIsMine(Ptr)))
+ return GuardedAlloc.getSize(Ptr);
+#endif // GWP_ASAN_HOOKS
+
+ Ptr = getHeaderTaggedPointer(const_cast<void *>(Ptr));
+ Chunk::UnpackedHeader Header;
+ Chunk::loadHeader(Cookie, Ptr, &Header);
+ // Getting the usable size of a chunk only makes sense if it's allocated.
+ if (UNLIKELY(Header.State != Chunk::State::Allocated))
+ reportInvalidChunkState(AllocatorAction::Sizing, const_cast<void *>(Ptr));
+ return getSize(Ptr, &Header);
+ }
+
+ void getStats(StatCounters S) {
+ initThreadMaybe();
+ Stats.get(S);
+ }
+
+ // Returns true if the pointer provided was allocated by the current
+ // allocator instance, which is compliant with tcmalloc's ownership concept.
+ // A corrupted chunk will not be reported as owned, which is WAI.
+ bool isOwned(const void *Ptr) {
+ initThreadMaybe();
+#ifdef GWP_ASAN_HOOKS
+ if (GuardedAlloc.pointerIsMine(Ptr))
+ return true;
+#endif // GWP_ASAN_HOOKS
+ if (!Ptr || !isAligned(reinterpret_cast<uptr>(Ptr), MinAlignment))
+ return false;
+ Ptr = getHeaderTaggedPointer(const_cast<void *>(Ptr));
+ Chunk::UnpackedHeader Header;
+ return Chunk::isValid(Cookie, Ptr, &Header) &&
+ Header.State == Chunk::State::Allocated;
+ }
+
+ void setRssLimitsTestOnly(int SoftRssLimitMb, int HardRssLimitMb,
+ bool MayReturnNull) {
+ RssChecker.init(SoftRssLimitMb, HardRssLimitMb);
+ if (MayReturnNull)
+ Primary.Options.set(OptionBit::MayReturnNull);
+ }
+
+ bool useMemoryTaggingTestOnly() const {
+ return useMemoryTagging<Params>(Primary.Options.load());
+ }
+ void disableMemoryTagging() {
+ // If we haven't been initialized yet, we need to initialize now in order to
+ // prevent a future call to initThreadMaybe() from enabling memory tagging
+ // based on feature detection. But don't call initThreadMaybe() because it
+ // may end up calling the allocator (via pthread_atfork, via the post-init
+ // callback), which may cause mappings to be created with memory tagging
+ // enabled.
+ TSDRegistry.initOnceMaybe(this);
+ if (allocatorSupportsMemoryTagging<Params>()) {
+ Secondary.disableMemoryTagging();
+ Primary.Options.clear(OptionBit::UseMemoryTagging);
+ }
+ }
+
+ void setTrackAllocationStacks(bool Track) {
+ initThreadMaybe();
+ if (getFlags()->allocation_ring_buffer_size == 0) {
+ DCHECK(!Primary.Options.load().get(OptionBit::TrackAllocationStacks));
+ return;
+ }
+ if (Track)
+ Primary.Options.set(OptionBit::TrackAllocationStacks);
+ else
+ Primary.Options.clear(OptionBit::TrackAllocationStacks);
+ }
+
+ void setFillContents(FillContentsMode FillContents) {
+ initThreadMaybe();
+ Primary.Options.setFillContentsMode(FillContents);
+ }
+
+ void setAddLargeAllocationSlack(bool AddSlack) {
+ initThreadMaybe();
+ if (AddSlack)
+ Primary.Options.set(OptionBit::AddLargeAllocationSlack);
+ else
+ Primary.Options.clear(OptionBit::AddLargeAllocationSlack);
+ }
+
+ const char *getStackDepotAddress() const {
+ return reinterpret_cast<const char *>(&Depot);
+ }
+
+ const char *getRegionInfoArrayAddress() const {
+ return Primary.getRegionInfoArrayAddress();
+ }
+
+ static uptr getRegionInfoArraySize() {
+ return PrimaryT::getRegionInfoArraySize();
+ }
+
+ const char *getRingBufferAddress() {
+ initThreadMaybe();
+ return RawRingBuffer;
+ }
+
+ uptr getRingBufferSize() {
+ initThreadMaybe();
+ auto *RingBuffer = getRingBuffer();
+ return RingBuffer ? ringBufferSizeInBytes(RingBuffer->Size) : 0;
+ }
+
+ static bool setRingBufferSizeForBuffer(char *Buffer, size_t Size) {
+ // Need at least one entry.
+ if (Size < sizeof(AllocationRingBuffer) +
+ sizeof(typename AllocationRingBuffer::Entry)) {
+ return false;
+ }
+ AllocationRingBuffer *RingBuffer =
+ reinterpret_cast<AllocationRingBuffer *>(Buffer);
+ RingBuffer->Size = (Size - sizeof(AllocationRingBuffer)) /
+ sizeof(typename AllocationRingBuffer::Entry);
+ return true;
+ }
+
+ static const uptr MaxTraceSize = 64;
+
+ static void collectTraceMaybe(const StackDepot *Depot,
+ uintptr_t (&Trace)[MaxTraceSize], u32 Hash) {
+ uptr RingPos, Size;
+ if (!Depot->find(Hash, &RingPos, &Size))
+ return;
+ for (unsigned I = 0; I != Size && I != MaxTraceSize; ++I)
+ Trace[I] = static_cast<uintptr_t>((*Depot)[RingPos + I]);
+ }
+
+ static void getErrorInfo(struct scudo_error_info *ErrorInfo,
+ uintptr_t FaultAddr, const char *DepotPtr,
+ const char *RegionInfoPtr, const char *RingBufferPtr,
+ const char *Memory, const char *MemoryTags,
+ uintptr_t MemoryAddr, size_t MemorySize) {
+ *ErrorInfo = {};
+ if (!allocatorSupportsMemoryTagging<Params>() ||
+ MemoryAddr + MemorySize < MemoryAddr)
+ return;
+
+ auto *Depot = reinterpret_cast<const StackDepot *>(DepotPtr);
+ size_t NextErrorReport = 0;
+
+ // Check for OOB in the current block and the two surrounding blocks. Beyond
+ // that, UAF is more likely.
+ if (extractTag(FaultAddr) != 0)
+ getInlineErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, Depot,
+ RegionInfoPtr, Memory, MemoryTags, MemoryAddr,
+ MemorySize, 0, 2);
+
+ // Check the ring buffer. For primary allocations this will only find UAF;
+ // for secondary allocations we can find either UAF or OOB.
+ getRingBufferErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, Depot,
+ RingBufferPtr);
+
+ // Check for OOB in the 28 blocks surrounding the 3 we checked earlier.
+ // Beyond that we are likely to hit false positives.
+ if (extractTag(FaultAddr) != 0)
+ getInlineErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, Depot,
+ RegionInfoPtr, Memory, MemoryTags, MemoryAddr,
+ MemorySize, 2, 16);
+ }
+
+private:
+ using SecondaryT = MapAllocator<Params>;
+ typedef typename PrimaryT::SizeClassMap SizeClassMap;
+
+ static const uptr MinAlignmentLog = SCUDO_MIN_ALIGNMENT_LOG;
+ static const uptr MaxAlignmentLog = 24U; // 16 MB seems reasonable.
+ static const uptr MinAlignment = 1UL << MinAlignmentLog;
+ static const uptr MaxAlignment = 1UL << MaxAlignmentLog;
+ static const uptr MaxAllowedMallocSize =
+ FIRST_32_SECOND_64(1UL << 31, 1ULL << 40);
+
+ static_assert(MinAlignment >= sizeof(Chunk::PackedHeader),
+ "Minimal alignment must at least cover a chunk header.");
+ static_assert(!allocatorSupportsMemoryTagging<Params>() ||
+ MinAlignment >= archMemoryTagGranuleSize(),
+ "");
+
+ static const u32 BlockMarker = 0x44554353U;
+
+ // These are indexes into an "array" of 32-bit values that store information
+ // inline with a chunk that is relevant to diagnosing memory tag faults, where
+ // 0 corresponds to the address of the user memory. This means that only
+ // negative indexes may be used. The smallest index that may be used is -2,
+ // which corresponds to 8 bytes before the user memory, because the chunk
+ // header size is 8 bytes and in allocators that support memory tagging the
+ // minimum alignment is at least the tag granule size (16 on aarch64).
+ static const sptr MemTagAllocationTraceIndex = -2;
+ static const sptr MemTagAllocationTidIndex = -1;
+
+ u32 Cookie = 0;
+ u32 QuarantineMaxChunkSize = 0;
+
+ GlobalStats Stats;
+ PrimaryT Primary;
+ SecondaryT Secondary;
+ QuarantineT Quarantine;
+ TSDRegistryT TSDRegistry;
+ pthread_once_t PostInitNonce = PTHREAD_ONCE_INIT;
+ RssLimitChecker RssChecker;
+
+#ifdef GWP_ASAN_HOOKS
+ gwp_asan::GuardedPoolAllocator GuardedAlloc;
+ uptr GuardedAllocSlotSize = 0;
+#endif // GWP_ASAN_HOOKS
+
+ StackDepot Depot;
+
+ struct AllocationRingBuffer {
+ struct Entry {
+ atomic_uptr Ptr;
+ atomic_uptr AllocationSize;
+ atomic_u32 AllocationTrace;
+ atomic_u32 AllocationTid;
+ atomic_u32 DeallocationTrace;
+ atomic_u32 DeallocationTid;
+ };
+
+ atomic_uptr Pos;
+ u32 Size;
+ // An array of Size (at least one) elements of type Entry is immediately
+ // following to this struct.
+ };
+ // Pointer to memory mapped area starting with AllocationRingBuffer struct,
+ // and immediately followed by Size elements of type Entry.
+ char *RawRingBuffer = {};
+
+ // The following might get optimized out by the compiler.
+ NOINLINE void performSanityChecks() {
+ // Verify that the header offset field can hold the maximum offset. In the
+ // case of the Secondary allocator, it takes care of alignment and the
+ // offset will always be small. In the case of the Primary, the worst case
+ // scenario happens in the last size class, when the backend allocation
+ // would already be aligned on the requested alignment, which would happen
+ // to be the maximum alignment that would fit in that size class. As a
+ // result, the maximum offset will be at most the maximum alignment for the
+ // last size class minus the header size, in multiples of MinAlignment.
+ Chunk::UnpackedHeader Header = {};
+ const uptr MaxPrimaryAlignment = 1UL << getMostSignificantSetBitIndex(
+ SizeClassMap::MaxSize - MinAlignment);
+ const uptr MaxOffset =
+ (MaxPrimaryAlignment - Chunk::getHeaderSize()) >> MinAlignmentLog;
+ Header.Offset = MaxOffset & Chunk::OffsetMask;
+ if (UNLIKELY(Header.Offset != MaxOffset))
+ reportSanityCheckError("offset");
+
+ // Verify that we can fit the maximum size or amount of unused bytes in the
+ // header. Given that the Secondary fits the allocation to a page, the worst
+ // case scenario happens in the Primary. It will depend on the second to
+ // last and last class sizes, as well as the dynamic base for the Primary.
+ // The following is an over-approximation that works for our needs.
+ const uptr MaxSizeOrUnusedBytes = SizeClassMap::MaxSize - 1;
+ Header.SizeOrUnusedBytes = MaxSizeOrUnusedBytes;
+ if (UNLIKELY(Header.SizeOrUnusedBytes != MaxSizeOrUnusedBytes))
+ reportSanityCheckError("size (or unused bytes)");
+
+ const uptr LargestClassId = SizeClassMap::LargestClassId;
+ Header.ClassId = LargestClassId;
+ if (UNLIKELY(Header.ClassId != LargestClassId))
+ reportSanityCheckError("class ID");
+ }
+
+ static inline void *getBlockBegin(const void *Ptr,
+ Chunk::UnpackedHeader *Header) {
+ return reinterpret_cast<void *>(
+ reinterpret_cast<uptr>(Ptr) - Chunk::getHeaderSize() -
+ (static_cast<uptr>(Header->Offset) << MinAlignmentLog));
+ }
+
+ // Return the size of a chunk as requested during its allocation.
+ inline uptr getSize(const void *Ptr, Chunk::UnpackedHeader *Header) {
+ const uptr SizeOrUnusedBytes = Header->SizeOrUnusedBytes;
+ if (LIKELY(Header->ClassId))
+ return SizeOrUnusedBytes;
+ if (allocatorSupportsMemoryTagging<Params>())
+ Ptr = untagPointer(const_cast<void *>(Ptr));
+ return SecondaryT::getBlockEnd(getBlockBegin(Ptr, Header)) -
+ reinterpret_cast<uptr>(Ptr) - SizeOrUnusedBytes;
+ }
+
+ void quarantineOrDeallocateChunk(Options Options, void *TaggedPtr,
+ Chunk::UnpackedHeader *Header, uptr Size) {
+ void *Ptr = getHeaderTaggedPointer(TaggedPtr);
+ Chunk::UnpackedHeader NewHeader = *Header;
+ // If the quarantine is disabled, the actual size of a chunk is 0 or larger
+ // than the maximum allowed, we return a chunk directly to the backend.
+ // This purposefully underflows for Size == 0.
+ const bool BypassQuarantine = !Quarantine.getCacheSize() ||
+ ((Size - 1) >= QuarantineMaxChunkSize) ||
+ !NewHeader.ClassId;
+ if (BypassQuarantine)
+ NewHeader.State = Chunk::State::Available;
+ else
+ NewHeader.State = Chunk::State::Quarantined;
+ NewHeader.OriginOrWasZeroed = useMemoryTagging<Params>(Options) &&
+ NewHeader.ClassId &&
+ !TSDRegistry.getDisableMemInit();
+ Chunk::compareExchangeHeader(Cookie, Ptr, &NewHeader, Header);
+
+ if (UNLIKELY(useMemoryTagging<Params>(Options))) {
+ u8 PrevTag = extractTag(reinterpret_cast<uptr>(TaggedPtr));
+ storeDeallocationStackMaybe(Options, Ptr, PrevTag, Size);
+ if (NewHeader.ClassId) {
+ if (!TSDRegistry.getDisableMemInit()) {
+ uptr TaggedBegin, TaggedEnd;
+ const uptr OddEvenMask = computeOddEvenMaskForPointerMaybe(
+ Options, reinterpret_cast<uptr>(getBlockBegin(Ptr, &NewHeader)),
+ NewHeader.ClassId);
+ // Exclude the previous tag so that immediate use after free is
+ // detected 100% of the time.
+ setRandomTag(Ptr, Size, OddEvenMask | (1UL << PrevTag), &TaggedBegin,
+ &TaggedEnd);
+ }
+ }
+ }
+ if (BypassQuarantine) {
+ if (allocatorSupportsMemoryTagging<Params>())
+ Ptr = untagPointer(Ptr);
+ void *BlockBegin = getBlockBegin(Ptr, &NewHeader);
+ const uptr ClassId = NewHeader.ClassId;
+ if (LIKELY(ClassId)) {
+ bool UnlockRequired;
+ auto *TSD = TSDRegistry.getTSDAndLock(&UnlockRequired);
+ TSD->Cache.deallocate(ClassId, BlockBegin);
+ if (UnlockRequired)
+ TSD->unlock();
+ } else {
+ if (UNLIKELY(useMemoryTagging<Params>(Options)))
+ storeTags(reinterpret_cast<uptr>(BlockBegin),
+ reinterpret_cast<uptr>(Ptr));
+ Secondary.deallocate(Options, BlockBegin);
+ }
+ } else {
+ bool UnlockRequired;
+ auto *TSD = TSDRegistry.getTSDAndLock(&UnlockRequired);
+ Quarantine.put(&TSD->QuarantineCache,
+ QuarantineCallback(*this, TSD->Cache), Ptr, Size);
+ if (UnlockRequired)
+ TSD->unlock();
+ }
+ }
+
+ bool getChunkFromBlock(uptr Block, uptr *Chunk,
+ Chunk::UnpackedHeader *Header) {
+ *Chunk =
+ Block + getChunkOffsetFromBlock(reinterpret_cast<const char *>(Block));
+ return Chunk::isValid(Cookie, reinterpret_cast<void *>(*Chunk), Header);
+ }
+
+ static uptr getChunkOffsetFromBlock(const char *Block) {
+ u32 Offset = 0;
+ if (reinterpret_cast<const u32 *>(Block)[0] == BlockMarker)
+ Offset = reinterpret_cast<const u32 *>(Block)[1];
+ return Offset + Chunk::getHeaderSize();
+ }
+
+ // Set the tag of the granule past the end of the allocation to 0, to catch
+ // linear overflows even if a previous larger allocation used the same block
+ // and tag. Only do this if the granule past the end is in our block, because
+ // this would otherwise lead to a SEGV if the allocation covers the entire
+ // block and our block is at the end of a mapping. The tag of the next block's
+ // header granule will be set to 0, so it will serve the purpose of catching
+ // linear overflows in this case.
+ //
+ // For allocations of size 0 we do not end up storing the address tag to the
+ // memory tag space, which getInlineErrorInfo() normally relies on to match
+ // address tags against chunks. To allow matching in this case we store the
+ // address tag in the first byte of the chunk.
+ void storeEndMarker(uptr End, uptr Size, uptr BlockEnd) {
+ DCHECK_EQ(BlockEnd, untagPointer(BlockEnd));
+ uptr UntaggedEnd = untagPointer(End);
+ if (UntaggedEnd != BlockEnd) {
+ storeTag(UntaggedEnd);
+ if (Size == 0)
+ *reinterpret_cast<u8 *>(UntaggedEnd) = extractTag(End);
+ }
+ }
+
+ void *prepareTaggedChunk(void *Ptr, uptr Size, uptr ExcludeMask,
+ uptr BlockEnd) {
+ // Prepare the granule before the chunk to store the chunk header by setting
+ // its tag to 0. Normally its tag will already be 0, but in the case where a
+ // chunk holding a low alignment allocation is reused for a higher alignment
+ // allocation, the chunk may already have a non-zero tag from the previous
+ // allocation.
+ storeTag(reinterpret_cast<uptr>(Ptr) - archMemoryTagGranuleSize());
+
+ uptr TaggedBegin, TaggedEnd;
+ setRandomTag(Ptr, Size, ExcludeMask, &TaggedBegin, &TaggedEnd);
+
+ storeEndMarker(TaggedEnd, Size, BlockEnd);
+ return reinterpret_cast<void *>(TaggedBegin);
+ }
+
+ void resizeTaggedChunk(uptr OldPtr, uptr NewPtr, uptr NewSize,
+ uptr BlockEnd) {
+ uptr RoundOldPtr = roundUpTo(OldPtr, archMemoryTagGranuleSize());
+ uptr RoundNewPtr;
+ if (RoundOldPtr >= NewPtr) {
+ // If the allocation is shrinking we just need to set the tag past the end
+ // of the allocation to 0. See explanation in storeEndMarker() above.
+ RoundNewPtr = roundUpTo(NewPtr, archMemoryTagGranuleSize());
+ } else {
+ // Set the memory tag of the region
+ // [RoundOldPtr, roundUpTo(NewPtr, archMemoryTagGranuleSize()))
+ // to the pointer tag stored in OldPtr.
+ RoundNewPtr = storeTags(RoundOldPtr, NewPtr);
+ }
+ storeEndMarker(RoundNewPtr, NewSize, BlockEnd);
+ }
+
+ void storePrimaryAllocationStackMaybe(Options Options, void *Ptr) {
+ if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)))
+ return;
+ auto *Ptr32 = reinterpret_cast<u32 *>(Ptr);
+ Ptr32[MemTagAllocationTraceIndex] = collectStackTrace();
+ Ptr32[MemTagAllocationTidIndex] = getThreadID();
+ }
+
+ void storeRingBufferEntry(void *Ptr, u32 AllocationTrace, u32 AllocationTid,
+ uptr AllocationSize, u32 DeallocationTrace,
+ u32 DeallocationTid) {
+ uptr Pos = atomic_fetch_add(&getRingBuffer()->Pos, 1, memory_order_relaxed);
+ typename AllocationRingBuffer::Entry *Entry =
+ getRingBufferEntry(RawRingBuffer, Pos % getRingBuffer()->Size);
+
+ // First invalidate our entry so that we don't attempt to interpret a
+ // partially written state in getSecondaryErrorInfo(). The fences below
+ // ensure that the compiler does not move the stores to Ptr in between the
+ // stores to the other fields.
+ atomic_store_relaxed(&Entry->Ptr, 0);
+
+ __atomic_signal_fence(__ATOMIC_SEQ_CST);
+ atomic_store_relaxed(&Entry->AllocationTrace, AllocationTrace);
+ atomic_store_relaxed(&Entry->AllocationTid, AllocationTid);
+ atomic_store_relaxed(&Entry->AllocationSize, AllocationSize);
+ atomic_store_relaxed(&Entry->DeallocationTrace, DeallocationTrace);
+ atomic_store_relaxed(&Entry->DeallocationTid, DeallocationTid);
+ __atomic_signal_fence(__ATOMIC_SEQ_CST);
+
+ atomic_store_relaxed(&Entry->Ptr, reinterpret_cast<uptr>(Ptr));
+ }
+
+ void storeSecondaryAllocationStackMaybe(Options Options, void *Ptr,
+ uptr Size) {
+ if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)))
+ return;
+
+ u32 Trace = collectStackTrace();
+ u32 Tid = getThreadID();
+
+ auto *Ptr32 = reinterpret_cast<u32 *>(Ptr);
+ Ptr32[MemTagAllocationTraceIndex] = Trace;
+ Ptr32[MemTagAllocationTidIndex] = Tid;
+
+ storeRingBufferEntry(untagPointer(Ptr), Trace, Tid, Size, 0, 0);
+ }
+
+ void storeDeallocationStackMaybe(Options Options, void *Ptr, u8 PrevTag,
+ uptr Size) {
+ if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)))
+ return;
+
+ auto *Ptr32 = reinterpret_cast<u32 *>(Ptr);
+ u32 AllocationTrace = Ptr32[MemTagAllocationTraceIndex];
+ u32 AllocationTid = Ptr32[MemTagAllocationTidIndex];
+
+ u32 DeallocationTrace = collectStackTrace();
+ u32 DeallocationTid = getThreadID();
+
+ storeRingBufferEntry(addFixedTag(untagPointer(Ptr), PrevTag),
+ AllocationTrace, AllocationTid, Size,
+ DeallocationTrace, DeallocationTid);
+ }
+
+ static const size_t NumErrorReports =
+ sizeof(((scudo_error_info *)nullptr)->reports) /
+ sizeof(((scudo_error_info *)nullptr)->reports[0]);
+
+ static void getInlineErrorInfo(struct scudo_error_info *ErrorInfo,
+ size_t &NextErrorReport, uintptr_t FaultAddr,
+ const StackDepot *Depot,
+ const char *RegionInfoPtr, const char *Memory,
+ const char *MemoryTags, uintptr_t MemoryAddr,
+ size_t MemorySize, size_t MinDistance,
+ size_t MaxDistance) {
+ uptr UntaggedFaultAddr = untagPointer(FaultAddr);
+ u8 FaultAddrTag = extractTag(FaultAddr);
+ BlockInfo Info =
+ PrimaryT::findNearestBlock(RegionInfoPtr, UntaggedFaultAddr);
+
+ auto GetGranule = [&](uptr Addr, const char **Data, uint8_t *Tag) -> bool {
+ if (Addr < MemoryAddr || Addr + archMemoryTagGranuleSize() < Addr ||
+ Addr + archMemoryTagGranuleSize() > MemoryAddr + MemorySize)
+ return false;
+ *Data = &Memory[Addr - MemoryAddr];
+ *Tag = static_cast<u8>(
+ MemoryTags[(Addr - MemoryAddr) / archMemoryTagGranuleSize()]);
+ return true;
+ };
+
+ auto ReadBlock = [&](uptr Addr, uptr *ChunkAddr,
+ Chunk::UnpackedHeader *Header, const u32 **Data,
+ u8 *Tag) {
+ const char *BlockBegin;
+ u8 BlockBeginTag;
+ if (!GetGranule(Addr, &BlockBegin, &BlockBeginTag))
+ return false;
+ uptr ChunkOffset = getChunkOffsetFromBlock(BlockBegin);
+ *ChunkAddr = Addr + ChunkOffset;
+
+ const char *ChunkBegin;
+ if (!GetGranule(*ChunkAddr, &ChunkBegin, Tag))
+ return false;
+ *Header = *reinterpret_cast<const Chunk::UnpackedHeader *>(
+ ChunkBegin - Chunk::getHeaderSize());
+ *Data = reinterpret_cast<const u32 *>(ChunkBegin);
+
+ // Allocations of size 0 will have stashed the tag in the first byte of
+ // the chunk, see storeEndMarker().
+ if (Header->SizeOrUnusedBytes == 0)
+ *Tag = static_cast<u8>(*ChunkBegin);
+
+ return true;
+ };
+
+ if (NextErrorReport == NumErrorReports)
+ return;
+
+ auto CheckOOB = [&](uptr BlockAddr) {
+ if (BlockAddr < Info.RegionBegin || BlockAddr >= Info.RegionEnd)
+ return false;
+
+ uptr ChunkAddr;
+ Chunk::UnpackedHeader Header;
+ const u32 *Data;
+ uint8_t Tag;
+ if (!ReadBlock(BlockAddr, &ChunkAddr, &Header, &Data, &Tag) ||
+ Header.State != Chunk::State::Allocated || Tag != FaultAddrTag)
+ return false;
+
+ auto *R = &ErrorInfo->reports[NextErrorReport++];
+ R->error_type =
+ UntaggedFaultAddr < ChunkAddr ? BUFFER_UNDERFLOW : BUFFER_OVERFLOW;
+ R->allocation_address = ChunkAddr;
+ R->allocation_size = Header.SizeOrUnusedBytes;
+ collectTraceMaybe(Depot, R->allocation_trace,
+ Data[MemTagAllocationTraceIndex]);
+ R->allocation_tid = Data[MemTagAllocationTidIndex];
+ return NextErrorReport == NumErrorReports;
+ };
+
+ if (MinDistance == 0 && CheckOOB(Info.BlockBegin))
+ return;
+
+ for (size_t I = Max<size_t>(MinDistance, 1); I != MaxDistance; ++I)
+ if (CheckOOB(Info.BlockBegin + I * Info.BlockSize) ||
+ CheckOOB(Info.BlockBegin - I * Info.BlockSize))
+ return;
+ }
+
+ static void getRingBufferErrorInfo(struct scudo_error_info *ErrorInfo,
+ size_t &NextErrorReport,
+ uintptr_t FaultAddr,
+ const StackDepot *Depot,
+ const char *RingBufferPtr) {
+ auto *RingBuffer =
+ reinterpret_cast<const AllocationRingBuffer *>(RingBufferPtr);
+ if (!RingBuffer || RingBuffer->Size == 0)
+ return;
+ uptr Pos = atomic_load_relaxed(&RingBuffer->Pos);
+
+ for (uptr I = Pos - 1;
+ I != Pos - 1 - RingBuffer->Size && NextErrorReport != NumErrorReports;
+ --I) {
+ auto *Entry = getRingBufferEntry(RingBufferPtr, I % RingBuffer->Size);
+ uptr EntryPtr = atomic_load_relaxed(&Entry->Ptr);
+ if (!EntryPtr)
+ continue;
+
+ uptr UntaggedEntryPtr = untagPointer(EntryPtr);
+ uptr EntrySize = atomic_load_relaxed(&Entry->AllocationSize);
+ u32 AllocationTrace = atomic_load_relaxed(&Entry->AllocationTrace);
+ u32 AllocationTid = atomic_load_relaxed(&Entry->AllocationTid);
+ u32 DeallocationTrace = atomic_load_relaxed(&Entry->DeallocationTrace);
+ u32 DeallocationTid = atomic_load_relaxed(&Entry->DeallocationTid);
+
+ if (DeallocationTid) {
+ // For UAF we only consider in-bounds fault addresses because
+ // out-of-bounds UAF is rare and attempting to detect it is very likely
+ // to result in false positives.
+ if (FaultAddr < EntryPtr || FaultAddr >= EntryPtr + EntrySize)
+ continue;
+ } else {
+ // Ring buffer OOB is only possible with secondary allocations. In this
+ // case we are guaranteed a guard region of at least a page on either
+ // side of the allocation (guard page on the right, guard page + tagged
+ // region on the left), so ignore any faults outside of that range.
+ if (FaultAddr < EntryPtr - getPageSizeCached() ||
+ FaultAddr >= EntryPtr + EntrySize + getPageSizeCached())
+ continue;
+
+ // For UAF the ring buffer will contain two entries, one for the
+ // allocation and another for the deallocation. Don't report buffer
+ // overflow/underflow using the allocation entry if we have already
+ // collected a report from the deallocation entry.
+ bool Found = false;
+ for (uptr J = 0; J != NextErrorReport; ++J) {
+ if (ErrorInfo->reports[J].allocation_address == UntaggedEntryPtr) {
+ Found = true;
+ break;
+ }
+ }
+ if (Found)
+ continue;
+ }
+
+ auto *R = &ErrorInfo->reports[NextErrorReport++];
+ if (DeallocationTid)
+ R->error_type = USE_AFTER_FREE;
+ else if (FaultAddr < EntryPtr)
+ R->error_type = BUFFER_UNDERFLOW;
+ else
+ R->error_type = BUFFER_OVERFLOW;
+
+ R->allocation_address = UntaggedEntryPtr;
+ R->allocation_size = EntrySize;
+ collectTraceMaybe(Depot, R->allocation_trace, AllocationTrace);
+ R->allocation_tid = AllocationTid;
+ collectTraceMaybe(Depot, R->deallocation_trace, DeallocationTrace);
+ R->deallocation_tid = DeallocationTid;
+ }
+ }
+
+ uptr getStats(ScopedString *Str) {
+ Primary.getStats(Str);
+ Secondary.getStats(Str);
+ Quarantine.getStats(Str);
+ return Str->length();
+ }
+
+ static typename AllocationRingBuffer::Entry *
+ getRingBufferEntry(char *RawRingBuffer, uptr N) {
+ return &reinterpret_cast<typename AllocationRingBuffer::Entry *>(
+ &RawRingBuffer[sizeof(AllocationRingBuffer)])[N];
+ }
+ static const typename AllocationRingBuffer::Entry *
+ getRingBufferEntry(const char *RawRingBuffer, uptr N) {
+ return &reinterpret_cast<const typename AllocationRingBuffer::Entry *>(
+ &RawRingBuffer[sizeof(AllocationRingBuffer)])[N];
+ }
+
+ void initRingBuffer() {
+ u32 AllocationRingBufferSize =
+ static_cast<u32>(getFlags()->allocation_ring_buffer_size);
+ if (AllocationRingBufferSize < 1)
+ return;
+ MapPlatformData Data = {};
+ RawRingBuffer = static_cast<char *>(
+ map(/*Addr=*/nullptr,
+ roundUpTo(ringBufferSizeInBytes(AllocationRingBufferSize), getPageSizeCached()),
+ "AllocatorRingBuffer", /*Flags=*/0, &Data));
+ auto *RingBuffer = reinterpret_cast<AllocationRingBuffer *>(RawRingBuffer);
+ RingBuffer->Size = AllocationRingBufferSize;
+ static_assert(sizeof(AllocationRingBuffer) %
+ alignof(typename AllocationRingBuffer::Entry) ==
+ 0,
+ "invalid alignment");
+ }
+
+ static constexpr size_t ringBufferSizeInBytes(u32 AllocationRingBufferSize) {
+ return sizeof(AllocationRingBuffer) +
+ AllocationRingBufferSize *
+ sizeof(typename AllocationRingBuffer::Entry);
+ }
+
+ inline AllocationRingBuffer *getRingBuffer() {
+ return reinterpret_cast<AllocationRingBuffer *>(RawRingBuffer);
+ }
+};
+
+} // namespace scudo
+
+#endif // SCUDO_COMBINED_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/common.cpp b/contrib/libs/clang16-rt/lib/scudo/standalone/common.cpp
new file mode 100644
index 00000000000..9f14faeef28
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/common.cpp
@@ -0,0 +1,42 @@
+//===-- common.cpp ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "common.h"
+#include "atomic_helpers.h"
+#include "string_utils.h"
+
+namespace scudo {
+
+uptr PageSizeCached;
+uptr getPageSize();
+
+uptr getPageSizeSlow() {
+ PageSizeCached = getPageSize();
+ CHECK_NE(PageSizeCached, 0);
+ return PageSizeCached;
+}
+
+// Fatal internal map() or unmap() error (potentially OOM related).
+void NORETURN dieOnMapUnmapError(uptr SizeIfOOM) {
+ char Error[128] = "Scudo ERROR: internal map or unmap failure\n";
+ if (SizeIfOOM) {
+ formatString(
+ Error, sizeof(Error),
+ "Scudo ERROR: internal map failure (NO MEMORY) requesting %zuKB\n",
+ SizeIfOOM >> 10);
+ }
+ outputRaw(Error);
+ setAbortMessage(Error);
+ die();
+}
+
+#if !SCUDO_LINUX
+uptr GetRSS() { return 0; }
+#endif
+
+} // namespace scudo
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/common.h b/contrib/libs/clang16-rt/lib/scudo/standalone/common.h
new file mode 100644
index 00000000000..2ec9a630359
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/common.h
@@ -0,0 +1,214 @@
+//===-- common.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_COMMON_H_
+#define SCUDO_COMMON_H_
+
+#include "internal_defs.h"
+
+#include "fuchsia.h"
+#include "linux.h"
+#include "trusty.h"
+
+#include <stddef.h>
+#include <string.h>
+
+namespace scudo {
+
+template <class Dest, class Source> inline Dest bit_cast(const Source &S) {
+ static_assert(sizeof(Dest) == sizeof(Source), "");
+ Dest D;
+ memcpy(&D, &S, sizeof(D));
+ return D;
+}
+
+inline constexpr uptr roundUpTo(uptr X, uptr Boundary) {
+ return (X + Boundary - 1) & ~(Boundary - 1);
+}
+
+inline constexpr uptr roundDownTo(uptr X, uptr Boundary) {
+ return X & ~(Boundary - 1);
+}
+
+inline constexpr bool isAligned(uptr X, uptr Alignment) {
+ return (X & (Alignment - 1)) == 0;
+}
+
+template <class T> constexpr T Min(T A, T B) { return A < B ? A : B; }
+
+template <class T> constexpr T Max(T A, T B) { return A > B ? A : B; }
+
+template <class T> void Swap(T &A, T &B) {
+ T Tmp = A;
+ A = B;
+ B = Tmp;
+}
+
+inline bool isPowerOfTwo(uptr X) { return (X & (X - 1)) == 0; }
+
+inline uptr getMostSignificantSetBitIndex(uptr X) {
+ DCHECK_NE(X, 0U);
+ return SCUDO_WORDSIZE - 1U - static_cast<uptr>(__builtin_clzl(X));
+}
+
+inline uptr roundUpToPowerOfTwo(uptr Size) {
+ DCHECK(Size);
+ if (isPowerOfTwo(Size))
+ return Size;
+ const uptr Up = getMostSignificantSetBitIndex(Size);
+ DCHECK_LT(Size, (1UL << (Up + 1)));
+ DCHECK_GT(Size, (1UL << Up));
+ return 1UL << (Up + 1);
+}
+
+inline uptr getLeastSignificantSetBitIndex(uptr X) {
+ DCHECK_NE(X, 0U);
+ return static_cast<uptr>(__builtin_ctzl(X));
+}
+
+inline uptr getLog2(uptr X) {
+ DCHECK(isPowerOfTwo(X));
+ return getLeastSignificantSetBitIndex(X);
+}
+
+inline u32 getRandomU32(u32 *State) {
+ // ANSI C linear congruential PRNG (16-bit output).
+ // return (*State = *State * 1103515245 + 12345) >> 16;
+ // XorShift (32-bit output).
+ *State ^= *State << 13;
+ *State ^= *State >> 17;
+ *State ^= *State << 5;
+ return *State;
+}
+
+inline u32 getRandomModN(u32 *State, u32 N) {
+ return getRandomU32(State) % N; // [0, N)
+}
+
+template <typename T> inline void shuffle(T *A, u32 N, u32 *RandState) {
+ if (N <= 1)
+ return;
+ u32 State = *RandState;
+ for (u32 I = N - 1; I > 0; I--)
+ Swap(A[I], A[getRandomModN(&State, I + 1)]);
+ *RandState = State;
+}
+
+// Hardware specific inlinable functions.
+
+inline void yieldProcessor(UNUSED u8 Count) {
+#if defined(__i386__) || defined(__x86_64__)
+ __asm__ __volatile__("" ::: "memory");
+ for (u8 I = 0; I < Count; I++)
+ __asm__ __volatile__("pause");
+#elif defined(__aarch64__) || defined(__arm__)
+ __asm__ __volatile__("" ::: "memory");
+ for (u8 I = 0; I < Count; I++)
+ __asm__ __volatile__("yield");
+#endif
+ __asm__ __volatile__("" ::: "memory");
+}
+
+// Platform specific functions.
+
+extern uptr PageSizeCached;
+uptr getPageSizeSlow();
+inline uptr getPageSizeCached() {
+ // Bionic uses a hardcoded value.
+ if (SCUDO_ANDROID)
+ return 4096U;
+ if (LIKELY(PageSizeCached))
+ return PageSizeCached;
+ return getPageSizeSlow();
+}
+
+// Returns 0 if the number of CPUs could not be determined.
+u32 getNumberOfCPUs();
+
+const char *getEnv(const char *Name);
+
+uptr GetRSS();
+
+u64 getMonotonicTime();
+
+u32 getThreadID();
+
+// Our randomness gathering function is limited to 256 bytes to ensure we get
+// as many bytes as requested, and avoid interruptions (on Linux).
+constexpr uptr MaxRandomLength = 256U;
+bool getRandom(void *Buffer, uptr Length, bool Blocking = false);
+
+// Platform memory mapping functions.
+
+#define MAP_ALLOWNOMEM (1U << 0)
+#define MAP_NOACCESS (1U << 1)
+#define MAP_RESIZABLE (1U << 2)
+#define MAP_MEMTAG (1U << 3)
+#define MAP_PRECOMMIT (1U << 4)
+
+// Our platform memory mapping use is restricted to 3 scenarios:
+// - reserve memory at a random address (MAP_NOACCESS);
+// - commit memory in a previously reserved space;
+// - commit memory at a random address.
+// As such, only a subset of parameters combinations is valid, which is checked
+// by the function implementation. The Data parameter allows to pass opaque
+// platform specific data to the function.
+// Returns nullptr on error or dies if MAP_ALLOWNOMEM is not specified.
+void *map(void *Addr, uptr Size, const char *Name, uptr Flags = 0,
+ MapPlatformData *Data = nullptr);
+
+// Indicates that we are getting rid of the whole mapping, which might have
+// further consequences on Data, depending on the platform.
+#define UNMAP_ALL (1U << 0)
+
+void unmap(void *Addr, uptr Size, uptr Flags = 0,
+ MapPlatformData *Data = nullptr);
+
+void setMemoryPermission(uptr Addr, uptr Size, uptr Flags,
+ MapPlatformData *Data = nullptr);
+
+void releasePagesToOS(uptr BaseAddress, uptr Offset, uptr Size,
+ MapPlatformData *Data = nullptr);
+
+// Internal map & unmap fatal error. This must not call map(). SizeIfOOM shall
+// hold the requested size on an out-of-memory error, 0 otherwise.
+void NORETURN dieOnMapUnmapError(uptr SizeIfOOM = 0);
+
+// Logging related functions.
+
+void setAbortMessage(const char *Message);
+
+struct BlockInfo {
+ uptr BlockBegin;
+ uptr BlockSize;
+ uptr RegionBegin;
+ uptr RegionEnd;
+};
+
+enum class Option : u8 {
+ ReleaseInterval, // Release to OS interval in milliseconds.
+ MemtagTuning, // Whether to tune tagging for UAF or overflow.
+ ThreadDisableMemInit, // Whether to disable automatic heap initialization and,
+ // where possible, memory tagging, on this thread.
+ MaxCacheEntriesCount, // Maximum number of blocks that can be cached.
+ MaxCacheEntrySize, // Maximum size of a block that can be cached.
+ MaxTSDsCount, // Number of usable TSDs for the shared registry.
+};
+
+constexpr unsigned char PatternFillByte = 0xAB;
+
+enum FillContentsMode {
+ NoFill = 0,
+ ZeroFill = 1,
+ PatternOrZeroFill = 2 // Pattern fill unless the memory is known to be
+ // zero-initialized already.
+};
+
+} // namespace scudo
+
+#endif // SCUDO_COMMON_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/crc32_hw.cpp b/contrib/libs/clang16-rt/lib/scudo/standalone/crc32_hw.cpp
new file mode 100644
index 00000000000..73f2ae000c6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/crc32_hw.cpp
@@ -0,0 +1,20 @@
+//===-- crc32_hw.cpp --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "checksum.h"
+
+namespace scudo {
+
+#if defined(__CRC32__) || defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32)
+u32 computeHardwareCRC32(u32 Crc, uptr Data) {
+ return static_cast<u32>(CRC32_INTRINSIC(Crc, Data));
+}
+#endif // defined(__CRC32__) || defined(__SSE4_2__) ||
+ // defined(__ARM_FEATURE_CRC32)
+
+} // namespace scudo
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/flags.cpp b/contrib/libs/clang16-rt/lib/scudo/standalone/flags.cpp
new file mode 100644
index 00000000000..de5153b288b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/flags.cpp
@@ -0,0 +1,73 @@
+//===-- flags.cpp -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "flags.h"
+#include "common.h"
+#include "flags_parser.h"
+
+#include "scudo/interface.h"
+
+namespace scudo {
+
+Flags *getFlags() {
+ static Flags F;
+ return &F;
+}
+
+void Flags::setDefaults() {
+#define SCUDO_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "flags.inc"
+#undef SCUDO_FLAG
+
+#ifdef GWP_ASAN_HOOKS
+#define GWP_ASAN_OPTION(Type, Name, DefaultValue, Description) \
+ GWP_ASAN_##Name = DefaultValue;
+#include "gwp_asan/options.inc"
+#undef GWP_ASAN_OPTION
+#endif // GWP_ASAN_HOOKS
+}
+
+void registerFlags(FlagParser *Parser, Flags *F) {
+#define SCUDO_FLAG(Type, Name, DefaultValue, Description) \
+ Parser->registerFlag(#Name, Description, FlagType::FT_##Type, \
+ reinterpret_cast<void *>(&F->Name));
+#include "flags.inc"
+#undef SCUDO_FLAG
+
+#ifdef GWP_ASAN_HOOKS
+#define GWP_ASAN_OPTION(Type, Name, DefaultValue, Description) \
+ Parser->registerFlag("GWP_ASAN_" #Name, Description, FlagType::FT_##Type, \
+ reinterpret_cast<void *>(&F->GWP_ASAN_##Name));
+#include "gwp_asan/options.inc"
+#undef GWP_ASAN_OPTION
+#endif // GWP_ASAN_HOOKS
+}
+
+static const char *getCompileDefinitionScudoDefaultOptions() {
+#ifdef SCUDO_DEFAULT_OPTIONS
+ return STRINGIFY(SCUDO_DEFAULT_OPTIONS);
+#else
+ return "";
+#endif
+}
+
+static const char *getScudoDefaultOptions() {
+ return (&__scudo_default_options) ? __scudo_default_options() : "";
+}
+
+void initFlags() {
+ Flags *F = getFlags();
+ F->setDefaults();
+ FlagParser Parser;
+ registerFlags(&Parser, F);
+ Parser.parseString(getCompileDefinitionScudoDefaultOptions());
+ Parser.parseString(getScudoDefaultOptions());
+ Parser.parseString(getEnv("SCUDO_OPTIONS"));
+}
+
+} // namespace scudo
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/flags.h b/contrib/libs/clang16-rt/lib/scudo/standalone/flags.h
new file mode 100644
index 00000000000..2cd0a5b1334
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/flags.h
@@ -0,0 +1,38 @@
+//===-- flags.h -------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_FLAGS_H_
+#define SCUDO_FLAGS_H_
+
+#include "internal_defs.h"
+
+namespace scudo {
+
+struct Flags {
+#define SCUDO_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "flags.inc"
+#undef SCUDO_FLAG
+
+#ifdef GWP_ASAN_HOOKS
+#define GWP_ASAN_OPTION(Type, Name, DefaultValue, Description) \
+ Type GWP_ASAN_##Name;
+#include "gwp_asan/options.inc"
+#undef GWP_ASAN_OPTION
+#endif // GWP_ASAN_HOOKS
+
+ void setDefaults();
+};
+
+Flags *getFlags();
+void initFlags();
+class FlagParser;
+void registerFlags(FlagParser *Parser, Flags *F);
+
+} // namespace scudo
+
+#endif // SCUDO_FLAGS_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/flags.inc b/contrib/libs/clang16-rt/lib/scudo/standalone/flags.inc
new file mode 100644
index 00000000000..c1f153bafdd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/flags.inc
@@ -0,0 +1,59 @@
+//===-- flags.inc -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_FLAG
+#error "Define SCUDO_FLAG prior to including this file!"
+#endif
+
+SCUDO_FLAG(int, quarantine_size_kb, 0,
+ "Size (in kilobytes) of quarantine used to delay the actual "
+ "deallocation of chunks. Lower value may reduce memory usage but "
+ "decrease the effectiveness of the mitigation.")
+
+SCUDO_FLAG(int, thread_local_quarantine_size_kb, 0,
+ "Size (in kilobytes) of per-thread cache used to offload the global "
+ "quarantine. Lower value may reduce memory usage but might increase "
+ "the contention on the global quarantine.")
+
+SCUDO_FLAG(int, quarantine_max_chunk_size, 0,
+ "Size (in bytes) up to which chunks will be quarantined (if lower "
+ "than or equal to).")
+
+SCUDO_FLAG(bool, dealloc_type_mismatch, false,
+ "Terminate on a type mismatch in allocation-deallocation functions, "
+ "eg: malloc/delete, new/free, new/delete[], etc.")
+
+SCUDO_FLAG(bool, delete_size_mismatch, true,
+ "Terminate on a size mismatch between a sized-delete and the actual "
+ "size of a chunk (as provided to new/new[]).")
+
+SCUDO_FLAG(bool, zero_contents, false, "Zero chunk contents on allocation.")
+
+SCUDO_FLAG(bool, pattern_fill_contents, false,
+ "Pattern fill chunk contents on allocation.")
+
+SCUDO_FLAG(bool, may_return_null, true,
+ "Indicate whether the allocator should terminate instead of "
+ "returning NULL in otherwise non-fatal error scenarios, eg: OOM, "
+ "invalid allocation alignments, etc.")
+
+SCUDO_FLAG(int, release_to_os_interval_ms, SCUDO_ANDROID ? INT32_MIN : 5000,
+ "Interval (in milliseconds) at which to attempt release of unused "
+ "memory to the OS. Negative values disable the feature.")
+
+SCUDO_FLAG(int, hard_rss_limit_mb, 0,
+ "Hard RSS Limit in Mb. If non-zero, once the limit is achieved, "
+ "abort the process")
+
+SCUDO_FLAG(int, soft_rss_limit_mb, 0,
+ "Soft RSS Limit in Mb. If non-zero, once the limit is reached, all "
+ "subsequent calls will fail or return NULL until the RSS goes below "
+ "the soft limit")
+
+SCUDO_FLAG(int, allocation_ring_buffer_size, 32768,
+ "Entries to keep in the allocation ring buffer for scudo.")
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/flags_parser.cpp b/contrib/libs/clang16-rt/lib/scudo/standalone/flags_parser.cpp
new file mode 100644
index 00000000000..be39fcd4f88
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/flags_parser.cpp
@@ -0,0 +1,164 @@
+//===-- flags_parser.cpp ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "flags_parser.h"
+#include "common.h"
+#include "report.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+namespace scudo {
+
+class UnknownFlagsRegistry {
+ static const u32 MaxUnknownFlags = 16;
+ const char *UnknownFlagsNames[MaxUnknownFlags];
+ u32 NumberOfUnknownFlags;
+
+public:
+ void add(const char *Name) {
+ CHECK_LT(NumberOfUnknownFlags, MaxUnknownFlags);
+ UnknownFlagsNames[NumberOfUnknownFlags++] = Name;
+ }
+
+ void report() {
+ if (!NumberOfUnknownFlags)
+ return;
+ Printf("Scudo WARNING: found %d unrecognized flag(s):\n",
+ NumberOfUnknownFlags);
+ for (u32 I = 0; I < NumberOfUnknownFlags; ++I)
+ Printf(" %s\n", UnknownFlagsNames[I]);
+ NumberOfUnknownFlags = 0;
+ }
+};
+static UnknownFlagsRegistry UnknownFlags;
+
+void reportUnrecognizedFlags() { UnknownFlags.report(); }
+
+void FlagParser::printFlagDescriptions() {
+ Printf("Available flags for Scudo:\n");
+ for (u32 I = 0; I < NumberOfFlags; ++I)
+ Printf("\t%s\n\t\t- %s\n", Flags[I].Name, Flags[I].Desc);
+}
+
+static bool isSeparator(char C) {
+ return C == ' ' || C == ',' || C == ':' || C == '\n' || C == '\t' ||
+ C == '\r';
+}
+
+static bool isSeparatorOrNull(char C) { return !C || isSeparator(C); }
+
+void FlagParser::skipWhitespace() {
+ while (isSeparator(Buffer[Pos]))
+ ++Pos;
+}
+
+void FlagParser::parseFlag() {
+ const uptr NameStart = Pos;
+ while (Buffer[Pos] != '=' && !isSeparatorOrNull(Buffer[Pos]))
+ ++Pos;
+ if (Buffer[Pos] != '=')
+ reportError("expected '='");
+ const char *Name = Buffer + NameStart;
+ const uptr ValueStart = ++Pos;
+ const char *Value;
+ if (Buffer[Pos] == '\'' || Buffer[Pos] == '"') {
+ const char Quote = Buffer[Pos++];
+ while (Buffer[Pos] != 0 && Buffer[Pos] != Quote)
+ ++Pos;
+ if (Buffer[Pos] == 0)
+ reportError("unterminated string");
+ Value = Buffer + ValueStart + 1;
+ ++Pos; // consume the closing quote
+ } else {
+ while (!isSeparatorOrNull(Buffer[Pos]))
+ ++Pos;
+ Value = Buffer + ValueStart;
+ }
+ if (!runHandler(Name, Value))
+ reportError("flag parsing failed.");
+}
+
+void FlagParser::parseFlags() {
+ while (true) {
+ skipWhitespace();
+ if (Buffer[Pos] == 0)
+ break;
+ parseFlag();
+ }
+}
+
+void FlagParser::parseString(const char *S) {
+ if (!S)
+ return;
+ // Backup current parser state to allow nested parseString() calls.
+ const char *OldBuffer = Buffer;
+ const uptr OldPos = Pos;
+ Buffer = S;
+ Pos = 0;
+
+ parseFlags();
+
+ Buffer = OldBuffer;
+ Pos = OldPos;
+}
+
+inline bool parseBool(const char *Value, bool *b) {
+ if (strncmp(Value, "0", 1) == 0 || strncmp(Value, "no", 2) == 0 ||
+ strncmp(Value, "false", 5) == 0) {
+ *b = false;
+ return true;
+ }
+ if (strncmp(Value, "1", 1) == 0 || strncmp(Value, "yes", 3) == 0 ||
+ strncmp(Value, "true", 4) == 0) {
+ *b = true;
+ return true;
+ }
+ return false;
+}
+
+bool FlagParser::runHandler(const char *Name, const char *Value) {
+ for (u32 I = 0; I < NumberOfFlags; ++I) {
+ const uptr Len = strlen(Flags[I].Name);
+ if (strncmp(Name, Flags[I].Name, Len) != 0 || Name[Len] != '=')
+ continue;
+ bool Ok = false;
+ switch (Flags[I].Type) {
+ case FlagType::FT_bool:
+ Ok = parseBool(Value, reinterpret_cast<bool *>(Flags[I].Var));
+ if (!Ok)
+ reportInvalidFlag("bool", Value);
+ break;
+ case FlagType::FT_int:
+ char *ValueEnd;
+ *reinterpret_cast<int *>(Flags[I].Var) =
+ static_cast<int>(strtol(Value, &ValueEnd, 10));
+ Ok =
+ *ValueEnd == '"' || *ValueEnd == '\'' || isSeparatorOrNull(*ValueEnd);
+ if (!Ok)
+ reportInvalidFlag("int", Value);
+ break;
+ }
+ return Ok;
+ }
+ // Unrecognized flag. This is not a fatal error, we may print a warning later.
+ UnknownFlags.add(Name);
+ return true;
+}
+
+void FlagParser::registerFlag(const char *Name, const char *Desc, FlagType Type,
+ void *Var) {
+ CHECK_LT(NumberOfFlags, MaxFlags);
+ Flags[NumberOfFlags].Name = Name;
+ Flags[NumberOfFlags].Desc = Desc;
+ Flags[NumberOfFlags].Type = Type;
+ Flags[NumberOfFlags].Var = Var;
+ ++NumberOfFlags;
+}
+
+} // namespace scudo
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/flags_parser.h b/contrib/libs/clang16-rt/lib/scudo/standalone/flags_parser.h
new file mode 100644
index 00000000000..ba832adbd90
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/flags_parser.h
@@ -0,0 +1,55 @@
+//===-- flags_parser.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_FLAGS_PARSER_H_
+#define SCUDO_FLAGS_PARSER_H_
+
+#include "report.h"
+#include "string_utils.h"
+
+#include <stddef.h>
+
+namespace scudo {
+
+enum class FlagType : u8 {
+ FT_bool,
+ FT_int,
+};
+
+class FlagParser {
+public:
+ void registerFlag(const char *Name, const char *Desc, FlagType Type,
+ void *Var);
+ void parseString(const char *S);
+ void printFlagDescriptions();
+
+private:
+ static const u32 MaxFlags = 20;
+ struct Flag {
+ const char *Name;
+ const char *Desc;
+ FlagType Type;
+ void *Var;
+ } Flags[MaxFlags];
+
+ u32 NumberOfFlags = 0;
+ const char *Buffer = nullptr;
+ uptr Pos = 0;
+
+ void reportFatalError(const char *Error);
+ void skipWhitespace();
+ void parseFlags();
+ void parseFlag();
+ bool runHandler(const char *Name, const char *Value);
+};
+
+void reportUnrecognizedFlags();
+
+} // namespace scudo
+
+#endif // SCUDO_FLAGS_PARSER_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/fuchsia.cpp b/contrib/libs/clang16-rt/lib/scudo/standalone/fuchsia.cpp
new file mode 100644
index 00000000000..2efff0a2a27
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/fuchsia.cpp
@@ -0,0 +1,220 @@
+//===-- fuchsia.cpp ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "platform.h"
+
+#if SCUDO_FUCHSIA
+
+#include "common.h"
+#include "mutex.h"
+#include "string_utils.h"
+
+#error #include <lib/sync/mutex.h> // for sync_mutex_t
+#include <stdlib.h> // for getenv()
+#error #include <zircon/compiler.h>
+#error #include <zircon/process.h>
+#error #include <zircon/sanitizer.h>
+#error #include <zircon/syscalls.h>
+
+namespace scudo {
+
+uptr getPageSize() { return _zx_system_get_page_size(); }
+
+void NORETURN die() { __builtin_trap(); }
+
+// We zero-initialize the Extra parameter of map(), make sure this is consistent
+// with ZX_HANDLE_INVALID.
+static_assert(ZX_HANDLE_INVALID == 0, "");
+
+static void *allocateVmar(uptr Size, MapPlatformData *Data, bool AllowNoMem) {
+ // Only scenario so far.
+ DCHECK(Data);
+ DCHECK_EQ(Data->Vmar, ZX_HANDLE_INVALID);
+
+ const zx_status_t Status = _zx_vmar_allocate(
+ _zx_vmar_root_self(),
+ ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE | ZX_VM_CAN_MAP_SPECIFIC, 0,
+ Size, &Data->Vmar, &Data->VmarBase);
+ if (UNLIKELY(Status != ZX_OK)) {
+ if (Status != ZX_ERR_NO_MEMORY || !AllowNoMem)
+ dieOnMapUnmapError(Status == ZX_ERR_NO_MEMORY ? Size : 0);
+ return nullptr;
+ }
+ return reinterpret_cast<void *>(Data->VmarBase);
+}
+
+void *map(void *Addr, uptr Size, const char *Name, uptr Flags,
+ MapPlatformData *Data) {
+ DCHECK_EQ(Size % getPageSizeCached(), 0);
+ const bool AllowNoMem = !!(Flags & MAP_ALLOWNOMEM);
+
+ // For MAP_NOACCESS, just allocate a Vmar and return.
+ if (Flags & MAP_NOACCESS)
+ return allocateVmar(Size, Data, AllowNoMem);
+
+ const zx_handle_t Vmar = (Data && Data->Vmar != ZX_HANDLE_INVALID)
+ ? Data->Vmar
+ : _zx_vmar_root_self();
+
+ zx_status_t Status;
+ zx_handle_t Vmo;
+ uint64_t VmoSize = 0;
+ if (Data && Data->Vmo != ZX_HANDLE_INVALID) {
+ // If a Vmo was specified, it's a resize operation.
+ CHECK(Addr);
+ DCHECK(Flags & MAP_RESIZABLE);
+ Vmo = Data->Vmo;
+ VmoSize = Data->VmoSize;
+ Status = _zx_vmo_set_size(Vmo, VmoSize + Size);
+ if (Status != ZX_OK) {
+ if (Status != ZX_ERR_NO_MEMORY || !AllowNoMem)
+ dieOnMapUnmapError(Status == ZX_ERR_NO_MEMORY ? Size : 0);
+ return nullptr;
+ }
+ } else {
+ // Otherwise, create a Vmo and set its name.
+ Status = _zx_vmo_create(Size, ZX_VMO_RESIZABLE, &Vmo);
+ if (UNLIKELY(Status != ZX_OK)) {
+ if (Status != ZX_ERR_NO_MEMORY || !AllowNoMem)
+ dieOnMapUnmapError(Status == ZX_ERR_NO_MEMORY ? Size : 0);
+ return nullptr;
+ }
+ _zx_object_set_property(Vmo, ZX_PROP_NAME, Name, strlen(Name));
+ }
+
+ uintptr_t P;
+ zx_vm_option_t MapFlags =
+ ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_ALLOW_FAULTS;
+ if (Addr)
+ DCHECK(Data);
+ const uint64_t Offset =
+ Addr ? reinterpret_cast<uintptr_t>(Addr) - Data->VmarBase : 0;
+ if (Offset)
+ MapFlags |= ZX_VM_SPECIFIC;
+ Status = _zx_vmar_map(Vmar, MapFlags, Offset, Vmo, VmoSize, Size, &P);
+ if (UNLIKELY(Status != ZX_OK)) {
+ if (Status != ZX_ERR_NO_MEMORY || !AllowNoMem)
+ dieOnMapUnmapError(Status == ZX_ERR_NO_MEMORY ? Size : 0);
+ return nullptr;
+ }
+
+ if (Flags & MAP_PRECOMMIT) {
+ Status = _zx_vmar_op_range(Vmar, ZX_VMAR_OP_COMMIT, P, Size,
+ /*buffer=*/nullptr, /*buffer_size=*/0);
+ }
+
+ // No need to track the Vmo if we don't intend on resizing it. Close it.
+ if (Flags & MAP_RESIZABLE) {
+ DCHECK(Data);
+ if (Data->Vmo == ZX_HANDLE_INVALID)
+ Data->Vmo = Vmo;
+ else
+ DCHECK_EQ(Data->Vmo, Vmo);
+ } else {
+ CHECK_EQ(_zx_handle_close(Vmo), ZX_OK);
+ }
+ if (UNLIKELY(Status != ZX_OK)) {
+ if (Status != ZX_ERR_NO_MEMORY || !AllowNoMem)
+ dieOnMapUnmapError(Status == ZX_ERR_NO_MEMORY ? Size : 0);
+ return nullptr;
+ }
+
+ if (Data)
+ Data->VmoSize += Size;
+
+ return reinterpret_cast<void *>(P);
+}
+
+void unmap(void *Addr, uptr Size, uptr Flags, MapPlatformData *Data) {
+ if (Flags & UNMAP_ALL) {
+ DCHECK_NE(Data, nullptr);
+ const zx_handle_t Vmar = Data->Vmar;
+ DCHECK_NE(Vmar, _zx_vmar_root_self());
+ // Destroying the vmar effectively unmaps the whole mapping.
+ CHECK_EQ(_zx_vmar_destroy(Vmar), ZX_OK);
+ CHECK_EQ(_zx_handle_close(Vmar), ZX_OK);
+ } else {
+ const zx_handle_t Vmar = (Data && Data->Vmar != ZX_HANDLE_INVALID)
+ ? Data->Vmar
+ : _zx_vmar_root_self();
+ const zx_status_t Status =
+ _zx_vmar_unmap(Vmar, reinterpret_cast<uintptr_t>(Addr), Size);
+ if (UNLIKELY(Status != ZX_OK))
+ dieOnMapUnmapError();
+ }
+ if (Data) {
+ if (Data->Vmo != ZX_HANDLE_INVALID)
+ CHECK_EQ(_zx_handle_close(Data->Vmo), ZX_OK);
+ memset(Data, 0, sizeof(*Data));
+ }
+}
+
+void setMemoryPermission(UNUSED uptr Addr, UNUSED uptr Size, UNUSED uptr Flags,
+ UNUSED MapPlatformData *Data) {
+ const zx_vm_option_t Prot =
+ (Flags & MAP_NOACCESS) ? 0 : (ZX_VM_PERM_READ | ZX_VM_PERM_WRITE);
+ DCHECK(Data);
+ DCHECK_NE(Data->Vmar, ZX_HANDLE_INVALID);
+ if (_zx_vmar_protect(Data->Vmar, Prot, Addr, Size) != ZX_OK)
+ dieOnMapUnmapError();
+}
+
+void releasePagesToOS(UNUSED uptr BaseAddress, uptr Offset, uptr Size,
+ MapPlatformData *Data) {
+ DCHECK(Data);
+ DCHECK_NE(Data->Vmar, ZX_HANDLE_INVALID);
+ DCHECK_NE(Data->Vmo, ZX_HANDLE_INVALID);
+ const zx_status_t Status =
+ _zx_vmo_op_range(Data->Vmo, ZX_VMO_OP_DECOMMIT, Offset, Size, NULL, 0);
+ CHECK_EQ(Status, ZX_OK);
+}
+
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+// Note: we need to flag these methods with __TA_NO_THREAD_SAFETY_ANALYSIS
+// because the Fuchsia implementation of sync_mutex_t has clang thread safety
+// annotations. Were we to apply proper capability annotations to the top level
+// HybridMutex class itself, they would not be needed. As it stands, the
+// thread analysis thinks that we are locking the mutex and accidentally leaving
+// it locked on the way out.
+bool HybridMutex::tryLock() __TA_NO_THREAD_SAFETY_ANALYSIS {
+ // Size and alignment must be compatible between both types.
+ return sync_mutex_trylock(&M) == ZX_OK;
+}
+
+void HybridMutex::lockSlow() __TA_NO_THREAD_SAFETY_ANALYSIS {
+ sync_mutex_lock(&M);
+}
+
+void HybridMutex::unlock() __TA_NO_THREAD_SAFETY_ANALYSIS {
+ sync_mutex_unlock(&M);
+}
+
+u64 getMonotonicTime() { return _zx_clock_get_monotonic(); }
+
+u32 getNumberOfCPUs() { return _zx_system_get_num_cpus(); }
+
+u32 getThreadID() { return 0; }
+
+bool getRandom(void *Buffer, uptr Length, UNUSED bool Blocking) {
+ static_assert(MaxRandomLength <= ZX_CPRNG_DRAW_MAX_LEN, "");
+ if (UNLIKELY(!Buffer || !Length || Length > MaxRandomLength))
+ return false;
+ _zx_cprng_draw(Buffer, Length);
+ return true;
+}
+
+void outputRaw(const char *Buffer) {
+ __sanitizer_log_write(Buffer, strlen(Buffer));
+}
+
+void setAbortMessage(const char *Message) {}
+
+} // namespace scudo
+
+#endif // SCUDO_FUCHSIA
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/fuchsia.h b/contrib/libs/clang16-rt/lib/scudo/standalone/fuchsia.h
new file mode 100644
index 00000000000..6de8dc5b4fe
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/fuchsia.h
@@ -0,0 +1,32 @@
+//===-- fuchsia.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_FUCHSIA_H_
+#define SCUDO_FUCHSIA_H_
+
+#include "platform.h"
+
+#if SCUDO_FUCHSIA
+
+#include <stdint.h>
+#error #include <zircon/types.h>
+
+namespace scudo {
+
+struct MapPlatformData {
+ zx_handle_t Vmar;
+ zx_handle_t Vmo;
+ uintptr_t VmarBase;
+ uint64_t VmoSize;
+};
+
+} // namespace scudo
+
+#endif // SCUDO_FUCHSIA
+
+#endif // SCUDO_FUCHSIA_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/include/scudo/interface.h b/contrib/libs/clang16-rt/lib/scudo/standalone/include/scudo/interface.h
new file mode 100644
index 00000000000..23bcfba3982
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/include/scudo/interface.h
@@ -0,0 +1,160 @@
+//===-- scudo/interface.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_INTERFACE_H_
+#define SCUDO_INTERFACE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+extern "C" {
+
+__attribute__((weak)) const char *__scudo_default_options(void);
+
+// Post-allocation & pre-deallocation hooks.
+// They must be thread-safe and not use heap related functions.
+__attribute__((weak)) void __scudo_allocate_hook(void *ptr, size_t size);
+__attribute__((weak)) void __scudo_deallocate_hook(void *ptr);
+
+void __scudo_print_stats(void);
+
+typedef void (*iterate_callback)(uintptr_t base, size_t size, void *arg);
+
+// Determine the likely cause of a tag check fault or other memory protection
+// error on a system with memory tagging support. The results are returned via
+// the error_info data structure. Up to three possible causes are returned in
+// the reports array, in decreasing order of probability. The remaining elements
+// of reports are zero-initialized.
+//
+// This function may be called from a different process from the one that
+// crashed. In this case, various data structures must be copied from the
+// crashing process to the process that analyzes the crash.
+//
+// This interface is not guaranteed to be stable and may change at any time.
+// Furthermore, the version of scudo in the crashing process must be the same as
+// the version in the process that analyzes the crash.
+//
+// fault_addr is the fault address. On aarch64 this is available in the system
+// register FAR_ELx, or siginfo.si_addr in Linux 5.11 or above. This address
+// must include the pointer tag; this is available if SA_EXPOSE_TAGBITS was set
+// in sigaction.sa_flags when the signal handler was registered. Note that the
+// kernel strips the tag from the field sigcontext.fault_address, so this
+// address is not suitable to be passed as fault_addr.
+//
+// stack_depot is a pointer to the stack depot data structure, which may be
+// obtained by calling the function __scudo_get_stack_depot_addr() in the
+// crashing process. The size of the stack depot is available by calling the
+// function __scudo_get_stack_depot_size().
+//
+// region_info is a pointer to the region info data structure, which may be
+// obtained by calling the function __scudo_get_region_info_addr() in the
+// crashing process. The size of the region info is available by calling the
+// function __scudo_get_region_info_size().
+//
+// memory is a pointer to a region of memory surrounding the fault address.
+// The more memory available via this pointer, the more likely it is that the
+// function will be able to analyze a crash correctly. It is recommended to
+// provide an amount of memory equal to 16 * the primary allocator's largest
+// size class either side of the fault address.
+//
+// memory_tags is a pointer to an array of memory tags for the memory accessed
+// via memory. Each byte of this array corresponds to a region of memory of size
+// equal to the architecturally defined memory tag granule size (16 on aarch64).
+//
+// memory_addr is the start address of memory in the crashing process's address
+// space.
+//
+// memory_size is the size of the memory region referred to by the memory
+// pointer.
+void __scudo_get_error_info(struct scudo_error_info *error_info,
+ uintptr_t fault_addr, const char *stack_depot,
+ const char *region_info, const char *ring_buffer,
+ const char *memory, const char *memory_tags,
+ uintptr_t memory_addr, size_t memory_size);
+
+enum scudo_error_type {
+ UNKNOWN,
+ USE_AFTER_FREE,
+ BUFFER_OVERFLOW,
+ BUFFER_UNDERFLOW,
+};
+
+struct scudo_error_report {
+ enum scudo_error_type error_type;
+
+ uintptr_t allocation_address;
+ uintptr_t allocation_size;
+
+ uint32_t allocation_tid;
+ uintptr_t allocation_trace[64];
+
+ uint32_t deallocation_tid;
+ uintptr_t deallocation_trace[64];
+};
+
+struct scudo_error_info {
+ struct scudo_error_report reports[3];
+};
+
+const char *__scudo_get_stack_depot_addr(void);
+size_t __scudo_get_stack_depot_size(void);
+
+const char *__scudo_get_region_info_addr(void);
+size_t __scudo_get_region_info_size(void);
+
+const char *__scudo_get_ring_buffer_addr(void);
+size_t __scudo_get_ring_buffer_size(void);
+
+#ifndef M_DECAY_TIME
+#define M_DECAY_TIME -100
+#endif
+
+#ifndef M_PURGE
+#define M_PURGE -101
+#endif
+
+// Tune the allocator's choice of memory tags to make it more likely that
+// a certain class of memory errors will be detected. The value argument should
+// be one of the M_MEMTAG_TUNING_* constants below.
+#ifndef M_MEMTAG_TUNING
+#define M_MEMTAG_TUNING -102
+#endif
+
+// Per-thread memory initialization tuning. The value argument should be one of:
+// 1: Disable automatic heap initialization and, where possible, memory tagging,
+// on this thread.
+// 0: Normal behavior.
+#ifndef M_THREAD_DISABLE_MEM_INIT
+#define M_THREAD_DISABLE_MEM_INIT -103
+#endif
+
+#ifndef M_CACHE_COUNT_MAX
+#define M_CACHE_COUNT_MAX -200
+#endif
+
+#ifndef M_CACHE_SIZE_MAX
+#define M_CACHE_SIZE_MAX -201
+#endif
+
+#ifndef M_TSDS_COUNT_MAX
+#define M_TSDS_COUNT_MAX -202
+#endif
+
+// Tune for buffer overflows.
+#ifndef M_MEMTAG_TUNING_BUFFER_OVERFLOW
+#define M_MEMTAG_TUNING_BUFFER_OVERFLOW 0
+#endif
+
+// Tune for use-after-free.
+#ifndef M_MEMTAG_TUNING_UAF
+#define M_MEMTAG_TUNING_UAF 1
+#endif
+
+} // extern "C"
+
+#endif // SCUDO_INTERFACE_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/internal_defs.h b/contrib/libs/clang16-rt/lib/scudo/standalone/internal_defs.h
new file mode 100644
index 00000000000..27c6b451ffe
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/internal_defs.h
@@ -0,0 +1,166 @@
+//===-- internal_defs.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_INTERNAL_DEFS_H_
+#define SCUDO_INTERNAL_DEFS_H_
+
+#include "platform.h"
+
+#include <stdint.h>
+
+#ifndef SCUDO_DEBUG
+#define SCUDO_DEBUG 0
+#endif
+
+#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
+
+// String related macros.
+
+#define STRINGIFY_(S) #S
+#define STRINGIFY(S) STRINGIFY_(S)
+#define CONCATENATE_(S, C) S##C
+#define CONCATENATE(S, C) CONCATENATE_(S, C)
+
+// Attributes & builtins related macros.
+
+#define INTERFACE __attribute__((visibility("default")))
+#define HIDDEN __attribute__((visibility("hidden")))
+#define WEAK __attribute__((weak))
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+#define ALIAS(X) __attribute__((alias(X)))
+#define FORMAT(F, A) __attribute__((format(printf, F, A)))
+#define NOINLINE __attribute__((noinline))
+#define NORETURN __attribute__((noreturn))
+#define LIKELY(X) __builtin_expect(!!(X), 1)
+#define UNLIKELY(X) __builtin_expect(!!(X), 0)
+#if defined(__i386__) || defined(__x86_64__)
+// __builtin_prefetch(X) generates prefetchnt0 on x86
+#define PREFETCH(X) __asm__("prefetchnta (%0)" : : "r"(X))
+#else
+#define PREFETCH(X) __builtin_prefetch(X)
+#endif
+#define UNUSED __attribute__((unused))
+#define USED __attribute__((used))
+#define NOEXCEPT noexcept
+
+// This check is only available on Clang. This is essentially an alias of
+// C++20's 'constinit' specifier which will take care of this when (if?) we can
+// ask all libc's that use Scudo to compile us with C++20. Dynamic
+// initialization is bad; Scudo is designed to be lazy-initializated on the
+// first call to malloc/free (and friends), and this generally happens in the
+// loader somewhere in libdl's init. After the loader is done, control is
+// transferred to libc's initialization, and the dynamic initializers are run.
+// If there's a dynamic initializer for Scudo, then it will clobber the
+// already-initialized Scudo, and re-initialize all its members back to default
+// values, causing various explosions. Unfortunately, marking
+// scudo::Allocator<>'s constructor as 'constexpr' isn't sufficient to prevent
+// dynamic initialization, as default initialization is fine under 'constexpr'
+// (but not 'constinit'). Clang at -O0, and gcc at all opt levels will emit a
+// dynamic initializer for any constant-initialized variables if there is a mix
+// of default-initialized and constant-initialized variables.
+//
+// If you're looking at this because your build failed, you probably introduced
+// a new member to scudo::Allocator<> (possibly transiently) that didn't have an
+// initializer. The fix is easy - just add one.
+#if defined(__has_attribute)
+#if __has_attribute(require_constant_initialization)
+#define SCUDO_REQUIRE_CONSTANT_INITIALIZATION \
+ __attribute__((__require_constant_initialization__))
+#else
+#define SCUDO_REQUIRE_CONSTANT_INITIALIZATION
+#endif
+#endif
+
+namespace scudo {
+
+typedef uintptr_t uptr;
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef intptr_t sptr;
+typedef int8_t s8;
+typedef int16_t s16;
+typedef int32_t s32;
+typedef int64_t s64;
+
+// The following two functions have platform specific implementations.
+void outputRaw(const char *Buffer);
+void NORETURN die();
+
+#define RAW_CHECK_MSG(Expr, Msg) \
+ do { \
+ if (UNLIKELY(!(Expr))) { \
+ outputRaw(Msg); \
+ die(); \
+ } \
+ } while (false)
+
+#define RAW_CHECK(Expr) RAW_CHECK_MSG(Expr, #Expr)
+
+void NORETURN reportCheckFailed(const char *File, int Line,
+ const char *Condition, u64 Value1, u64 Value2);
+#define CHECK_IMPL(C1, Op, C2) \
+ do { \
+ if (UNLIKELY(!(C1 Op C2))) { \
+ scudo::reportCheckFailed(__FILE__, __LINE__, #C1 " " #Op " " #C2, \
+ (scudo::u64)C1, (scudo::u64)C2); \
+ scudo::die(); \
+ } \
+ } while (false)
+
+#define CHECK(A) CHECK_IMPL((A), !=, 0)
+#define CHECK_EQ(A, B) CHECK_IMPL((A), ==, (B))
+#define CHECK_NE(A, B) CHECK_IMPL((A), !=, (B))
+#define CHECK_LT(A, B) CHECK_IMPL((A), <, (B))
+#define CHECK_LE(A, B) CHECK_IMPL((A), <=, (B))
+#define CHECK_GT(A, B) CHECK_IMPL((A), >, (B))
+#define CHECK_GE(A, B) CHECK_IMPL((A), >=, (B))
+
+#if SCUDO_DEBUG
+#define DCHECK(A) CHECK(A)
+#define DCHECK_EQ(A, B) CHECK_EQ(A, B)
+#define DCHECK_NE(A, B) CHECK_NE(A, B)
+#define DCHECK_LT(A, B) CHECK_LT(A, B)
+#define DCHECK_LE(A, B) CHECK_LE(A, B)
+#define DCHECK_GT(A, B) CHECK_GT(A, B)
+#define DCHECK_GE(A, B) CHECK_GE(A, B)
+#else
+#define DCHECK(A) \
+ do { \
+ } while (false && (A))
+#define DCHECK_EQ(A, B) \
+ do { \
+ } while (false && (A) == (B))
+#define DCHECK_NE(A, B) \
+ do { \
+ } while (false && (A) != (B))
+#define DCHECK_LT(A, B) \
+ do { \
+ } while (false && (A) < (B))
+#define DCHECK_LE(A, B) \
+ do { \
+ } while (false && (A) <= (B))
+#define DCHECK_GT(A, B) \
+ do { \
+ } while (false && (A) > (B))
+#define DCHECK_GE(A, B) \
+ do { \
+ } while (false && (A) >= (B))
+#endif
+
+// The superfluous die() call effectively makes this macro NORETURN.
+#define UNREACHABLE(Msg) \
+ do { \
+ CHECK(0 && Msg); \
+ die(); \
+ } while (0)
+
+} // namespace scudo
+
+#endif // SCUDO_INTERNAL_DEFS_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/linux.cpp b/contrib/libs/clang16-rt/lib/scudo/standalone/linux.cpp
new file mode 100644
index 00000000000..9c5755af575
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/linux.cpp
@@ -0,0 +1,252 @@
+//===-- linux.cpp -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "platform.h"
+
+#if SCUDO_LINUX
+
+#include "common.h"
+#include "linux.h"
+#include "mutex.h"
+#include "string_utils.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/futex.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#if SCUDO_ANDROID
+#include <sys/prctl.h>
+// Definitions of prctl arguments to set a vma name in Android kernels.
+#define ANDROID_PR_SET_VMA 0x53564d41
+#define ANDROID_PR_SET_VMA_ANON_NAME 0
+#endif
+
+namespace scudo {
+
+uptr getPageSize() { return static_cast<uptr>(sysconf(_SC_PAGESIZE)); }
+
+void NORETURN die() { abort(); }
+
+void *map(void *Addr, uptr Size, UNUSED const char *Name, uptr Flags,
+ UNUSED MapPlatformData *Data) {
+ int MmapFlags = MAP_PRIVATE | MAP_ANONYMOUS;
+ int MmapProt;
+ if (Flags & MAP_NOACCESS) {
+ MmapFlags |= MAP_NORESERVE;
+ MmapProt = PROT_NONE;
+ } else {
+ MmapProt = PROT_READ | PROT_WRITE;
+ }
+#if defined(__aarch64__)
+#ifndef PROT_MTE
+#define PROT_MTE 0x20
+#endif
+ if (Flags & MAP_MEMTAG)
+ MmapProt |= PROT_MTE;
+#endif
+ if (Addr)
+ MmapFlags |= MAP_FIXED;
+ void *P = mmap(Addr, Size, MmapProt, MmapFlags, -1, 0);
+ if (P == MAP_FAILED) {
+ if (!(Flags & MAP_ALLOWNOMEM) || errno != ENOMEM)
+ dieOnMapUnmapError(errno == ENOMEM ? Size : 0);
+ return nullptr;
+ }
+#if SCUDO_ANDROID
+ if (Name)
+ prctl(ANDROID_PR_SET_VMA, ANDROID_PR_SET_VMA_ANON_NAME, P, Size, Name);
+#endif
+ return P;
+}
+
+void unmap(void *Addr, uptr Size, UNUSED uptr Flags,
+ UNUSED MapPlatformData *Data) {
+ if (munmap(Addr, Size) != 0)
+ dieOnMapUnmapError();
+}
+
+void setMemoryPermission(uptr Addr, uptr Size, uptr Flags,
+ UNUSED MapPlatformData *Data) {
+ int Prot = (Flags & MAP_NOACCESS) ? PROT_NONE : (PROT_READ | PROT_WRITE);
+ if (mprotect(reinterpret_cast<void *>(Addr), Size, Prot) != 0)
+ dieOnMapUnmapError();
+}
+
+void releasePagesToOS(uptr BaseAddress, uptr Offset, uptr Size,
+ UNUSED MapPlatformData *Data) {
+ void *Addr = reinterpret_cast<void *>(BaseAddress + Offset);
+
+ while (madvise(Addr, Size, MADV_DONTNEED) == -1 && errno == EAGAIN) {
+ }
+}
+
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+namespace {
+enum State : u32 { Unlocked = 0, Locked = 1, Sleeping = 2 };
+}
+
+bool HybridMutex::tryLock() {
+ return atomic_compare_exchange(&M, Unlocked, Locked) == Unlocked;
+}
+
+// The following is based on https://akkadia.org/drepper/futex.pdf.
+void HybridMutex::lockSlow() {
+ u32 V = atomic_compare_exchange(&M, Unlocked, Locked);
+ if (V == Unlocked)
+ return;
+ if (V != Sleeping)
+ V = atomic_exchange(&M, Sleeping, memory_order_acquire);
+ while (V != Unlocked) {
+ syscall(SYS_futex, reinterpret_cast<uptr>(&M), FUTEX_WAIT_PRIVATE, Sleeping,
+ nullptr, nullptr, 0);
+ V = atomic_exchange(&M, Sleeping, memory_order_acquire);
+ }
+}
+
+void HybridMutex::unlock() {
+ if (atomic_fetch_sub(&M, 1U, memory_order_release) != Locked) {
+ atomic_store(&M, Unlocked, memory_order_release);
+ syscall(SYS_futex, reinterpret_cast<uptr>(&M), FUTEX_WAKE_PRIVATE, 1,
+ nullptr, nullptr, 0);
+ }
+}
+
+u64 getMonotonicTime() {
+ timespec TS;
+ clock_gettime(CLOCK_MONOTONIC, &TS);
+ return static_cast<u64>(TS.tv_sec) * (1000ULL * 1000 * 1000) +
+ static_cast<u64>(TS.tv_nsec);
+}
+
+u32 getNumberOfCPUs() {
+ cpu_set_t CPUs;
+ // sched_getaffinity can fail for a variety of legitimate reasons (lack of
+ // CAP_SYS_NICE, syscall filtering, etc), in which case we shall return 0.
+ if (sched_getaffinity(0, sizeof(cpu_set_t), &CPUs) != 0)
+ return 0;
+ return static_cast<u32>(CPU_COUNT(&CPUs));
+}
+
+u32 getThreadID() {
+#if SCUDO_ANDROID
+ return static_cast<u32>(gettid());
+#else
+ return static_cast<u32>(syscall(SYS_gettid));
+#endif
+}
+
+// Blocking is possibly unused if the getrandom block is not compiled in.
+bool getRandom(void *Buffer, uptr Length, UNUSED bool Blocking) {
+ if (!Buffer || !Length || Length > MaxRandomLength)
+ return false;
+ ssize_t ReadBytes;
+#if defined(SYS_getrandom)
+#if !defined(GRND_NONBLOCK)
+#define GRND_NONBLOCK 1
+#endif
+ // Up to 256 bytes, getrandom will not be interrupted.
+ ReadBytes =
+ syscall(SYS_getrandom, Buffer, Length, Blocking ? 0 : GRND_NONBLOCK);
+ if (ReadBytes == static_cast<ssize_t>(Length))
+ return true;
+#endif // defined(SYS_getrandom)
+ // Up to 256 bytes, a read off /dev/urandom will not be interrupted.
+ // Blocking is moot here, O_NONBLOCK has no effect when opening /dev/urandom.
+ const int FileDesc = open("/dev/urandom", O_RDONLY);
+ if (FileDesc == -1)
+ return false;
+ ReadBytes = read(FileDesc, Buffer, Length);
+ close(FileDesc);
+ return (ReadBytes == static_cast<ssize_t>(Length));
+}
+
+// Allocation free syslog-like API.
+extern "C" WEAK int async_safe_write_log(int pri, const char *tag,
+ const char *msg);
+
+static uptr GetRSSFromBuffer(const char *Buf) {
+ // The format of the file is:
+ // 1084 89 69 11 0 79 0
+ // We need the second number which is RSS in pages.
+ const char *Pos = Buf;
+ // Skip the first number.
+ while (*Pos >= '0' && *Pos <= '9')
+ Pos++;
+ // Skip whitespaces.
+ while (!(*Pos >= '0' && *Pos <= '9') && *Pos != 0)
+ Pos++;
+ // Read the number.
+ u64 Rss = 0;
+ for (; *Pos >= '0' && *Pos <= '9'; Pos++)
+ Rss = Rss * 10 + static_cast<u64>(*Pos) - '0';
+ return static_cast<uptr>(Rss * getPageSizeCached());
+}
+
+uptr GetRSS() {
+ // TODO: We currently use sanitizer_common's GetRSS which reads the
+ // RSS from /proc/self/statm by default. We might want to
+ // call getrusage directly, even if it's less accurate.
+ auto Fd = open("/proc/self/statm", O_RDONLY);
+ char Buf[64];
+ s64 Len = read(Fd, Buf, sizeof(Buf) - 1);
+ close(Fd);
+ if (Len <= 0)
+ return 0;
+ Buf[Len] = 0;
+
+ return GetRSSFromBuffer(Buf);
+}
+
+void outputRaw(const char *Buffer) {
+ if (&async_safe_write_log) {
+ constexpr s32 AndroidLogInfo = 4;
+ constexpr uptr MaxLength = 1024U;
+ char LocalBuffer[MaxLength];
+ while (strlen(Buffer) > MaxLength) {
+ uptr P;
+ for (P = MaxLength - 1; P > 0; P--) {
+ if (Buffer[P] == '\n') {
+ memcpy(LocalBuffer, Buffer, P);
+ LocalBuffer[P] = '\0';
+ async_safe_write_log(AndroidLogInfo, "scudo", LocalBuffer);
+ Buffer = &Buffer[P + 1];
+ break;
+ }
+ }
+ // If no newline was found, just log the buffer.
+ if (P == 0)
+ break;
+ }
+ async_safe_write_log(AndroidLogInfo, "scudo", Buffer);
+ } else {
+ (void)write(2, Buffer, strlen(Buffer));
+ }
+}
+
+extern "C" WEAK void android_set_abort_message(const char *);
+
+void setAbortMessage(const char *Message) {
+ if (&android_set_abort_message)
+ android_set_abort_message(Message);
+}
+
+} // namespace scudo
+
+#endif // SCUDO_LINUX
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/linux.h b/contrib/libs/clang16-rt/lib/scudo/standalone/linux.h
new file mode 100644
index 00000000000..72acb6da83a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/linux.h
@@ -0,0 +1,25 @@
+//===-- linux.h -------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_LINUX_H_
+#define SCUDO_LINUX_H_
+
+#include "platform.h"
+
+#if SCUDO_LINUX
+
+namespace scudo {
+
+// MapPlatformData is unused on Linux, define it as a minimally sized structure.
+struct MapPlatformData {};
+
+} // namespace scudo
+
+#endif // SCUDO_LINUX
+
+#endif // SCUDO_LINUX_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/list.h b/contrib/libs/clang16-rt/lib/scudo/standalone/list.h
new file mode 100644
index 00000000000..0137667d1dc
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/list.h
@@ -0,0 +1,240 @@
+//===-- list.h --------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_LIST_H_
+#define SCUDO_LIST_H_
+
+#include "internal_defs.h"
+
+namespace scudo {
+
+// Intrusive POD singly and doubly linked list.
+// An object with all zero fields should represent a valid empty list. clear()
+// should be called on all non-zero-initialized objects before using.
+
+template <class T> class IteratorBase {
+public:
+ explicit IteratorBase(T *CurrentT) : Current(CurrentT) {}
+ IteratorBase &operator++() {
+ Current = Current->Next;
+ return *this;
+ }
+ bool operator!=(IteratorBase Other) const { return Current != Other.Current; }
+ T &operator*() { return *Current; }
+
+private:
+ T *Current;
+};
+
+template <class T> struct IntrusiveList {
+ bool empty() const { return Size == 0; }
+ uptr size() const { return Size; }
+
+ T *front() { return First; }
+ const T *front() const { return First; }
+ T *back() { return Last; }
+ const T *back() const { return Last; }
+
+ void clear() {
+ First = Last = nullptr;
+ Size = 0;
+ }
+
+ typedef IteratorBase<T> Iterator;
+ typedef IteratorBase<const T> ConstIterator;
+
+ Iterator begin() { return Iterator(First); }
+ Iterator end() { return Iterator(nullptr); }
+
+ ConstIterator begin() const { return ConstIterator(First); }
+ ConstIterator end() const { return ConstIterator(nullptr); }
+
+ void checkConsistency() const;
+
+protected:
+ uptr Size = 0;
+ T *First = nullptr;
+ T *Last = nullptr;
+};
+
+template <class T> void IntrusiveList<T>::checkConsistency() const {
+ if (Size == 0) {
+ CHECK_EQ(First, nullptr);
+ CHECK_EQ(Last, nullptr);
+ } else {
+ uptr Count = 0;
+ for (T *I = First;; I = I->Next) {
+ Count++;
+ if (I == Last)
+ break;
+ }
+ CHECK_EQ(this->size(), Count);
+ CHECK_EQ(Last->Next, nullptr);
+ }
+}
+
+template <class T> struct SinglyLinkedList : public IntrusiveList<T> {
+ using IntrusiveList<T>::First;
+ using IntrusiveList<T>::Last;
+ using IntrusiveList<T>::Size;
+ using IntrusiveList<T>::empty;
+
+ void push_back(T *X) {
+ X->Next = nullptr;
+ if (empty())
+ First = X;
+ else
+ Last->Next = X;
+ Last = X;
+ Size++;
+ }
+
+ void push_front(T *X) {
+ if (empty())
+ Last = X;
+ X->Next = First;
+ First = X;
+ Size++;
+ }
+
+ void pop_front() {
+ DCHECK(!empty());
+ First = First->Next;
+ if (!First)
+ Last = nullptr;
+ Size--;
+ }
+
+ // Insert X next to Prev
+ void insert(T *Prev, T *X) {
+ DCHECK(!empty());
+ DCHECK_NE(Prev, nullptr);
+ DCHECK_NE(X, nullptr);
+ X->Next = Prev->Next;
+ Prev->Next = X;
+ if (Last == Prev)
+ Last = X;
+ ++Size;
+ }
+
+ void extract(T *Prev, T *X) {
+ DCHECK(!empty());
+ DCHECK_NE(Prev, nullptr);
+ DCHECK_NE(X, nullptr);
+ DCHECK_EQ(Prev->Next, X);
+ Prev->Next = X->Next;
+ if (Last == X)
+ Last = Prev;
+ Size--;
+ }
+
+ void append_back(SinglyLinkedList<T> *L) {
+ DCHECK_NE(this, L);
+ if (L->empty())
+ return;
+ if (empty()) {
+ *this = *L;
+ } else {
+ Last->Next = L->First;
+ Last = L->Last;
+ Size += L->size();
+ }
+ L->clear();
+ }
+};
+
+template <class T> struct DoublyLinkedList : IntrusiveList<T> {
+ using IntrusiveList<T>::First;
+ using IntrusiveList<T>::Last;
+ using IntrusiveList<T>::Size;
+ using IntrusiveList<T>::empty;
+
+ void push_front(T *X) {
+ X->Prev = nullptr;
+ if (empty()) {
+ Last = X;
+ } else {
+ DCHECK_EQ(First->Prev, nullptr);
+ First->Prev = X;
+ }
+ X->Next = First;
+ First = X;
+ Size++;
+ }
+
+ // Inserts X before Y.
+ void insert(T *X, T *Y) {
+ if (Y == First)
+ return push_front(X);
+ T *Prev = Y->Prev;
+ // This is a hard CHECK to ensure consistency in the event of an intentional
+ // corruption of Y->Prev, to prevent a potential write-{4,8}.
+ CHECK_EQ(Prev->Next, Y);
+ Prev->Next = X;
+ X->Prev = Prev;
+ X->Next = Y;
+ Y->Prev = X;
+ Size++;
+ }
+
+ void push_back(T *X) {
+ X->Next = nullptr;
+ if (empty()) {
+ First = X;
+ } else {
+ DCHECK_EQ(Last->Next, nullptr);
+ Last->Next = X;
+ }
+ X->Prev = Last;
+ Last = X;
+ Size++;
+ }
+
+ void pop_front() {
+ DCHECK(!empty());
+ First = First->Next;
+ if (!First)
+ Last = nullptr;
+ else
+ First->Prev = nullptr;
+ Size--;
+ }
+
+ // The consistency of the adjacent links is aggressively checked in order to
+ // catch potential corruption attempts, that could yield a mirrored
+ // write-{4,8} primitive. nullptr checks are deemed less vital.
+ void remove(T *X) {
+ T *Prev = X->Prev;
+ T *Next = X->Next;
+ if (Prev) {
+ CHECK_EQ(Prev->Next, X);
+ Prev->Next = Next;
+ }
+ if (Next) {
+ CHECK_EQ(Next->Prev, X);
+ Next->Prev = Prev;
+ }
+ if (First == X) {
+ DCHECK_EQ(Prev, nullptr);
+ First = Next;
+ } else {
+ DCHECK_NE(Prev, nullptr);
+ }
+ if (Last == X) {
+ DCHECK_EQ(Next, nullptr);
+ Last = Prev;
+ } else {
+ DCHECK_NE(Next, nullptr);
+ }
+ Size--;
+ }
+};
+
+} // namespace scudo
+
+#endif // SCUDO_LIST_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/local_cache.h b/contrib/libs/clang16-rt/lib/scudo/standalone/local_cache.h
new file mode 100644
index 00000000000..6e84158659a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/local_cache.h
@@ -0,0 +1,234 @@
+//===-- local_cache.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_LOCAL_CACHE_H_
+#define SCUDO_LOCAL_CACHE_H_
+
+#include "internal_defs.h"
+#include "list.h"
+#include "platform.h"
+#include "report.h"
+#include "stats.h"
+
+namespace scudo {
+
+template <class SizeClassAllocator> struct SizeClassAllocatorLocalCache {
+ typedef typename SizeClassAllocator::SizeClassMap SizeClassMap;
+ typedef typename SizeClassAllocator::CompactPtrT CompactPtrT;
+
+ struct TransferBatch {
+ static const u16 MaxNumCached = SizeClassMap::MaxNumCachedHint;
+ void setFromArray(CompactPtrT *Array, u16 N) {
+ DCHECK_LE(N, MaxNumCached);
+ Count = N;
+ memcpy(Batch, Array, sizeof(Batch[0]) * Count);
+ }
+ void appendFromArray(CompactPtrT *Array, u16 N) {
+ DCHECK_LE(N, MaxNumCached - Count);
+ memcpy(Batch + Count, Array, sizeof(Batch[0]) * N);
+ // u16 will be promoted to int by arithmetic type conversion.
+ Count = static_cast<u16>(Count + N);
+ }
+ void clear() { Count = 0; }
+ void add(CompactPtrT P) {
+ DCHECK_LT(Count, MaxNumCached);
+ Batch[Count++] = P;
+ }
+ void copyToArray(CompactPtrT *Array) const {
+ memcpy(Array, Batch, sizeof(Batch[0]) * Count);
+ }
+ u16 getCount() const { return Count; }
+ CompactPtrT get(u16 I) const {
+ DCHECK_LE(I, Count);
+ return Batch[I];
+ }
+ static u16 getMaxCached(uptr Size) {
+ return Min(MaxNumCached, SizeClassMap::getMaxCachedHint(Size));
+ }
+ TransferBatch *Next;
+
+ private:
+ CompactPtrT Batch[MaxNumCached];
+ u16 Count;
+ };
+
+ // A BatchGroup is used to collect blocks. Each group has a group id to
+ // identify the group kind of contained blocks.
+ struct BatchGroup {
+ // `Next` is used by IntrusiveList.
+ BatchGroup *Next;
+ // The identifier of each group
+ uptr GroupId;
+ // Cache value of TransferBatch::getMaxCached()
+ u16 MaxCachedPerBatch;
+ // Number of blocks pushed into this group. This is an increment-only
+ // counter.
+ uptr PushedBlocks;
+ // This is used to track how many blocks are pushed since last time we
+ // checked `PushedBlocks`. It's useful for page releasing to determine the
+ // usage of a BatchGroup.
+ uptr PushedBlocksAtLastCheckpoint;
+ // Blocks are managed by TransferBatch in a list.
+ SinglyLinkedList<TransferBatch> Batches;
+ };
+
+ static_assert(sizeof(BatchGroup) <= sizeof(TransferBatch),
+ "BatchGroup uses the same class size as TransferBatch");
+
+ void init(GlobalStats *S, SizeClassAllocator *A) {
+ DCHECK(isEmpty());
+ Stats.init();
+ if (LIKELY(S))
+ S->link(&Stats);
+ Allocator = A;
+ }
+
+ void destroy(GlobalStats *S) {
+ drain();
+ if (LIKELY(S))
+ S->unlink(&Stats);
+ }
+
+ void *allocate(uptr ClassId) {
+ DCHECK_LT(ClassId, NumClasses);
+ PerClass *C = &PerClassArray[ClassId];
+ if (C->Count == 0) {
+ if (UNLIKELY(!refill(C, ClassId)))
+ return nullptr;
+ DCHECK_GT(C->Count, 0);
+ }
+ // We read ClassSize first before accessing Chunks because it's adjacent to
+ // Count, while Chunks might be further off (depending on Count). That keeps
+ // the memory accesses in close quarters.
+ const uptr ClassSize = C->ClassSize;
+ CompactPtrT CompactP = C->Chunks[--C->Count];
+ Stats.add(StatAllocated, ClassSize);
+ Stats.sub(StatFree, ClassSize);
+ return Allocator->decompactPtr(ClassId, CompactP);
+ }
+
+ void deallocate(uptr ClassId, void *P) {
+ CHECK_LT(ClassId, NumClasses);
+ PerClass *C = &PerClassArray[ClassId];
+ // We still have to initialize the cache in the event that the first heap
+ // operation in a thread is a deallocation.
+ initCacheMaybe(C);
+ if (C->Count == C->MaxCount)
+ drain(C, ClassId);
+ // See comment in allocate() about memory accesses.
+ const uptr ClassSize = C->ClassSize;
+ C->Chunks[C->Count++] =
+ Allocator->compactPtr(ClassId, reinterpret_cast<uptr>(P));
+ Stats.sub(StatAllocated, ClassSize);
+ Stats.add(StatFree, ClassSize);
+ }
+
+ bool isEmpty() const {
+ for (uptr I = 0; I < NumClasses; ++I)
+ if (PerClassArray[I].Count)
+ return false;
+ return true;
+ }
+
+ void drain() {
+ // Drain BatchClassId last as createBatch can refill it.
+ for (uptr I = 0; I < NumClasses; ++I) {
+ if (I == BatchClassId)
+ continue;
+ while (PerClassArray[I].Count > 0)
+ drain(&PerClassArray[I], I);
+ }
+ while (PerClassArray[BatchClassId].Count > 0)
+ drain(&PerClassArray[BatchClassId], BatchClassId);
+ DCHECK(isEmpty());
+ }
+
+ TransferBatch *createBatch(uptr ClassId, void *B) {
+ if (ClassId != BatchClassId)
+ B = allocate(BatchClassId);
+ if (UNLIKELY(!B))
+ reportOutOfMemory(SizeClassAllocator::getSizeByClassId(BatchClassId));
+ return reinterpret_cast<TransferBatch *>(B);
+ }
+
+ BatchGroup *createGroup() {
+ void *Ptr = allocate(BatchClassId);
+ if (UNLIKELY(!Ptr))
+ reportOutOfMemory(SizeClassAllocator::getSizeByClassId(BatchClassId));
+ return reinterpret_cast<BatchGroup *>(Ptr);
+ }
+
+ LocalStats &getStats() { return Stats; }
+
+private:
+ static const uptr NumClasses = SizeClassMap::NumClasses;
+ static const uptr BatchClassId = SizeClassMap::BatchClassId;
+ struct alignas(SCUDO_CACHE_LINE_SIZE) PerClass {
+ u16 Count;
+ u16 MaxCount;
+ // Note: ClassSize is zero for the transfer batch.
+ uptr ClassSize;
+ CompactPtrT Chunks[2 * TransferBatch::MaxNumCached];
+ };
+ PerClass PerClassArray[NumClasses] = {};
+ LocalStats Stats;
+ SizeClassAllocator *Allocator = nullptr;
+
+ ALWAYS_INLINE void initCacheMaybe(PerClass *C) {
+ if (LIKELY(C->MaxCount))
+ return;
+ initCache();
+ DCHECK_NE(C->MaxCount, 0U);
+ }
+
+ NOINLINE void initCache() {
+ for (uptr I = 0; I < NumClasses; I++) {
+ PerClass *P = &PerClassArray[I];
+ const uptr Size = SizeClassAllocator::getSizeByClassId(I);
+ P->MaxCount = static_cast<u16>(2 * TransferBatch::getMaxCached(Size));
+ if (I != BatchClassId) {
+ P->ClassSize = Size;
+ } else {
+ // ClassSize in this struct is only used for malloc/free stats, which
+ // should only track user allocations, not internal movements.
+ P->ClassSize = 0;
+ }
+ }
+ }
+
+ void destroyBatch(uptr ClassId, void *B) {
+ if (ClassId != BatchClassId)
+ deallocate(BatchClassId, B);
+ }
+
+ NOINLINE bool refill(PerClass *C, uptr ClassId) {
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+ return false;
+ DCHECK_GT(B->getCount(), 0);
+ C->Count = B->getCount();
+ B->copyToArray(C->Chunks);
+ B->clear();
+ destroyBatch(ClassId, B);
+ return true;
+ }
+
+ NOINLINE void drain(PerClass *C, uptr ClassId) {
+ const u16 Count = Min(static_cast<u16>(C->MaxCount / 2), C->Count);
+ Allocator->pushBlocks(this, ClassId, &C->Chunks[0], Count);
+ // u16 will be promoted to int by arithmetic type conversion.
+ C->Count = static_cast<u16>(C->Count - Count);
+ for (u16 I = 0; I < C->Count; I++)
+ C->Chunks[I] = C->Chunks[I + Count];
+ }
+};
+
+} // namespace scudo
+
+#endif // SCUDO_LOCAL_CACHE_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/memtag.h b/contrib/libs/clang16-rt/lib/scudo/standalone/memtag.h
new file mode 100644
index 00000000000..7f14a30fee1
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/memtag.h
@@ -0,0 +1,335 @@
+//===-- memtag.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_MEMTAG_H_
+#define SCUDO_MEMTAG_H_
+
+#include "internal_defs.h"
+
+#if SCUDO_LINUX
+#include <sys/auxv.h>
+#include <sys/prctl.h>
+#endif
+
+namespace scudo {
+
+#if (__clang_major__ >= 12 && defined(__aarch64__) && !defined(__ILP32__)) || \
+ defined(SCUDO_FUZZ)
+
+// We assume that Top-Byte Ignore is enabled if the architecture supports memory
+// tagging. Not all operating systems enable TBI, so we only claim architectural
+// support for memory tagging if the operating system enables TBI.
+// HWASan uses the top byte for its own purpose and Scudo should not touch it.
+#if SCUDO_LINUX && !defined(SCUDO_DISABLE_TBI) && \
+ !__has_feature(hwaddress_sanitizer)
+inline constexpr bool archSupportsMemoryTagging() { return true; }
+#else
+inline constexpr bool archSupportsMemoryTagging() { return false; }
+#endif
+
+inline constexpr uptr archMemoryTagGranuleSize() { return 16; }
+
+inline uptr untagPointer(uptr Ptr) { return Ptr & ((1ULL << 56) - 1); }
+
+inline uint8_t extractTag(uptr Ptr) { return (Ptr >> 56) & 0xf; }
+
+#else
+
+inline constexpr bool archSupportsMemoryTagging() { return false; }
+
+inline NORETURN uptr archMemoryTagGranuleSize() {
+ UNREACHABLE("memory tagging not supported");
+}
+
+inline NORETURN uptr untagPointer(uptr Ptr) {
+ (void)Ptr;
+ UNREACHABLE("memory tagging not supported");
+}
+
+inline NORETURN uint8_t extractTag(uptr Ptr) {
+ (void)Ptr;
+ UNREACHABLE("memory tagging not supported");
+}
+
+#endif
+
+#if __clang_major__ >= 12 && defined(__aarch64__) && !defined(__ILP32__)
+
+#if SCUDO_LINUX
+
+inline bool systemSupportsMemoryTagging() {
+#ifndef HWCAP2_MTE
+#define HWCAP2_MTE (1 << 18)
+#endif
+ return getauxval(AT_HWCAP2) & HWCAP2_MTE;
+}
+
+inline bool systemDetectsMemoryTagFaultsTestOnly() {
+#ifndef PR_SET_TAGGED_ADDR_CTRL
+#define PR_SET_TAGGED_ADDR_CTRL 54
+#endif
+#ifndef PR_GET_TAGGED_ADDR_CTRL
+#define PR_GET_TAGGED_ADDR_CTRL 56
+#endif
+#ifndef PR_TAGGED_ADDR_ENABLE
+#define PR_TAGGED_ADDR_ENABLE (1UL << 0)
+#endif
+#ifndef PR_MTE_TCF_SHIFT
+#define PR_MTE_TCF_SHIFT 1
+#endif
+#ifndef PR_MTE_TAG_SHIFT
+#define PR_MTE_TAG_SHIFT 3
+#endif
+#ifndef PR_MTE_TCF_NONE
+#define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
+#endif
+#ifndef PR_MTE_TCF_SYNC
+#define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
+#endif
+#ifndef PR_MTE_TCF_MASK
+#define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
+#endif
+ int res = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
+ if (res == -1)
+ return false;
+ return (static_cast<unsigned long>(res) & PR_MTE_TCF_MASK) != PR_MTE_TCF_NONE;
+}
+
+inline void enableSystemMemoryTaggingTestOnly() {
+ prctl(PR_SET_TAGGED_ADDR_CTRL,
+ PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | (0xfffe << PR_MTE_TAG_SHIFT),
+ 0, 0, 0);
+}
+
+#else // !SCUDO_LINUX
+
+inline bool systemSupportsMemoryTagging() { return false; }
+
+inline NORETURN bool systemDetectsMemoryTagFaultsTestOnly() {
+ UNREACHABLE("memory tagging not supported");
+}
+
+inline NORETURN void enableSystemMemoryTaggingTestOnly() {
+ UNREACHABLE("memory tagging not supported");
+}
+
+#endif // SCUDO_LINUX
+
+class ScopedDisableMemoryTagChecks {
+ uptr PrevTCO;
+
+public:
+ ScopedDisableMemoryTagChecks() {
+ __asm__ __volatile__(
+ R"(
+ .arch_extension memtag
+ mrs %0, tco
+ msr tco, #1
+ )"
+ : "=r"(PrevTCO));
+ }
+
+ ~ScopedDisableMemoryTagChecks() {
+ __asm__ __volatile__(
+ R"(
+ .arch_extension memtag
+ msr tco, %0
+ )"
+ :
+ : "r"(PrevTCO));
+ }
+};
+
+inline uptr selectRandomTag(uptr Ptr, uptr ExcludeMask) {
+ ExcludeMask |= 1; // Always exclude Tag 0.
+ uptr TaggedPtr;
+ __asm__ __volatile__(
+ R"(
+ .arch_extension memtag
+ irg %[TaggedPtr], %[Ptr], %[ExcludeMask]
+ )"
+ : [TaggedPtr] "=r"(TaggedPtr)
+ : [Ptr] "r"(Ptr), [ExcludeMask] "r"(ExcludeMask));
+ return TaggedPtr;
+}
+
+inline uptr addFixedTag(uptr Ptr, uptr Tag) {
+ DCHECK_LT(Tag, 16);
+ DCHECK_EQ(untagPointer(Ptr), Ptr);
+ return Ptr | (Tag << 56);
+}
+
+inline uptr storeTags(uptr Begin, uptr End) {
+ DCHECK_EQ(0, Begin % 16);
+ uptr LineSize, Next, Tmp;
+ __asm__ __volatile__(
+ R"(
+ .arch_extension memtag
+
+ // Compute the cache line size in bytes (DCZID_EL0 stores it as the log2
+ // of the number of 4-byte words) and bail out to the slow path if DCZID_EL0
+ // indicates that the DC instructions are unavailable.
+ DCZID .req %[Tmp]
+ mrs DCZID, dczid_el0
+ tbnz DCZID, #4, 3f
+ and DCZID, DCZID, #15
+ mov %[LineSize], #4
+ lsl %[LineSize], %[LineSize], DCZID
+ .unreq DCZID
+
+ // Our main loop doesn't handle the case where we don't need to perform any
+ // DC GZVA operations. If the size of our tagged region is less than
+ // twice the cache line size, bail out to the slow path since it's not
+ // guaranteed that we'll be able to do a DC GZVA.
+ Size .req %[Tmp]
+ sub Size, %[End], %[Cur]
+ cmp Size, %[LineSize], lsl #1
+ b.lt 3f
+ .unreq Size
+
+ LineMask .req %[Tmp]
+ sub LineMask, %[LineSize], #1
+
+ // STZG until the start of the next cache line.
+ orr %[Next], %[Cur], LineMask
+ 1:
+ stzg %[Cur], [%[Cur]], #16
+ cmp %[Cur], %[Next]
+ b.lt 1b
+
+ // DC GZVA cache lines until we have no more full cache lines.
+ bic %[Next], %[End], LineMask
+ .unreq LineMask
+ 2:
+ dc gzva, %[Cur]
+ add %[Cur], %[Cur], %[LineSize]
+ cmp %[Cur], %[Next]
+ b.lt 2b
+
+ // STZG until the end of the tagged region. This loop is also used to handle
+ // slow path cases.
+ 3:
+ cmp %[Cur], %[End]
+ b.ge 4f
+ stzg %[Cur], [%[Cur]], #16
+ b 3b
+
+ 4:
+ )"
+ : [Cur] "+&r"(Begin), [LineSize] "=&r"(LineSize), [Next] "=&r"(Next),
+ [Tmp] "=&r"(Tmp)
+ : [End] "r"(End)
+ : "memory");
+ DCHECK_EQ(0, Begin % 16);
+ return Begin;
+}
+
+inline void storeTag(uptr Ptr) {
+ DCHECK_EQ(0, Ptr % 16);
+ __asm__ __volatile__(R"(
+ .arch_extension memtag
+ stg %0, [%0]
+ )"
+ :
+ : "r"(Ptr)
+ : "memory");
+}
+
+inline uptr loadTag(uptr Ptr) {
+ DCHECK_EQ(0, Ptr % 16);
+ uptr TaggedPtr = Ptr;
+ __asm__ __volatile__(
+ R"(
+ .arch_extension memtag
+ ldg %0, [%0]
+ )"
+ : "+r"(TaggedPtr)
+ :
+ : "memory");
+ return TaggedPtr;
+}
+
+#else
+
+inline NORETURN bool systemSupportsMemoryTagging() {
+ UNREACHABLE("memory tagging not supported");
+}
+
+inline NORETURN bool systemDetectsMemoryTagFaultsTestOnly() {
+ UNREACHABLE("memory tagging not supported");
+}
+
+inline NORETURN void enableSystemMemoryTaggingTestOnly() {
+ UNREACHABLE("memory tagging not supported");
+}
+
+struct ScopedDisableMemoryTagChecks {
+ ScopedDisableMemoryTagChecks() {}
+};
+
+inline NORETURN uptr selectRandomTag(uptr Ptr, uptr ExcludeMask) {
+ (void)Ptr;
+ (void)ExcludeMask;
+ UNREACHABLE("memory tagging not supported");
+}
+
+inline NORETURN uptr addFixedTag(uptr Ptr, uptr Tag) {
+ (void)Ptr;
+ (void)Tag;
+ UNREACHABLE("memory tagging not supported");
+}
+
+inline NORETURN uptr storeTags(uptr Begin, uptr End) {
+ (void)Begin;
+ (void)End;
+ UNREACHABLE("memory tagging not supported");
+}
+
+inline NORETURN void storeTag(uptr Ptr) {
+ (void)Ptr;
+ UNREACHABLE("memory tagging not supported");
+}
+
+inline NORETURN uptr loadTag(uptr Ptr) {
+ (void)Ptr;
+ UNREACHABLE("memory tagging not supported");
+}
+
+#endif
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-noreturn"
+inline void setRandomTag(void *Ptr, uptr Size, uptr ExcludeMask,
+ uptr *TaggedBegin, uptr *TaggedEnd) {
+ *TaggedBegin = selectRandomTag(reinterpret_cast<uptr>(Ptr), ExcludeMask);
+ *TaggedEnd = storeTags(*TaggedBegin, *TaggedBegin + Size);
+}
+#pragma GCC diagnostic pop
+
+inline void *untagPointer(void *Ptr) {
+ return reinterpret_cast<void *>(untagPointer(reinterpret_cast<uptr>(Ptr)));
+}
+
+inline void *loadTag(void *Ptr) {
+ return reinterpret_cast<void *>(loadTag(reinterpret_cast<uptr>(Ptr)));
+}
+
+inline void *addFixedTag(void *Ptr, uptr Tag) {
+ return reinterpret_cast<void *>(
+ addFixedTag(reinterpret_cast<uptr>(Ptr), Tag));
+}
+
+template <typename Config>
+inline constexpr bool allocatorSupportsMemoryTagging() {
+ return archSupportsMemoryTagging() && Config::MaySupportMemoryTagging &&
+ (1 << SCUDO_MIN_ALIGNMENT_LOG) >= archMemoryTagGranuleSize();
+}
+
+} // namespace scudo
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/mutex.h b/contrib/libs/clang16-rt/lib/scudo/standalone/mutex.h
new file mode 100644
index 00000000000..b66733244c6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/mutex.h
@@ -0,0 +1,72 @@
+//===-- mutex.h -------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_MUTEX_H_
+#define SCUDO_MUTEX_H_
+
+#include "atomic_helpers.h"
+#include "common.h"
+
+#include <string.h>
+
+#if SCUDO_FUCHSIA
+#error #include <lib/sync/mutex.h> // for sync_mutex_t
+#endif
+
+namespace scudo {
+
+class HybridMutex {
+public:
+ bool tryLock();
+ NOINLINE void lock() {
+ if (LIKELY(tryLock()))
+ return;
+ // The compiler may try to fully unroll the loop, ending up in a
+ // NumberOfTries*NumberOfYields block of pauses mixed with tryLocks. This
+ // is large, ugly and unneeded, a compact loop is better for our purpose
+ // here. Use a pragma to tell the compiler not to unroll the loop.
+#ifdef __clang__
+#pragma nounroll
+#endif
+ for (u8 I = 0U; I < NumberOfTries; I++) {
+ yieldProcessor(NumberOfYields);
+ if (tryLock())
+ return;
+ }
+ lockSlow();
+ }
+ void unlock();
+
+private:
+ static constexpr u8 NumberOfTries = 8U;
+ static constexpr u8 NumberOfYields = 8U;
+
+#if SCUDO_LINUX
+ atomic_u32 M = {};
+#elif SCUDO_FUCHSIA
+ sync_mutex_t M = {};
+#endif
+
+ void lockSlow();
+};
+
+class ScopedLock {
+public:
+ explicit ScopedLock(HybridMutex &M) : Mutex(M) { Mutex.lock(); }
+ ~ScopedLock() { Mutex.unlock(); }
+
+private:
+ HybridMutex &Mutex;
+
+ ScopedLock(const ScopedLock &) = delete;
+ void operator=(const ScopedLock &) = delete;
+};
+
+} // namespace scudo
+
+#endif // SCUDO_MUTEX_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/options.h b/contrib/libs/clang16-rt/lib/scudo/standalone/options.h
new file mode 100644
index 00000000000..4e678651333
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/options.h
@@ -0,0 +1,74 @@
+//===-- options.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_OPTIONS_H_
+#define SCUDO_OPTIONS_H_
+
+#include "atomic_helpers.h"
+#include "common.h"
+#include "memtag.h"
+
+namespace scudo {
+
+enum class OptionBit {
+ MayReturnNull,
+ FillContents0of2,
+ FillContents1of2,
+ DeallocTypeMismatch,
+ DeleteSizeMismatch,
+ TrackAllocationStacks,
+ UseOddEvenTags,
+ UseMemoryTagging,
+ AddLargeAllocationSlack,
+};
+
+struct Options {
+ u32 Val;
+
+ bool get(OptionBit Opt) const { return Val & (1U << static_cast<u32>(Opt)); }
+
+ FillContentsMode getFillContentsMode() const {
+ return static_cast<FillContentsMode>(
+ (Val >> static_cast<u32>(OptionBit::FillContents0of2)) & 3);
+ }
+};
+
+template <typename Config> bool useMemoryTagging(Options Options) {
+ return allocatorSupportsMemoryTagging<Config>() &&
+ Options.get(OptionBit::UseMemoryTagging);
+}
+
+struct AtomicOptions {
+ atomic_u32 Val = {};
+
+ Options load() const { return Options{atomic_load_relaxed(&Val)}; }
+
+ void clear(OptionBit Opt) {
+ atomic_fetch_and(&Val, ~(1U << static_cast<u32>(Opt)),
+ memory_order_relaxed);
+ }
+
+ void set(OptionBit Opt) {
+ atomic_fetch_or(&Val, 1U << static_cast<u32>(Opt), memory_order_relaxed);
+ }
+
+ void setFillContentsMode(FillContentsMode FillContents) {
+ u32 Opts = atomic_load_relaxed(&Val), NewOpts;
+ do {
+ NewOpts = Opts;
+ NewOpts &= ~(3U << static_cast<u32>(OptionBit::FillContents0of2));
+ NewOpts |= static_cast<u32>(FillContents)
+ << static_cast<u32>(OptionBit::FillContents0of2);
+ } while (!atomic_compare_exchange_strong(&Val, &Opts, NewOpts,
+ memory_order_relaxed));
+ }
+};
+
+} // namespace scudo
+
+#endif // SCUDO_OPTIONS_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/platform.h b/contrib/libs/clang16-rt/lib/scudo/standalone/platform.h
new file mode 100644
index 00000000000..db4217ddab9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/platform.h
@@ -0,0 +1,80 @@
+//===-- platform.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_PLATFORM_H_
+#define SCUDO_PLATFORM_H_
+
+// Transitive includes of stdint.h specify some of the defines checked below.
+#include <stdint.h>
+
+#if defined(__linux__) && !defined(__TRUSTY__)
+#define SCUDO_LINUX 1
+#else
+#define SCUDO_LINUX 0
+#endif
+
+// See https://android.googlesource.com/platform/bionic/+/master/docs/defines.md
+#if defined(__BIONIC__)
+#define SCUDO_ANDROID 1
+#else
+#define SCUDO_ANDROID 0
+#endif
+
+#if defined(__Fuchsia__)
+#define SCUDO_FUCHSIA 1
+#else
+#define SCUDO_FUCHSIA 0
+#endif
+
+#if defined(__TRUSTY__)
+#define SCUDO_TRUSTY 1
+#else
+#define SCUDO_TRUSTY 0
+#endif
+
+#if defined(__LP64__)
+#define SCUDO_WORDSIZE 64U
+#else
+#define SCUDO_WORDSIZE 32U
+#endif
+
+#if SCUDO_WORDSIZE == 64U
+#define FIRST_32_SECOND_64(a, b) (b)
+#else
+#define FIRST_32_SECOND_64(a, b) (a)
+#endif
+
+#ifndef SCUDO_CAN_USE_PRIMARY64
+#define SCUDO_CAN_USE_PRIMARY64 (SCUDO_WORDSIZE == 64U)
+#endif
+
+#ifndef SCUDO_MIN_ALIGNMENT_LOG
+// We force malloc-type functions to be aligned to std::max_align_t, but there
+// is no reason why the minimum alignment for all other functions can't be 8
+// bytes. Except obviously for applications making incorrect assumptions.
+// TODO(kostyak): define SCUDO_MIN_ALIGNMENT_LOG 3
+#define SCUDO_MIN_ALIGNMENT_LOG FIRST_32_SECOND_64(3, 4)
+#endif
+
+#if defined(__aarch64__)
+#define SCUDO_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 48)
+#else
+#define SCUDO_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
+#endif
+
+// Older gcc have issues aligning to a constexpr, and require an integer.
+// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56859 among others.
+#if defined(__powerpc__) || defined(__powerpc64__)
+#define SCUDO_CACHE_LINE_SIZE 128
+#else
+#define SCUDO_CACHE_LINE_SIZE 64
+#endif
+
+#define SCUDO_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 12)
+
+#endif // SCUDO_PLATFORM_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/primary32.h b/contrib/libs/clang16-rt/lib/scudo/standalone/primary32.h
new file mode 100644
index 00000000000..a3d908cee9e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/primary32.h
@@ -0,0 +1,764 @@
+//===-- primary32.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_PRIMARY32_H_
+#define SCUDO_PRIMARY32_H_
+
+#include "bytemap.h"
+#include "common.h"
+#include "list.h"
+#include "local_cache.h"
+#include "options.h"
+#include "release.h"
+#include "report.h"
+#include "stats.h"
+#include "string_utils.h"
+
+namespace scudo {
+
+// SizeClassAllocator32 is an allocator for 32 or 64-bit address space.
+//
+// It maps Regions of 2^RegionSizeLog bytes aligned on a 2^RegionSizeLog bytes
+// boundary, and keeps a bytemap of the mappable address space to track the size
+// class they are associated with.
+//
+// Mapped regions are split into equally sized Blocks according to the size
+// class they belong to, and the associated pointers are shuffled to prevent any
+// predictable address pattern (the predictability increases with the block
+// size).
+//
+// Regions for size class 0 are special and used to hold TransferBatches, which
+// allow to transfer arrays of pointers from the global size class freelist to
+// the thread specific freelist for said class, and back.
+//
+// Memory used by this allocator is never unmapped but can be partially
+// reclaimed if the platform allows for it.
+
+template <typename Config> class SizeClassAllocator32 {
+public:
+ typedef typename Config::PrimaryCompactPtrT CompactPtrT;
+ typedef typename Config::SizeClassMap SizeClassMap;
+ static const uptr GroupSizeLog = Config::PrimaryGroupSizeLog;
+ // The bytemap can only track UINT8_MAX - 1 classes.
+ static_assert(SizeClassMap::LargestClassId <= (UINT8_MAX - 1), "");
+ // Regions should be large enough to hold the largest Block.
+ static_assert((1UL << Config::PrimaryRegionSizeLog) >= SizeClassMap::MaxSize,
+ "");
+ typedef SizeClassAllocator32<Config> ThisT;
+ typedef SizeClassAllocatorLocalCache<ThisT> CacheT;
+ typedef typename CacheT::TransferBatch TransferBatch;
+ typedef typename CacheT::BatchGroup BatchGroup;
+
+ static uptr getSizeByClassId(uptr ClassId) {
+ return (ClassId == SizeClassMap::BatchClassId)
+ ? sizeof(TransferBatch)
+ : SizeClassMap::getSizeByClassId(ClassId);
+ }
+
+ static bool canAllocate(uptr Size) { return Size <= SizeClassMap::MaxSize; }
+
+ void init(s32 ReleaseToOsInterval) {
+ if (SCUDO_FUCHSIA)
+ reportError("SizeClassAllocator32 is not supported on Fuchsia");
+
+ if (SCUDO_TRUSTY)
+ reportError("SizeClassAllocator32 is not supported on Trusty");
+
+ DCHECK(isAligned(reinterpret_cast<uptr>(this), alignof(ThisT)));
+ PossibleRegions.init();
+ u32 Seed;
+ const u64 Time = getMonotonicTime();
+ if (!getRandom(reinterpret_cast<void *>(&Seed), sizeof(Seed)))
+ Seed = static_cast<u32>(
+ Time ^ (reinterpret_cast<uptr>(SizeClassInfoArray) >> 6));
+ for (uptr I = 0; I < NumClasses; I++) {
+ SizeClassInfo *Sci = getSizeClassInfo(I);
+ Sci->RandState = getRandomU32(&Seed);
+ // Sci->MaxRegionIndex is already initialized to 0.
+ Sci->MinRegionIndex = NumRegions;
+ Sci->ReleaseInfo.LastReleaseAtNs = Time;
+ }
+ setOption(Option::ReleaseInterval, static_cast<sptr>(ReleaseToOsInterval));
+ }
+
+ void unmapTestOnly() {
+ while (NumberOfStashedRegions > 0)
+ unmap(reinterpret_cast<void *>(RegionsStash[--NumberOfStashedRegions]),
+ RegionSize);
+ uptr MinRegionIndex = NumRegions, MaxRegionIndex = 0;
+ for (uptr I = 0; I < NumClasses; I++) {
+ SizeClassInfo *Sci = getSizeClassInfo(I);
+ if (Sci->MinRegionIndex < MinRegionIndex)
+ MinRegionIndex = Sci->MinRegionIndex;
+ if (Sci->MaxRegionIndex > MaxRegionIndex)
+ MaxRegionIndex = Sci->MaxRegionIndex;
+ *Sci = {};
+ }
+ for (uptr I = MinRegionIndex; I < MaxRegionIndex; I++)
+ if (PossibleRegions[I])
+ unmap(reinterpret_cast<void *>(I * RegionSize), RegionSize);
+ PossibleRegions.unmapTestOnly();
+ }
+
+ CompactPtrT compactPtr(UNUSED uptr ClassId, uptr Ptr) const {
+ return static_cast<CompactPtrT>(Ptr);
+ }
+
+ void *decompactPtr(UNUSED uptr ClassId, CompactPtrT CompactPtr) const {
+ return reinterpret_cast<void *>(static_cast<uptr>(CompactPtr));
+ }
+
+ uptr compactPtrGroup(CompactPtrT CompactPtr) {
+ return CompactPtr >> GroupSizeLog;
+ }
+
+ TransferBatch *popBatch(CacheT *C, uptr ClassId) {
+ DCHECK_LT(ClassId, NumClasses);
+ SizeClassInfo *Sci = getSizeClassInfo(ClassId);
+ ScopedLock L(Sci->Mutex);
+ TransferBatch *B = popBatchImpl(C, ClassId);
+ if (UNLIKELY(!B)) {
+ if (UNLIKELY(!populateFreeList(C, ClassId, Sci)))
+ return nullptr;
+ B = popBatchImpl(C, ClassId);
+ // if `populateFreeList` succeeded, we are supposed to get free blocks.
+ DCHECK_NE(B, nullptr);
+ }
+ Sci->Stats.PoppedBlocks += B->getCount();
+ return B;
+ }
+
+ // Push the array of free blocks to the designated batch group.
+ void pushBlocks(CacheT *C, uptr ClassId, CompactPtrT *Array, u32 Size) {
+ DCHECK_LT(ClassId, NumClasses);
+ DCHECK_GT(Size, 0);
+
+ SizeClassInfo *Sci = getSizeClassInfo(ClassId);
+ if (ClassId == SizeClassMap::BatchClassId) {
+ ScopedLock L(Sci->Mutex);
+ // Constructing a batch group in the free list will use two blocks in
+ // BatchClassId. If we are pushing BatchClassId blocks, we will use the
+ // blocks in the array directly (can't delegate local cache which will
+ // cause a recursive allocation). However, The number of free blocks may
+ // be less than two. Therefore, populate the free list before inserting
+ // the blocks.
+ if (Size == 1 && !populateFreeList(C, ClassId, Sci))
+ return;
+ pushBlocksImpl(C, ClassId, Array, Size);
+ Sci->Stats.PushedBlocks += Size;
+ return;
+ }
+
+ // TODO(chiahungduan): Consider not doing grouping if the group size is not
+ // greater than the block size with a certain scale.
+
+ // Sort the blocks so that blocks belonging to the same group can be pushed
+ // together.
+ bool SameGroup = true;
+ for (u32 I = 1; I < Size; ++I) {
+ if (compactPtrGroup(Array[I - 1]) != compactPtrGroup(Array[I]))
+ SameGroup = false;
+ CompactPtrT Cur = Array[I];
+ u32 J = I;
+ while (J > 0 && compactPtrGroup(Cur) < compactPtrGroup(Array[J - 1])) {
+ Array[J] = Array[J - 1];
+ --J;
+ }
+ Array[J] = Cur;
+ }
+
+ ScopedLock L(Sci->Mutex);
+ pushBlocksImpl(C, ClassId, Array, Size, SameGroup);
+
+ Sci->Stats.PushedBlocks += Size;
+ if (ClassId != SizeClassMap::BatchClassId)
+ releaseToOSMaybe(Sci, ClassId);
+ }
+
+ void disable() {
+ // The BatchClassId must be locked last since other classes can use it.
+ for (sptr I = static_cast<sptr>(NumClasses) - 1; I >= 0; I--) {
+ if (static_cast<uptr>(I) == SizeClassMap::BatchClassId)
+ continue;
+ getSizeClassInfo(static_cast<uptr>(I))->Mutex.lock();
+ }
+ getSizeClassInfo(SizeClassMap::BatchClassId)->Mutex.lock();
+ RegionsStashMutex.lock();
+ PossibleRegions.disable();
+ }
+
+ void enable() {
+ PossibleRegions.enable();
+ RegionsStashMutex.unlock();
+ getSizeClassInfo(SizeClassMap::BatchClassId)->Mutex.unlock();
+ for (uptr I = 0; I < NumClasses; I++) {
+ if (I == SizeClassMap::BatchClassId)
+ continue;
+ getSizeClassInfo(I)->Mutex.unlock();
+ }
+ }
+
+ template <typename F> void iterateOverBlocks(F Callback) {
+ uptr MinRegionIndex = NumRegions, MaxRegionIndex = 0;
+ for (uptr I = 0; I < NumClasses; I++) {
+ SizeClassInfo *Sci = getSizeClassInfo(I);
+ if (Sci->MinRegionIndex < MinRegionIndex)
+ MinRegionIndex = Sci->MinRegionIndex;
+ if (Sci->MaxRegionIndex > MaxRegionIndex)
+ MaxRegionIndex = Sci->MaxRegionIndex;
+ }
+ for (uptr I = MinRegionIndex; I <= MaxRegionIndex; I++)
+ if (PossibleRegions[I] &&
+ (PossibleRegions[I] - 1U) != SizeClassMap::BatchClassId) {
+ const uptr BlockSize = getSizeByClassId(PossibleRegions[I] - 1U);
+ const uptr From = I * RegionSize;
+ const uptr To = From + (RegionSize / BlockSize) * BlockSize;
+ for (uptr Block = From; Block < To; Block += BlockSize)
+ Callback(Block);
+ }
+ }
+
+ void getStats(ScopedString *Str) {
+ // TODO(kostyak): get the RSS per region.
+ uptr TotalMapped = 0;
+ uptr PoppedBlocks = 0;
+ uptr PushedBlocks = 0;
+ for (uptr I = 0; I < NumClasses; I++) {
+ SizeClassInfo *Sci = getSizeClassInfo(I);
+ TotalMapped += Sci->AllocatedUser;
+ PoppedBlocks += Sci->Stats.PoppedBlocks;
+ PushedBlocks += Sci->Stats.PushedBlocks;
+ }
+ Str->append("Stats: SizeClassAllocator32: %zuM mapped in %zu allocations; "
+ "remains %zu\n",
+ TotalMapped >> 20, PoppedBlocks, PoppedBlocks - PushedBlocks);
+ for (uptr I = 0; I < NumClasses; I++)
+ getStats(Str, I, 0);
+ }
+
+ bool setOption(Option O, sptr Value) {
+ if (O == Option::ReleaseInterval) {
+ const s32 Interval = Max(
+ Min(static_cast<s32>(Value), Config::PrimaryMaxReleaseToOsIntervalMs),
+ Config::PrimaryMinReleaseToOsIntervalMs);
+ atomic_store_relaxed(&ReleaseToOsIntervalMs, Interval);
+ return true;
+ }
+ // Not supported by the Primary, but not an error either.
+ return true;
+ }
+
+ uptr releaseToOS() {
+ uptr TotalReleasedBytes = 0;
+ for (uptr I = 0; I < NumClasses; I++) {
+ if (I == SizeClassMap::BatchClassId)
+ continue;
+ SizeClassInfo *Sci = getSizeClassInfo(I);
+ ScopedLock L(Sci->Mutex);
+ TotalReleasedBytes += releaseToOSMaybe(Sci, I, /*Force=*/true);
+ }
+ return TotalReleasedBytes;
+ }
+
+ const char *getRegionInfoArrayAddress() const { return nullptr; }
+ static uptr getRegionInfoArraySize() { return 0; }
+
+ static BlockInfo findNearestBlock(UNUSED const char *RegionInfoData,
+ UNUSED uptr Ptr) {
+ return {};
+ }
+
+ AtomicOptions Options;
+
+private:
+ static const uptr NumClasses = SizeClassMap::NumClasses;
+ static const uptr RegionSize = 1UL << Config::PrimaryRegionSizeLog;
+ static const uptr NumRegions =
+ SCUDO_MMAP_RANGE_SIZE >> Config::PrimaryRegionSizeLog;
+ static const u32 MaxNumBatches = SCUDO_ANDROID ? 4U : 8U;
+ typedef FlatByteMap<NumRegions> ByteMap;
+
+ struct SizeClassStats {
+ uptr PoppedBlocks;
+ uptr PushedBlocks;
+ };
+
+ struct ReleaseToOsInfo {
+ uptr PushedBlocksAtLastRelease;
+ uptr RangesReleased;
+ uptr LastReleasedBytes;
+ u64 LastReleaseAtNs;
+ };
+
+ struct alignas(SCUDO_CACHE_LINE_SIZE) SizeClassInfo {
+ HybridMutex Mutex;
+ SinglyLinkedList<BatchGroup> FreeList;
+ uptr CurrentRegion;
+ uptr CurrentRegionAllocated;
+ SizeClassStats Stats;
+ u32 RandState;
+ uptr AllocatedUser;
+ // Lowest & highest region index allocated for this size class, to avoid
+ // looping through the whole NumRegions.
+ uptr MinRegionIndex;
+ uptr MaxRegionIndex;
+ ReleaseToOsInfo ReleaseInfo;
+ };
+ static_assert(sizeof(SizeClassInfo) % SCUDO_CACHE_LINE_SIZE == 0, "");
+
+ uptr computeRegionId(uptr Mem) {
+ const uptr Id = Mem >> Config::PrimaryRegionSizeLog;
+ CHECK_LT(Id, NumRegions);
+ return Id;
+ }
+
+ uptr allocateRegionSlow() {
+ uptr MapSize = 2 * RegionSize;
+ const uptr MapBase = reinterpret_cast<uptr>(
+ map(nullptr, MapSize, "scudo:primary", MAP_ALLOWNOMEM));
+ if (!MapBase)
+ return 0;
+ const uptr MapEnd = MapBase + MapSize;
+ uptr Region = MapBase;
+ if (isAligned(Region, RegionSize)) {
+ ScopedLock L(RegionsStashMutex);
+ if (NumberOfStashedRegions < MaxStashedRegions)
+ RegionsStash[NumberOfStashedRegions++] = MapBase + RegionSize;
+ else
+ MapSize = RegionSize;
+ } else {
+ Region = roundUpTo(MapBase, RegionSize);
+ unmap(reinterpret_cast<void *>(MapBase), Region - MapBase);
+ MapSize = RegionSize;
+ }
+ const uptr End = Region + MapSize;
+ if (End != MapEnd)
+ unmap(reinterpret_cast<void *>(End), MapEnd - End);
+ return Region;
+ }
+
+ uptr allocateRegion(SizeClassInfo *Sci, uptr ClassId) {
+ DCHECK_LT(ClassId, NumClasses);
+ uptr Region = 0;
+ {
+ ScopedLock L(RegionsStashMutex);
+ if (NumberOfStashedRegions > 0)
+ Region = RegionsStash[--NumberOfStashedRegions];
+ }
+ if (!Region)
+ Region = allocateRegionSlow();
+ if (LIKELY(Region)) {
+ // Sci->Mutex is held by the caller, updating the Min/Max is safe.
+ const uptr RegionIndex = computeRegionId(Region);
+ if (RegionIndex < Sci->MinRegionIndex)
+ Sci->MinRegionIndex = RegionIndex;
+ if (RegionIndex > Sci->MaxRegionIndex)
+ Sci->MaxRegionIndex = RegionIndex;
+ PossibleRegions.set(RegionIndex, static_cast<u8>(ClassId + 1U));
+ }
+ return Region;
+ }
+
+ SizeClassInfo *getSizeClassInfo(uptr ClassId) {
+ DCHECK_LT(ClassId, NumClasses);
+ return &SizeClassInfoArray[ClassId];
+ }
+
+ // Push the blocks to their batch group. The layout will be like,
+ //
+ // FreeList - > BG -> BG -> BG
+ // | | |
+ // v v v
+ // TB TB TB
+ // |
+ // v
+ // TB
+ //
+ // Each BlockGroup(BG) will associate with unique group id and the free blocks
+ // are managed by a list of TransferBatch(TB). To reduce the time of inserting
+ // blocks, BGs are sorted and the input `Array` are supposed to be sorted so
+ // that we can get better performance of maintaining sorted property.
+ // Use `SameGroup=true` to indicate that all blocks in the array are from the
+ // same group then we will skip checking the group id of each block.
+ //
+ // Note that this aims to have a better management of dirty pages, i.e., the
+ // RSS usage won't grow indefinitely. There's an exception that we may not put
+ // a block to its associated group. While populating new blocks, we may have
+ // blocks cross different groups. However, most cases will fall into same
+ // group and they are supposed to be popped soon. In that case, it's not worth
+ // sorting the array with the almost-sorted property. Therefore, we use
+ // `SameGroup=true` instead.
+ //
+ // The region mutex needs to be held while calling this method.
+ void pushBlocksImpl(CacheT *C, uptr ClassId, CompactPtrT *Array, u32 Size,
+ bool SameGroup = false) {
+ DCHECK_GT(Size, 0U);
+ SizeClassInfo *Sci = getSizeClassInfo(ClassId);
+
+ auto CreateGroup = [&](uptr GroupId) {
+ BatchGroup *BG = nullptr;
+ TransferBatch *TB = nullptr;
+ if (ClassId == SizeClassMap::BatchClassId) {
+ DCHECK_GE(Size, 2U);
+ BG = reinterpret_cast<BatchGroup *>(
+ decompactPtr(ClassId, Array[Size - 1]));
+ BG->Batches.clear();
+
+ TB = reinterpret_cast<TransferBatch *>(
+ decompactPtr(ClassId, Array[Size - 2]));
+ TB->clear();
+ } else {
+ BG = C->createGroup();
+ BG->Batches.clear();
+
+ TB = C->createBatch(ClassId, nullptr);
+ TB->clear();
+ }
+
+ BG->GroupId = GroupId;
+ BG->Batches.push_front(TB);
+ BG->PushedBlocks = 0;
+ BG->PushedBlocksAtLastCheckpoint = 0;
+ BG->MaxCachedPerBatch =
+ TransferBatch::getMaxCached(getSizeByClassId(ClassId));
+
+ return BG;
+ };
+
+ auto InsertBlocks = [&](BatchGroup *BG, CompactPtrT *Array, u32 Size) {
+ SinglyLinkedList<TransferBatch> &Batches = BG->Batches;
+ TransferBatch *CurBatch = Batches.front();
+ DCHECK_NE(CurBatch, nullptr);
+
+ for (u32 I = 0; I < Size;) {
+ DCHECK_GE(BG->MaxCachedPerBatch, CurBatch->getCount());
+ u16 UnusedSlots =
+ static_cast<u16>(BG->MaxCachedPerBatch - CurBatch->getCount());
+ if (UnusedSlots == 0) {
+ CurBatch = C->createBatch(
+ ClassId,
+ reinterpret_cast<void *>(decompactPtr(ClassId, Array[I])));
+ CurBatch->clear();
+ Batches.push_front(CurBatch);
+ UnusedSlots = BG->MaxCachedPerBatch;
+ }
+ // `UnusedSlots` is u16 so the result will be also fit in u16.
+ u16 AppendSize = static_cast<u16>(Min<u32>(UnusedSlots, Size - I));
+ CurBatch->appendFromArray(&Array[I], AppendSize);
+ I += AppendSize;
+ }
+
+ BG->PushedBlocks += Size;
+ };
+
+ BatchGroup *Cur = Sci->FreeList.front();
+
+ if (ClassId == SizeClassMap::BatchClassId) {
+ if (Cur == nullptr) {
+ // Don't need to classify BatchClassId.
+ Cur = CreateGroup(/*GroupId=*/0);
+ Sci->FreeList.push_front(Cur);
+ }
+ InsertBlocks(Cur, Array, Size);
+ return;
+ }
+
+ // In the following, `Cur` always points to the BatchGroup for blocks that
+ // will be pushed next. `Prev` is the element right before `Cur`.
+ BatchGroup *Prev = nullptr;
+
+ while (Cur != nullptr && compactPtrGroup(Array[0]) > Cur->GroupId) {
+ Prev = Cur;
+ Cur = Cur->Next;
+ }
+
+ if (Cur == nullptr || compactPtrGroup(Array[0]) != Cur->GroupId) {
+ Cur = CreateGroup(compactPtrGroup(Array[0]));
+ if (Prev == nullptr)
+ Sci->FreeList.push_front(Cur);
+ else
+ Sci->FreeList.insert(Prev, Cur);
+ }
+
+ // All the blocks are from the same group, just push without checking group
+ // id.
+ if (SameGroup) {
+ InsertBlocks(Cur, Array, Size);
+ return;
+ }
+
+ // The blocks are sorted by group id. Determine the segment of group and
+ // push them to their group together.
+ u32 Count = 1;
+ for (u32 I = 1; I < Size; ++I) {
+ if (compactPtrGroup(Array[I - 1]) != compactPtrGroup(Array[I])) {
+ DCHECK_EQ(compactPtrGroup(Array[I - 1]), Cur->GroupId);
+ InsertBlocks(Cur, Array + I - Count, Count);
+
+ while (Cur != nullptr && compactPtrGroup(Array[I]) > Cur->GroupId) {
+ Prev = Cur;
+ Cur = Cur->Next;
+ }
+
+ if (Cur == nullptr || compactPtrGroup(Array[I]) != Cur->GroupId) {
+ Cur = CreateGroup(compactPtrGroup(Array[I]));
+ DCHECK_NE(Prev, nullptr);
+ Sci->FreeList.insert(Prev, Cur);
+ }
+
+ Count = 1;
+ } else {
+ ++Count;
+ }
+ }
+
+ InsertBlocks(Cur, Array + Size - Count, Count);
+ }
+
+ // Pop one TransferBatch from a BatchGroup. The BatchGroup with the smallest
+ // group id will be considered first.
+ //
+ // The region mutex needs to be held while calling this method.
+ TransferBatch *popBatchImpl(CacheT *C, uptr ClassId) {
+ SizeClassInfo *Sci = getSizeClassInfo(ClassId);
+ if (Sci->FreeList.empty())
+ return nullptr;
+
+ SinglyLinkedList<TransferBatch> &Batches = Sci->FreeList.front()->Batches;
+ DCHECK(!Batches.empty());
+
+ TransferBatch *B = Batches.front();
+ Batches.pop_front();
+ DCHECK_NE(B, nullptr);
+ DCHECK_GT(B->getCount(), 0U);
+
+ if (Batches.empty()) {
+ BatchGroup *BG = Sci->FreeList.front();
+ Sci->FreeList.pop_front();
+
+ // We don't keep BatchGroup with zero blocks to avoid empty-checking while
+ // allocating. Note that block used by constructing BatchGroup is recorded
+ // as free blocks in the last element of BatchGroup::Batches. Which means,
+ // once we pop the last TransferBatch, the block is implicitly
+ // deallocated.
+ if (ClassId != SizeClassMap::BatchClassId)
+ C->deallocate(SizeClassMap::BatchClassId, BG);
+ }
+
+ return B;
+ }
+
+ NOINLINE bool populateFreeList(CacheT *C, uptr ClassId, SizeClassInfo *Sci) {
+ uptr Region;
+ uptr Offset;
+ // If the size-class currently has a region associated to it, use it. The
+ // newly created blocks will be located after the currently allocated memory
+ // for that region (up to RegionSize). Otherwise, create a new region, where
+ // the new blocks will be carved from the beginning.
+ if (Sci->CurrentRegion) {
+ Region = Sci->CurrentRegion;
+ DCHECK_GT(Sci->CurrentRegionAllocated, 0U);
+ Offset = Sci->CurrentRegionAllocated;
+ } else {
+ DCHECK_EQ(Sci->CurrentRegionAllocated, 0U);
+ Region = allocateRegion(Sci, ClassId);
+ if (UNLIKELY(!Region))
+ return false;
+ C->getStats().add(StatMapped, RegionSize);
+ Sci->CurrentRegion = Region;
+ Offset = 0;
+ }
+
+ const uptr Size = getSizeByClassId(ClassId);
+ const u16 MaxCount = TransferBatch::getMaxCached(Size);
+ DCHECK_GT(MaxCount, 0U);
+ // The maximum number of blocks we should carve in the region is dictated
+ // by the maximum number of batches we want to fill, and the amount of
+ // memory left in the current region (we use the lowest of the two). This
+ // will not be 0 as we ensure that a region can at least hold one block (via
+ // static_assert and at the end of this function).
+ const u32 NumberOfBlocks =
+ Min(MaxNumBatches * MaxCount,
+ static_cast<u32>((RegionSize - Offset) / Size));
+ DCHECK_GT(NumberOfBlocks, 0U);
+
+ constexpr u32 ShuffleArraySize =
+ MaxNumBatches * TransferBatch::MaxNumCached;
+ // Fill the transfer batches and put them in the size-class freelist. We
+ // need to randomize the blocks for security purposes, so we first fill a
+ // local array that we then shuffle before populating the batches.
+ CompactPtrT ShuffleArray[ShuffleArraySize];
+ DCHECK_LE(NumberOfBlocks, ShuffleArraySize);
+
+ uptr P = Region + Offset;
+ for (u32 I = 0; I < NumberOfBlocks; I++, P += Size)
+ ShuffleArray[I] = reinterpret_cast<CompactPtrT>(P);
+ // No need to shuffle the batches size class.
+ if (ClassId != SizeClassMap::BatchClassId)
+ shuffle(ShuffleArray, NumberOfBlocks, &Sci->RandState);
+ for (u32 I = 0; I < NumberOfBlocks;) {
+ // `MaxCount` is u16 so the result will also fit in u16.
+ const u16 N = static_cast<u16>(Min<u32>(MaxCount, NumberOfBlocks - I));
+ // Note that the N blocks here may have different group ids. Given that
+ // it only happens when it crosses the group size boundary. Instead of
+ // sorting them, treat them as same group here to avoid sorting the
+ // almost-sorted blocks.
+ pushBlocksImpl(C, ClassId, &ShuffleArray[I], N, /*SameGroup=*/true);
+ I += N;
+ }
+
+ const uptr AllocatedUser = Size * NumberOfBlocks;
+ C->getStats().add(StatFree, AllocatedUser);
+ DCHECK_LE(Sci->CurrentRegionAllocated + AllocatedUser, RegionSize);
+ // If there is not enough room in the region currently associated to fit
+ // more blocks, we deassociate the region by resetting CurrentRegion and
+ // CurrentRegionAllocated. Otherwise, update the allocated amount.
+ if (RegionSize - (Sci->CurrentRegionAllocated + AllocatedUser) < Size) {
+ Sci->CurrentRegion = 0;
+ Sci->CurrentRegionAllocated = 0;
+ } else {
+ Sci->CurrentRegionAllocated += AllocatedUser;
+ }
+ Sci->AllocatedUser += AllocatedUser;
+
+ return true;
+ }
+
+ void getStats(ScopedString *Str, uptr ClassId, uptr Rss) {
+ SizeClassInfo *Sci = getSizeClassInfo(ClassId);
+ if (Sci->AllocatedUser == 0)
+ return;
+ const uptr InUse = Sci->Stats.PoppedBlocks - Sci->Stats.PushedBlocks;
+ const uptr AvailableChunks = Sci->AllocatedUser / getSizeByClassId(ClassId);
+ Str->append(" %02zu (%6zu): mapped: %6zuK popped: %7zu pushed: %7zu "
+ "inuse: %6zu avail: %6zu rss: %6zuK releases: %6zu\n",
+ ClassId, getSizeByClassId(ClassId), Sci->AllocatedUser >> 10,
+ Sci->Stats.PoppedBlocks, Sci->Stats.PushedBlocks, InUse,
+ AvailableChunks, Rss >> 10, Sci->ReleaseInfo.RangesReleased);
+ }
+
+ NOINLINE uptr releaseToOSMaybe(SizeClassInfo *Sci, uptr ClassId,
+ bool Force = false) {
+ const uptr BlockSize = getSizeByClassId(ClassId);
+ const uptr PageSize = getPageSizeCached();
+
+ DCHECK_GE(Sci->Stats.PoppedBlocks, Sci->Stats.PushedBlocks);
+ const uptr BytesInFreeList =
+ Sci->AllocatedUser -
+ (Sci->Stats.PoppedBlocks - Sci->Stats.PushedBlocks) * BlockSize;
+ if (BytesInFreeList < PageSize)
+ return 0; // No chance to release anything.
+ const uptr BytesPushed =
+ (Sci->Stats.PushedBlocks - Sci->ReleaseInfo.PushedBlocksAtLastRelease) *
+ BlockSize;
+ if (BytesPushed < PageSize)
+ return 0; // Nothing new to release.
+
+ const bool CheckDensity = BlockSize < PageSize / 16U;
+ // Releasing smaller blocks is expensive, so we want to make sure that a
+ // significant amount of bytes are free, and that there has been a good
+ // amount of batches pushed to the freelist before attempting to release.
+ if (CheckDensity) {
+ if (!Force && BytesPushed < Sci->AllocatedUser / 16U)
+ return 0;
+ }
+
+ if (!Force) {
+ const s32 IntervalMs = atomic_load_relaxed(&ReleaseToOsIntervalMs);
+ if (IntervalMs < 0)
+ return 0;
+ if (Sci->ReleaseInfo.LastReleaseAtNs +
+ static_cast<u64>(IntervalMs) * 1000000 >
+ getMonotonicTime()) {
+ return 0; // Memory was returned recently.
+ }
+ }
+
+ const uptr First = Sci->MinRegionIndex;
+ const uptr Last = Sci->MaxRegionIndex;
+ DCHECK_NE(Last, 0U);
+ DCHECK_LE(First, Last);
+ uptr TotalReleasedBytes = 0;
+ const uptr Base = First * RegionSize;
+ const uptr NumberOfRegions = Last - First + 1U;
+ const uptr GroupSize = (1U << GroupSizeLog);
+ const uptr CurRegionGroupId =
+ compactPtrGroup(compactPtr(ClassId, Sci->CurrentRegion));
+
+ ReleaseRecorder Recorder(Base);
+ PageReleaseContext Context(BlockSize, RegionSize, NumberOfRegions);
+
+ auto DecompactPtr = [](CompactPtrT CompactPtr) {
+ return reinterpret_cast<uptr>(CompactPtr);
+ };
+ for (BatchGroup &BG : Sci->FreeList) {
+ const uptr PushedBytesDelta =
+ BG.PushedBlocks - BG.PushedBlocksAtLastCheckpoint;
+ if (PushedBytesDelta * BlockSize < PageSize)
+ continue;
+
+ uptr AllocatedGroupSize = BG.GroupId == CurRegionGroupId
+ ? Sci->CurrentRegionAllocated
+ : GroupSize;
+ if (AllocatedGroupSize == 0)
+ continue;
+
+ // TransferBatches are pushed in front of BG.Batches. The first one may
+ // not have all caches used.
+ const uptr NumBlocks = (BG.Batches.size() - 1) * BG.MaxCachedPerBatch +
+ BG.Batches.front()->getCount();
+ const uptr BytesInBG = NumBlocks * BlockSize;
+ // Given the randomness property, we try to release the pages only if the
+ // bytes used by free blocks exceed certain proportion of allocated
+ // spaces.
+ if (CheckDensity && (BytesInBG * 100U) / AllocatedGroupSize <
+ (100U - 1U - BlockSize / 16U)) {
+ continue;
+ }
+
+ BG.PushedBlocksAtLastCheckpoint = BG.PushedBlocks;
+ // Note that we don't always visit blocks in each BatchGroup so that we
+ // may miss the chance of releasing certain pages that cross BatchGroups.
+ Context.markFreeBlocks(BG.Batches, DecompactPtr, Base);
+ }
+
+ if (!Context.hasBlockMarked())
+ return 0;
+
+ auto SkipRegion = [this, First, ClassId](uptr RegionIndex) {
+ return (PossibleRegions[First + RegionIndex] - 1U) != ClassId;
+ };
+ releaseFreeMemoryToOS(Context, Recorder, SkipRegion);
+
+ if (Recorder.getReleasedRangesCount() > 0) {
+ Sci->ReleaseInfo.PushedBlocksAtLastRelease = Sci->Stats.PushedBlocks;
+ Sci->ReleaseInfo.RangesReleased += Recorder.getReleasedRangesCount();
+ Sci->ReleaseInfo.LastReleasedBytes = Recorder.getReleasedBytes();
+ TotalReleasedBytes += Sci->ReleaseInfo.LastReleasedBytes;
+ }
+ Sci->ReleaseInfo.LastReleaseAtNs = getMonotonicTime();
+
+ return TotalReleasedBytes;
+ }
+
+ SizeClassInfo SizeClassInfoArray[NumClasses] = {};
+
+ // Track the regions in use, 0 is unused, otherwise store ClassId + 1.
+ ByteMap PossibleRegions = {};
+ atomic_s32 ReleaseToOsIntervalMs = {};
+ // Unless several threads request regions simultaneously from different size
+ // classes, the stash rarely contains more than 1 entry.
+ static constexpr uptr MaxStashedRegions = 4;
+ HybridMutex RegionsStashMutex;
+ uptr NumberOfStashedRegions = 0;
+ uptr RegionsStash[MaxStashedRegions] = {};
+};
+
+} // namespace scudo
+
+#endif // SCUDO_PRIMARY32_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/primary64.h b/contrib/libs/clang16-rt/lib/scudo/standalone/primary64.h
new file mode 100644
index 00000000000..b653bc80202
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/primary64.h
@@ -0,0 +1,784 @@
+//===-- primary64.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_PRIMARY64_H_
+#define SCUDO_PRIMARY64_H_
+
+#include "bytemap.h"
+#include "common.h"
+#include "list.h"
+#include "local_cache.h"
+#include "memtag.h"
+#include "options.h"
+#include "release.h"
+#include "stats.h"
+#include "string_utils.h"
+
+namespace scudo {
+
+// SizeClassAllocator64 is an allocator tuned for 64-bit address space.
+//
+// It starts by reserving NumClasses * 2^RegionSizeLog bytes, equally divided in
+// Regions, specific to each size class. Note that the base of that mapping is
+// random (based to the platform specific map() capabilities). If
+// PrimaryEnableRandomOffset is set, each Region actually starts at a random
+// offset from its base.
+//
+// Regions are mapped incrementally on demand to fulfill allocation requests,
+// those mappings being split into equally sized Blocks based on the size class
+// they belong to. The Blocks created are shuffled to prevent predictable
+// address patterns (the predictability increases with the size of the Blocks).
+//
+// The 1st Region (for size class 0) holds the TransferBatches. This is a
+// structure used to transfer arrays of available pointers from the class size
+// freelist to the thread specific freelist, and back.
+//
+// The memory used by this allocator is never unmapped, but can be partially
+// released if the platform allows for it.
+
+template <typename Config> class SizeClassAllocator64 {
+public:
+ typedef typename Config::PrimaryCompactPtrT CompactPtrT;
+ static const uptr CompactPtrScale = Config::PrimaryCompactPtrScale;
+ static const uptr GroupSizeLog = Config::PrimaryGroupSizeLog;
+ typedef typename Config::SizeClassMap SizeClassMap;
+ typedef SizeClassAllocator64<Config> ThisT;
+ typedef SizeClassAllocatorLocalCache<ThisT> CacheT;
+ typedef typename CacheT::TransferBatch TransferBatch;
+ typedef typename CacheT::BatchGroup BatchGroup;
+
+ static uptr getSizeByClassId(uptr ClassId) {
+ return (ClassId == SizeClassMap::BatchClassId)
+ ? roundUpTo(sizeof(TransferBatch), 1U << CompactPtrScale)
+ : SizeClassMap::getSizeByClassId(ClassId);
+ }
+
+ static bool canAllocate(uptr Size) { return Size <= SizeClassMap::MaxSize; }
+
+ void init(s32 ReleaseToOsInterval) {
+ DCHECK(isAligned(reinterpret_cast<uptr>(this), alignof(ThisT)));
+ DCHECK_EQ(PrimaryBase, 0U);
+ // Reserve the space required for the Primary.
+ PrimaryBase = reinterpret_cast<uptr>(
+ map(nullptr, PrimarySize, nullptr, MAP_NOACCESS, &Data));
+
+ u32 Seed;
+ const u64 Time = getMonotonicTime();
+ if (!getRandom(reinterpret_cast<void *>(&Seed), sizeof(Seed)))
+ Seed = static_cast<u32>(Time ^ (PrimaryBase >> 12));
+ const uptr PageSize = getPageSizeCached();
+ for (uptr I = 0; I < NumClasses; I++) {
+ RegionInfo *Region = getRegionInfo(I);
+ // The actual start of a region is offset by a random number of pages
+ // when PrimaryEnableRandomOffset is set.
+ Region->RegionBeg = getRegionBaseByClassId(I) +
+ (Config::PrimaryEnableRandomOffset
+ ? ((getRandomModN(&Seed, 16) + 1) * PageSize)
+ : 0);
+ Region->RandState = getRandomU32(&Seed);
+ Region->ReleaseInfo.LastReleaseAtNs = Time;
+ }
+ setOption(Option::ReleaseInterval, static_cast<sptr>(ReleaseToOsInterval));
+ }
+
+ void unmapTestOnly() {
+ for (uptr I = 0; I < NumClasses; I++) {
+ RegionInfo *Region = getRegionInfo(I);
+ *Region = {};
+ }
+ if (PrimaryBase)
+ unmap(reinterpret_cast<void *>(PrimaryBase), PrimarySize, UNMAP_ALL,
+ &Data);
+ PrimaryBase = 0U;
+ }
+
+ TransferBatch *popBatch(CacheT *C, uptr ClassId) {
+ DCHECK_LT(ClassId, NumClasses);
+ RegionInfo *Region = getRegionInfo(ClassId);
+ ScopedLock L(Region->Mutex);
+ TransferBatch *B = popBatchImpl(C, ClassId);
+ if (UNLIKELY(!B)) {
+ if (UNLIKELY(!populateFreeList(C, ClassId, Region)))
+ return nullptr;
+ B = popBatchImpl(C, ClassId);
+ // if `populateFreeList` succeeded, we are supposed to get free blocks.
+ DCHECK_NE(B, nullptr);
+ }
+ Region->Stats.PoppedBlocks += B->getCount();
+ return B;
+ }
+
+ // Push the array of free blocks to the designated batch group.
+ void pushBlocks(CacheT *C, uptr ClassId, CompactPtrT *Array, u32 Size) {
+ DCHECK_LT(ClassId, NumClasses);
+ DCHECK_GT(Size, 0);
+
+ RegionInfo *Region = getRegionInfo(ClassId);
+ if (ClassId == SizeClassMap::BatchClassId) {
+ ScopedLock L(Region->Mutex);
+ // Constructing a batch group in the free list will use two blocks in
+ // BatchClassId. If we are pushing BatchClassId blocks, we will use the
+ // blocks in the array directly (can't delegate local cache which will
+ // cause a recursive allocation). However, The number of free blocks may
+ // be less than two. Therefore, populate the free list before inserting
+ // the blocks.
+ if (Size == 1 && UNLIKELY(!populateFreeList(C, ClassId, Region)))
+ return;
+ pushBlocksImpl(C, ClassId, Array, Size);
+ Region->Stats.PushedBlocks += Size;
+ return;
+ }
+
+ // TODO(chiahungduan): Consider not doing grouping if the group size is not
+ // greater than the block size with a certain scale.
+
+ // Sort the blocks so that blocks belonging to the same group can be pushed
+ // together.
+ bool SameGroup = true;
+ for (u32 I = 1; I < Size; ++I) {
+ if (compactPtrGroup(Array[I - 1]) != compactPtrGroup(Array[I]))
+ SameGroup = false;
+ CompactPtrT Cur = Array[I];
+ u32 J = I;
+ while (J > 0 && compactPtrGroup(Cur) < compactPtrGroup(Array[J - 1])) {
+ Array[J] = Array[J - 1];
+ --J;
+ }
+ Array[J] = Cur;
+ }
+
+ ScopedLock L(Region->Mutex);
+ pushBlocksImpl(C, ClassId, Array, Size, SameGroup);
+
+ Region->Stats.PushedBlocks += Size;
+ if (ClassId != SizeClassMap::BatchClassId)
+ releaseToOSMaybe(Region, ClassId);
+ }
+
+ void disable() {
+ // The BatchClassId must be locked last since other classes can use it.
+ for (sptr I = static_cast<sptr>(NumClasses) - 1; I >= 0; I--) {
+ if (static_cast<uptr>(I) == SizeClassMap::BatchClassId)
+ continue;
+ getRegionInfo(static_cast<uptr>(I))->Mutex.lock();
+ }
+ getRegionInfo(SizeClassMap::BatchClassId)->Mutex.lock();
+ }
+
+ void enable() {
+ getRegionInfo(SizeClassMap::BatchClassId)->Mutex.unlock();
+ for (uptr I = 0; I < NumClasses; I++) {
+ if (I == SizeClassMap::BatchClassId)
+ continue;
+ getRegionInfo(I)->Mutex.unlock();
+ }
+ }
+
+ template <typename F> void iterateOverBlocks(F Callback) {
+ for (uptr I = 0; I < NumClasses; I++) {
+ if (I == SizeClassMap::BatchClassId)
+ continue;
+ const RegionInfo *Region = getRegionInfo(I);
+ const uptr BlockSize = getSizeByClassId(I);
+ const uptr From = Region->RegionBeg;
+ const uptr To = From + Region->AllocatedUser;
+ for (uptr Block = From; Block < To; Block += BlockSize)
+ Callback(Block);
+ }
+ }
+
+ void getStats(ScopedString *Str) {
+ // TODO(kostyak): get the RSS per region.
+ uptr TotalMapped = 0;
+ uptr PoppedBlocks = 0;
+ uptr PushedBlocks = 0;
+ for (uptr I = 0; I < NumClasses; I++) {
+ RegionInfo *Region = getRegionInfo(I);
+ if (Region->MappedUser)
+ TotalMapped += Region->MappedUser;
+ PoppedBlocks += Region->Stats.PoppedBlocks;
+ PushedBlocks += Region->Stats.PushedBlocks;
+ }
+ Str->append("Stats: SizeClassAllocator64: %zuM mapped (%uM rss) in %zu "
+ "allocations; remains %zu\n",
+ TotalMapped >> 20, 0U, PoppedBlocks,
+ PoppedBlocks - PushedBlocks);
+
+ for (uptr I = 0; I < NumClasses; I++)
+ getStats(Str, I, 0);
+ }
+
+ bool setOption(Option O, sptr Value) {
+ if (O == Option::ReleaseInterval) {
+ const s32 Interval = Max(
+ Min(static_cast<s32>(Value), Config::PrimaryMaxReleaseToOsIntervalMs),
+ Config::PrimaryMinReleaseToOsIntervalMs);
+ atomic_store_relaxed(&ReleaseToOsIntervalMs, Interval);
+ return true;
+ }
+ // Not supported by the Primary, but not an error either.
+ return true;
+ }
+
+ uptr releaseToOS() {
+ uptr TotalReleasedBytes = 0;
+ for (uptr I = 0; I < NumClasses; I++) {
+ if (I == SizeClassMap::BatchClassId)
+ continue;
+ RegionInfo *Region = getRegionInfo(I);
+ ScopedLock L(Region->Mutex);
+ TotalReleasedBytes += releaseToOSMaybe(Region, I, /*Force=*/true);
+ }
+ return TotalReleasedBytes;
+ }
+
+ const char *getRegionInfoArrayAddress() const {
+ return reinterpret_cast<const char *>(RegionInfoArray);
+ }
+
+ static uptr getRegionInfoArraySize() { return sizeof(RegionInfoArray); }
+
+ uptr getCompactPtrBaseByClassId(uptr ClassId) {
+ // If we are not compacting pointers, base everything off of 0.
+ if (sizeof(CompactPtrT) == sizeof(uptr) && CompactPtrScale == 0)
+ return 0;
+ return getRegionInfo(ClassId)->RegionBeg;
+ }
+
+ CompactPtrT compactPtr(uptr ClassId, uptr Ptr) {
+ DCHECK_LE(ClassId, SizeClassMap::LargestClassId);
+ return compactPtrInternal(getCompactPtrBaseByClassId(ClassId), Ptr);
+ }
+
+ void *decompactPtr(uptr ClassId, CompactPtrT CompactPtr) {
+ DCHECK_LE(ClassId, SizeClassMap::LargestClassId);
+ return reinterpret_cast<void *>(
+ decompactPtrInternal(getCompactPtrBaseByClassId(ClassId), CompactPtr));
+ }
+
+ static BlockInfo findNearestBlock(const char *RegionInfoData, uptr Ptr) {
+ const RegionInfo *RegionInfoArray =
+ reinterpret_cast<const RegionInfo *>(RegionInfoData);
+ uptr ClassId;
+ uptr MinDistance = -1UL;
+ for (uptr I = 0; I != NumClasses; ++I) {
+ if (I == SizeClassMap::BatchClassId)
+ continue;
+ uptr Begin = RegionInfoArray[I].RegionBeg;
+ uptr End = Begin + RegionInfoArray[I].AllocatedUser;
+ if (Begin > End || End - Begin < SizeClassMap::getSizeByClassId(I))
+ continue;
+ uptr RegionDistance;
+ if (Begin <= Ptr) {
+ if (Ptr < End)
+ RegionDistance = 0;
+ else
+ RegionDistance = Ptr - End;
+ } else {
+ RegionDistance = Begin - Ptr;
+ }
+
+ if (RegionDistance < MinDistance) {
+ MinDistance = RegionDistance;
+ ClassId = I;
+ }
+ }
+
+ BlockInfo B = {};
+ if (MinDistance <= 8192) {
+ B.RegionBegin = RegionInfoArray[ClassId].RegionBeg;
+ B.RegionEnd = B.RegionBegin + RegionInfoArray[ClassId].AllocatedUser;
+ B.BlockSize = SizeClassMap::getSizeByClassId(ClassId);
+ B.BlockBegin =
+ B.RegionBegin + uptr(sptr(Ptr - B.RegionBegin) / sptr(B.BlockSize) *
+ sptr(B.BlockSize));
+ while (B.BlockBegin < B.RegionBegin)
+ B.BlockBegin += B.BlockSize;
+ while (B.RegionEnd < B.BlockBegin + B.BlockSize)
+ B.BlockBegin -= B.BlockSize;
+ }
+ return B;
+ }
+
+ AtomicOptions Options;
+
+private:
+ static const uptr RegionSize = 1UL << Config::PrimaryRegionSizeLog;
+ static const uptr NumClasses = SizeClassMap::NumClasses;
+ static const uptr PrimarySize = RegionSize * NumClasses;
+
+ static const uptr MapSizeIncrement = Config::PrimaryMapSizeIncrement;
+ // Fill at most this number of batches from the newly map'd memory.
+ static const u32 MaxNumBatches = SCUDO_ANDROID ? 4U : 8U;
+
+ struct RegionStats {
+ uptr PoppedBlocks;
+ uptr PushedBlocks;
+ };
+
+ struct ReleaseToOsInfo {
+ uptr PushedBlocksAtLastRelease;
+ uptr RangesReleased;
+ uptr LastReleasedBytes;
+ u64 LastReleaseAtNs;
+ };
+
+ struct UnpaddedRegionInfo {
+ HybridMutex Mutex;
+ SinglyLinkedList<BatchGroup> FreeList;
+ uptr RegionBeg = 0;
+ RegionStats Stats = {};
+ u32 RandState = 0;
+ uptr MappedUser = 0; // Bytes mapped for user memory.
+ uptr AllocatedUser = 0; // Bytes allocated for user memory.
+ MapPlatformData Data = {};
+ ReleaseToOsInfo ReleaseInfo = {};
+ bool Exhausted = false;
+ };
+ struct RegionInfo : UnpaddedRegionInfo {
+ char Padding[SCUDO_CACHE_LINE_SIZE -
+ (sizeof(UnpaddedRegionInfo) % SCUDO_CACHE_LINE_SIZE)] = {};
+ };
+ static_assert(sizeof(RegionInfo) % SCUDO_CACHE_LINE_SIZE == 0, "");
+
+ uptr PrimaryBase = 0;
+ MapPlatformData Data = {};
+ atomic_s32 ReleaseToOsIntervalMs = {};
+ alignas(SCUDO_CACHE_LINE_SIZE) RegionInfo RegionInfoArray[NumClasses];
+
+ RegionInfo *getRegionInfo(uptr ClassId) {
+ DCHECK_LT(ClassId, NumClasses);
+ return &RegionInfoArray[ClassId];
+ }
+
+ uptr getRegionBaseByClassId(uptr ClassId) const {
+ return PrimaryBase + (ClassId << Config::PrimaryRegionSizeLog);
+ }
+
+ static CompactPtrT compactPtrInternal(uptr Base, uptr Ptr) {
+ return static_cast<CompactPtrT>((Ptr - Base) >> CompactPtrScale);
+ }
+
+ static uptr decompactPtrInternal(uptr Base, CompactPtrT CompactPtr) {
+ return Base + (static_cast<uptr>(CompactPtr) << CompactPtrScale);
+ }
+
+ static uptr compactPtrGroup(CompactPtrT CompactPtr) {
+ return static_cast<uptr>(CompactPtr) >> (GroupSizeLog - CompactPtrScale);
+ }
+ static uptr batchGroupBase(uptr Base, uptr GroupId) {
+ return (GroupId << GroupSizeLog) + Base;
+ }
+
+ // Push the blocks to their batch group. The layout will be like,
+ //
+ // FreeList - > BG -> BG -> BG
+ // | | |
+ // v v v
+ // TB TB TB
+ // |
+ // v
+ // TB
+ //
+ // Each BlockGroup(BG) will associate with unique group id and the free blocks
+ // are managed by a list of TransferBatch(TB). To reduce the time of inserting
+ // blocks, BGs are sorted and the input `Array` are supposed to be sorted so
+ // that we can get better performance of maintaining sorted property.
+ // Use `SameGroup=true` to indicate that all blocks in the array are from the
+ // same group then we will skip checking the group id of each block.
+ //
+ // Note that this aims to have a better management of dirty pages, i.e., the
+ // RSS usage won't grow indefinitely. There's an exception that we may not put
+ // a block to its associated group. While populating new blocks, we may have
+ // blocks cross different groups. However, most cases will fall into same
+ // group and they are supposed to be popped soon. In that case, it's not worth
+ // sorting the array with the almost-sorted property. Therefore, we use
+ // `SameGroup=true` instead.
+ //
+ // The region mutex needs to be held while calling this method.
+ void pushBlocksImpl(CacheT *C, uptr ClassId, CompactPtrT *Array, u32 Size,
+ bool SameGroup = false) {
+ DCHECK_GT(Size, 0U);
+ RegionInfo *Region = getRegionInfo(ClassId);
+
+ auto CreateGroup = [&](uptr GroupId) {
+ BatchGroup *BG = nullptr;
+ TransferBatch *TB = nullptr;
+ if (ClassId == SizeClassMap::BatchClassId) {
+ DCHECK_GE(Size, 2U);
+ BG = reinterpret_cast<BatchGroup *>(
+ decompactPtr(ClassId, Array[Size - 1]));
+ BG->Batches.clear();
+
+ TB = reinterpret_cast<TransferBatch *>(
+ decompactPtr(ClassId, Array[Size - 2]));
+ TB->clear();
+ } else {
+ BG = C->createGroup();
+ BG->Batches.clear();
+
+ TB = C->createBatch(ClassId, nullptr);
+ TB->clear();
+ }
+
+ BG->GroupId = GroupId;
+ BG->Batches.push_front(TB);
+ BG->PushedBlocks = 0;
+ BG->PushedBlocksAtLastCheckpoint = 0;
+ BG->MaxCachedPerBatch =
+ TransferBatch::getMaxCached(getSizeByClassId(ClassId));
+
+ return BG;
+ };
+
+ auto InsertBlocks = [&](BatchGroup *BG, CompactPtrT *Array, u32 Size) {
+ SinglyLinkedList<TransferBatch> &Batches = BG->Batches;
+ TransferBatch *CurBatch = Batches.front();
+ DCHECK_NE(CurBatch, nullptr);
+
+ for (u32 I = 0; I < Size;) {
+ DCHECK_GE(BG->MaxCachedPerBatch, CurBatch->getCount());
+ u16 UnusedSlots =
+ static_cast<u16>(BG->MaxCachedPerBatch - CurBatch->getCount());
+ if (UnusedSlots == 0) {
+ CurBatch = C->createBatch(
+ ClassId,
+ reinterpret_cast<void *>(decompactPtr(ClassId, Array[I])));
+ CurBatch->clear();
+ Batches.push_front(CurBatch);
+ UnusedSlots = BG->MaxCachedPerBatch;
+ }
+ // `UnusedSlots` is u16 so the result will be also fit in u16.
+ u16 AppendSize = static_cast<u16>(Min<u32>(UnusedSlots, Size - I));
+ CurBatch->appendFromArray(&Array[I], AppendSize);
+ I += AppendSize;
+ }
+
+ BG->PushedBlocks += Size;
+ };
+
+ BatchGroup *Cur = Region->FreeList.front();
+
+ if (ClassId == SizeClassMap::BatchClassId) {
+ if (Cur == nullptr) {
+ // Don't need to classify BatchClassId.
+ Cur = CreateGroup(/*GroupId=*/0);
+ Region->FreeList.push_front(Cur);
+ }
+ InsertBlocks(Cur, Array, Size);
+ return;
+ }
+
+ // In the following, `Cur` always points to the BatchGroup for blocks that
+ // will be pushed next. `Prev` is the element right before `Cur`.
+ BatchGroup *Prev = nullptr;
+
+ while (Cur != nullptr && compactPtrGroup(Array[0]) > Cur->GroupId) {
+ Prev = Cur;
+ Cur = Cur->Next;
+ }
+
+ if (Cur == nullptr || compactPtrGroup(Array[0]) != Cur->GroupId) {
+ Cur = CreateGroup(compactPtrGroup(Array[0]));
+ if (Prev == nullptr)
+ Region->FreeList.push_front(Cur);
+ else
+ Region->FreeList.insert(Prev, Cur);
+ }
+
+ // All the blocks are from the same group, just push without checking group
+ // id.
+ if (SameGroup) {
+ InsertBlocks(Cur, Array, Size);
+ return;
+ }
+
+ // The blocks are sorted by group id. Determine the segment of group and
+ // push them to their group together.
+ u32 Count = 1;
+ for (u32 I = 1; I < Size; ++I) {
+ if (compactPtrGroup(Array[I - 1]) != compactPtrGroup(Array[I])) {
+ DCHECK_EQ(compactPtrGroup(Array[I - 1]), Cur->GroupId);
+ InsertBlocks(Cur, Array + I - Count, Count);
+
+ while (Cur != nullptr && compactPtrGroup(Array[I]) > Cur->GroupId) {
+ Prev = Cur;
+ Cur = Cur->Next;
+ }
+
+ if (Cur == nullptr || compactPtrGroup(Array[I]) != Cur->GroupId) {
+ Cur = CreateGroup(compactPtrGroup(Array[I]));
+ DCHECK_NE(Prev, nullptr);
+ Region->FreeList.insert(Prev, Cur);
+ }
+
+ Count = 1;
+ } else {
+ ++Count;
+ }
+ }
+
+ InsertBlocks(Cur, Array + Size - Count, Count);
+ }
+
+ // Pop one TransferBatch from a BatchGroup. The BatchGroup with the smallest
+ // group id will be considered first.
+ //
+ // The region mutex needs to be held while calling this method.
+ TransferBatch *popBatchImpl(CacheT *C, uptr ClassId) {
+ RegionInfo *Region = getRegionInfo(ClassId);
+ if (Region->FreeList.empty())
+ return nullptr;
+
+ SinglyLinkedList<TransferBatch> &Batches =
+ Region->FreeList.front()->Batches;
+ DCHECK(!Batches.empty());
+
+ TransferBatch *B = Batches.front();
+ Batches.pop_front();
+ DCHECK_NE(B, nullptr);
+ DCHECK_GT(B->getCount(), 0U);
+
+ if (Batches.empty()) {
+ BatchGroup *BG = Region->FreeList.front();
+ Region->FreeList.pop_front();
+
+ // We don't keep BatchGroup with zero blocks to avoid empty-checking while
+ // allocating. Note that block used by constructing BatchGroup is recorded
+ // as free blocks in the last element of BatchGroup::Batches. Which means,
+ // once we pop the last TransferBatch, the block is implicitly
+ // deallocated.
+ if (ClassId != SizeClassMap::BatchClassId)
+ C->deallocate(SizeClassMap::BatchClassId, BG);
+ }
+
+ return B;
+ }
+
+ NOINLINE bool populateFreeList(CacheT *C, uptr ClassId, RegionInfo *Region) {
+ const uptr Size = getSizeByClassId(ClassId);
+ const u16 MaxCount = TransferBatch::getMaxCached(Size);
+
+ const uptr RegionBeg = Region->RegionBeg;
+ const uptr MappedUser = Region->MappedUser;
+ const uptr TotalUserBytes = Region->AllocatedUser + MaxCount * Size;
+ // Map more space for blocks, if necessary.
+ if (TotalUserBytes > MappedUser) {
+ // Do the mmap for the user memory.
+ const uptr MapSize =
+ roundUpTo(TotalUserBytes - MappedUser, MapSizeIncrement);
+ const uptr RegionBase = RegionBeg - getRegionBaseByClassId(ClassId);
+ if (UNLIKELY(RegionBase + MappedUser + MapSize > RegionSize)) {
+ if (!Region->Exhausted) {
+ Region->Exhausted = true;
+ ScopedString Str;
+ getStats(&Str);
+ Str.append(
+ "Scudo OOM: The process has exhausted %zuM for size class %zu.\n",
+ RegionSize >> 20, Size);
+ Str.output();
+ }
+ return false;
+ }
+ if (MappedUser == 0)
+ Region->Data = Data;
+ if (UNLIKELY(!map(
+ reinterpret_cast<void *>(RegionBeg + MappedUser), MapSize,
+ "scudo:primary",
+ MAP_ALLOWNOMEM | MAP_RESIZABLE |
+ (useMemoryTagging<Config>(Options.load()) ? MAP_MEMTAG : 0),
+ &Region->Data))) {
+ return false;
+ }
+ Region->MappedUser += MapSize;
+ C->getStats().add(StatMapped, MapSize);
+ }
+
+ const u32 NumberOfBlocks = Min(
+ MaxNumBatches * MaxCount,
+ static_cast<u32>((Region->MappedUser - Region->AllocatedUser) / Size));
+ DCHECK_GT(NumberOfBlocks, 0);
+
+ constexpr u32 ShuffleArraySize =
+ MaxNumBatches * TransferBatch::MaxNumCached;
+ CompactPtrT ShuffleArray[ShuffleArraySize];
+ DCHECK_LE(NumberOfBlocks, ShuffleArraySize);
+
+ const uptr CompactPtrBase = getCompactPtrBaseByClassId(ClassId);
+ uptr P = RegionBeg + Region->AllocatedUser;
+ for (u32 I = 0; I < NumberOfBlocks; I++, P += Size)
+ ShuffleArray[I] = compactPtrInternal(CompactPtrBase, P);
+ // No need to shuffle the batches size class.
+ if (ClassId != SizeClassMap::BatchClassId)
+ shuffle(ShuffleArray, NumberOfBlocks, &Region->RandState);
+ for (u32 I = 0; I < NumberOfBlocks;) {
+ // `MaxCount` is u16 so the result will also fit in u16.
+ const u16 N = static_cast<u16>(Min<u32>(MaxCount, NumberOfBlocks - I));
+ // Note that the N blocks here may have different group ids. Given that
+ // it only happens when it crosses the group size boundary. Instead of
+ // sorting them, treat them as same group here to avoid sorting the
+ // almost-sorted blocks.
+ pushBlocksImpl(C, ClassId, &ShuffleArray[I], N, /*SameGroup=*/true);
+ I += N;
+ }
+
+ const uptr AllocatedUser = Size * NumberOfBlocks;
+ C->getStats().add(StatFree, AllocatedUser);
+ Region->AllocatedUser += AllocatedUser;
+
+ return true;
+ }
+
+ void getStats(ScopedString *Str, uptr ClassId, uptr Rss) {
+ RegionInfo *Region = getRegionInfo(ClassId);
+ if (Region->MappedUser == 0)
+ return;
+ const uptr InUse = Region->Stats.PoppedBlocks - Region->Stats.PushedBlocks;
+ const uptr TotalChunks = Region->AllocatedUser / getSizeByClassId(ClassId);
+ Str->append("%s %02zu (%6zu): mapped: %6zuK popped: %7zu pushed: %7zu "
+ "inuse: %6zu total: %6zu rss: %6zuK releases: %6zu last "
+ "released: %6zuK region: 0x%zx (0x%zx)\n",
+ Region->Exhausted ? "F" : " ", ClassId,
+ getSizeByClassId(ClassId), Region->MappedUser >> 10,
+ Region->Stats.PoppedBlocks, Region->Stats.PushedBlocks, InUse,
+ TotalChunks, Rss >> 10, Region->ReleaseInfo.RangesReleased,
+ Region->ReleaseInfo.LastReleasedBytes >> 10, Region->RegionBeg,
+ getRegionBaseByClassId(ClassId));
+ }
+
+ NOINLINE uptr releaseToOSMaybe(RegionInfo *Region, uptr ClassId,
+ bool Force = false) {
+ const uptr BlockSize = getSizeByClassId(ClassId);
+ const uptr PageSize = getPageSizeCached();
+
+ DCHECK_GE(Region->Stats.PoppedBlocks, Region->Stats.PushedBlocks);
+ const uptr BytesInFreeList =
+ Region->AllocatedUser -
+ (Region->Stats.PoppedBlocks - Region->Stats.PushedBlocks) * BlockSize;
+ if (BytesInFreeList < PageSize)
+ return 0; // No chance to release anything.
+ const uptr BytesPushed = (Region->Stats.PushedBlocks -
+ Region->ReleaseInfo.PushedBlocksAtLastRelease) *
+ BlockSize;
+ if (BytesPushed < PageSize)
+ return 0; // Nothing new to release.
+
+ bool CheckDensity = BlockSize < PageSize / 16U;
+ // Releasing smaller blocks is expensive, so we want to make sure that a
+ // significant amount of bytes are free, and that there has been a good
+ // amount of batches pushed to the freelist before attempting to release.
+ if (CheckDensity) {
+ if (!Force && BytesPushed < Region->AllocatedUser / 16U)
+ return 0;
+ }
+
+ if (!Force) {
+ const s32 IntervalMs = atomic_load_relaxed(&ReleaseToOsIntervalMs);
+ if (IntervalMs < 0)
+ return 0;
+ if (Region->ReleaseInfo.LastReleaseAtNs +
+ static_cast<u64>(IntervalMs) * 1000000 >
+ getMonotonicTime()) {
+ return 0; // Memory was returned recently.
+ }
+ }
+
+ const uptr GroupSize = (1U << GroupSizeLog);
+ const uptr AllocatedUserEnd = Region->AllocatedUser + Region->RegionBeg;
+ ReleaseRecorder Recorder(Region->RegionBeg, &Region->Data);
+ PageReleaseContext Context(BlockSize, Region->AllocatedUser,
+ /*NumberOfRegions=*/1U);
+
+ const uptr CompactPtrBase = getCompactPtrBaseByClassId(ClassId);
+ auto DecompactPtr = [CompactPtrBase](CompactPtrT CompactPtr) {
+ return decompactPtrInternal(CompactPtrBase, CompactPtr);
+ };
+ for (BatchGroup &BG : Region->FreeList) {
+ const uptr PushedBytesDelta =
+ BG.PushedBlocks - BG.PushedBlocksAtLastCheckpoint;
+ if (PushedBytesDelta * BlockSize < PageSize)
+ continue;
+
+ // Group boundary does not necessarily have the same alignment as Region.
+ // It may sit across a Region boundary. Which means that we may have the
+ // following two cases,
+ //
+ // 1. Group boundary sits before RegionBeg.
+ //
+ // (BatchGroupBeg)
+ // batchGroupBase RegionBeg BatchGroupEnd
+ // | | |
+ // v v v
+ // +------------+----------------+
+ // \ /
+ // ------ GroupSize ------
+ //
+ // 2. Group boundary sits after RegionBeg.
+ //
+ // (BatchGroupBeg)
+ // RegionBeg batchGroupBase BatchGroupEnd
+ // | | |
+ // v v v
+ // +-----------+-----------------------------+
+ // \ /
+ // ------ GroupSize ------
+ //
+ // Note that in the first case, the group range before RegionBeg is never
+ // used. Therefore, while calculating the used group size, we should
+ // exclude that part to get the correct size.
+ const uptr BatchGroupBeg =
+ Max(batchGroupBase(CompactPtrBase, BG.GroupId), Region->RegionBeg);
+ DCHECK_GE(AllocatedUserEnd, BatchGroupBeg);
+ const uptr BatchGroupEnd =
+ batchGroupBase(CompactPtrBase, BG.GroupId) + GroupSize;
+ const uptr AllocatedGroupSize = AllocatedUserEnd >= BatchGroupEnd
+ ? BatchGroupEnd - BatchGroupBeg
+ : AllocatedUserEnd - BatchGroupBeg;
+ if (AllocatedGroupSize == 0)
+ continue;
+
+ // TransferBatches are pushed in front of BG.Batches. The first one may
+ // not have all caches used.
+ const uptr NumBlocks = (BG.Batches.size() - 1) * BG.MaxCachedPerBatch +
+ BG.Batches.front()->getCount();
+ const uptr BytesInBG = NumBlocks * BlockSize;
+ // Given the randomness property, we try to release the pages only if the
+ // bytes used by free blocks exceed certain proportion of group size. Note
+ // that this heuristic only applies when all the spaces in a BatchGroup
+ // are allocated.
+ if (CheckDensity && (BytesInBG * 100U) / AllocatedGroupSize <
+ (100U - 1U - BlockSize / 16U)) {
+ continue;
+ }
+
+ BG.PushedBlocksAtLastCheckpoint = BG.PushedBlocks;
+ // Note that we don't always visit blocks in each BatchGroup so that we
+ // may miss the chance of releasing certain pages that cross BatchGroups.
+ Context.markFreeBlocks(BG.Batches, DecompactPtr, Region->RegionBeg);
+ }
+
+ if (!Context.hasBlockMarked())
+ return 0;
+
+ auto SkipRegion = [](UNUSED uptr RegionIndex) { return false; };
+ releaseFreeMemoryToOS(Context, Recorder, SkipRegion);
+
+ if (Recorder.getReleasedRangesCount() > 0) {
+ Region->ReleaseInfo.PushedBlocksAtLastRelease =
+ Region->Stats.PushedBlocks;
+ Region->ReleaseInfo.RangesReleased += Recorder.getReleasedRangesCount();
+ Region->ReleaseInfo.LastReleasedBytes = Recorder.getReleasedBytes();
+ }
+ Region->ReleaseInfo.LastReleaseAtNs = getMonotonicTime();
+ return Recorder.getReleasedBytes();
+ }
+};
+
+} // namespace scudo
+
+#endif // SCUDO_PRIMARY64_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/quarantine.h b/contrib/libs/clang16-rt/lib/scudo/standalone/quarantine.h
new file mode 100644
index 00000000000..2d231c3a28d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/quarantine.h
@@ -0,0 +1,297 @@
+//===-- quarantine.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_QUARANTINE_H_
+#define SCUDO_QUARANTINE_H_
+
+#include "list.h"
+#include "mutex.h"
+#include "string_utils.h"
+
+namespace scudo {
+
+struct QuarantineBatch {
+ // With the following count, a batch (and the header that protects it) occupy
+ // 4096 bytes on 32-bit platforms, and 8192 bytes on 64-bit.
+ static const u32 MaxCount = 1019;
+ QuarantineBatch *Next;
+ uptr Size;
+ u32 Count;
+ void *Batch[MaxCount];
+
+ void init(void *Ptr, uptr Size) {
+ Count = 1;
+ Batch[0] = Ptr;
+ this->Size = Size + sizeof(QuarantineBatch); // Account for the Batch Size.
+ }
+
+ // The total size of quarantined nodes recorded in this batch.
+ uptr getQuarantinedSize() const { return Size - sizeof(QuarantineBatch); }
+
+ void push_back(void *Ptr, uptr Size) {
+ DCHECK_LT(Count, MaxCount);
+ Batch[Count++] = Ptr;
+ this->Size += Size;
+ }
+
+ bool canMerge(const QuarantineBatch *const From) const {
+ return Count + From->Count <= MaxCount;
+ }
+
+ void merge(QuarantineBatch *const From) {
+ DCHECK_LE(Count + From->Count, MaxCount);
+ DCHECK_GE(Size, sizeof(QuarantineBatch));
+
+ for (uptr I = 0; I < From->Count; ++I)
+ Batch[Count + I] = From->Batch[I];
+ Count += From->Count;
+ Size += From->getQuarantinedSize();
+
+ From->Count = 0;
+ From->Size = sizeof(QuarantineBatch);
+ }
+
+ void shuffle(u32 State) { ::scudo::shuffle(Batch, Count, &State); }
+};
+
+static_assert(sizeof(QuarantineBatch) <= (1U << 13), ""); // 8Kb.
+
+// Per-thread cache of memory blocks.
+template <typename Callback> class QuarantineCache {
+public:
+ void init() { DCHECK_EQ(atomic_load_relaxed(&Size), 0U); }
+
+ // Total memory used, including internal accounting.
+ uptr getSize() const { return atomic_load_relaxed(&Size); }
+ // Memory used for internal accounting.
+ uptr getOverheadSize() const { return List.size() * sizeof(QuarantineBatch); }
+
+ void enqueue(Callback Cb, void *Ptr, uptr Size) {
+ if (List.empty() || List.back()->Count == QuarantineBatch::MaxCount) {
+ QuarantineBatch *B =
+ reinterpret_cast<QuarantineBatch *>(Cb.allocate(sizeof(*B)));
+ DCHECK(B);
+ B->init(Ptr, Size);
+ enqueueBatch(B);
+ } else {
+ List.back()->push_back(Ptr, Size);
+ addToSize(Size);
+ }
+ }
+
+ void transfer(QuarantineCache *From) {
+ List.append_back(&From->List);
+ addToSize(From->getSize());
+ atomic_store_relaxed(&From->Size, 0);
+ }
+
+ void enqueueBatch(QuarantineBatch *B) {
+ List.push_back(B);
+ addToSize(B->Size);
+ }
+
+ QuarantineBatch *dequeueBatch() {
+ if (List.empty())
+ return nullptr;
+ QuarantineBatch *B = List.front();
+ List.pop_front();
+ subFromSize(B->Size);
+ return B;
+ }
+
+ void mergeBatches(QuarantineCache *ToDeallocate) {
+ uptr ExtractedSize = 0;
+ QuarantineBatch *Current = List.front();
+ while (Current && Current->Next) {
+ if (Current->canMerge(Current->Next)) {
+ QuarantineBatch *Extracted = Current->Next;
+ // Move all the chunks into the current batch.
+ Current->merge(Extracted);
+ DCHECK_EQ(Extracted->Count, 0);
+ DCHECK_EQ(Extracted->Size, sizeof(QuarantineBatch));
+ // Remove the next batch From the list and account for its Size.
+ List.extract(Current, Extracted);
+ ExtractedSize += Extracted->Size;
+ // Add it to deallocation list.
+ ToDeallocate->enqueueBatch(Extracted);
+ } else {
+ Current = Current->Next;
+ }
+ }
+ subFromSize(ExtractedSize);
+ }
+
+ void getStats(ScopedString *Str) const {
+ uptr BatchCount = 0;
+ uptr TotalOverheadBytes = 0;
+ uptr TotalBytes = 0;
+ uptr TotalQuarantineChunks = 0;
+ for (const QuarantineBatch &Batch : List) {
+ BatchCount++;
+ TotalBytes += Batch.Size;
+ TotalOverheadBytes += Batch.Size - Batch.getQuarantinedSize();
+ TotalQuarantineChunks += Batch.Count;
+ }
+ const uptr QuarantineChunksCapacity =
+ BatchCount * QuarantineBatch::MaxCount;
+ const uptr ChunksUsagePercent =
+ (QuarantineChunksCapacity == 0)
+ ? 0
+ : TotalQuarantineChunks * 100 / QuarantineChunksCapacity;
+ const uptr TotalQuarantinedBytes = TotalBytes - TotalOverheadBytes;
+ const uptr MemoryOverheadPercent =
+ (TotalQuarantinedBytes == 0)
+ ? 0
+ : TotalOverheadBytes * 100 / TotalQuarantinedBytes;
+ Str->append(
+ "Stats: Quarantine: batches: %zu; bytes: %zu (user: %zu); chunks: %zu "
+ "(capacity: %zu); %zu%% chunks used; %zu%% memory overhead\n",
+ BatchCount, TotalBytes, TotalQuarantinedBytes, TotalQuarantineChunks,
+ QuarantineChunksCapacity, ChunksUsagePercent, MemoryOverheadPercent);
+ }
+
+private:
+ SinglyLinkedList<QuarantineBatch> List;
+ atomic_uptr Size = {};
+
+ void addToSize(uptr add) { atomic_store_relaxed(&Size, getSize() + add); }
+ void subFromSize(uptr sub) { atomic_store_relaxed(&Size, getSize() - sub); }
+};
+
+// The callback interface is:
+// void Callback::recycle(Node *Ptr);
+// void *Callback::allocate(uptr Size);
+// void Callback::deallocate(void *Ptr);
+template <typename Callback, typename Node> class GlobalQuarantine {
+public:
+ typedef QuarantineCache<Callback> CacheT;
+ using ThisT = GlobalQuarantine<Callback, Node>;
+
+ void init(uptr Size, uptr CacheSize) {
+ DCHECK(isAligned(reinterpret_cast<uptr>(this), alignof(ThisT)));
+ DCHECK_EQ(atomic_load_relaxed(&MaxSize), 0U);
+ DCHECK_EQ(atomic_load_relaxed(&MinSize), 0U);
+ DCHECK_EQ(atomic_load_relaxed(&MaxCacheSize), 0U);
+ // Thread local quarantine size can be zero only when global quarantine size
+ // is zero (it allows us to perform just one atomic read per put() call).
+ CHECK((Size == 0 && CacheSize == 0) || CacheSize != 0);
+
+ atomic_store_relaxed(&MaxSize, Size);
+ atomic_store_relaxed(&MinSize, Size / 10 * 9); // 90% of max size.
+ atomic_store_relaxed(&MaxCacheSize, CacheSize);
+
+ Cache.init();
+ }
+
+ uptr getMaxSize() const { return atomic_load_relaxed(&MaxSize); }
+ uptr getCacheSize() const { return atomic_load_relaxed(&MaxCacheSize); }
+
+ void put(CacheT *C, Callback Cb, Node *Ptr, uptr Size) {
+ C->enqueue(Cb, Ptr, Size);
+ if (C->getSize() > getCacheSize())
+ drain(C, Cb);
+ }
+
+ void NOINLINE drain(CacheT *C, Callback Cb) {
+ {
+ ScopedLock L(CacheMutex);
+ Cache.transfer(C);
+ }
+ if (Cache.getSize() > getMaxSize() && RecycleMutex.tryLock())
+ recycle(atomic_load_relaxed(&MinSize), Cb);
+ }
+
+ void NOINLINE drainAndRecycle(CacheT *C, Callback Cb) {
+ {
+ ScopedLock L(CacheMutex);
+ Cache.transfer(C);
+ }
+ RecycleMutex.lock();
+ recycle(0, Cb);
+ }
+
+ void getStats(ScopedString *Str) const {
+ // It assumes that the world is stopped, just as the allocator's printStats.
+ Cache.getStats(Str);
+ Str->append("Quarantine limits: global: %zuK; thread local: %zuK\n",
+ getMaxSize() >> 10, getCacheSize() >> 10);
+ }
+
+ void disable() {
+ // RecycleMutex must be locked 1st since we grab CacheMutex within recycle.
+ RecycleMutex.lock();
+ CacheMutex.lock();
+ }
+
+ void enable() {
+ CacheMutex.unlock();
+ RecycleMutex.unlock();
+ }
+
+private:
+ // Read-only data.
+ alignas(SCUDO_CACHE_LINE_SIZE) HybridMutex CacheMutex;
+ CacheT Cache;
+ alignas(SCUDO_CACHE_LINE_SIZE) HybridMutex RecycleMutex;
+ atomic_uptr MinSize = {};
+ atomic_uptr MaxSize = {};
+ alignas(SCUDO_CACHE_LINE_SIZE) atomic_uptr MaxCacheSize = {};
+
+ void NOINLINE recycle(uptr MinSize, Callback Cb) {
+ CacheT Tmp;
+ Tmp.init();
+ {
+ ScopedLock L(CacheMutex);
+ // Go over the batches and merge partially filled ones to
+ // save some memory, otherwise batches themselves (since the memory used
+ // by them is counted against quarantine limit) can overcome the actual
+ // user's quarantined chunks, which diminishes the purpose of the
+ // quarantine.
+ const uptr CacheSize = Cache.getSize();
+ const uptr OverheadSize = Cache.getOverheadSize();
+ DCHECK_GE(CacheSize, OverheadSize);
+ // Do the merge only when overhead exceeds this predefined limit (might
+ // require some tuning). It saves us merge attempt when the batch list
+ // quarantine is unlikely to contain batches suitable for merge.
+ constexpr uptr OverheadThresholdPercents = 100;
+ if (CacheSize > OverheadSize &&
+ OverheadSize * (100 + OverheadThresholdPercents) >
+ CacheSize * OverheadThresholdPercents) {
+ Cache.mergeBatches(&Tmp);
+ }
+ // Extract enough chunks from the quarantine to get below the max
+ // quarantine size and leave some leeway for the newly quarantined chunks.
+ while (Cache.getSize() > MinSize)
+ Tmp.enqueueBatch(Cache.dequeueBatch());
+ }
+ RecycleMutex.unlock();
+ doRecycle(&Tmp, Cb);
+ }
+
+ void NOINLINE doRecycle(CacheT *C, Callback Cb) {
+ while (QuarantineBatch *B = C->dequeueBatch()) {
+ const u32 Seed = static_cast<u32>(
+ (reinterpret_cast<uptr>(B) ^ reinterpret_cast<uptr>(C)) >> 4);
+ B->shuffle(Seed);
+ constexpr uptr NumberOfPrefetch = 8UL;
+ CHECK(NumberOfPrefetch <= ARRAY_SIZE(B->Batch));
+ for (uptr I = 0; I < NumberOfPrefetch; I++)
+ PREFETCH(B->Batch[I]);
+ for (uptr I = 0, Count = B->Count; I < Count; I++) {
+ if (I + NumberOfPrefetch < Count)
+ PREFETCH(B->Batch[I + NumberOfPrefetch]);
+ Cb.recycle(reinterpret_cast<Node *>(B->Batch[I]));
+ }
+ Cb.deallocate(B);
+ }
+ }
+};
+
+} // namespace scudo
+
+#endif // SCUDO_QUARANTINE_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/release.cpp b/contrib/libs/clang16-rt/lib/scudo/standalone/release.cpp
new file mode 100644
index 00000000000..3f40dbec6d7
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/release.cpp
@@ -0,0 +1,16 @@
+//===-- release.cpp ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "release.h"
+
+namespace scudo {
+
+HybridMutex RegionPageMap::Mutex = {};
+uptr RegionPageMap::StaticBuffer[RegionPageMap::StaticBufferCount];
+
+} // namespace scudo
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/release.h b/contrib/libs/clang16-rt/lib/scudo/standalone/release.h
new file mode 100644
index 00000000000..6de3b15534d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/release.h
@@ -0,0 +1,430 @@
+//===-- release.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_RELEASE_H_
+#define SCUDO_RELEASE_H_
+
+#include "common.h"
+#include "list.h"
+#include "mutex.h"
+
+namespace scudo {
+
+class ReleaseRecorder {
+public:
+ ReleaseRecorder(uptr Base, MapPlatformData *Data = nullptr)
+ : Base(Base), Data(Data) {}
+
+ uptr getReleasedRangesCount() const { return ReleasedRangesCount; }
+
+ uptr getReleasedBytes() const { return ReleasedBytes; }
+
+ uptr getBase() const { return Base; }
+
+ // Releases [From, To) range of pages back to OS.
+ void releasePageRangeToOS(uptr From, uptr To) {
+ const uptr Size = To - From;
+ releasePagesToOS(Base, From, Size, Data);
+ ReleasedRangesCount++;
+ ReleasedBytes += Size;
+ }
+
+private:
+ uptr ReleasedRangesCount = 0;
+ uptr ReleasedBytes = 0;
+ uptr Base = 0;
+ MapPlatformData *Data = nullptr;
+};
+
+// A Region page map is used to record the usage of pages in the regions. It
+// implements a packed array of Counters. Each counter occupies 2^N bits, enough
+// to store counter's MaxValue. Ctor will try to use a static buffer first, and
+// if that fails (the buffer is too small or already locked), will allocate the
+// required Buffer via map(). The caller is expected to check whether the
+// initialization was successful by checking isAllocated() result. For
+// performance sake, none of the accessors check the validity of the arguments,
+// It is assumed that Index is always in [0, N) range and the value is not
+// incremented past MaxValue.
+class RegionPageMap {
+public:
+ RegionPageMap()
+ : Regions(0),
+ NumCounters(0),
+ CounterSizeBitsLog(0),
+ CounterMask(0),
+ PackingRatioLog(0),
+ BitOffsetMask(0),
+ SizePerRegion(0),
+ BufferSize(0),
+ Buffer(nullptr) {}
+ RegionPageMap(uptr NumberOfRegions, uptr CountersPerRegion, uptr MaxValue) {
+ reset(NumberOfRegions, CountersPerRegion, MaxValue);
+ }
+ ~RegionPageMap() {
+ if (!isAllocated())
+ return;
+ if (Buffer == &StaticBuffer[0])
+ Mutex.unlock();
+ else
+ unmap(reinterpret_cast<void *>(Buffer),
+ roundUpTo(BufferSize, getPageSizeCached()));
+ Buffer = nullptr;
+ }
+
+ void reset(uptr NumberOfRegion, uptr CountersPerRegion, uptr MaxValue) {
+ DCHECK_GT(NumberOfRegion, 0);
+ DCHECK_GT(CountersPerRegion, 0);
+ DCHECK_GT(MaxValue, 0);
+
+ Regions = NumberOfRegion;
+ NumCounters = CountersPerRegion;
+
+ constexpr uptr MaxCounterBits = sizeof(*Buffer) * 8UL;
+ // Rounding counter storage size up to the power of two allows for using
+ // bit shifts calculating particular counter's Index and offset.
+ const uptr CounterSizeBits =
+ roundUpToPowerOfTwo(getMostSignificantSetBitIndex(MaxValue) + 1);
+ DCHECK_LE(CounterSizeBits, MaxCounterBits);
+ CounterSizeBitsLog = getLog2(CounterSizeBits);
+ CounterMask = ~(static_cast<uptr>(0)) >> (MaxCounterBits - CounterSizeBits);
+
+ const uptr PackingRatio = MaxCounterBits >> CounterSizeBitsLog;
+ DCHECK_GT(PackingRatio, 0);
+ PackingRatioLog = getLog2(PackingRatio);
+ BitOffsetMask = PackingRatio - 1;
+
+ SizePerRegion =
+ roundUpTo(NumCounters, static_cast<uptr>(1U) << PackingRatioLog) >>
+ PackingRatioLog;
+ BufferSize = SizePerRegion * sizeof(*Buffer) * Regions;
+ if (BufferSize <= (StaticBufferCount * sizeof(Buffer[0])) &&
+ Mutex.tryLock()) {
+ Buffer = &StaticBuffer[0];
+ memset(Buffer, 0, BufferSize);
+ } else {
+ // When using a heap-based buffer, precommit the pages backing the
+ // Vmar by passing |MAP_PRECOMMIT| flag. This allows an optimization
+ // where page fault exceptions are skipped as the allocated memory
+ // is accessed.
+ const uptr MmapFlags =
+ MAP_ALLOWNOMEM | (SCUDO_FUCHSIA ? MAP_PRECOMMIT : 0);
+ Buffer = reinterpret_cast<uptr *>(
+ map(nullptr, roundUpTo(BufferSize, getPageSizeCached()),
+ "scudo:counters", MmapFlags, &MapData));
+ }
+ }
+
+ bool isAllocated() const { return !!Buffer; }
+
+ uptr getCount() const { return NumCounters; }
+
+ uptr get(uptr Region, uptr I) const {
+ DCHECK_LT(Region, Regions);
+ DCHECK_LT(I, NumCounters);
+ const uptr Index = I >> PackingRatioLog;
+ const uptr BitOffset = (I & BitOffsetMask) << CounterSizeBitsLog;
+ return (Buffer[Region * SizePerRegion + Index] >> BitOffset) & CounterMask;
+ }
+
+ void inc(uptr Region, uptr I) const {
+ DCHECK_LT(get(Region, I), CounterMask);
+ const uptr Index = I >> PackingRatioLog;
+ const uptr BitOffset = (I & BitOffsetMask) << CounterSizeBitsLog;
+ DCHECK_LT(BitOffset, SCUDO_WORDSIZE);
+ DCHECK_EQ(isAllCounted(Region, I), false);
+ Buffer[Region * SizePerRegion + Index] += static_cast<uptr>(1U)
+ << BitOffset;
+ }
+
+ void incRange(uptr Region, uptr From, uptr To) const {
+ DCHECK_LE(From, To);
+ const uptr Top = Min(To + 1, NumCounters);
+ for (uptr I = From; I < Top; I++)
+ inc(Region, I);
+ }
+
+ // Set the counter to the max value. Note that the max number of blocks in a
+ // page may vary. To provide an easier way to tell if all the blocks are
+ // counted for different pages, set to the same max value to denote the
+ // all-counted status.
+ void setAsAllCounted(uptr Region, uptr I) const {
+ DCHECK_LE(get(Region, I), CounterMask);
+ const uptr Index = I >> PackingRatioLog;
+ const uptr BitOffset = (I & BitOffsetMask) << CounterSizeBitsLog;
+ DCHECK_LT(BitOffset, SCUDO_WORDSIZE);
+ Buffer[Region * SizePerRegion + Index] |= CounterMask << BitOffset;
+ }
+ bool isAllCounted(uptr Region, uptr I) const {
+ return get(Region, I) == CounterMask;
+ }
+
+ uptr getBufferSize() const { return BufferSize; }
+
+ static const uptr StaticBufferCount = 2048U;
+
+private:
+ uptr Regions;
+ uptr NumCounters;
+ uptr CounterSizeBitsLog;
+ uptr CounterMask;
+ uptr PackingRatioLog;
+ uptr BitOffsetMask;
+
+ uptr SizePerRegion;
+ uptr BufferSize;
+ uptr *Buffer;
+ [[no_unique_address]] MapPlatformData MapData = {};
+
+ static HybridMutex Mutex;
+ static uptr StaticBuffer[StaticBufferCount];
+};
+
+template <class ReleaseRecorderT> class FreePagesRangeTracker {
+public:
+ explicit FreePagesRangeTracker(ReleaseRecorderT &Recorder)
+ : Recorder(Recorder), PageSizeLog(getLog2(getPageSizeCached())) {}
+
+ void processNextPage(bool Released) {
+ if (Released) {
+ if (!InRange) {
+ CurrentRangeStatePage = CurrentPage;
+ InRange = true;
+ }
+ } else {
+ closeOpenedRange();
+ }
+ CurrentPage++;
+ }
+
+ void skipPages(uptr N) {
+ closeOpenedRange();
+ CurrentPage += N;
+ }
+
+ void finish() { closeOpenedRange(); }
+
+private:
+ void closeOpenedRange() {
+ if (InRange) {
+ Recorder.releasePageRangeToOS((CurrentRangeStatePage << PageSizeLog),
+ (CurrentPage << PageSizeLog));
+ InRange = false;
+ }
+ }
+
+ ReleaseRecorderT &Recorder;
+ const uptr PageSizeLog;
+ bool InRange = false;
+ uptr CurrentPage = 0;
+ uptr CurrentRangeStatePage = 0;
+};
+
+struct PageReleaseContext {
+ PageReleaseContext(uptr BlockSize, uptr RegionSize, uptr NumberOfRegions) :
+ BlockSize(BlockSize),
+ RegionSize(RegionSize),
+ NumberOfRegions(NumberOfRegions) {
+ PageSize = getPageSizeCached();
+ if (BlockSize <= PageSize) {
+ if (PageSize % BlockSize == 0) {
+ // Same number of chunks per page, no cross overs.
+ FullPagesBlockCountMax = PageSize / BlockSize;
+ SameBlockCountPerPage = true;
+ } else if (BlockSize % (PageSize % BlockSize) == 0) {
+ // Some chunks are crossing page boundaries, which means that the page
+ // contains one or two partial chunks, but all pages contain the same
+ // number of chunks.
+ FullPagesBlockCountMax = PageSize / BlockSize + 1;
+ SameBlockCountPerPage = true;
+ } else {
+ // Some chunks are crossing page boundaries, which means that the page
+ // contains one or two partial chunks.
+ FullPagesBlockCountMax = PageSize / BlockSize + 2;
+ SameBlockCountPerPage = false;
+ }
+ } else {
+ if (BlockSize % PageSize == 0) {
+ // One chunk covers multiple pages, no cross overs.
+ FullPagesBlockCountMax = 1;
+ SameBlockCountPerPage = true;
+ } else {
+ // One chunk covers multiple pages, Some chunks are crossing page
+ // boundaries. Some pages contain one chunk, some contain two.
+ FullPagesBlockCountMax = 2;
+ SameBlockCountPerPage = false;
+ }
+ }
+
+ PagesCount = roundUpTo(RegionSize, PageSize) / PageSize;
+ PageSizeLog = getLog2(PageSize);
+ RoundedRegionSize = PagesCount << PageSizeLog;
+ RoundedSize = NumberOfRegions * RoundedRegionSize;
+ }
+
+ // PageMap is lazily allocated when markFreeBlocks() is invoked.
+ bool hasBlockMarked() const {
+ return PageMap.isAllocated();
+ }
+
+ void ensurePageMapAllocated() {
+ if (PageMap.isAllocated())
+ return;
+ PageMap.reset(NumberOfRegions, PagesCount, FullPagesBlockCountMax);
+ DCHECK(PageMap.isAllocated());
+ }
+
+ template<class TransferBatchT, typename DecompactPtrT>
+ void markFreeBlocks(const IntrusiveList<TransferBatchT> &FreeList,
+ DecompactPtrT DecompactPtr, uptr Base) {
+ ensurePageMapAllocated();
+
+ // Iterate over free chunks and count how many free chunks affect each
+ // allocated page.
+ if (BlockSize <= PageSize && PageSize % BlockSize == 0) {
+ // Each chunk affects one page only.
+ for (const auto &It : FreeList) {
+ for (u16 I = 0; I < It.getCount(); I++) {
+ const uptr P = DecompactPtr(It.get(I)) - Base;
+ if (P >= RoundedSize)
+ continue;
+ const uptr RegionIndex = NumberOfRegions == 1U ? 0 : P / RegionSize;
+ const uptr PInRegion = P - RegionIndex * RegionSize;
+ PageMap.inc(RegionIndex, PInRegion >> PageSizeLog);
+ }
+ }
+ } else {
+ // In all other cases chunks might affect more than one page.
+ DCHECK_GE(RegionSize, BlockSize);
+ const uptr LastBlockInRegion =
+ ((RegionSize / BlockSize) - 1U) * BlockSize;
+ for (const auto &It : FreeList) {
+ for (u16 I = 0; I < It.getCount(); I++) {
+ const uptr P = DecompactPtr(It.get(I)) - Base;
+ if (P >= RoundedSize)
+ continue;
+ const uptr RegionIndex = NumberOfRegions == 1U ? 0 : P / RegionSize;
+ uptr PInRegion = P - RegionIndex * RegionSize;
+ PageMap.incRange(RegionIndex, PInRegion >> PageSizeLog,
+ (PInRegion + BlockSize - 1) >> PageSizeLog);
+ // The last block in a region might straddle a page, so if it's
+ // free, we mark the following "pretend" memory block(s) as free.
+ if (PInRegion == LastBlockInRegion) {
+ PInRegion += BlockSize;
+ while (PInRegion < RoundedRegionSize) {
+ PageMap.incRange(RegionIndex, PInRegion >> PageSizeLog,
+ (PInRegion + BlockSize - 1) >> PageSizeLog);
+ PInRegion += BlockSize;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ uptr BlockSize;
+ uptr RegionSize;
+ uptr NumberOfRegions;
+ uptr PageSize;
+ uptr PagesCount;
+ uptr PageSizeLog;
+ uptr RoundedRegionSize;
+ uptr RoundedSize;
+ uptr FullPagesBlockCountMax;
+ bool SameBlockCountPerPage;
+ RegionPageMap PageMap;
+};
+
+// Try to release the page which doesn't have any in-used block, i.e., they are
+// all free blocks. The `PageMap` will record the number of free blocks in each
+// page.
+template <class ReleaseRecorderT, typename SkipRegionT>
+NOINLINE void
+releaseFreeMemoryToOS(PageReleaseContext &Context,
+ ReleaseRecorderT &Recorder, SkipRegionT SkipRegion) {
+ const uptr PageSize = Context.PageSize;
+ const uptr BlockSize = Context.BlockSize;
+ const uptr PagesCount = Context.PagesCount;
+ const uptr NumberOfRegions = Context.NumberOfRegions;
+ const uptr FullPagesBlockCountMax = Context.FullPagesBlockCountMax;
+ const bool SameBlockCountPerPage = Context.SameBlockCountPerPage;
+ RegionPageMap &PageMap = Context.PageMap;
+
+ // Iterate over pages detecting ranges of pages with chunk Counters equal
+ // to the expected number of chunks for the particular page.
+ FreePagesRangeTracker<ReleaseRecorderT> RangeTracker(Recorder);
+ if (SameBlockCountPerPage) {
+ // Fast path, every page has the same number of chunks affecting it.
+ for (uptr I = 0; I < NumberOfRegions; I++) {
+ if (SkipRegion(I)) {
+ RangeTracker.skipPages(PagesCount);
+ continue;
+ }
+ for (uptr J = 0; J < PagesCount; J++) {
+ const bool CanRelease = PageMap.get(I, J) == FullPagesBlockCountMax;
+ if (CanRelease)
+ PageMap.setAsAllCounted(I, J);
+ RangeTracker.processNextPage(CanRelease);
+ }
+ }
+ } else {
+ // Slow path, go through the pages keeping count how many chunks affect
+ // each page.
+ const uptr Pn = BlockSize < PageSize ? PageSize / BlockSize : 1;
+ const uptr Pnc = Pn * BlockSize;
+ // The idea is to increment the current page pointer by the first chunk
+ // size, middle portion size (the portion of the page covered by chunks
+ // except the first and the last one) and then the last chunk size, adding
+ // up the number of chunks on the current page and checking on every step
+ // whether the page boundary was crossed.
+ for (uptr I = 0; I < NumberOfRegions; I++) {
+ if (SkipRegion(I)) {
+ RangeTracker.skipPages(PagesCount);
+ continue;
+ }
+ uptr PrevPageBoundary = 0;
+ uptr CurrentBoundary = 0;
+ for (uptr J = 0; J < PagesCount; J++) {
+ const uptr PageBoundary = PrevPageBoundary + PageSize;
+ uptr BlocksPerPage = Pn;
+ if (CurrentBoundary < PageBoundary) {
+ if (CurrentBoundary > PrevPageBoundary)
+ BlocksPerPage++;
+ CurrentBoundary += Pnc;
+ if (CurrentBoundary < PageBoundary) {
+ BlocksPerPage++;
+ CurrentBoundary += BlockSize;
+ }
+ }
+ PrevPageBoundary = PageBoundary;
+ const bool CanRelease = PageMap.get(I, J) == BlocksPerPage;
+ if (CanRelease)
+ PageMap.setAsAllCounted(I, J);
+ RangeTracker.processNextPage(CanRelease);
+ }
+ }
+ }
+ RangeTracker.finish();
+}
+
+// An overload releaseFreeMemoryToOS which doesn't require the page usage
+// information after releasing.
+template <class TransferBatchT, class ReleaseRecorderT, typename DecompactPtrT,
+ typename SkipRegionT>
+NOINLINE void
+releaseFreeMemoryToOS(const IntrusiveList<TransferBatchT> &FreeList,
+ uptr RegionSize, uptr NumberOfRegions, uptr BlockSize,
+ ReleaseRecorderT &Recorder, DecompactPtrT DecompactPtr,
+ SkipRegionT SkipRegion) {
+ PageReleaseContext Context(BlockSize, RegionSize, NumberOfRegions);
+ Context.markFreeBlocks(FreeList, DecompactPtr, Recorder.getBase());
+ releaseFreeMemoryToOS(Context, Recorder, SkipRegion);
+}
+
+} // namespace scudo
+
+#endif // SCUDO_RELEASE_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/report.cpp b/contrib/libs/clang16-rt/lib/scudo/standalone/report.cpp
new file mode 100644
index 00000000000..a37faacbb93
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/report.cpp
@@ -0,0 +1,204 @@
+//===-- report.cpp ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "report.h"
+
+#include "atomic_helpers.h"
+#include "string_utils.h"
+
+#include <stdarg.h>
+
+namespace scudo {
+
+class ScopedErrorReport {
+public:
+ ScopedErrorReport() : Message() { Message.append("Scudo ERROR: "); }
+ void append(const char *Format, ...) {
+ va_list Args;
+ va_start(Args, Format);
+ Message.append(Format, Args);
+ va_end(Args);
+ }
+ NORETURN ~ScopedErrorReport() {
+ outputRaw(Message.data());
+ setAbortMessage(Message.data());
+ die();
+ }
+
+private:
+ ScopedString Message;
+};
+
+inline void NORETURN trap() { __builtin_trap(); }
+
+void NORETURN reportSoftRSSLimit(uptr RssLimitMb) {
+ ScopedErrorReport Report;
+ Report.append("Soft RSS limit of %zu MB exhausted, current RSS is %zu MB\n",
+ RssLimitMb, GetRSS() >> 20);
+}
+
+void NORETURN reportHardRSSLimit(uptr RssLimitMb) {
+ ScopedErrorReport Report;
+ Report.append("Hard RSS limit of %zu MB exhausted, current RSS is %zu MB\n",
+ RssLimitMb, GetRSS() >> 20);
+}
+
+// This could potentially be called recursively if a CHECK fails in the reports.
+void NORETURN reportCheckFailed(const char *File, int Line,
+ const char *Condition, u64 Value1, u64 Value2) {
+ static atomic_u32 NumberOfCalls;
+ if (atomic_fetch_add(&NumberOfCalls, 1, memory_order_relaxed) > 2) {
+ // TODO(kostyak): maybe sleep here?
+ trap();
+ }
+ ScopedErrorReport Report;
+ Report.append("CHECK failed @ %s:%d %s ((u64)op1=%llu, (u64)op2=%llu)\n",
+ File, Line, Condition, Value1, Value2);
+}
+
+// Generic string fatal error message.
+void NORETURN reportError(const char *Message) {
+ ScopedErrorReport Report;
+ Report.append("%s\n", Message);
+}
+
+void NORETURN reportInvalidFlag(const char *FlagType, const char *Value) {
+ ScopedErrorReport Report;
+ Report.append("invalid value for %s option: '%s'\n", FlagType, Value);
+}
+
+// The checksum of a chunk header is invalid. This could be caused by an
+// {over,under}write of the header, a pointer that is not an actual chunk.
+void NORETURN reportHeaderCorruption(void *Ptr) {
+ ScopedErrorReport Report;
+ Report.append("corrupted chunk header at address %p\n", Ptr);
+}
+
+// Two threads have attempted to modify a chunk header at the same time. This is
+// symptomatic of a race-condition in the application code, or general lack of
+// proper locking.
+void NORETURN reportHeaderRace(void *Ptr) {
+ ScopedErrorReport Report;
+ Report.append("race on chunk header at address %p\n", Ptr);
+}
+
+// The allocator was compiled with parameters that conflict with field size
+// requirements.
+void NORETURN reportSanityCheckError(const char *Field) {
+ ScopedErrorReport Report;
+ Report.append("maximum possible %s doesn't fit in header\n", Field);
+}
+
+// We enforce a maximum alignment, to keep fields smaller and generally prevent
+// integer overflows, or unexpected corner cases.
+void NORETURN reportAlignmentTooBig(uptr Alignment, uptr MaxAlignment) {
+ ScopedErrorReport Report;
+ Report.append("invalid allocation alignment: %zu exceeds maximum supported "
+ "alignment of %zu\n",
+ Alignment, MaxAlignment);
+}
+
+// See above, we also enforce a maximum size.
+void NORETURN reportAllocationSizeTooBig(uptr UserSize, uptr TotalSize,
+ uptr MaxSize) {
+ ScopedErrorReport Report;
+ Report.append("requested allocation size %zu (%zu after adjustments) exceeds "
+ "maximum supported size of %zu\n",
+ UserSize, TotalSize, MaxSize);
+}
+
+void NORETURN reportOutOfMemory(uptr RequestedSize) {
+ ScopedErrorReport Report;
+ Report.append("out of memory trying to allocate %zu bytes\n", RequestedSize);
+}
+
+static const char *stringifyAction(AllocatorAction Action) {
+ switch (Action) {
+ case AllocatorAction::Recycling:
+ return "recycling";
+ case AllocatorAction::Deallocating:
+ return "deallocating";
+ case AllocatorAction::Reallocating:
+ return "reallocating";
+ case AllocatorAction::Sizing:
+ return "sizing";
+ }
+ return "<invalid action>";
+}
+
+// The chunk is not in a state congruent with the operation we want to perform.
+// This is usually the case with a double-free, a realloc of a freed pointer.
+void NORETURN reportInvalidChunkState(AllocatorAction Action, void *Ptr) {
+ ScopedErrorReport Report;
+ Report.append("invalid chunk state when %s address %p\n",
+ stringifyAction(Action), Ptr);
+}
+
+void NORETURN reportMisalignedPointer(AllocatorAction Action, void *Ptr) {
+ ScopedErrorReport Report;
+ Report.append("misaligned pointer when %s address %p\n",
+ stringifyAction(Action), Ptr);
+}
+
+// The deallocation function used is at odds with the one used to allocate the
+// chunk (eg: new[]/delete or malloc/delete, and so on).
+void NORETURN reportDeallocTypeMismatch(AllocatorAction Action, void *Ptr,
+ u8 TypeA, u8 TypeB) {
+ ScopedErrorReport Report;
+ Report.append("allocation type mismatch when %s address %p (%d vs %d)\n",
+ stringifyAction(Action), Ptr, TypeA, TypeB);
+}
+
+// The size specified to the delete operator does not match the one that was
+// passed to new when allocating the chunk.
+void NORETURN reportDeleteSizeMismatch(void *Ptr, uptr Size,
+ uptr ExpectedSize) {
+ ScopedErrorReport Report;
+ Report.append(
+ "invalid sized delete when deallocating address %p (%zu vs %zu)\n", Ptr,
+ Size, ExpectedSize);
+}
+
+void NORETURN reportAlignmentNotPowerOfTwo(uptr Alignment) {
+ ScopedErrorReport Report;
+ Report.append(
+ "invalid allocation alignment: %zu, alignment must be a power of two\n",
+ Alignment);
+}
+
+void NORETURN reportCallocOverflow(uptr Count, uptr Size) {
+ ScopedErrorReport Report;
+ Report.append("calloc parameters overflow: count * size (%zu * %zu) cannot "
+ "be represented with type size_t\n",
+ Count, Size);
+}
+
+void NORETURN reportInvalidPosixMemalignAlignment(uptr Alignment) {
+ ScopedErrorReport Report;
+ Report.append(
+ "invalid alignment requested in posix_memalign: %zu, alignment must be a "
+ "power of two and a multiple of sizeof(void *) == %zu\n",
+ Alignment, sizeof(void *));
+}
+
+void NORETURN reportPvallocOverflow(uptr Size) {
+ ScopedErrorReport Report;
+ Report.append("pvalloc parameters overflow: size %zu rounded up to system "
+ "page size %zu cannot be represented in type size_t\n",
+ Size, getPageSizeCached());
+}
+
+void NORETURN reportInvalidAlignedAllocAlignment(uptr Alignment, uptr Size) {
+ ScopedErrorReport Report;
+ Report.append("invalid alignment requested in aligned_alloc: %zu, alignment "
+ "must be a power of two and the requested size %zu must be a "
+ "multiple of alignment\n",
+ Alignment, Size);
+}
+
+} // namespace scudo
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/report.h b/contrib/libs/clang16-rt/lib/scudo/standalone/report.h
new file mode 100644
index 00000000000..d38451da098
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/report.h
@@ -0,0 +1,59 @@
+//===-- report.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_REPORT_H_
+#define SCUDO_REPORT_H_
+
+#include "internal_defs.h"
+
+namespace scudo {
+
+// Reports are *fatal* unless stated otherwise.
+
+// Generic error.
+void NORETURN reportError(const char *Message);
+
+// Flags related errors.
+void NORETURN reportInvalidFlag(const char *FlagType, const char *Value);
+
+// Chunk header related errors.
+void NORETURN reportHeaderCorruption(void *Ptr);
+void NORETURN reportHeaderRace(void *Ptr);
+
+// Sanity checks related error.
+void NORETURN reportSanityCheckError(const char *Field);
+
+// Combined allocator errors.
+void NORETURN reportAlignmentTooBig(uptr Alignment, uptr MaxAlignment);
+void NORETURN reportAllocationSizeTooBig(uptr UserSize, uptr TotalSize,
+ uptr MaxSize);
+void NORETURN reportOutOfMemory(uptr RequestedSize);
+void NORETURN reportSoftRSSLimit(uptr RssLimitMb);
+void NORETURN reportHardRSSLimit(uptr RssLimitMb);
+enum class AllocatorAction : u8 {
+ Recycling,
+ Deallocating,
+ Reallocating,
+ Sizing,
+};
+void NORETURN reportInvalidChunkState(AllocatorAction Action, void *Ptr);
+void NORETURN reportMisalignedPointer(AllocatorAction Action, void *Ptr);
+void NORETURN reportDeallocTypeMismatch(AllocatorAction Action, void *Ptr,
+ u8 TypeA, u8 TypeB);
+void NORETURN reportDeleteSizeMismatch(void *Ptr, uptr Size, uptr ExpectedSize);
+
+// C wrappers errors.
+void NORETURN reportAlignmentNotPowerOfTwo(uptr Alignment);
+void NORETURN reportInvalidPosixMemalignAlignment(uptr Alignment);
+void NORETURN reportCallocOverflow(uptr Count, uptr Size);
+void NORETURN reportPvallocOverflow(uptr Size);
+void NORETURN reportInvalidAlignedAllocAlignment(uptr Size, uptr Alignment);
+
+} // namespace scudo
+
+#endif // SCUDO_REPORT_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/rss_limit_checker.cpp b/contrib/libs/clang16-rt/lib/scudo/standalone/rss_limit_checker.cpp
new file mode 100644
index 00000000000..f428386b755
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/rss_limit_checker.cpp
@@ -0,0 +1,37 @@
+//===-- common.cpp ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "rss_limit_checker.h"
+#include "atomic_helpers.h"
+#include "string_utils.h"
+
+namespace scudo {
+
+void RssLimitChecker::check(u64 NextCheck) {
+ // The interval for the checks is 250ms.
+ static constexpr u64 CheckInterval = 250 * 1000000;
+
+ // Early return in case another thread already did the calculation.
+ if (!atomic_compare_exchange_strong(&RssNextCheckAtNS, &NextCheck,
+ getMonotonicTime() + CheckInterval,
+ memory_order_relaxed)) {
+ return;
+ }
+
+ const uptr CurrentRssMb = GetRSS() >> 20;
+
+ RssLimitExceeded Result = RssLimitExceeded::Neither;
+ if (UNLIKELY(HardRssLimitMb && HardRssLimitMb < CurrentRssMb))
+ Result = RssLimitExceeded::Hard;
+ else if (UNLIKELY(SoftRssLimitMb && SoftRssLimitMb < CurrentRssMb))
+ Result = RssLimitExceeded::Soft;
+
+ atomic_store_relaxed(&RssLimitStatus, static_cast<u8>(Result));
+}
+
+} // namespace scudo
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/rss_limit_checker.h b/contrib/libs/clang16-rt/lib/scudo/standalone/rss_limit_checker.h
new file mode 100644
index 00000000000..29dc063f3fc
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/rss_limit_checker.h
@@ -0,0 +1,63 @@
+//===-- common.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_RSS_LIMIT_CHECKER_H_
+#define SCUDO_RSS_LIMIT_CHECKER_H_
+
+#include "atomic_helpers.h"
+#include "common.h"
+#include "internal_defs.h"
+
+namespace scudo {
+
+class RssLimitChecker {
+public:
+ enum RssLimitExceeded {
+ Neither,
+ Soft,
+ Hard,
+ };
+
+ void init(int SoftRssLimitMb, int HardRssLimitMb) {
+ CHECK_GE(SoftRssLimitMb, 0);
+ CHECK_GE(HardRssLimitMb, 0);
+ this->SoftRssLimitMb = static_cast<uptr>(SoftRssLimitMb);
+ this->HardRssLimitMb = static_cast<uptr>(HardRssLimitMb);
+ }
+
+ // Opportunistic RSS limit check. This will update the RSS limit status, if
+ // it can, every 250ms, otherwise it will just return the current one.
+ RssLimitExceeded getRssLimitExceeded() {
+ if (!HardRssLimitMb && !SoftRssLimitMb)
+ return RssLimitExceeded::Neither;
+
+ u64 NextCheck = atomic_load_relaxed(&RssNextCheckAtNS);
+ u64 Now = getMonotonicTime();
+
+ if (UNLIKELY(Now >= NextCheck))
+ check(NextCheck);
+
+ return static_cast<RssLimitExceeded>(atomic_load_relaxed(&RssLimitStatus));
+ }
+
+ uptr getSoftRssLimit() const { return SoftRssLimitMb; }
+ uptr getHardRssLimit() const { return HardRssLimitMb; }
+
+private:
+ void check(u64 NextCheck);
+
+ uptr SoftRssLimitMb = 0;
+ uptr HardRssLimitMb = 0;
+
+ atomic_u64 RssNextCheckAtNS = {};
+ atomic_u8 RssLimitStatus = {};
+};
+
+} // namespace scudo
+
+#endif // SCUDO_RSS_LIMIT_CHECKER_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/secondary.h b/contrib/libs/clang16-rt/lib/scudo/standalone/secondary.h
new file mode 100644
index 00000000000..2d177576258
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/secondary.h
@@ -0,0 +1,628 @@
+//===-- secondary.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_SECONDARY_H_
+#define SCUDO_SECONDARY_H_
+
+#include "chunk.h"
+#include "common.h"
+#include "list.h"
+#include "memtag.h"
+#include "mutex.h"
+#include "options.h"
+#include "stats.h"
+#include "string_utils.h"
+
+namespace scudo {
+
+// This allocator wraps the platform allocation primitives, and as such is on
+// the slower side and should preferably be used for larger sized allocations.
+// Blocks allocated will be preceded and followed by a guard page, and hold
+// their own header that is not checksummed: the guard pages and the Combined
+// header should be enough for our purpose.
+
+namespace LargeBlock {
+
+struct alignas(Max<uptr>(archSupportsMemoryTagging()
+ ? archMemoryTagGranuleSize()
+ : 1,
+ 1U << SCUDO_MIN_ALIGNMENT_LOG)) Header {
+ LargeBlock::Header *Prev;
+ LargeBlock::Header *Next;
+ uptr CommitBase;
+ uptr CommitSize;
+ uptr MapBase;
+ uptr MapSize;
+ [[no_unique_address]] MapPlatformData Data;
+};
+
+static_assert(sizeof(Header) % (1U << SCUDO_MIN_ALIGNMENT_LOG) == 0, "");
+static_assert(!archSupportsMemoryTagging() ||
+ sizeof(Header) % archMemoryTagGranuleSize() == 0,
+ "");
+
+constexpr uptr getHeaderSize() { return sizeof(Header); }
+
+template <typename Config> static uptr addHeaderTag(uptr Ptr) {
+ if (allocatorSupportsMemoryTagging<Config>())
+ return addFixedTag(Ptr, 1);
+ return Ptr;
+}
+
+template <typename Config> static Header *getHeader(uptr Ptr) {
+ return reinterpret_cast<Header *>(addHeaderTag<Config>(Ptr)) - 1;
+}
+
+template <typename Config> static Header *getHeader(const void *Ptr) {
+ return getHeader<Config>(reinterpret_cast<uptr>(Ptr));
+}
+
+} // namespace LargeBlock
+
+static void unmap(LargeBlock::Header *H) {
+ MapPlatformData Data = H->Data;
+ unmap(reinterpret_cast<void *>(H->MapBase), H->MapSize, UNMAP_ALL, &Data);
+}
+
+class MapAllocatorNoCache {
+public:
+ void init(UNUSED s32 ReleaseToOsInterval) {}
+ bool retrieve(UNUSED Options Options, UNUSED uptr Size, UNUSED uptr Alignment,
+ UNUSED LargeBlock::Header **H, UNUSED bool *Zeroed) {
+ return false;
+ }
+ void store(UNUSED Options Options, LargeBlock::Header *H) { unmap(H); }
+ bool canCache(UNUSED uptr Size) { return false; }
+ void disable() {}
+ void enable() {}
+ void releaseToOS() {}
+ void disableMemoryTagging() {}
+ void unmapTestOnly() {}
+ bool setOption(Option O, UNUSED sptr Value) {
+ if (O == Option::ReleaseInterval || O == Option::MaxCacheEntriesCount ||
+ O == Option::MaxCacheEntrySize)
+ return false;
+ // Not supported by the Secondary Cache, but not an error either.
+ return true;
+ }
+};
+
+static const uptr MaxUnusedCachePages = 4U;
+
+template <typename Config>
+void mapSecondary(Options Options, uptr CommitBase, uptr CommitSize,
+ uptr AllocPos, uptr Flags, MapPlatformData *Data) {
+ const uptr MaxUnusedCacheBytes = MaxUnusedCachePages * getPageSizeCached();
+ if (useMemoryTagging<Config>(Options) && CommitSize > MaxUnusedCacheBytes) {
+ const uptr UntaggedPos = Max(AllocPos, CommitBase + MaxUnusedCacheBytes);
+ map(reinterpret_cast<void *>(CommitBase), UntaggedPos - CommitBase,
+ "scudo:secondary", MAP_RESIZABLE | MAP_MEMTAG | Flags, Data);
+ map(reinterpret_cast<void *>(UntaggedPos),
+ CommitBase + CommitSize - UntaggedPos, "scudo:secondary",
+ MAP_RESIZABLE | Flags, Data);
+ } else {
+ map(reinterpret_cast<void *>(CommitBase), CommitSize, "scudo:secondary",
+ MAP_RESIZABLE | (useMemoryTagging<Config>(Options) ? MAP_MEMTAG : 0) |
+ Flags,
+ Data);
+ }
+}
+
+// Template specialization to avoid producing zero-length array
+template <typename T, size_t Size> class NonZeroLengthArray {
+public:
+ T &operator[](uptr Idx) { return values[Idx]; }
+
+private:
+ T values[Size];
+};
+template <typename T> class NonZeroLengthArray<T, 0> {
+public:
+ T &operator[](uptr UNUSED Idx) { UNREACHABLE("Unsupported!"); }
+};
+
+template <typename Config> class MapAllocatorCache {
+public:
+ // Ensure the default maximum specified fits the array.
+ static_assert(Config::SecondaryCacheDefaultMaxEntriesCount <=
+ Config::SecondaryCacheEntriesArraySize,
+ "");
+
+ void init(s32 ReleaseToOsInterval) {
+ DCHECK_EQ(EntriesCount, 0U);
+ setOption(Option::MaxCacheEntriesCount,
+ static_cast<sptr>(Config::SecondaryCacheDefaultMaxEntriesCount));
+ setOption(Option::MaxCacheEntrySize,
+ static_cast<sptr>(Config::SecondaryCacheDefaultMaxEntrySize));
+ setOption(Option::ReleaseInterval, static_cast<sptr>(ReleaseToOsInterval));
+ }
+
+ void store(Options Options, LargeBlock::Header *H) {
+ if (!canCache(H->CommitSize))
+ return unmap(H);
+
+ bool EntryCached = false;
+ bool EmptyCache = false;
+ const s32 Interval = atomic_load_relaxed(&ReleaseToOsIntervalMs);
+ const u64 Time = getMonotonicTime();
+ const u32 MaxCount = atomic_load_relaxed(&MaxEntriesCount);
+ CachedBlock Entry;
+ Entry.CommitBase = H->CommitBase;
+ Entry.CommitSize = H->CommitSize;
+ Entry.MapBase = H->MapBase;
+ Entry.MapSize = H->MapSize;
+ Entry.BlockBegin = reinterpret_cast<uptr>(H + 1);
+ Entry.Data = H->Data;
+ Entry.Time = Time;
+ if (useMemoryTagging<Config>(Options)) {
+ if (Interval == 0 && !SCUDO_FUCHSIA) {
+ // Release the memory and make it inaccessible at the same time by
+ // creating a new MAP_NOACCESS mapping on top of the existing mapping.
+ // Fuchsia does not support replacing mappings by creating a new mapping
+ // on top so we just do the two syscalls there.
+ Entry.Time = 0;
+ mapSecondary<Config>(Options, Entry.CommitBase, Entry.CommitSize,
+ Entry.CommitBase, MAP_NOACCESS, &Entry.Data);
+ } else {
+ setMemoryPermission(Entry.CommitBase, Entry.CommitSize, MAP_NOACCESS,
+ &Entry.Data);
+ }
+ } else if (Interval == 0) {
+ releasePagesToOS(Entry.CommitBase, 0, Entry.CommitSize, &Entry.Data);
+ Entry.Time = 0;
+ }
+ do {
+ ScopedLock L(Mutex);
+ if (useMemoryTagging<Config>(Options) && QuarantinePos == -1U) {
+ // If we get here then memory tagging was disabled in between when we
+ // read Options and when we locked Mutex. We can't insert our entry into
+ // the quarantine or the cache because the permissions would be wrong so
+ // just unmap it.
+ break;
+ }
+ if (Config::SecondaryCacheQuarantineSize &&
+ useMemoryTagging<Config>(Options)) {
+ QuarantinePos =
+ (QuarantinePos + 1) % Max(Config::SecondaryCacheQuarantineSize, 1u);
+ if (!Quarantine[QuarantinePos].CommitBase) {
+ Quarantine[QuarantinePos] = Entry;
+ return;
+ }
+ CachedBlock PrevEntry = Quarantine[QuarantinePos];
+ Quarantine[QuarantinePos] = Entry;
+ if (OldestTime == 0)
+ OldestTime = Entry.Time;
+ Entry = PrevEntry;
+ }
+ if (EntriesCount >= MaxCount) {
+ if (IsFullEvents++ == 4U)
+ EmptyCache = true;
+ } else {
+ for (u32 I = 0; I < MaxCount; I++) {
+ if (Entries[I].CommitBase)
+ continue;
+ if (I != 0)
+ Entries[I] = Entries[0];
+ Entries[0] = Entry;
+ EntriesCount++;
+ if (OldestTime == 0)
+ OldestTime = Entry.Time;
+ EntryCached = true;
+ break;
+ }
+ }
+ } while (0);
+ if (EmptyCache)
+ empty();
+ else if (Interval >= 0)
+ releaseOlderThan(Time - static_cast<u64>(Interval) * 1000000);
+ if (!EntryCached)
+ unmap(reinterpret_cast<void *>(Entry.MapBase), Entry.MapSize, UNMAP_ALL,
+ &Entry.Data);
+ }
+
+ bool retrieve(Options Options, uptr Size, uptr Alignment,
+ LargeBlock::Header **H, bool *Zeroed) {
+ const uptr PageSize = getPageSizeCached();
+ const u32 MaxCount = atomic_load_relaxed(&MaxEntriesCount);
+ bool Found = false;
+ CachedBlock Entry;
+ uptr HeaderPos = 0;
+ {
+ ScopedLock L(Mutex);
+ if (EntriesCount == 0)
+ return false;
+ for (u32 I = 0; I < MaxCount; I++) {
+ const uptr CommitBase = Entries[I].CommitBase;
+ if (!CommitBase)
+ continue;
+ const uptr CommitSize = Entries[I].CommitSize;
+ const uptr AllocPos =
+ roundDownTo(CommitBase + CommitSize - Size, Alignment);
+ HeaderPos =
+ AllocPos - Chunk::getHeaderSize() - LargeBlock::getHeaderSize();
+ if (HeaderPos > CommitBase + CommitSize)
+ continue;
+ if (HeaderPos < CommitBase ||
+ AllocPos > CommitBase + PageSize * MaxUnusedCachePages)
+ continue;
+ Found = true;
+ Entry = Entries[I];
+ Entries[I].CommitBase = 0;
+ break;
+ }
+ }
+ if (Found) {
+ *H = reinterpret_cast<LargeBlock::Header *>(
+ LargeBlock::addHeaderTag<Config>(HeaderPos));
+ *Zeroed = Entry.Time == 0;
+ if (useMemoryTagging<Config>(Options))
+ setMemoryPermission(Entry.CommitBase, Entry.CommitSize, 0, &Entry.Data);
+ uptr NewBlockBegin = reinterpret_cast<uptr>(*H + 1);
+ if (useMemoryTagging<Config>(Options)) {
+ if (*Zeroed)
+ storeTags(LargeBlock::addHeaderTag<Config>(Entry.CommitBase),
+ NewBlockBegin);
+ else if (Entry.BlockBegin < NewBlockBegin)
+ storeTags(Entry.BlockBegin, NewBlockBegin);
+ else
+ storeTags(untagPointer(NewBlockBegin),
+ untagPointer(Entry.BlockBegin));
+ }
+ (*H)->CommitBase = Entry.CommitBase;
+ (*H)->CommitSize = Entry.CommitSize;
+ (*H)->MapBase = Entry.MapBase;
+ (*H)->MapSize = Entry.MapSize;
+ (*H)->Data = Entry.Data;
+ EntriesCount--;
+ }
+ return Found;
+ }
+
+ bool canCache(uptr Size) {
+ return atomic_load_relaxed(&MaxEntriesCount) != 0U &&
+ Size <= atomic_load_relaxed(&MaxEntrySize);
+ }
+
+ bool setOption(Option O, sptr Value) {
+ if (O == Option::ReleaseInterval) {
+ const s32 Interval =
+ Max(Min(static_cast<s32>(Value),
+ Config::SecondaryCacheMaxReleaseToOsIntervalMs),
+ Config::SecondaryCacheMinReleaseToOsIntervalMs);
+ atomic_store_relaxed(&ReleaseToOsIntervalMs, Interval);
+ return true;
+ }
+ if (O == Option::MaxCacheEntriesCount) {
+ const u32 MaxCount = static_cast<u32>(Value);
+ if (MaxCount > Config::SecondaryCacheEntriesArraySize)
+ return false;
+ atomic_store_relaxed(&MaxEntriesCount, MaxCount);
+ return true;
+ }
+ if (O == Option::MaxCacheEntrySize) {
+ atomic_store_relaxed(&MaxEntrySize, static_cast<uptr>(Value));
+ return true;
+ }
+ // Not supported by the Secondary Cache, but not an error either.
+ return true;
+ }
+
+ void releaseToOS() { releaseOlderThan(UINT64_MAX); }
+
+ void disableMemoryTagging() {
+ ScopedLock L(Mutex);
+ for (u32 I = 0; I != Config::SecondaryCacheQuarantineSize; ++I) {
+ if (Quarantine[I].CommitBase) {
+ unmap(reinterpret_cast<void *>(Quarantine[I].MapBase),
+ Quarantine[I].MapSize, UNMAP_ALL, &Quarantine[I].Data);
+ Quarantine[I].CommitBase = 0;
+ }
+ }
+ const u32 MaxCount = atomic_load_relaxed(&MaxEntriesCount);
+ for (u32 I = 0; I < MaxCount; I++)
+ if (Entries[I].CommitBase)
+ setMemoryPermission(Entries[I].CommitBase, Entries[I].CommitSize, 0,
+ &Entries[I].Data);
+ QuarantinePos = -1U;
+ }
+
+ void disable() { Mutex.lock(); }
+
+ void enable() { Mutex.unlock(); }
+
+ void unmapTestOnly() { empty(); }
+
+private:
+ void empty() {
+ struct {
+ void *MapBase;
+ uptr MapSize;
+ MapPlatformData Data;
+ } MapInfo[Config::SecondaryCacheEntriesArraySize];
+ uptr N = 0;
+ {
+ ScopedLock L(Mutex);
+ for (uptr I = 0; I < Config::SecondaryCacheEntriesArraySize; I++) {
+ if (!Entries[I].CommitBase)
+ continue;
+ MapInfo[N].MapBase = reinterpret_cast<void *>(Entries[I].MapBase);
+ MapInfo[N].MapSize = Entries[I].MapSize;
+ MapInfo[N].Data = Entries[I].Data;
+ Entries[I].CommitBase = 0;
+ N++;
+ }
+ EntriesCount = 0;
+ IsFullEvents = 0;
+ }
+ for (uptr I = 0; I < N; I++)
+ unmap(MapInfo[I].MapBase, MapInfo[I].MapSize, UNMAP_ALL,
+ &MapInfo[I].Data);
+ }
+
+ struct CachedBlock {
+ uptr CommitBase;
+ uptr CommitSize;
+ uptr MapBase;
+ uptr MapSize;
+ uptr BlockBegin;
+ [[no_unique_address]] MapPlatformData Data;
+ u64 Time;
+ };
+
+ void releaseIfOlderThan(CachedBlock &Entry, u64 Time) {
+ if (!Entry.CommitBase || !Entry.Time)
+ return;
+ if (Entry.Time > Time) {
+ if (OldestTime == 0 || Entry.Time < OldestTime)
+ OldestTime = Entry.Time;
+ return;
+ }
+ releasePagesToOS(Entry.CommitBase, 0, Entry.CommitSize, &Entry.Data);
+ Entry.Time = 0;
+ }
+
+ void releaseOlderThan(u64 Time) {
+ ScopedLock L(Mutex);
+ if (!EntriesCount || OldestTime == 0 || OldestTime > Time)
+ return;
+ OldestTime = 0;
+ for (uptr I = 0; I < Config::SecondaryCacheQuarantineSize; I++)
+ releaseIfOlderThan(Quarantine[I], Time);
+ for (uptr I = 0; I < Config::SecondaryCacheEntriesArraySize; I++)
+ releaseIfOlderThan(Entries[I], Time);
+ }
+
+ HybridMutex Mutex;
+ u32 EntriesCount = 0;
+ u32 QuarantinePos = 0;
+ atomic_u32 MaxEntriesCount = {};
+ atomic_uptr MaxEntrySize = {};
+ u64 OldestTime = 0;
+ u32 IsFullEvents = 0;
+ atomic_s32 ReleaseToOsIntervalMs = {};
+
+ CachedBlock Entries[Config::SecondaryCacheEntriesArraySize] = {};
+ NonZeroLengthArray<CachedBlock, Config::SecondaryCacheQuarantineSize>
+ Quarantine = {};
+};
+
+template <typename Config> class MapAllocator {
+public:
+ void init(GlobalStats *S, s32 ReleaseToOsInterval = -1) {
+ DCHECK_EQ(AllocatedBytes, 0U);
+ DCHECK_EQ(FreedBytes, 0U);
+ Cache.init(ReleaseToOsInterval);
+ Stats.init();
+ if (LIKELY(S))
+ S->link(&Stats);
+ }
+
+ void *allocate(Options Options, uptr Size, uptr AlignmentHint = 0,
+ uptr *BlockEnd = nullptr,
+ FillContentsMode FillContents = NoFill);
+
+ void deallocate(Options Options, void *Ptr);
+
+ static uptr getBlockEnd(void *Ptr) {
+ auto *B = LargeBlock::getHeader<Config>(Ptr);
+ return B->CommitBase + B->CommitSize;
+ }
+
+ static uptr getBlockSize(void *Ptr) {
+ return getBlockEnd(Ptr) - reinterpret_cast<uptr>(Ptr);
+ }
+
+ void getStats(ScopedString *Str) const;
+
+ void disable() {
+ Mutex.lock();
+ Cache.disable();
+ }
+
+ void enable() {
+ Cache.enable();
+ Mutex.unlock();
+ }
+
+ template <typename F> void iterateOverBlocks(F Callback) const {
+ for (const auto &H : InUseBlocks) {
+ uptr Ptr = reinterpret_cast<uptr>(&H) + LargeBlock::getHeaderSize();
+ if (allocatorSupportsMemoryTagging<Config>())
+ Ptr = untagPointer(Ptr);
+ Callback(Ptr);
+ }
+ }
+
+ bool canCache(uptr Size) { return Cache.canCache(Size); }
+
+ bool setOption(Option O, sptr Value) { return Cache.setOption(O, Value); }
+
+ void releaseToOS() { Cache.releaseToOS(); }
+
+ void disableMemoryTagging() { Cache.disableMemoryTagging(); }
+
+ void unmapTestOnly() { Cache.unmapTestOnly(); }
+
+private:
+ typename Config::SecondaryCache Cache;
+
+ HybridMutex Mutex;
+ DoublyLinkedList<LargeBlock::Header> InUseBlocks;
+ uptr AllocatedBytes = 0;
+ uptr FreedBytes = 0;
+ uptr LargestSize = 0;
+ u32 NumberOfAllocs = 0;
+ u32 NumberOfFrees = 0;
+ LocalStats Stats;
+};
+
+// As with the Primary, the size passed to this function includes any desired
+// alignment, so that the frontend can align the user allocation. The hint
+// parameter allows us to unmap spurious memory when dealing with larger
+// (greater than a page) alignments on 32-bit platforms.
+// Due to the sparsity of address space available on those platforms, requesting
+// an allocation from the Secondary with a large alignment would end up wasting
+// VA space (even though we are not committing the whole thing), hence the need
+// to trim off some of the reserved space.
+// For allocations requested with an alignment greater than or equal to a page,
+// the committed memory will amount to something close to Size - AlignmentHint
+// (pending rounding and headers).
+template <typename Config>
+void *MapAllocator<Config>::allocate(Options Options, uptr Size, uptr Alignment,
+ uptr *BlockEndPtr,
+ FillContentsMode FillContents) {
+ if (Options.get(OptionBit::AddLargeAllocationSlack))
+ Size += 1UL << SCUDO_MIN_ALIGNMENT_LOG;
+ Alignment = Max(Alignment, uptr(1U) << SCUDO_MIN_ALIGNMENT_LOG);
+ const uptr PageSize = getPageSizeCached();
+ uptr RoundedSize =
+ roundUpTo(roundUpTo(Size, Alignment) + LargeBlock::getHeaderSize() +
+ Chunk::getHeaderSize(),
+ PageSize);
+ if (Alignment > PageSize)
+ RoundedSize += Alignment - PageSize;
+
+ if (Alignment < PageSize && Cache.canCache(RoundedSize)) {
+ LargeBlock::Header *H;
+ bool Zeroed;
+ if (Cache.retrieve(Options, Size, Alignment, &H, &Zeroed)) {
+ const uptr BlockEnd = H->CommitBase + H->CommitSize;
+ if (BlockEndPtr)
+ *BlockEndPtr = BlockEnd;
+ uptr HInt = reinterpret_cast<uptr>(H);
+ if (allocatorSupportsMemoryTagging<Config>())
+ HInt = untagPointer(HInt);
+ const uptr PtrInt = HInt + LargeBlock::getHeaderSize();
+ void *Ptr = reinterpret_cast<void *>(PtrInt);
+ if (FillContents && !Zeroed)
+ memset(Ptr, FillContents == ZeroFill ? 0 : PatternFillByte,
+ BlockEnd - PtrInt);
+ const uptr BlockSize = BlockEnd - HInt;
+ {
+ ScopedLock L(Mutex);
+ InUseBlocks.push_back(H);
+ AllocatedBytes += BlockSize;
+ NumberOfAllocs++;
+ Stats.add(StatAllocated, BlockSize);
+ Stats.add(StatMapped, H->MapSize);
+ }
+ return Ptr;
+ }
+ }
+
+ MapPlatformData Data = {};
+ const uptr MapSize = RoundedSize + 2 * PageSize;
+ uptr MapBase = reinterpret_cast<uptr>(
+ map(nullptr, MapSize, nullptr, MAP_NOACCESS | MAP_ALLOWNOMEM, &Data));
+ if (UNLIKELY(!MapBase))
+ return nullptr;
+ uptr CommitBase = MapBase + PageSize;
+ uptr MapEnd = MapBase + MapSize;
+
+ // In the unlikely event of alignments larger than a page, adjust the amount
+ // of memory we want to commit, and trim the extra memory.
+ if (UNLIKELY(Alignment >= PageSize)) {
+ // For alignments greater than or equal to a page, the user pointer (eg: the
+ // pointer that is returned by the C or C++ allocation APIs) ends up on a
+ // page boundary , and our headers will live in the preceding page.
+ CommitBase = roundUpTo(MapBase + PageSize + 1, Alignment) - PageSize;
+ const uptr NewMapBase = CommitBase - PageSize;
+ DCHECK_GE(NewMapBase, MapBase);
+ // We only trim the extra memory on 32-bit platforms: 64-bit platforms
+ // are less constrained memory wise, and that saves us two syscalls.
+ if (SCUDO_WORDSIZE == 32U && NewMapBase != MapBase) {
+ unmap(reinterpret_cast<void *>(MapBase), NewMapBase - MapBase, 0, &Data);
+ MapBase = NewMapBase;
+ }
+ const uptr NewMapEnd =
+ CommitBase + PageSize + roundUpTo(Size, PageSize) + PageSize;
+ DCHECK_LE(NewMapEnd, MapEnd);
+ if (SCUDO_WORDSIZE == 32U && NewMapEnd != MapEnd) {
+ unmap(reinterpret_cast<void *>(NewMapEnd), MapEnd - NewMapEnd, 0, &Data);
+ MapEnd = NewMapEnd;
+ }
+ }
+
+ const uptr CommitSize = MapEnd - PageSize - CommitBase;
+ const uptr AllocPos = roundDownTo(CommitBase + CommitSize - Size, Alignment);
+ mapSecondary<Config>(Options, CommitBase, CommitSize, AllocPos, 0, &Data);
+ const uptr HeaderPos =
+ AllocPos - Chunk::getHeaderSize() - LargeBlock::getHeaderSize();
+ LargeBlock::Header *H = reinterpret_cast<LargeBlock::Header *>(
+ LargeBlock::addHeaderTag<Config>(HeaderPos));
+ if (useMemoryTagging<Config>(Options))
+ storeTags(LargeBlock::addHeaderTag<Config>(CommitBase),
+ reinterpret_cast<uptr>(H + 1));
+ H->MapBase = MapBase;
+ H->MapSize = MapEnd - MapBase;
+ H->CommitBase = CommitBase;
+ H->CommitSize = CommitSize;
+ H->Data = Data;
+ if (BlockEndPtr)
+ *BlockEndPtr = CommitBase + CommitSize;
+ {
+ ScopedLock L(Mutex);
+ InUseBlocks.push_back(H);
+ AllocatedBytes += CommitSize;
+ if (LargestSize < CommitSize)
+ LargestSize = CommitSize;
+ NumberOfAllocs++;
+ Stats.add(StatAllocated, CommitSize);
+ Stats.add(StatMapped, H->MapSize);
+ }
+ return reinterpret_cast<void *>(HeaderPos + LargeBlock::getHeaderSize());
+}
+
+template <typename Config>
+void MapAllocator<Config>::deallocate(Options Options, void *Ptr) {
+ LargeBlock::Header *H = LargeBlock::getHeader<Config>(Ptr);
+ const uptr CommitSize = H->CommitSize;
+ {
+ ScopedLock L(Mutex);
+ InUseBlocks.remove(H);
+ FreedBytes += CommitSize;
+ NumberOfFrees++;
+ Stats.sub(StatAllocated, CommitSize);
+ Stats.sub(StatMapped, H->MapSize);
+ }
+ Cache.store(Options, H);
+}
+
+template <typename Config>
+void MapAllocator<Config>::getStats(ScopedString *Str) const {
+ Str->append("Stats: MapAllocator: allocated %u times (%zuK), freed %u times "
+ "(%zuK), remains %u (%zuK) max %zuM\n",
+ NumberOfAllocs, AllocatedBytes >> 10, NumberOfFrees,
+ FreedBytes >> 10, NumberOfAllocs - NumberOfFrees,
+ (AllocatedBytes - FreedBytes) >> 10, LargestSize >> 20);
+}
+
+} // namespace scudo
+
+#endif // SCUDO_SECONDARY_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/size_class_map.h b/contrib/libs/clang16-rt/lib/scudo/standalone/size_class_map.h
new file mode 100644
index 00000000000..766562495ec
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/size_class_map.h
@@ -0,0 +1,377 @@
+//===-- size_class_map.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_SIZE_CLASS_MAP_H_
+#define SCUDO_SIZE_CLASS_MAP_H_
+
+#include "chunk.h"
+#include "common.h"
+#include "string_utils.h"
+
+namespace scudo {
+
+inline uptr scaledLog2(uptr Size, uptr ZeroLog, uptr LogBits) {
+ const uptr L = getMostSignificantSetBitIndex(Size);
+ const uptr LBits = (Size >> (L - LogBits)) - (1 << LogBits);
+ const uptr HBits = (L - ZeroLog) << LogBits;
+ return LBits + HBits;
+}
+
+template <typename Config> struct SizeClassMapBase {
+ static u16 getMaxCachedHint(uptr Size) {
+ DCHECK_NE(Size, 0);
+ u32 N;
+ // Force a 32-bit division if the template parameters allow for it.
+ if (Config::MaxBytesCachedLog > 31 || Config::MaxSizeLog > 31)
+ N = static_cast<u32>((1UL << Config::MaxBytesCachedLog) / Size);
+ else
+ N = (1U << Config::MaxBytesCachedLog) / static_cast<u32>(Size);
+
+ // Note that Config::MaxNumCachedHint is u16 so the result is guaranteed to
+ // fit in u16.
+ return static_cast<u16>(Max(1U, Min<u32>(Config::MaxNumCachedHint, N)));
+ }
+};
+
+// SizeClassMap maps allocation sizes into size classes and back, in an
+// efficient table-free manner.
+//
+// Class 0 is a special class that doesn't abide by the same rules as other
+// classes. The allocator uses it to hold batches.
+//
+// The other sizes are controlled by the template parameters:
+// - MinSizeLog: defines the first class as 2^MinSizeLog bytes.
+// - MaxSizeLog: defines the last class as 2^MaxSizeLog bytes.
+// - MidSizeLog: classes increase with step 2^MinSizeLog from 2^MinSizeLog to
+// 2^MidSizeLog bytes.
+// - NumBits: the number of non-zero bits in sizes after 2^MidSizeLog.
+// eg. with NumBits==3 all size classes after 2^MidSizeLog look like
+// 0b1xx0..0 (where x is either 0 or 1).
+//
+// This class also gives a hint to a thread-caching allocator about the amount
+// of chunks that can be cached per-thread:
+// - MaxNumCachedHint is a hint for the max number of chunks cached per class.
+// - 2^MaxBytesCachedLog is the max number of bytes cached per class.
+template <typename Config>
+class FixedSizeClassMap : public SizeClassMapBase<Config> {
+ typedef SizeClassMapBase<Config> Base;
+
+ static const uptr MinSize = 1UL << Config::MinSizeLog;
+ static const uptr MidSize = 1UL << Config::MidSizeLog;
+ static const uptr MidClass = MidSize / MinSize;
+ static const u8 S = Config::NumBits - 1;
+ static const uptr M = (1UL << S) - 1;
+
+public:
+ static const u16 MaxNumCachedHint = Config::MaxNumCachedHint;
+
+ static const uptr MaxSize = (1UL << Config::MaxSizeLog) + Config::SizeDelta;
+ static const uptr NumClasses =
+ MidClass + ((Config::MaxSizeLog - Config::MidSizeLog) << S) + 1;
+ static_assert(NumClasses <= 256, "");
+ static const uptr LargestClassId = NumClasses - 1;
+ static const uptr BatchClassId = 0;
+
+ static uptr getSizeByClassId(uptr ClassId) {
+ DCHECK_NE(ClassId, BatchClassId);
+ if (ClassId <= MidClass)
+ return (ClassId << Config::MinSizeLog) + Config::SizeDelta;
+ ClassId -= MidClass;
+ const uptr T = MidSize << (ClassId >> S);
+ return T + (T >> S) * (ClassId & M) + Config::SizeDelta;
+ }
+
+ static u8 getSizeLSBByClassId(uptr ClassId) {
+ return u8(getLeastSignificantSetBitIndex(getSizeByClassId(ClassId)));
+ }
+
+ static constexpr bool usesCompressedLSBFormat() { return false; }
+
+ static uptr getClassIdBySize(uptr Size) {
+ if (Size <= Config::SizeDelta + (1 << Config::MinSizeLog))
+ return 1;
+ Size -= Config::SizeDelta;
+ DCHECK_LE(Size, MaxSize);
+ if (Size <= MidSize)
+ return (Size + MinSize - 1) >> Config::MinSizeLog;
+ return MidClass + 1 + scaledLog2(Size - 1, Config::MidSizeLog, S);
+ }
+
+ static u16 getMaxCachedHint(uptr Size) {
+ DCHECK_LE(Size, MaxSize);
+ return Base::getMaxCachedHint(Size);
+ }
+};
+
+template <typename Config>
+class TableSizeClassMap : public SizeClassMapBase<Config> {
+ typedef SizeClassMapBase<Config> Base;
+
+ static const u8 S = Config::NumBits - 1;
+ static const uptr M = (1UL << S) - 1;
+ static const uptr ClassesSize =
+ sizeof(Config::Classes) / sizeof(Config::Classes[0]);
+
+ struct SizeTable {
+ constexpr SizeTable() {
+ uptr Pos = 1 << Config::MidSizeLog;
+ uptr Inc = 1 << (Config::MidSizeLog - S);
+ for (uptr i = 0; i != getTableSize(); ++i) {
+ Pos += Inc;
+ if ((Pos & (Pos - 1)) == 0)
+ Inc *= 2;
+ Tab[i] = computeClassId(Pos + Config::SizeDelta);
+ }
+ }
+
+ constexpr static u8 computeClassId(uptr Size) {
+ for (uptr i = 0; i != ClassesSize; ++i) {
+ if (Size <= Config::Classes[i])
+ return static_cast<u8>(i + 1);
+ }
+ return static_cast<u8>(-1);
+ }
+
+ constexpr static uptr getTableSize() {
+ return (Config::MaxSizeLog - Config::MidSizeLog) << S;
+ }
+
+ u8 Tab[getTableSize()] = {};
+ };
+
+ static constexpr SizeTable SzTable = {};
+
+ struct LSBTable {
+ constexpr LSBTable() {
+ u8 Min = 255, Max = 0;
+ for (uptr I = 0; I != ClassesSize; ++I) {
+ for (u8 Bit = 0; Bit != 64; ++Bit) {
+ if (Config::Classes[I] & (1 << Bit)) {
+ Tab[I] = Bit;
+ if (Bit < Min)
+ Min = Bit;
+ if (Bit > Max)
+ Max = Bit;
+ break;
+ }
+ }
+ }
+
+ if (Max - Min > 3 || ClassesSize > 32)
+ return;
+
+ UseCompressedFormat = true;
+ CompressedMin = Min;
+ for (uptr I = 0; I != ClassesSize; ++I)
+ CompressedValue |= u64(Tab[I] - Min) << (I * 2);
+ }
+
+ u8 Tab[ClassesSize] = {};
+
+ bool UseCompressedFormat = false;
+ u8 CompressedMin = 0;
+ u64 CompressedValue = 0;
+ };
+
+ static constexpr LSBTable LTable = {};
+
+public:
+ static const u16 MaxNumCachedHint = Config::MaxNumCachedHint;
+
+ static const uptr NumClasses = ClassesSize + 1;
+ static_assert(NumClasses < 256, "");
+ static const uptr LargestClassId = NumClasses - 1;
+ static const uptr BatchClassId = 0;
+ static const uptr MaxSize = Config::Classes[LargestClassId - 1];
+
+ static uptr getSizeByClassId(uptr ClassId) {
+ return Config::Classes[ClassId - 1];
+ }
+
+ static u8 getSizeLSBByClassId(uptr ClassId) {
+ if (LTable.UseCompressedFormat)
+ return ((LTable.CompressedValue >> ((ClassId - 1) * 2)) & 3) +
+ LTable.CompressedMin;
+ else
+ return LTable.Tab[ClassId - 1];
+ }
+
+ static constexpr bool usesCompressedLSBFormat() {
+ return LTable.UseCompressedFormat;
+ }
+
+ static uptr getClassIdBySize(uptr Size) {
+ if (Size <= Config::Classes[0])
+ return 1;
+ Size -= Config::SizeDelta;
+ DCHECK_LE(Size, MaxSize);
+ if (Size <= (1 << Config::MidSizeLog))
+ return ((Size - 1) >> Config::MinSizeLog) + 1;
+ return SzTable.Tab[scaledLog2(Size - 1, Config::MidSizeLog, S)];
+ }
+
+ static u16 getMaxCachedHint(uptr Size) {
+ DCHECK_LE(Size, MaxSize);
+ return Base::getMaxCachedHint(Size);
+ }
+};
+
+struct DefaultSizeClassConfig {
+ static const uptr NumBits = 3;
+ static const uptr MinSizeLog = 5;
+ static const uptr MidSizeLog = 8;
+ static const uptr MaxSizeLog = 17;
+ static const u16 MaxNumCachedHint = 14;
+ static const uptr MaxBytesCachedLog = 10;
+ static const uptr SizeDelta = 0;
+};
+
+typedef FixedSizeClassMap<DefaultSizeClassConfig> DefaultSizeClassMap;
+
+struct FuchsiaSizeClassConfig {
+ static const uptr NumBits = 3;
+ static const uptr MinSizeLog = 5;
+ static const uptr MidSizeLog = 8;
+ static const uptr MaxSizeLog = 17;
+ static const u16 MaxNumCachedHint = 12;
+ static const uptr MaxBytesCachedLog = 10;
+ static const uptr SizeDelta = Chunk::getHeaderSize();
+};
+
+typedef FixedSizeClassMap<FuchsiaSizeClassConfig> FuchsiaSizeClassMap;
+
+struct AndroidSizeClassConfig {
+#if SCUDO_WORDSIZE == 64U
+ static const uptr NumBits = 7;
+ static const uptr MinSizeLog = 4;
+ static const uptr MidSizeLog = 6;
+ static const uptr MaxSizeLog = 16;
+ static const u16 MaxNumCachedHint = 13;
+ static const uptr MaxBytesCachedLog = 13;
+
+ static constexpr u32 Classes[] = {
+ 0x00020, 0x00030, 0x00040, 0x00050, 0x00060, 0x00070, 0x00090, 0x000b0,
+ 0x000c0, 0x000e0, 0x00120, 0x00160, 0x001c0, 0x00250, 0x00320, 0x00450,
+ 0x00670, 0x00830, 0x00a10, 0x00c30, 0x01010, 0x01210, 0x01bd0, 0x02210,
+ 0x02d90, 0x03790, 0x04010, 0x04810, 0x05a10, 0x07310, 0x08210, 0x10010,
+ };
+ static const uptr SizeDelta = 16;
+#else
+ static const uptr NumBits = 8;
+ static const uptr MinSizeLog = 4;
+ static const uptr MidSizeLog = 7;
+ static const uptr MaxSizeLog = 16;
+ static const u16 MaxNumCachedHint = 14;
+ static const uptr MaxBytesCachedLog = 13;
+
+ static constexpr u32 Classes[] = {
+ 0x00020, 0x00030, 0x00040, 0x00050, 0x00060, 0x00070, 0x00080, 0x00090,
+ 0x000a0, 0x000b0, 0x000c0, 0x000e0, 0x000f0, 0x00110, 0x00120, 0x00130,
+ 0x00150, 0x00160, 0x00170, 0x00190, 0x001d0, 0x00210, 0x00240, 0x002a0,
+ 0x00330, 0x00370, 0x003a0, 0x00400, 0x00430, 0x004a0, 0x00530, 0x00610,
+ 0x00730, 0x00840, 0x00910, 0x009c0, 0x00a60, 0x00b10, 0x00ca0, 0x00e00,
+ 0x00fb0, 0x01030, 0x01130, 0x011f0, 0x01490, 0x01650, 0x01930, 0x02010,
+ 0x02190, 0x02490, 0x02850, 0x02d50, 0x03010, 0x03210, 0x03c90, 0x04090,
+ 0x04510, 0x04810, 0x05c10, 0x06f10, 0x07310, 0x08010, 0x0c010, 0x10010,
+ };
+ static const uptr SizeDelta = 16;
+#endif
+};
+
+typedef TableSizeClassMap<AndroidSizeClassConfig> AndroidSizeClassMap;
+
+#if SCUDO_WORDSIZE == 64U && defined(__clang__)
+static_assert(AndroidSizeClassMap::usesCompressedLSBFormat(), "");
+#endif
+
+struct SvelteSizeClassConfig {
+#if SCUDO_WORDSIZE == 64U
+ static const uptr NumBits = 4;
+ static const uptr MinSizeLog = 4;
+ static const uptr MidSizeLog = 8;
+ static const uptr MaxSizeLog = 14;
+ static const u16 MaxNumCachedHint = 13;
+ static const uptr MaxBytesCachedLog = 10;
+ static const uptr SizeDelta = Chunk::getHeaderSize();
+#else
+ static const uptr NumBits = 4;
+ static const uptr MinSizeLog = 3;
+ static const uptr MidSizeLog = 7;
+ static const uptr MaxSizeLog = 14;
+ static const u16 MaxNumCachedHint = 14;
+ static const uptr MaxBytesCachedLog = 10;
+ static const uptr SizeDelta = Chunk::getHeaderSize();
+#endif
+};
+
+typedef FixedSizeClassMap<SvelteSizeClassConfig> SvelteSizeClassMap;
+
+// Trusty is configured to only have one region containing blocks of size
+// 2^7 bytes.
+struct TrustySizeClassConfig {
+ static const uptr NumBits = 1;
+ static const uptr MinSizeLog = 7;
+ static const uptr MidSizeLog = 7;
+ static const uptr MaxSizeLog = 7;
+ static const u16 MaxNumCachedHint = 12;
+ static const uptr MaxBytesCachedLog = 10;
+ static const uptr SizeDelta = 0;
+};
+
+typedef FixedSizeClassMap<TrustySizeClassConfig> TrustySizeClassMap;
+
+template <typename SCMap> inline void printMap() {
+ ScopedString Buffer;
+ uptr PrevS = 0;
+ uptr TotalCached = 0;
+ for (uptr I = 0; I < SCMap::NumClasses; I++) {
+ if (I == SCMap::BatchClassId)
+ continue;
+ const uptr S = SCMap::getSizeByClassId(I);
+ const uptr D = S - PrevS;
+ const uptr P = PrevS ? (D * 100 / PrevS) : 0;
+ const uptr L = S ? getMostSignificantSetBitIndex(S) : 0;
+ const uptr Cached = SCMap::getMaxCachedHint(S) * S;
+ Buffer.append(
+ "C%02zu => S: %zu diff: +%zu %02zu%% L %zu Cached: %u %zu; id %zu\n", I,
+ S, D, P, L, SCMap::getMaxCachedHint(S), Cached,
+ SCMap::getClassIdBySize(S));
+ TotalCached += Cached;
+ PrevS = S;
+ }
+ Buffer.append("Total Cached: %zu\n", TotalCached);
+ Buffer.output();
+}
+
+template <typename SCMap> static UNUSED void validateMap() {
+ for (uptr C = 0; C < SCMap::NumClasses; C++) {
+ if (C == SCMap::BatchClassId)
+ continue;
+ const uptr S = SCMap::getSizeByClassId(C);
+ CHECK_NE(S, 0U);
+ CHECK_EQ(SCMap::getClassIdBySize(S), C);
+ if (C < SCMap::LargestClassId)
+ CHECK_EQ(SCMap::getClassIdBySize(S + 1), C + 1);
+ CHECK_EQ(SCMap::getClassIdBySize(S - 1), C);
+ if (C - 1 != SCMap::BatchClassId)
+ CHECK_GT(SCMap::getSizeByClassId(C), SCMap::getSizeByClassId(C - 1));
+ }
+ // Do not perform the loop if the maximum size is too large.
+ if (SCMap::MaxSize > (1 << 19))
+ return;
+ for (uptr S = 1; S <= SCMap::MaxSize; S++) {
+ const uptr C = SCMap::getClassIdBySize(S);
+ CHECK_LT(C, SCMap::NumClasses);
+ CHECK_GE(SCMap::getSizeByClassId(C), S);
+ if (C - 1 != SCMap::BatchClassId)
+ CHECK_LT(SCMap::getSizeByClassId(C - 1), S);
+ }
+}
+} // namespace scudo
+
+#endif // SCUDO_SIZE_CLASS_MAP_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/stack_depot.h b/contrib/libs/clang16-rt/lib/scudo/standalone/stack_depot.h
new file mode 100644
index 00000000000..458198fcb7a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/stack_depot.h
@@ -0,0 +1,144 @@
+//===-- stack_depot.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_STACK_DEPOT_H_
+#define SCUDO_STACK_DEPOT_H_
+
+#include "atomic_helpers.h"
+#include "mutex.h"
+
+namespace scudo {
+
+class MurMur2HashBuilder {
+ static const u32 M = 0x5bd1e995;
+ static const u32 Seed = 0x9747b28c;
+ static const u32 R = 24;
+ u32 H;
+
+public:
+ explicit MurMur2HashBuilder(u32 Init = 0) { H = Seed ^ Init; }
+ void add(u32 K) {
+ K *= M;
+ K ^= K >> R;
+ K *= M;
+ H *= M;
+ H ^= K;
+ }
+ u32 get() {
+ u32 X = H;
+ X ^= X >> 13;
+ X *= M;
+ X ^= X >> 15;
+ return X;
+ }
+};
+
+class StackDepot {
+ HybridMutex RingEndMu;
+ u32 RingEnd = 0;
+
+ // This data structure stores a stack trace for each allocation and
+ // deallocation when stack trace recording is enabled, that may be looked up
+ // using a hash of the stack trace. The lower bits of the hash are an index
+ // into the Tab array, which stores an index into the Ring array where the
+ // stack traces are stored. As the name implies, Ring is a ring buffer, so a
+ // stack trace may wrap around to the start of the array.
+ //
+ // Each stack trace in Ring is prefixed by a stack trace marker consisting of
+ // a fixed 1 bit in bit 0 (this allows disambiguation between stack frames
+ // and stack trace markers in the case where instruction pointers are 4-byte
+ // aligned, as they are on arm64), the stack trace hash in bits 1-32, and the
+ // size of the stack trace in bits 33-63.
+ //
+ // The insert() function is potentially racy in its accesses to the Tab and
+ // Ring arrays, but find() is resilient to races in the sense that, barring
+ // hash collisions, it will either return the correct stack trace or no stack
+ // trace at all, even if two instances of insert() raced with one another.
+ // This is achieved by re-checking the hash of the stack trace before
+ // returning the trace.
+
+#ifdef SCUDO_FUZZ
+ // Use smaller table sizes for fuzzing in order to reduce input size.
+ static const uptr TabBits = 4;
+#else
+ static const uptr TabBits = 16;
+#endif
+ static const uptr TabSize = 1 << TabBits;
+ static const uptr TabMask = TabSize - 1;
+ atomic_u32 Tab[TabSize] = {};
+
+#ifdef SCUDO_FUZZ
+ static const uptr RingBits = 4;
+#else
+ static const uptr RingBits = 19;
+#endif
+ static const uptr RingSize = 1 << RingBits;
+ static const uptr RingMask = RingSize - 1;
+ atomic_u64 Ring[RingSize] = {};
+
+public:
+ // Insert hash of the stack trace [Begin, End) into the stack depot, and
+ // return the hash.
+ u32 insert(uptr *Begin, uptr *End) {
+ MurMur2HashBuilder B;
+ for (uptr *I = Begin; I != End; ++I)
+ B.add(u32(*I) >> 2);
+ u32 Hash = B.get();
+
+ u32 Pos = Hash & TabMask;
+ u32 RingPos = atomic_load_relaxed(&Tab[Pos]);
+ u64 Entry = atomic_load_relaxed(&Ring[RingPos]);
+ u64 Id = (u64(End - Begin) << 33) | (u64(Hash) << 1) | 1;
+ if (Entry == Id)
+ return Hash;
+
+ ScopedLock Lock(RingEndMu);
+ RingPos = RingEnd;
+ atomic_store_relaxed(&Tab[Pos], RingPos);
+ atomic_store_relaxed(&Ring[RingPos], Id);
+ for (uptr *I = Begin; I != End; ++I) {
+ RingPos = (RingPos + 1) & RingMask;
+ atomic_store_relaxed(&Ring[RingPos], *I);
+ }
+ RingEnd = (RingPos + 1) & RingMask;
+ return Hash;
+ }
+
+ // Look up a stack trace by hash. Returns true if successful. The trace may be
+ // accessed via operator[] passing indexes between *RingPosPtr and
+ // *RingPosPtr + *SizePtr.
+ bool find(u32 Hash, uptr *RingPosPtr, uptr *SizePtr) const {
+ u32 Pos = Hash & TabMask;
+ u32 RingPos = atomic_load_relaxed(&Tab[Pos]);
+ if (RingPos >= RingSize)
+ return false;
+ u64 Entry = atomic_load_relaxed(&Ring[RingPos]);
+ u64 HashWithTagBit = (u64(Hash) << 1) | 1;
+ if ((Entry & 0x1ffffffff) != HashWithTagBit)
+ return false;
+ u32 Size = u32(Entry >> 33);
+ if (Size >= RingSize)
+ return false;
+ *RingPosPtr = (RingPos + 1) & RingMask;
+ *SizePtr = Size;
+ MurMur2HashBuilder B;
+ for (uptr I = 0; I != Size; ++I) {
+ RingPos = (RingPos + 1) & RingMask;
+ B.add(u32(atomic_load_relaxed(&Ring[RingPos])) >> 2);
+ }
+ return B.get() == Hash;
+ }
+
+ u64 operator[](uptr RingPos) const {
+ return atomic_load_relaxed(&Ring[RingPos & RingMask]);
+ }
+};
+
+} // namespace scudo
+
+#endif // SCUDO_STACK_DEPOT_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/stats.h b/contrib/libs/clang16-rt/lib/scudo/standalone/stats.h
new file mode 100644
index 00000000000..be5bf2d3720
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/stats.h
@@ -0,0 +1,101 @@
+//===-- stats.h -------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_STATS_H_
+#define SCUDO_STATS_H_
+
+#include "atomic_helpers.h"
+#include "list.h"
+#include "mutex.h"
+
+#include <string.h>
+
+namespace scudo {
+
+// Memory allocator statistics
+enum StatType { StatAllocated, StatFree, StatMapped, StatCount };
+
+typedef uptr StatCounters[StatCount];
+
+// Per-thread stats, live in per-thread cache. We use atomics so that the
+// numbers themselves are consistent. But we don't use atomic_{add|sub} or a
+// lock, because those are expensive operations , and we only care for the stats
+// to be "somewhat" correct: eg. if we call GlobalStats::get while a thread is
+// LocalStats::add'ing, this is OK, we will still get a meaningful number.
+class LocalStats {
+public:
+ void init() {
+ for (uptr I = 0; I < StatCount; I++)
+ DCHECK_EQ(get(static_cast<StatType>(I)), 0U);
+ }
+
+ void add(StatType I, uptr V) {
+ V += atomic_load_relaxed(&StatsArray[I]);
+ atomic_store_relaxed(&StatsArray[I], V);
+ }
+
+ void sub(StatType I, uptr V) {
+ V = atomic_load_relaxed(&StatsArray[I]) - V;
+ atomic_store_relaxed(&StatsArray[I], V);
+ }
+
+ void set(StatType I, uptr V) { atomic_store_relaxed(&StatsArray[I], V); }
+
+ uptr get(StatType I) const { return atomic_load_relaxed(&StatsArray[I]); }
+
+ LocalStats *Next = nullptr;
+ LocalStats *Prev = nullptr;
+
+private:
+ atomic_uptr StatsArray[StatCount] = {};
+};
+
+// Global stats, used for aggregation and querying.
+class GlobalStats : public LocalStats {
+public:
+ void init() { LocalStats::init(); }
+
+ void link(LocalStats *S) {
+ ScopedLock L(Mutex);
+ StatsList.push_back(S);
+ }
+
+ void unlink(LocalStats *S) {
+ ScopedLock L(Mutex);
+ StatsList.remove(S);
+ for (uptr I = 0; I < StatCount; I++)
+ add(static_cast<StatType>(I), S->get(static_cast<StatType>(I)));
+ }
+
+ void get(uptr *S) const {
+ ScopedLock L(Mutex);
+ for (uptr I = 0; I < StatCount; I++)
+ S[I] = LocalStats::get(static_cast<StatType>(I));
+ for (const auto &Stats : StatsList) {
+ for (uptr I = 0; I < StatCount; I++)
+ S[I] += Stats.get(static_cast<StatType>(I));
+ }
+ // All stats must be non-negative.
+ for (uptr I = 0; I < StatCount; I++)
+ S[I] = static_cast<sptr>(S[I]) >= 0 ? S[I] : 0;
+ }
+
+ void lock() { Mutex.lock(); }
+ void unlock() { Mutex.unlock(); }
+
+ void disable() { lock(); }
+ void enable() { unlock(); }
+
+private:
+ mutable HybridMutex Mutex;
+ DoublyLinkedList<LocalStats> StatsList;
+};
+
+} // namespace scudo
+
+#endif // SCUDO_STATS_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/string_utils.cpp b/contrib/libs/clang16-rt/lib/scudo/standalone/string_utils.cpp
new file mode 100644
index 00000000000..13fdb9c6ca6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/string_utils.cpp
@@ -0,0 +1,255 @@
+//===-- string_utils.cpp ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "string_utils.h"
+#include "common.h"
+
+#include <stdarg.h>
+#include <string.h>
+
+namespace scudo {
+
+static int appendChar(char **Buffer, const char *BufferEnd, char C) {
+ if (*Buffer < BufferEnd) {
+ **Buffer = C;
+ (*Buffer)++;
+ }
+ return 1;
+}
+
+// Appends number in a given Base to buffer. If its length is less than
+// |MinNumberLength|, it is padded with leading zeroes or spaces, depending
+// on the value of |PadWithZero|.
+static int appendNumber(char **Buffer, const char *BufferEnd, u64 AbsoluteValue,
+ u8 Base, u8 MinNumberLength, bool PadWithZero,
+ bool Negative, bool Upper) {
+ constexpr uptr MaxLen = 30;
+ RAW_CHECK(Base == 10 || Base == 16);
+ RAW_CHECK(Base == 10 || !Negative);
+ RAW_CHECK(AbsoluteValue || !Negative);
+ RAW_CHECK(MinNumberLength < MaxLen);
+ int Res = 0;
+ if (Negative && MinNumberLength)
+ --MinNumberLength;
+ if (Negative && PadWithZero)
+ Res += appendChar(Buffer, BufferEnd, '-');
+ uptr NumBuffer[MaxLen];
+ int Pos = 0;
+ do {
+ RAW_CHECK_MSG(static_cast<uptr>(Pos) < MaxLen,
+ "appendNumber buffer overflow");
+ NumBuffer[Pos++] = static_cast<uptr>(AbsoluteValue % Base);
+ AbsoluteValue /= Base;
+ } while (AbsoluteValue > 0);
+ if (Pos < MinNumberLength) {
+ memset(&NumBuffer[Pos], 0,
+ sizeof(NumBuffer[0]) * static_cast<uptr>(MinNumberLength - Pos));
+ Pos = MinNumberLength;
+ }
+ RAW_CHECK(Pos > 0);
+ Pos--;
+ for (; Pos >= 0 && NumBuffer[Pos] == 0; Pos--) {
+ char c = (PadWithZero || Pos == 0) ? '0' : ' ';
+ Res += appendChar(Buffer, BufferEnd, c);
+ }
+ if (Negative && !PadWithZero)
+ Res += appendChar(Buffer, BufferEnd, '-');
+ for (; Pos >= 0; Pos--) {
+ char Digit = static_cast<char>(NumBuffer[Pos]);
+ Digit = static_cast<char>((Digit < 10) ? '0' + Digit
+ : (Upper ? 'A' : 'a') + Digit - 10);
+ Res += appendChar(Buffer, BufferEnd, Digit);
+ }
+ return Res;
+}
+
+static int appendUnsigned(char **Buffer, const char *BufferEnd, u64 Num,
+ u8 Base, u8 MinNumberLength, bool PadWithZero,
+ bool Upper) {
+ return appendNumber(Buffer, BufferEnd, Num, Base, MinNumberLength,
+ PadWithZero, /*Negative=*/false, Upper);
+}
+
+static int appendSignedDecimal(char **Buffer, const char *BufferEnd, s64 Num,
+ u8 MinNumberLength, bool PadWithZero) {
+ const bool Negative = (Num < 0);
+ const u64 UnsignedNum = (Num == INT64_MIN)
+ ? static_cast<u64>(INT64_MAX) + 1
+ : static_cast<u64>(Negative ? -Num : Num);
+ return appendNumber(Buffer, BufferEnd, UnsignedNum, 10, MinNumberLength,
+ PadWithZero, Negative, /*Upper=*/false);
+}
+
+// Use the fact that explicitly requesting 0 Width (%0s) results in UB and
+// interpret Width == 0 as "no Width requested":
+// Width == 0 - no Width requested
+// Width < 0 - left-justify S within and pad it to -Width chars, if necessary
+// Width > 0 - right-justify S, not implemented yet
+static int appendString(char **Buffer, const char *BufferEnd, int Width,
+ int MaxChars, const char *S) {
+ if (!S)
+ S = "<null>";
+ int Res = 0;
+ for (; *S; S++) {
+ if (MaxChars >= 0 && Res >= MaxChars)
+ break;
+ Res += appendChar(Buffer, BufferEnd, *S);
+ }
+ // Only the left justified strings are supported.
+ while (Width < -Res)
+ Res += appendChar(Buffer, BufferEnd, ' ');
+ return Res;
+}
+
+static int appendPointer(char **Buffer, const char *BufferEnd, u64 ptr_value) {
+ int Res = 0;
+ Res += appendString(Buffer, BufferEnd, 0, -1, "0x");
+ Res += appendUnsigned(Buffer, BufferEnd, ptr_value, 16,
+ SCUDO_POINTER_FORMAT_LENGTH, /*PadWithZero=*/true,
+ /*Upper=*/false);
+ return Res;
+}
+
+static int formatString(char *Buffer, uptr BufferLength, const char *Format,
+ va_list Args) {
+ static const char *PrintfFormatsHelp =
+ "Supported formatString formats: %([0-9]*)?(z|ll)?{d,u,x,X}; %p; "
+ "%[-]([0-9]*)?(\\.\\*)?s; %c\n";
+ RAW_CHECK(Format);
+ RAW_CHECK(BufferLength > 0);
+ const char *BufferEnd = &Buffer[BufferLength - 1];
+ const char *Cur = Format;
+ int Res = 0;
+ for (; *Cur; Cur++) {
+ if (*Cur != '%') {
+ Res += appendChar(&Buffer, BufferEnd, *Cur);
+ continue;
+ }
+ Cur++;
+ const bool LeftJustified = *Cur == '-';
+ if (LeftJustified)
+ Cur++;
+ bool HaveWidth = (*Cur >= '0' && *Cur <= '9');
+ const bool PadWithZero = (*Cur == '0');
+ u8 Width = 0;
+ if (HaveWidth) {
+ while (*Cur >= '0' && *Cur <= '9')
+ Width = static_cast<u8>(Width * 10 + *Cur++ - '0');
+ }
+ const bool HavePrecision = (Cur[0] == '.' && Cur[1] == '*');
+ int Precision = -1;
+ if (HavePrecision) {
+ Cur += 2;
+ Precision = va_arg(Args, int);
+ }
+ const bool HaveZ = (*Cur == 'z');
+ Cur += HaveZ;
+ const bool HaveLL = !HaveZ && (Cur[0] == 'l' && Cur[1] == 'l');
+ Cur += HaveLL * 2;
+ s64 DVal;
+ u64 UVal;
+ const bool HaveLength = HaveZ || HaveLL;
+ const bool HaveFlags = HaveWidth || HaveLength;
+ // At the moment only %s supports precision and left-justification.
+ CHECK(!((Precision >= 0 || LeftJustified) && *Cur != 's'));
+ switch (*Cur) {
+ case 'd': {
+ DVal = HaveLL ? va_arg(Args, s64)
+ : HaveZ ? va_arg(Args, sptr)
+ : va_arg(Args, int);
+ Res += appendSignedDecimal(&Buffer, BufferEnd, DVal, Width, PadWithZero);
+ break;
+ }
+ case 'u':
+ case 'x':
+ case 'X': {
+ UVal = HaveLL ? va_arg(Args, u64)
+ : HaveZ ? va_arg(Args, uptr)
+ : va_arg(Args, unsigned);
+ const bool Upper = (*Cur == 'X');
+ Res += appendUnsigned(&Buffer, BufferEnd, UVal, (*Cur == 'u') ? 10 : 16,
+ Width, PadWithZero, Upper);
+ break;
+ }
+ case 'p': {
+ RAW_CHECK_MSG(!HaveFlags, PrintfFormatsHelp);
+ Res += appendPointer(&Buffer, BufferEnd, va_arg(Args, uptr));
+ break;
+ }
+ case 's': {
+ RAW_CHECK_MSG(!HaveLength, PrintfFormatsHelp);
+ // Only left-justified Width is supported.
+ CHECK(!HaveWidth || LeftJustified);
+ Res += appendString(&Buffer, BufferEnd, LeftJustified ? -Width : Width,
+ Precision, va_arg(Args, char *));
+ break;
+ }
+ case 'c': {
+ RAW_CHECK_MSG(!HaveFlags, PrintfFormatsHelp);
+ Res +=
+ appendChar(&Buffer, BufferEnd, static_cast<char>(va_arg(Args, int)));
+ break;
+ }
+ case '%': {
+ RAW_CHECK_MSG(!HaveFlags, PrintfFormatsHelp);
+ Res += appendChar(&Buffer, BufferEnd, '%');
+ break;
+ }
+ default: {
+ RAW_CHECK_MSG(false, PrintfFormatsHelp);
+ }
+ }
+ }
+ RAW_CHECK(Buffer <= BufferEnd);
+ appendChar(&Buffer, BufferEnd + 1, '\0');
+ return Res;
+}
+
+int formatString(char *Buffer, uptr BufferLength, const char *Format, ...) {
+ va_list Args;
+ va_start(Args, Format);
+ int Res = formatString(Buffer, BufferLength, Format, Args);
+ va_end(Args);
+ return Res;
+}
+
+void ScopedString::append(const char *Format, va_list Args) {
+ va_list ArgsCopy;
+ va_copy(ArgsCopy, Args);
+ // formatString doesn't currently support a null buffer or zero buffer length,
+ // so in order to get the resulting formatted string length, we use a one-char
+ // buffer.
+ char C[1];
+ const uptr AdditionalLength =
+ static_cast<uptr>(formatString(C, sizeof(C), Format, Args)) + 1;
+ const uptr Length = length();
+ String.resize(Length + AdditionalLength);
+ const uptr FormattedLength = static_cast<uptr>(formatString(
+ String.data() + Length, String.size() - Length, Format, ArgsCopy));
+ RAW_CHECK(data()[length()] == '\0');
+ RAW_CHECK(FormattedLength + 1 == AdditionalLength);
+ va_end(ArgsCopy);
+}
+
+void ScopedString::append(const char *Format, ...) {
+ va_list Args;
+ va_start(Args, Format);
+ append(Format, Args);
+ va_end(Args);
+}
+
+void Printf(const char *Format, ...) {
+ va_list Args;
+ va_start(Args, Format);
+ ScopedString Msg;
+ Msg.append(Format, Args);
+ outputRaw(Msg.data());
+ va_end(Args);
+}
+
+} // namespace scudo
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/string_utils.h b/contrib/libs/clang16-rt/lib/scudo/standalone/string_utils.h
new file mode 100644
index 00000000000..41901194dfd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/string_utils.h
@@ -0,0 +1,43 @@
+//===-- string_utils.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_STRING_UTILS_H_
+#define SCUDO_STRING_UTILS_H_
+
+#include "internal_defs.h"
+#include "vector.h"
+
+#include <stdarg.h>
+
+namespace scudo {
+
+class ScopedString {
+public:
+ explicit ScopedString() { String.push_back('\0'); }
+ uptr length() { return String.size() - 1; }
+ const char *data() { return String.data(); }
+ void clear() {
+ String.clear();
+ String.push_back('\0');
+ }
+ void append(const char *Format, va_list Args);
+ void append(const char *Format, ...) FORMAT(2, 3);
+ void output() const { outputRaw(String.data()); }
+ void reserve(size_t Size) { String.reserve(Size + 1); }
+
+private:
+ Vector<char> String;
+};
+
+int formatString(char *Buffer, uptr BufferLength, const char *Format, ...)
+ FORMAT(3, 4);
+void Printf(const char *Format, ...) FORMAT(1, 2);
+
+} // namespace scudo
+
+#endif // SCUDO_STRING_UTILS_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/trusty.h b/contrib/libs/clang16-rt/lib/scudo/standalone/trusty.h
new file mode 100644
index 00000000000..50edd1c6fe6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/trusty.h
@@ -0,0 +1,24 @@
+//===-- trusty.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_TRUSTY_H_
+#define SCUDO_TRUSTY_H_
+
+#include "platform.h"
+
+#if SCUDO_TRUSTY
+
+namespace scudo {
+// MapPlatformData is unused on Trusty, define it as a minimially sized
+// structure.
+struct MapPlatformData {};
+} // namespace scudo
+
+#endif // SCUDO_TRUSTY
+
+#endif // SCUDO_TRUSTY_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/tsd.h b/contrib/libs/clang16-rt/lib/scudo/standalone/tsd.h
new file mode 100644
index 00000000000..b400a3b56da
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/tsd.h
@@ -0,0 +1,66 @@
+//===-- tsd.h ---------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_TSD_H_
+#define SCUDO_TSD_H_
+
+#include "atomic_helpers.h"
+#include "common.h"
+#include "mutex.h"
+
+#include <limits.h> // for PTHREAD_DESTRUCTOR_ITERATIONS
+#include <pthread.h>
+
+// With some build setups, this might still not be defined.
+#ifndef PTHREAD_DESTRUCTOR_ITERATIONS
+#define PTHREAD_DESTRUCTOR_ITERATIONS 4
+#endif
+
+namespace scudo {
+
+template <class Allocator> struct alignas(SCUDO_CACHE_LINE_SIZE) TSD {
+ typename Allocator::CacheT Cache;
+ typename Allocator::QuarantineCacheT QuarantineCache;
+ using ThisT = TSD<Allocator>;
+ u8 DestructorIterations = 0;
+
+ void init(Allocator *Instance) {
+ DCHECK_EQ(DestructorIterations, 0U);
+ DCHECK(isAligned(reinterpret_cast<uptr>(this), alignof(ThisT)));
+ Instance->initCache(&Cache);
+ DestructorIterations = PTHREAD_DESTRUCTOR_ITERATIONS;
+ }
+
+ void commitBack(Allocator *Instance) { Instance->commitBack(this); }
+
+ inline bool tryLock() {
+ if (Mutex.tryLock()) {
+ atomic_store_relaxed(&Precedence, 0);
+ return true;
+ }
+ if (atomic_load_relaxed(&Precedence) == 0)
+ atomic_store_relaxed(
+ &Precedence,
+ static_cast<uptr>(getMonotonicTime() >> FIRST_32_SECOND_64(16, 0)));
+ return false;
+ }
+ inline void lock() {
+ atomic_store_relaxed(&Precedence, 0);
+ Mutex.lock();
+ }
+ inline void unlock() { Mutex.unlock(); }
+ inline uptr getPrecedence() { return atomic_load_relaxed(&Precedence); }
+
+private:
+ HybridMutex Mutex;
+ atomic_uptr Precedence = {};
+};
+
+} // namespace scudo
+
+#endif // SCUDO_TSD_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/tsd_exclusive.h b/contrib/libs/clang16-rt/lib/scudo/standalone/tsd_exclusive.h
new file mode 100644
index 00000000000..d49427b2005
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/tsd_exclusive.h
@@ -0,0 +1,152 @@
+//===-- tsd_exclusive.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_TSD_EXCLUSIVE_H_
+#define SCUDO_TSD_EXCLUSIVE_H_
+
+#include "tsd.h"
+
+namespace scudo {
+
+struct ThreadState {
+ bool DisableMemInit : 1;
+ enum : unsigned {
+ NotInitialized = 0,
+ Initialized,
+ TornDown,
+ } InitState : 2;
+};
+
+template <class Allocator> void teardownThread(void *Ptr);
+
+template <class Allocator> struct TSDRegistryExT {
+ void init(Allocator *Instance) {
+ DCHECK(!Initialized);
+ Instance->init();
+ CHECK_EQ(pthread_key_create(&PThreadKey, teardownThread<Allocator>), 0);
+ FallbackTSD.init(Instance);
+ Initialized = true;
+ }
+
+ void initOnceMaybe(Allocator *Instance) {
+ ScopedLock L(Mutex);
+ if (LIKELY(Initialized))
+ return;
+ init(Instance); // Sets Initialized.
+ }
+
+ void unmapTestOnly(Allocator *Instance) {
+ DCHECK(Instance);
+ if (reinterpret_cast<Allocator *>(pthread_getspecific(PThreadKey))) {
+ DCHECK_EQ(reinterpret_cast<Allocator *>(pthread_getspecific(PThreadKey)),
+ Instance);
+ ThreadTSD.commitBack(Instance);
+ ThreadTSD = {};
+ }
+ CHECK_EQ(pthread_key_delete(PThreadKey), 0);
+ PThreadKey = {};
+ FallbackTSD.commitBack(Instance);
+ FallbackTSD = {};
+ State = {};
+ Initialized = false;
+ }
+
+ ALWAYS_INLINE void initThreadMaybe(Allocator *Instance, bool MinimalInit) {
+ if (LIKELY(State.InitState != ThreadState::NotInitialized))
+ return;
+ initThread(Instance, MinimalInit);
+ }
+
+ ALWAYS_INLINE TSD<Allocator> *getTSDAndLock(bool *UnlockRequired) {
+ if (LIKELY(State.InitState == ThreadState::Initialized &&
+ !atomic_load(&Disabled, memory_order_acquire))) {
+ *UnlockRequired = false;
+ return &ThreadTSD;
+ }
+ FallbackTSD.lock();
+ *UnlockRequired = true;
+ return &FallbackTSD;
+ }
+
+ // To disable the exclusive TSD registry, we effectively lock the fallback TSD
+ // and force all threads to attempt to use it instead of their local one.
+ void disable() {
+ Mutex.lock();
+ FallbackTSD.lock();
+ atomic_store(&Disabled, 1U, memory_order_release);
+ }
+
+ void enable() {
+ atomic_store(&Disabled, 0U, memory_order_release);
+ FallbackTSD.unlock();
+ Mutex.unlock();
+ }
+
+ bool setOption(Option O, sptr Value) {
+ if (O == Option::ThreadDisableMemInit)
+ State.DisableMemInit = Value;
+ if (O == Option::MaxTSDsCount)
+ return false;
+ return true;
+ }
+
+ bool getDisableMemInit() { return State.DisableMemInit; }
+
+private:
+ // Using minimal initialization allows for global initialization while keeping
+ // the thread specific structure untouched. The fallback structure will be
+ // used instead.
+ NOINLINE void initThread(Allocator *Instance, bool MinimalInit) {
+ initOnceMaybe(Instance);
+ if (UNLIKELY(MinimalInit))
+ return;
+ CHECK_EQ(
+ pthread_setspecific(PThreadKey, reinterpret_cast<void *>(Instance)), 0);
+ ThreadTSD.init(Instance);
+ State.InitState = ThreadState::Initialized;
+ Instance->callPostInitCallback();
+ }
+
+ pthread_key_t PThreadKey = {};
+ bool Initialized = false;
+ atomic_u8 Disabled = {};
+ TSD<Allocator> FallbackTSD;
+ HybridMutex Mutex;
+ static thread_local ThreadState State;
+ static thread_local TSD<Allocator> ThreadTSD;
+
+ friend void teardownThread<Allocator>(void *Ptr);
+};
+
+template <class Allocator>
+thread_local TSD<Allocator> TSDRegistryExT<Allocator>::ThreadTSD;
+template <class Allocator>
+thread_local ThreadState TSDRegistryExT<Allocator>::State;
+
+template <class Allocator> void teardownThread(void *Ptr) {
+ typedef TSDRegistryExT<Allocator> TSDRegistryT;
+ Allocator *Instance = reinterpret_cast<Allocator *>(Ptr);
+ // The glibc POSIX thread-local-storage deallocation routine calls user
+ // provided destructors in a loop of PTHREAD_DESTRUCTOR_ITERATIONS.
+ // We want to be called last since other destructors might call free and the
+ // like, so we wait until PTHREAD_DESTRUCTOR_ITERATIONS before draining the
+ // quarantine and swallowing the cache.
+ if (TSDRegistryT::ThreadTSD.DestructorIterations > 1) {
+ TSDRegistryT::ThreadTSD.DestructorIterations--;
+ // If pthread_setspecific fails, we will go ahead with the teardown.
+ if (LIKELY(pthread_setspecific(Instance->getTSDRegistry()->PThreadKey,
+ Ptr) == 0))
+ return;
+ }
+ TSDRegistryT::ThreadTSD.commitBack(Instance);
+ TSDRegistryT::State.InitState = ThreadState::TornDown;
+}
+
+} // namespace scudo
+
+#endif // SCUDO_TSD_EXCLUSIVE_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/tsd_shared.h b/contrib/libs/clang16-rt/lib/scudo/standalone/tsd_shared.h
new file mode 100644
index 00000000000..4b3b1a07c12
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/tsd_shared.h
@@ -0,0 +1,216 @@
+//===-- tsd_shared.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_TSD_SHARED_H_
+#define SCUDO_TSD_SHARED_H_
+
+#include "tsd.h"
+
+#if SCUDO_HAS_PLATFORM_TLS_SLOT
+// This is a platform-provided header that needs to be on the include path when
+// Scudo is compiled. It must declare a function with the prototype:
+// uintptr_t *getPlatformAllocatorTlsSlot()
+// that returns the address of a thread-local word of storage reserved for
+// Scudo, that must be zero-initialized in newly created threads.
+#error #include "scudo_platform_tls_slot.h"
+#endif
+
+namespace scudo {
+
+template <class Allocator, u32 TSDsArraySize, u32 DefaultTSDCount>
+struct TSDRegistrySharedT {
+ void init(Allocator *Instance) {
+ DCHECK(!Initialized);
+ Instance->init();
+ for (u32 I = 0; I < TSDsArraySize; I++)
+ TSDs[I].init(Instance);
+ const u32 NumberOfCPUs = getNumberOfCPUs();
+ setNumberOfTSDs((NumberOfCPUs == 0) ? DefaultTSDCount
+ : Min(NumberOfCPUs, DefaultTSDCount));
+ Initialized = true;
+ }
+
+ void initOnceMaybe(Allocator *Instance) {
+ ScopedLock L(Mutex);
+ if (LIKELY(Initialized))
+ return;
+ init(Instance); // Sets Initialized.
+ }
+
+ void unmapTestOnly(Allocator *Instance) {
+ for (u32 I = 0; I < TSDsArraySize; I++) {
+ TSDs[I].commitBack(Instance);
+ TSDs[I] = {};
+ }
+ setCurrentTSD(nullptr);
+ Initialized = false;
+ }
+
+ ALWAYS_INLINE void initThreadMaybe(Allocator *Instance,
+ UNUSED bool MinimalInit) {
+ if (LIKELY(getCurrentTSD()))
+ return;
+ initThread(Instance);
+ }
+
+ ALWAYS_INLINE TSD<Allocator> *getTSDAndLock(bool *UnlockRequired) {
+ TSD<Allocator> *TSD = getCurrentTSD();
+ DCHECK(TSD);
+ *UnlockRequired = true;
+ // Try to lock the currently associated context.
+ if (TSD->tryLock())
+ return TSD;
+ // If that fails, go down the slow path.
+ if (TSDsArraySize == 1U) {
+ // Only 1 TSD, not need to go any further.
+ // The compiler will optimize this one way or the other.
+ TSD->lock();
+ return TSD;
+ }
+ return getTSDAndLockSlow(TSD);
+ }
+
+ void disable() {
+ Mutex.lock();
+ for (u32 I = 0; I < TSDsArraySize; I++)
+ TSDs[I].lock();
+ }
+
+ void enable() {
+ for (s32 I = static_cast<s32>(TSDsArraySize - 1); I >= 0; I--)
+ TSDs[I].unlock();
+ Mutex.unlock();
+ }
+
+ bool setOption(Option O, sptr Value) {
+ if (O == Option::MaxTSDsCount)
+ return setNumberOfTSDs(static_cast<u32>(Value));
+ if (O == Option::ThreadDisableMemInit)
+ setDisableMemInit(Value);
+ // Not supported by the TSD Registry, but not an error either.
+ return true;
+ }
+
+ bool getDisableMemInit() const { return *getTlsPtr() & 1; }
+
+private:
+ ALWAYS_INLINE uptr *getTlsPtr() const {
+#if SCUDO_HAS_PLATFORM_TLS_SLOT
+ return reinterpret_cast<uptr *>(getPlatformAllocatorTlsSlot());
+#else
+ static thread_local uptr ThreadTSD;
+ return &ThreadTSD;
+#endif
+ }
+
+ static_assert(alignof(TSD<Allocator>) >= 2, "");
+
+ ALWAYS_INLINE void setCurrentTSD(TSD<Allocator> *CurrentTSD) {
+ *getTlsPtr() &= 1;
+ *getTlsPtr() |= reinterpret_cast<uptr>(CurrentTSD);
+ }
+
+ ALWAYS_INLINE TSD<Allocator> *getCurrentTSD() {
+ return reinterpret_cast<TSD<Allocator> *>(*getTlsPtr() & ~1ULL);
+ }
+
+ bool setNumberOfTSDs(u32 N) {
+ ScopedLock L(MutexTSDs);
+ if (N < NumberOfTSDs)
+ return false;
+ if (N > TSDsArraySize)
+ N = TSDsArraySize;
+ NumberOfTSDs = N;
+ NumberOfCoPrimes = 0;
+ // Compute all the coprimes of NumberOfTSDs. This will be used to walk the
+ // array of TSDs in a random order. For details, see:
+ // https://lemire.me/blog/2017/09/18/visiting-all-values-in-an-array-exactly-once-in-random-order/
+ for (u32 I = 0; I < N; I++) {
+ u32 A = I + 1;
+ u32 B = N;
+ // Find the GCD between I + 1 and N. If 1, they are coprimes.
+ while (B != 0) {
+ const u32 T = A;
+ A = B;
+ B = T % B;
+ }
+ if (A == 1)
+ CoPrimes[NumberOfCoPrimes++] = I + 1;
+ }
+ return true;
+ }
+
+ void setDisableMemInit(bool B) {
+ *getTlsPtr() &= ~1ULL;
+ *getTlsPtr() |= B;
+ }
+
+ NOINLINE void initThread(Allocator *Instance) {
+ initOnceMaybe(Instance);
+ // Initial context assignment is done in a plain round-robin fashion.
+ const u32 Index = atomic_fetch_add(&CurrentIndex, 1U, memory_order_relaxed);
+ setCurrentTSD(&TSDs[Index % NumberOfTSDs]);
+ Instance->callPostInitCallback();
+ }
+
+ NOINLINE TSD<Allocator> *getTSDAndLockSlow(TSD<Allocator> *CurrentTSD) {
+ // Use the Precedence of the current TSD as our random seed. Since we are
+ // in the slow path, it means that tryLock failed, and as a result it's
+ // very likely that said Precedence is non-zero.
+ const u32 R = static_cast<u32>(CurrentTSD->getPrecedence());
+ u32 N, Inc;
+ {
+ ScopedLock L(MutexTSDs);
+ N = NumberOfTSDs;
+ DCHECK_NE(NumberOfCoPrimes, 0U);
+ Inc = CoPrimes[R % NumberOfCoPrimes];
+ }
+ if (N > 1U) {
+ u32 Index = R % N;
+ uptr LowestPrecedence = UINTPTR_MAX;
+ TSD<Allocator> *CandidateTSD = nullptr;
+ // Go randomly through at most 4 contexts and find a candidate.
+ for (u32 I = 0; I < Min(4U, N); I++) {
+ if (TSDs[Index].tryLock()) {
+ setCurrentTSD(&TSDs[Index]);
+ return &TSDs[Index];
+ }
+ const uptr Precedence = TSDs[Index].getPrecedence();
+ // A 0 precedence here means another thread just locked this TSD.
+ if (Precedence && Precedence < LowestPrecedence) {
+ CandidateTSD = &TSDs[Index];
+ LowestPrecedence = Precedence;
+ }
+ Index += Inc;
+ if (Index >= N)
+ Index -= N;
+ }
+ if (CandidateTSD) {
+ CandidateTSD->lock();
+ setCurrentTSD(CandidateTSD);
+ return CandidateTSD;
+ }
+ }
+ // Last resort, stick with the current one.
+ CurrentTSD->lock();
+ return CurrentTSD;
+ }
+
+ atomic_u32 CurrentIndex = {};
+ u32 NumberOfTSDs = 0;
+ u32 NumberOfCoPrimes = 0;
+ u32 CoPrimes[TSDsArraySize] = {};
+ bool Initialized = false;
+ HybridMutex Mutex;
+ HybridMutex MutexTSDs;
+ TSD<Allocator> TSDs[TSDsArraySize];
+};
+
+} // namespace scudo
+
+#endif // SCUDO_TSD_SHARED_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/vector.h b/contrib/libs/clang16-rt/lib/scudo/standalone/vector.h
new file mode 100644
index 00000000000..d43205a7111
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/vector.h
@@ -0,0 +1,118 @@
+//===-- vector.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_VECTOR_H_
+#define SCUDO_VECTOR_H_
+
+#include "common.h"
+
+#include <string.h>
+
+namespace scudo {
+
+// A low-level vector based on map. May incur a significant memory overhead for
+// small vectors. The current implementation supports only POD types.
+template <typename T> class VectorNoCtor {
+public:
+ constexpr void init(uptr InitialCapacity = 0) {
+ Data = &LocalData[0];
+ CapacityBytes = sizeof(LocalData);
+ if (InitialCapacity > capacity())
+ reserve(InitialCapacity);
+ }
+ void destroy() {
+ if (Data != &LocalData[0])
+ unmap(Data, CapacityBytes, 0, &MapData);
+ }
+ T &operator[](uptr I) {
+ DCHECK_LT(I, Size);
+ return Data[I];
+ }
+ const T &operator[](uptr I) const {
+ DCHECK_LT(I, Size);
+ return Data[I];
+ }
+ void push_back(const T &Element) {
+ DCHECK_LE(Size, capacity());
+ if (Size == capacity()) {
+ const uptr NewCapacity = roundUpToPowerOfTwo(Size + 1);
+ reallocate(NewCapacity);
+ }
+ memcpy(&Data[Size++], &Element, sizeof(T));
+ }
+ T &back() {
+ DCHECK_GT(Size, 0);
+ return Data[Size - 1];
+ }
+ void pop_back() {
+ DCHECK_GT(Size, 0);
+ Size--;
+ }
+ uptr size() const { return Size; }
+ const T *data() const { return Data; }
+ T *data() { return Data; }
+ constexpr uptr capacity() const { return CapacityBytes / sizeof(T); }
+ void reserve(uptr NewSize) {
+ // Never downsize internal buffer.
+ if (NewSize > capacity())
+ reallocate(NewSize);
+ }
+ void resize(uptr NewSize) {
+ if (NewSize > Size) {
+ reserve(NewSize);
+ memset(&Data[Size], 0, sizeof(T) * (NewSize - Size));
+ }
+ Size = NewSize;
+ }
+
+ void clear() { Size = 0; }
+ bool empty() const { return size() == 0; }
+
+ const T *begin() const { return data(); }
+ T *begin() { return data(); }
+ const T *end() const { return data() + size(); }
+ T *end() { return data() + size(); }
+
+private:
+ void reallocate(uptr NewCapacity) {
+ DCHECK_GT(NewCapacity, 0);
+ DCHECK_LE(Size, NewCapacity);
+ NewCapacity = roundUpTo(NewCapacity * sizeof(T), getPageSizeCached());
+ T *NewData = reinterpret_cast<T *>(
+ map(nullptr, NewCapacity, "scudo:vector", 0, &MapData));
+ memcpy(NewData, Data, Size * sizeof(T));
+ destroy();
+ Data = NewData;
+ CapacityBytes = NewCapacity;
+ }
+
+ T *Data = nullptr;
+ T LocalData[256 / sizeof(T)] = {};
+ uptr CapacityBytes = 0;
+ uptr Size = 0;
+ [[no_unique_address]] MapPlatformData MapData = {};
+};
+
+template <typename T> class Vector : public VectorNoCtor<T> {
+public:
+ constexpr Vector() { VectorNoCtor<T>::init(); }
+ explicit Vector(uptr Count) {
+ VectorNoCtor<T>::init(Count);
+ this->resize(Count);
+ }
+ ~Vector() { VectorNoCtor<T>::destroy(); }
+ // Disallow copies and moves.
+ Vector(const Vector &) = delete;
+ Vector &operator=(const Vector &) = delete;
+ Vector(Vector &&) = delete;
+ Vector &operator=(Vector &&) = delete;
+};
+
+} // namespace scudo
+
+#endif // SCUDO_VECTOR_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c.cpp b/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c.cpp
new file mode 100644
index 00000000000..b4d51be716c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c.cpp
@@ -0,0 +1,37 @@
+//===-- wrappers_c.cpp ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "platform.h"
+
+// Skip this compilation unit if compiled as part of Bionic.
+#if !SCUDO_ANDROID || !_BIONIC
+
+#include "allocator_config.h"
+#include "wrappers_c.h"
+#include "wrappers_c_checks.h"
+
+#include <stdint.h>
+#include <stdio.h>
+
+#define SCUDO_PREFIX(name) name
+#define SCUDO_ALLOCATOR Allocator
+
+// Export the static allocator so that the C++ wrappers can access it.
+// Technically we could have a completely separated heap for C & C++ but in
+// reality the amount of cross pollination between the two is staggering.
+SCUDO_REQUIRE_CONSTANT_INITIALIZATION
+scudo::Allocator<scudo::Config, SCUDO_PREFIX(malloc_postinit)> SCUDO_ALLOCATOR;
+
+#include "wrappers_c.inc"
+
+#undef SCUDO_ALLOCATOR
+#undef SCUDO_PREFIX
+
+extern "C" INTERFACE void __scudo_print_stats(void) { Allocator.printStats(); }
+
+#endif // !SCUDO_ANDROID || !_BIONIC
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c.h b/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c.h
new file mode 100644
index 00000000000..08dc679b34c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c.h
@@ -0,0 +1,62 @@
+//===-- wrappers_c.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_WRAPPERS_C_H_
+#define SCUDO_WRAPPERS_C_H_
+
+#include "platform.h"
+#include "stats.h"
+
+// Bionic's struct mallinfo consists of size_t (mallinfo(3) uses int).
+#if SCUDO_ANDROID
+typedef size_t __scudo_mallinfo_data_t;
+#else
+typedef int __scudo_mallinfo_data_t;
+#endif
+
+struct __scudo_mallinfo {
+ __scudo_mallinfo_data_t arena;
+ __scudo_mallinfo_data_t ordblks;
+ __scudo_mallinfo_data_t smblks;
+ __scudo_mallinfo_data_t hblks;
+ __scudo_mallinfo_data_t hblkhd;
+ __scudo_mallinfo_data_t usmblks;
+ __scudo_mallinfo_data_t fsmblks;
+ __scudo_mallinfo_data_t uordblks;
+ __scudo_mallinfo_data_t fordblks;
+ __scudo_mallinfo_data_t keepcost;
+};
+
+struct __scudo_mallinfo2 {
+ size_t arena;
+ size_t ordblks;
+ size_t smblks;
+ size_t hblks;
+ size_t hblkhd;
+ size_t usmblks;
+ size_t fsmblks;
+ size_t uordblks;
+ size_t fordblks;
+ size_t keepcost;
+};
+
+// Android sometimes includes malloc.h no matter what, which yields to
+// conflicting return types for mallinfo() if we use our own structure. So if
+// struct mallinfo is declared (#define courtesy of malloc.h), use it directly.
+#if STRUCT_MALLINFO_DECLARED
+#define SCUDO_MALLINFO mallinfo
+#else
+#define SCUDO_MALLINFO __scudo_mallinfo
+#endif
+
+#if !SCUDO_ANDROID || !_BIONIC
+extern "C" void malloc_postinit();
+extern HIDDEN scudo::Allocator<scudo::Config, malloc_postinit> Allocator;
+#endif
+
+#endif // SCUDO_WRAPPERS_C_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c.inc b/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c.inc
new file mode 100644
index 00000000000..bbe3617dd0d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c.inc
@@ -0,0 +1,288 @@
+//===-- wrappers_c.inc ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_PREFIX
+#error "Define SCUDO_PREFIX prior to including this file!"
+#endif
+
+// malloc-type functions have to be aligned to std::max_align_t. This is
+// distinct from (1U << SCUDO_MIN_ALIGNMENT_LOG), since C++ new-type functions
+// do not have to abide by the same requirement.
+#ifndef SCUDO_MALLOC_ALIGNMENT
+#define SCUDO_MALLOC_ALIGNMENT FIRST_32_SECOND_64(8U, 16U)
+#endif
+
+extern "C" {
+
+INTERFACE WEAK void *SCUDO_PREFIX(calloc)(size_t nmemb, size_t size) {
+ scudo::uptr Product;
+ if (UNLIKELY(scudo::checkForCallocOverflow(size, nmemb, &Product))) {
+ if (SCUDO_ALLOCATOR.canReturnNull()) {
+ errno = ENOMEM;
+ return nullptr;
+ }
+ scudo::reportCallocOverflow(nmemb, size);
+ }
+ return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
+ Product, scudo::Chunk::Origin::Malloc, SCUDO_MALLOC_ALIGNMENT, true));
+}
+
+INTERFACE WEAK void SCUDO_PREFIX(free)(void *ptr) {
+ SCUDO_ALLOCATOR.deallocate(ptr, scudo::Chunk::Origin::Malloc);
+}
+
+INTERFACE WEAK struct SCUDO_MALLINFO SCUDO_PREFIX(mallinfo)(void) {
+ struct SCUDO_MALLINFO Info = {};
+ scudo::StatCounters Stats;
+ SCUDO_ALLOCATOR.getStats(Stats);
+ // Space allocated in mmapped regions (bytes)
+ Info.hblkhd = static_cast<__scudo_mallinfo_data_t>(Stats[scudo::StatMapped]);
+ // Maximum total allocated space (bytes)
+ Info.usmblks = Info.hblkhd;
+ // Space in freed fastbin blocks (bytes)
+ Info.fsmblks = static_cast<__scudo_mallinfo_data_t>(Stats[scudo::StatFree]);
+ // Total allocated space (bytes)
+ Info.uordblks =
+ static_cast<__scudo_mallinfo_data_t>(Stats[scudo::StatAllocated]);
+ // Total free space (bytes)
+ Info.fordblks = Info.fsmblks;
+ return Info;
+}
+
+INTERFACE WEAK struct __scudo_mallinfo2 SCUDO_PREFIX(mallinfo2)(void) {
+ struct __scudo_mallinfo2 Info = {};
+ scudo::StatCounters Stats;
+ SCUDO_ALLOCATOR.getStats(Stats);
+ // Space allocated in mmapped regions (bytes)
+ Info.hblkhd = Stats[scudo::StatMapped];
+ // Maximum total allocated space (bytes)
+ Info.usmblks = Info.hblkhd;
+ // Space in freed fastbin blocks (bytes)
+ Info.fsmblks = Stats[scudo::StatFree];
+ // Total allocated space (bytes)
+ Info.uordblks = Stats[scudo::StatAllocated];
+ // Total free space (bytes)
+ Info.fordblks = Info.fsmblks;
+ return Info;
+}
+
+INTERFACE WEAK void *SCUDO_PREFIX(malloc)(size_t size) {
+ return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
+ size, scudo::Chunk::Origin::Malloc, SCUDO_MALLOC_ALIGNMENT));
+}
+
+#if SCUDO_ANDROID
+INTERFACE WEAK size_t SCUDO_PREFIX(malloc_usable_size)(const void *ptr) {
+#else
+INTERFACE WEAK size_t SCUDO_PREFIX(malloc_usable_size)(void *ptr) {
+#endif
+ return SCUDO_ALLOCATOR.getUsableSize(ptr);
+}
+
+INTERFACE WEAK void *SCUDO_PREFIX(memalign)(size_t alignment, size_t size) {
+ // Android rounds up the alignment to a power of two if it isn't one.
+ if (SCUDO_ANDROID) {
+ if (UNLIKELY(!alignment)) {
+ alignment = 1U;
+ } else {
+ if (UNLIKELY(!scudo::isPowerOfTwo(alignment)))
+ alignment = scudo::roundUpToPowerOfTwo(alignment);
+ }
+ } else {
+ if (UNLIKELY(!scudo::isPowerOfTwo(alignment))) {
+ if (SCUDO_ALLOCATOR.canReturnNull()) {
+ errno = EINVAL;
+ return nullptr;
+ }
+ scudo::reportAlignmentNotPowerOfTwo(alignment);
+ }
+ }
+ return SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign,
+ alignment);
+}
+
+INTERFACE WEAK int SCUDO_PREFIX(posix_memalign)(void **memptr, size_t alignment,
+ size_t size) {
+ if (UNLIKELY(scudo::checkPosixMemalignAlignment(alignment))) {
+ if (!SCUDO_ALLOCATOR.canReturnNull())
+ scudo::reportInvalidPosixMemalignAlignment(alignment);
+ return EINVAL;
+ }
+ void *Ptr =
+ SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign, alignment);
+ if (UNLIKELY(!Ptr))
+ return ENOMEM;
+ *memptr = Ptr;
+ return 0;
+}
+
+INTERFACE WEAK void *SCUDO_PREFIX(pvalloc)(size_t size) {
+ const scudo::uptr PageSize = scudo::getPageSizeCached();
+ if (UNLIKELY(scudo::checkForPvallocOverflow(size, PageSize))) {
+ if (SCUDO_ALLOCATOR.canReturnNull()) {
+ errno = ENOMEM;
+ return nullptr;
+ }
+ scudo::reportPvallocOverflow(size);
+ }
+ // pvalloc(0) should allocate one page.
+ return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
+ size ? scudo::roundUpTo(size, PageSize) : PageSize,
+ scudo::Chunk::Origin::Memalign, PageSize));
+}
+
+INTERFACE WEAK void *SCUDO_PREFIX(realloc)(void *ptr, size_t size) {
+ if (!ptr)
+ return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
+ size, scudo::Chunk::Origin::Malloc, SCUDO_MALLOC_ALIGNMENT));
+ if (size == 0) {
+ SCUDO_ALLOCATOR.deallocate(ptr, scudo::Chunk::Origin::Malloc);
+ return nullptr;
+ }
+ return scudo::setErrnoOnNull(
+ SCUDO_ALLOCATOR.reallocate(ptr, size, SCUDO_MALLOC_ALIGNMENT));
+}
+
+INTERFACE WEAK void *SCUDO_PREFIX(valloc)(size_t size) {
+ return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
+ size, scudo::Chunk::Origin::Memalign, scudo::getPageSizeCached()));
+}
+
+INTERFACE WEAK int SCUDO_PREFIX(malloc_iterate)(
+ uintptr_t base, size_t size,
+ void (*callback)(uintptr_t base, size_t size, void *arg), void *arg) {
+ SCUDO_ALLOCATOR.iterateOverChunks(base, size, callback, arg);
+ return 0;
+}
+
+INTERFACE WEAK void SCUDO_PREFIX(malloc_enable)() { SCUDO_ALLOCATOR.enable(); }
+
+INTERFACE WEAK void SCUDO_PREFIX(malloc_disable)() {
+ SCUDO_ALLOCATOR.disable();
+}
+
+void SCUDO_PREFIX(malloc_postinit)() {
+ SCUDO_ALLOCATOR.initGwpAsan();
+ pthread_atfork(SCUDO_PREFIX(malloc_disable), SCUDO_PREFIX(malloc_enable),
+ SCUDO_PREFIX(malloc_enable));
+}
+
+INTERFACE WEAK int SCUDO_PREFIX(mallopt)(int param, int value) {
+ if (param == M_DECAY_TIME) {
+ if (SCUDO_ANDROID) {
+ if (value == 0) {
+ // Will set the release values to their minimum values.
+ value = INT32_MIN;
+ } else {
+ // Will set the release values to their maximum values.
+ value = INT32_MAX;
+ }
+ }
+
+ SCUDO_ALLOCATOR.setOption(scudo::Option::ReleaseInterval,
+ static_cast<scudo::sptr>(value));
+ return 1;
+ } else if (param == M_PURGE) {
+ SCUDO_ALLOCATOR.releaseToOS();
+ return 1;
+ } else {
+ scudo::Option option;
+ switch (param) {
+ case M_MEMTAG_TUNING:
+ option = scudo::Option::MemtagTuning;
+ break;
+ case M_THREAD_DISABLE_MEM_INIT:
+ option = scudo::Option::ThreadDisableMemInit;
+ break;
+ case M_CACHE_COUNT_MAX:
+ option = scudo::Option::MaxCacheEntriesCount;
+ break;
+ case M_CACHE_SIZE_MAX:
+ option = scudo::Option::MaxCacheEntrySize;
+ break;
+ case M_TSDS_COUNT_MAX:
+ option = scudo::Option::MaxTSDsCount;
+ break;
+ default:
+ return 0;
+ }
+ return SCUDO_ALLOCATOR.setOption(option, static_cast<scudo::sptr>(value));
+ }
+}
+
+INTERFACE WEAK void *SCUDO_PREFIX(aligned_alloc)(size_t alignment,
+ size_t size) {
+ if (UNLIKELY(scudo::checkAlignedAllocAlignmentAndSize(alignment, size))) {
+ if (SCUDO_ALLOCATOR.canReturnNull()) {
+ errno = EINVAL;
+ return nullptr;
+ }
+ scudo::reportInvalidAlignedAllocAlignment(alignment, size);
+ }
+ return scudo::setErrnoOnNull(
+ SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Malloc, alignment));
+}
+
+INTERFACE WEAK int SCUDO_PREFIX(malloc_info)(UNUSED int options, FILE *stream) {
+ const scudo::uptr max_size =
+ decltype(SCUDO_ALLOCATOR)::PrimaryT::SizeClassMap::MaxSize;
+ auto *sizes = static_cast<scudo::uptr *>(
+ SCUDO_PREFIX(calloc)(max_size, sizeof(scudo::uptr)));
+ auto callback = [](uintptr_t, size_t size, void *arg) {
+ auto *sizes = reinterpret_cast<scudo::uptr *>(arg);
+ if (size < max_size)
+ sizes[size]++;
+ };
+ SCUDO_ALLOCATOR.iterateOverChunks(0, -1ul, callback, sizes);
+
+ fputs("<malloc version=\"scudo-1\">\n", stream);
+ for (scudo::uptr i = 0; i != max_size; ++i)
+ if (sizes[i])
+ fprintf(stream, "<alloc size=\"%zu\" count=\"%zu\"/>\n", i, sizes[i]);
+ fputs("</malloc>\n", stream);
+ SCUDO_PREFIX(free)(sizes);
+ return 0;
+}
+
+// Disable memory tagging for the heap. The caller must disable memory tag
+// checks globally (e.g. by clearing TCF0 on aarch64) before calling this
+// function, and may not re-enable them after calling the function.
+INTERFACE WEAK void SCUDO_PREFIX(malloc_disable_memory_tagging)() {
+ SCUDO_ALLOCATOR.disableMemoryTagging();
+}
+
+// Sets whether scudo records stack traces and other metadata for allocations
+// and deallocations. This function only has an effect if the allocator and
+// hardware support memory tagging.
+INTERFACE WEAK void
+SCUDO_PREFIX(malloc_set_track_allocation_stacks)(int track) {
+ SCUDO_ALLOCATOR.setTrackAllocationStacks(track);
+}
+
+// Sets whether scudo zero-initializes all allocated memory.
+INTERFACE WEAK void SCUDO_PREFIX(malloc_set_zero_contents)(int zero_contents) {
+ SCUDO_ALLOCATOR.setFillContents(zero_contents ? scudo::ZeroFill
+ : scudo::NoFill);
+}
+
+// Sets whether scudo pattern-initializes all allocated memory.
+INTERFACE WEAK void
+SCUDO_PREFIX(malloc_set_pattern_fill_contents)(int pattern_fill_contents) {
+ SCUDO_ALLOCATOR.setFillContents(
+ pattern_fill_contents ? scudo::PatternOrZeroFill : scudo::NoFill);
+}
+
+// Sets whether scudo adds a small amount of slack at the end of large
+// allocations, before the guard page. This can be enabled to work around buggy
+// applications that read a few bytes past the end of their allocation.
+INTERFACE WEAK void
+SCUDO_PREFIX(malloc_set_add_large_allocation_slack)(int add_slack) {
+ SCUDO_ALLOCATOR.setAddLargeAllocationSlack(add_slack);
+}
+
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c_checks.h b/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c_checks.h
new file mode 100644
index 00000000000..815d40023b6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_c_checks.h
@@ -0,0 +1,72 @@
+//===-- wrappers_c_checks.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_CHECKS_H_
+#define SCUDO_CHECKS_H_
+
+#include "common.h"
+
+#include <errno.h>
+
+#ifndef __has_builtin
+#define __has_builtin(X) 0
+#endif
+
+namespace scudo {
+
+// A common errno setting logic shared by almost all Scudo C wrappers.
+inline void *setErrnoOnNull(void *Ptr) {
+ if (UNLIKELY(!Ptr))
+ errno = ENOMEM;
+ return Ptr;
+}
+
+// Checks return true on failure.
+
+// Checks aligned_alloc() parameters, verifies that the alignment is a power of
+// two and that the size is a multiple of alignment.
+inline bool checkAlignedAllocAlignmentAndSize(uptr Alignment, uptr Size) {
+ return Alignment == 0 || !isPowerOfTwo(Alignment) ||
+ !isAligned(Size, Alignment);
+}
+
+// Checks posix_memalign() parameters, verifies that alignment is a power of two
+// and a multiple of sizeof(void *).
+inline bool checkPosixMemalignAlignment(uptr Alignment) {
+ return Alignment == 0 || !isPowerOfTwo(Alignment) ||
+ !isAligned(Alignment, sizeof(void *));
+}
+
+// Returns true if calloc(Size, N) overflows on Size*N calculation. Use a
+// builtin supported by recent clang & GCC if it exists, otherwise fallback to a
+// costly division.
+inline bool checkForCallocOverflow(uptr Size, uptr N, uptr *Product) {
+#if __has_builtin(__builtin_umull_overflow) && (SCUDO_WORDSIZE == 64U)
+ return __builtin_umull_overflow(Size, N,
+ reinterpret_cast<unsigned long *>(Product));
+#elif __has_builtin(__builtin_umul_overflow) && (SCUDO_WORDSIZE == 32U)
+ // On, e.g. armv7, uptr/uintptr_t may be defined as unsigned long
+ return __builtin_umul_overflow(Size, N,
+ reinterpret_cast<unsigned int *>(Product));
+#else
+ *Product = Size * N;
+ if (!Size)
+ return false;
+ return (*Product / Size) != N;
+#endif
+}
+
+// Returns true if the size passed to pvalloc overflows when rounded to the next
+// multiple of PageSize.
+inline bool checkForPvallocOverflow(uptr Size, uptr PageSize) {
+ return roundUpTo(Size, PageSize) < Size;
+}
+
+} // namespace scudo
+
+#endif // SCUDO_CHECKS_H_
diff --git a/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_cpp.cpp b/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_cpp.cpp
new file mode 100644
index 00000000000..374e36d72b3
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo/standalone/wrappers_cpp.cpp
@@ -0,0 +1,108 @@
+//===-- wrappers_cpp.cpp ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "platform.h"
+
+// Skip this compilation unit if compiled as part of Bionic.
+#if !SCUDO_ANDROID || !_BIONIC
+
+#include "allocator_config.h"
+#include "wrappers_c.h"
+
+#include <stdint.h>
+
+namespace std {
+struct nothrow_t {};
+enum class align_val_t : size_t {};
+} // namespace std
+
+INTERFACE WEAK void *operator new(size_t size) {
+ return Allocator.allocate(size, scudo::Chunk::Origin::New);
+}
+INTERFACE WEAK void *operator new[](size_t size) {
+ return Allocator.allocate(size, scudo::Chunk::Origin::NewArray);
+}
+INTERFACE WEAK void *operator new(size_t size,
+ std::nothrow_t const &) NOEXCEPT {
+ return Allocator.allocate(size, scudo::Chunk::Origin::New);
+}
+INTERFACE WEAK void *operator new[](size_t size,
+ std::nothrow_t const &) NOEXCEPT {
+ return Allocator.allocate(size, scudo::Chunk::Origin::NewArray);
+}
+INTERFACE WEAK void *operator new(size_t size, std::align_val_t align) {
+ return Allocator.allocate(size, scudo::Chunk::Origin::New,
+ static_cast<scudo::uptr>(align));
+}
+INTERFACE WEAK void *operator new[](size_t size, std::align_val_t align) {
+ return Allocator.allocate(size, scudo::Chunk::Origin::NewArray,
+ static_cast<scudo::uptr>(align));
+}
+INTERFACE WEAK void *operator new(size_t size, std::align_val_t align,
+ std::nothrow_t const &) NOEXCEPT {
+ return Allocator.allocate(size, scudo::Chunk::Origin::New,
+ static_cast<scudo::uptr>(align));
+}
+INTERFACE WEAK void *operator new[](size_t size, std::align_val_t align,
+ std::nothrow_t const &) NOEXCEPT {
+ return Allocator.allocate(size, scudo::Chunk::Origin::NewArray,
+ static_cast<scudo::uptr>(align));
+}
+
+INTERFACE WEAK void operator delete(void *ptr) NOEXCEPT {
+ Allocator.deallocate(ptr, scudo::Chunk::Origin::New);
+}
+INTERFACE WEAK void operator delete[](void *ptr) NOEXCEPT {
+ Allocator.deallocate(ptr, scudo::Chunk::Origin::NewArray);
+}
+INTERFACE WEAK void operator delete(void *ptr,
+ std::nothrow_t const &) NOEXCEPT {
+ Allocator.deallocate(ptr, scudo::Chunk::Origin::New);
+}
+INTERFACE WEAK void operator delete[](void *ptr,
+ std::nothrow_t const &) NOEXCEPT {
+ Allocator.deallocate(ptr, scudo::Chunk::Origin::NewArray);
+}
+INTERFACE WEAK void operator delete(void *ptr, size_t size) NOEXCEPT {
+ Allocator.deallocate(ptr, scudo::Chunk::Origin::New, size);
+}
+INTERFACE WEAK void operator delete[](void *ptr, size_t size) NOEXCEPT {
+ Allocator.deallocate(ptr, scudo::Chunk::Origin::NewArray, size);
+}
+INTERFACE WEAK void operator delete(void *ptr,
+ std::align_val_t align) NOEXCEPT {
+ Allocator.deallocate(ptr, scudo::Chunk::Origin::New, 0,
+ static_cast<scudo::uptr>(align));
+}
+INTERFACE WEAK void operator delete[](void *ptr,
+ std::align_val_t align) NOEXCEPT {
+ Allocator.deallocate(ptr, scudo::Chunk::Origin::NewArray, 0,
+ static_cast<scudo::uptr>(align));
+}
+INTERFACE WEAK void operator delete(void *ptr, std::align_val_t align,
+ std::nothrow_t const &) NOEXCEPT {
+ Allocator.deallocate(ptr, scudo::Chunk::Origin::New, 0,
+ static_cast<scudo::uptr>(align));
+}
+INTERFACE WEAK void operator delete[](void *ptr, std::align_val_t align,
+ std::nothrow_t const &) NOEXCEPT {
+ Allocator.deallocate(ptr, scudo::Chunk::Origin::NewArray, 0,
+ static_cast<scudo::uptr>(align));
+}
+INTERFACE WEAK void operator delete(void *ptr, size_t size,
+ std::align_val_t align) NOEXCEPT {
+ Allocator.deallocate(ptr, scudo::Chunk::Origin::New, size,
+ static_cast<scudo::uptr>(align));
+}
+INTERFACE WEAK void operator delete[](void *ptr, size_t size,
+ std::align_val_t align) NOEXCEPT {
+ Allocator.deallocate(ptr, scudo::Chunk::Origin::NewArray, size,
+ static_cast<scudo::uptr>(align));
+}
+
+#endif // !SCUDO_ANDROID || !_BIONIC
diff --git a/contrib/libs/clang16-rt/lib/scudo_standalone/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/scudo_standalone/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo_standalone/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/scudo_standalone/ya.make b/contrib/libs/clang16-rt/lib/scudo_standalone/ya.make
new file mode 100644
index 00000000000..e9ff600c943
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo_standalone/ya.make
@@ -0,0 +1,70 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.scudo_standalone${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+ contrib/libs/clang16-rt/lib/scudo/standalone/include
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DGWP_ASAN_HOOKS
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-omit-frame-pointer
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ gwp_asan/common.cpp
+ gwp_asan/crash_handler.cpp
+ gwp_asan/guarded_pool_allocator.cpp
+ gwp_asan/optional/backtrace_linux_libc.cpp
+ gwp_asan/optional/options_parser.cpp
+ gwp_asan/optional/segv_handler_posix.cpp
+ gwp_asan/platform_specific/common_posix.cpp
+ gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp
+ gwp_asan/platform_specific/mutex_posix.cpp
+ gwp_asan/platform_specific/utilities_posix.cpp
+ gwp_asan/stack_trace_compressor.cpp
+ scudo/standalone/checksum.cpp
+ scudo/standalone/common.cpp
+ scudo/standalone/crc32_hw.cpp
+ scudo/standalone/flags.cpp
+ scudo/standalone/flags_parser.cpp
+ scudo/standalone/fuchsia.cpp
+ scudo/standalone/linux.cpp
+ scudo/standalone/release.cpp
+ scudo/standalone/report.cpp
+ scudo/standalone/rss_limit_checker.cpp
+ scudo/standalone/string_utils.cpp
+ scudo/standalone/wrappers_c.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/scudo_standalone_cxx/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/scudo_standalone_cxx/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo_standalone_cxx/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/scudo_standalone_cxx/ya.make b/contrib/libs/clang16-rt/lib/scudo_standalone_cxx/ya.make
new file mode 100644
index 00000000000..8a50fadb7e5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/scudo_standalone_cxx/ya.make
@@ -0,0 +1,43 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.scudo_standalone_cxx${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+ contrib/libs/clang16-rt/lib/scudo/standalone/include
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DGWP_ASAN_HOOKS
+ -fno-exceptions
+ -fno-lto
+ -fno-omit-frame-pointer
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib/scudo/standalone)
+
+SRCS(
+ wrappers_cpp.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/stats/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/stats/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/stats/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/stats/stats.cpp b/contrib/libs/clang16-rt/lib/stats/stats.cpp
new file mode 100644
index 00000000000..da254fdb5a5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/stats/stats.cpp
@@ -0,0 +1,136 @@
+//===-- stats.cpp ---------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Sanitizer statistics gathering. Manages statistics for a process and is
+// responsible for writing the report file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_file.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#if SANITIZER_POSIX
+#include "sanitizer_common/sanitizer_posix.h"
+#endif
+#include "sanitizer_common/sanitizer_symbolizer.h"
+#include "stats/stats.h"
+#if SANITIZER_POSIX
+#include <signal.h>
+#endif
+
+using namespace __sanitizer;
+
+namespace {
+
+InternalMmapVectorNoCtor<StatModule **> modules;
+StaticSpinMutex modules_mutex;
+
+fd_t stats_fd;
+
+void WriteLE(fd_t fd, uptr val) {
+ char chars[sizeof(uptr)];
+ for (unsigned i = 0; i != sizeof(uptr); ++i) {
+ chars[i] = val >> (i * 8);
+ }
+ WriteToFile(fd, chars, sizeof(uptr));
+}
+
+void OpenStatsFile(const char *path_env) {
+ InternalMmapVector<char> path(kMaxPathLength);
+ SubstituteForFlagValue(path_env, path.data(), kMaxPathLength);
+
+ error_t err;
+ stats_fd = OpenFile(path.data(), WrOnly, &err);
+ if (stats_fd == kInvalidFd) {
+ Report("stats: failed to open %s for writing (reason: %d)\n", path.data(),
+ err);
+ return;
+ }
+ char sizeof_uptr = sizeof(uptr);
+ WriteToFile(stats_fd, &sizeof_uptr, 1);
+}
+
+void WriteModuleReport(StatModule **smodp) {
+ CHECK(smodp);
+ const char *path_env = GetEnv("SANITIZER_STATS_PATH");
+ if (!path_env || stats_fd == kInvalidFd)
+ return;
+ if (!stats_fd)
+ OpenStatsFile(path_env);
+ const LoadedModule *mod = Symbolizer::GetOrInit()->FindModuleForAddress(
+ reinterpret_cast<uptr>(smodp));
+ WriteToFile(stats_fd, mod->full_name(),
+ internal_strlen(mod->full_name()) + 1);
+ for (StatModule *smod = *smodp; smod; smod = smod->next) {
+ for (u32 i = 0; i != smod->size; ++i) {
+ StatInfo *s = &smod->infos[i];
+ if (!s->addr)
+ continue;
+ WriteLE(stats_fd, s->addr - mod->base_address());
+ WriteLE(stats_fd, s->data);
+ }
+ }
+ WriteLE(stats_fd, 0);
+ WriteLE(stats_fd, 0);
+}
+
+} // namespace
+
+extern "C"
+SANITIZER_INTERFACE_ATTRIBUTE
+unsigned __sanitizer_stats_register(StatModule **mod) {
+ SpinMutexLock l(&modules_mutex);
+ modules.push_back(mod);
+ return modules.size() - 1;
+}
+
+extern "C"
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_stats_unregister(unsigned index) {
+ SpinMutexLock l(&modules_mutex);
+ WriteModuleReport(modules[index]);
+ modules[index] = 0;
+}
+
+namespace {
+
+void WriteFullReport() {
+ SpinMutexLock l(&modules_mutex);
+ for (StatModule **mod : modules) {
+ if (!mod)
+ continue;
+ WriteModuleReport(mod);
+ }
+ if (stats_fd != 0 && stats_fd != kInvalidFd) {
+ CloseFile(stats_fd);
+ stats_fd = kInvalidFd;
+ }
+}
+
+#if SANITIZER_POSIX
+void USR2Handler(int sig) {
+ WriteFullReport();
+}
+#endif
+
+struct WriteReportOnExitOrSignal {
+ WriteReportOnExitOrSignal() {
+#if SANITIZER_POSIX
+ struct sigaction sigact;
+ internal_memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = USR2Handler;
+ internal_sigaction(SIGUSR2, &sigact, nullptr);
+#endif
+ }
+
+ ~WriteReportOnExitOrSignal() {
+ WriteFullReport();
+ }
+} wr;
+
+} // namespace
diff --git a/contrib/libs/clang16-rt/lib/stats/stats.h b/contrib/libs/clang16-rt/lib/stats/stats.h
new file mode 100644
index 00000000000..4b7514d6108
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/stats/stats.h
@@ -0,0 +1,42 @@
+//===-- stats.h -------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Data definitions for sanitizer statistics gathering.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_STATS_STATS_H
+#define SANITIZER_STATS_STATS_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+// Number of bits in data that are used for the sanitizer kind. Needs to match
+// llvm::kSanitizerStatKindBits in
+// llvm/include/llvm/Transforms/Utils/SanitizerStats.h
+enum { kKindBits = 3 };
+
+struct StatInfo {
+ uptr addr;
+ uptr data;
+};
+
+struct StatModule {
+ StatModule *next;
+ u32 size;
+ StatInfo infos[1];
+};
+
+inline uptr CountFromData(uptr data) {
+ return data & ((1ull << (sizeof(uptr) * 8 - kKindBits)) - 1);
+}
+
+}
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/stats/stats_client.cpp b/contrib/libs/clang16-rt/lib/stats/stats_client.cpp
new file mode 100644
index 00000000000..52eab8eea07
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/stats/stats_client.cpp
@@ -0,0 +1,83 @@
+//===-- stats_client.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Sanitizer statistics gathering. Manages statistics for a module (executable
+// or DSO) and registers statistics with the process.
+//
+// This is linked into each individual modle and cannot directly use functions
+// declared in sanitizer_common.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#else
+#include <dlfcn.h>
+#endif
+#include <stdint.h>
+#include <stdio.h>
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "stats/stats.h"
+
+using namespace __sanitizer;
+
+namespace {
+
+void *LookupSymbolFromMain(const char *name) {
+#ifdef _WIN32
+ return reinterpret_cast<void *>(GetProcAddress(GetModuleHandle(0), name));
+#else
+ return dlsym(RTLD_DEFAULT, name);
+#endif
+}
+
+StatModule *list;
+
+struct RegisterSanStats {
+ unsigned module_id;
+
+ RegisterSanStats() {
+ typedef unsigned (*reg_func_t)(StatModule **);
+ reg_func_t reg_func = reinterpret_cast<reg_func_t>(
+ LookupSymbolFromMain("__sanitizer_stats_register"));
+ if (reg_func)
+ module_id = reg_func(&list);
+ }
+
+ ~RegisterSanStats() {
+ typedef void (*unreg_func_t)(unsigned);
+ unreg_func_t unreg_func = reinterpret_cast<unreg_func_t>(
+ LookupSymbolFromMain("__sanitizer_stats_unregister"));
+ if (unreg_func)
+ unreg_func(module_id);
+ }
+} reg;
+
+}
+
+extern "C" void __sanitizer_stat_init(StatModule *mod) {
+ mod->next = list;
+ list = mod;
+}
+
+extern "C" void __sanitizer_stat_report(StatInfo *s) {
+ s->addr = GET_CALLER_PC();
+#if defined(_WIN64) && !defined(__clang__)
+ uptr old_data = InterlockedIncrement64(reinterpret_cast<LONG64 *>(&s->data));
+#elif defined(_WIN32) && !defined(__clang__)
+ uptr old_data = InterlockedIncrement(&s->data);
+#else
+ uptr old_data = __sync_fetch_and_add(&s->data, 1);
+#endif
+
+ // Overflow check.
+ if (CountFromData(old_data + 1) == 0)
+ Trap();
+}
diff --git a/contrib/libs/clang16-rt/lib/stats/ya.make b/contrib/libs/clang16-rt/lib/stats/ya.make
new file mode 100644
index 00000000000..892b74b1ead
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/stats/ya.make
@@ -0,0 +1,110 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.stats${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHAVE_RPC_XDR_H=0
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ sanitizer_common/sanitizer_allocator.cpp
+ sanitizer_common/sanitizer_allocator_checks.cpp
+ sanitizer_common/sanitizer_allocator_report.cpp
+ sanitizer_common/sanitizer_chained_origin_depot.cpp
+ sanitizer_common/sanitizer_common.cpp
+ sanitizer_common/sanitizer_common_libcdep.cpp
+ sanitizer_common/sanitizer_deadlock_detector1.cpp
+ sanitizer_common/sanitizer_deadlock_detector2.cpp
+ sanitizer_common/sanitizer_errno.cpp
+ sanitizer_common/sanitizer_file.cpp
+ sanitizer_common/sanitizer_flag_parser.cpp
+ sanitizer_common/sanitizer_flags.cpp
+ sanitizer_common/sanitizer_fuchsia.cpp
+ sanitizer_common/sanitizer_libc.cpp
+ sanitizer_common/sanitizer_libignore.cpp
+ sanitizer_common/sanitizer_linux.cpp
+ sanitizer_common/sanitizer_linux_libcdep.cpp
+ sanitizer_common/sanitizer_linux_s390.cpp
+ sanitizer_common/sanitizer_mac.cpp
+ sanitizer_common/sanitizer_mac_libcdep.cpp
+ sanitizer_common/sanitizer_mutex.cpp
+ sanitizer_common/sanitizer_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+ sanitizer_common/sanitizer_platform_limits_linux.cpp
+ sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_posix.cpp
+ sanitizer_common/sanitizer_platform_limits_solaris.cpp
+ sanitizer_common/sanitizer_posix.cpp
+ sanitizer_common/sanitizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_printf.cpp
+ sanitizer_common/sanitizer_procmaps_bsd.cpp
+ sanitizer_common/sanitizer_procmaps_common.cpp
+ sanitizer_common/sanitizer_procmaps_fuchsia.cpp
+ sanitizer_common/sanitizer_procmaps_linux.cpp
+ sanitizer_common/sanitizer_procmaps_mac.cpp
+ sanitizer_common/sanitizer_procmaps_solaris.cpp
+ sanitizer_common/sanitizer_solaris.cpp
+ sanitizer_common/sanitizer_stack_store.cpp
+ sanitizer_common/sanitizer_stackdepot.cpp
+ sanitizer_common/sanitizer_stacktrace.cpp
+ sanitizer_common/sanitizer_stacktrace_libcdep.cpp
+ sanitizer_common/sanitizer_stacktrace_printer.cpp
+ sanitizer_common/sanitizer_stacktrace_sparc.cpp
+ sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
+ sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_mac.cpp
+ sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_win.cpp
+ sanitizer_common/sanitizer_suppressions.cpp
+ sanitizer_common/sanitizer_symbolizer.cpp
+ sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
+ sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_mac.cpp
+ sanitizer_common/sanitizer_symbolizer_markup.cpp
+ sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_report.cpp
+ sanitizer_common/sanitizer_symbolizer_win.cpp
+ sanitizer_common/sanitizer_termination.cpp
+ sanitizer_common/sanitizer_thread_registry.cpp
+ sanitizer_common/sanitizer_tls_get_addr.cpp
+ sanitizer_common/sanitizer_type_traits.cpp
+ sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
+ sanitizer_common/sanitizer_unwind_win.cpp
+ sanitizer_common/sanitizer_win.cpp
+ stats/stats.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/stats_client/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/stats_client/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/stats_client/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/stats_client/ya.make b/contrib/libs/clang16-rt/lib/stats_client/ya.make
new file mode 100644
index 00000000000..0d20d7eb783
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/stats_client/ya.make
@@ -0,0 +1,44 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.stats_client${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib/stats)
+
+SRCS(
+ stats_client.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/tsan/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/tsan/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..b42fe728ba8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/.yandex_meta/licenses.list.txt
@@ -0,0 +1,383 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ return AllocSuperBlock(c);
+ Block *ptr = MapBlock(idx);
+ xchg = ptr->next | (cmp & kCounterMask);
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/tsan/dd/dd_interceptors.cpp b/contrib/libs/clang16-rt/lib/tsan/dd/dd_interceptors.cpp
new file mode 100644
index 00000000000..2c36f691ec5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/dd/dd_interceptors.cpp
@@ -0,0 +1,330 @@
+//===-- dd_interceptors.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <pthread.h>
+
+#include "dd_rtl.h"
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_allocator_internal.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+
+using namespace __dsan;
+
+__attribute__((tls_model("initial-exec")))
+static __thread Thread *thr;
+__attribute__((tls_model("initial-exec")))
+static __thread volatile int initing;
+static bool inited;
+static uptr g_data_start;
+static uptr g_data_end;
+
+static bool InitThread() {
+ if (initing)
+ return false;
+ if (thr != 0)
+ return true;
+ initing = true;
+ if (!inited) {
+ inited = true;
+ Initialize();
+ }
+ thr = (Thread*)InternalAlloc(sizeof(*thr));
+ internal_memset(thr, 0, sizeof(*thr));
+ ThreadInit(thr);
+ initing = false;
+ return true;
+}
+
+INTERCEPTOR(int, pthread_mutex_destroy, pthread_mutex_t *m) {
+ InitThread();
+ MutexDestroy(thr, (uptr)m);
+ return REAL(pthread_mutex_destroy)(m);
+}
+
+INTERCEPTOR(int, pthread_mutex_lock, pthread_mutex_t *m) {
+ InitThread();
+ MutexBeforeLock(thr, (uptr)m, true);
+ int res = REAL(pthread_mutex_lock)(m);
+ MutexAfterLock(thr, (uptr)m, true, false);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_mutex_trylock, pthread_mutex_t *m) {
+ InitThread();
+ int res = REAL(pthread_mutex_trylock)(m);
+ if (res == 0)
+ MutexAfterLock(thr, (uptr)m, true, true);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_mutex_unlock, pthread_mutex_t *m) {
+ InitThread();
+ MutexBeforeUnlock(thr, (uptr)m, true);
+ return REAL(pthread_mutex_unlock)(m);
+}
+
+INTERCEPTOR(int, pthread_spin_destroy, pthread_spinlock_t *m) {
+ InitThread();
+ int res = REAL(pthread_spin_destroy)(m);
+ MutexDestroy(thr, (uptr)m);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_spin_lock, pthread_spinlock_t *m) {
+ InitThread();
+ MutexBeforeLock(thr, (uptr)m, true);
+ int res = REAL(pthread_spin_lock)(m);
+ MutexAfterLock(thr, (uptr)m, true, false);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_spin_trylock, pthread_spinlock_t *m) {
+ InitThread();
+ int res = REAL(pthread_spin_trylock)(m);
+ if (res == 0)
+ MutexAfterLock(thr, (uptr)m, true, true);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_spin_unlock, pthread_spinlock_t *m) {
+ InitThread();
+ MutexBeforeUnlock(thr, (uptr)m, true);
+ return REAL(pthread_spin_unlock)(m);
+}
+
+INTERCEPTOR(int, pthread_rwlock_destroy, pthread_rwlock_t *m) {
+ InitThread();
+ MutexDestroy(thr, (uptr)m);
+ return REAL(pthread_rwlock_destroy)(m);
+}
+
+INTERCEPTOR(int, pthread_rwlock_rdlock, pthread_rwlock_t *m) {
+ InitThread();
+ MutexBeforeLock(thr, (uptr)m, false);
+ int res = REAL(pthread_rwlock_rdlock)(m);
+ MutexAfterLock(thr, (uptr)m, false, false);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_rwlock_tryrdlock, pthread_rwlock_t *m) {
+ InitThread();
+ int res = REAL(pthread_rwlock_tryrdlock)(m);
+ if (res == 0)
+ MutexAfterLock(thr, (uptr)m, false, true);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_rwlock_timedrdlock, pthread_rwlock_t *m,
+ const timespec *abstime) {
+ InitThread();
+ int res = REAL(pthread_rwlock_timedrdlock)(m, abstime);
+ if (res == 0)
+ MutexAfterLock(thr, (uptr)m, false, true);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_rwlock_wrlock, pthread_rwlock_t *m) {
+ InitThread();
+ MutexBeforeLock(thr, (uptr)m, true);
+ int res = REAL(pthread_rwlock_wrlock)(m);
+ MutexAfterLock(thr, (uptr)m, true, false);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_rwlock_trywrlock, pthread_rwlock_t *m) {
+ InitThread();
+ int res = REAL(pthread_rwlock_trywrlock)(m);
+ if (res == 0)
+ MutexAfterLock(thr, (uptr)m, true, true);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_rwlock_timedwrlock, pthread_rwlock_t *m,
+ const timespec *abstime) {
+ InitThread();
+ int res = REAL(pthread_rwlock_timedwrlock)(m, abstime);
+ if (res == 0)
+ MutexAfterLock(thr, (uptr)m, true, true);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_rwlock_unlock, pthread_rwlock_t *m) {
+ InitThread();
+ MutexBeforeUnlock(thr, (uptr)m, true); // note: not necessary write unlock
+ return REAL(pthread_rwlock_unlock)(m);
+}
+
+static pthread_cond_t *init_cond(pthread_cond_t *c, bool force = false) {
+ atomic_uintptr_t *p = (atomic_uintptr_t*)c;
+ uptr cond = atomic_load(p, memory_order_acquire);
+ if (!force && cond != 0)
+ return (pthread_cond_t*)cond;
+ void *newcond = InternalAlloc(sizeof(pthread_cond_t));
+ internal_memset(newcond, 0, sizeof(pthread_cond_t));
+ if (atomic_compare_exchange_strong(p, &cond, (uptr)newcond,
+ memory_order_acq_rel))
+ return (pthread_cond_t*)newcond;
+ InternalFree(newcond);
+ return (pthread_cond_t*)cond;
+}
+
+INTERCEPTOR(int, pthread_cond_init, pthread_cond_t *c,
+ const pthread_condattr_t *a) {
+ InitThread();
+ pthread_cond_t *cond = init_cond(c, true);
+ return REAL(pthread_cond_init)(cond, a);
+}
+
+INTERCEPTOR(int, pthread_cond_wait, pthread_cond_t *c, pthread_mutex_t *m) {
+ InitThread();
+ pthread_cond_t *cond = init_cond(c);
+ MutexBeforeUnlock(thr, (uptr)m, true);
+ MutexBeforeLock(thr, (uptr)m, true);
+ int res = REAL(pthread_cond_wait)(cond, m);
+ MutexAfterLock(thr, (uptr)m, true, false);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_cond_timedwait, pthread_cond_t *c, pthread_mutex_t *m,
+ const timespec *abstime) {
+ InitThread();
+ pthread_cond_t *cond = init_cond(c);
+ MutexBeforeUnlock(thr, (uptr)m, true);
+ MutexBeforeLock(thr, (uptr)m, true);
+ int res = REAL(pthread_cond_timedwait)(cond, m, abstime);
+ MutexAfterLock(thr, (uptr)m, true, false);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_cond_signal, pthread_cond_t *c) {
+ InitThread();
+ pthread_cond_t *cond = init_cond(c);
+ return REAL(pthread_cond_signal)(cond);
+}
+
+INTERCEPTOR(int, pthread_cond_broadcast, pthread_cond_t *c) {
+ InitThread();
+ pthread_cond_t *cond = init_cond(c);
+ return REAL(pthread_cond_broadcast)(cond);
+}
+
+INTERCEPTOR(int, pthread_cond_destroy, pthread_cond_t *c) {
+ InitThread();
+ pthread_cond_t *cond = init_cond(c);
+ int res = REAL(pthread_cond_destroy)(cond);
+ InternalFree(cond);
+ atomic_store((atomic_uintptr_t*)c, 0, memory_order_relaxed);
+ return res;
+}
+
+// for symbolizer
+INTERCEPTOR(char*, realpath, const char *path, char *resolved_path) {
+ InitThread();
+ return REAL(realpath)(path, resolved_path);
+}
+
+INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
+ InitThread();
+ return REAL(read)(fd, ptr, count);
+}
+
+INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
+ InitThread();
+ return REAL(pread)(fd, ptr, count, offset);
+}
+
+extern "C" {
+void __dsan_before_mutex_lock(uptr m, int writelock) {
+ if (!InitThread())
+ return;
+ MutexBeforeLock(thr, m, writelock);
+}
+
+void __dsan_after_mutex_lock(uptr m, int writelock, int trylock) {
+ if (!InitThread())
+ return;
+ MutexAfterLock(thr, m, writelock, trylock);
+}
+
+void __dsan_before_mutex_unlock(uptr m, int writelock) {
+ if (!InitThread())
+ return;
+ MutexBeforeUnlock(thr, m, writelock);
+}
+
+void __dsan_mutex_destroy(uptr m) {
+ if (!InitThread())
+ return;
+ // if (m >= g_data_start && m < g_data_end)
+ // return;
+ MutexDestroy(thr, m);
+}
+} // extern "C"
+
+namespace __dsan {
+
+static void InitDataSeg() {
+ MemoryMappingLayout proc_maps(true);
+ char name[128];
+ MemoryMappedSegment segment(name, ARRAY_SIZE(name));
+ bool prev_is_data = false;
+ while (proc_maps.Next(&segment)) {
+ bool is_data = segment.offset != 0 && segment.filename[0] != 0;
+ // BSS may get merged with [heap] in /proc/self/maps. This is not very
+ // reliable.
+ bool is_bss = segment.offset == 0 &&
+ (segment.filename[0] == 0 ||
+ internal_strcmp(segment.filename, "[heap]") == 0) &&
+ prev_is_data;
+ if (g_data_start == 0 && is_data) g_data_start = segment.start;
+ if (is_bss) g_data_end = segment.end;
+ prev_is_data = is_data;
+ }
+ VPrintf(1, "guessed data_start=0x%zx data_end=0x%zx\n", g_data_start,
+ g_data_end);
+ CHECK_LT(g_data_start, g_data_end);
+ CHECK_GE((uptr)&g_data_start, g_data_start);
+ CHECK_LT((uptr)&g_data_start, g_data_end);
+}
+
+void InitializeInterceptors() {
+ INTERCEPT_FUNCTION(pthread_mutex_destroy);
+ INTERCEPT_FUNCTION(pthread_mutex_lock);
+ INTERCEPT_FUNCTION(pthread_mutex_trylock);
+ INTERCEPT_FUNCTION(pthread_mutex_unlock);
+
+ INTERCEPT_FUNCTION(pthread_spin_destroy);
+ INTERCEPT_FUNCTION(pthread_spin_lock);
+ INTERCEPT_FUNCTION(pthread_spin_trylock);
+ INTERCEPT_FUNCTION(pthread_spin_unlock);
+
+ INTERCEPT_FUNCTION(pthread_rwlock_destroy);
+ INTERCEPT_FUNCTION(pthread_rwlock_rdlock);
+ INTERCEPT_FUNCTION(pthread_rwlock_tryrdlock);
+ INTERCEPT_FUNCTION(pthread_rwlock_timedrdlock);
+ INTERCEPT_FUNCTION(pthread_rwlock_wrlock);
+ INTERCEPT_FUNCTION(pthread_rwlock_trywrlock);
+ INTERCEPT_FUNCTION(pthread_rwlock_timedwrlock);
+ INTERCEPT_FUNCTION(pthread_rwlock_unlock);
+
+ INTERCEPT_FUNCTION_VER(pthread_cond_init, "GLIBC_2.3.2");
+ INTERCEPT_FUNCTION_VER(pthread_cond_signal, "GLIBC_2.3.2");
+ INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, "GLIBC_2.3.2");
+ INTERCEPT_FUNCTION_VER(pthread_cond_wait, "GLIBC_2.3.2");
+ INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, "GLIBC_2.3.2");
+ INTERCEPT_FUNCTION_VER(pthread_cond_destroy, "GLIBC_2.3.2");
+
+ // for symbolizer
+ INTERCEPT_FUNCTION(realpath);
+ INTERCEPT_FUNCTION(read);
+ INTERCEPT_FUNCTION(pread);
+
+ InitDataSeg();
+}
+
+} // namespace __dsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/dd/dd_rtl.cpp b/contrib/libs/clang16-rt/lib/tsan/dd/dd_rtl.cpp
new file mode 100644
index 00000000000..35b367c0cec
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/dd/dd_rtl.cpp
@@ -0,0 +1,158 @@
+//===-- dd_rtl.cpp --------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "dd_rtl.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+namespace __dsan {
+
+static Context *ctx;
+
+static u32 CurrentStackTrace(Thread *thr, uptr skip) {
+ BufferedStackTrace stack;
+ thr->ignore_interceptors = true;
+ stack.Unwind(1000, 0, 0, 0, 0, 0, false);
+ thr->ignore_interceptors = false;
+ if (stack.size <= skip)
+ return 0;
+ return StackDepotPut(StackTrace(stack.trace + skip, stack.size - skip));
+}
+
+static void PrintStackTrace(Thread *thr, u32 stk) {
+ StackTrace stack = StackDepotGet(stk);
+ thr->ignore_interceptors = true;
+ stack.Print();
+ thr->ignore_interceptors = false;
+}
+
+static void ReportDeadlock(Thread *thr, DDReport *rep) {
+ if (rep == 0)
+ return;
+ Lock lock(&ctx->report_mutex);
+ Printf("==============================\n");
+ Printf("WARNING: lock-order-inversion (potential deadlock)\n");
+ for (int i = 0; i < rep->n; i++) {
+ Printf("Thread %lld locks mutex %llu while holding mutex %llu:\n",
+ rep->loop[i].thr_ctx, rep->loop[i].mtx_ctx1, rep->loop[i].mtx_ctx0);
+ PrintStackTrace(thr, rep->loop[i].stk[1]);
+ if (rep->loop[i].stk[0]) {
+ Printf("Mutex %llu was acquired here:\n",
+ rep->loop[i].mtx_ctx0);
+ PrintStackTrace(thr, rep->loop[i].stk[0]);
+ }
+ }
+ Printf("==============================\n");
+}
+
+Callback::Callback(Thread *thr)
+ : thr(thr) {
+ lt = thr->dd_lt;
+ pt = thr->dd_pt;
+}
+
+u32 Callback::Unwind() {
+ return CurrentStackTrace(thr, 3);
+}
+
+static void InitializeFlags() {
+ Flags *f = flags();
+
+ // Default values.
+ f->second_deadlock_stack = false;
+
+ SetCommonFlagsDefaults();
+ {
+ // Override some common flags defaults.
+ CommonFlags cf;
+ cf.CopyFrom(*common_flags());
+ cf.allow_addr2line = true;
+ OverrideCommonFlags(cf);
+ }
+
+ // Override from command line.
+ FlagParser parser;
+ RegisterFlag(&parser, "second_deadlock_stack", "", &f->second_deadlock_stack);
+ RegisterCommonFlags(&parser);
+ parser.ParseStringFromEnv("DSAN_OPTIONS");
+ SetVerbosity(common_flags()->verbosity);
+}
+
+void Initialize() {
+ static u64 ctx_mem[sizeof(Context) / sizeof(u64) + 1];
+ ctx = new(ctx_mem) Context();
+
+ InitializeInterceptors();
+ InitializeFlags();
+ ctx->dd = DDetector::Create(flags());
+}
+
+void ThreadInit(Thread *thr) {
+ static atomic_uintptr_t id_gen;
+ uptr id = atomic_fetch_add(&id_gen, 1, memory_order_relaxed);
+ thr->dd_pt = ctx->dd->CreatePhysicalThread();
+ thr->dd_lt = ctx->dd->CreateLogicalThread(id);
+}
+
+void ThreadDestroy(Thread *thr) {
+ ctx->dd->DestroyPhysicalThread(thr->dd_pt);
+ ctx->dd->DestroyLogicalThread(thr->dd_lt);
+}
+
+void MutexBeforeLock(Thread *thr, uptr m, bool writelock) {
+ if (thr->ignore_interceptors)
+ return;
+ Callback cb(thr);
+ {
+ MutexHashMap::Handle h(&ctx->mutex_map, m);
+ if (h.created())
+ ctx->dd->MutexInit(&cb, &h->dd);
+ ctx->dd->MutexBeforeLock(&cb, &h->dd, writelock);
+ }
+ ReportDeadlock(thr, ctx->dd->GetReport(&cb));
+}
+
+void MutexAfterLock(Thread *thr, uptr m, bool writelock, bool trylock) {
+ if (thr->ignore_interceptors)
+ return;
+ Callback cb(thr);
+ {
+ MutexHashMap::Handle h(&ctx->mutex_map, m);
+ if (h.created())
+ ctx->dd->MutexInit(&cb, &h->dd);
+ ctx->dd->MutexAfterLock(&cb, &h->dd, writelock, trylock);
+ }
+ ReportDeadlock(thr, ctx->dd->GetReport(&cb));
+}
+
+void MutexBeforeUnlock(Thread *thr, uptr m, bool writelock) {
+ if (thr->ignore_interceptors)
+ return;
+ Callback cb(thr);
+ {
+ MutexHashMap::Handle h(&ctx->mutex_map, m);
+ ctx->dd->MutexBeforeUnlock(&cb, &h->dd, writelock);
+ }
+ ReportDeadlock(thr, ctx->dd->GetReport(&cb));
+}
+
+void MutexDestroy(Thread *thr, uptr m) {
+ if (thr->ignore_interceptors)
+ return;
+ Callback cb(thr);
+ MutexHashMap::Handle h(&ctx->mutex_map, m, true);
+ if (!h.exists())
+ return;
+ ctx->dd->MutexDestroy(&cb, &h->dd);
+}
+
+} // namespace __dsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/dd/dd_rtl.h b/contrib/libs/clang16-rt/lib/tsan/dd/dd_rtl.h
new file mode 100644
index 00000000000..c812ffbd139
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/dd/dd_rtl.h
@@ -0,0 +1,66 @@
+//===-- dd_rtl.h ----------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef DD_RTL_H
+#define DD_RTL_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_allocator_internal.h"
+#include "sanitizer_common/sanitizer_addrhashmap.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+
+namespace __dsan {
+
+typedef DDFlags Flags;
+
+struct UserMutex {
+ DDMutex dd;
+};
+
+struct Thread {
+ DDPhysicalThread *dd_pt;
+ DDLogicalThread *dd_lt;
+
+ bool ignore_interceptors;
+};
+
+struct Callback final : public DDCallback {
+ Thread *thr;
+
+ Callback(Thread *thr);
+ u32 Unwind() override;
+};
+
+typedef AddrHashMap<UserMutex, 31051> MutexHashMap;
+
+struct Context {
+ DDetector *dd;
+
+ Mutex report_mutex;
+ MutexHashMap mutex_map;
+};
+
+inline Flags* flags() {
+ static Flags flags;
+ return &flags;
+}
+
+void Initialize();
+void InitializeInterceptors();
+
+void ThreadInit(Thread *thr);
+void ThreadDestroy(Thread *thr);
+
+void MutexBeforeLock(Thread *thr, uptr m, bool writelock);
+void MutexAfterLock(Thread *thr, uptr m, bool writelock, bool trylock);
+void MutexBeforeUnlock(Thread *thr, uptr m, bool writelock);
+void MutexDestroy(Thread *thr, uptr m);
+
+} // namespace __dsan
+#endif // DD_RTL_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_debugging.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_debugging.cpp
new file mode 100644
index 00000000000..1e61c31c5a9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_debugging.cpp
@@ -0,0 +1,262 @@
+//===-- tsan_debugging.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// TSan debugging API implementation.
+//===----------------------------------------------------------------------===//
+#include "tsan_interface.h"
+#include "tsan_report.h"
+#include "tsan_rtl.h"
+
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+using namespace __tsan;
+
+static const char *ReportTypeDescription(ReportType typ) {
+ switch (typ) {
+ case ReportTypeRace: return "data-race";
+ case ReportTypeVptrRace: return "data-race-vptr";
+ case ReportTypeUseAfterFree: return "heap-use-after-free";
+ case ReportTypeVptrUseAfterFree: return "heap-use-after-free-vptr";
+ case ReportTypeExternalRace: return "external-race";
+ case ReportTypeThreadLeak: return "thread-leak";
+ case ReportTypeMutexDestroyLocked: return "locked-mutex-destroy";
+ case ReportTypeMutexDoubleLock: return "mutex-double-lock";
+ case ReportTypeMutexInvalidAccess: return "mutex-invalid-access";
+ case ReportTypeMutexBadUnlock: return "mutex-bad-unlock";
+ case ReportTypeMutexBadReadLock: return "mutex-bad-read-lock";
+ case ReportTypeMutexBadReadUnlock: return "mutex-bad-read-unlock";
+ case ReportTypeSignalUnsafe: return "signal-unsafe-call";
+ case ReportTypeErrnoInSignal: return "errno-in-signal-handler";
+ case ReportTypeDeadlock: return "lock-order-inversion";
+ // No default case so compiler warns us if we miss one
+ }
+ UNREACHABLE("missing case");
+}
+
+static const char *ReportLocationTypeDescription(ReportLocationType typ) {
+ switch (typ) {
+ case ReportLocationGlobal: return "global";
+ case ReportLocationHeap: return "heap";
+ case ReportLocationStack: return "stack";
+ case ReportLocationTLS: return "tls";
+ case ReportLocationFD: return "fd";
+ // No default case so compiler warns us if we miss one
+ }
+ UNREACHABLE("missing case");
+}
+
+static void CopyTrace(SymbolizedStack *first_frame, void **trace,
+ uptr trace_size) {
+ uptr i = 0;
+ for (SymbolizedStack *frame = first_frame; frame != nullptr;
+ frame = frame->next) {
+ trace[i++] = (void *)frame->info.address;
+ if (i >= trace_size) break;
+ }
+}
+
+// Meant to be called by the debugger.
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__tsan_get_current_report() {
+ return const_cast<ReportDesc*>(cur_thread()->current_report);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_data(void *report, const char **description, int *count,
+ int *stack_count, int *mop_count, int *loc_count,
+ int *mutex_count, int *thread_count,
+ int *unique_tid_count, void **sleep_trace,
+ uptr trace_size) {
+ const ReportDesc *rep = (ReportDesc *)report;
+ *description = ReportTypeDescription(rep->typ);
+ *count = rep->count;
+ *stack_count = rep->stacks.Size();
+ *mop_count = rep->mops.Size();
+ *loc_count = rep->locs.Size();
+ *mutex_count = rep->mutexes.Size();
+ *thread_count = rep->threads.Size();
+ *unique_tid_count = rep->unique_tids.Size();
+ if (rep->sleep) CopyTrace(rep->sleep->frames, sleep_trace, trace_size);
+ return 1;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_tag(void *report, uptr *tag) {
+ const ReportDesc *rep = (ReportDesc *)report;
+ *tag = rep->tag;
+ return 1;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_stack(void *report, uptr idx, void **trace,
+ uptr trace_size) {
+ const ReportDesc *rep = (ReportDesc *)report;
+ CHECK_LT(idx, rep->stacks.Size());
+ ReportStack *stack = rep->stacks[idx];
+ if (stack) CopyTrace(stack->frames, trace, trace_size);
+ return stack ? 1 : 0;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_mop(void *report, uptr idx, int *tid, void **addr,
+ int *size, int *write, int *atomic, void **trace,
+ uptr trace_size) {
+ const ReportDesc *rep = (ReportDesc *)report;
+ CHECK_LT(idx, rep->mops.Size());
+ ReportMop *mop = rep->mops[idx];
+ *tid = mop->tid;
+ *addr = (void *)mop->addr;
+ *size = mop->size;
+ *write = mop->write ? 1 : 0;
+ *atomic = mop->atomic ? 1 : 0;
+ if (mop->stack) CopyTrace(mop->stack->frames, trace, trace_size);
+ return 1;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_loc(void *report, uptr idx, const char **type,
+ void **addr, uptr *start, uptr *size, int *tid,
+ int *fd, int *suppressable, void **trace,
+ uptr trace_size) {
+ const ReportDesc *rep = (ReportDesc *)report;
+ CHECK_LT(idx, rep->locs.Size());
+ ReportLocation *loc = rep->locs[idx];
+ *type = ReportLocationTypeDescription(loc->type);
+ *addr = (void *)loc->global.start;
+ *start = loc->heap_chunk_start;
+ *size = loc->heap_chunk_size;
+ *tid = loc->tid;
+ *fd = loc->fd;
+ *suppressable = loc->suppressable;
+ if (loc->stack) CopyTrace(loc->stack->frames, trace, trace_size);
+ return 1;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_loc_object_type(void *report, uptr idx,
+ const char **object_type) {
+ const ReportDesc *rep = (ReportDesc *)report;
+ CHECK_LT(idx, rep->locs.Size());
+ ReportLocation *loc = rep->locs[idx];
+ *object_type = GetObjectTypeFromTag(loc->external_tag);
+ return 1;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr,
+ int *destroyed, void **trace, uptr trace_size) {
+ const ReportDesc *rep = (ReportDesc *)report;
+ CHECK_LT(idx, rep->mutexes.Size());
+ ReportMutex *mutex = rep->mutexes[idx];
+ *mutex_id = mutex->id;
+ *addr = (void *)mutex->addr;
+ *destroyed = false;
+ if (mutex->stack) CopyTrace(mutex->stack->frames, trace, trace_size);
+ return 1;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_thread(void *report, uptr idx, int *tid, tid_t *os_id,
+ int *running, const char **name, int *parent_tid,
+ void **trace, uptr trace_size) {
+ const ReportDesc *rep = (ReportDesc *)report;
+ CHECK_LT(idx, rep->threads.Size());
+ ReportThread *thread = rep->threads[idx];
+ *tid = thread->id;
+ *os_id = thread->os_id;
+ *running = thread->running;
+ *name = thread->name;
+ *parent_tid = thread->parent_tid;
+ if (thread->stack) CopyTrace(thread->stack->frames, trace, trace_size);
+ return 1;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_unique_tid(void *report, uptr idx, int *tid) {
+ const ReportDesc *rep = (ReportDesc *)report;
+ CHECK_LT(idx, rep->unique_tids.Size());
+ *tid = rep->unique_tids[idx];
+ return 1;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,
+ uptr *region_address_ptr,
+ uptr *region_size_ptr) {
+ uptr region_address = 0;
+ uptr region_size = 0;
+ const char *region_kind = nullptr;
+ if (name && name_size > 0) name[0] = 0;
+
+ if (IsMetaMem(reinterpret_cast<u32 *>(addr))) {
+ region_kind = "meta shadow";
+ } else if (IsShadowMem(reinterpret_cast<RawShadow *>(addr))) {
+ region_kind = "shadow";
+ } else {
+ bool is_stack = false;
+ MBlock *b = 0;
+ Allocator *a = allocator();
+ if (a->PointerIsMine((void *)addr)) {
+ void *block_begin = a->GetBlockBegin((void *)addr);
+ if (block_begin) b = ctx->metamap.GetBlock((uptr)block_begin);
+ }
+
+ if (b != 0) {
+ region_address = (uptr)allocator()->GetBlockBegin((void *)addr);
+ region_size = b->siz;
+ region_kind = "heap";
+ } else {
+ // TODO(kuba.brecka): We should not lock. This is supposed to be called
+ // from within the debugger when other threads are stopped.
+ ctx->thread_registry.Lock();
+ ThreadContext *tctx = IsThreadStackOrTls(addr, &is_stack);
+ ctx->thread_registry.Unlock();
+ if (tctx) {
+ region_kind = is_stack ? "stack" : "tls";
+ } else {
+ region_kind = "global";
+ DataInfo info;
+ if (Symbolizer::GetOrInit()->SymbolizeData(addr, &info)) {
+ internal_strncpy(name, info.name, name_size);
+ region_address = info.start;
+ region_size = info.size;
+ }
+ }
+ }
+ }
+
+ CHECK(region_kind);
+ if (region_address_ptr) *region_address_ptr = region_address;
+ if (region_size_ptr) *region_size_ptr = region_size;
+ return region_kind;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,
+ tid_t *os_id) {
+ MBlock *b = 0;
+ Allocator *a = allocator();
+ if (a->PointerIsMine((void *)addr)) {
+ void *block_begin = a->GetBlockBegin((void *)addr);
+ if (block_begin) b = ctx->metamap.GetBlock((uptr)block_begin);
+ }
+ if (b == 0) return 0;
+
+ *thread_id = b->tid;
+ // No locking. This is supposed to be called from within the debugger when
+ // other threads are stopped.
+ ThreadContextBase *tctx = ctx->thread_registry.GetThreadLocked(b->tid);
+ *os_id = tctx->os_id;
+
+ StackTrace stack = StackDepotGet(b->stk);
+ size = Min(size, (uptr)stack.size);
+ for (uptr i = 0; i < size; i++) trace[i] = stack.trace[stack.size - i - 1];
+ return size;
+}
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_defs.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_defs.h
new file mode 100644
index 00000000000..1ffa3d6aec4
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_defs.h
@@ -0,0 +1,217 @@
+//===-- tsan_defs.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TSAN_DEFS_H
+#define TSAN_DEFS_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+#include "ubsan/ubsan_platform.h"
+
+#ifndef TSAN_VECTORIZE
+# define TSAN_VECTORIZE __SSE4_2__
+#endif
+
+#if TSAN_VECTORIZE
+// <emmintrin.h> transitively includes <stdlib.h>,
+// and it's prohibited to include std headers into tsan runtime.
+// So we do this dirty trick.
+# define _MM_MALLOC_H_INCLUDED
+# define __MM_MALLOC_H
+# include <emmintrin.h>
+# include <smmintrin.h>
+# define VECTOR_ALIGNED ALIGNED(16)
+typedef __m128i m128;
+#else
+# define VECTOR_ALIGNED
+#endif
+
+// Setup defaults for compile definitions.
+#ifndef TSAN_NO_HISTORY
+# define TSAN_NO_HISTORY 0
+#endif
+
+#ifndef TSAN_CONTAINS_UBSAN
+# if CAN_SANITIZE_UB && !SANITIZER_GO
+# define TSAN_CONTAINS_UBSAN 1
+# else
+# define TSAN_CONTAINS_UBSAN 0
+# endif
+#endif
+
+namespace __tsan {
+
+constexpr uptr kByteBits = 8;
+
+// Thread slot ID.
+enum class Sid : u8 {};
+constexpr uptr kThreadSlotCount = 256;
+constexpr Sid kFreeSid = static_cast<Sid>(255);
+
+// Abstract time unit, vector clock element.
+enum class Epoch : u16 {};
+constexpr uptr kEpochBits = 14;
+constexpr Epoch kEpochZero = static_cast<Epoch>(0);
+constexpr Epoch kEpochOver = static_cast<Epoch>(1 << kEpochBits);
+constexpr Epoch kEpochLast = static_cast<Epoch>((1 << kEpochBits) - 1);
+
+inline Epoch EpochInc(Epoch epoch) {
+ return static_cast<Epoch>(static_cast<u16>(epoch) + 1);
+}
+
+inline bool EpochOverflow(Epoch epoch) { return epoch == kEpochOver; }
+
+const uptr kShadowStackSize = 64 * 1024;
+
+// Count of shadow values in a shadow cell.
+const uptr kShadowCnt = 4;
+
+// That many user bytes are mapped onto a single shadow cell.
+const uptr kShadowCell = 8;
+
+// Single shadow value.
+enum class RawShadow : u32 {};
+const uptr kShadowSize = sizeof(RawShadow);
+
+// Shadow memory is kShadowMultiplier times larger than user memory.
+const uptr kShadowMultiplier = kShadowSize * kShadowCnt / kShadowCell;
+
+// That many user bytes are mapped onto a single meta shadow cell.
+// Must be less or equal to minimal memory allocator alignment.
+const uptr kMetaShadowCell = 8;
+
+// Size of a single meta shadow value (u32).
+const uptr kMetaShadowSize = 4;
+
+// All addresses and PCs are assumed to be compressable to that many bits.
+const uptr kCompressedAddrBits = 44;
+
+#if TSAN_NO_HISTORY
+const bool kCollectHistory = false;
+#else
+const bool kCollectHistory = true;
+#endif
+
+// The following "build consistency" machinery ensures that all source files
+// are built in the same configuration. Inconsistent builds lead to
+// hard to debug crashes.
+#if SANITIZER_DEBUG
+void build_consistency_debug();
+#else
+void build_consistency_release();
+#endif
+
+static inline void USED build_consistency() {
+#if SANITIZER_DEBUG
+ build_consistency_debug();
+#else
+ build_consistency_release();
+#endif
+}
+
+template<typename T>
+T min(T a, T b) {
+ return a < b ? a : b;
+}
+
+template<typename T>
+T max(T a, T b) {
+ return a > b ? a : b;
+}
+
+template<typename T>
+T RoundUp(T p, u64 align) {
+ DCHECK_EQ(align & (align - 1), 0);
+ return (T)(((u64)p + align - 1) & ~(align - 1));
+}
+
+template<typename T>
+T RoundDown(T p, u64 align) {
+ DCHECK_EQ(align & (align - 1), 0);
+ return (T)((u64)p & ~(align - 1));
+}
+
+// Zeroizes high part, returns 'bits' lsb bits.
+template<typename T>
+T GetLsb(T v, int bits) {
+ return (T)((u64)v & ((1ull << bits) - 1));
+}
+
+struct MD5Hash {
+ u64 hash[2];
+ bool operator==(const MD5Hash &other) const;
+};
+
+MD5Hash md5_hash(const void *data, uptr size);
+
+struct Processor;
+struct ThreadState;
+class ThreadContext;
+struct TidSlot;
+struct Context;
+struct ReportStack;
+class ReportDesc;
+class RegionAlloc;
+struct Trace;
+struct TracePart;
+
+typedef uptr AccessType;
+
+enum : AccessType {
+ kAccessWrite = 0,
+ kAccessRead = 1 << 0,
+ kAccessAtomic = 1 << 1,
+ kAccessVptr = 1 << 2, // read or write of an object virtual table pointer
+ kAccessFree = 1 << 3, // synthetic memory access during memory freeing
+ kAccessExternalPC = 1 << 4, // access PC can have kExternalPCBit set
+ kAccessCheckOnly = 1 << 5, // check for races, but don't store
+ kAccessNoRodata = 1 << 6, // don't check for .rodata marker
+ kAccessSlotLocked = 1 << 7, // memory access with TidSlot locked
+};
+
+// Descriptor of user's memory block.
+struct MBlock {
+ u64 siz : 48;
+ u64 tag : 16;
+ StackID stk;
+ Tid tid;
+};
+
+COMPILER_CHECK(sizeof(MBlock) == 16);
+
+enum ExternalTag : uptr {
+ kExternalTagNone = 0,
+ kExternalTagSwiftModifyingAccess = 1,
+ kExternalTagFirstUserAvailable = 2,
+ kExternalTagMax = 1024,
+ // Don't set kExternalTagMax over 65,536, since MBlock only stores tags
+ // as 16-bit values, see tsan_defs.h.
+};
+
+enum {
+ MutexTypeReport = MutexLastCommon,
+ MutexTypeSyncVar,
+ MutexTypeAnnotations,
+ MutexTypeAtExit,
+ MutexTypeFired,
+ MutexTypeRacy,
+ MutexTypeGlobalProc,
+ MutexTypeInternalAlloc,
+ MutexTypeTrace,
+ MutexTypeSlot,
+ MutexTypeSlots,
+};
+
+} // namespace __tsan
+
+#endif // TSAN_DEFS_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_dense_alloc.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_dense_alloc.h
new file mode 100644
index 00000000000..2eaff39057b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_dense_alloc.h
@@ -0,0 +1,196 @@
+//===-- tsan_dense_alloc.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// A DenseSlabAlloc is a freelist-based allocator of fixed-size objects.
+// DenseSlabAllocCache is a thread-local cache for DenseSlabAlloc.
+// The only difference with traditional slab allocators is that DenseSlabAlloc
+// allocates/free indices of objects and provide a functionality to map
+// the index onto the real pointer. The index is u32, that is, 2 times smaller
+// than uptr (hense the Dense prefix).
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_DENSE_ALLOC_H
+#define TSAN_DENSE_ALLOC_H
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "tsan_defs.h"
+
+namespace __tsan {
+
+class DenseSlabAllocCache {
+ static const uptr kSize = 128;
+ typedef u32 IndexT;
+ uptr pos;
+ IndexT cache[kSize];
+ template <typename, uptr, uptr, u64>
+ friend class DenseSlabAlloc;
+};
+
+template <typename T, uptr kL1Size, uptr kL2Size, u64 kReserved = 0>
+class DenseSlabAlloc {
+ public:
+ typedef DenseSlabAllocCache Cache;
+ typedef typename Cache::IndexT IndexT;
+
+ static_assert((kL1Size & (kL1Size - 1)) == 0,
+ "kL1Size must be a power-of-two");
+ static_assert((kL2Size & (kL2Size - 1)) == 0,
+ "kL2Size must be a power-of-two");
+ static_assert((kL1Size * kL2Size) <= (1ull << (sizeof(IndexT) * 8)),
+ "kL1Size/kL2Size are too large");
+ static_assert(((kL1Size * kL2Size - 1) & kReserved) == 0,
+ "reserved bits don't fit");
+ static_assert(sizeof(T) > sizeof(IndexT),
+ "it doesn't make sense to use dense alloc");
+
+ DenseSlabAlloc(LinkerInitialized, const char *name) : name_(name) {}
+
+ explicit DenseSlabAlloc(const char *name)
+ : DenseSlabAlloc(LINKER_INITIALIZED, name) {
+ // It can be very large.
+ // Don't page it in for linker initialized objects.
+ internal_memset(map_, 0, sizeof(map_));
+ }
+
+ ~DenseSlabAlloc() {
+ for (uptr i = 0; i < kL1Size; i++) {
+ if (map_[i] != 0)
+ UnmapOrDie(map_[i], kL2Size * sizeof(T));
+ }
+ }
+
+ IndexT Alloc(Cache *c) {
+ if (c->pos == 0)
+ Refill(c);
+ return c->cache[--c->pos];
+ }
+
+ void Free(Cache *c, IndexT idx) {
+ DCHECK_NE(idx, 0);
+ if (c->pos == Cache::kSize)
+ Drain(c);
+ c->cache[c->pos++] = idx;
+ }
+
+ T *Map(IndexT idx) {
+ DCHECK_NE(idx, 0);
+ DCHECK_LE(idx, kL1Size * kL2Size);
+ return &map_[idx / kL2Size][idx % kL2Size];
+ }
+
+ void FlushCache(Cache *c) {
+ while (c->pos) Drain(c);
+ }
+
+ void InitCache(Cache *c) {
+ c->pos = 0;
+ internal_memset(c->cache, 0, sizeof(c->cache));
+ }
+
+ uptr AllocatedMemory() const {
+ return atomic_load_relaxed(&fillpos_) * kL2Size * sizeof(T);
+ }
+
+ template <typename Func>
+ void ForEach(Func func) {
+ Lock lock(&mtx_);
+ uptr fillpos = atomic_load_relaxed(&fillpos_);
+ for (uptr l1 = 0; l1 < fillpos; l1++) {
+ for (IndexT l2 = l1 == 0 ? 1 : 0; l2 < kL2Size; l2++) func(&map_[l1][l2]);
+ }
+ }
+
+ private:
+ T *map_[kL1Size];
+ Mutex mtx_;
+ // The freelist is organized as a lock-free stack of batches of nodes.
+ // The stack itself uses Block::next links, while the batch within each
+ // stack node uses Block::batch links.
+ // Low 32-bits of freelist_ is the node index, top 32-bits is ABA-counter.
+ atomic_uint64_t freelist_ = {0};
+ atomic_uintptr_t fillpos_ = {0};
+ const char *const name_;
+
+ struct Block {
+ IndexT next;
+ IndexT batch;
+ };
+
+ Block *MapBlock(IndexT idx) { return reinterpret_cast<Block *>(Map(idx)); }
+
+ static constexpr u64 kCounterInc = 1ull << 32;
+ static constexpr u64 kCounterMask = ~(kCounterInc - 1);
+
+ NOINLINE void Refill(Cache *c) {
+ // Pop 1 batch of nodes from the freelist.
+ IndexT idx;
+ u64 xchg;
+ u64 cmp = atomic_load(&freelist_, memory_order_acquire);
+ do {
+ idx = static_cast<IndexT>(cmp);
+ if (!idx)
+ return AllocSuperBlock(c);
+ Block *ptr = MapBlock(idx);
+ xchg = ptr->next | (cmp & kCounterMask);
+ } while (!atomic_compare_exchange_weak(&freelist_, &cmp, xchg,
+ memory_order_acq_rel));
+ // Unpack it into c->cache.
+ while (idx) {
+ c->cache[c->pos++] = idx;
+ idx = MapBlock(idx)->batch;
+ }
+ }
+
+ NOINLINE void Drain(Cache *c) {
+ // Build a batch of at most Cache::kSize / 2 nodes linked by Block::batch.
+ IndexT head_idx = 0;
+ for (uptr i = 0; i < Cache::kSize / 2 && c->pos; i++) {
+ IndexT idx = c->cache[--c->pos];
+ Block *ptr = MapBlock(idx);
+ ptr->batch = head_idx;
+ head_idx = idx;
+ }
+ // Push it onto the freelist stack.
+ Block *head = MapBlock(head_idx);
+ u64 xchg;
+ u64 cmp = atomic_load(&freelist_, memory_order_acquire);
+ do {
+ head->next = static_cast<IndexT>(cmp);
+ xchg = head_idx | (cmp & kCounterMask) + kCounterInc;
+ } while (!atomic_compare_exchange_weak(&freelist_, &cmp, xchg,
+ memory_order_acq_rel));
+ }
+
+ NOINLINE void AllocSuperBlock(Cache *c) {
+ Lock lock(&mtx_);
+ uptr fillpos = atomic_load_relaxed(&fillpos_);
+ if (fillpos == kL1Size) {
+ Printf("ThreadSanitizer: %s overflow (%zu*%zu). Dying.\n", name_, kL1Size,
+ kL2Size);
+ Die();
+ }
+ VPrintf(2, "ThreadSanitizer: growing %s: %zu out of %zu*%zu\n", name_,
+ fillpos, kL1Size, kL2Size);
+ T *batch = (T *)MmapOrDie(kL2Size * sizeof(T), name_);
+ map_[fillpos] = batch;
+ // Reserve 0 as invalid index.
+ for (IndexT i = fillpos ? 0 : 1; i < kL2Size; i++) {
+ new (batch + i) T;
+ c->cache[c->pos++] = i + fillpos * kL2Size;
+ if (c->pos == Cache::kSize)
+ Drain(c);
+ }
+ atomic_store_relaxed(&fillpos_, fillpos + 1);
+ CHECK(c->pos);
+ }
+};
+
+} // namespace __tsan
+
+#endif // TSAN_DENSE_ALLOC_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_external.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_external.cpp
new file mode 100644
index 00000000000..19ae174f20a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_external.cpp
@@ -0,0 +1,126 @@
+//===-- tsan_external.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_rtl.h"
+#include "sanitizer_common/sanitizer_ptrauth.h"
+
+#if !SANITIZER_GO
+# include "tsan_interceptors.h"
+#endif
+
+namespace __tsan {
+
+#define CALLERPC ((uptr)__builtin_return_address(0))
+
+struct TagData {
+ const char *object_type;
+ const char *header;
+};
+
+static TagData registered_tags[kExternalTagMax] = {
+ {},
+ {"Swift variable", "Swift access race"},
+};
+static atomic_uint32_t used_tags{kExternalTagFirstUserAvailable};
+static TagData *GetTagData(uptr tag) {
+ // Invalid/corrupted tag? Better return NULL and let the caller deal with it.
+ if (tag >= atomic_load(&used_tags, memory_order_relaxed)) return nullptr;
+ return &registered_tags[tag];
+}
+
+const char *GetObjectTypeFromTag(uptr tag) {
+ TagData *tag_data = GetTagData(tag);
+ return tag_data ? tag_data->object_type : nullptr;
+}
+
+const char *GetReportHeaderFromTag(uptr tag) {
+ TagData *tag_data = GetTagData(tag);
+ return tag_data ? tag_data->header : nullptr;
+}
+
+void InsertShadowStackFrameForTag(ThreadState *thr, uptr tag) {
+ FuncEntry(thr, (uptr)&registered_tags[tag]);
+}
+
+uptr TagFromShadowStackFrame(uptr pc) {
+ uptr tag_count = atomic_load(&used_tags, memory_order_relaxed);
+ void *pc_ptr = (void *)pc;
+ if (pc_ptr < GetTagData(0) || pc_ptr > GetTagData(tag_count - 1))
+ return 0;
+ return (TagData *)pc_ptr - GetTagData(0);
+}
+
+#if !SANITIZER_GO
+
+void ExternalAccess(void *addr, uptr caller_pc, void *tag, AccessType typ) {
+ CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed));
+ ThreadState *thr = cur_thread();
+ if (caller_pc) FuncEntry(thr, caller_pc);
+ InsertShadowStackFrameForTag(thr, (uptr)tag);
+ bool in_ignored_lib;
+ if (!caller_pc || !libignore()->IsIgnored(caller_pc, &in_ignored_lib))
+ MemoryAccess(thr, CALLERPC, (uptr)addr, 1, typ);
+ FuncExit(thr);
+ if (caller_pc) FuncExit(thr);
+}
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__tsan_external_register_tag(const char *object_type) {
+ uptr new_tag = atomic_fetch_add(&used_tags, 1, memory_order_relaxed);
+ CHECK_LT(new_tag, kExternalTagMax);
+ GetTagData(new_tag)->object_type = internal_strdup(object_type);
+ char header[127] = {0};
+ internal_snprintf(header, sizeof(header), "race on %s", object_type);
+ GetTagData(new_tag)->header = internal_strdup(header);
+ return (void *)new_tag;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_external_register_header(void *tag, const char *header) {
+ CHECK_GE((uptr)tag, kExternalTagFirstUserAvailable);
+ CHECK_LT((uptr)tag, kExternalTagMax);
+ atomic_uintptr_t *header_ptr =
+ (atomic_uintptr_t *)&GetTagData((uptr)tag)->header;
+ header = internal_strdup(header);
+ char *old_header =
+ (char *)atomic_exchange(header_ptr, (uptr)header, memory_order_seq_cst);
+ Free(old_header);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_external_assign_tag(void *addr, void *tag) {
+ CHECK_LT(tag, atomic_load(&used_tags, memory_order_relaxed));
+ Allocator *a = allocator();
+ MBlock *b = nullptr;
+ if (a->PointerIsMine((void *)addr)) {
+ void *block_begin = a->GetBlockBegin((void *)addr);
+ if (block_begin) b = ctx->metamap.GetBlock((uptr)block_begin);
+ }
+ if (b) {
+ b->tag = (uptr)tag;
+ }
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_external_read(void *addr, void *caller_pc, void *tag) {
+ ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, kAccessRead);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_external_write(void *addr, void *caller_pc, void *tag) {
+ ExternalAccess(addr, STRIP_PAC_PC(caller_pc), tag, kAccessWrite);
+}
+} // extern "C"
+
+#endif // !SANITIZER_GO
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_fd.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_fd.cpp
new file mode 100644
index 00000000000..ab295a69dce
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_fd.cpp
@@ -0,0 +1,375 @@
+//===-- tsan_fd.cpp -------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "tsan_fd.h"
+
+#include <sanitizer_common/sanitizer_atomic.h>
+
+#include "tsan_interceptors.h"
+#include "tsan_rtl.h"
+
+namespace __tsan {
+
+const int kTableSizeL1 = 1024;
+const int kTableSizeL2 = 1024;
+const int kTableSize = kTableSizeL1 * kTableSizeL2;
+
+struct FdSync {
+ atomic_uint64_t rc;
+};
+
+struct FdDesc {
+ FdSync *sync;
+ // This is used to establish write -> epoll_wait synchronization
+ // where epoll_wait receives notification about the write.
+ atomic_uintptr_t aux_sync; // FdSync*
+ Tid creation_tid;
+ StackID creation_stack;
+ bool closed;
+};
+
+struct FdContext {
+ atomic_uintptr_t tab[kTableSizeL1];
+ // Addresses used for synchronization.
+ FdSync globsync;
+ FdSync filesync;
+ FdSync socksync;
+ u64 connectsync;
+};
+
+static FdContext fdctx;
+
+static bool bogusfd(int fd) {
+ // Apparently a bogus fd value.
+ return fd < 0 || fd >= kTableSize;
+}
+
+static FdSync *allocsync(ThreadState *thr, uptr pc) {
+ FdSync *s = (FdSync*)user_alloc_internal(thr, pc, sizeof(FdSync),
+ kDefaultAlignment, false);
+ atomic_store(&s->rc, 1, memory_order_relaxed);
+ return s;
+}
+
+static FdSync *ref(FdSync *s) {
+ if (s && atomic_load(&s->rc, memory_order_relaxed) != (u64)-1)
+ atomic_fetch_add(&s->rc, 1, memory_order_relaxed);
+ return s;
+}
+
+static void unref(ThreadState *thr, uptr pc, FdSync *s) {
+ if (s && atomic_load(&s->rc, memory_order_relaxed) != (u64)-1) {
+ if (atomic_fetch_sub(&s->rc, 1, memory_order_acq_rel) == 1) {
+ CHECK_NE(s, &fdctx.globsync);
+ CHECK_NE(s, &fdctx.filesync);
+ CHECK_NE(s, &fdctx.socksync);
+ user_free(thr, pc, s, false);
+ }
+ }
+}
+
+static FdDesc *fddesc(ThreadState *thr, uptr pc, int fd) {
+ CHECK_GE(fd, 0);
+ CHECK_LT(fd, kTableSize);
+ atomic_uintptr_t *pl1 = &fdctx.tab[fd / kTableSizeL2];
+ uptr l1 = atomic_load(pl1, memory_order_consume);
+ if (l1 == 0) {
+ uptr size = kTableSizeL2 * sizeof(FdDesc);
+ // We need this to reside in user memory to properly catch races on it.
+ void *p = user_alloc_internal(thr, pc, size, kDefaultAlignment, false);
+ internal_memset(p, 0, size);
+ MemoryResetRange(thr, (uptr)&fddesc, (uptr)p, size);
+ if (atomic_compare_exchange_strong(pl1, &l1, (uptr)p, memory_order_acq_rel))
+ l1 = (uptr)p;
+ else
+ user_free(thr, pc, p, false);
+ }
+ FdDesc *fds = reinterpret_cast<FdDesc *>(l1);
+ return &fds[fd % kTableSizeL2];
+}
+
+// pd must be already ref'ed.
+static void init(ThreadState *thr, uptr pc, int fd, FdSync *s,
+ bool write = true) {
+ FdDesc *d = fddesc(thr, pc, fd);
+ // As a matter of fact, we don't intercept all close calls.
+ // See e.g. libc __res_iclose().
+ if (d->sync) {
+ unref(thr, pc, d->sync);
+ d->sync = 0;
+ }
+ unref(thr, pc,
+ reinterpret_cast<FdSync *>(
+ atomic_load(&d->aux_sync, memory_order_relaxed)));
+ atomic_store(&d->aux_sync, 0, memory_order_relaxed);
+ if (flags()->io_sync == 0) {
+ unref(thr, pc, s);
+ } else if (flags()->io_sync == 1) {
+ d->sync = s;
+ } else if (flags()->io_sync == 2) {
+ unref(thr, pc, s);
+ d->sync = &fdctx.globsync;
+ }
+ d->creation_tid = thr->tid;
+ d->creation_stack = CurrentStackId(thr, pc);
+ d->closed = false;
+ // This prevents false positives on fd_close_norace3.cpp test.
+ // The mechanics of the false positive are not completely clear,
+ // but it happens only if global reset is enabled (flush_memory_ms=1)
+ // and may be related to lost writes during asynchronous MADV_DONTNEED.
+ SlotLocker locker(thr);
+ if (write) {
+ // To catch races between fd usage and open.
+ MemoryRangeImitateWrite(thr, pc, (uptr)d, 8);
+ } else {
+ // See the dup-related comment in FdClose.
+ MemoryAccess(thr, pc, (uptr)d, 8, kAccessRead | kAccessSlotLocked);
+ }
+}
+
+void FdInit() {
+ atomic_store(&fdctx.globsync.rc, (u64)-1, memory_order_relaxed);
+ atomic_store(&fdctx.filesync.rc, (u64)-1, memory_order_relaxed);
+ atomic_store(&fdctx.socksync.rc, (u64)-1, memory_order_relaxed);
+}
+
+void FdOnFork(ThreadState *thr, uptr pc) {
+ // On fork() we need to reset all fd's, because the child is going
+ // close all them, and that will cause races between previous read/write
+ // and the close.
+ for (int l1 = 0; l1 < kTableSizeL1; l1++) {
+ FdDesc *tab = (FdDesc*)atomic_load(&fdctx.tab[l1], memory_order_relaxed);
+ if (tab == 0)
+ break;
+ for (int l2 = 0; l2 < kTableSizeL2; l2++) {
+ FdDesc *d = &tab[l2];
+ MemoryResetRange(thr, pc, (uptr)d, 8);
+ }
+ }
+}
+
+bool FdLocation(uptr addr, int *fd, Tid *tid, StackID *stack, bool *closed) {
+ for (int l1 = 0; l1 < kTableSizeL1; l1++) {
+ FdDesc *tab = (FdDesc*)atomic_load(&fdctx.tab[l1], memory_order_relaxed);
+ if (tab == 0)
+ break;
+ if (addr >= (uptr)tab && addr < (uptr)(tab + kTableSizeL2)) {
+ int l2 = (addr - (uptr)tab) / sizeof(FdDesc);
+ FdDesc *d = &tab[l2];
+ *fd = l1 * kTableSizeL1 + l2;
+ *tid = d->creation_tid;
+ *stack = d->creation_stack;
+ *closed = d->closed;
+ return true;
+ }
+ }
+ return false;
+}
+
+void FdAcquire(ThreadState *thr, uptr pc, int fd) {
+ if (bogusfd(fd))
+ return;
+ FdDesc *d = fddesc(thr, pc, fd);
+ FdSync *s = d->sync;
+ DPrintf("#%d: FdAcquire(%d) -> %p\n", thr->tid, fd, s);
+ MemoryAccess(thr, pc, (uptr)d, 8, kAccessRead);
+ if (s)
+ Acquire(thr, pc, (uptr)s);
+}
+
+void FdRelease(ThreadState *thr, uptr pc, int fd) {
+ if (bogusfd(fd))
+ return;
+ FdDesc *d = fddesc(thr, pc, fd);
+ FdSync *s = d->sync;
+ DPrintf("#%d: FdRelease(%d) -> %p\n", thr->tid, fd, s);
+ MemoryAccess(thr, pc, (uptr)d, 8, kAccessRead);
+ if (s)
+ Release(thr, pc, (uptr)s);
+ if (uptr aux_sync = atomic_load(&d->aux_sync, memory_order_acquire))
+ Release(thr, pc, aux_sync);
+}
+
+void FdAccess(ThreadState *thr, uptr pc, int fd) {
+ DPrintf("#%d: FdAccess(%d)\n", thr->tid, fd);
+ if (bogusfd(fd))
+ return;
+ FdDesc *d = fddesc(thr, pc, fd);
+ MemoryAccess(thr, pc, (uptr)d, 8, kAccessRead);
+}
+
+void FdClose(ThreadState *thr, uptr pc, int fd, bool write) {
+ DPrintf("#%d: FdClose(%d)\n", thr->tid, fd);
+ if (bogusfd(fd))
+ return;
+ FdDesc *d = fddesc(thr, pc, fd);
+ {
+ // Need to lock the slot to make MemoryAccess and MemoryResetRange atomic
+ // with respect to global reset. See the comment in MemoryRangeFreed.
+ SlotLocker locker(thr);
+ if (!MustIgnoreInterceptor(thr)) {
+ if (write) {
+ // To catch races between fd usage and close.
+ MemoryAccess(thr, pc, (uptr)d, 8,
+ kAccessWrite | kAccessCheckOnly | kAccessSlotLocked);
+ } else {
+ // This path is used only by dup2/dup3 calls.
+ // We do read instead of write because there is a number of legitimate
+ // cases where write would lead to false positives:
+ // 1. Some software dups a closed pipe in place of a socket before
+ // closing
+ // the socket (to prevent races actually).
+ // 2. Some daemons dup /dev/null in place of stdin/stdout.
+ // On the other hand we have not seen cases when write here catches real
+ // bugs.
+ MemoryAccess(thr, pc, (uptr)d, 8,
+ kAccessRead | kAccessCheckOnly | kAccessSlotLocked);
+ }
+ }
+ // We need to clear it, because if we do not intercept any call out there
+ // that creates fd, we will hit false postives.
+ MemoryResetRange(thr, pc, (uptr)d, 8);
+ }
+ unref(thr, pc, d->sync);
+ d->sync = 0;
+ unref(thr, pc,
+ reinterpret_cast<FdSync *>(
+ atomic_load(&d->aux_sync, memory_order_relaxed)));
+ atomic_store(&d->aux_sync, 0, memory_order_relaxed);
+ d->closed = true;
+ d->creation_tid = thr->tid;
+ d->creation_stack = CurrentStackId(thr, pc);
+}
+
+void FdFileCreate(ThreadState *thr, uptr pc, int fd) {
+ DPrintf("#%d: FdFileCreate(%d)\n", thr->tid, fd);
+ if (bogusfd(fd))
+ return;
+ init(thr, pc, fd, &fdctx.filesync);
+}
+
+void FdDup(ThreadState *thr, uptr pc, int oldfd, int newfd, bool write) {
+ DPrintf("#%d: FdDup(%d, %d)\n", thr->tid, oldfd, newfd);
+ if (bogusfd(oldfd) || bogusfd(newfd))
+ return;
+ // Ignore the case when user dups not yet connected socket.
+ FdDesc *od = fddesc(thr, pc, oldfd);
+ MemoryAccess(thr, pc, (uptr)od, 8, kAccessRead);
+ FdClose(thr, pc, newfd, write);
+ init(thr, pc, newfd, ref(od->sync), write);
+}
+
+void FdPipeCreate(ThreadState *thr, uptr pc, int rfd, int wfd) {
+ DPrintf("#%d: FdCreatePipe(%d, %d)\n", thr->tid, rfd, wfd);
+ FdSync *s = allocsync(thr, pc);
+ init(thr, pc, rfd, ref(s));
+ init(thr, pc, wfd, ref(s));
+ unref(thr, pc, s);
+}
+
+void FdEventCreate(ThreadState *thr, uptr pc, int fd) {
+ DPrintf("#%d: FdEventCreate(%d)\n", thr->tid, fd);
+ if (bogusfd(fd))
+ return;
+ init(thr, pc, fd, allocsync(thr, pc));
+}
+
+void FdSignalCreate(ThreadState *thr, uptr pc, int fd) {
+ DPrintf("#%d: FdSignalCreate(%d)\n", thr->tid, fd);
+ if (bogusfd(fd))
+ return;
+ init(thr, pc, fd, 0);
+}
+
+void FdInotifyCreate(ThreadState *thr, uptr pc, int fd) {
+ DPrintf("#%d: FdInotifyCreate(%d)\n", thr->tid, fd);
+ if (bogusfd(fd))
+ return;
+ init(thr, pc, fd, 0);
+}
+
+void FdPollCreate(ThreadState *thr, uptr pc, int fd) {
+ DPrintf("#%d: FdPollCreate(%d)\n", thr->tid, fd);
+ if (bogusfd(fd))
+ return;
+ init(thr, pc, fd, allocsync(thr, pc));
+}
+
+void FdPollAdd(ThreadState *thr, uptr pc, int epfd, int fd) {
+ DPrintf("#%d: FdPollAdd(%d, %d)\n", thr->tid, epfd, fd);
+ if (bogusfd(epfd) || bogusfd(fd))
+ return;
+ FdDesc *d = fddesc(thr, pc, fd);
+ // Associate fd with epoll fd only once.
+ // While an fd can be associated with multiple epolls at the same time,
+ // or with different epolls during different phases of lifetime,
+ // synchronization semantics (and examples) of this are unclear.
+ // So we don't support this for now.
+ // If we change the association, it will also create lifetime management
+ // problem for FdRelease which accesses the aux_sync.
+ if (atomic_load(&d->aux_sync, memory_order_relaxed))
+ return;
+ FdDesc *epd = fddesc(thr, pc, epfd);
+ FdSync *s = epd->sync;
+ if (!s)
+ return;
+ uptr cmp = 0;
+ if (atomic_compare_exchange_strong(
+ &d->aux_sync, &cmp, reinterpret_cast<uptr>(s), memory_order_release))
+ ref(s);
+}
+
+void FdSocketCreate(ThreadState *thr, uptr pc, int fd) {
+ DPrintf("#%d: FdSocketCreate(%d)\n", thr->tid, fd);
+ if (bogusfd(fd))
+ return;
+ // It can be a UDP socket.
+ init(thr, pc, fd, &fdctx.socksync);
+}
+
+void FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd) {
+ DPrintf("#%d: FdSocketAccept(%d, %d)\n", thr->tid, fd, newfd);
+ if (bogusfd(fd))
+ return;
+ // Synchronize connect->accept.
+ Acquire(thr, pc, (uptr)&fdctx.connectsync);
+ init(thr, pc, newfd, &fdctx.socksync);
+}
+
+void FdSocketConnecting(ThreadState *thr, uptr pc, int fd) {
+ DPrintf("#%d: FdSocketConnecting(%d)\n", thr->tid, fd);
+ if (bogusfd(fd))
+ return;
+ // Synchronize connect->accept.
+ Release(thr, pc, (uptr)&fdctx.connectsync);
+}
+
+void FdSocketConnect(ThreadState *thr, uptr pc, int fd) {
+ DPrintf("#%d: FdSocketConnect(%d)\n", thr->tid, fd);
+ if (bogusfd(fd))
+ return;
+ init(thr, pc, fd, &fdctx.socksync);
+}
+
+uptr File2addr(const char *path) {
+ (void)path;
+ static u64 addr;
+ return (uptr)&addr;
+}
+
+uptr Dir2addr(const char *path) {
+ (void)path;
+ static u64 addr;
+ return (uptr)&addr;
+}
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_fd.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_fd.h
new file mode 100644
index 00000000000..dddc1d2ab24
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_fd.h
@@ -0,0 +1,65 @@
+//===-- tsan_fd.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// This file handles synchronization via IO.
+// People use IO for synchronization along the lines of:
+//
+// int X;
+// int client_socket; // initialized elsewhere
+// int server_socket; // initialized elsewhere
+//
+// Thread 1:
+// X = 42;
+// send(client_socket, ...);
+//
+// Thread 2:
+// if (recv(server_socket, ...) > 0)
+// assert(X == 42);
+//
+// This file determines the scope of the file descriptor (pipe, socket,
+// all local files, etc) and executes acquire and release operations on
+// the scope as necessary. Some scopes are very fine grained (e.g. pipe
+// operations synchronize only with operations on the same pipe), while
+// others are corse-grained (e.g. all operations on local files synchronize
+// with each other).
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_FD_H
+#define TSAN_FD_H
+
+#include "tsan_rtl.h"
+
+namespace __tsan {
+
+void FdInit();
+void FdAcquire(ThreadState *thr, uptr pc, int fd);
+void FdRelease(ThreadState *thr, uptr pc, int fd);
+void FdAccess(ThreadState *thr, uptr pc, int fd);
+void FdClose(ThreadState *thr, uptr pc, int fd, bool write = true);
+void FdFileCreate(ThreadState *thr, uptr pc, int fd);
+void FdDup(ThreadState *thr, uptr pc, int oldfd, int newfd, bool write);
+void FdPipeCreate(ThreadState *thr, uptr pc, int rfd, int wfd);
+void FdEventCreate(ThreadState *thr, uptr pc, int fd);
+void FdSignalCreate(ThreadState *thr, uptr pc, int fd);
+void FdInotifyCreate(ThreadState *thr, uptr pc, int fd);
+void FdPollCreate(ThreadState *thr, uptr pc, int fd);
+void FdPollAdd(ThreadState *thr, uptr pc, int epfd, int fd);
+void FdSocketCreate(ThreadState *thr, uptr pc, int fd);
+void FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd);
+void FdSocketConnecting(ThreadState *thr, uptr pc, int fd);
+void FdSocketConnect(ThreadState *thr, uptr pc, int fd);
+bool FdLocation(uptr addr, int *fd, Tid *tid, StackID *stack, bool *closed);
+void FdOnFork(ThreadState *thr, uptr pc);
+
+uptr File2addr(const char *path);
+uptr Dir2addr(const char *path);
+
+} // namespace __tsan
+
+#endif // TSAN_INTERFACE_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_flags.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_flags.cpp
new file mode 100644
index 00000000000..ee78f25cc65
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_flags.cpp
@@ -0,0 +1,120 @@
+//===-- tsan_flags.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "tsan_flags.h"
+#include "tsan_rtl.h"
+#include "tsan_mman.h"
+#include "ubsan/ubsan_flags.h"
+
+namespace __tsan {
+
+// Can be overriden in frontend.
+#ifdef TSAN_EXTERNAL_HOOKS
+extern "C" const char* __tsan_default_options();
+#else
+SANITIZER_WEAK_DEFAULT_IMPL
+const char *__tsan_default_options() {
+ return "";
+}
+#endif
+
+void Flags::SetDefaults() {
+#define TSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "tsan_flags.inc"
+#undef TSAN_FLAG
+ // DDFlags
+ second_deadlock_stack = false;
+}
+
+void RegisterTsanFlags(FlagParser *parser, Flags *f) {
+#define TSAN_FLAG(Type, Name, DefaultValue, Description) \
+ RegisterFlag(parser, #Name, Description, &f->Name);
+#include "tsan_flags.inc"
+#undef TSAN_FLAG
+ // DDFlags
+ RegisterFlag(parser, "second_deadlock_stack",
+ "Report where each mutex is locked in deadlock reports",
+ &f->second_deadlock_stack);
+}
+
+void InitializeFlags(Flags *f, const char *env, const char *env_option_name) {
+ SetCommonFlagsDefaults();
+ {
+ // Override some common flags defaults.
+ CommonFlags cf;
+ cf.CopyFrom(*common_flags());
+ cf.external_symbolizer_path = GetEnv("TSAN_SYMBOLIZER_PATH");
+ cf.allow_addr2line = true;
+ if (SANITIZER_GO) {
+ // Does not work as expected for Go: runtime handles SIGABRT and crashes.
+ cf.abort_on_error = false;
+ // Go does not have mutexes.
+ cf.detect_deadlocks = false;
+ }
+ cf.print_suppressions = false;
+ cf.stack_trace_format = " #%n %f %S %M";
+ cf.exitcode = 66;
+ cf.intercept_tls_get_addr = true;
+ OverrideCommonFlags(cf);
+ }
+
+ f->SetDefaults();
+
+ FlagParser parser;
+ RegisterTsanFlags(&parser, f);
+ RegisterCommonFlags(&parser);
+
+#if TSAN_CONTAINS_UBSAN
+ __ubsan::Flags *uf = __ubsan::flags();
+ uf->SetDefaults();
+
+ FlagParser ubsan_parser;
+ __ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
+ RegisterCommonFlags(&ubsan_parser);
+#endif
+
+ // Let a frontend override.
+ parser.ParseString(__tsan_default_options());
+#if TSAN_CONTAINS_UBSAN
+ const char *ubsan_default_options = __ubsan_default_options();
+ ubsan_parser.ParseString(ubsan_default_options);
+#endif
+ // Override from command line.
+ parser.ParseString(env, env_option_name);
+#if TSAN_CONTAINS_UBSAN
+ ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
+#endif
+
+ // Check flags.
+ if (!f->report_bugs) {
+ f->report_thread_leaks = false;
+ f->report_destroy_locked = false;
+ f->report_signal_unsafe = false;
+ }
+
+ InitializeCommonFlags();
+
+ if (Verbosity()) ReportUnrecognizedFlags();
+
+ if (common_flags()->help) parser.PrintFlagDescriptions();
+
+ if (f->io_sync < 0 || f->io_sync > 2) {
+ Printf("ThreadSanitizer: incorrect value for io_sync"
+ " (must be [0..2])\n");
+ Die();
+ }
+}
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_flags.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_flags.h
new file mode 100644
index 00000000000..da27d5b992b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_flags.h
@@ -0,0 +1,34 @@
+//===-- tsan_flags.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+// NOTE: This file may be included into user code.
+//===----------------------------------------------------------------------===//
+
+#ifndef TSAN_FLAGS_H
+#define TSAN_FLAGS_H
+
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
+
+namespace __tsan {
+
+struct Flags : DDFlags {
+#define TSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "tsan_flags.inc"
+#undef TSAN_FLAG
+
+ void SetDefaults();
+ void ParseFromString(const char *str);
+};
+
+void InitializeFlags(Flags *flags, const char *env,
+ const char *env_option_name = nullptr);
+} // namespace __tsan
+
+#endif // TSAN_FLAGS_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_flags.inc b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_flags.inc
new file mode 100644
index 00000000000..731d776cc89
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_flags.inc
@@ -0,0 +1,82 @@
+//===-- tsan_flags.inc ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// TSan runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_FLAG
+# error "Define TSAN_FLAG prior to including this file!"
+#endif
+
+// TSAN_FLAG(Type, Name, DefaultValue, Description)
+// See COMMON_FLAG in sanitizer_flags.inc for more details.
+
+TSAN_FLAG(bool, enable_annotations, true,
+ "Enable dynamic annotations, otherwise they are no-ops.")
+// Suppress a race report if we've already output another race report
+// with the same stack.
+TSAN_FLAG(bool, suppress_equal_stacks, true,
+ "Suppress a race report if we've already output another race report "
+ "with the same stack.")
+TSAN_FLAG(bool, report_bugs, true,
+ "Turns off bug reporting entirely (useful for benchmarking).")
+TSAN_FLAG(bool, report_thread_leaks, true, "Report thread leaks at exit?")
+TSAN_FLAG(bool, report_destroy_locked, true,
+ "Report destruction of a locked mutex?")
+TSAN_FLAG(bool, report_mutex_bugs, true,
+ "Report incorrect usages of mutexes and mutex annotations?")
+TSAN_FLAG(bool, report_signal_unsafe, true,
+ "Report violations of async signal-safety "
+ "(e.g. malloc() call from a signal handler).")
+TSAN_FLAG(bool, report_atomic_races, true,
+ "Report races between atomic and plain memory accesses.")
+TSAN_FLAG(
+ bool, force_seq_cst_atomics, false,
+ "If set, all atomics are effectively sequentially consistent (seq_cst), "
+ "regardless of what user actually specified.")
+TSAN_FLAG(bool, force_background_thread, false,
+ "If set, eagerly launch a background thread for memory reclamation "
+ "instead of waiting for a user call to pthread_create.")
+TSAN_FLAG(bool, halt_on_error, false, "Exit after first reported error.")
+TSAN_FLAG(int, atexit_sleep_ms, 1000,
+ "Sleep in main thread before exiting for that many ms "
+ "(useful to catch \"at exit\" races).")
+TSAN_FLAG(const char *, profile_memory, "",
+ "If set, periodically write memory profile to that file.")
+TSAN_FLAG(int, flush_memory_ms, 0, "Flush shadow memory every X ms.")
+TSAN_FLAG(int, flush_symbolizer_ms, 5000, "Flush symbolizer caches every X ms.")
+TSAN_FLAG(
+ int, memory_limit_mb, 0,
+ "Resident memory limit in MB to aim at."
+ "If the process consumes more memory, then TSan will flush shadow memory.")
+TSAN_FLAG(bool, stop_on_start, false,
+ "Stops on start until __tsan_resume() is called (for debugging).")
+TSAN_FLAG(bool, running_on_valgrind, false,
+ "Controls whether RunningOnValgrind() returns true or false.")
+TSAN_FLAG(
+ uptr, history_size, 0,
+ "Per-thread history size,"
+ " controls how many extra previous memory accesses are remembered per thread.")
+TSAN_FLAG(int, io_sync, 1,
+ "Controls level of synchronization implied by IO operations. "
+ "0 - no synchronization "
+ "1 - reasonable level of synchronization (write->read)"
+ "2 - global synchronization of all IO operations.")
+TSAN_FLAG(bool, die_after_fork, true,
+ "Die after multi-threaded fork if the child creates new threads.")
+TSAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
+TSAN_FLAG(bool, ignore_interceptors_accesses, SANITIZER_APPLE ? true : false,
+ "Ignore reads and writes from all interceptors.")
+TSAN_FLAG(bool, ignore_noninstrumented_modules, SANITIZER_APPLE ? true : false,
+ "Interceptors should only detect races when called from instrumented "
+ "modules.")
+TSAN_FLAG(bool, shared_ptr_interceptor, true,
+ "Track atomic reference counting in libc++ shared_ptr and weak_ptr.")
+TSAN_FLAG(bool, print_full_thread_history, false,
+ "If set, prints thread creation stacks for the threads involved in "
+ "the report and their ancestors up to the main thread.")
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_ignoreset.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_ignoreset.cpp
new file mode 100644
index 00000000000..1fca1cf4f9f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_ignoreset.cpp
@@ -0,0 +1,38 @@
+//===-- tsan_ignoreset.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_ignoreset.h"
+
+namespace __tsan {
+
+const uptr IgnoreSet::kMaxSize;
+
+IgnoreSet::IgnoreSet()
+ : size_() {
+}
+
+void IgnoreSet::Add(StackID stack_id) {
+ if (size_ == kMaxSize)
+ return;
+ for (uptr i = 0; i < size_; i++) {
+ if (stacks_[i] == stack_id)
+ return;
+ }
+ stacks_[size_++] = stack_id;
+}
+
+StackID IgnoreSet::At(uptr i) const {
+ CHECK_LT(i, size_);
+ CHECK_LE(size_, kMaxSize);
+ return stacks_[i];
+}
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_ignoreset.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_ignoreset.h
new file mode 100644
index 00000000000..4e2511291ce
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_ignoreset.h
@@ -0,0 +1,36 @@
+//===-- tsan_ignoreset.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// IgnoreSet holds a set of stack traces where ignores were enabled.
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_IGNORESET_H
+#define TSAN_IGNORESET_H
+
+#include "tsan_defs.h"
+
+namespace __tsan {
+
+class IgnoreSet {
+ public:
+ IgnoreSet();
+ void Add(StackID stack_id);
+ void Reset() { size_ = 0; }
+ uptr Size() const { return size_; }
+ StackID At(uptr i) const;
+
+ private:
+ static constexpr uptr kMaxSize = 16;
+ uptr size_;
+ StackID stacks_[kMaxSize];
+};
+
+} // namespace __tsan
+
+#endif // TSAN_IGNORESET_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_ilist.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_ilist.h
new file mode 100644
index 00000000000..d7d8be219db
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_ilist.h
@@ -0,0 +1,189 @@
+//===-- tsan_ilist.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_ILIST_H
+#define TSAN_ILIST_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __tsan {
+
+class INode {
+ public:
+ INode() = default;
+
+ private:
+ INode* next_ = nullptr;
+ INode* prev_ = nullptr;
+
+ template <typename Base, INode Base::*Node, typename Elem>
+ friend class IList;
+ INode(const INode&) = delete;
+ void operator=(const INode&) = delete;
+};
+
+// Intrusive doubly-linked list.
+//
+// The node class (MyNode) needs to include "INode foo" field,
+// then the list can be declared as IList<MyNode, &MyNode::foo>.
+// This design allows to link MyNode into multiple lists using
+// different INode fields.
+// The optional Elem template argument allows to specify node MDT
+// (most derived type) if it's different from MyNode.
+template <typename Base, INode Base::*Node, typename Elem = Base>
+class IList {
+ public:
+ IList();
+
+ void PushFront(Elem* e);
+ void PushBack(Elem* e);
+ void Remove(Elem* e);
+
+ Elem* PopFront();
+ Elem* PopBack();
+ Elem* Front();
+ Elem* Back();
+
+ // Prev links point towards front of the queue.
+ Elem* Prev(Elem* e);
+ // Next links point towards back of the queue.
+ Elem* Next(Elem* e);
+
+ uptr Size() const;
+ bool Empty() const;
+ bool Queued(Elem* e) const;
+
+ private:
+ INode node_;
+ uptr size_ = 0;
+
+ void Push(Elem* e, INode* after);
+ static INode* ToNode(Elem* e);
+ static Elem* ToElem(INode* n);
+
+ IList(const IList&) = delete;
+ void operator=(const IList&) = delete;
+};
+
+template <typename Base, INode Base::*Node, typename Elem>
+IList<Base, Node, Elem>::IList() {
+ node_.next_ = node_.prev_ = &node_;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+void IList<Base, Node, Elem>::PushFront(Elem* e) {
+ Push(e, &node_);
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+void IList<Base, Node, Elem>::PushBack(Elem* e) {
+ Push(e, node_.prev_);
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+void IList<Base, Node, Elem>::Push(Elem* e, INode* after) {
+ INode* n = ToNode(e);
+ DCHECK_EQ(n->next_, nullptr);
+ DCHECK_EQ(n->prev_, nullptr);
+ INode* next = after->next_;
+ n->next_ = next;
+ n->prev_ = after;
+ next->prev_ = n;
+ after->next_ = n;
+ size_++;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+void IList<Base, Node, Elem>::Remove(Elem* e) {
+ INode* n = ToNode(e);
+ INode* next = n->next_;
+ INode* prev = n->prev_;
+ DCHECK(next);
+ DCHECK(prev);
+ DCHECK(size_);
+ next->prev_ = prev;
+ prev->next_ = next;
+ n->prev_ = n->next_ = nullptr;
+ size_--;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::PopFront() {
+ Elem* e = Front();
+ if (e)
+ Remove(e);
+ return e;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::PopBack() {
+ Elem* e = Back();
+ if (e)
+ Remove(e);
+ return e;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::Front() {
+ return size_ ? ToElem(node_.next_) : nullptr;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::Back() {
+ return size_ ? ToElem(node_.prev_) : nullptr;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::Prev(Elem* e) {
+ INode* n = ToNode(e);
+ DCHECK(n->prev_);
+ return n->prev_ != &node_ ? ToElem(n->prev_) : nullptr;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::Next(Elem* e) {
+ INode* n = ToNode(e);
+ DCHECK(n->next_);
+ return n->next_ != &node_ ? ToElem(n->next_) : nullptr;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+uptr IList<Base, Node, Elem>::Size() const {
+ return size_;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+bool IList<Base, Node, Elem>::Empty() const {
+ return size_ == 0;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+bool IList<Base, Node, Elem>::Queued(Elem* e) const {
+ INode* n = ToNode(e);
+ DCHECK_EQ(!n->next_, !n->prev_);
+ return n->next_;
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+INode* IList<Base, Node, Elem>::ToNode(Elem* e) {
+ return &(e->*Node);
+}
+
+template <typename Base, INode Base::*Node, typename Elem>
+Elem* IList<Base, Node, Elem>::ToElem(INode* n) {
+ return static_cast<Elem*>(reinterpret_cast<Base*>(
+ reinterpret_cast<uptr>(n) -
+ reinterpret_cast<uptr>(&(reinterpret_cast<Elem*>(0)->*Node))));
+}
+
+} // namespace __tsan
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors.h
new file mode 100644
index 00000000000..60fbc58f988
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors.h
@@ -0,0 +1,106 @@
+#ifndef TSAN_INTERCEPTORS_H
+#define TSAN_INTERCEPTORS_H
+
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "tsan_rtl.h"
+
+namespace __tsan {
+
+class ScopedInterceptor {
+ public:
+ ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc);
+ ~ScopedInterceptor();
+ void DisableIgnores() {
+ if (UNLIKELY(ignoring_))
+ DisableIgnoresImpl();
+ }
+ void EnableIgnores() {
+ if (UNLIKELY(ignoring_))
+ EnableIgnoresImpl();
+ }
+
+ private:
+ ThreadState *const thr_;
+ bool in_ignored_lib_ = false;
+ bool in_blocking_func_ = false;
+ bool ignoring_ = false;
+
+ void DisableIgnoresImpl();
+ void EnableIgnoresImpl();
+};
+
+LibIgnore *libignore();
+
+#if !SANITIZER_GO
+inline bool in_symbolizer() {
+ return UNLIKELY(cur_thread_init()->in_symbolizer);
+}
+#endif
+
+inline bool MustIgnoreInterceptor(ThreadState *thr) {
+ return !thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib;
+}
+
+} // namespace __tsan
+
+#define SCOPED_INTERCEPTOR_RAW(func, ...) \
+ ThreadState *thr = cur_thread_init(); \
+ ScopedInterceptor si(thr, #func, GET_CALLER_PC()); \
+ UNUSED const uptr pc = GET_CURRENT_PC();
+
+#ifdef __powerpc64__
+// Debugging of crashes on powerpc after commit:
+// c80604f7a3 ("tsan: remove real func check from interceptors")
+// Somehow replacing if with DCHECK leads to strange failures in:
+// SanitizerCommon-tsan-powerpc64le-Linux :: Linux/ptrace.cpp
+// https://lab.llvm.org/buildbot/#/builders/105
+// https://lab.llvm.org/buildbot/#/builders/121
+// https://lab.llvm.org/buildbot/#/builders/57
+# define CHECK_REAL_FUNC(func) \
+ if (REAL(func) == 0) { \
+ Report("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \
+ Die(); \
+ }
+#else
+# define CHECK_REAL_FUNC(func) DCHECK(REAL(func))
+#endif
+
+#define SCOPED_TSAN_INTERCEPTOR(func, ...) \
+ SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
+ CHECK_REAL_FUNC(func); \
+ if (MustIgnoreInterceptor(thr)) \
+ return REAL(func)(__VA_ARGS__);
+
+#define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START() \
+ si.DisableIgnores();
+
+#define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END() \
+ si.EnableIgnores();
+
+#define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__)
+
+#if SANITIZER_FREEBSD
+# define TSAN_INTERCEPTOR_FREEBSD_ALIAS(ret, func, ...) \
+ TSAN_INTERCEPTOR(ret, _pthread_##func, __VA_ARGS__) \
+ ALIAS(WRAPPER_NAME(pthread_##func));
+#else
+# define TSAN_INTERCEPTOR_FREEBSD_ALIAS(ret, func, ...)
+#endif
+
+#if SANITIZER_NETBSD
+# define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...) \
+ TSAN_INTERCEPTOR(ret, __libc_##func, __VA_ARGS__) \
+ ALIAS(WRAPPER_NAME(pthread_##func));
+# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...) \
+ TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \
+ ALIAS(WRAPPER_NAME(pthread_##func));
+# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...) \
+ TSAN_INTERCEPTOR(ret, __libc_thr_##func, __VA_ARGS__) \
+ ALIAS(WRAPPER_NAME(pthread_##func2));
+#else
+# define TSAN_INTERCEPTOR_NETBSD_ALIAS(ret, func, ...)
+# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(ret, func, ...)
+# define TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(ret, func, func2, ...)
+#endif
+
+#endif // TSAN_INTERCEPTORS_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_libdispatch.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_libdispatch.cpp
new file mode 100644
index 00000000000..88d5f0a4811
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_libdispatch.cpp
@@ -0,0 +1,814 @@
+//===-- tsan_interceptors_libdispatch.cpp ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Support for intercepting libdispatch (GCD).
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "interception/interception.h"
+#include "tsan_interceptors.h"
+#include "tsan_rtl.h"
+
+#include "BlocksRuntime/Block.h"
+#include "tsan_dispatch_defs.h"
+
+#if SANITIZER_APPLE
+# include <Availability.h>
+#endif
+
+namespace __tsan {
+ typedef u16 uint16_t;
+
+typedef struct {
+ dispatch_queue_t queue;
+ void *orig_context;
+ dispatch_function_t orig_work;
+ bool free_context_in_callback;
+ bool submitted_synchronously;
+ bool is_barrier_block;
+ uptr non_queue_sync_object;
+} block_context_t;
+
+// The offsets of different fields of the dispatch_queue_t structure, exported
+// by libdispatch.dylib.
+extern "C" struct dispatch_queue_offsets_s {
+ const uint16_t dqo_version;
+ const uint16_t dqo_label;
+ const uint16_t dqo_label_size;
+ const uint16_t dqo_flags;
+ const uint16_t dqo_flags_size;
+ const uint16_t dqo_serialnum;
+ const uint16_t dqo_serialnum_size;
+ const uint16_t dqo_width;
+ const uint16_t dqo_width_size;
+ const uint16_t dqo_running;
+ const uint16_t dqo_running_size;
+ const uint16_t dqo_suspend_cnt;
+ const uint16_t dqo_suspend_cnt_size;
+ const uint16_t dqo_target_queue;
+ const uint16_t dqo_target_queue_size;
+ const uint16_t dqo_priority;
+ const uint16_t dqo_priority_size;
+} dispatch_queue_offsets;
+
+static bool IsQueueSerial(dispatch_queue_t q) {
+ CHECK_EQ(dispatch_queue_offsets.dqo_width_size, 2);
+ uptr width = *(uint16_t *)(((uptr)q) + dispatch_queue_offsets.dqo_width);
+ CHECK_NE(width, 0);
+ return width == 1;
+}
+
+static dispatch_queue_t GetTargetQueueFromQueue(dispatch_queue_t q) {
+ CHECK_EQ(dispatch_queue_offsets.dqo_target_queue_size, 8);
+ dispatch_queue_t tq = *(
+ dispatch_queue_t *)(((uptr)q) + dispatch_queue_offsets.dqo_target_queue);
+ return tq;
+}
+
+static dispatch_queue_t GetTargetQueueFromSource(dispatch_source_t source) {
+ dispatch_queue_t tq = GetTargetQueueFromQueue((dispatch_queue_t)source);
+ CHECK_NE(tq, 0);
+ return tq;
+}
+
+static block_context_t *AllocContext(ThreadState *thr, uptr pc,
+ dispatch_queue_t queue, void *orig_context,
+ dispatch_function_t orig_work) {
+ block_context_t *new_context =
+ (block_context_t *)user_alloc_internal(thr, pc, sizeof(block_context_t));
+ new_context->queue = queue;
+ new_context->orig_context = orig_context;
+ new_context->orig_work = orig_work;
+ new_context->free_context_in_callback = true;
+ new_context->submitted_synchronously = false;
+ new_context->is_barrier_block = false;
+ new_context->non_queue_sync_object = 0;
+ return new_context;
+}
+
+#define GET_QUEUE_SYNC_VARS(context, q) \
+ bool is_queue_serial = q && IsQueueSerial(q); \
+ uptr sync_ptr = (uptr)q ?: context->non_queue_sync_object; \
+ uptr serial_sync = (uptr)sync_ptr; \
+ uptr concurrent_sync = sync_ptr ? ((uptr)sync_ptr) + sizeof(uptr) : 0; \
+ bool serial_task = context->is_barrier_block || is_queue_serial
+
+static void dispatch_sync_pre_execute(ThreadState *thr, uptr pc,
+ block_context_t *context) {
+ uptr submit_sync = (uptr)context;
+ Acquire(thr, pc, submit_sync);
+
+ dispatch_queue_t q = context->queue;
+ do {
+ GET_QUEUE_SYNC_VARS(context, q);
+ if (serial_sync) Acquire(thr, pc, serial_sync);
+ if (serial_task && concurrent_sync) Acquire(thr, pc, concurrent_sync);
+
+ if (q) q = GetTargetQueueFromQueue(q);
+ } while (q);
+}
+
+static void dispatch_sync_post_execute(ThreadState *thr, uptr pc,
+ block_context_t *context) {
+ uptr submit_sync = (uptr)context;
+ if (context->submitted_synchronously) Release(thr, pc, submit_sync);
+
+ dispatch_queue_t q = context->queue;
+ do {
+ GET_QUEUE_SYNC_VARS(context, q);
+ if (serial_task && serial_sync) Release(thr, pc, serial_sync);
+ if (!serial_task && concurrent_sync) Release(thr, pc, concurrent_sync);
+
+ if (q) q = GetTargetQueueFromQueue(q);
+ } while (q);
+}
+
+static void dispatch_callback_wrap(void *param) {
+ SCOPED_INTERCEPTOR_RAW(dispatch_callback_wrap);
+ block_context_t *context = (block_context_t *)param;
+
+ dispatch_sync_pre_execute(thr, pc, context);
+
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+ context->orig_work(context->orig_context);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+
+ dispatch_sync_post_execute(thr, pc, context);
+
+ if (context->free_context_in_callback) user_free(thr, pc, context);
+}
+
+static void invoke_block(void *param) {
+ dispatch_block_t block = (dispatch_block_t)param;
+ block();
+}
+
+static void invoke_and_release_block(void *param) {
+ dispatch_block_t block = (dispatch_block_t)param;
+ block();
+ Block_release(block);
+}
+
+#define DISPATCH_INTERCEPT_ASYNC_B(name, barrier) \
+ TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, dispatch_block_t block) { \
+ SCOPED_TSAN_INTERCEPTOR(name, q, block); \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); \
+ dispatch_block_t heap_block = Block_copy(block); \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); \
+ block_context_t *new_context = \
+ AllocContext(thr, pc, q, heap_block, &invoke_and_release_block); \
+ new_context->is_barrier_block = barrier; \
+ Release(thr, pc, (uptr)new_context); \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); \
+ REAL(name##_f)(q, new_context, dispatch_callback_wrap); \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); \
+ }
+
+#define DISPATCH_INTERCEPT_SYNC_B(name, barrier) \
+ TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, \
+ DISPATCH_NOESCAPE dispatch_block_t block) { \
+ SCOPED_TSAN_INTERCEPTOR(name, q, block); \
+ block_context_t new_context = { \
+ q, block, &invoke_block, false, true, barrier, 0}; \
+ Release(thr, pc, (uptr)&new_context); \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); \
+ REAL(name##_f)(q, &new_context, dispatch_callback_wrap); \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); \
+ Acquire(thr, pc, (uptr)&new_context); \
+ }
+
+#define DISPATCH_INTERCEPT_ASYNC_F(name, barrier) \
+ TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, void *context, \
+ dispatch_function_t work) { \
+ SCOPED_TSAN_INTERCEPTOR(name, q, context, work); \
+ block_context_t *new_context = \
+ AllocContext(thr, pc, q, context, work); \
+ new_context->is_barrier_block = barrier; \
+ Release(thr, pc, (uptr)new_context); \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); \
+ REAL(name)(q, new_context, dispatch_callback_wrap); \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); \
+ }
+
+#define DISPATCH_INTERCEPT_SYNC_F(name, barrier) \
+ TSAN_INTERCEPTOR(void, name, dispatch_queue_t q, void *context, \
+ dispatch_function_t work) { \
+ SCOPED_TSAN_INTERCEPTOR(name, q, context, work); \
+ block_context_t new_context = { \
+ q, context, work, false, true, barrier, 0}; \
+ Release(thr, pc, (uptr)&new_context); \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START(); \
+ REAL(name)(q, &new_context, dispatch_callback_wrap); \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END(); \
+ Acquire(thr, pc, (uptr)&new_context); \
+ }
+
+#define DISPATCH_INTERCEPT(name, barrier) \
+ DISPATCH_INTERCEPT_ASYNC_F(name##_async_f, barrier) \
+ DISPATCH_INTERCEPT_ASYNC_B(name##_async, barrier) \
+ DISPATCH_INTERCEPT_SYNC_F(name##_sync_f, barrier) \
+ DISPATCH_INTERCEPT_SYNC_B(name##_sync, barrier)
+
+// We wrap dispatch_async, dispatch_sync and friends where we allocate a new
+// context, which is used to synchronize (we release the context before
+// submitting, and the callback acquires it before executing the original
+// callback).
+DISPATCH_INTERCEPT(dispatch, false)
+DISPATCH_INTERCEPT(dispatch_barrier, true)
+
+// dispatch_async_and_wait() and friends were introduced in macOS 10.14.
+// Linking of these interceptors fails when using an older SDK.
+#if !SANITIZER_APPLE || defined(__MAC_10_14)
+// macOS 10.14 is greater than our minimal deployment target. To ensure we
+// generate a weak reference so the TSan dylib continues to work on older
+// systems, we need to forward declare the intercepted functions as "weak
+// imports". Note that this file is multi-platform, so we cannot include the
+// actual header file (#include <dispatch/dispatch.h>).
+SANITIZER_WEAK_IMPORT void dispatch_async_and_wait(
+ dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);
+SANITIZER_WEAK_IMPORT void dispatch_async_and_wait_f(
+ dispatch_queue_t queue, void *context, dispatch_function_t work);
+SANITIZER_WEAK_IMPORT void dispatch_barrier_async_and_wait(
+ dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);
+SANITIZER_WEAK_IMPORT void dispatch_barrier_async_and_wait_f(
+ dispatch_queue_t queue, void *context, dispatch_function_t work);
+
+DISPATCH_INTERCEPT_SYNC_F(dispatch_async_and_wait_f, false)
+DISPATCH_INTERCEPT_SYNC_B(dispatch_async_and_wait, false)
+DISPATCH_INTERCEPT_SYNC_F(dispatch_barrier_async_and_wait_f, true)
+DISPATCH_INTERCEPT_SYNC_B(dispatch_barrier_async_and_wait, true)
+#endif
+
+
+DECLARE_REAL(void, dispatch_after_f, dispatch_time_t when,
+ dispatch_queue_t queue, void *context, dispatch_function_t work)
+
+TSAN_INTERCEPTOR(void, dispatch_after, dispatch_time_t when,
+ dispatch_queue_t queue, dispatch_block_t block) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_after, when, queue, block);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+ dispatch_block_t heap_block = Block_copy(block);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+ block_context_t *new_context =
+ AllocContext(thr, pc, queue, heap_block, &invoke_and_release_block);
+ Release(thr, pc, (uptr)new_context);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+ REAL(dispatch_after_f)(when, queue, new_context, dispatch_callback_wrap);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+}
+
+TSAN_INTERCEPTOR(void, dispatch_after_f, dispatch_time_t when,
+ dispatch_queue_t queue, void *context,
+ dispatch_function_t work) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_after_f, when, queue, context, work);
+ WRAP(dispatch_after)(when, queue, ^(void) {
+ work(context);
+ });
+}
+
+// GCD's dispatch_once implementation has a fast path that contains a racy read
+// and it's inlined into user's code. Furthermore, this fast path doesn't
+// establish a proper happens-before relations between the initialization and
+// code following the call to dispatch_once. We could deal with this in
+// instrumented code, but there's not much we can do about it in system
+// libraries. Let's disable the fast path (by never storing the value ~0 to
+// predicate), so the interceptor is always called, and let's add proper release
+// and acquire semantics. Since TSan does not see its own atomic stores, the
+// race on predicate won't be reported - the only accesses to it that TSan sees
+// are the loads on the fast path. Loads don't race. Secondly, dispatch_once is
+// both a macro and a real function, we want to intercept the function, so we
+// need to undefine the macro.
+#undef dispatch_once
+TSAN_INTERCEPTOR(void, dispatch_once, dispatch_once_t *predicate,
+ DISPATCH_NOESCAPE dispatch_block_t block) {
+ SCOPED_INTERCEPTOR_RAW(dispatch_once, predicate, block);
+ atomic_uint32_t *a = reinterpret_cast<atomic_uint32_t *>(predicate);
+ u32 v = atomic_load(a, memory_order_acquire);
+ if (v == 0 &&
+ atomic_compare_exchange_strong(a, &v, 1, memory_order_relaxed)) {
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+ block();
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+ Release(thr, pc, (uptr)a);
+ atomic_store(a, 2, memory_order_release);
+ } else {
+ while (v != 2) {
+ internal_sched_yield();
+ v = atomic_load(a, memory_order_acquire);
+ }
+ Acquire(thr, pc, (uptr)a);
+ }
+}
+
+#undef dispatch_once_f
+TSAN_INTERCEPTOR(void, dispatch_once_f, dispatch_once_t *predicate,
+ void *context, dispatch_function_t function) {
+ SCOPED_INTERCEPTOR_RAW(dispatch_once_f, predicate, context, function);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+ WRAP(dispatch_once)(predicate, ^(void) {
+ function(context);
+ });
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+}
+
+TSAN_INTERCEPTOR(long_t, dispatch_semaphore_signal,
+ dispatch_semaphore_t dsema) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_semaphore_signal, dsema);
+ Release(thr, pc, (uptr)dsema);
+ return REAL(dispatch_semaphore_signal)(dsema);
+}
+
+TSAN_INTERCEPTOR(long_t, dispatch_semaphore_wait, dispatch_semaphore_t dsema,
+ dispatch_time_t timeout) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_semaphore_wait, dsema, timeout);
+ long_t result = REAL(dispatch_semaphore_wait)(dsema, timeout);
+ if (result == 0) Acquire(thr, pc, (uptr)dsema);
+ return result;
+}
+
+TSAN_INTERCEPTOR(long_t, dispatch_group_wait, dispatch_group_t group,
+ dispatch_time_t timeout) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_group_wait, group, timeout);
+ long_t result = REAL(dispatch_group_wait)(group, timeout);
+ if (result == 0) Acquire(thr, pc, (uptr)group);
+ return result;
+}
+
+// Used, but not intercepted.
+extern "C" void dispatch_group_enter(dispatch_group_t group);
+
+TSAN_INTERCEPTOR(void, dispatch_group_leave, dispatch_group_t group) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_group_leave, group);
+ // Acquired in the group notification callback in dispatch_group_notify[_f].
+ Release(thr, pc, (uptr)group);
+ REAL(dispatch_group_leave)(group);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_group_async, dispatch_group_t group,
+ dispatch_queue_t queue, dispatch_block_t block) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_group_async, group, queue, block);
+ dispatch_retain(group);
+ dispatch_group_enter(group);
+ __block dispatch_block_t block_copy = (dispatch_block_t)Block_copy(block);
+ WRAP(dispatch_async)(queue, ^(void) {
+ block_copy();
+ Block_release(block_copy);
+ WRAP(dispatch_group_leave)(group);
+ dispatch_release(group);
+ });
+}
+
+TSAN_INTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group,
+ dispatch_queue_t queue, void *context,
+ dispatch_function_t work) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_group_async_f, group, queue, context, work);
+ dispatch_retain(group);
+ dispatch_group_enter(group);
+ WRAP(dispatch_async)(queue, ^(void) {
+ work(context);
+ WRAP(dispatch_group_leave)(group);
+ dispatch_release(group);
+ });
+}
+
+DECLARE_REAL(void, dispatch_group_notify_f, dispatch_group_t group,
+ dispatch_queue_t q, void *context, dispatch_function_t work)
+
+TSAN_INTERCEPTOR(void, dispatch_group_notify, dispatch_group_t group,
+ dispatch_queue_t q, dispatch_block_t block) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_group_notify, group, q, block);
+
+ // To make sure the group is still available in the callback (otherwise
+ // it can be already destroyed). Will be released in the callback.
+ dispatch_retain(group);
+
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+ dispatch_block_t heap_block = Block_copy(^(void) {
+ {
+ SCOPED_INTERCEPTOR_RAW(dispatch_read_callback);
+ // Released when leaving the group (dispatch_group_leave).
+ Acquire(thr, pc, (uptr)group);
+ }
+ dispatch_release(group);
+ block();
+ });
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+ block_context_t *new_context =
+ AllocContext(thr, pc, q, heap_block, &invoke_and_release_block);
+ new_context->is_barrier_block = true;
+ Release(thr, pc, (uptr)new_context);
+ REAL(dispatch_group_notify_f)(group, q, new_context, dispatch_callback_wrap);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_group_notify_f, dispatch_group_t group,
+ dispatch_queue_t q, void *context, dispatch_function_t work) {
+ WRAP(dispatch_group_notify)(group, q, ^(void) { work(context); });
+}
+
+TSAN_INTERCEPTOR(void, dispatch_source_set_event_handler,
+ dispatch_source_t source, dispatch_block_t handler) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_event_handler, source, handler);
+ if (handler == nullptr)
+ return REAL(dispatch_source_set_event_handler)(source, nullptr);
+ dispatch_queue_t q = GetTargetQueueFromSource(source);
+ __block block_context_t new_context = {
+ q, handler, &invoke_block, false, false, false, 0 };
+ dispatch_block_t new_handler = Block_copy(^(void) {
+ new_context.orig_context = handler; // To explicitly capture "handler".
+ dispatch_callback_wrap(&new_context);
+ });
+ uptr submit_sync = (uptr)&new_context;
+ Release(thr, pc, submit_sync);
+ REAL(dispatch_source_set_event_handler)(source, new_handler);
+ Block_release(new_handler);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_source_set_event_handler_f,
+ dispatch_source_t source, dispatch_function_t handler) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_event_handler_f, source, handler);
+ if (handler == nullptr)
+ return REAL(dispatch_source_set_event_handler)(source, nullptr);
+ dispatch_block_t block = ^(void) {
+ handler(dispatch_get_context(source));
+ };
+ WRAP(dispatch_source_set_event_handler)(source, block);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_source_set_cancel_handler,
+ dispatch_source_t source, dispatch_block_t handler) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_cancel_handler, source, handler);
+ if (handler == nullptr)
+ return REAL(dispatch_source_set_cancel_handler)(source, nullptr);
+ dispatch_queue_t q = GetTargetQueueFromSource(source);
+ __block block_context_t new_context = {
+ q, handler, &invoke_block, false, false, false, 0};
+ dispatch_block_t new_handler = Block_copy(^(void) {
+ new_context.orig_context = handler; // To explicitly capture "handler".
+ dispatch_callback_wrap(&new_context);
+ });
+ uptr submit_sync = (uptr)&new_context;
+ Release(thr, pc, submit_sync);
+ REAL(dispatch_source_set_cancel_handler)(source, new_handler);
+ Block_release(new_handler);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_source_set_cancel_handler_f,
+ dispatch_source_t source, dispatch_function_t handler) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_cancel_handler_f, source,
+ handler);
+ if (handler == nullptr)
+ return REAL(dispatch_source_set_cancel_handler)(source, nullptr);
+ dispatch_block_t block = ^(void) {
+ handler(dispatch_get_context(source));
+ };
+ WRAP(dispatch_source_set_cancel_handler)(source, block);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_source_set_registration_handler,
+ dispatch_source_t source, dispatch_block_t handler) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_registration_handler, source,
+ handler);
+ if (handler == nullptr)
+ return REAL(dispatch_source_set_registration_handler)(source, nullptr);
+ dispatch_queue_t q = GetTargetQueueFromSource(source);
+ __block block_context_t new_context = {
+ q, handler, &invoke_block, false, false, false, 0};
+ dispatch_block_t new_handler = Block_copy(^(void) {
+ new_context.orig_context = handler; // To explicitly capture "handler".
+ dispatch_callback_wrap(&new_context);
+ });
+ uptr submit_sync = (uptr)&new_context;
+ Release(thr, pc, submit_sync);
+ REAL(dispatch_source_set_registration_handler)(source, new_handler);
+ Block_release(new_handler);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_source_set_registration_handler_f,
+ dispatch_source_t source, dispatch_function_t handler) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_source_set_registration_handler_f, source,
+ handler);
+ if (handler == nullptr)
+ return REAL(dispatch_source_set_registration_handler)(source, nullptr);
+ dispatch_block_t block = ^(void) {
+ handler(dispatch_get_context(source));
+ };
+ WRAP(dispatch_source_set_registration_handler)(source, block);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_apply, size_t iterations,
+ dispatch_queue_t queue,
+ DISPATCH_NOESCAPE void (^block)(size_t)) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_apply, iterations, queue, block);
+
+ u8 sync1, sync2;
+ uptr parent_to_child_sync = (uptr)&sync1;
+ uptr child_to_parent_sync = (uptr)&sync2;
+
+ Release(thr, pc, parent_to_child_sync);
+ void (^new_block)(size_t) = ^(size_t iteration) {
+ SCOPED_INTERCEPTOR_RAW(dispatch_apply);
+ Acquire(thr, pc, parent_to_child_sync);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+ block(iteration);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+ Release(thr, pc, child_to_parent_sync);
+ };
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+ REAL(dispatch_apply)(iterations, queue, new_block);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+ Acquire(thr, pc, child_to_parent_sync);
+}
+
+static void invoke_block_iteration(void *param, size_t iteration) {
+ auto block = (void (^)(size_t)) param;
+ block(iteration);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_apply_f, size_t iterations,
+ dispatch_queue_t queue, void *context,
+ void (*work)(void *, size_t)) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_apply_f, iterations, queue, context, work);
+
+ // Unfortunately, we cannot delegate to dispatch_apply, since libdispatch
+ // implements dispatch_apply in terms of dispatch_apply_f.
+ u8 sync1, sync2;
+ uptr parent_to_child_sync = (uptr)&sync1;
+ uptr child_to_parent_sync = (uptr)&sync2;
+
+ Release(thr, pc, parent_to_child_sync);
+ void (^new_block)(size_t) = ^(size_t iteration) {
+ SCOPED_INTERCEPTOR_RAW(dispatch_apply_f);
+ Acquire(thr, pc, parent_to_child_sync);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+ work(context, iteration);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+ Release(thr, pc, child_to_parent_sync);
+ };
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+ REAL(dispatch_apply_f)(iterations, queue, new_block, invoke_block_iteration);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+ Acquire(thr, pc, child_to_parent_sync);
+}
+
+DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
+DECLARE_REAL_AND_INTERCEPTOR(int, munmap, void *addr, long_t sz)
+
+TSAN_INTERCEPTOR(dispatch_data_t, dispatch_data_create, const void *buffer,
+ size_t size, dispatch_queue_t q, dispatch_block_t destructor) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_data_create, buffer, size, q, destructor);
+ if ((q == nullptr) || (destructor == DISPATCH_DATA_DESTRUCTOR_DEFAULT))
+ return REAL(dispatch_data_create)(buffer, size, q, destructor);
+
+ if (destructor == DISPATCH_DATA_DESTRUCTOR_FREE)
+ destructor = ^(void) { WRAP(free)((void *)(uintptr_t)buffer); };
+ else if (destructor == DISPATCH_DATA_DESTRUCTOR_MUNMAP)
+ destructor = ^(void) { WRAP(munmap)((void *)(uintptr_t)buffer, size); };
+
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START();
+ dispatch_block_t heap_block = Block_copy(destructor);
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END();
+ block_context_t *new_context =
+ AllocContext(thr, pc, q, heap_block, &invoke_and_release_block);
+ uptr submit_sync = (uptr)new_context;
+ Release(thr, pc, submit_sync);
+ return REAL(dispatch_data_create)(buffer, size, q, ^(void) {
+ dispatch_callback_wrap(new_context);
+ });
+}
+
+typedef void (^fd_handler_t)(dispatch_data_t data, int error);
+typedef void (^cleanup_handler_t)(int error);
+
+TSAN_INTERCEPTOR(void, dispatch_read, dispatch_fd_t fd, size_t length,
+ dispatch_queue_t q, fd_handler_t h) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_read, fd, length, q, h);
+ __block block_context_t new_context = {
+ q, nullptr, &invoke_block, false, false, false, 0};
+ fd_handler_t new_h = Block_copy(^(dispatch_data_t data, int error) {
+ new_context.orig_context = ^(void) {
+ h(data, error);
+ };
+ dispatch_callback_wrap(&new_context);
+ });
+ uptr submit_sync = (uptr)&new_context;
+ Release(thr, pc, submit_sync);
+ REAL(dispatch_read)(fd, length, q, new_h);
+ Block_release(new_h);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_write, dispatch_fd_t fd, dispatch_data_t data,
+ dispatch_queue_t q, fd_handler_t h) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_write, fd, data, q, h);
+ __block block_context_t new_context = {
+ q, nullptr, &invoke_block, false, false, false, 0};
+ fd_handler_t new_h = Block_copy(^(dispatch_data_t data, int error) {
+ new_context.orig_context = ^(void) {
+ h(data, error);
+ };
+ dispatch_callback_wrap(&new_context);
+ });
+ uptr submit_sync = (uptr)&new_context;
+ Release(thr, pc, submit_sync);
+ REAL(dispatch_write)(fd, data, q, new_h);
+ Block_release(new_h);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_io_read, dispatch_io_t channel, off_t offset,
+ size_t length, dispatch_queue_t q, dispatch_io_handler_t h) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_io_read, channel, offset, length, q, h);
+ __block block_context_t new_context = {
+ q, nullptr, &invoke_block, false, false, false, 0};
+ dispatch_io_handler_t new_h =
+ Block_copy(^(bool done, dispatch_data_t data, int error) {
+ new_context.orig_context = ^(void) {
+ h(done, data, error);
+ };
+ dispatch_callback_wrap(&new_context);
+ });
+ uptr submit_sync = (uptr)&new_context;
+ Release(thr, pc, submit_sync);
+ REAL(dispatch_io_read)(channel, offset, length, q, new_h);
+ Block_release(new_h);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_io_write, dispatch_io_t channel, off_t offset,
+ dispatch_data_t data, dispatch_queue_t q,
+ dispatch_io_handler_t h) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_io_write, channel, offset, data, q, h);
+ __block block_context_t new_context = {
+ q, nullptr, &invoke_block, false, false, false, 0};
+ dispatch_io_handler_t new_h =
+ Block_copy(^(bool done, dispatch_data_t data, int error) {
+ new_context.orig_context = ^(void) {
+ h(done, data, error);
+ };
+ dispatch_callback_wrap(&new_context);
+ });
+ uptr submit_sync = (uptr)&new_context;
+ Release(thr, pc, submit_sync);
+ REAL(dispatch_io_write)(channel, offset, data, q, new_h);
+ Block_release(new_h);
+}
+
+TSAN_INTERCEPTOR(void, dispatch_io_barrier, dispatch_io_t channel,
+ dispatch_block_t barrier) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_io_barrier, channel, barrier);
+ __block block_context_t new_context = {
+ nullptr, nullptr, &invoke_block, false, false, false, 0};
+ new_context.non_queue_sync_object = (uptr)channel;
+ new_context.is_barrier_block = true;
+ dispatch_block_t new_block = Block_copy(^(void) {
+ new_context.orig_context = ^(void) {
+ barrier();
+ };
+ dispatch_callback_wrap(&new_context);
+ });
+ uptr submit_sync = (uptr)&new_context;
+ Release(thr, pc, submit_sync);
+ REAL(dispatch_io_barrier)(channel, new_block);
+ Block_release(new_block);
+}
+
+TSAN_INTERCEPTOR(dispatch_io_t, dispatch_io_create, dispatch_io_type_t type,
+ dispatch_fd_t fd, dispatch_queue_t q, cleanup_handler_t h) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_io_create, type, fd, q, h);
+ __block dispatch_io_t new_channel = nullptr;
+ __block block_context_t new_context = {
+ q, nullptr, &invoke_block, false, false, false, 0};
+ cleanup_handler_t new_h = Block_copy(^(int error) {
+ {
+ SCOPED_INTERCEPTOR_RAW(dispatch_io_create_callback);
+ Acquire(thr, pc, (uptr)new_channel); // Release() in dispatch_io_close.
+ }
+ new_context.orig_context = ^(void) {
+ h(error);
+ };
+ dispatch_callback_wrap(&new_context);
+ });
+ uptr submit_sync = (uptr)&new_context;
+ Release(thr, pc, submit_sync);
+ new_channel = REAL(dispatch_io_create)(type, fd, q, new_h);
+ Block_release(new_h);
+ return new_channel;
+}
+
+TSAN_INTERCEPTOR(dispatch_io_t, dispatch_io_create_with_path,
+ dispatch_io_type_t type, const char *path, int oflag,
+ mode_t mode, dispatch_queue_t q, cleanup_handler_t h) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_io_create_with_path, type, path, oflag, mode,
+ q, h);
+ __block dispatch_io_t new_channel = nullptr;
+ __block block_context_t new_context = {
+ q, nullptr, &invoke_block, false, false, false, 0};
+ cleanup_handler_t new_h = Block_copy(^(int error) {
+ {
+ SCOPED_INTERCEPTOR_RAW(dispatch_io_create_callback);
+ Acquire(thr, pc, (uptr)new_channel); // Release() in dispatch_io_close.
+ }
+ new_context.orig_context = ^(void) {
+ h(error);
+ };
+ dispatch_callback_wrap(&new_context);
+ });
+ uptr submit_sync = (uptr)&new_context;
+ Release(thr, pc, submit_sync);
+ new_channel =
+ REAL(dispatch_io_create_with_path)(type, path, oflag, mode, q, new_h);
+ Block_release(new_h);
+ return new_channel;
+}
+
+TSAN_INTERCEPTOR(dispatch_io_t, dispatch_io_create_with_io,
+ dispatch_io_type_t type, dispatch_io_t io, dispatch_queue_t q,
+ cleanup_handler_t h) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_io_create_with_io, type, io, q, h);
+ __block dispatch_io_t new_channel = nullptr;
+ __block block_context_t new_context = {
+ q, nullptr, &invoke_block, false, false, false, 0};
+ cleanup_handler_t new_h = Block_copy(^(int error) {
+ {
+ SCOPED_INTERCEPTOR_RAW(dispatch_io_create_callback);
+ Acquire(thr, pc, (uptr)new_channel); // Release() in dispatch_io_close.
+ }
+ new_context.orig_context = ^(void) {
+ h(error);
+ };
+ dispatch_callback_wrap(&new_context);
+ });
+ uptr submit_sync = (uptr)&new_context;
+ Release(thr, pc, submit_sync);
+ new_channel = REAL(dispatch_io_create_with_io)(type, io, q, new_h);
+ Block_release(new_h);
+ return new_channel;
+}
+
+TSAN_INTERCEPTOR(void, dispatch_io_close, dispatch_io_t channel,
+ dispatch_io_close_flags_t flags) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_io_close, channel, flags);
+ Release(thr, pc, (uptr)channel); // Acquire() in dispatch_io_create[_*].
+ return REAL(dispatch_io_close)(channel, flags);
+}
+
+// Resuming a suspended queue needs to synchronize with all subsequent
+// executions of blocks in that queue.
+TSAN_INTERCEPTOR(void, dispatch_resume, dispatch_object_t o) {
+ SCOPED_TSAN_INTERCEPTOR(dispatch_resume, o);
+ Release(thr, pc, (uptr)o); // Synchronizes with the Acquire() on serial_sync
+ // in dispatch_sync_pre_execute
+ return REAL(dispatch_resume)(o);
+}
+
+void InitializeLibdispatchInterceptors() {
+ INTERCEPT_FUNCTION(dispatch_async);
+ INTERCEPT_FUNCTION(dispatch_async_f);
+ INTERCEPT_FUNCTION(dispatch_sync);
+ INTERCEPT_FUNCTION(dispatch_sync_f);
+ INTERCEPT_FUNCTION(dispatch_barrier_async);
+ INTERCEPT_FUNCTION(dispatch_barrier_async_f);
+ INTERCEPT_FUNCTION(dispatch_barrier_sync);
+ INTERCEPT_FUNCTION(dispatch_barrier_sync_f);
+ INTERCEPT_FUNCTION(dispatch_async_and_wait);
+ INTERCEPT_FUNCTION(dispatch_async_and_wait_f);
+ INTERCEPT_FUNCTION(dispatch_barrier_async_and_wait);
+ INTERCEPT_FUNCTION(dispatch_barrier_async_and_wait_f);
+ INTERCEPT_FUNCTION(dispatch_after);
+ INTERCEPT_FUNCTION(dispatch_after_f);
+ INTERCEPT_FUNCTION(dispatch_once);
+ INTERCEPT_FUNCTION(dispatch_once_f);
+ INTERCEPT_FUNCTION(dispatch_semaphore_signal);
+ INTERCEPT_FUNCTION(dispatch_semaphore_wait);
+ INTERCEPT_FUNCTION(dispatch_group_wait);
+ INTERCEPT_FUNCTION(dispatch_group_leave);
+ INTERCEPT_FUNCTION(dispatch_group_async);
+ INTERCEPT_FUNCTION(dispatch_group_async_f);
+ INTERCEPT_FUNCTION(dispatch_group_notify);
+ INTERCEPT_FUNCTION(dispatch_group_notify_f);
+ INTERCEPT_FUNCTION(dispatch_source_set_event_handler);
+ INTERCEPT_FUNCTION(dispatch_source_set_event_handler_f);
+ INTERCEPT_FUNCTION(dispatch_source_set_cancel_handler);
+ INTERCEPT_FUNCTION(dispatch_source_set_cancel_handler_f);
+ INTERCEPT_FUNCTION(dispatch_source_set_registration_handler);
+ INTERCEPT_FUNCTION(dispatch_source_set_registration_handler_f);
+ INTERCEPT_FUNCTION(dispatch_apply);
+ INTERCEPT_FUNCTION(dispatch_apply_f);
+ INTERCEPT_FUNCTION(dispatch_data_create);
+ INTERCEPT_FUNCTION(dispatch_read);
+ INTERCEPT_FUNCTION(dispatch_write);
+ INTERCEPT_FUNCTION(dispatch_io_read);
+ INTERCEPT_FUNCTION(dispatch_io_write);
+ INTERCEPT_FUNCTION(dispatch_io_barrier);
+ INTERCEPT_FUNCTION(dispatch_io_create);
+ INTERCEPT_FUNCTION(dispatch_io_create_with_path);
+ INTERCEPT_FUNCTION(dispatch_io_create_with_io);
+ INTERCEPT_FUNCTION(dispatch_io_close);
+ INTERCEPT_FUNCTION(dispatch_resume);
+}
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp
new file mode 100644
index 00000000000..1ee47bcd123
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp
@@ -0,0 +1,521 @@
+//===-- tsan_interceptors_mac.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Mac-specific interceptors.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_APPLE
+
+#include "interception/interception.h"
+#include "tsan_interceptors.h"
+#include "tsan_interface.h"
+#include "tsan_interface_ann.h"
+#include "sanitizer_common/sanitizer_addrhashmap.h"
+
+#include <errno.h>
+#include <libkern/OSAtomic.h>
+#include <objc/objc-sync.h>
+#include <os/lock.h>
+#include <sys/ucontext.h>
+
+#if defined(__has_include) && __has_include(<xpc/xpc.h>)
+#include <xpc/xpc.h>
+#endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
+
+typedef long long_t;
+
+extern "C" {
+int getcontext(ucontext_t *ucp) __attribute__((returns_twice));
+int setcontext(const ucontext_t *ucp);
+}
+
+namespace __tsan {
+
+// The non-barrier versions of OSAtomic* functions are semantically mo_relaxed,
+// but the two variants (e.g. OSAtomicAdd32 and OSAtomicAdd32Barrier) are
+// actually aliases of each other, and we cannot have different interceptors for
+// them, because they're actually the same function. Thus, we have to stay
+// conservative and treat the non-barrier versions as mo_acq_rel.
+static constexpr morder kMacOrderBarrier = mo_acq_rel;
+static constexpr morder kMacOrderNonBarrier = mo_acq_rel;
+static constexpr morder kMacFailureOrder = mo_relaxed;
+
+#define OSATOMIC_INTERCEPTOR(return_t, t, tsan_t, f, tsan_atomic_f, mo) \
+ TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \
+ SCOPED_TSAN_INTERCEPTOR(f, x, ptr); \
+ return tsan_atomic_f((volatile tsan_t *)ptr, x, mo); \
+ }
+
+#define OSATOMIC_INTERCEPTOR_PLUS_X(return_t, t, tsan_t, f, tsan_atomic_f, mo) \
+ TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \
+ SCOPED_TSAN_INTERCEPTOR(f, x, ptr); \
+ return tsan_atomic_f((volatile tsan_t *)ptr, x, mo) + x; \
+ }
+
+#define OSATOMIC_INTERCEPTOR_PLUS_1(return_t, t, tsan_t, f, tsan_atomic_f, mo) \
+ TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \
+ SCOPED_TSAN_INTERCEPTOR(f, ptr); \
+ return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) + 1; \
+ }
+
+#define OSATOMIC_INTERCEPTOR_MINUS_1(return_t, t, tsan_t, f, tsan_atomic_f, \
+ mo) \
+ TSAN_INTERCEPTOR(return_t, f, volatile t *ptr) { \
+ SCOPED_TSAN_INTERCEPTOR(f, ptr); \
+ return tsan_atomic_f((volatile tsan_t *)ptr, 1, mo) - 1; \
+ }
+
+#define OSATOMIC_INTERCEPTORS_ARITHMETIC(f, tsan_atomic_f, m) \
+ m(int32_t, int32_t, a32, f##32, __tsan_atomic32_##tsan_atomic_f, \
+ kMacOrderNonBarrier) \
+ m(int32_t, int32_t, a32, f##32##Barrier, __tsan_atomic32_##tsan_atomic_f, \
+ kMacOrderBarrier) \
+ m(int64_t, int64_t, a64, f##64, __tsan_atomic64_##tsan_atomic_f, \
+ kMacOrderNonBarrier) \
+ m(int64_t, int64_t, a64, f##64##Barrier, __tsan_atomic64_##tsan_atomic_f, \
+ kMacOrderBarrier)
+
+#define OSATOMIC_INTERCEPTORS_BITWISE(f, tsan_atomic_f, m, m_orig) \
+ m(int32_t, uint32_t, a32, f##32, __tsan_atomic32_##tsan_atomic_f, \
+ kMacOrderNonBarrier) \
+ m(int32_t, uint32_t, a32, f##32##Barrier, __tsan_atomic32_##tsan_atomic_f, \
+ kMacOrderBarrier) \
+ m_orig(int32_t, uint32_t, a32, f##32##Orig, __tsan_atomic32_##tsan_atomic_f, \
+ kMacOrderNonBarrier) \
+ m_orig(int32_t, uint32_t, a32, f##32##OrigBarrier, \
+ __tsan_atomic32_##tsan_atomic_f, kMacOrderBarrier)
+
+OSATOMIC_INTERCEPTORS_ARITHMETIC(OSAtomicAdd, fetch_add,
+ OSATOMIC_INTERCEPTOR_PLUS_X)
+OSATOMIC_INTERCEPTORS_ARITHMETIC(OSAtomicIncrement, fetch_add,
+ OSATOMIC_INTERCEPTOR_PLUS_1)
+OSATOMIC_INTERCEPTORS_ARITHMETIC(OSAtomicDecrement, fetch_sub,
+ OSATOMIC_INTERCEPTOR_MINUS_1)
+OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicOr, fetch_or, OSATOMIC_INTERCEPTOR_PLUS_X,
+ OSATOMIC_INTERCEPTOR)
+OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicAnd, fetch_and,
+ OSATOMIC_INTERCEPTOR_PLUS_X, OSATOMIC_INTERCEPTOR)
+OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicXor, fetch_xor,
+ OSATOMIC_INTERCEPTOR_PLUS_X, OSATOMIC_INTERCEPTOR)
+
+#define OSATOMIC_INTERCEPTORS_CAS(f, tsan_atomic_f, tsan_t, t) \
+ TSAN_INTERCEPTOR(bool, f, t old_value, t new_value, t volatile *ptr) { \
+ SCOPED_TSAN_INTERCEPTOR(f, old_value, new_value, ptr); \
+ return tsan_atomic_f##_compare_exchange_strong( \
+ (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \
+ kMacOrderNonBarrier, kMacFailureOrder); \
+ } \
+ \
+ TSAN_INTERCEPTOR(bool, f##Barrier, t old_value, t new_value, \
+ t volatile *ptr) { \
+ SCOPED_TSAN_INTERCEPTOR(f##Barrier, old_value, new_value, ptr); \
+ return tsan_atomic_f##_compare_exchange_strong( \
+ (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \
+ kMacOrderBarrier, kMacFailureOrder); \
+ }
+
+OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapInt, __tsan_atomic32, a32, int)
+OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapLong, __tsan_atomic64, a64,
+ long_t)
+OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapPtr, __tsan_atomic64, a64,
+ void *)
+OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwap32, __tsan_atomic32, a32,
+ int32_t)
+OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwap64, __tsan_atomic64, a64,
+ int64_t)
+
+#define OSATOMIC_INTERCEPTOR_BITOP(f, op, clear, mo) \
+ TSAN_INTERCEPTOR(bool, f, uint32_t n, volatile void *ptr) { \
+ SCOPED_TSAN_INTERCEPTOR(f, n, ptr); \
+ volatile char *byte_ptr = ((volatile char *)ptr) + (n >> 3); \
+ char bit = 0x80u >> (n & 7); \
+ char mask = clear ? ~bit : bit; \
+ char orig_byte = op((volatile a8 *)byte_ptr, mask, mo); \
+ return orig_byte & bit; \
+ }
+
+#define OSATOMIC_INTERCEPTORS_BITOP(f, op, clear) \
+ OSATOMIC_INTERCEPTOR_BITOP(f, op, clear, kMacOrderNonBarrier) \
+ OSATOMIC_INTERCEPTOR_BITOP(f##Barrier, op, clear, kMacOrderBarrier)
+
+OSATOMIC_INTERCEPTORS_BITOP(OSAtomicTestAndSet, __tsan_atomic8_fetch_or, false)
+OSATOMIC_INTERCEPTORS_BITOP(OSAtomicTestAndClear, __tsan_atomic8_fetch_and,
+ true)
+
+TSAN_INTERCEPTOR(void, OSAtomicEnqueue, OSQueueHead *list, void *item,
+ size_t offset) {
+ SCOPED_TSAN_INTERCEPTOR(OSAtomicEnqueue, list, item, offset);
+ __tsan_release(item);
+ REAL(OSAtomicEnqueue)(list, item, offset);
+}
+
+TSAN_INTERCEPTOR(void *, OSAtomicDequeue, OSQueueHead *list, size_t offset) {
+ SCOPED_TSAN_INTERCEPTOR(OSAtomicDequeue, list, offset);
+ void *item = REAL(OSAtomicDequeue)(list, offset);
+ if (item) __tsan_acquire(item);
+ return item;
+}
+
+// OSAtomicFifoEnqueue and OSAtomicFifoDequeue are only on OS X.
+#if !SANITIZER_IOS
+
+TSAN_INTERCEPTOR(void, OSAtomicFifoEnqueue, OSFifoQueueHead *list, void *item,
+ size_t offset) {
+ SCOPED_TSAN_INTERCEPTOR(OSAtomicFifoEnqueue, list, item, offset);
+ __tsan_release(item);
+ REAL(OSAtomicFifoEnqueue)(list, item, offset);
+}
+
+TSAN_INTERCEPTOR(void *, OSAtomicFifoDequeue, OSFifoQueueHead *list,
+ size_t offset) {
+ SCOPED_TSAN_INTERCEPTOR(OSAtomicFifoDequeue, list, offset);
+ void *item = REAL(OSAtomicFifoDequeue)(list, offset);
+ if (item) __tsan_acquire(item);
+ return item;
+}
+
+#endif
+
+TSAN_INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) {
+ CHECK(!cur_thread()->is_dead);
+ if (!cur_thread()->is_inited) {
+ return REAL(OSSpinLockLock)(lock);
+ }
+ SCOPED_TSAN_INTERCEPTOR(OSSpinLockLock, lock);
+ REAL(OSSpinLockLock)(lock);
+ Acquire(thr, pc, (uptr)lock);
+}
+
+TSAN_INTERCEPTOR(bool, OSSpinLockTry, volatile OSSpinLock *lock) {
+ CHECK(!cur_thread()->is_dead);
+ if (!cur_thread()->is_inited) {
+ return REAL(OSSpinLockTry)(lock);
+ }
+ SCOPED_TSAN_INTERCEPTOR(OSSpinLockTry, lock);
+ bool result = REAL(OSSpinLockTry)(lock);
+ if (result)
+ Acquire(thr, pc, (uptr)lock);
+ return result;
+}
+
+TSAN_INTERCEPTOR(void, OSSpinLockUnlock, volatile OSSpinLock *lock) {
+ CHECK(!cur_thread()->is_dead);
+ if (!cur_thread()->is_inited) {
+ return REAL(OSSpinLockUnlock)(lock);
+ }
+ SCOPED_TSAN_INTERCEPTOR(OSSpinLockUnlock, lock);
+ Release(thr, pc, (uptr)lock);
+ REAL(OSSpinLockUnlock)(lock);
+}
+
+TSAN_INTERCEPTOR(void, os_lock_lock, void *lock) {
+ CHECK(!cur_thread()->is_dead);
+ if (!cur_thread()->is_inited) {
+ return REAL(os_lock_lock)(lock);
+ }
+ SCOPED_TSAN_INTERCEPTOR(os_lock_lock, lock);
+ REAL(os_lock_lock)(lock);
+ Acquire(thr, pc, (uptr)lock);
+}
+
+TSAN_INTERCEPTOR(bool, os_lock_trylock, void *lock) {
+ CHECK(!cur_thread()->is_dead);
+ if (!cur_thread()->is_inited) {
+ return REAL(os_lock_trylock)(lock);
+ }
+ SCOPED_TSAN_INTERCEPTOR(os_lock_trylock, lock);
+ bool result = REAL(os_lock_trylock)(lock);
+ if (result)
+ Acquire(thr, pc, (uptr)lock);
+ return result;
+}
+
+TSAN_INTERCEPTOR(void, os_lock_unlock, void *lock) {
+ CHECK(!cur_thread()->is_dead);
+ if (!cur_thread()->is_inited) {
+ return REAL(os_lock_unlock)(lock);
+ }
+ SCOPED_TSAN_INTERCEPTOR(os_lock_unlock, lock);
+ Release(thr, pc, (uptr)lock);
+ REAL(os_lock_unlock)(lock);
+}
+
+TSAN_INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
+ if (!cur_thread()->is_inited || cur_thread()->is_dead) {
+ return REAL(os_unfair_lock_lock)(lock);
+ }
+ SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_lock, lock);
+ REAL(os_unfair_lock_lock)(lock);
+ Acquire(thr, pc, (uptr)lock);
+}
+
+TSAN_INTERCEPTOR(void, os_unfair_lock_lock_with_options, os_unfair_lock_t lock,
+ u32 options) {
+ if (!cur_thread()->is_inited || cur_thread()->is_dead) {
+ return REAL(os_unfair_lock_lock_with_options)(lock, options);
+ }
+ SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_lock_with_options, lock, options);
+ REAL(os_unfair_lock_lock_with_options)(lock, options);
+ Acquire(thr, pc, (uptr)lock);
+}
+
+TSAN_INTERCEPTOR(bool, os_unfair_lock_trylock, os_unfair_lock_t lock) {
+ if (!cur_thread()->is_inited || cur_thread()->is_dead) {
+ return REAL(os_unfair_lock_trylock)(lock);
+ }
+ SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_trylock, lock);
+ bool result = REAL(os_unfair_lock_trylock)(lock);
+ if (result)
+ Acquire(thr, pc, (uptr)lock);
+ return result;
+}
+
+TSAN_INTERCEPTOR(void, os_unfair_lock_unlock, os_unfair_lock_t lock) {
+ if (!cur_thread()->is_inited || cur_thread()->is_dead) {
+ return REAL(os_unfair_lock_unlock)(lock);
+ }
+ SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_unlock, lock);
+ Release(thr, pc, (uptr)lock);
+ REAL(os_unfair_lock_unlock)(lock);
+}
+
+#if defined(__has_include) && __has_include(<xpc/xpc.h>)
+
+TSAN_INTERCEPTOR(void, xpc_connection_set_event_handler,
+ xpc_connection_t connection, xpc_handler_t handler) {
+ SCOPED_TSAN_INTERCEPTOR(xpc_connection_set_event_handler, connection,
+ handler);
+ Release(thr, pc, (uptr)connection);
+ xpc_handler_t new_handler = ^(xpc_object_t object) {
+ {
+ SCOPED_INTERCEPTOR_RAW(xpc_connection_set_event_handler);
+ Acquire(thr, pc, (uptr)connection);
+ }
+ handler(object);
+ };
+ REAL(xpc_connection_set_event_handler)(connection, new_handler);
+}
+
+TSAN_INTERCEPTOR(void, xpc_connection_send_barrier, xpc_connection_t connection,
+ dispatch_block_t barrier) {
+ SCOPED_TSAN_INTERCEPTOR(xpc_connection_send_barrier, connection, barrier);
+ Release(thr, pc, (uptr)connection);
+ dispatch_block_t new_barrier = ^() {
+ {
+ SCOPED_INTERCEPTOR_RAW(xpc_connection_send_barrier);
+ Acquire(thr, pc, (uptr)connection);
+ }
+ barrier();
+ };
+ REAL(xpc_connection_send_barrier)(connection, new_barrier);
+}
+
+TSAN_INTERCEPTOR(void, xpc_connection_send_message_with_reply,
+ xpc_connection_t connection, xpc_object_t message,
+ dispatch_queue_t replyq, xpc_handler_t handler) {
+ SCOPED_TSAN_INTERCEPTOR(xpc_connection_send_message_with_reply, connection,
+ message, replyq, handler);
+ Release(thr, pc, (uptr)connection);
+ xpc_handler_t new_handler = ^(xpc_object_t object) {
+ {
+ SCOPED_INTERCEPTOR_RAW(xpc_connection_send_message_with_reply);
+ Acquire(thr, pc, (uptr)connection);
+ }
+ handler(object);
+ };
+ REAL(xpc_connection_send_message_with_reply)
+ (connection, message, replyq, new_handler);
+}
+
+TSAN_INTERCEPTOR(void, xpc_connection_cancel, xpc_connection_t connection) {
+ SCOPED_TSAN_INTERCEPTOR(xpc_connection_cancel, connection);
+ Release(thr, pc, (uptr)connection);
+ REAL(xpc_connection_cancel)(connection);
+}
+
+#endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>)
+
+// Determines whether the Obj-C object pointer is a tagged pointer. Tagged
+// pointers encode the object data directly in their pointer bits and do not
+// have an associated memory allocation. The Obj-C runtime uses tagged pointers
+// to transparently optimize small objects.
+static bool IsTaggedObjCPointer(id obj) {
+ const uptr kPossibleTaggedBits = 0x8000000000000001ull;
+ return ((uptr)obj & kPossibleTaggedBits) != 0;
+}
+
+// Returns an address which can be used to inform TSan about synchronization
+// points (MutexLock/Unlock). The TSan infrastructure expects this to be a valid
+// address in the process space. We do a small allocation here to obtain a
+// stable address (the array backing the hash map can change). The memory is
+// never free'd (leaked) and allocation and locking are slow, but this code only
+// runs for @synchronized with tagged pointers, which is very rare.
+static uptr GetOrCreateSyncAddress(uptr addr, ThreadState *thr, uptr pc) {
+ typedef AddrHashMap<uptr, 5> Map;
+ static Map Addresses;
+ Map::Handle h(&Addresses, addr);
+ if (h.created()) {
+ ThreadIgnoreBegin(thr, pc);
+ *h = (uptr) user_alloc(thr, pc, /*size=*/1);
+ ThreadIgnoreEnd(thr);
+ }
+ return *h;
+}
+
+// Returns an address on which we can synchronize given an Obj-C object pointer.
+// For normal object pointers, this is just the address of the object in memory.
+// Tagged pointers are not backed by an actual memory allocation, so we need to
+// synthesize a valid address.
+static uptr SyncAddressForObjCObject(id obj, ThreadState *thr, uptr pc) {
+ if (IsTaggedObjCPointer(obj))
+ return GetOrCreateSyncAddress((uptr)obj, thr, pc);
+ return (uptr)obj;
+}
+
+TSAN_INTERCEPTOR(int, objc_sync_enter, id obj) {
+ SCOPED_TSAN_INTERCEPTOR(objc_sync_enter, obj);
+ if (!obj) return REAL(objc_sync_enter)(obj);
+ uptr addr = SyncAddressForObjCObject(obj, thr, pc);
+ MutexPreLock(thr, pc, addr, MutexFlagWriteReentrant);
+ int result = REAL(objc_sync_enter)(obj);
+ CHECK_EQ(result, OBJC_SYNC_SUCCESS);
+ MutexPostLock(thr, pc, addr, MutexFlagWriteReentrant);
+ return result;
+}
+
+TSAN_INTERCEPTOR(int, objc_sync_exit, id obj) {
+ SCOPED_TSAN_INTERCEPTOR(objc_sync_exit, obj);
+ if (!obj) return REAL(objc_sync_exit)(obj);
+ uptr addr = SyncAddressForObjCObject(obj, thr, pc);
+ MutexUnlock(thr, pc, addr);
+ int result = REAL(objc_sync_exit)(obj);
+ if (result != OBJC_SYNC_SUCCESS) MutexInvalidAccess(thr, pc, addr);
+ return result;
+}
+
+TSAN_INTERCEPTOR(int, swapcontext, ucontext_t *oucp, const ucontext_t *ucp) {
+ {
+ SCOPED_INTERCEPTOR_RAW(swapcontext, oucp, ucp);
+ }
+ // Because of swapcontext() semantics we have no option but to copy its
+ // implementation here
+ if (!oucp || !ucp) {
+ errno = EINVAL;
+ return -1;
+ }
+ ThreadState *thr = cur_thread();
+ const int UCF_SWAPPED = 0x80000000;
+ oucp->uc_onstack &= ~UCF_SWAPPED;
+ thr->ignore_interceptors++;
+ int ret = getcontext(oucp);
+ if (!(oucp->uc_onstack & UCF_SWAPPED)) {
+ thr->ignore_interceptors--;
+ if (!ret) {
+ oucp->uc_onstack |= UCF_SWAPPED;
+ ret = setcontext(ucp);
+ }
+ }
+ return ret;
+}
+
+// On macOS, libc++ is always linked dynamically, so intercepting works the
+// usual way.
+#define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR
+
+namespace {
+struct fake_shared_weak_count {
+ volatile a64 shared_owners;
+ volatile a64 shared_weak_owners;
+ virtual void _unused_0x0() = 0;
+ virtual void _unused_0x8() = 0;
+ virtual void on_zero_shared() = 0;
+ virtual void _unused_0x18() = 0;
+ virtual void on_zero_shared_weak() = 0;
+ virtual ~fake_shared_weak_count() = 0; // suppress -Wnon-virtual-dtor
+};
+} // namespace
+
+// The following code adds libc++ interceptors for:
+// void __shared_weak_count::__release_shared() _NOEXCEPT;
+// bool __shared_count::__release_shared() _NOEXCEPT;
+// Shared and weak pointers in C++ maintain reference counts via atomics in
+// libc++.dylib, which are TSan-invisible, and this leads to false positives in
+// destructor code. These interceptors re-implements the whole functions so that
+// the mo_acq_rel semantics of the atomic decrement are visible.
+//
+// Unfortunately, the interceptors cannot simply Acquire/Release some sync
+// object and call the original function, because it would have a race between
+// the sync and the destruction of the object. Calling both under a lock will
+// not work because the destructor can invoke this interceptor again (and even
+// in a different thread, so recursive locks don't help).
+
+STDCXX_INTERCEPTOR(void, _ZNSt3__119__shared_weak_count16__release_sharedEv,
+ fake_shared_weak_count *o) {
+ if (!flags()->shared_ptr_interceptor)
+ return REAL(_ZNSt3__119__shared_weak_count16__release_sharedEv)(o);
+
+ SCOPED_TSAN_INTERCEPTOR(_ZNSt3__119__shared_weak_count16__release_sharedEv,
+ o);
+ if (__tsan_atomic64_fetch_add(&o->shared_owners, -1, mo_release) == 0) {
+ Acquire(thr, pc, (uptr)&o->shared_owners);
+ o->on_zero_shared();
+ if (__tsan_atomic64_fetch_add(&o->shared_weak_owners, -1, mo_release) ==
+ 0) {
+ Acquire(thr, pc, (uptr)&o->shared_weak_owners);
+ o->on_zero_shared_weak();
+ }
+ }
+}
+
+STDCXX_INTERCEPTOR(bool, _ZNSt3__114__shared_count16__release_sharedEv,
+ fake_shared_weak_count *o) {
+ if (!flags()->shared_ptr_interceptor)
+ return REAL(_ZNSt3__114__shared_count16__release_sharedEv)(o);
+
+ SCOPED_TSAN_INTERCEPTOR(_ZNSt3__114__shared_count16__release_sharedEv, o);
+ if (__tsan_atomic64_fetch_add(&o->shared_owners, -1, mo_release) == 0) {
+ Acquire(thr, pc, (uptr)&o->shared_owners);
+ o->on_zero_shared();
+ return true;
+ }
+ return false;
+}
+
+namespace {
+struct call_once_callback_args {
+ void (*orig_func)(void *arg);
+ void *orig_arg;
+ void *flag;
+};
+
+void call_once_callback_wrapper(void *arg) {
+ call_once_callback_args *new_args = (call_once_callback_args *)arg;
+ new_args->orig_func(new_args->orig_arg);
+ __tsan_release(new_args->flag);
+}
+} // namespace
+
+// This adds a libc++ interceptor for:
+// void __call_once(volatile unsigned long&, void*, void(*)(void*));
+// C++11 call_once is implemented via an internal function __call_once which is
+// inside libc++.dylib, and the atomic release store inside it is thus
+// TSan-invisible. To avoid false positives, this interceptor wraps the callback
+// function and performs an explicit Release after the user code has run.
+STDCXX_INTERCEPTOR(void, _ZNSt3__111__call_onceERVmPvPFvS2_E, void *flag,
+ void *arg, void (*func)(void *arg)) {
+ call_once_callback_args new_args = {func, arg, flag};
+ REAL(_ZNSt3__111__call_onceERVmPvPFvS2_E)(flag, &new_args,
+ call_once_callback_wrapper);
+}
+
+} // namespace __tsan
+
+#endif // SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_mach_vm.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_mach_vm.cpp
new file mode 100644
index 00000000000..6d62ff6a838
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_mach_vm.cpp
@@ -0,0 +1,53 @@
+//===-- tsan_interceptors_mach_vm.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Interceptors for mach_vm_* user space memory routines on Darwin.
+//===----------------------------------------------------------------------===//
+
+#include "interception/interception.h"
+#include "tsan_interceptors.h"
+#include "tsan_platform.h"
+
+#include <mach/mach.h>
+
+namespace __tsan {
+
+static bool intersects_with_shadow(mach_vm_address_t address,
+ mach_vm_size_t size, int flags) {
+ // VM_FLAGS_FIXED is 0x0, so we have to test for VM_FLAGS_ANYWHERE.
+ if (flags & VM_FLAGS_ANYWHERE) return false;
+ return !IsAppMem(address) || !IsAppMem(address + size - 1);
+}
+
+TSAN_INTERCEPTOR(kern_return_t, mach_vm_allocate, vm_map_t target,
+ mach_vm_address_t *address, mach_vm_size_t size, int flags) {
+ SCOPED_TSAN_INTERCEPTOR(mach_vm_allocate, target, address, size, flags);
+ if (target != mach_task_self())
+ return REAL(mach_vm_allocate)(target, address, size, flags);
+ if (address && intersects_with_shadow(*address, size, flags))
+ return KERN_NO_SPACE;
+ kern_return_t kr = REAL(mach_vm_allocate)(target, address, size, flags);
+ if (kr == KERN_SUCCESS)
+ MemoryRangeImitateWriteOrResetRange(thr, pc, *address, size);
+ return kr;
+}
+
+TSAN_INTERCEPTOR(kern_return_t, mach_vm_deallocate, vm_map_t target,
+ mach_vm_address_t address, mach_vm_size_t size) {
+ SCOPED_TSAN_INTERCEPTOR(mach_vm_deallocate, target, address, size);
+ if (target != mach_task_self())
+ return REAL(mach_vm_deallocate)(target, address, size);
+ kern_return_t kr = REAL(mach_vm_deallocate)(target, address, size);
+ if (kr == KERN_SUCCESS && address)
+ UnmapShadow(thr, address, size);
+ return kr;
+}
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
new file mode 100644
index 00000000000..97aa4b77311
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -0,0 +1,3180 @@
+//===-- tsan_interceptors_posix.cpp ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// FIXME: move as many interceptors as possible into
+// sanitizer_common/sanitizer_common_interceptors.inc
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_errno.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
+#include "sanitizer_common/sanitizer_platform_limits_posix.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_posix.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_tls_get_addr.h"
+#include "interception/interception.h"
+#include "tsan_interceptors.h"
+#include "tsan_interface.h"
+#include "tsan_platform.h"
+#include "tsan_suppressions.h"
+#include "tsan_rtl.h"
+#include "tsan_mman.h"
+#include "tsan_fd.h"
+
+#include <stdarg.h>
+
+using namespace __tsan;
+
+#if SANITIZER_FREEBSD || SANITIZER_APPLE
+#define stdout __stdoutp
+#define stderr __stderrp
+#endif
+
+#if SANITIZER_NETBSD
+#define dirfd(dirp) (*(int *)(dirp))
+#define fileno_unlocked(fp) \
+ (((__sanitizer_FILE *)fp)->_file == -1 \
+ ? -1 \
+ : (int)(unsigned short)(((__sanitizer_FILE *)fp)->_file))
+
+#define stdout ((__sanitizer_FILE*)&__sF[1])
+#define stderr ((__sanitizer_FILE*)&__sF[2])
+
+#define nanosleep __nanosleep50
+#define vfork __vfork14
+#endif
+
+#ifdef __mips__
+const int kSigCount = 129;
+#else
+const int kSigCount = 65;
+#endif
+
+#ifdef __mips__
+struct ucontext_t {
+ u64 opaque[768 / sizeof(u64) + 1];
+};
+#else
+struct ucontext_t {
+ // The size is determined by looking at sizeof of real ucontext_t on linux.
+ u64 opaque[936 / sizeof(u64) + 1];
+};
+#endif
+
+#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \
+ defined(__s390x__)
+#define PTHREAD_ABI_BASE "GLIBC_2.3.2"
+#elif defined(__aarch64__) || SANITIZER_PPC64V2
+#define PTHREAD_ABI_BASE "GLIBC_2.17"
+#elif SANITIZER_LOONGARCH64
+#define PTHREAD_ABI_BASE "GLIBC_2.36"
+#endif
+
+extern "C" int pthread_attr_init(void *attr);
+extern "C" int pthread_attr_destroy(void *attr);
+DECLARE_REAL(int, pthread_attr_getdetachstate, void *, void *)
+extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize);
+extern "C" int pthread_atfork(void (*prepare)(void), void (*parent)(void),
+ void (*child)(void));
+extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v));
+extern "C" int pthread_setspecific(unsigned key, const void *v);
+DECLARE_REAL(int, pthread_mutexattr_gettype, void *, void *)
+DECLARE_REAL(int, fflush, __sanitizer_FILE *fp)
+DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr size)
+DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
+extern "C" int pthread_equal(void *t1, void *t2);
+extern "C" void *pthread_self();
+extern "C" void _exit(int status);
+#if !SANITIZER_NETBSD
+extern "C" int fileno_unlocked(void *stream);
+extern "C" int dirfd(void *dirp);
+#endif
+#if SANITIZER_NETBSD
+extern __sanitizer_FILE __sF[];
+#else
+extern __sanitizer_FILE *stdout, *stderr;
+#endif
+#if !SANITIZER_FREEBSD && !SANITIZER_APPLE && !SANITIZER_NETBSD
+const int PTHREAD_MUTEX_RECURSIVE = 1;
+const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
+#else
+const int PTHREAD_MUTEX_RECURSIVE = 2;
+const int PTHREAD_MUTEX_RECURSIVE_NP = 2;
+#endif
+#if !SANITIZER_FREEBSD && !SANITIZER_APPLE && !SANITIZER_NETBSD
+const int EPOLL_CTL_ADD = 1;
+#endif
+const int SIGILL = 4;
+const int SIGTRAP = 5;
+const int SIGABRT = 6;
+const int SIGFPE = 8;
+const int SIGSEGV = 11;
+const int SIGPIPE = 13;
+const int SIGTERM = 15;
+#if defined(__mips__) || SANITIZER_FREEBSD || SANITIZER_APPLE || SANITIZER_NETBSD
+const int SIGBUS = 10;
+const int SIGSYS = 12;
+#else
+const int SIGBUS = 7;
+const int SIGSYS = 31;
+#endif
+const int SI_TIMER = -2;
+void *const MAP_FAILED = (void*)-1;
+#if SANITIZER_NETBSD
+const int PTHREAD_BARRIER_SERIAL_THREAD = 1234567;
+#elif !SANITIZER_APPLE
+const int PTHREAD_BARRIER_SERIAL_THREAD = -1;
+#endif
+const int MAP_FIXED = 0x10;
+typedef long long_t;
+typedef __sanitizer::u16 mode_t;
+
+// From /usr/include/unistd.h
+# define F_ULOCK 0 /* Unlock a previously locked region. */
+# define F_LOCK 1 /* Lock a region for exclusive use. */
+# define F_TLOCK 2 /* Test and lock a region for exclusive use. */
+# define F_TEST 3 /* Test a region for other processes locks. */
+
+#if SANITIZER_FREEBSD || SANITIZER_APPLE || SANITIZER_NETBSD
+const int SA_SIGINFO = 0x40;
+const int SIG_SETMASK = 3;
+#elif defined(__mips__)
+const int SA_SIGINFO = 8;
+const int SIG_SETMASK = 3;
+#else
+const int SA_SIGINFO = 4;
+const int SIG_SETMASK = 2;
+#endif
+
+#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED \
+ (!cur_thread_init()->is_inited)
+
+namespace __tsan {
+struct SignalDesc {
+ bool armed;
+ __sanitizer_siginfo siginfo;
+ ucontext_t ctx;
+};
+
+struct ThreadSignalContext {
+ int int_signal_send;
+ SignalDesc pending_signals[kSigCount];
+ // emptyset and oldset are too big for stack.
+ __sanitizer_sigset_t emptyset;
+ __sanitizer_sigset_t oldset;
+};
+
+void EnterBlockingFunc(ThreadState *thr) {
+ for (;;) {
+ // The order is important to not delay a signal infinitely if it's
+ // delivered right before we set in_blocking_func. Note: we can't call
+ // ProcessPendingSignals when in_blocking_func is set, or we can handle
+ // a signal synchronously when we are already handling a signal.
+ atomic_store(&thr->in_blocking_func, 1, memory_order_relaxed);
+ if (atomic_load(&thr->pending_signals, memory_order_relaxed) == 0)
+ break;
+ atomic_store(&thr->in_blocking_func, 0, memory_order_relaxed);
+ ProcessPendingSignals(thr);
+ }
+}
+
+// The sole reason tsan wraps atexit callbacks is to establish synchronization
+// between callback setup and callback execution.
+struct AtExitCtx {
+ void (*f)();
+ void *arg;
+ uptr pc;
+};
+
+// InterceptorContext holds all global data required for interceptors.
+// It's explicitly constructed in InitializeInterceptors with placement new
+// and is never destroyed. This allows usage of members with non-trivial
+// constructors and destructors.
+struct InterceptorContext {
+ // The object is 64-byte aligned, because we want hot data to be located
+ // in a single cache line if possible (it's accessed in every interceptor).
+ ALIGNED(64) LibIgnore libignore;
+ __sanitizer_sigaction sigactions[kSigCount];
+#if !SANITIZER_APPLE && !SANITIZER_NETBSD
+ unsigned finalize_key;
+#endif
+
+ Mutex atexit_mu;
+ Vector<struct AtExitCtx *> AtExitStack;
+
+ InterceptorContext() : libignore(LINKER_INITIALIZED), atexit_mu(MutexTypeAtExit), AtExitStack() {}
+};
+
+static ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)];
+InterceptorContext *interceptor_ctx() {
+ return reinterpret_cast<InterceptorContext*>(&interceptor_placeholder[0]);
+}
+
+LibIgnore *libignore() {
+ return &interceptor_ctx()->libignore;
+}
+
+void InitializeLibIgnore() {
+ const SuppressionContext &supp = *Suppressions();
+ const uptr n = supp.SuppressionCount();
+ for (uptr i = 0; i < n; i++) {
+ const Suppression *s = supp.SuppressionAt(i);
+ if (0 == internal_strcmp(s->type, kSuppressionLib))
+ libignore()->AddIgnoredLibrary(s->templ);
+ }
+ if (flags()->ignore_noninstrumented_modules)
+ libignore()->IgnoreNoninstrumentedModules(true);
+ libignore()->OnLibraryLoaded(0);
+}
+
+// The following two hooks can be used by for cooperative scheduling when
+// locking.
+#ifdef TSAN_EXTERNAL_HOOKS
+void OnPotentiallyBlockingRegionBegin();
+void OnPotentiallyBlockingRegionEnd();
+#else
+SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionBegin() {}
+SANITIZER_WEAK_CXX_DEFAULT_IMPL void OnPotentiallyBlockingRegionEnd() {}
+#endif
+
+} // namespace __tsan
+
+static ThreadSignalContext *SigCtx(ThreadState *thr) {
+ // This function may be called reentrantly if it is interrupted by a signal
+ // handler. Use CAS to handle the race.
+ uptr ctx = atomic_load(&thr->signal_ctx, memory_order_relaxed);
+ if (ctx == 0 && !thr->is_dead) {
+ uptr pctx =
+ (uptr)MmapOrDie(sizeof(ThreadSignalContext), "ThreadSignalContext");
+ MemoryResetRange(thr, (uptr)&SigCtx, pctx, sizeof(ThreadSignalContext));
+ if (atomic_compare_exchange_strong(&thr->signal_ctx, &ctx, pctx,
+ memory_order_relaxed)) {
+ ctx = pctx;
+ } else {
+ UnmapOrDie((ThreadSignalContext *)pctx, sizeof(ThreadSignalContext));
+ }
+ }
+ return (ThreadSignalContext *)ctx;
+}
+
+ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
+ uptr pc)
+ : thr_(thr) {
+ LazyInitialize(thr);
+ if (UNLIKELY(atomic_load(&thr->in_blocking_func, memory_order_relaxed))) {
+ // pthread_join is marked as blocking, but it's also known to call other
+ // intercepted functions (mmap, free). If we don't reset in_blocking_func
+ // we can get deadlocks and memory corruptions if we deliver a synchronous
+ // signal inside of an mmap/free interceptor.
+ // So reset it and restore it back in the destructor.
+ // See https://github.com/google/sanitizers/issues/1540
+ atomic_store(&thr->in_blocking_func, 0, memory_order_relaxed);
+ in_blocking_func_ = true;
+ }
+ if (!thr_->is_inited) return;
+ if (!thr_->ignore_interceptors) FuncEntry(thr, pc);
+ DPrintf("#%d: intercept %s()\n", thr_->tid, fname);
+ ignoring_ =
+ !thr_->in_ignored_lib && (flags()->ignore_interceptors_accesses ||
+ libignore()->IsIgnored(pc, &in_ignored_lib_));
+ EnableIgnores();
+}
+
+ScopedInterceptor::~ScopedInterceptor() {
+ if (!thr_->is_inited) return;
+ DisableIgnores();
+ if (UNLIKELY(in_blocking_func_))
+ EnterBlockingFunc(thr_);
+ if (!thr_->ignore_interceptors) {
+ ProcessPendingSignals(thr_);
+ FuncExit(thr_);
+ CheckedMutex::CheckNoLocks();
+ }
+}
+
+NOINLINE
+void ScopedInterceptor::EnableIgnoresImpl() {
+ ThreadIgnoreBegin(thr_, 0);
+ if (flags()->ignore_noninstrumented_modules)
+ thr_->suppress_reports++;
+ if (in_ignored_lib_) {
+ DCHECK(!thr_->in_ignored_lib);
+ thr_->in_ignored_lib = true;
+ }
+}
+
+NOINLINE
+void ScopedInterceptor::DisableIgnoresImpl() {
+ ThreadIgnoreEnd(thr_);
+ if (flags()->ignore_noninstrumented_modules)
+ thr_->suppress_reports--;
+ if (in_ignored_lib_) {
+ DCHECK(thr_->in_ignored_lib);
+ thr_->in_ignored_lib = false;
+ }
+}
+
+#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
+#if SANITIZER_FREEBSD || SANITIZER_NETBSD
+# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func)
+#else
+# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION_VER(func, ver)
+#endif
+#if SANITIZER_FREEBSD
+# define TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(func) \
+ INTERCEPT_FUNCTION(_pthread_##func)
+#else
+# define TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(func)
+#endif
+#if SANITIZER_NETBSD
+# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(func) \
+ INTERCEPT_FUNCTION(__libc_##func)
+# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(func) \
+ INTERCEPT_FUNCTION(__libc_thr_##func)
+#else
+# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(func)
+# define TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(func)
+#endif
+
+#define READ_STRING_OF_LEN(thr, pc, s, len, n) \
+ MemoryAccessRange((thr), (pc), (uptr)(s), \
+ common_flags()->strict_string_checks ? (len) + 1 : (n), false)
+
+#define READ_STRING(thr, pc, s, n) \
+ READ_STRING_OF_LEN((thr), (pc), (s), internal_strlen(s), (n))
+
+#define BLOCK_REAL(name) (BlockingCall(thr), REAL(name))
+
+struct BlockingCall {
+ explicit BlockingCall(ThreadState *thr)
+ : thr(thr) {
+ EnterBlockingFunc(thr);
+ // When we are in a "blocking call", we process signals asynchronously
+ // (right when they arrive). In this context we do not expect to be
+ // executing any user/runtime code. The known interceptor sequence when
+ // this is not true is: pthread_join -> munmap(stack). It's fine
+ // to ignore munmap in this case -- we handle stack shadow separately.
+ thr->ignore_interceptors++;
+ }
+
+ ~BlockingCall() {
+ thr->ignore_interceptors--;
+ atomic_store(&thr->in_blocking_func, 0, memory_order_relaxed);
+ }
+
+ ThreadState *thr;
+};
+
+TSAN_INTERCEPTOR(unsigned, sleep, unsigned sec) {
+ SCOPED_TSAN_INTERCEPTOR(sleep, sec);
+ unsigned res = BLOCK_REAL(sleep)(sec);
+ AfterSleep(thr, pc);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, usleep, long_t usec) {
+ SCOPED_TSAN_INTERCEPTOR(usleep, usec);
+ int res = BLOCK_REAL(usleep)(usec);
+ AfterSleep(thr, pc);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) {
+ SCOPED_TSAN_INTERCEPTOR(nanosleep, req, rem);
+ int res = BLOCK_REAL(nanosleep)(req, rem);
+ AfterSleep(thr, pc);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pause, int fake) {
+ SCOPED_TSAN_INTERCEPTOR(pause, fake);
+ return BLOCK_REAL(pause)(fake);
+}
+
+// Note: we specifically call the function in such strange way
+// with "installed_at" because in reports it will appear between
+// callback frames and the frame that installed the callback.
+static void at_exit_callback_installed_at() {
+ AtExitCtx *ctx;
+ {
+ // Ensure thread-safety.
+ Lock l(&interceptor_ctx()->atexit_mu);
+
+ // Pop AtExitCtx from the top of the stack of callback functions
+ uptr element = interceptor_ctx()->AtExitStack.Size() - 1;
+ ctx = interceptor_ctx()->AtExitStack[element];
+ interceptor_ctx()->AtExitStack.PopBack();
+ }
+
+ ThreadState *thr = cur_thread();
+ Acquire(thr, ctx->pc, (uptr)ctx);
+ FuncEntry(thr, ctx->pc);
+ ((void(*)())ctx->f)();
+ FuncExit(thr);
+ Free(ctx);
+}
+
+static void cxa_at_exit_callback_installed_at(void *arg) {
+ ThreadState *thr = cur_thread();
+ AtExitCtx *ctx = (AtExitCtx*)arg;
+ Acquire(thr, ctx->pc, (uptr)arg);
+ FuncEntry(thr, ctx->pc);
+ ((void(*)(void *arg))ctx->f)(ctx->arg);
+ FuncExit(thr);
+ Free(ctx);
+}
+
+static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
+ void *arg, void *dso);
+
+#if !SANITIZER_ANDROID
+TSAN_INTERCEPTOR(int, atexit, void (*f)()) {
+ if (in_symbolizer())
+ return 0;
+ // We want to setup the atexit callback even if we are in ignored lib
+ // or after fork.
+ SCOPED_INTERCEPTOR_RAW(atexit, f);
+ return setup_at_exit_wrapper(thr, GET_CALLER_PC(), (void (*)())f, 0, 0);
+}
+#endif
+
+TSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) {
+ if (in_symbolizer())
+ return 0;
+ SCOPED_TSAN_INTERCEPTOR(__cxa_atexit, f, arg, dso);
+ return setup_at_exit_wrapper(thr, GET_CALLER_PC(), (void (*)())f, arg, dso);
+}
+
+static int setup_at_exit_wrapper(ThreadState *thr, uptr pc, void(*f)(),
+ void *arg, void *dso) {
+ auto *ctx = New<AtExitCtx>();
+ ctx->f = f;
+ ctx->arg = arg;
+ ctx->pc = pc;
+ Release(thr, pc, (uptr)ctx);
+ // Memory allocation in __cxa_atexit will race with free during exit,
+ // because we do not see synchronization around atexit callback list.
+ ThreadIgnoreBegin(thr, pc);
+ int res;
+ if (!dso) {
+ // NetBSD does not preserve the 2nd argument if dso is equal to 0
+ // Store ctx in a local stack-like structure
+
+ // Ensure thread-safety.
+ Lock l(&interceptor_ctx()->atexit_mu);
+ // __cxa_atexit calls calloc. If we don't ignore interceptors, we will fail
+ // due to atexit_mu held on exit from the calloc interceptor.
+ ScopedIgnoreInterceptors ignore;
+
+ res = REAL(__cxa_atexit)((void (*)(void *a))at_exit_callback_installed_at,
+ 0, 0);
+ // Push AtExitCtx on the top of the stack of callback functions
+ if (!res) {
+ interceptor_ctx()->AtExitStack.PushBack(ctx);
+ }
+ } else {
+ res = REAL(__cxa_atexit)(cxa_at_exit_callback_installed_at, ctx, dso);
+ }
+ ThreadIgnoreEnd(thr);
+ return res;
+}
+
+#if !SANITIZER_APPLE && !SANITIZER_NETBSD
+static void on_exit_callback_installed_at(int status, void *arg) {
+ ThreadState *thr = cur_thread();
+ AtExitCtx *ctx = (AtExitCtx*)arg;
+ Acquire(thr, ctx->pc, (uptr)arg);
+ FuncEntry(thr, ctx->pc);
+ ((void(*)(int status, void *arg))ctx->f)(status, ctx->arg);
+ FuncExit(thr);
+ Free(ctx);
+}
+
+TSAN_INTERCEPTOR(int, on_exit, void(*f)(int, void*), void *arg) {
+ if (in_symbolizer())
+ return 0;
+ SCOPED_TSAN_INTERCEPTOR(on_exit, f, arg);
+ auto *ctx = New<AtExitCtx>();
+ ctx->f = (void(*)())f;
+ ctx->arg = arg;
+ ctx->pc = GET_CALLER_PC();
+ Release(thr, pc, (uptr)ctx);
+ // Memory allocation in __cxa_atexit will race with free during exit,
+ // because we do not see synchronization around atexit callback list.
+ ThreadIgnoreBegin(thr, pc);
+ int res = REAL(on_exit)(on_exit_callback_installed_at, ctx);
+ ThreadIgnoreEnd(thr);
+ return res;
+}
+#define TSAN_MAYBE_INTERCEPT_ON_EXIT TSAN_INTERCEPT(on_exit)
+#else
+#define TSAN_MAYBE_INTERCEPT_ON_EXIT
+#endif
+
+// Cleanup old bufs.
+static void JmpBufGarbageCollect(ThreadState *thr, uptr sp) {
+ for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) {
+ JmpBuf *buf = &thr->jmp_bufs[i];
+ if (buf->sp <= sp) {
+ uptr sz = thr->jmp_bufs.Size();
+ internal_memcpy(buf, &thr->jmp_bufs[sz - 1], sizeof(*buf));
+ thr->jmp_bufs.PopBack();
+ i--;
+ }
+ }
+}
+
+static void SetJmp(ThreadState *thr, uptr sp) {
+ if (!thr->is_inited) // called from libc guts during bootstrap
+ return;
+ // Cleanup old bufs.
+ JmpBufGarbageCollect(thr, sp);
+ // Remember the buf.
+ JmpBuf *buf = thr->jmp_bufs.PushBack();
+ buf->sp = sp;
+ buf->shadow_stack_pos = thr->shadow_stack_pos;
+ ThreadSignalContext *sctx = SigCtx(thr);
+ buf->int_signal_send = sctx ? sctx->int_signal_send : 0;
+ buf->in_blocking_func = atomic_load(&thr->in_blocking_func, memory_order_relaxed);
+ buf->in_signal_handler = atomic_load(&thr->in_signal_handler,
+ memory_order_relaxed);
+}
+
+static void LongJmp(ThreadState *thr, uptr *env) {
+ uptr sp = ExtractLongJmpSp(env);
+ // Find the saved buf with matching sp.
+ for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) {
+ JmpBuf *buf = &thr->jmp_bufs[i];
+ if (buf->sp == sp) {
+ CHECK_GE(thr->shadow_stack_pos, buf->shadow_stack_pos);
+ // Unwind the stack.
+ while (thr->shadow_stack_pos > buf->shadow_stack_pos)
+ FuncExit(thr);
+ ThreadSignalContext *sctx = SigCtx(thr);
+ if (sctx)
+ sctx->int_signal_send = buf->int_signal_send;
+ atomic_store(&thr->in_blocking_func, buf->in_blocking_func,
+ memory_order_relaxed);
+ atomic_store(&thr->in_signal_handler, buf->in_signal_handler,
+ memory_order_relaxed);
+ JmpBufGarbageCollect(thr, buf->sp - 1); // do not collect buf->sp
+ return;
+ }
+ }
+ Printf("ThreadSanitizer: can't find longjmp buf\n");
+ CHECK(0);
+}
+
+// FIXME: put everything below into a common extern "C" block?
+extern "C" void __tsan_setjmp(uptr sp) { SetJmp(cur_thread_init(), sp); }
+
+#if SANITIZER_APPLE
+TSAN_INTERCEPTOR(int, setjmp, void *env);
+TSAN_INTERCEPTOR(int, _setjmp, void *env);
+TSAN_INTERCEPTOR(int, sigsetjmp, void *env);
+#else // SANITIZER_APPLE
+
+#if SANITIZER_NETBSD
+#define setjmp_symname __setjmp14
+#define sigsetjmp_symname __sigsetjmp14
+#else
+#define setjmp_symname setjmp
+#define sigsetjmp_symname sigsetjmp
+#endif
+
+#define TSAN_INTERCEPTOR_SETJMP_(x) __interceptor_ ## x
+#define TSAN_INTERCEPTOR_SETJMP__(x) TSAN_INTERCEPTOR_SETJMP_(x)
+#define TSAN_INTERCEPTOR_SETJMP TSAN_INTERCEPTOR_SETJMP__(setjmp_symname)
+#define TSAN_INTERCEPTOR_SIGSETJMP TSAN_INTERCEPTOR_SETJMP__(sigsetjmp_symname)
+
+#define TSAN_STRING_SETJMP SANITIZER_STRINGIFY(setjmp_symname)
+#define TSAN_STRING_SIGSETJMP SANITIZER_STRINGIFY(sigsetjmp_symname)
+
+// Not called. Merely to satisfy TSAN_INTERCEPT().
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+int TSAN_INTERCEPTOR_SETJMP(void *env);
+extern "C" int TSAN_INTERCEPTOR_SETJMP(void *env) {
+ CHECK(0);
+ return 0;
+}
+
+// FIXME: any reason to have a separate declaration?
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+int __interceptor__setjmp(void *env);
+extern "C" int __interceptor__setjmp(void *env) {
+ CHECK(0);
+ return 0;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+int TSAN_INTERCEPTOR_SIGSETJMP(void *env);
+extern "C" int TSAN_INTERCEPTOR_SIGSETJMP(void *env) {
+ CHECK(0);
+ return 0;
+}
+
+#if !SANITIZER_NETBSD
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+int __interceptor___sigsetjmp(void *env);
+extern "C" int __interceptor___sigsetjmp(void *env) {
+ CHECK(0);
+ return 0;
+}
+#endif
+
+extern "C" int setjmp_symname(void *env);
+extern "C" int _setjmp(void *env);
+extern "C" int sigsetjmp_symname(void *env);
+#if !SANITIZER_NETBSD
+extern "C" int __sigsetjmp(void *env);
+#endif
+DEFINE_REAL(int, setjmp_symname, void *env)
+DEFINE_REAL(int, _setjmp, void *env)
+DEFINE_REAL(int, sigsetjmp_symname, void *env)
+#if !SANITIZER_NETBSD
+DEFINE_REAL(int, __sigsetjmp, void *env)
+#endif
+#endif // SANITIZER_APPLE
+
+#if SANITIZER_NETBSD
+#define longjmp_symname __longjmp14
+#define siglongjmp_symname __siglongjmp14
+#else
+#define longjmp_symname longjmp
+#define siglongjmp_symname siglongjmp
+#endif
+
+TSAN_INTERCEPTOR(void, longjmp_symname, uptr *env, int val) {
+ // Note: if we call REAL(longjmp) in the context of ScopedInterceptor,
+ // bad things will happen. We will jump over ScopedInterceptor dtor and can
+ // leave thr->in_ignored_lib set.
+ {
+ SCOPED_INTERCEPTOR_RAW(longjmp_symname, env, val);
+ }
+ LongJmp(cur_thread(), env);
+ REAL(longjmp_symname)(env, val);
+}
+
+TSAN_INTERCEPTOR(void, siglongjmp_symname, uptr *env, int val) {
+ {
+ SCOPED_INTERCEPTOR_RAW(siglongjmp_symname, env, val);
+ }
+ LongJmp(cur_thread(), env);
+ REAL(siglongjmp_symname)(env, val);
+}
+
+#if SANITIZER_NETBSD
+TSAN_INTERCEPTOR(void, _longjmp, uptr *env, int val) {
+ {
+ SCOPED_INTERCEPTOR_RAW(_longjmp, env, val);
+ }
+ LongJmp(cur_thread(), env);
+ REAL(_longjmp)(env, val);
+}
+#endif
+
+#if !SANITIZER_APPLE
+TSAN_INTERCEPTOR(void*, malloc, uptr size) {
+ if (in_symbolizer())
+ return InternalAlloc(size);
+ void *p = 0;
+ {
+ SCOPED_INTERCEPTOR_RAW(malloc, size);
+ p = user_alloc(thr, pc, size);
+ }
+ invoke_malloc_hook(p, size);
+ return p;
+}
+
+// In glibc<2.25, dynamic TLS blocks are allocated by __libc_memalign. Intercept
+// __libc_memalign so that (1) we can detect races (2) free will not be called
+// on libc internally allocated blocks.
+TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) {
+ SCOPED_INTERCEPTOR_RAW(__libc_memalign, align, sz);
+ return user_memalign(thr, pc, align, sz);
+}
+
+TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
+ if (in_symbolizer())
+ return InternalCalloc(size, n);
+ void *p = 0;
+ {
+ SCOPED_INTERCEPTOR_RAW(calloc, size, n);
+ p = user_calloc(thr, pc, size, n);
+ }
+ invoke_malloc_hook(p, n * size);
+ return p;
+}
+
+TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
+ if (in_symbolizer())
+ return InternalRealloc(p, size);
+ if (p)
+ invoke_free_hook(p);
+ {
+ SCOPED_INTERCEPTOR_RAW(realloc, p, size);
+ p = user_realloc(thr, pc, p, size);
+ }
+ invoke_malloc_hook(p, size);
+ return p;
+}
+
+TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr size, uptr n) {
+ if (in_symbolizer())
+ return InternalReallocArray(p, size, n);
+ if (p)
+ invoke_free_hook(p);
+ {
+ SCOPED_INTERCEPTOR_RAW(reallocarray, p, size, n);
+ p = user_reallocarray(thr, pc, p, size, n);
+ }
+ invoke_malloc_hook(p, size);
+ return p;
+}
+
+TSAN_INTERCEPTOR(void, free, void *p) {
+ if (p == 0)
+ return;
+ if (in_symbolizer())
+ return InternalFree(p);
+ invoke_free_hook(p);
+ SCOPED_INTERCEPTOR_RAW(free, p);
+ user_free(thr, pc, p);
+}
+
+TSAN_INTERCEPTOR(void, cfree, void *p) {
+ if (p == 0)
+ return;
+ if (in_symbolizer())
+ return InternalFree(p);
+ invoke_free_hook(p);
+ SCOPED_INTERCEPTOR_RAW(cfree, p);
+ user_free(thr, pc, p);
+}
+
+TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) {
+ SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p);
+ return user_alloc_usable_size(p);
+}
+#endif
+
+TSAN_INTERCEPTOR(char *, strcpy, char *dst, const char *src) {
+ SCOPED_TSAN_INTERCEPTOR(strcpy, dst, src);
+ uptr srclen = internal_strlen(src);
+ MemoryAccessRange(thr, pc, (uptr)dst, srclen + 1, true);
+ MemoryAccessRange(thr, pc, (uptr)src, srclen + 1, false);
+ return REAL(strcpy)(dst, src);
+}
+
+TSAN_INTERCEPTOR(char*, strncpy, char *dst, char *src, uptr n) {
+ SCOPED_TSAN_INTERCEPTOR(strncpy, dst, src, n);
+ uptr srclen = internal_strnlen(src, n);
+ MemoryAccessRange(thr, pc, (uptr)dst, n, true);
+ MemoryAccessRange(thr, pc, (uptr)src, min(srclen + 1, n), false);
+ return REAL(strncpy)(dst, src, n);
+}
+
+TSAN_INTERCEPTOR(char*, strdup, const char *str) {
+ SCOPED_TSAN_INTERCEPTOR(strdup, str);
+ // strdup will call malloc, so no instrumentation is required here.
+ return REAL(strdup)(str);
+}
+
+// Zero out addr if it points into shadow memory and was provided as a hint
+// only, i.e., MAP_FIXED is not set.
+static bool fix_mmap_addr(void **addr, long_t sz, int flags) {
+ if (*addr) {
+ if (!IsAppMem((uptr)*addr) || !IsAppMem((uptr)*addr + sz - 1)) {
+ if (flags & MAP_FIXED) {
+ errno = errno_EINVAL;
+ return false;
+ } else {
+ *addr = 0;
+ }
+ }
+ }
+ return true;
+}
+
+template <class Mmap>
+static void *mmap_interceptor(ThreadState *thr, uptr pc, Mmap real_mmap,
+ void *addr, SIZE_T sz, int prot, int flags,
+ int fd, OFF64_T off) {
+ if (!fix_mmap_addr(&addr, sz, flags)) return MAP_FAILED;
+ void *res = real_mmap(addr, sz, prot, flags, fd, off);
+ if (res != MAP_FAILED) {
+ if (!IsAppMem((uptr)res) || !IsAppMem((uptr)res + sz - 1)) {
+ Report("ThreadSanitizer: mmap at bad address: addr=%p size=%p res=%p\n",
+ addr, (void*)sz, res);
+ Die();
+ }
+ if (fd > 0) FdAccess(thr, pc, fd);
+ MemoryRangeImitateWriteOrResetRange(thr, pc, (uptr)res, sz);
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) {
+ SCOPED_TSAN_INTERCEPTOR(munmap, addr, sz);
+ UnmapShadow(thr, (uptr)addr, sz);
+ int res = REAL(munmap)(addr, sz);
+ return res;
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) {
+ SCOPED_INTERCEPTOR_RAW(memalign, align, sz);
+ return user_memalign(thr, pc, align, sz);
+}
+#define TSAN_MAYBE_INTERCEPT_MEMALIGN TSAN_INTERCEPT(memalign)
+#else
+#define TSAN_MAYBE_INTERCEPT_MEMALIGN
+#endif
+
+#if !SANITIZER_APPLE
+TSAN_INTERCEPTOR(void*, aligned_alloc, uptr align, uptr sz) {
+ if (in_symbolizer())
+ return InternalAlloc(sz, nullptr, align);
+ SCOPED_INTERCEPTOR_RAW(aligned_alloc, align, sz);
+ return user_aligned_alloc(thr, pc, align, sz);
+}
+
+TSAN_INTERCEPTOR(void*, valloc, uptr sz) {
+ if (in_symbolizer())
+ return InternalAlloc(sz, nullptr, GetPageSizeCached());
+ SCOPED_INTERCEPTOR_RAW(valloc, sz);
+ return user_valloc(thr, pc, sz);
+}
+#endif
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) {
+ if (in_symbolizer()) {
+ uptr PageSize = GetPageSizeCached();
+ sz = sz ? RoundUpTo(sz, PageSize) : PageSize;
+ return InternalAlloc(sz, nullptr, PageSize);
+ }
+ SCOPED_INTERCEPTOR_RAW(pvalloc, sz);
+ return user_pvalloc(thr, pc, sz);
+}
+#define TSAN_MAYBE_INTERCEPT_PVALLOC TSAN_INTERCEPT(pvalloc)
+#else
+#define TSAN_MAYBE_INTERCEPT_PVALLOC
+#endif
+
+#if !SANITIZER_APPLE
+TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) {
+ if (in_symbolizer()) {
+ void *p = InternalAlloc(sz, nullptr, align);
+ if (!p)
+ return errno_ENOMEM;
+ *memptr = p;
+ return 0;
+ }
+ SCOPED_INTERCEPTOR_RAW(posix_memalign, memptr, align, sz);
+ return user_posix_memalign(thr, pc, memptr, align, sz);
+}
+#endif
+
+// Both __cxa_guard_acquire and pthread_once 0-initialize
+// the object initially. pthread_once does not have any
+// other ABI requirements. __cxa_guard_acquire assumes
+// that any non-0 value in the first byte means that
+// initialization is completed. Contents of the remaining
+// bytes are up to us.
+constexpr u32 kGuardInit = 0;
+constexpr u32 kGuardDone = 1;
+constexpr u32 kGuardRunning = 1 << 16;
+constexpr u32 kGuardWaiter = 1 << 17;
+
+static int guard_acquire(ThreadState *thr, uptr pc, atomic_uint32_t *g,
+ bool blocking_hooks = true) {
+ if (blocking_hooks)
+ OnPotentiallyBlockingRegionBegin();
+ auto on_exit = at_scope_exit([blocking_hooks] {
+ if (blocking_hooks)
+ OnPotentiallyBlockingRegionEnd();
+ });
+
+ for (;;) {
+ u32 cmp = atomic_load(g, memory_order_acquire);
+ if (cmp == kGuardInit) {
+ if (atomic_compare_exchange_strong(g, &cmp, kGuardRunning,
+ memory_order_relaxed))
+ return 1;
+ } else if (cmp == kGuardDone) {
+ if (!thr->in_ignored_lib)
+ Acquire(thr, pc, (uptr)g);
+ return 0;
+ } else {
+ if ((cmp & kGuardWaiter) ||
+ atomic_compare_exchange_strong(g, &cmp, cmp | kGuardWaiter,
+ memory_order_relaxed))
+ FutexWait(g, cmp | kGuardWaiter);
+ }
+ }
+}
+
+static void guard_release(ThreadState *thr, uptr pc, atomic_uint32_t *g,
+ u32 v) {
+ if (!thr->in_ignored_lib)
+ Release(thr, pc, (uptr)g);
+ u32 old = atomic_exchange(g, v, memory_order_release);
+ if (old & kGuardWaiter)
+ FutexWake(g, 1 << 30);
+}
+
+// __cxa_guard_acquire and friends need to be intercepted in a special way -
+// regular interceptors will break statically-linked libstdc++. Linux
+// interceptors are especially defined as weak functions (so that they don't
+// cause link errors when user defines them as well). So they silently
+// auto-disable themselves when such symbol is already present in the binary. If
+// we link libstdc++ statically, it will bring own __cxa_guard_acquire which
+// will silently replace our interceptor. That's why on Linux we simply export
+// these interceptors with INTERFACE_ATTRIBUTE.
+// On OS X, we don't support statically linking, so we just use a regular
+// interceptor.
+#if SANITIZER_APPLE
+#define STDCXX_INTERCEPTOR TSAN_INTERCEPTOR
+#else
+#define STDCXX_INTERCEPTOR(rettype, name, ...) \
+ extern "C" rettype INTERFACE_ATTRIBUTE name(__VA_ARGS__)
+#endif
+
+// Used in thread-safe function static initialization.
+STDCXX_INTERCEPTOR(int, __cxa_guard_acquire, atomic_uint32_t *g) {
+ SCOPED_INTERCEPTOR_RAW(__cxa_guard_acquire, g);
+ return guard_acquire(thr, pc, g);
+}
+
+STDCXX_INTERCEPTOR(void, __cxa_guard_release, atomic_uint32_t *g) {
+ SCOPED_INTERCEPTOR_RAW(__cxa_guard_release, g);
+ guard_release(thr, pc, g, kGuardDone);
+}
+
+STDCXX_INTERCEPTOR(void, __cxa_guard_abort, atomic_uint32_t *g) {
+ SCOPED_INTERCEPTOR_RAW(__cxa_guard_abort, g);
+ guard_release(thr, pc, g, kGuardInit);
+}
+
+namespace __tsan {
+void DestroyThreadState() {
+ ThreadState *thr = cur_thread();
+ Processor *proc = thr->proc();
+ ThreadFinish(thr);
+ ProcUnwire(proc, thr);
+ ProcDestroy(proc);
+ DTLS_Destroy();
+ cur_thread_finalize();
+}
+
+void PlatformCleanUpThreadState(ThreadState *thr) {
+ ThreadSignalContext *sctx = (ThreadSignalContext *)atomic_load(
+ &thr->signal_ctx, memory_order_relaxed);
+ if (sctx) {
+ atomic_store(&thr->signal_ctx, 0, memory_order_relaxed);
+ UnmapOrDie(sctx, sizeof(*sctx));
+ }
+}
+} // namespace __tsan
+
+#if !SANITIZER_APPLE && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
+static void thread_finalize(void *v) {
+ uptr iter = (uptr)v;
+ if (iter > 1) {
+ if (pthread_setspecific(interceptor_ctx()->finalize_key,
+ (void*)(iter - 1))) {
+ Printf("ThreadSanitizer: failed to set thread key\n");
+ Die();
+ }
+ return;
+ }
+ DestroyThreadState();
+}
+#endif
+
+
+struct ThreadParam {
+ void* (*callback)(void *arg);
+ void *param;
+ Tid tid;
+ Semaphore created;
+ Semaphore started;
+};
+
+extern "C" void *__tsan_thread_start_func(void *arg) {
+ ThreadParam *p = (ThreadParam*)arg;
+ void* (*callback)(void *arg) = p->callback;
+ void *param = p->param;
+ {
+ ThreadState *thr = cur_thread_init();
+ // Thread-local state is not initialized yet.
+ ScopedIgnoreInterceptors ignore;
+#if !SANITIZER_APPLE && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
+ ThreadIgnoreBegin(thr, 0);
+ if (pthread_setspecific(interceptor_ctx()->finalize_key,
+ (void *)GetPthreadDestructorIterations())) {
+ Printf("ThreadSanitizer: failed to set thread key\n");
+ Die();
+ }
+ ThreadIgnoreEnd(thr);
+#endif
+ p->created.Wait();
+ Processor *proc = ProcCreate();
+ ProcWire(proc, thr);
+ ThreadStart(thr, p->tid, GetTid(), ThreadType::Regular);
+ p->started.Post();
+ }
+ void *res = callback(param);
+ // Prevent the callback from being tail called,
+ // it mixes up stack traces.
+ volatile int foo = 42;
+ foo++;
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_create,
+ void *th, void *attr, void *(*callback)(void*), void * param) {
+ SCOPED_INTERCEPTOR_RAW(pthread_create, th, attr, callback, param);
+
+ MaybeSpawnBackgroundThread();
+
+ if (ctx->after_multithreaded_fork) {
+ if (flags()->die_after_fork) {
+ Report("ThreadSanitizer: starting new threads after multi-threaded "
+ "fork is not supported. Dying (set die_after_fork=0 to override)\n");
+ Die();
+ } else {
+ VPrintf(1,
+ "ThreadSanitizer: starting new threads after multi-threaded "
+ "fork is not supported (pid %lu). Continuing because of "
+ "die_after_fork=0, but you are on your own\n",
+ internal_getpid());
+ }
+ }
+ __sanitizer_pthread_attr_t myattr;
+ if (attr == 0) {
+ pthread_attr_init(&myattr);
+ attr = &myattr;
+ }
+ int detached = 0;
+ REAL(pthread_attr_getdetachstate)(attr, &detached);
+ AdjustStackSize(attr);
+
+ ThreadParam p;
+ p.callback = callback;
+ p.param = param;
+ p.tid = kMainTid;
+ int res = -1;
+ {
+ // Otherwise we see false positives in pthread stack manipulation.
+ ScopedIgnoreInterceptors ignore;
+ ThreadIgnoreBegin(thr, pc);
+ res = REAL(pthread_create)(th, attr, __tsan_thread_start_func, &p);
+ ThreadIgnoreEnd(thr);
+ }
+ if (res == 0) {
+ p.tid = ThreadCreate(thr, pc, *(uptr *)th, IsStateDetached(detached));
+ CHECK_NE(p.tid, kMainTid);
+ // Synchronization on p.tid serves two purposes:
+ // 1. ThreadCreate must finish before the new thread starts.
+ // Otherwise the new thread can call pthread_detach, but the pthread_t
+ // identifier is not yet registered in ThreadRegistry by ThreadCreate.
+ // 2. ThreadStart must finish before this thread continues.
+ // Otherwise, this thread can call pthread_detach and reset thr->sync
+ // before the new thread got a chance to acquire from it in ThreadStart.
+ p.created.Post();
+ p.started.Wait();
+ }
+ if (attr == &myattr)
+ pthread_attr_destroy(&myattr);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
+ SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret);
+ Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
+ ThreadIgnoreBegin(thr, pc);
+ int res = BLOCK_REAL(pthread_join)(th, ret);
+ ThreadIgnoreEnd(thr);
+ if (res == 0) {
+ ThreadJoin(thr, pc, tid);
+ }
+ return res;
+}
+
+DEFINE_REAL_PTHREAD_FUNCTIONS
+
+TSAN_INTERCEPTOR(int, pthread_detach, void *th) {
+ SCOPED_INTERCEPTOR_RAW(pthread_detach, th);
+ Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
+ int res = REAL(pthread_detach)(th);
+ if (res == 0) {
+ ThreadDetach(thr, pc, tid);
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(void, pthread_exit, void *retval) {
+ {
+ SCOPED_INTERCEPTOR_RAW(pthread_exit, retval);
+#if !SANITIZER_APPLE && !SANITIZER_ANDROID
+ CHECK_EQ(thr, &cur_thread_placeholder);
+#endif
+ }
+ REAL(pthread_exit)(retval);
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void *th, void **ret) {
+ SCOPED_INTERCEPTOR_RAW(pthread_tryjoin_np, th, ret);
+ Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
+ ThreadIgnoreBegin(thr, pc);
+ int res = REAL(pthread_tryjoin_np)(th, ret);
+ ThreadIgnoreEnd(thr);
+ if (res == 0)
+ ThreadJoin(thr, pc, tid);
+ else
+ ThreadNotJoined(thr, pc, tid, (uptr)th);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_timedjoin_np, void *th, void **ret,
+ const struct timespec *abstime) {
+ SCOPED_INTERCEPTOR_RAW(pthread_timedjoin_np, th, ret, abstime);
+ Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
+ ThreadIgnoreBegin(thr, pc);
+ int res = BLOCK_REAL(pthread_timedjoin_np)(th, ret, abstime);
+ ThreadIgnoreEnd(thr);
+ if (res == 0)
+ ThreadJoin(thr, pc, tid);
+ else
+ ThreadNotJoined(thr, pc, tid, (uptr)th);
+ return res;
+}
+#endif
+
+// Problem:
+// NPTL implementation of pthread_cond has 2 versions (2.2.5 and 2.3.2).
+// pthread_cond_t has different size in the different versions.
+// If call new REAL functions for old pthread_cond_t, they will corrupt memory
+// after pthread_cond_t (old cond is smaller).
+// If we call old REAL functions for new pthread_cond_t, we will lose some
+// functionality (e.g. old functions do not support waiting against
+// CLOCK_REALTIME).
+// Proper handling would require to have 2 versions of interceptors as well.
+// But this is messy, in particular requires linker scripts when sanitizer
+// runtime is linked into a shared library.
+// Instead we assume we don't have dynamic libraries built against old
+// pthread (2.2.5 is dated by 2002). And provide legacy_pthread_cond flag
+// that allows to work with old libraries (but this mode does not support
+// some features, e.g. pthread_condattr_getpshared).
+static void *init_cond(void *c, bool force = false) {
+ // sizeof(pthread_cond_t) >= sizeof(uptr) in both versions.
+ // So we allocate additional memory on the side large enough to hold
+ // any pthread_cond_t object. Always call new REAL functions, but pass
+ // the aux object to them.
+ // Note: the code assumes that PTHREAD_COND_INITIALIZER initializes
+ // first word of pthread_cond_t to zero.
+ // It's all relevant only for linux.
+ if (!common_flags()->legacy_pthread_cond)
+ return c;
+ atomic_uintptr_t *p = (atomic_uintptr_t*)c;
+ uptr cond = atomic_load(p, memory_order_acquire);
+ if (!force && cond != 0)
+ return (void*)cond;
+ void *newcond = WRAP(malloc)(pthread_cond_t_sz);
+ internal_memset(newcond, 0, pthread_cond_t_sz);
+ if (atomic_compare_exchange_strong(p, &cond, (uptr)newcond,
+ memory_order_acq_rel))
+ return newcond;
+ WRAP(free)(newcond);
+ return (void*)cond;
+}
+
+namespace {
+
+template <class Fn>
+struct CondMutexUnlockCtx {
+ ScopedInterceptor *si;
+ ThreadState *thr;
+ uptr pc;
+ void *m;
+ void *c;
+ const Fn &fn;
+
+ int Cancel() const { return fn(); }
+ void Unlock() const;
+};
+
+template <class Fn>
+void CondMutexUnlockCtx<Fn>::Unlock() const {
+ // pthread_cond_wait interceptor has enabled async signal delivery
+ // (see BlockingCall below). Disable async signals since we are running
+ // tsan code. Also ScopedInterceptor and BlockingCall destructors won't run
+ // since the thread is cancelled, so we have to manually execute them
+ // (the thread still can run some user code due to pthread_cleanup_push).
+ CHECK_EQ(atomic_load(&thr->in_blocking_func, memory_order_relaxed), 1);
+ atomic_store(&thr->in_blocking_func, 0, memory_order_relaxed);
+ MutexPostLock(thr, pc, (uptr)m, MutexFlagDoPreLockOnPostLock);
+ // Undo BlockingCall ctor effects.
+ thr->ignore_interceptors--;
+ si->~ScopedInterceptor();
+}
+} // namespace
+
+INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
+ void *cond = init_cond(c, true);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_init, cond, a);
+ MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), true);
+ return REAL(pthread_cond_init)(cond, a);
+}
+
+template <class Fn>
+int cond_wait(ThreadState *thr, uptr pc, ScopedInterceptor *si, const Fn &fn,
+ void *c, void *m) {
+ MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
+ MutexUnlock(thr, pc, (uptr)m);
+ int res = 0;
+ // This ensures that we handle mutex lock even in case of pthread_cancel.
+ // See test/tsan/cond_cancel.cpp.
+ {
+ // Enable signal delivery while the thread is blocked.
+ BlockingCall bc(thr);
+ CondMutexUnlockCtx<Fn> arg = {si, thr, pc, m, c, fn};
+ res = call_pthread_cancel_with_cleanup(
+ [](void *arg) -> int {
+ return ((const CondMutexUnlockCtx<Fn> *)arg)->Cancel();
+ },
+ [](void *arg) { ((const CondMutexUnlockCtx<Fn> *)arg)->Unlock(); },
+ &arg);
+ }
+ if (res == errno_EOWNERDEAD) MutexRepair(thr, pc, (uptr)m);
+ MutexPostLock(thr, pc, (uptr)m, MutexFlagDoPreLockOnPostLock);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
+ void *cond = init_cond(c);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, cond, m);
+ return cond_wait(
+ thr, pc, &si, [=]() { return REAL(pthread_cond_wait)(cond, m); }, cond,
+ m);
+}
+
+INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) {
+ void *cond = init_cond(c);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, cond, m, abstime);
+ return cond_wait(
+ thr, pc, &si,
+ [=]() { return REAL(pthread_cond_timedwait)(cond, m, abstime); }, cond,
+ m);
+}
+
+#if SANITIZER_LINUX
+INTERCEPTOR(int, pthread_cond_clockwait, void *c, void *m,
+ __sanitizer_clockid_t clock, void *abstime) {
+ void *cond = init_cond(c);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_clockwait, cond, m, clock, abstime);
+ return cond_wait(
+ thr, pc, &si,
+ [=]() { return REAL(pthread_cond_clockwait)(cond, m, clock, abstime); },
+ cond, m);
+}
+#define TSAN_MAYBE_PTHREAD_COND_CLOCKWAIT TSAN_INTERCEPT(pthread_cond_clockwait)
+#else
+#define TSAN_MAYBE_PTHREAD_COND_CLOCKWAIT
+#endif
+
+#if SANITIZER_APPLE
+INTERCEPTOR(int, pthread_cond_timedwait_relative_np, void *c, void *m,
+ void *reltime) {
+ void *cond = init_cond(c);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait_relative_np, cond, m, reltime);
+ return cond_wait(
+ thr, pc, &si,
+ [=]() {
+ return REAL(pthread_cond_timedwait_relative_np)(cond, m, reltime);
+ },
+ cond, m);
+}
+#endif
+
+INTERCEPTOR(int, pthread_cond_signal, void *c) {
+ void *cond = init_cond(c);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, cond);
+ MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
+ return REAL(pthread_cond_signal)(cond);
+}
+
+INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
+ void *cond = init_cond(c);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast, cond);
+ MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
+ return REAL(pthread_cond_broadcast)(cond);
+}
+
+INTERCEPTOR(int, pthread_cond_destroy, void *c) {
+ void *cond = init_cond(c);
+ SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, cond);
+ MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), true);
+ int res = REAL(pthread_cond_destroy)(cond);
+ if (common_flags()->legacy_pthread_cond) {
+ // Free our aux cond and zero the pointer to not leave dangling pointers.
+ WRAP(free)(cond);
+ atomic_store((atomic_uintptr_t*)c, 0, memory_order_relaxed);
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_mutex_init, void *m, void *a) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_mutex_init, m, a);
+ int res = REAL(pthread_mutex_init)(m, a);
+ if (res == 0) {
+ u32 flagz = 0;
+ if (a) {
+ int type = 0;
+ if (REAL(pthread_mutexattr_gettype)(a, &type) == 0)
+ if (type == PTHREAD_MUTEX_RECURSIVE ||
+ type == PTHREAD_MUTEX_RECURSIVE_NP)
+ flagz |= MutexFlagWriteReentrant;
+ }
+ MutexCreate(thr, pc, (uptr)m, flagz);
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_mutex_destroy, m);
+ int res = REAL(pthread_mutex_destroy)(m);
+ if (res == 0 || res == errno_EBUSY) {
+ MutexDestroy(thr, pc, (uptr)m);
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_mutex_lock, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_mutex_lock, m);
+ MutexPreLock(thr, pc, (uptr)m);
+ int res = REAL(pthread_mutex_lock)(m);
+ if (res == errno_EOWNERDEAD)
+ MutexRepair(thr, pc, (uptr)m);
+ if (res == 0 || res == errno_EOWNERDEAD)
+ MutexPostLock(thr, pc, (uptr)m);
+ if (res == errno_EINVAL)
+ MutexInvalidAccess(thr, pc, (uptr)m);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_mutex_trylock, m);
+ int res = REAL(pthread_mutex_trylock)(m);
+ if (res == errno_EOWNERDEAD)
+ MutexRepair(thr, pc, (uptr)m);
+ if (res == 0 || res == errno_EOWNERDEAD)
+ MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
+ return res;
+}
+
+#if !SANITIZER_APPLE
+TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_mutex_timedlock, m, abstime);
+ int res = REAL(pthread_mutex_timedlock)(m, abstime);
+ if (res == 0) {
+ MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
+ }
+ return res;
+}
+#endif
+
+TSAN_INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_mutex_unlock, m);
+ MutexUnlock(thr, pc, (uptr)m);
+ int res = REAL(pthread_mutex_unlock)(m);
+ if (res == errno_EINVAL)
+ MutexInvalidAccess(thr, pc, (uptr)m);
+ return res;
+}
+
+#if SANITIZER_GLIBC
+# if !__GLIBC_PREREQ(2, 34)
+// glibc 2.34 applies a non-default version for the two functions. They are no
+// longer expected to be intercepted by programs.
+TSAN_INTERCEPTOR(int, __pthread_mutex_lock, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(__pthread_mutex_lock, m);
+ MutexPreLock(thr, pc, (uptr)m);
+ int res = REAL(__pthread_mutex_lock)(m);
+ if (res == errno_EOWNERDEAD)
+ MutexRepair(thr, pc, (uptr)m);
+ if (res == 0 || res == errno_EOWNERDEAD)
+ MutexPostLock(thr, pc, (uptr)m);
+ if (res == errno_EINVAL)
+ MutexInvalidAccess(thr, pc, (uptr)m);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, __pthread_mutex_unlock, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(__pthread_mutex_unlock, m);
+ MutexUnlock(thr, pc, (uptr)m);
+ int res = REAL(__pthread_mutex_unlock)(m);
+ if (res == errno_EINVAL)
+ MutexInvalidAccess(thr, pc, (uptr)m);
+ return res;
+}
+# endif
+#endif
+
+#if !SANITIZER_APPLE
+TSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared);
+ int res = REAL(pthread_spin_init)(m, pshared);
+ if (res == 0) {
+ MutexCreate(thr, pc, (uptr)m);
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_spin_destroy, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_spin_destroy, m);
+ int res = REAL(pthread_spin_destroy)(m);
+ if (res == 0) {
+ MutexDestroy(thr, pc, (uptr)m);
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_spin_lock, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_spin_lock, m);
+ MutexPreLock(thr, pc, (uptr)m);
+ int res = REAL(pthread_spin_lock)(m);
+ if (res == 0) {
+ MutexPostLock(thr, pc, (uptr)m);
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_spin_trylock, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_spin_trylock, m);
+ int res = REAL(pthread_spin_trylock)(m);
+ if (res == 0) {
+ MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_spin_unlock, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_spin_unlock, m);
+ MutexUnlock(thr, pc, (uptr)m);
+ int res = REAL(pthread_spin_unlock)(m);
+ return res;
+}
+#endif
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_init, void *m, void *a) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_init, m, a);
+ int res = REAL(pthread_rwlock_init)(m, a);
+ if (res == 0) {
+ MutexCreate(thr, pc, (uptr)m);
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_destroy, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_destroy, m);
+ int res = REAL(pthread_rwlock_destroy)(m);
+ if (res == 0) {
+ MutexDestroy(thr, pc, (uptr)m);
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_rdlock, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_rdlock, m);
+ MutexPreReadLock(thr, pc, (uptr)m);
+ int res = REAL(pthread_rwlock_rdlock)(m);
+ if (res == 0) {
+ MutexPostReadLock(thr, pc, (uptr)m);
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_tryrdlock, m);
+ int res = REAL(pthread_rwlock_tryrdlock)(m);
+ if (res == 0) {
+ MutexPostReadLock(thr, pc, (uptr)m, MutexFlagTryLock);
+ }
+ return res;
+}
+
+#if !SANITIZER_APPLE
+TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedrdlock, m, abstime);
+ int res = REAL(pthread_rwlock_timedrdlock)(m, abstime);
+ if (res == 0) {
+ MutexPostReadLock(thr, pc, (uptr)m);
+ }
+ return res;
+}
+#endif
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m);
+ MutexPreLock(thr, pc, (uptr)m);
+ int res = REAL(pthread_rwlock_wrlock)(m);
+ if (res == 0) {
+ MutexPostLock(thr, pc, (uptr)m);
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_trywrlock, m);
+ int res = REAL(pthread_rwlock_trywrlock)(m);
+ if (res == 0) {
+ MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
+ }
+ return res;
+}
+
+#if !SANITIZER_APPLE
+TSAN_INTERCEPTOR(int, pthread_rwlock_timedwrlock, void *m, void *abstime) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_timedwrlock, m, abstime);
+ int res = REAL(pthread_rwlock_timedwrlock)(m, abstime);
+ if (res == 0) {
+ MutexPostLock(thr, pc, (uptr)m, MutexFlagTryLock);
+ }
+ return res;
+}
+#endif
+
+TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_unlock, m);
+ MutexReadOrWriteUnlock(thr, pc, (uptr)m);
+ int res = REAL(pthread_rwlock_unlock)(m);
+ return res;
+}
+
+#if !SANITIZER_APPLE
+TSAN_INTERCEPTOR(int, pthread_barrier_init, void *b, void *a, unsigned count) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_barrier_init, b, a, count);
+ MemoryAccess(thr, pc, (uptr)b, 1, kAccessWrite);
+ int res = REAL(pthread_barrier_init)(b, a, count);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_barrier_destroy, void *b) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_barrier_destroy, b);
+ MemoryAccess(thr, pc, (uptr)b, 1, kAccessWrite);
+ int res = REAL(pthread_barrier_destroy)(b);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_barrier_wait, b);
+ Release(thr, pc, (uptr)b);
+ MemoryAccess(thr, pc, (uptr)b, 1, kAccessRead);
+ int res = REAL(pthread_barrier_wait)(b);
+ MemoryAccess(thr, pc, (uptr)b, 1, kAccessRead);
+ if (res == 0 || res == PTHREAD_BARRIER_SERIAL_THREAD) {
+ Acquire(thr, pc, (uptr)b);
+ }
+ return res;
+}
+#endif
+
+TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
+ SCOPED_INTERCEPTOR_RAW(pthread_once, o, f);
+ if (o == 0 || f == 0)
+ return errno_EINVAL;
+ atomic_uint32_t *a;
+
+ if (SANITIZER_APPLE)
+ a = static_cast<atomic_uint32_t*>((void *)((char *)o + sizeof(long_t)));
+ else if (SANITIZER_NETBSD)
+ a = static_cast<atomic_uint32_t*>
+ ((void *)((char *)o + __sanitizer::pthread_mutex_t_sz));
+ else
+ a = static_cast<atomic_uint32_t*>(o);
+
+ // Mac OS X appears to use pthread_once() where calling BlockingRegion hooks
+ // result in crashes due to too little stack space.
+ if (guard_acquire(thr, pc, a, !SANITIZER_APPLE)) {
+ (*f)();
+ guard_release(thr, pc, a, kGuardDone);
+ }
+ return 0;
+}
+
+#if SANITIZER_GLIBC
+TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) {
+ SCOPED_TSAN_INTERCEPTOR(__fxstat, version, fd, buf);
+ if (fd > 0)
+ FdAccess(thr, pc, fd);
+ return REAL(__fxstat)(version, fd, buf);
+}
+#define TSAN_MAYBE_INTERCEPT___FXSTAT TSAN_INTERCEPT(__fxstat)
+#else
+#define TSAN_MAYBE_INTERCEPT___FXSTAT
+#endif
+
+TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) {
+#if SANITIZER_GLIBC
+ SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf);
+ if (fd > 0)
+ FdAccess(thr, pc, fd);
+ return REAL(__fxstat)(0, fd, buf);
+#else
+ SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf);
+ if (fd > 0)
+ FdAccess(thr, pc, fd);
+ return REAL(fstat)(fd, buf);
+#endif
+}
+
+#if SANITIZER_GLIBC
+TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) {
+ SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf);
+ if (fd > 0)
+ FdAccess(thr, pc, fd);
+ return REAL(__fxstat64)(version, fd, buf);
+}
+#define TSAN_MAYBE_INTERCEPT___FXSTAT64 TSAN_INTERCEPT(__fxstat64)
+#else
+#define TSAN_MAYBE_INTERCEPT___FXSTAT64
+#endif
+
+#if SANITIZER_GLIBC
+TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
+ SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf);
+ if (fd > 0)
+ FdAccess(thr, pc, fd);
+ return REAL(__fxstat64)(0, fd, buf);
+}
+#define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64)
+#else
+#define TSAN_MAYBE_INTERCEPT_FSTAT64
+#endif
+
+TSAN_INTERCEPTOR(int, open, const char *name, int oflag, ...) {
+ va_list ap;
+ va_start(ap, oflag);
+ mode_t mode = va_arg(ap, int);
+ va_end(ap);
+ SCOPED_TSAN_INTERCEPTOR(open, name, oflag, mode);
+ READ_STRING(thr, pc, name, 0);
+ int fd = REAL(open)(name, oflag, mode);
+ if (fd >= 0)
+ FdFileCreate(thr, pc, fd);
+ return fd;
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, open64, const char *name, int oflag, ...) {
+ va_list ap;
+ va_start(ap, oflag);
+ mode_t mode = va_arg(ap, int);
+ va_end(ap);
+ SCOPED_TSAN_INTERCEPTOR(open64, name, oflag, mode);
+ READ_STRING(thr, pc, name, 0);
+ int fd = REAL(open64)(name, oflag, mode);
+ if (fd >= 0)
+ FdFileCreate(thr, pc, fd);
+ return fd;
+}
+#define TSAN_MAYBE_INTERCEPT_OPEN64 TSAN_INTERCEPT(open64)
+#else
+#define TSAN_MAYBE_INTERCEPT_OPEN64
+#endif
+
+TSAN_INTERCEPTOR(int, creat, const char *name, int mode) {
+ SCOPED_TSAN_INTERCEPTOR(creat, name, mode);
+ READ_STRING(thr, pc, name, 0);
+ int fd = REAL(creat)(name, mode);
+ if (fd >= 0)
+ FdFileCreate(thr, pc, fd);
+ return fd;
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, creat64, const char *name, int mode) {
+ SCOPED_TSAN_INTERCEPTOR(creat64, name, mode);
+ READ_STRING(thr, pc, name, 0);
+ int fd = REAL(creat64)(name, mode);
+ if (fd >= 0)
+ FdFileCreate(thr, pc, fd);
+ return fd;
+}
+#define TSAN_MAYBE_INTERCEPT_CREAT64 TSAN_INTERCEPT(creat64)
+#else
+#define TSAN_MAYBE_INTERCEPT_CREAT64
+#endif
+
+TSAN_INTERCEPTOR(int, dup, int oldfd) {
+ SCOPED_TSAN_INTERCEPTOR(dup, oldfd);
+ int newfd = REAL(dup)(oldfd);
+ if (oldfd >= 0 && newfd >= 0 && newfd != oldfd)
+ FdDup(thr, pc, oldfd, newfd, true);
+ return newfd;
+}
+
+TSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) {
+ SCOPED_TSAN_INTERCEPTOR(dup2, oldfd, newfd);
+ int newfd2 = REAL(dup2)(oldfd, newfd);
+ if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
+ FdDup(thr, pc, oldfd, newfd2, false);
+ return newfd2;
+}
+
+#if !SANITIZER_APPLE
+TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) {
+ SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags);
+ int newfd2 = REAL(dup3)(oldfd, newfd, flags);
+ if (oldfd >= 0 && newfd2 >= 0 && newfd2 != oldfd)
+ FdDup(thr, pc, oldfd, newfd2, false);
+ return newfd2;
+}
+#endif
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, eventfd, unsigned initval, int flags) {
+ SCOPED_TSAN_INTERCEPTOR(eventfd, initval, flags);
+ int fd = REAL(eventfd)(initval, flags);
+ if (fd >= 0)
+ FdEventCreate(thr, pc, fd);
+ return fd;
+}
+#define TSAN_MAYBE_INTERCEPT_EVENTFD TSAN_INTERCEPT(eventfd)
+#else
+#define TSAN_MAYBE_INTERCEPT_EVENTFD
+#endif
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, signalfd, int fd, void *mask, int flags) {
+ SCOPED_INTERCEPTOR_RAW(signalfd, fd, mask, flags);
+ FdClose(thr, pc, fd);
+ fd = REAL(signalfd)(fd, mask, flags);
+ if (!MustIgnoreInterceptor(thr))
+ FdSignalCreate(thr, pc, fd);
+ return fd;
+}
+#define TSAN_MAYBE_INTERCEPT_SIGNALFD TSAN_INTERCEPT(signalfd)
+#else
+#define TSAN_MAYBE_INTERCEPT_SIGNALFD
+#endif
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, inotify_init, int fake) {
+ SCOPED_TSAN_INTERCEPTOR(inotify_init, fake);
+ int fd = REAL(inotify_init)(fake);
+ if (fd >= 0)
+ FdInotifyCreate(thr, pc, fd);
+ return fd;
+}
+#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT TSAN_INTERCEPT(inotify_init)
+#else
+#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT
+#endif
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, inotify_init1, int flags) {
+ SCOPED_TSAN_INTERCEPTOR(inotify_init1, flags);
+ int fd = REAL(inotify_init1)(flags);
+ if (fd >= 0)
+ FdInotifyCreate(thr, pc, fd);
+ return fd;
+}
+#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1 TSAN_INTERCEPT(inotify_init1)
+#else
+#define TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1
+#endif
+
+TSAN_INTERCEPTOR(int, socket, int domain, int type, int protocol) {
+ SCOPED_TSAN_INTERCEPTOR(socket, domain, type, protocol);
+ int fd = REAL(socket)(domain, type, protocol);
+ if (fd >= 0)
+ FdSocketCreate(thr, pc, fd);
+ return fd;
+}
+
+TSAN_INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int *fd) {
+ SCOPED_TSAN_INTERCEPTOR(socketpair, domain, type, protocol, fd);
+ int res = REAL(socketpair)(domain, type, protocol, fd);
+ if (res == 0 && fd[0] >= 0 && fd[1] >= 0)
+ FdPipeCreate(thr, pc, fd[0], fd[1]);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, connect, int fd, void *addr, unsigned addrlen) {
+ SCOPED_TSAN_INTERCEPTOR(connect, fd, addr, addrlen);
+ FdSocketConnecting(thr, pc, fd);
+ int res = REAL(connect)(fd, addr, addrlen);
+ if (res == 0 && fd >= 0)
+ FdSocketConnect(thr, pc, fd);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, bind, int fd, void *addr, unsigned addrlen) {
+ SCOPED_TSAN_INTERCEPTOR(bind, fd, addr, addrlen);
+ int res = REAL(bind)(fd, addr, addrlen);
+ if (fd > 0 && res == 0)
+ FdAccess(thr, pc, fd);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, listen, int fd, int backlog) {
+ SCOPED_TSAN_INTERCEPTOR(listen, fd, backlog);
+ int res = REAL(listen)(fd, backlog);
+ if (fd > 0 && res == 0)
+ FdAccess(thr, pc, fd);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, close, int fd) {
+ SCOPED_INTERCEPTOR_RAW(close, fd);
+ if (!in_symbolizer())
+ FdClose(thr, pc, fd);
+ return REAL(close)(fd);
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, __close, int fd) {
+ SCOPED_INTERCEPTOR_RAW(__close, fd);
+ FdClose(thr, pc, fd);
+ return REAL(__close)(fd);
+}
+#define TSAN_MAYBE_INTERCEPT___CLOSE TSAN_INTERCEPT(__close)
+#else
+#define TSAN_MAYBE_INTERCEPT___CLOSE
+#endif
+
+// glibc guts
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) {
+ SCOPED_INTERCEPTOR_RAW(__res_iclose, state, free_addr);
+ int fds[64];
+ int cnt = ExtractResolvFDs(state, fds, ARRAY_SIZE(fds));
+ for (int i = 0; i < cnt; i++) FdClose(thr, pc, fds[i]);
+ REAL(__res_iclose)(state, free_addr);
+}
+#define TSAN_MAYBE_INTERCEPT___RES_ICLOSE TSAN_INTERCEPT(__res_iclose)
+#else
+#define TSAN_MAYBE_INTERCEPT___RES_ICLOSE
+#endif
+
+TSAN_INTERCEPTOR(int, pipe, int *pipefd) {
+ SCOPED_TSAN_INTERCEPTOR(pipe, pipefd);
+ int res = REAL(pipe)(pipefd);
+ if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
+ FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
+ return res;
+}
+
+#if !SANITIZER_APPLE
+TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) {
+ SCOPED_TSAN_INTERCEPTOR(pipe2, pipefd, flags);
+ int res = REAL(pipe2)(pipefd, flags);
+ if (res == 0 && pipefd[0] >= 0 && pipefd[1] >= 0)
+ FdPipeCreate(thr, pc, pipefd[0], pipefd[1]);
+ return res;
+}
+#endif
+
+TSAN_INTERCEPTOR(int, unlink, char *path) {
+ SCOPED_TSAN_INTERCEPTOR(unlink, path);
+ Release(thr, pc, File2addr(path));
+ int res = REAL(unlink)(path);
+ return res;
+}
+
+TSAN_INTERCEPTOR(void*, tmpfile, int fake) {
+ SCOPED_TSAN_INTERCEPTOR(tmpfile, fake);
+ void *res = REAL(tmpfile)(fake);
+ if (res) {
+ int fd = fileno_unlocked(res);
+ if (fd >= 0)
+ FdFileCreate(thr, pc, fd);
+ }
+ return res;
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(void*, tmpfile64, int fake) {
+ SCOPED_TSAN_INTERCEPTOR(tmpfile64, fake);
+ void *res = REAL(tmpfile64)(fake);
+ if (res) {
+ int fd = fileno_unlocked(res);
+ if (fd >= 0)
+ FdFileCreate(thr, pc, fd);
+ }
+ return res;
+}
+#define TSAN_MAYBE_INTERCEPT_TMPFILE64 TSAN_INTERCEPT(tmpfile64)
+#else
+#define TSAN_MAYBE_INTERCEPT_TMPFILE64
+#endif
+
+static void FlushStreams() {
+ // Flushing all the streams here may freeze the process if a child thread is
+ // performing file stream operations at the same time.
+ REAL(fflush)(stdout);
+ REAL(fflush)(stderr);
+}
+
+TSAN_INTERCEPTOR(void, abort, int fake) {
+ SCOPED_TSAN_INTERCEPTOR(abort, fake);
+ FlushStreams();
+ REAL(abort)(fake);
+}
+
+TSAN_INTERCEPTOR(int, rmdir, char *path) {
+ SCOPED_TSAN_INTERCEPTOR(rmdir, path);
+ Release(thr, pc, Dir2addr(path));
+ int res = REAL(rmdir)(path);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, closedir, void *dirp) {
+ SCOPED_INTERCEPTOR_RAW(closedir, dirp);
+ if (dirp) {
+ int fd = dirfd(dirp);
+ FdClose(thr, pc, fd);
+ }
+ return REAL(closedir)(dirp);
+}
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, epoll_create, int size) {
+ SCOPED_TSAN_INTERCEPTOR(epoll_create, size);
+ int fd = REAL(epoll_create)(size);
+ if (fd >= 0)
+ FdPollCreate(thr, pc, fd);
+ return fd;
+}
+
+TSAN_INTERCEPTOR(int, epoll_create1, int flags) {
+ SCOPED_TSAN_INTERCEPTOR(epoll_create1, flags);
+ int fd = REAL(epoll_create1)(flags);
+ if (fd >= 0)
+ FdPollCreate(thr, pc, fd);
+ return fd;
+}
+
+TSAN_INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, void *ev) {
+ SCOPED_TSAN_INTERCEPTOR(epoll_ctl, epfd, op, fd, ev);
+ if (epfd >= 0)
+ FdAccess(thr, pc, epfd);
+ if (epfd >= 0 && fd >= 0)
+ FdAccess(thr, pc, fd);
+ if (op == EPOLL_CTL_ADD && epfd >= 0) {
+ FdPollAdd(thr, pc, epfd, fd);
+ FdRelease(thr, pc, epfd);
+ }
+ int res = REAL(epoll_ctl)(epfd, op, fd, ev);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) {
+ SCOPED_TSAN_INTERCEPTOR(epoll_wait, epfd, ev, cnt, timeout);
+ if (epfd >= 0)
+ FdAccess(thr, pc, epfd);
+ int res = BLOCK_REAL(epoll_wait)(epfd, ev, cnt, timeout);
+ if (res > 0 && epfd >= 0)
+ FdAcquire(thr, pc, epfd);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, epoll_pwait, int epfd, void *ev, int cnt, int timeout,
+ void *sigmask) {
+ SCOPED_TSAN_INTERCEPTOR(epoll_pwait, epfd, ev, cnt, timeout, sigmask);
+ if (epfd >= 0)
+ FdAccess(thr, pc, epfd);
+ int res = BLOCK_REAL(epoll_pwait)(epfd, ev, cnt, timeout, sigmask);
+ if (res > 0 && epfd >= 0)
+ FdAcquire(thr, pc, epfd);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, epoll_pwait2, int epfd, void *ev, int cnt, void *timeout,
+ void *sigmask) {
+ SCOPED_INTERCEPTOR_RAW(epoll_pwait2, epfd, ev, cnt, timeout, sigmask);
+ // This function is new and may not be present in libc and/or kernel.
+ // Since we effectively add it to libc (as will be probed by the program
+ // using dlsym or a weak function pointer) we need to handle the case
+ // when it's not present in the actual libc.
+ if (!REAL(epoll_pwait2)) {
+ errno = errno_ENOSYS;
+ return -1;
+ }
+ if (MustIgnoreInterceptor(thr))
+ REAL(epoll_pwait2)(epfd, ev, cnt, timeout, sigmask);
+ if (epfd >= 0)
+ FdAccess(thr, pc, epfd);
+ int res = BLOCK_REAL(epoll_pwait2)(epfd, ev, cnt, timeout, sigmask);
+ if (res > 0 && epfd >= 0)
+ FdAcquire(thr, pc, epfd);
+ return res;
+}
+
+# define TSAN_MAYBE_INTERCEPT_EPOLL \
+ TSAN_INTERCEPT(epoll_create); \
+ TSAN_INTERCEPT(epoll_create1); \
+ TSAN_INTERCEPT(epoll_ctl); \
+ TSAN_INTERCEPT(epoll_wait); \
+ TSAN_INTERCEPT(epoll_pwait); \
+ TSAN_INTERCEPT(epoll_pwait2)
+#else
+#define TSAN_MAYBE_INTERCEPT_EPOLL
+#endif
+
+// The following functions are intercepted merely to process pending signals.
+// If program blocks signal X, we must deliver the signal before the function
+// returns. Similarly, if program unblocks a signal (or returns from sigsuspend)
+// it's better to deliver the signal straight away.
+TSAN_INTERCEPTOR(int, sigsuspend, const __sanitizer_sigset_t *mask) {
+ SCOPED_TSAN_INTERCEPTOR(sigsuspend, mask);
+ return REAL(sigsuspend)(mask);
+}
+
+TSAN_INTERCEPTOR(int, sigblock, int mask) {
+ SCOPED_TSAN_INTERCEPTOR(sigblock, mask);
+ return REAL(sigblock)(mask);
+}
+
+TSAN_INTERCEPTOR(int, sigsetmask, int mask) {
+ SCOPED_TSAN_INTERCEPTOR(sigsetmask, mask);
+ return REAL(sigsetmask)(mask);
+}
+
+TSAN_INTERCEPTOR(int, pthread_sigmask, int how, const __sanitizer_sigset_t *set,
+ __sanitizer_sigset_t *oldset) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_sigmask, how, set, oldset);
+ return REAL(pthread_sigmask)(how, set, oldset);
+}
+
+namespace __tsan {
+
+static void ReportErrnoSpoiling(ThreadState *thr, uptr pc, int sig) {
+ VarSizeStackTrace stack;
+ // StackTrace::GetNestInstructionPc(pc) is used because return address is
+ // expected, OutputReport() will undo this.
+ ObtainCurrentStack(thr, StackTrace::GetNextInstructionPc(pc), &stack);
+ ThreadRegistryLock l(&ctx->thread_registry);
+ ScopedReport rep(ReportTypeErrnoInSignal);
+ rep.SetSigNum(sig);
+ if (!IsFiredSuppression(ctx, ReportTypeErrnoInSignal, stack)) {
+ rep.AddStack(stack, true);
+ OutputReport(thr, rep);
+ }
+}
+
+static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
+ int sig, __sanitizer_siginfo *info,
+ void *uctx) {
+ CHECK(thr->slot);
+ __sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
+ if (acquire)
+ Acquire(thr, 0, (uptr)&sigactions[sig]);
+ // Signals are generally asynchronous, so if we receive a signals when
+ // ignores are enabled we should disable ignores. This is critical for sync
+ // and interceptors, because otherwise we can miss synchronization and report
+ // false races.
+ int ignore_reads_and_writes = thr->ignore_reads_and_writes;
+ int ignore_interceptors = thr->ignore_interceptors;
+ int ignore_sync = thr->ignore_sync;
+ // For symbolizer we only process SIGSEGVs synchronously
+ // (bug in symbolizer or in tsan). But we want to reset
+ // in_symbolizer to fail gracefully. Symbolizer and user code
+ // use different memory allocators, so if we don't reset
+ // in_symbolizer we can get memory allocated with one being
+ // feed with another, which can cause more crashes.
+ int in_symbolizer = thr->in_symbolizer;
+ if (!ctx->after_multithreaded_fork) {
+ thr->ignore_reads_and_writes = 0;
+ thr->fast_state.ClearIgnoreBit();
+ thr->ignore_interceptors = 0;
+ thr->ignore_sync = 0;
+ thr->in_symbolizer = 0;
+ }
+ // Ensure that the handler does not spoil errno.
+ const int saved_errno = errno;
+ errno = 99;
+ // This code races with sigaction. Be careful to not read sa_sigaction twice.
+ // Also need to remember pc for reporting before the call,
+ // because the handler can reset it.
+ volatile uptr pc = (sigactions[sig].sa_flags & SA_SIGINFO)
+ ? (uptr)sigactions[sig].sigaction
+ : (uptr)sigactions[sig].handler;
+ if (pc != sig_dfl && pc != sig_ign) {
+ // The callback can be either sa_handler or sa_sigaction.
+ // They have different signatures, but we assume that passing
+ // additional arguments to sa_handler works and is harmless.
+ ((__sanitizer_sigactionhandler_ptr)pc)(sig, info, uctx);
+ }
+ if (!ctx->after_multithreaded_fork) {
+ thr->ignore_reads_and_writes = ignore_reads_and_writes;
+ if (ignore_reads_and_writes)
+ thr->fast_state.SetIgnoreBit();
+ thr->ignore_interceptors = ignore_interceptors;
+ thr->ignore_sync = ignore_sync;
+ thr->in_symbolizer = in_symbolizer;
+ }
+ // We do not detect errno spoiling for SIGTERM,
+ // because some SIGTERM handlers do spoil errno but reraise SIGTERM,
+ // tsan reports false positive in such case.
+ // It's difficult to properly detect this situation (reraise),
+ // because in async signal processing case (when handler is called directly
+ // from rtl_generic_sighandler) we have not yet received the reraised
+ // signal; and it looks too fragile to intercept all ways to reraise a signal.
+ if (ShouldReport(thr, ReportTypeErrnoInSignal) && !sync && sig != SIGTERM &&
+ errno != 99)
+ ReportErrnoSpoiling(thr, pc, sig);
+ errno = saved_errno;
+}
+
+void ProcessPendingSignalsImpl(ThreadState *thr) {
+ atomic_store(&thr->pending_signals, 0, memory_order_relaxed);
+ ThreadSignalContext *sctx = SigCtx(thr);
+ if (sctx == 0)
+ return;
+ atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
+ internal_sigfillset(&sctx->emptyset);
+ int res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->emptyset, &sctx->oldset);
+ CHECK_EQ(res, 0);
+ for (int sig = 0; sig < kSigCount; sig++) {
+ SignalDesc *signal = &sctx->pending_signals[sig];
+ if (signal->armed) {
+ signal->armed = false;
+ CallUserSignalHandler(thr, false, true, sig, &signal->siginfo,
+ &signal->ctx);
+ }
+ }
+ res = REAL(pthread_sigmask)(SIG_SETMASK, &sctx->oldset, 0);
+ CHECK_EQ(res, 0);
+ atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
+}
+
+} // namespace __tsan
+
+static bool is_sync_signal(ThreadSignalContext *sctx, int sig,
+ __sanitizer_siginfo *info) {
+ // If we are sending signal to ourselves, we must process it now.
+ if (sctx && sig == sctx->int_signal_send)
+ return true;
+#if SANITIZER_HAS_SIGINFO
+ // POSIX timers can be configured to send any kind of signal; however, it
+ // doesn't make any sense to consider a timer signal as synchronous!
+ if (info->si_code == SI_TIMER)
+ return false;
+#endif
+ return sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || sig == SIGTRAP ||
+ sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS;
+}
+
+void sighandler(int sig, __sanitizer_siginfo *info, void *ctx) {
+ ThreadState *thr = cur_thread_init();
+ ThreadSignalContext *sctx = SigCtx(thr);
+ if (sig < 0 || sig >= kSigCount) {
+ VPrintf(1, "ThreadSanitizer: ignoring signal %d\n", sig);
+ return;
+ }
+ // Don't mess with synchronous signals.
+ const bool sync = is_sync_signal(sctx, sig, info);
+ if (sync ||
+ // If we are in blocking function, we can safely process it now
+ // (but check if we are in a recursive interceptor,
+ // i.e. pthread_join()->munmap()).
+ atomic_load(&thr->in_blocking_func, memory_order_relaxed)) {
+ atomic_fetch_add(&thr->in_signal_handler, 1, memory_order_relaxed);
+ if (atomic_load(&thr->in_blocking_func, memory_order_relaxed)) {
+ atomic_store(&thr->in_blocking_func, 0, memory_order_relaxed);
+ CallUserSignalHandler(thr, sync, true, sig, info, ctx);
+ atomic_store(&thr->in_blocking_func, 1, memory_order_relaxed);
+ } else {
+ // Be very conservative with when we do acquire in this case.
+ // It's unsafe to do acquire in async handlers, because ThreadState
+ // can be in inconsistent state.
+ // SIGSYS looks relatively safe -- it's synchronous and can actually
+ // need some global state.
+ bool acq = (sig == SIGSYS);
+ CallUserSignalHandler(thr, sync, acq, sig, info, ctx);
+ }
+ atomic_fetch_add(&thr->in_signal_handler, -1, memory_order_relaxed);
+ return;
+ }
+
+ if (sctx == 0)
+ return;
+ SignalDesc *signal = &sctx->pending_signals[sig];
+ if (signal->armed == false) {
+ signal->armed = true;
+ internal_memcpy(&signal->siginfo, info, sizeof(*info));
+ internal_memcpy(&signal->ctx, ctx, sizeof(signal->ctx));
+ atomic_store(&thr->pending_signals, 1, memory_order_relaxed);
+ }
+}
+
+TSAN_INTERCEPTOR(int, raise, int sig) {
+ SCOPED_TSAN_INTERCEPTOR(raise, sig);
+ ThreadSignalContext *sctx = SigCtx(thr);
+ CHECK_NE(sctx, 0);
+ int prev = sctx->int_signal_send;
+ sctx->int_signal_send = sig;
+ int res = REAL(raise)(sig);
+ CHECK_EQ(sctx->int_signal_send, sig);
+ sctx->int_signal_send = prev;
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, kill, int pid, int sig) {
+ SCOPED_TSAN_INTERCEPTOR(kill, pid, sig);
+ ThreadSignalContext *sctx = SigCtx(thr);
+ CHECK_NE(sctx, 0);
+ int prev = sctx->int_signal_send;
+ if (pid == (int)internal_getpid()) {
+ sctx->int_signal_send = sig;
+ }
+ int res = REAL(kill)(pid, sig);
+ if (pid == (int)internal_getpid()) {
+ CHECK_EQ(sctx->int_signal_send, sig);
+ sctx->int_signal_send = prev;
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_kill, void *tid, int sig) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_kill, tid, sig);
+ ThreadSignalContext *sctx = SigCtx(thr);
+ CHECK_NE(sctx, 0);
+ int prev = sctx->int_signal_send;
+ bool self = pthread_equal(tid, pthread_self());
+ if (self)
+ sctx->int_signal_send = sig;
+ int res = REAL(pthread_kill)(tid, sig);
+ if (self) {
+ CHECK_EQ(sctx->int_signal_send, sig);
+ sctx->int_signal_send = prev;
+ }
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
+ SCOPED_TSAN_INTERCEPTOR(gettimeofday, tv, tz);
+ // It's intercepted merely to process pending signals.
+ return REAL(gettimeofday)(tv, tz);
+}
+
+TSAN_INTERCEPTOR(int, getaddrinfo, void *node, void *service,
+ void *hints, void *rv) {
+ SCOPED_TSAN_INTERCEPTOR(getaddrinfo, node, service, hints, rv);
+ // We miss atomic synchronization in getaddrinfo,
+ // and can report false race between malloc and free
+ // inside of getaddrinfo. So ignore memory accesses.
+ ThreadIgnoreBegin(thr, pc);
+ int res = REAL(getaddrinfo)(node, service, hints, rv);
+ ThreadIgnoreEnd(thr);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, fork, int fake) {
+ if (in_symbolizer())
+ return REAL(fork)(fake);
+ SCOPED_INTERCEPTOR_RAW(fork, fake);
+ return REAL(fork)(fake);
+}
+
+void atfork_prepare() {
+ if (in_symbolizer())
+ return;
+ ThreadState *thr = cur_thread();
+ const uptr pc = StackTrace::GetCurrentPc();
+ ForkBefore(thr, pc);
+}
+
+void atfork_parent() {
+ if (in_symbolizer())
+ return;
+ ThreadState *thr = cur_thread();
+ const uptr pc = StackTrace::GetCurrentPc();
+ ForkParentAfter(thr, pc);
+}
+
+void atfork_child() {
+ if (in_symbolizer())
+ return;
+ ThreadState *thr = cur_thread();
+ const uptr pc = StackTrace::GetCurrentPc();
+ ForkChildAfter(thr, pc, true);
+ FdOnFork(thr, pc);
+}
+
+#if !SANITIZER_IOS
+TSAN_INTERCEPTOR(int, vfork, int fake) {
+ // Some programs (e.g. openjdk) call close for all file descriptors
+ // in the child process. Under tsan it leads to false positives, because
+ // address space is shared, so the parent process also thinks that
+ // the descriptors are closed (while they are actually not).
+ // This leads to false positives due to missed synchronization.
+ // Strictly saying this is undefined behavior, because vfork child is not
+ // allowed to call any functions other than exec/exit. But this is what
+ // openjdk does, so we want to handle it.
+ // We could disable interceptors in the child process. But it's not possible
+ // to simply intercept and wrap vfork, because vfork child is not allowed
+ // to return from the function that calls vfork, and that's exactly what
+ // we would do. So this would require some assembly trickery as well.
+ // Instead we simply turn vfork into fork.
+ return WRAP(fork)(fake);
+}
+#endif
+
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, clone, int (*fn)(void *), void *stack, int flags,
+ void *arg, int *parent_tid, void *tls, pid_t *child_tid) {
+ SCOPED_INTERCEPTOR_RAW(clone, fn, stack, flags, arg, parent_tid, tls,
+ child_tid);
+ struct Arg {
+ int (*fn)(void *);
+ void *arg;
+ };
+ auto wrapper = +[](void *p) -> int {
+ auto *thr = cur_thread();
+ uptr pc = GET_CURRENT_PC();
+ // Start the background thread for fork, but not for clone.
+ // For fork we did this always and it's known to work (or user code has
+ // adopted). But if we do this for the new clone interceptor some code
+ // (sandbox2) fails. So model we used to do for years and don't start the
+ // background thread after clone.
+ ForkChildAfter(thr, pc, false);
+ FdOnFork(thr, pc);
+ auto *arg = static_cast<Arg *>(p);
+ return arg->fn(arg->arg);
+ };
+ ForkBefore(thr, pc);
+ Arg arg_wrapper = {fn, arg};
+ int pid = REAL(clone)(wrapper, stack, flags, &arg_wrapper, parent_tid, tls,
+ child_tid);
+ ForkParentAfter(thr, pc);
+ return pid;
+}
+#endif
+
+#if !SANITIZER_APPLE && !SANITIZER_ANDROID
+typedef int (*dl_iterate_phdr_cb_t)(__sanitizer_dl_phdr_info *info, SIZE_T size,
+ void *data);
+struct dl_iterate_phdr_data {
+ ThreadState *thr;
+ uptr pc;
+ dl_iterate_phdr_cb_t cb;
+ void *data;
+};
+
+static bool IsAppNotRodata(uptr addr) {
+ return IsAppMem(addr) && *MemToShadow(addr) != Shadow::kRodata;
+}
+
+static int dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
+ void *data) {
+ dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
+ // dlopen/dlclose allocate/free dynamic-linker-internal memory, which is later
+ // accessible in dl_iterate_phdr callback. But we don't see synchronization
+ // inside of dynamic linker, so we "unpoison" it here in order to not
+ // produce false reports. Ignoring malloc/free in dlopen/dlclose is not enough
+ // because some libc functions call __libc_dlopen.
+ if (info && IsAppNotRodata((uptr)info->dlpi_name))
+ MemoryResetRange(cbdata->thr, cbdata->pc, (uptr)info->dlpi_name,
+ internal_strlen(info->dlpi_name));
+ int res = cbdata->cb(info, size, cbdata->data);
+ // Perform the check one more time in case info->dlpi_name was overwritten
+ // by user callback.
+ if (info && IsAppNotRodata((uptr)info->dlpi_name))
+ MemoryResetRange(cbdata->thr, cbdata->pc, (uptr)info->dlpi_name,
+ internal_strlen(info->dlpi_name));
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb_t cb, void *data) {
+ SCOPED_TSAN_INTERCEPTOR(dl_iterate_phdr, cb, data);
+ dl_iterate_phdr_data cbdata;
+ cbdata.thr = thr;
+ cbdata.pc = pc;
+ cbdata.cb = cb;
+ cbdata.data = data;
+ int res = REAL(dl_iterate_phdr)(dl_iterate_phdr_cb, &cbdata);
+ return res;
+}
+#endif
+
+static int OnExit(ThreadState *thr) {
+ int status = Finalize(thr);
+ FlushStreams();
+ return status;
+}
+
+struct TsanInterceptorContext {
+ ThreadState *thr;
+ const uptr pc;
+};
+
+#if !SANITIZER_APPLE
+static void HandleRecvmsg(ThreadState *thr, uptr pc,
+ __sanitizer_msghdr *msg) {
+ int fds[64];
+ int cnt = ExtractRecvmsgFDs(msg, fds, ARRAY_SIZE(fds));
+ for (int i = 0; i < cnt; i++)
+ FdEventCreate(thr, pc, fds[i]);
+}
+#endif
+
+#include "sanitizer_common/sanitizer_platform_interceptors.h"
+// Causes interceptor recursion (getaddrinfo() and fopen())
+#undef SANITIZER_INTERCEPT_GETADDRINFO
+// We define our own.
+#if SANITIZER_INTERCEPT_TLS_GET_ADDR
+#define NEED_TLS_GET_ADDR
+#endif
+#undef SANITIZER_INTERCEPT_TLS_GET_ADDR
+#define SANITIZER_INTERCEPT_TLS_GET_OFFSET 1
+#undef SANITIZER_INTERCEPT_PTHREAD_SIGMASK
+
+#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
+#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
+ INTERCEPT_FUNCTION_VER(name, ver)
+#define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
+ (INTERCEPT_FUNCTION_VER(name, ver) || INTERCEPT_FUNCTION(name))
+
+#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
+ MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \
+ ((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \
+ true)
+
+#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
+ MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \
+ ((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \
+ false)
+
+#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
+ SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__); \
+ TsanInterceptorContext _ctx = {thr, pc}; \
+ ctx = (void *)&_ctx; \
+ (void)ctx;
+
+#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, func, ...) \
+ SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \
+ TsanInterceptorContext _ctx = {thr, pc}; \
+ ctx = (void *)&_ctx; \
+ (void)ctx;
+
+#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) \
+ if (path) \
+ Acquire(thr, pc, File2addr(path)); \
+ if (file) { \
+ int fd = fileno_unlocked(file); \
+ if (fd >= 0) FdFileCreate(thr, pc, fd); \
+ }
+
+#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) \
+ if (file) { \
+ int fd = fileno_unlocked(file); \
+ FdClose(thr, pc, fd); \
+ }
+
+#define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \
+ ({ \
+ CheckNoDeepBind(filename, flag); \
+ ThreadIgnoreBegin(thr, 0); \
+ void *res = REAL(dlopen)(filename, flag); \
+ ThreadIgnoreEnd(thr); \
+ res; \
+ })
+
+#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
+ libignore()->OnLibraryLoaded(filename)
+
+#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() \
+ libignore()->OnLibraryUnloaded()
+
+#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) \
+ Acquire(((TsanInterceptorContext *) ctx)->thr, pc, u)
+
+#define COMMON_INTERCEPTOR_RELEASE(ctx, u) \
+ Release(((TsanInterceptorContext *) ctx)->thr, pc, u)
+
+#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
+ Acquire(((TsanInterceptorContext *) ctx)->thr, pc, Dir2addr(path))
+
+#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
+ FdAcquire(((TsanInterceptorContext *) ctx)->thr, pc, fd)
+
+#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
+ FdRelease(((TsanInterceptorContext *) ctx)->thr, pc, fd)
+
+#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) \
+ FdAccess(((TsanInterceptorContext *) ctx)->thr, pc, fd)
+
+#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
+ FdSocketAccept(((TsanInterceptorContext *) ctx)->thr, pc, fd, newfd)
+
+#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
+ ThreadSetName(((TsanInterceptorContext *) ctx)->thr, name)
+
+#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
+ if (pthread_equal(pthread_self(), reinterpret_cast<void *>(thread))) \
+ COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name); \
+ else \
+ __tsan::ctx->thread_registry.SetThreadNameByUserId(thread, name)
+
+#define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name)
+
+#define COMMON_INTERCEPTOR_ON_EXIT(ctx) \
+ OnExit(((TsanInterceptorContext *) ctx)->thr)
+
+#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, \
+ off) \
+ do { \
+ return mmap_interceptor(thr, pc, REAL(mmap), addr, sz, prot, flags, fd, \
+ off); \
+ } while (false)
+
+#if !SANITIZER_APPLE
+#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \
+ HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \
+ ((TsanInterceptorContext *)ctx)->pc, msg)
+#endif
+
+#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
+ if (TsanThread *t = GetCurrentThread()) { \
+ *begin = t->tls_begin(); \
+ *end = t->tls_end(); \
+ } else { \
+ *begin = *end = 0; \
+ }
+
+#define COMMON_INTERCEPTOR_USER_CALLBACK_START() \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START()
+
+#define COMMON_INTERCEPTOR_USER_CALLBACK_END() \
+ SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END()
+
+#include "sanitizer_common/sanitizer_common_interceptors.inc"
+
+static int sigaction_impl(int sig, const __sanitizer_sigaction *act,
+ __sanitizer_sigaction *old);
+static __sanitizer_sighandler_ptr signal_impl(int sig,
+ __sanitizer_sighandler_ptr h);
+
+#define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signo, act, oldact) \
+ { return sigaction_impl(signo, act, oldact); }
+
+#define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
+ { return (uptr)signal_impl(signo, (__sanitizer_sighandler_ptr)handler); }
+
+#include "sanitizer_common/sanitizer_signal_interceptors.inc"
+
+int sigaction_impl(int sig, const __sanitizer_sigaction *act,
+ __sanitizer_sigaction *old) {
+ // Note: if we call REAL(sigaction) directly for any reason without proxying
+ // the signal handler through sighandler, very bad things will happen.
+ // The handler will run synchronously and corrupt tsan per-thread state.
+ SCOPED_INTERCEPTOR_RAW(sigaction, sig, act, old);
+ if (sig <= 0 || sig >= kSigCount) {
+ errno = errno_EINVAL;
+ return -1;
+ }
+ __sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
+ __sanitizer_sigaction old_stored;
+ if (old) internal_memcpy(&old_stored, &sigactions[sig], sizeof(old_stored));
+ __sanitizer_sigaction newact;
+ if (act) {
+ // Copy act into sigactions[sig].
+ // Can't use struct copy, because compiler can emit call to memcpy.
+ // Can't use internal_memcpy, because it copies byte-by-byte,
+ // and signal handler reads the handler concurrently. It it can read
+ // some bytes from old value and some bytes from new value.
+ // Use volatile to prevent insertion of memcpy.
+ sigactions[sig].handler =
+ *(volatile __sanitizer_sighandler_ptr const *)&act->handler;
+ sigactions[sig].sa_flags = *(volatile int const *)&act->sa_flags;
+ internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask,
+ sizeof(sigactions[sig].sa_mask));
+#if !SANITIZER_FREEBSD && !SANITIZER_APPLE && !SANITIZER_NETBSD
+ sigactions[sig].sa_restorer = act->sa_restorer;
+#endif
+ internal_memcpy(&newact, act, sizeof(newact));
+ internal_sigfillset(&newact.sa_mask);
+ if ((act->sa_flags & SA_SIGINFO) ||
+ ((uptr)act->handler != sig_ign && (uptr)act->handler != sig_dfl)) {
+ newact.sa_flags |= SA_SIGINFO;
+ newact.sigaction = sighandler;
+ }
+ ReleaseStore(thr, pc, (uptr)&sigactions[sig]);
+ act = &newact;
+ }
+ int res = REAL(sigaction)(sig, act, old);
+ if (res == 0 && old && old->sigaction == sighandler)
+ internal_memcpy(old, &old_stored, sizeof(*old));
+ return res;
+}
+
+static __sanitizer_sighandler_ptr signal_impl(int sig,
+ __sanitizer_sighandler_ptr h) {
+ __sanitizer_sigaction act;
+ act.handler = h;
+ internal_memset(&act.sa_mask, -1, sizeof(act.sa_mask));
+ act.sa_flags = 0;
+ __sanitizer_sigaction old;
+ int res = sigaction_symname(sig, &act, &old);
+ if (res) return (__sanitizer_sighandler_ptr)sig_err;
+ return old.handler;
+}
+
+#define TSAN_SYSCALL() \
+ ThreadState *thr = cur_thread(); \
+ if (thr->ignore_interceptors) \
+ return; \
+ ScopedSyscall scoped_syscall(thr)
+
+struct ScopedSyscall {
+ ThreadState *thr;
+
+ explicit ScopedSyscall(ThreadState *thr) : thr(thr) { LazyInitialize(thr); }
+
+ ~ScopedSyscall() {
+ ProcessPendingSignals(thr);
+ }
+};
+
+#if !SANITIZER_FREEBSD && !SANITIZER_APPLE
+static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) {
+ TSAN_SYSCALL();
+ MemoryAccessRange(thr, pc, p, s, write);
+}
+
+static USED void syscall_acquire(uptr pc, uptr addr) {
+ TSAN_SYSCALL();
+ Acquire(thr, pc, addr);
+ DPrintf("syscall_acquire(0x%zx))\n", addr);
+}
+
+static USED void syscall_release(uptr pc, uptr addr) {
+ TSAN_SYSCALL();
+ DPrintf("syscall_release(0x%zx)\n", addr);
+ Release(thr, pc, addr);
+}
+
+static void syscall_fd_close(uptr pc, int fd) {
+ auto *thr = cur_thread();
+ FdClose(thr, pc, fd);
+}
+
+static USED void syscall_fd_acquire(uptr pc, int fd) {
+ TSAN_SYSCALL();
+ FdAcquire(thr, pc, fd);
+ DPrintf("syscall_fd_acquire(%d)\n", fd);
+}
+
+static USED void syscall_fd_release(uptr pc, int fd) {
+ TSAN_SYSCALL();
+ DPrintf("syscall_fd_release(%d)\n", fd);
+ FdRelease(thr, pc, fd);
+}
+
+static void syscall_pre_fork(uptr pc) { ForkBefore(cur_thread(), pc); }
+
+static void syscall_post_fork(uptr pc, int pid) {
+ ThreadState *thr = cur_thread();
+ if (pid == 0) {
+ // child
+ ForkChildAfter(thr, pc, true);
+ FdOnFork(thr, pc);
+ } else if (pid > 0) {
+ // parent
+ ForkParentAfter(thr, pc);
+ } else {
+ // error
+ ForkParentAfter(thr, pc);
+ }
+}
+#endif
+
+#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) \
+ syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), false)
+
+#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
+ syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), true)
+
+#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
+ do { \
+ (void)(p); \
+ (void)(s); \
+ } while (false)
+
+#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
+ do { \
+ (void)(p); \
+ (void)(s); \
+ } while (false)
+
+#define COMMON_SYSCALL_ACQUIRE(addr) \
+ syscall_acquire(GET_CALLER_PC(), (uptr)(addr))
+
+#define COMMON_SYSCALL_RELEASE(addr) \
+ syscall_release(GET_CALLER_PC(), (uptr)(addr))
+
+#define COMMON_SYSCALL_FD_CLOSE(fd) syscall_fd_close(GET_CALLER_PC(), fd)
+
+#define COMMON_SYSCALL_FD_ACQUIRE(fd) syscall_fd_acquire(GET_CALLER_PC(), fd)
+
+#define COMMON_SYSCALL_FD_RELEASE(fd) syscall_fd_release(GET_CALLER_PC(), fd)
+
+#define COMMON_SYSCALL_PRE_FORK() \
+ syscall_pre_fork(GET_CALLER_PC())
+
+#define COMMON_SYSCALL_POST_FORK(res) \
+ syscall_post_fork(GET_CALLER_PC(), res)
+
+#include "sanitizer_common/sanitizer_common_syscalls.inc"
+#include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
+
+#ifdef NEED_TLS_GET_ADDR
+
+static void handle_tls_addr(void *arg, void *res) {
+ ThreadState *thr = cur_thread();
+ if (!thr)
+ return;
+ DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr,
+ thr->tls_addr + thr->tls_size);
+ if (!dtv)
+ return;
+ // New DTLS block has been allocated.
+ MemoryResetRange(thr, 0, dtv->beg, dtv->size);
+}
+
+#if !SANITIZER_S390
+// Define own interceptor instead of sanitizer_common's for three reasons:
+// 1. It must not process pending signals.
+// Signal handlers may contain MOVDQA instruction (see below).
+// 2. It must be as simple as possible to not contain MOVDQA.
+// 3. Sanitizer_common version uses COMMON_INTERCEPTOR_INITIALIZE_RANGE which
+// is empty for tsan (meant only for msan).
+// Note: __tls_get_addr can be called with mis-aligned stack due to:
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
+// So the interceptor must work with mis-aligned stack, in particular, does not
+// execute MOVDQA with stack addresses.
+TSAN_INTERCEPTOR(void *, __tls_get_addr, void *arg) {
+ void *res = REAL(__tls_get_addr)(arg);
+ handle_tls_addr(arg, res);
+ return res;
+}
+#else // SANITIZER_S390
+TSAN_INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
+ uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset));
+ char *tp = static_cast<char *>(__builtin_thread_pointer());
+ handle_tls_addr(arg, res + tp);
+ return res;
+}
+#endif
+#endif
+
+#if SANITIZER_NETBSD
+TSAN_INTERCEPTOR(void, _lwp_exit) {
+ SCOPED_TSAN_INTERCEPTOR(_lwp_exit);
+ DestroyThreadState();
+ REAL(_lwp_exit)();
+}
+#define TSAN_MAYBE_INTERCEPT__LWP_EXIT TSAN_INTERCEPT(_lwp_exit)
+#else
+#define TSAN_MAYBE_INTERCEPT__LWP_EXIT
+#endif
+
+#if SANITIZER_FREEBSD
+TSAN_INTERCEPTOR(void, thr_exit, tid_t *state) {
+ SCOPED_TSAN_INTERCEPTOR(thr_exit, state);
+ DestroyThreadState();
+ REAL(thr_exit(state));
+}
+#define TSAN_MAYBE_INTERCEPT_THR_EXIT TSAN_INTERCEPT(thr_exit)
+#else
+#define TSAN_MAYBE_INTERCEPT_THR_EXIT
+#endif
+
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, cond_init, void *c, void *a)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, cond_destroy, void *c)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, cond_signal, void *c)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, cond_broadcast, void *c)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, cond_wait, void *c, void *m)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, mutex_init, void *m, void *a)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, mutex_destroy, void *m)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, mutex_lock, void *m)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, mutex_trylock, void *m)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, mutex_unlock, void *m)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_init, void *l, void *a)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_destroy, void *l)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_rdlock, void *l)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_tryrdlock, void *l)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_wrlock, void *l)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_trywrlock, void *l)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, rwlock_unlock, void *l)
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, once, void *o, void (*i)())
+TSAN_INTERCEPTOR_FREEBSD_ALIAS(int, sigmask, int f, void *n, void *o)
+
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_init, void *c, void *a)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_signal, void *c)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_broadcast, void *c)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_wait, void *c, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_destroy, void *c)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_init, void *m, void *a)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_destroy, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_lock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_trylock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_unlock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_init, void *m, void *a)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_destroy, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_rdlock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_tryrdlock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_wrlock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_trywrlock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_unlock, void *m)
+TSAN_INTERCEPTOR_NETBSD_ALIAS_THR(int, once, void *o, void (*f)())
+TSAN_INTERCEPTOR_NETBSD_ALIAS_THR2(int, sigsetmask, sigmask, int a, void *b,
+ void *c)
+
+namespace __tsan {
+
+static void finalize(void *arg) {
+ ThreadState *thr = cur_thread();
+ int status = Finalize(thr);
+ // Make sure the output is not lost.
+ FlushStreams();
+ if (status)
+ Die();
+}
+
+#if !SANITIZER_APPLE && !SANITIZER_ANDROID
+static void unreachable() {
+ Report("FATAL: ThreadSanitizer: unreachable called\n");
+ Die();
+}
+#endif
+
+// Define default implementation since interception of libdispatch is optional.
+SANITIZER_WEAK_ATTRIBUTE void InitializeLibdispatchInterceptors() {}
+
+void InitializeInterceptors() {
+#if !SANITIZER_APPLE
+ // We need to setup it early, because functions like dlsym() can call it.
+ REAL(memset) = internal_memset;
+ REAL(memcpy) = internal_memcpy;
+#endif
+
+ new(interceptor_ctx()) InterceptorContext();
+
+ InitializeCommonInterceptors();
+ InitializeSignalInterceptors();
+ InitializeLibdispatchInterceptors();
+
+#if !SANITIZER_APPLE
+ // We can not use TSAN_INTERCEPT to get setjmp addr,
+ // because it does &setjmp and setjmp is not present in some versions of libc.
+ using __interception::InterceptFunction;
+ InterceptFunction(TSAN_STRING_SETJMP, (uptr*)&REAL(setjmp_symname), 0, 0);
+ InterceptFunction("_setjmp", (uptr*)&REAL(_setjmp), 0, 0);
+ InterceptFunction(TSAN_STRING_SIGSETJMP, (uptr*)&REAL(sigsetjmp_symname), 0,
+ 0);
+#if !SANITIZER_NETBSD
+ InterceptFunction("__sigsetjmp", (uptr*)&REAL(__sigsetjmp), 0, 0);
+#endif
+#endif
+
+ TSAN_INTERCEPT(longjmp_symname);
+ TSAN_INTERCEPT(siglongjmp_symname);
+#if SANITIZER_NETBSD
+ TSAN_INTERCEPT(_longjmp);
+#endif
+
+ TSAN_INTERCEPT(malloc);
+ TSAN_INTERCEPT(__libc_memalign);
+ TSAN_INTERCEPT(calloc);
+ TSAN_INTERCEPT(realloc);
+ TSAN_INTERCEPT(reallocarray);
+ TSAN_INTERCEPT(free);
+ TSAN_INTERCEPT(cfree);
+ TSAN_INTERCEPT(munmap);
+ TSAN_MAYBE_INTERCEPT_MEMALIGN;
+ TSAN_INTERCEPT(valloc);
+ TSAN_MAYBE_INTERCEPT_PVALLOC;
+ TSAN_INTERCEPT(posix_memalign);
+
+ TSAN_INTERCEPT(strcpy);
+ TSAN_INTERCEPT(strncpy);
+ TSAN_INTERCEPT(strdup);
+
+ TSAN_INTERCEPT(pthread_create);
+ TSAN_INTERCEPT(pthread_join);
+ TSAN_INTERCEPT(pthread_detach);
+ TSAN_INTERCEPT(pthread_exit);
+ #if SANITIZER_LINUX
+ TSAN_INTERCEPT(pthread_tryjoin_np);
+ TSAN_INTERCEPT(pthread_timedjoin_np);
+ #endif
+
+ TSAN_INTERCEPT_VER(pthread_cond_init, PTHREAD_ABI_BASE);
+ TSAN_INTERCEPT_VER(pthread_cond_signal, PTHREAD_ABI_BASE);
+ TSAN_INTERCEPT_VER(pthread_cond_broadcast, PTHREAD_ABI_BASE);
+ TSAN_INTERCEPT_VER(pthread_cond_wait, PTHREAD_ABI_BASE);
+ TSAN_INTERCEPT_VER(pthread_cond_timedwait, PTHREAD_ABI_BASE);
+ TSAN_INTERCEPT_VER(pthread_cond_destroy, PTHREAD_ABI_BASE);
+
+ TSAN_MAYBE_PTHREAD_COND_CLOCKWAIT;
+
+ TSAN_INTERCEPT(pthread_mutex_init);
+ TSAN_INTERCEPT(pthread_mutex_destroy);
+ TSAN_INTERCEPT(pthread_mutex_lock);
+ TSAN_INTERCEPT(pthread_mutex_trylock);
+ TSAN_INTERCEPT(pthread_mutex_timedlock);
+ TSAN_INTERCEPT(pthread_mutex_unlock);
+#if SANITIZER_GLIBC
+# if !__GLIBC_PREREQ(2, 34)
+ TSAN_INTERCEPT(__pthread_mutex_lock);
+ TSAN_INTERCEPT(__pthread_mutex_unlock);
+# endif
+#endif
+
+ TSAN_INTERCEPT(pthread_spin_init);
+ TSAN_INTERCEPT(pthread_spin_destroy);
+ TSAN_INTERCEPT(pthread_spin_lock);
+ TSAN_INTERCEPT(pthread_spin_trylock);
+ TSAN_INTERCEPT(pthread_spin_unlock);
+
+ TSAN_INTERCEPT(pthread_rwlock_init);
+ TSAN_INTERCEPT(pthread_rwlock_destroy);
+ TSAN_INTERCEPT(pthread_rwlock_rdlock);
+ TSAN_INTERCEPT(pthread_rwlock_tryrdlock);
+ TSAN_INTERCEPT(pthread_rwlock_timedrdlock);
+ TSAN_INTERCEPT(pthread_rwlock_wrlock);
+ TSAN_INTERCEPT(pthread_rwlock_trywrlock);
+ TSAN_INTERCEPT(pthread_rwlock_timedwrlock);
+ TSAN_INTERCEPT(pthread_rwlock_unlock);
+
+ TSAN_INTERCEPT(pthread_barrier_init);
+ TSAN_INTERCEPT(pthread_barrier_destroy);
+ TSAN_INTERCEPT(pthread_barrier_wait);
+
+ TSAN_INTERCEPT(pthread_once);
+
+ TSAN_INTERCEPT(fstat);
+ TSAN_MAYBE_INTERCEPT___FXSTAT;
+ TSAN_MAYBE_INTERCEPT_FSTAT64;
+ TSAN_MAYBE_INTERCEPT___FXSTAT64;
+ TSAN_INTERCEPT(open);
+ TSAN_MAYBE_INTERCEPT_OPEN64;
+ TSAN_INTERCEPT(creat);
+ TSAN_MAYBE_INTERCEPT_CREAT64;
+ TSAN_INTERCEPT(dup);
+ TSAN_INTERCEPT(dup2);
+ TSAN_INTERCEPT(dup3);
+ TSAN_MAYBE_INTERCEPT_EVENTFD;
+ TSAN_MAYBE_INTERCEPT_SIGNALFD;
+ TSAN_MAYBE_INTERCEPT_INOTIFY_INIT;
+ TSAN_MAYBE_INTERCEPT_INOTIFY_INIT1;
+ TSAN_INTERCEPT(socket);
+ TSAN_INTERCEPT(socketpair);
+ TSAN_INTERCEPT(connect);
+ TSAN_INTERCEPT(bind);
+ TSAN_INTERCEPT(listen);
+ TSAN_MAYBE_INTERCEPT_EPOLL;
+ TSAN_INTERCEPT(close);
+ TSAN_MAYBE_INTERCEPT___CLOSE;
+ TSAN_MAYBE_INTERCEPT___RES_ICLOSE;
+ TSAN_INTERCEPT(pipe);
+ TSAN_INTERCEPT(pipe2);
+
+ TSAN_INTERCEPT(unlink);
+ TSAN_INTERCEPT(tmpfile);
+ TSAN_MAYBE_INTERCEPT_TMPFILE64;
+ TSAN_INTERCEPT(abort);
+ TSAN_INTERCEPT(rmdir);
+ TSAN_INTERCEPT(closedir);
+
+ TSAN_INTERCEPT(sigsuspend);
+ TSAN_INTERCEPT(sigblock);
+ TSAN_INTERCEPT(sigsetmask);
+ TSAN_INTERCEPT(pthread_sigmask);
+ TSAN_INTERCEPT(raise);
+ TSAN_INTERCEPT(kill);
+ TSAN_INTERCEPT(pthread_kill);
+ TSAN_INTERCEPT(sleep);
+ TSAN_INTERCEPT(usleep);
+ TSAN_INTERCEPT(nanosleep);
+ TSAN_INTERCEPT(pause);
+ TSAN_INTERCEPT(gettimeofday);
+ TSAN_INTERCEPT(getaddrinfo);
+
+ TSAN_INTERCEPT(fork);
+ TSAN_INTERCEPT(vfork);
+#if SANITIZER_LINUX
+ TSAN_INTERCEPT(clone);
+#endif
+#if !SANITIZER_ANDROID
+ TSAN_INTERCEPT(dl_iterate_phdr);
+#endif
+ TSAN_MAYBE_INTERCEPT_ON_EXIT;
+ TSAN_INTERCEPT(__cxa_atexit);
+ TSAN_INTERCEPT(_exit);
+
+#ifdef NEED_TLS_GET_ADDR
+#if !SANITIZER_S390
+ TSAN_INTERCEPT(__tls_get_addr);
+#else
+ TSAN_INTERCEPT(__tls_get_addr_internal);
+ TSAN_INTERCEPT(__tls_get_offset);
+#endif
+#endif
+
+ TSAN_MAYBE_INTERCEPT__LWP_EXIT;
+ TSAN_MAYBE_INTERCEPT_THR_EXIT;
+
+#if !SANITIZER_APPLE && !SANITIZER_ANDROID
+ // Need to setup it, because interceptors check that the function is resolved.
+ // But atexit is emitted directly into the module, so can't be resolved.
+ REAL(atexit) = (int(*)(void(*)()))unreachable;
+#endif
+
+ if (REAL(__cxa_atexit)(&finalize, 0, 0)) {
+ Printf("ThreadSanitizer: failed to setup atexit callback\n");
+ Die();
+ }
+ if (pthread_atfork(atfork_prepare, atfork_parent, atfork_child)) {
+ Printf("ThreadSanitizer: failed to setup atfork callbacks\n");
+ Die();
+ }
+
+#if !SANITIZER_APPLE && !SANITIZER_NETBSD && !SANITIZER_FREEBSD
+ if (pthread_key_create(&interceptor_ctx()->finalize_key, &thread_finalize)) {
+ Printf("ThreadSanitizer: failed to create thread key\n");
+ Die();
+ }
+#endif
+
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(cond_init);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(cond_destroy);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(cond_signal);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(cond_broadcast);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(cond_wait);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(mutex_init);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(mutex_destroy);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(mutex_lock);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(mutex_trylock);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(mutex_unlock);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_init);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_destroy);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_rdlock);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_tryrdlock);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_wrlock);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_trywrlock);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(rwlock_unlock);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(once);
+ TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(sigmask);
+
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_init);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_signal);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_broadcast);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_wait);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_destroy);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_init);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_destroy);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_lock);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_trylock);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_unlock);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_init);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_destroy);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_rdlock);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_tryrdlock);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_wrlock);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_trywrlock);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_unlock);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(once);
+ TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS_THR(sigsetmask);
+
+ FdInit();
+}
+
+} // namespace __tsan
+
+// Invisible barrier for tests.
+// There were several unsuccessful iterations for this functionality:
+// 1. Initially it was implemented in user code using
+// REAL(pthread_barrier_wait). But pthread_barrier_wait is not supported on
+// MacOS. Futexes are linux-specific for this matter.
+// 2. Then we switched to atomics+usleep(10). But usleep produced parasitic
+// "as-if synchronized via sleep" messages in reports which failed some
+// output tests.
+// 3. Then we switched to atomics+sched_yield. But this produced tons of tsan-
+// visible events, which lead to "failed to restore stack trace" failures.
+// Note that no_sanitize_thread attribute does not turn off atomic interception
+// so attaching it to the function defined in user code does not help.
+// That's why we now have what we have.
+constexpr u32 kBarrierThreadBits = 10;
+constexpr u32 kBarrierThreads = 1 << kBarrierThreadBits;
+
+extern "C" {
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_testonly_barrier_init(
+ atomic_uint32_t *barrier, u32 num_threads) {
+ if (num_threads >= kBarrierThreads) {
+ Printf("barrier_init: count is too large (%d)\n", num_threads);
+ Die();
+ }
+ // kBarrierThreadBits lsb is thread count,
+ // the remaining are count of entered threads.
+ atomic_store(barrier, num_threads, memory_order_relaxed);
+}
+
+static u32 barrier_epoch(u32 value) {
+ return (value >> kBarrierThreadBits) / (value & (kBarrierThreads - 1));
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_testonly_barrier_wait(
+ atomic_uint32_t *barrier) {
+ u32 old = atomic_fetch_add(barrier, kBarrierThreads, memory_order_relaxed);
+ u32 old_epoch = barrier_epoch(old);
+ if (barrier_epoch(old + kBarrierThreads) != old_epoch) {
+ FutexWake(barrier, (1 << 30));
+ return;
+ }
+ for (;;) {
+ u32 cur = atomic_load(barrier, memory_order_relaxed);
+ if (barrier_epoch(cur) != old_epoch)
+ return;
+ FutexWait(barrier, cur);
+ }
+}
+
+void *__tsan_memcpy(void *dst, const void *src, uptr size) {
+ void *ctx;
+#if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE
+ COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size);
+#else
+ COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
+#endif
+}
+
+void *__tsan_memset(void *dst, int c, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, c, size);
+}
+
+void *__tsan_memmove(void *dst, const void *src, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
+}
+}
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface.cpp
new file mode 100644
index 00000000000..e6c4bf2e60a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface.cpp
@@ -0,0 +1,92 @@
+//===-- tsan_interface.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "tsan_interface.h"
+#include "tsan_interface_ann.h"
+#include "tsan_rtl.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_ptrauth.h"
+
+#define CALLERPC ((uptr)__builtin_return_address(0))
+
+using namespace __tsan;
+
+void __tsan_init() { Initialize(cur_thread_init()); }
+
+void __tsan_flush_memory() {
+ FlushShadowMemory();
+}
+
+void __tsan_read16_pc(void *addr, void *pc) {
+ uptr pc_no_pac = STRIP_PAC_PC(pc);
+ ThreadState *thr = cur_thread();
+ MemoryAccess(thr, pc_no_pac, (uptr)addr, 8, kAccessRead);
+ MemoryAccess(thr, pc_no_pac, (uptr)addr + 8, 8, kAccessRead);
+}
+
+void __tsan_write16_pc(void *addr, void *pc) {
+ uptr pc_no_pac = STRIP_PAC_PC(pc);
+ ThreadState *thr = cur_thread();
+ MemoryAccess(thr, pc_no_pac, (uptr)addr, 8, kAccessWrite);
+ MemoryAccess(thr, pc_no_pac, (uptr)addr + 8, 8, kAccessWrite);
+}
+
+// __tsan_unaligned_read/write calls are emitted by compiler.
+
+void __tsan_unaligned_read16(const void *addr) {
+ uptr pc = CALLERPC;
+ ThreadState *thr = cur_thread();
+ UnalignedMemoryAccess(thr, pc, (uptr)addr, 8, kAccessRead);
+ UnalignedMemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessRead);
+}
+
+void __tsan_unaligned_write16(void *addr) {
+ uptr pc = CALLERPC;
+ ThreadState *thr = cur_thread();
+ UnalignedMemoryAccess(thr, pc, (uptr)addr, 8, kAccessWrite);
+ UnalignedMemoryAccess(thr, pc, (uptr)addr + 8, 8, kAccessWrite);
+}
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__tsan_get_current_fiber() {
+ return cur_thread();
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__tsan_create_fiber(unsigned flags) {
+ return FiberCreate(cur_thread(), CALLERPC, flags);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_destroy_fiber(void *fiber) {
+ FiberDestroy(cur_thread(), CALLERPC, static_cast<ThreadState *>(fiber));
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_switch_to_fiber(void *fiber, unsigned flags) {
+ FiberSwitch(cur_thread(), CALLERPC, static_cast<ThreadState *>(fiber), flags);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_set_fiber_name(void *fiber, const char *name) {
+ ThreadSetName(static_cast<ThreadState *>(fiber), name);
+}
+} // extern "C"
+
+void __tsan_acquire(void *addr) {
+ Acquire(cur_thread(), CALLERPC, (uptr)addr);
+}
+
+void __tsan_release(void *addr) {
+ Release(cur_thread(), CALLERPC, (uptr)addr);
+}
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface.h
new file mode 100644
index 00000000000..5b9d664e503
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface.h
@@ -0,0 +1,431 @@
+//===-- tsan_interface.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// The functions declared in this header will be inserted by the instrumentation
+// module.
+// This header can be included by the instrumented program or by TSan tests.
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_INTERFACE_H
+#define TSAN_INTERFACE_H
+
+#include <sanitizer_common/sanitizer_internal_defs.h>
+using __sanitizer::uptr;
+using __sanitizer::tid_t;
+
+// This header should NOT include any other headers.
+// All functions in this header are extern "C" and start with __tsan_.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !SANITIZER_GO
+
+// This function should be called at the very beginning of the process,
+// before any instrumented code is executed and before any call to malloc.
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_init();
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_flush_memory();
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read1(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read2(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read4(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read8(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read16(void *addr);
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write1(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write2(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write4(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write8(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write16(void *addr);
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_read2(const void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_read4(const void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_read8(const void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_read16(const void *addr);
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_write2(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_write4(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_write8(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_write16(void *addr);
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read1_pc(void *addr, void *pc);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read2_pc(void *addr, void *pc);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read4_pc(void *addr, void *pc);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read8_pc(void *addr, void *pc);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read16_pc(void *addr, void *pc);
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write1_pc(void *addr, void *pc);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write2_pc(void *addr, void *pc);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write4_pc(void *addr, void *pc);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write8_pc(void *addr, void *pc);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write16_pc(void *addr, void *pc);
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_vptr_read(void **vptr_p);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_vptr_update(void **vptr_p, void *new_val);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__tsan_memcpy(void *dest, const void *src, uptr count);
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__tsan_memset(void *dest, int ch, uptr count);
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__tsan_memmove(void *dest, const void *src, uptr count);
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_entry(void *call_pc);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_exit();
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_ignore_thread_begin();
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_ignore_thread_end();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__tsan_external_register_tag(const char *object_type);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_external_register_header(void *tag, const char *header);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_external_assign_tag(void *addr, void *tag);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_external_read(void *addr, void *caller_pc, void *tag);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_external_write(void *addr, void *caller_pc, void *tag);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_read_range(void *addr, unsigned long size);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_write_range(void *addr, unsigned long size);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_read_range_pc(void *addr, unsigned long size, void *pc);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_write_range_pc(void *addr, unsigned long size, void *pc);
+
+// User may provide function that would be called right when TSan detects
+// an error. The argument 'report' is an opaque pointer that can be used to
+// gather additional information using other TSan report API functions.
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_on_report(void *report);
+
+// If TSan is currently reporting a detected issue on the current thread,
+// returns an opaque pointer to the current report. Otherwise returns NULL.
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__tsan_get_current_report();
+
+// Returns a report's description (issue type), number of duplicate issues
+// found, counts of array data (stack traces, memory operations, locations,
+// mutexes, threads, unique thread IDs) and a stack trace of a sleep() call (if
+// one was involved in the issue).
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_data(void *report, const char **description, int *count,
+ int *stack_count, int *mop_count, int *loc_count,
+ int *mutex_count, int *thread_count,
+ int *unique_tid_count, void **sleep_trace,
+ uptr trace_size);
+
+/// Retrieves the "tag" from a report (for external-race report types). External
+/// races can be associated with a tag which give them more meaning. For example
+/// tag value '1' means "Swift access race". Tag value '0' indicated a plain
+/// external race.
+///
+/// \param report opaque pointer to the current report (obtained as argument in
+/// __tsan_on_report, or from __tsan_get_current_report)
+/// \param [out] tag points to storage that will be filled with the tag value
+///
+/// \returns non-zero value on success, zero on failure
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_tag(void *report, uptr *tag);
+
+// Returns information about stack traces included in the report.
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_stack(void *report, uptr idx, void **trace,
+ uptr trace_size);
+
+// Returns information about memory operations included in the report.
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_mop(void *report, uptr idx, int *tid, void **addr,
+ int *size, int *write, int *atomic, void **trace,
+ uptr trace_size);
+
+// Returns information about locations included in the report.
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_loc(void *report, uptr idx, const char **type,
+ void **addr, uptr *start, uptr *size, int *tid,
+ int *fd, int *suppressable, void **trace,
+ uptr trace_size);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_loc_object_type(void *report, uptr idx,
+ const char **object_type);
+
+// Returns information about mutexes included in the report.
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr,
+ int *destroyed, void **trace, uptr trace_size);
+
+// Returns information about threads included in the report.
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_thread(void *report, uptr idx, int *tid, tid_t *os_id,
+ int *running, const char **name, int *parent_tid,
+ void **trace, uptr trace_size);
+
+// Returns information about unique thread IDs included in the report.
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_report_unique_tid(void *report, uptr idx, int *tid);
+
+// Returns the type of the pointer (heap, stack, global, ...) and if possible
+// also the starting address (e.g. of a heap allocation) and size.
+SANITIZER_INTERFACE_ATTRIBUTE
+const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,
+ uptr *region_address, uptr *region_size);
+
+// Returns the allocation stack for a heap pointer.
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,
+ tid_t *os_id);
+
+#endif // SANITIZER_GO
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+namespace __tsan {
+
+// These should match declarations from public tsan_interface_atomic.h header.
+typedef unsigned char a8;
+typedef unsigned short a16;
+typedef unsigned int a32;
+typedef unsigned long long a64;
+#if !SANITIZER_GO && (defined(__SIZEOF_INT128__) \
+ || (__clang_major__ * 100 + __clang_minor__ >= 302)) && \
+ !defined(__mips64) && !defined(__s390x__)
+__extension__ typedef __int128 a128;
+# define __TSAN_HAS_INT128 1
+#else
+# define __TSAN_HAS_INT128 0
+#endif
+
+// Part of ABI, do not change.
+// https://github.com/llvm/llvm-project/blob/main/libcxx/include/atomic
+typedef enum {
+ mo_relaxed,
+ mo_consume,
+ mo_acquire,
+ mo_release,
+ mo_acq_rel,
+ mo_seq_cst
+} morder;
+
+struct ThreadState;
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_load(const volatile a8 *a, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_load(const volatile a16 *a, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_load(const volatile a32 *a, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_load(const volatile a64 *a, morder mo);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_load(const volatile a128 *a, morder mo);
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic8_store(volatile a8 *a, a8 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic16_store(volatile a16 *a, a16 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic32_store(volatile a32 *a, a32 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic64_store(volatile a64 *a, a64 v, morder mo);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic128_store(volatile a128 *a, a128 v, morder mo);
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, morder mo);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, morder mo);
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, morder mo);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, morder mo);
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, morder mo);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, morder mo);
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, morder mo);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, morder mo);
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, morder mo);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, morder mo);
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, morder mo);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, morder mo);
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, morder mo);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, morder mo);
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v,
+ morder mo, morder fmo);
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,
+ morder mo, morder fmo);
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,
+ morder mo, morder fmo);
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,
+ morder mo, morder fmo);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,
+ morder mo, morder fmo);
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v, morder mo,
+ morder fmo);
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,
+ morder mo, morder fmo);
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,
+ morder mo, morder fmo);
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
+ morder mo, morder fmo);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,
+ morder mo, morder fmo);
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v, morder mo,
+ morder fmo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,
+ morder mo, morder fmo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,
+ morder mo, morder fmo);
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,
+ morder mo, morder fmo);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
+ morder mo, morder fmo);
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic_thread_fence(morder mo);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic_signal_fence(morder mo);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic32_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic64_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic32_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic64_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic32_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic64_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic32_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic64_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic32_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
+ u8 *a);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic64_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
+ u8 *a);
+
+} // extern "C"
+
+} // namespace __tsan
+
+#endif // TSAN_INTERFACE_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface.inc b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface.inc
new file mode 100644
index 00000000000..b0a424ff9c2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface.inc
@@ -0,0 +1,190 @@
+//===-- tsan_interface.inc --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_ptrauth.h"
+#include "tsan_interface.h"
+#include "tsan_rtl.h"
+
+#define CALLERPC ((uptr)__builtin_return_address(0))
+
+using namespace __tsan;
+
+void __tsan_read1(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 1, kAccessRead);
+}
+
+void __tsan_read2(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessRead);
+}
+
+void __tsan_read4(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessRead);
+}
+
+void __tsan_read8(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessRead);
+}
+
+void __tsan_read16(void *addr) {
+ MemoryAccess16(cur_thread(), CALLERPC, (uptr)addr, kAccessRead);
+}
+
+void __tsan_write1(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 1, kAccessWrite);
+}
+
+void __tsan_write2(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessWrite);
+}
+
+void __tsan_write4(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessWrite);
+}
+
+void __tsan_write8(void *addr) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessWrite);
+}
+
+void __tsan_write16(void *addr) {
+ MemoryAccess16(cur_thread(), CALLERPC, (uptr)addr, kAccessWrite);
+}
+
+void __tsan_read1_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 1, kAccessRead | kAccessExternalPC);
+}
+
+void __tsan_read2_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 2, kAccessRead | kAccessExternalPC);
+}
+
+void __tsan_read4_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 4, kAccessRead | kAccessExternalPC);
+}
+
+void __tsan_read8_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 8, kAccessRead | kAccessExternalPC);
+}
+
+void __tsan_write1_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 1, kAccessWrite | kAccessExternalPC);
+}
+
+void __tsan_write2_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 2, kAccessWrite | kAccessExternalPC);
+}
+
+void __tsan_write4_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 4, kAccessWrite | kAccessExternalPC);
+}
+
+void __tsan_write8_pc(void *addr, void *pc) {
+ MemoryAccess(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, 8, kAccessWrite | kAccessExternalPC);
+}
+
+ALWAYS_INLINE USED void __tsan_unaligned_read2(const void *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessRead);
+}
+
+ALWAYS_INLINE USED void __tsan_unaligned_read4(const void *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessRead);
+}
+
+ALWAYS_INLINE USED void __tsan_unaligned_read8(const void *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessRead);
+}
+
+ALWAYS_INLINE USED void __tsan_unaligned_write2(void *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, kAccessWrite);
+}
+
+ALWAYS_INLINE USED void __tsan_unaligned_write4(void *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, kAccessWrite);
+}
+
+ALWAYS_INLINE USED void __tsan_unaligned_write8(void *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, kAccessWrite);
+}
+
+extern "C" {
+// __sanitizer_unaligned_load/store are for user instrumentation.
+SANITIZER_INTERFACE_ATTRIBUTE
+u16 __sanitizer_unaligned_load16(const uu16 *addr) {
+ __tsan_unaligned_read2(addr);
+ return *addr;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+u32 __sanitizer_unaligned_load32(const uu32 *addr) {
+ __tsan_unaligned_read4(addr);
+ return *addr;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+u64 __sanitizer_unaligned_load64(const uu64 *addr) {
+ __tsan_unaligned_read8(addr);
+ return *addr;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store16(uu16 *addr, u16 v) {
+ *addr = v;
+ __tsan_unaligned_write2(addr);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store32(uu32 *addr, u32 v) {
+ *addr = v;
+ __tsan_unaligned_write4(addr);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store64(uu64 *addr, u64 v) {
+ *addr = v;
+ __tsan_unaligned_write8(addr);
+}
+}
+
+void __tsan_vptr_update(void **vptr_p, void *new_val) {
+ if (*vptr_p == new_val)
+ return;
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)vptr_p, sizeof(*vptr_p),
+ kAccessWrite | kAccessVptr);
+}
+
+void __tsan_vptr_read(void **vptr_p) {
+ MemoryAccess(cur_thread(), CALLERPC, (uptr)vptr_p, sizeof(*vptr_p),
+ kAccessRead | kAccessVptr);
+}
+
+void __tsan_func_entry(void *pc) { FuncEntry(cur_thread(), STRIP_PAC_PC(pc)); }
+
+void __tsan_func_exit() { FuncExit(cur_thread()); }
+
+void __tsan_ignore_thread_begin() { ThreadIgnoreBegin(cur_thread(), CALLERPC); }
+
+void __tsan_ignore_thread_end() { ThreadIgnoreEnd(cur_thread()); }
+
+void __tsan_read_range(void *addr, uptr size) {
+ MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, false);
+}
+
+void __tsan_write_range(void *addr, uptr size) {
+ MemoryAccessRange(cur_thread(), CALLERPC, (uptr)addr, size, true);
+}
+
+void __tsan_read_range_pc(void *addr, uptr size, void *pc) {
+ MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, false);
+}
+
+void __tsan_write_range_pc(void *addr, uptr size, void *pc) {
+ MemoryAccessRange(cur_thread(), STRIP_PAC_PC(pc), (uptr)addr, size, true);
+}
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_ann.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_ann.cpp
new file mode 100644
index 00000000000..6bd72e18d94
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_ann.cpp
@@ -0,0 +1,438 @@
+//===-- tsan_interface_ann.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_vector.h"
+#include "tsan_interface_ann.h"
+#include "tsan_report.h"
+#include "tsan_rtl.h"
+#include "tsan_mman.h"
+#include "tsan_flags.h"
+#include "tsan_platform.h"
+
+#define CALLERPC ((uptr)__builtin_return_address(0))
+
+using namespace __tsan;
+
+namespace __tsan {
+
+class ScopedAnnotation {
+ public:
+ ScopedAnnotation(ThreadState *thr, const char *aname, uptr pc)
+ : thr_(thr) {
+ FuncEntry(thr_, pc);
+ DPrintf("#%d: annotation %s()\n", thr_->tid, aname);
+ }
+
+ ~ScopedAnnotation() {
+ FuncExit(thr_);
+ CheckedMutex::CheckNoLocks();
+ }
+ private:
+ ThreadState *const thr_;
+};
+
+#define SCOPED_ANNOTATION_RET(typ, ret) \
+ if (!flags()->enable_annotations) \
+ return ret; \
+ ThreadState *thr = cur_thread(); \
+ const uptr caller_pc = (uptr)__builtin_return_address(0); \
+ ScopedAnnotation sa(thr, __func__, caller_pc); \
+ const uptr pc = StackTrace::GetCurrentPc(); \
+ (void)pc;
+
+#define SCOPED_ANNOTATION(typ) SCOPED_ANNOTATION_RET(typ, )
+
+static const int kMaxDescLen = 128;
+
+struct ExpectRace {
+ ExpectRace *next;
+ ExpectRace *prev;
+ atomic_uintptr_t hitcount;
+ atomic_uintptr_t addcount;
+ uptr addr;
+ uptr size;
+ char *file;
+ int line;
+ char desc[kMaxDescLen];
+};
+
+struct DynamicAnnContext {
+ Mutex mtx;
+ ExpectRace benign;
+
+ DynamicAnnContext() : mtx(MutexTypeAnnotations) {}
+};
+
+static DynamicAnnContext *dyn_ann_ctx;
+static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64);
+
+static void AddExpectRace(ExpectRace *list,
+ char *f, int l, uptr addr, uptr size, char *desc) {
+ ExpectRace *race = list->next;
+ for (; race != list; race = race->next) {
+ if (race->addr == addr && race->size == size) {
+ atomic_store_relaxed(&race->addcount,
+ atomic_load_relaxed(&race->addcount) + 1);
+ return;
+ }
+ }
+ race = static_cast<ExpectRace *>(Alloc(sizeof(ExpectRace)));
+ race->addr = addr;
+ race->size = size;
+ race->file = f;
+ race->line = l;
+ race->desc[0] = 0;
+ atomic_store_relaxed(&race->hitcount, 0);
+ atomic_store_relaxed(&race->addcount, 1);
+ if (desc) {
+ int i = 0;
+ for (; i < kMaxDescLen - 1 && desc[i]; i++)
+ race->desc[i] = desc[i];
+ race->desc[i] = 0;
+ }
+ race->prev = list;
+ race->next = list->next;
+ race->next->prev = race;
+ list->next = race;
+}
+
+static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
+ for (ExpectRace *race = list->next; race != list; race = race->next) {
+ uptr maxbegin = max(race->addr, addr);
+ uptr minend = min(race->addr + race->size, addr + size);
+ if (maxbegin < minend)
+ return race;
+ }
+ return 0;
+}
+
+static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
+ ExpectRace *race = FindRace(list, addr, size);
+ if (race == 0)
+ return false;
+ DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
+ race->desc, race->addr, (int)race->size, race->file, race->line);
+ atomic_fetch_add(&race->hitcount, 1, memory_order_relaxed);
+ return true;
+}
+
+static void InitList(ExpectRace *list) {
+ list->next = list;
+ list->prev = list;
+}
+
+void InitializeDynamicAnnotations() {
+ dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
+ InitList(&dyn_ann_ctx->benign);
+}
+
+bool IsExpectedReport(uptr addr, uptr size) {
+ ReadLock lock(&dyn_ann_ctx->mtx);
+ return CheckContains(&dyn_ann_ctx->benign, addr, size);
+}
+} // namespace __tsan
+
+using namespace __tsan;
+
+extern "C" {
+void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
+ SCOPED_ANNOTATION(AnnotateHappensBefore);
+ Release(thr, pc, addr);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
+ SCOPED_ANNOTATION(AnnotateHappensAfter);
+ Acquire(thr, pc, addr);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
+ uptr lock) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
+ SCOPED_ANNOTATION(AnnotateRWLockCreate);
+ MutexCreate(thr, pc, m, MutexFlagWriteReentrant);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
+ SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
+ MutexCreate(thr, pc, m, MutexFlagWriteReentrant | MutexFlagLinkerInit);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {
+ SCOPED_ANNOTATION(AnnotateRWLockDestroy);
+ MutexDestroy(thr, pc, m);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,
+ uptr is_w) {
+ SCOPED_ANNOTATION(AnnotateRWLockAcquired);
+ if (is_w)
+ MutexPostLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
+ else
+ MutexPostReadLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
+ uptr is_w) {
+ SCOPED_ANNOTATION(AnnotateRWLockReleased);
+ if (is_w)
+ MutexUnlock(thr, pc, m);
+ else
+ MutexReadUnlock(thr, pc, m);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
+ uptr size) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
+ char *f, int l, int enable) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
+ char *f, int l, uptr mu) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotatePCQGet(
+ char *f, int l, uptr pcq) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotatePCQPut(
+ char *f, int l, uptr pcq) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
+ char *f, int l, uptr pcq) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
+ char *f, int l, uptr pcq) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotateExpectRace(
+ char *f, int l, uptr mem, char *desc) {
+}
+
+static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {
+ Lock lock(&dyn_ann_ctx->mtx);
+ AddExpectRace(&dyn_ann_ctx->benign,
+ f, l, mem, size, desc);
+ DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
+ char *f, int l, uptr mem, uptr size, char *desc) {
+ SCOPED_ANNOTATION(AnnotateBenignRaceSized);
+ BenignRaceImpl(f, l, mem, size, desc);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateBenignRace(
+ char *f, int l, uptr mem, char *desc) {
+ SCOPED_ANNOTATION(AnnotateBenignRace);
+ BenignRaceImpl(f, l, mem, 1, desc);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
+ SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
+ ThreadIgnoreBegin(thr, pc);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
+ SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
+ ThreadIgnoreEnd(thr);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
+ SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
+ ThreadIgnoreBegin(thr, pc);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
+ SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
+ ThreadIgnoreEnd(thr);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
+ SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin);
+ ThreadIgnoreSyncBegin(thr, pc);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
+ SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
+ ThreadIgnoreSyncEnd(thr);
+}
+
+void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
+ char *f, int l, uptr addr, uptr size) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
+ char *f, int l, uptr addr, uptr size) {
+}
+
+void INTERFACE_ATTRIBUTE AnnotateThreadName(
+ char *f, int l, char *name) {
+ SCOPED_ANNOTATION(AnnotateThreadName);
+ ThreadSetName(thr, name);
+}
+
+// We deliberately omit the implementation of WTFAnnotateHappensBefore() and
+// WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
+// atomic operations, which should be handled by ThreadSanitizer correctly.
+void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
+}
+
+void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
+}
+
+void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
+ char *f, int l, uptr mem, uptr sz, char *desc) {
+ SCOPED_ANNOTATION(AnnotateBenignRaceSized);
+ BenignRaceImpl(f, l, mem, sz, desc);
+}
+
+int INTERFACE_ATTRIBUTE RunningOnValgrind() {
+ return flags()->running_on_valgrind;
+}
+
+double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
+ return 10.0;
+}
+
+const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
+ if (internal_strcmp(query, "pure_happens_before") == 0)
+ return "1";
+ else
+ return "0";
+}
+
+void INTERFACE_ATTRIBUTE
+AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}
+void INTERFACE_ATTRIBUTE
+AnnotateMemoryIsUninitialized(char *f, int l, uptr mem, uptr sz) {}
+
+// Note: the parameter is called flagz, because flags is already taken
+// by the global function that returns flags.
+INTERFACE_ATTRIBUTE
+void __tsan_mutex_create(void *m, unsigned flagz) {
+ SCOPED_ANNOTATION(__tsan_mutex_create);
+ MutexCreate(thr, pc, (uptr)m, flagz & MutexCreationFlagMask);
+}
+
+INTERFACE_ATTRIBUTE
+void __tsan_mutex_destroy(void *m, unsigned flagz) {
+ SCOPED_ANNOTATION(__tsan_mutex_destroy);
+ MutexDestroy(thr, pc, (uptr)m, flagz);
+}
+
+INTERFACE_ATTRIBUTE
+void __tsan_mutex_pre_lock(void *m, unsigned flagz) {
+ SCOPED_ANNOTATION(__tsan_mutex_pre_lock);
+ if (!(flagz & MutexFlagTryLock)) {
+ if (flagz & MutexFlagReadLock)
+ MutexPreReadLock(thr, pc, (uptr)m);
+ else
+ MutexPreLock(thr, pc, (uptr)m);
+ }
+ ThreadIgnoreBegin(thr, 0);
+ ThreadIgnoreSyncBegin(thr, 0);
+}
+
+INTERFACE_ATTRIBUTE
+void __tsan_mutex_post_lock(void *m, unsigned flagz, int rec) {
+ SCOPED_ANNOTATION(__tsan_mutex_post_lock);
+ ThreadIgnoreSyncEnd(thr);
+ ThreadIgnoreEnd(thr);
+ if (!(flagz & MutexFlagTryLockFailed)) {
+ if (flagz & MutexFlagReadLock)
+ MutexPostReadLock(thr, pc, (uptr)m, flagz);
+ else
+ MutexPostLock(thr, pc, (uptr)m, flagz, rec);
+ }
+}
+
+INTERFACE_ATTRIBUTE
+int __tsan_mutex_pre_unlock(void *m, unsigned flagz) {
+ SCOPED_ANNOTATION_RET(__tsan_mutex_pre_unlock, 0);
+ int ret = 0;
+ if (flagz & MutexFlagReadLock) {
+ CHECK(!(flagz & MutexFlagRecursiveUnlock));
+ MutexReadUnlock(thr, pc, (uptr)m);
+ } else {
+ ret = MutexUnlock(thr, pc, (uptr)m, flagz);
+ }
+ ThreadIgnoreBegin(thr, 0);
+ ThreadIgnoreSyncBegin(thr, 0);
+ return ret;
+}
+
+INTERFACE_ATTRIBUTE
+void __tsan_mutex_post_unlock(void *m, unsigned flagz) {
+ SCOPED_ANNOTATION(__tsan_mutex_post_unlock);
+ ThreadIgnoreSyncEnd(thr);
+ ThreadIgnoreEnd(thr);
+}
+
+INTERFACE_ATTRIBUTE
+void __tsan_mutex_pre_signal(void *addr, unsigned flagz) {
+ SCOPED_ANNOTATION(__tsan_mutex_pre_signal);
+ ThreadIgnoreBegin(thr, 0);
+ ThreadIgnoreSyncBegin(thr, 0);
+}
+
+INTERFACE_ATTRIBUTE
+void __tsan_mutex_post_signal(void *addr, unsigned flagz) {
+ SCOPED_ANNOTATION(__tsan_mutex_post_signal);
+ ThreadIgnoreSyncEnd(thr);
+ ThreadIgnoreEnd(thr);
+}
+
+INTERFACE_ATTRIBUTE
+void __tsan_mutex_pre_divert(void *addr, unsigned flagz) {
+ SCOPED_ANNOTATION(__tsan_mutex_pre_divert);
+ // Exit from ignore region started in __tsan_mutex_pre_lock/unlock/signal.
+ ThreadIgnoreSyncEnd(thr);
+ ThreadIgnoreEnd(thr);
+}
+
+INTERFACE_ATTRIBUTE
+void __tsan_mutex_post_divert(void *addr, unsigned flagz) {
+ SCOPED_ANNOTATION(__tsan_mutex_post_divert);
+ ThreadIgnoreBegin(thr, 0);
+ ThreadIgnoreSyncBegin(thr, 0);
+}
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_ann.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_ann.h
new file mode 100644
index 00000000000..458d61f5335
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_ann.h
@@ -0,0 +1,32 @@
+//===-- tsan_interface_ann.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Interface for dynamic annotations.
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_INTERFACE_ANN_H
+#define TSAN_INTERFACE_ANN_H
+
+#include <sanitizer_common/sanitizer_internal_defs.h>
+
+// This header should NOT include any other headers.
+// All functions in this header are extern "C" and start with __tsan_.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_acquire(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_release(void *addr);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // TSAN_INTERFACE_ANN_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_atomic.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_atomic.cpp
new file mode 100644
index 00000000000..f794a2fcdd0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_atomic.cpp
@@ -0,0 +1,925 @@
+//===-- tsan_interface_atomic.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+// ThreadSanitizer atomic operations are based on C++11/C1x standards.
+// For background see C++11 standard. A slightly older, publicly
+// available draft of the standard (not entirely up-to-date, but close enough
+// for casual browsing) is available here:
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
+// The following page contains more background information:
+// http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/
+
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+#include "tsan_flags.h"
+#include "tsan_interface.h"
+#include "tsan_rtl.h"
+
+using namespace __tsan;
+
+#if !SANITIZER_GO && __TSAN_HAS_INT128
+// Protects emulation of 128-bit atomic operations.
+static StaticSpinMutex mutex128;
+#endif
+
+#if SANITIZER_DEBUG
+static bool IsLoadOrder(morder mo) {
+ return mo == mo_relaxed || mo == mo_consume
+ || mo == mo_acquire || mo == mo_seq_cst;
+}
+
+static bool IsStoreOrder(morder mo) {
+ return mo == mo_relaxed || mo == mo_release || mo == mo_seq_cst;
+}
+#endif
+
+static bool IsReleaseOrder(morder mo) {
+ return mo == mo_release || mo == mo_acq_rel || mo == mo_seq_cst;
+}
+
+static bool IsAcquireOrder(morder mo) {
+ return mo == mo_consume || mo == mo_acquire
+ || mo == mo_acq_rel || mo == mo_seq_cst;
+}
+
+static bool IsAcqRelOrder(morder mo) {
+ return mo == mo_acq_rel || mo == mo_seq_cst;
+}
+
+template<typename T> T func_xchg(volatile T *v, T op) {
+ T res = __sync_lock_test_and_set(v, op);
+ // __sync_lock_test_and_set does not contain full barrier.
+ __sync_synchronize();
+ return res;
+}
+
+template<typename T> T func_add(volatile T *v, T op) {
+ return __sync_fetch_and_add(v, op);
+}
+
+template<typename T> T func_sub(volatile T *v, T op) {
+ return __sync_fetch_and_sub(v, op);
+}
+
+template<typename T> T func_and(volatile T *v, T op) {
+ return __sync_fetch_and_and(v, op);
+}
+
+template<typename T> T func_or(volatile T *v, T op) {
+ return __sync_fetch_and_or(v, op);
+}
+
+template<typename T> T func_xor(volatile T *v, T op) {
+ return __sync_fetch_and_xor(v, op);
+}
+
+template<typename T> T func_nand(volatile T *v, T op) {
+ // clang does not support __sync_fetch_and_nand.
+ T cmp = *v;
+ for (;;) {
+ T newv = ~(cmp & op);
+ T cur = __sync_val_compare_and_swap(v, cmp, newv);
+ if (cmp == cur)
+ return cmp;
+ cmp = cur;
+ }
+}
+
+template<typename T> T func_cas(volatile T *v, T cmp, T xch) {
+ return __sync_val_compare_and_swap(v, cmp, xch);
+}
+
+// clang does not support 128-bit atomic ops.
+// Atomic ops are executed under tsan internal mutex,
+// here we assume that the atomic variables are not accessed
+// from non-instrumented code.
+#if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && !SANITIZER_GO \
+ && __TSAN_HAS_INT128
+a128 func_xchg(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
+ a128 cmp = *v;
+ *v = op;
+ return cmp;
+}
+
+a128 func_add(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
+ a128 cmp = *v;
+ *v = cmp + op;
+ return cmp;
+}
+
+a128 func_sub(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
+ a128 cmp = *v;
+ *v = cmp - op;
+ return cmp;
+}
+
+a128 func_and(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
+ a128 cmp = *v;
+ *v = cmp & op;
+ return cmp;
+}
+
+a128 func_or(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
+ a128 cmp = *v;
+ *v = cmp | op;
+ return cmp;
+}
+
+a128 func_xor(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
+ a128 cmp = *v;
+ *v = cmp ^ op;
+ return cmp;
+}
+
+a128 func_nand(volatile a128 *v, a128 op) {
+ SpinMutexLock lock(&mutex128);
+ a128 cmp = *v;
+ *v = ~(cmp & op);
+ return cmp;
+}
+
+a128 func_cas(volatile a128 *v, a128 cmp, a128 xch) {
+ SpinMutexLock lock(&mutex128);
+ a128 cur = *v;
+ if (cur == cmp)
+ *v = xch;
+ return cur;
+}
+#endif
+
+template <typename T>
+static int AccessSize() {
+ if (sizeof(T) <= 1)
+ return 1;
+ else if (sizeof(T) <= 2)
+ return 2;
+ else if (sizeof(T) <= 4)
+ return 4;
+ else
+ return 8;
+ // For 16-byte atomics we also use 8-byte memory access,
+ // this leads to false negatives only in very obscure cases.
+}
+
+#if !SANITIZER_GO
+static atomic_uint8_t *to_atomic(const volatile a8 *a) {
+ return reinterpret_cast<atomic_uint8_t *>(const_cast<a8 *>(a));
+}
+
+static atomic_uint16_t *to_atomic(const volatile a16 *a) {
+ return reinterpret_cast<atomic_uint16_t *>(const_cast<a16 *>(a));
+}
+#endif
+
+static atomic_uint32_t *to_atomic(const volatile a32 *a) {
+ return reinterpret_cast<atomic_uint32_t *>(const_cast<a32 *>(a));
+}
+
+static atomic_uint64_t *to_atomic(const volatile a64 *a) {
+ return reinterpret_cast<atomic_uint64_t *>(const_cast<a64 *>(a));
+}
+
+static memory_order to_mo(morder mo) {
+ switch (mo) {
+ case mo_relaxed: return memory_order_relaxed;
+ case mo_consume: return memory_order_consume;
+ case mo_acquire: return memory_order_acquire;
+ case mo_release: return memory_order_release;
+ case mo_acq_rel: return memory_order_acq_rel;
+ case mo_seq_cst: return memory_order_seq_cst;
+ }
+ DCHECK(0);
+ return memory_order_seq_cst;
+}
+
+template<typename T>
+static T NoTsanAtomicLoad(const volatile T *a, morder mo) {
+ return atomic_load(to_atomic(a), to_mo(mo));
+}
+
+#if __TSAN_HAS_INT128 && !SANITIZER_GO
+static a128 NoTsanAtomicLoad(const volatile a128 *a, morder mo) {
+ SpinMutexLock lock(&mutex128);
+ return *a;
+}
+#endif
+
+template <typename T>
+static T AtomicLoad(ThreadState *thr, uptr pc, const volatile T *a, morder mo) {
+ DCHECK(IsLoadOrder(mo));
+ // This fast-path is critical for performance.
+ // Assume the access is atomic.
+ if (!IsAcquireOrder(mo)) {
+ MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(),
+ kAccessRead | kAccessAtomic);
+ return NoTsanAtomicLoad(a, mo);
+ }
+ // Don't create sync object if it does not exist yet. For example, an atomic
+ // pointer is initialized to nullptr and then periodically acquire-loaded.
+ T v = NoTsanAtomicLoad(a, mo);
+ SyncVar *s = ctx->metamap.GetSyncIfExists((uptr)a);
+ if (s) {
+ SlotLocker locker(thr);
+ ReadLock lock(&s->mtx);
+ thr->clock.Acquire(s->clock);
+ // Re-read under sync mutex because we need a consistent snapshot
+ // of the value and the clock we acquire.
+ v = NoTsanAtomicLoad(a, mo);
+ }
+ MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessRead | kAccessAtomic);
+ return v;
+}
+
+template<typename T>
+static void NoTsanAtomicStore(volatile T *a, T v, morder mo) {
+ atomic_store(to_atomic(a), v, to_mo(mo));
+}
+
+#if __TSAN_HAS_INT128 && !SANITIZER_GO
+static void NoTsanAtomicStore(volatile a128 *a, a128 v, morder mo) {
+ SpinMutexLock lock(&mutex128);
+ *a = v;
+}
+#endif
+
+template <typename T>
+static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v,
+ morder mo) {
+ DCHECK(IsStoreOrder(mo));
+ MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);
+ // This fast-path is critical for performance.
+ // Assume the access is atomic.
+ // Strictly saying even relaxed store cuts off release sequence,
+ // so must reset the clock.
+ if (!IsReleaseOrder(mo)) {
+ NoTsanAtomicStore(a, v, mo);
+ return;
+ }
+ SlotLocker locker(thr);
+ {
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
+ Lock lock(&s->mtx);
+ thr->clock.ReleaseStore(&s->clock);
+ NoTsanAtomicStore(a, v, mo);
+ }
+ IncrementEpoch(thr);
+}
+
+template <typename T, T (*F)(volatile T *v, T op)>
+static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {
+ MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);
+ if (LIKELY(mo == mo_relaxed))
+ return F(a, v);
+ SlotLocker locker(thr);
+ {
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
+ RWLock lock(&s->mtx, IsReleaseOrder(mo));
+ if (IsAcqRelOrder(mo))
+ thr->clock.ReleaseAcquire(&s->clock);
+ else if (IsReleaseOrder(mo))
+ thr->clock.Release(&s->clock);
+ else if (IsAcquireOrder(mo))
+ thr->clock.Acquire(s->clock);
+ v = F(a, v);
+ }
+ if (IsReleaseOrder(mo))
+ IncrementEpoch(thr);
+ return v;
+}
+
+template<typename T>
+static T NoTsanAtomicExchange(volatile T *a, T v, morder mo) {
+ return func_xchg(a, v);
+}
+
+template<typename T>
+static T NoTsanAtomicFetchAdd(volatile T *a, T v, morder mo) {
+ return func_add(a, v);
+}
+
+template<typename T>
+static T NoTsanAtomicFetchSub(volatile T *a, T v, morder mo) {
+ return func_sub(a, v);
+}
+
+template<typename T>
+static T NoTsanAtomicFetchAnd(volatile T *a, T v, morder mo) {
+ return func_and(a, v);
+}
+
+template<typename T>
+static T NoTsanAtomicFetchOr(volatile T *a, T v, morder mo) {
+ return func_or(a, v);
+}
+
+template<typename T>
+static T NoTsanAtomicFetchXor(volatile T *a, T v, morder mo) {
+ return func_xor(a, v);
+}
+
+template<typename T>
+static T NoTsanAtomicFetchNand(volatile T *a, T v, morder mo) {
+ return func_nand(a, v);
+}
+
+template<typename T>
+static T AtomicExchange(ThreadState *thr, uptr pc, volatile T *a, T v,
+ morder mo) {
+ return AtomicRMW<T, func_xchg>(thr, pc, a, v, mo);
+}
+
+template<typename T>
+static T AtomicFetchAdd(ThreadState *thr, uptr pc, volatile T *a, T v,
+ morder mo) {
+ return AtomicRMW<T, func_add>(thr, pc, a, v, mo);
+}
+
+template<typename T>
+static T AtomicFetchSub(ThreadState *thr, uptr pc, volatile T *a, T v,
+ morder mo) {
+ return AtomicRMW<T, func_sub>(thr, pc, a, v, mo);
+}
+
+template<typename T>
+static T AtomicFetchAnd(ThreadState *thr, uptr pc, volatile T *a, T v,
+ morder mo) {
+ return AtomicRMW<T, func_and>(thr, pc, a, v, mo);
+}
+
+template<typename T>
+static T AtomicFetchOr(ThreadState *thr, uptr pc, volatile T *a, T v,
+ morder mo) {
+ return AtomicRMW<T, func_or>(thr, pc, a, v, mo);
+}
+
+template<typename T>
+static T AtomicFetchXor(ThreadState *thr, uptr pc, volatile T *a, T v,
+ morder mo) {
+ return AtomicRMW<T, func_xor>(thr, pc, a, v, mo);
+}
+
+template<typename T>
+static T AtomicFetchNand(ThreadState *thr, uptr pc, volatile T *a, T v,
+ morder mo) {
+ return AtomicRMW<T, func_nand>(thr, pc, a, v, mo);
+}
+
+template<typename T>
+static bool NoTsanAtomicCAS(volatile T *a, T *c, T v, morder mo, morder fmo) {
+ return atomic_compare_exchange_strong(to_atomic(a), c, v, to_mo(mo));
+}
+
+#if __TSAN_HAS_INT128
+static bool NoTsanAtomicCAS(volatile a128 *a, a128 *c, a128 v,
+ morder mo, morder fmo) {
+ a128 old = *c;
+ a128 cur = func_cas(a, old, v);
+ if (cur == old)
+ return true;
+ *c = cur;
+ return false;
+}
+#endif
+
+template<typename T>
+static T NoTsanAtomicCAS(volatile T *a, T c, T v, morder mo, morder fmo) {
+ NoTsanAtomicCAS(a, &c, v, mo, fmo);
+ return c;
+}
+
+template <typename T>
+static bool AtomicCAS(ThreadState *thr, uptr pc, volatile T *a, T *c, T v,
+ morder mo, morder fmo) {
+ // 31.7.2.18: "The failure argument shall not be memory_order_release
+ // nor memory_order_acq_rel". LLVM (2021-05) fallbacks to Monotonic
+ // (mo_relaxed) when those are used.
+ DCHECK(IsLoadOrder(fmo));
+
+ MemoryAccess(thr, pc, (uptr)a, AccessSize<T>(), kAccessWrite | kAccessAtomic);
+ if (LIKELY(mo == mo_relaxed && fmo == mo_relaxed)) {
+ T cc = *c;
+ T pr = func_cas(a, cc, v);
+ if (pr == cc)
+ return true;
+ *c = pr;
+ return false;
+ }
+ SlotLocker locker(thr);
+ bool release = IsReleaseOrder(mo);
+ bool success;
+ {
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, (uptr)a, false);
+ RWLock lock(&s->mtx, release);
+ T cc = *c;
+ T pr = func_cas(a, cc, v);
+ success = pr == cc;
+ if (!success) {
+ *c = pr;
+ mo = fmo;
+ }
+ if (success && IsAcqRelOrder(mo))
+ thr->clock.ReleaseAcquire(&s->clock);
+ else if (success && IsReleaseOrder(mo))
+ thr->clock.Release(&s->clock);
+ else if (IsAcquireOrder(mo))
+ thr->clock.Acquire(s->clock);
+ }
+ if (success && release)
+ IncrementEpoch(thr);
+ return success;
+}
+
+template<typename T>
+static T AtomicCAS(ThreadState *thr, uptr pc,
+ volatile T *a, T c, T v, morder mo, morder fmo) {
+ AtomicCAS(thr, pc, a, &c, v, mo, fmo);
+ return c;
+}
+
+#if !SANITIZER_GO
+static void NoTsanAtomicFence(morder mo) {
+ __sync_synchronize();
+}
+
+static void AtomicFence(ThreadState *thr, uptr pc, morder mo) {
+ // FIXME(dvyukov): not implemented.
+ __sync_synchronize();
+}
+#endif
+
+// Interface functions follow.
+#if !SANITIZER_GO
+
+// C/C++
+
+static morder convert_morder(morder mo) {
+ if (flags()->force_seq_cst_atomics)
+ return (morder)mo_seq_cst;
+
+ // Filter out additional memory order flags:
+ // MEMMODEL_SYNC = 1 << 15
+ // __ATOMIC_HLE_ACQUIRE = 1 << 16
+ // __ATOMIC_HLE_RELEASE = 1 << 17
+ //
+ // HLE is an optimization, and we pretend that elision always fails.
+ // MEMMODEL_SYNC is used when lowering __sync_ atomics,
+ // since we use __sync_ atomics for actual atomic operations,
+ // we can safely ignore it as well. It also subtly affects semantics,
+ // but we don't model the difference.
+ return (morder)(mo & 0x7fff);
+}
+
+# define ATOMIC_IMPL(func, ...) \
+ ThreadState *const thr = cur_thread(); \
+ ProcessPendingSignals(thr); \
+ if (UNLIKELY(thr->ignore_sync || thr->ignore_interceptors)) \
+ return NoTsanAtomic##func(__VA_ARGS__); \
+ mo = convert_morder(mo); \
+ return Atomic##func(thr, GET_CALLER_PC(), __VA_ARGS__);
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_load(const volatile a8 *a, morder mo) {
+ ATOMIC_IMPL(Load, a, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_load(const volatile a16 *a, morder mo) {
+ ATOMIC_IMPL(Load, a, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_load(const volatile a32 *a, morder mo) {
+ ATOMIC_IMPL(Load, a, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_load(const volatile a64 *a, morder mo) {
+ ATOMIC_IMPL(Load, a, mo);
+}
+
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_load(const volatile a128 *a, morder mo) {
+ ATOMIC_IMPL(Load, a, mo);
+}
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic8_store(volatile a8 *a, a8 v, morder mo) {
+ ATOMIC_IMPL(Store, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic16_store(volatile a16 *a, a16 v, morder mo) {
+ ATOMIC_IMPL(Store, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic32_store(volatile a32 *a, a32 v, morder mo) {
+ ATOMIC_IMPL(Store, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic64_store(volatile a64 *a, a64 v, morder mo) {
+ ATOMIC_IMPL(Store, a, v, mo);
+}
+
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic128_store(volatile a128 *a, a128 v, morder mo) {
+ ATOMIC_IMPL(Store, a, v, mo);
+}
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_exchange(volatile a8 *a, a8 v, morder mo) {
+ ATOMIC_IMPL(Exchange, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_exchange(volatile a16 *a, a16 v, morder mo) {
+ ATOMIC_IMPL(Exchange, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_exchange(volatile a32 *a, a32 v, morder mo) {
+ ATOMIC_IMPL(Exchange, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_exchange(volatile a64 *a, a64 v, morder mo) {
+ ATOMIC_IMPL(Exchange, a, v, mo);
+}
+
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_exchange(volatile a128 *a, a128 v, morder mo) {
+ ATOMIC_IMPL(Exchange, a, v, mo);
+}
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_fetch_add(volatile a8 *a, a8 v, morder mo) {
+ ATOMIC_IMPL(FetchAdd, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_fetch_add(volatile a16 *a, a16 v, morder mo) {
+ ATOMIC_IMPL(FetchAdd, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_fetch_add(volatile a32 *a, a32 v, morder mo) {
+ ATOMIC_IMPL(FetchAdd, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_fetch_add(volatile a64 *a, a64 v, morder mo) {
+ ATOMIC_IMPL(FetchAdd, a, v, mo);
+}
+
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_fetch_add(volatile a128 *a, a128 v, morder mo) {
+ ATOMIC_IMPL(FetchAdd, a, v, mo);
+}
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_fetch_sub(volatile a8 *a, a8 v, morder mo) {
+ ATOMIC_IMPL(FetchSub, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_fetch_sub(volatile a16 *a, a16 v, morder mo) {
+ ATOMIC_IMPL(FetchSub, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_fetch_sub(volatile a32 *a, a32 v, morder mo) {
+ ATOMIC_IMPL(FetchSub, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_fetch_sub(volatile a64 *a, a64 v, morder mo) {
+ ATOMIC_IMPL(FetchSub, a, v, mo);
+}
+
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_fetch_sub(volatile a128 *a, a128 v, morder mo) {
+ ATOMIC_IMPL(FetchSub, a, v, mo);
+}
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_fetch_and(volatile a8 *a, a8 v, morder mo) {
+ ATOMIC_IMPL(FetchAnd, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_fetch_and(volatile a16 *a, a16 v, morder mo) {
+ ATOMIC_IMPL(FetchAnd, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_fetch_and(volatile a32 *a, a32 v, morder mo) {
+ ATOMIC_IMPL(FetchAnd, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_fetch_and(volatile a64 *a, a64 v, morder mo) {
+ ATOMIC_IMPL(FetchAnd, a, v, mo);
+}
+
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_fetch_and(volatile a128 *a, a128 v, morder mo) {
+ ATOMIC_IMPL(FetchAnd, a, v, mo);
+}
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_fetch_or(volatile a8 *a, a8 v, morder mo) {
+ ATOMIC_IMPL(FetchOr, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_fetch_or(volatile a16 *a, a16 v, morder mo) {
+ ATOMIC_IMPL(FetchOr, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_fetch_or(volatile a32 *a, a32 v, morder mo) {
+ ATOMIC_IMPL(FetchOr, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_fetch_or(volatile a64 *a, a64 v, morder mo) {
+ ATOMIC_IMPL(FetchOr, a, v, mo);
+}
+
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_fetch_or(volatile a128 *a, a128 v, morder mo) {
+ ATOMIC_IMPL(FetchOr, a, v, mo);
+}
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_fetch_xor(volatile a8 *a, a8 v, morder mo) {
+ ATOMIC_IMPL(FetchXor, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_fetch_xor(volatile a16 *a, a16 v, morder mo) {
+ ATOMIC_IMPL(FetchXor, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_fetch_xor(volatile a32 *a, a32 v, morder mo) {
+ ATOMIC_IMPL(FetchXor, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_fetch_xor(volatile a64 *a, a64 v, morder mo) {
+ ATOMIC_IMPL(FetchXor, a, v, mo);
+}
+
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_fetch_xor(volatile a128 *a, a128 v, morder mo) {
+ ATOMIC_IMPL(FetchXor, a, v, mo);
+}
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_fetch_nand(volatile a8 *a, a8 v, morder mo) {
+ ATOMIC_IMPL(FetchNand, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_fetch_nand(volatile a16 *a, a16 v, morder mo) {
+ ATOMIC_IMPL(FetchNand, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_fetch_nand(volatile a32 *a, a32 v, morder mo) {
+ ATOMIC_IMPL(FetchNand, a, v, mo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_fetch_nand(volatile a64 *a, a64 v, morder mo) {
+ ATOMIC_IMPL(FetchNand, a, v, mo);
+}
+
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_fetch_nand(volatile a128 *a, a128 v, morder mo) {
+ ATOMIC_IMPL(FetchNand, a, v, mo);
+}
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic8_compare_exchange_strong(volatile a8 *a, a8 *c, a8 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic16_compare_exchange_strong(volatile a16 *a, a16 *c, a16 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic32_compare_exchange_strong(volatile a32 *a, a32 *c, a32 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic64_compare_exchange_strong(volatile a64 *a, a64 *c, a64 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic128_compare_exchange_strong(volatile a128 *a, a128 *c, a128 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic8_compare_exchange_weak(volatile a8 *a, a8 *c, a8 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic16_compare_exchange_weak(volatile a16 *a, a16 *c, a16 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic32_compare_exchange_weak(volatile a32 *a, a32 *c, a32 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic64_compare_exchange_weak(volatile a64 *a, a64 *c, a64 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tsan_atomic128_compare_exchange_weak(volatile a128 *a, a128 *c, a128 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a8 __tsan_atomic8_compare_exchange_val(volatile a8 *a, a8 c, a8 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a16 __tsan_atomic16_compare_exchange_val(volatile a16 *a, a16 c, a16 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a32 __tsan_atomic32_compare_exchange_val(volatile a32 *a, a32 c, a32 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
+ morder mo, morder fmo) {
+ ATOMIC_IMPL(CAS, a, c, v, mo, fmo);
+}
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic_thread_fence(morder mo) { ATOMIC_IMPL(Fence, mo); }
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_atomic_signal_fence(morder mo) {
+}
+} // extern "C"
+
+#else // #if !SANITIZER_GO
+
+// Go
+
+# define ATOMIC(func, ...) \
+ if (thr->ignore_sync) { \
+ NoTsanAtomic##func(__VA_ARGS__); \
+ } else { \
+ FuncEntry(thr, cpc); \
+ Atomic##func(thr, pc, __VA_ARGS__); \
+ FuncExit(thr); \
+ }
+
+# define ATOMIC_RET(func, ret, ...) \
+ if (thr->ignore_sync) { \
+ (ret) = NoTsanAtomic##func(__VA_ARGS__); \
+ } else { \
+ FuncEntry(thr, cpc); \
+ (ret) = Atomic##func(thr, pc, __VA_ARGS__); \
+ FuncExit(thr); \
+ }
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic32_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
+ ATOMIC_RET(Load, *(a32*)(a+8), *(a32**)a, mo_acquire);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic64_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
+ ATOMIC_RET(Load, *(a64*)(a+8), *(a64**)a, mo_acquire);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic32_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
+ ATOMIC(Store, *(a32**)a, *(a32*)(a+8), mo_release);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic64_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
+ ATOMIC(Store, *(a64**)a, *(a64*)(a+8), mo_release);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic32_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
+ ATOMIC_RET(FetchAdd, *(a32*)(a+16), *(a32**)a, *(a32*)(a+8), mo_acq_rel);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic64_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
+ ATOMIC_RET(FetchAdd, *(a64*)(a+16), *(a64**)a, *(a64*)(a+8), mo_acq_rel);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic32_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
+ ATOMIC_RET(Exchange, *(a32*)(a+16), *(a32**)a, *(a32*)(a+8), mo_acq_rel);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic64_exchange(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
+ ATOMIC_RET(Exchange, *(a64*)(a+16), *(a64**)a, *(a64*)(a+8), mo_acq_rel);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic32_compare_exchange(
+ ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
+ a32 cur = 0;
+ a32 cmp = *(a32*)(a+8);
+ ATOMIC_RET(CAS, cur, *(a32**)a, cmp, *(a32*)(a+12), mo_acq_rel, mo_acquire);
+ *(bool*)(a+16) = (cur == cmp);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic64_compare_exchange(
+ ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
+ a64 cur = 0;
+ a64 cmp = *(a64*)(a+8);
+ ATOMIC_RET(CAS, cur, *(a64**)a, cmp, *(a64*)(a+16), mo_acq_rel, mo_acquire);
+ *(bool*)(a+24) = (cur == cmp);
+}
+} // extern "C"
+#endif // #if !SANITIZER_GO
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_java.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_java.cpp
new file mode 100644
index 00000000000..7c15a163882
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_java.cpp
@@ -0,0 +1,258 @@
+//===-- tsan_interface_java.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "tsan_interface_java.h"
+#include "tsan_rtl.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+
+using namespace __tsan;
+
+const jptr kHeapAlignment = 8;
+
+namespace __tsan {
+
+struct JavaContext {
+ const uptr heap_begin;
+ const uptr heap_size;
+
+ JavaContext(jptr heap_begin, jptr heap_size)
+ : heap_begin(heap_begin)
+ , heap_size(heap_size) {
+ }
+};
+
+static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
+static JavaContext *jctx;
+
+MBlock *JavaHeapBlock(uptr addr, uptr *start) {
+ if (!jctx || addr < jctx->heap_begin ||
+ addr >= jctx->heap_begin + jctx->heap_size)
+ return nullptr;
+ for (uptr p = RoundDown(addr, kMetaShadowCell); p >= jctx->heap_begin;
+ p -= kMetaShadowCell) {
+ MBlock *b = ctx->metamap.GetBlock(p);
+ if (!b)
+ continue;
+ if (p + b->siz <= addr)
+ return nullptr;
+ *start = p;
+ return b;
+ }
+ return nullptr;
+}
+
+} // namespace __tsan
+
+#define JAVA_FUNC_ENTER(func) \
+ ThreadState *thr = cur_thread(); \
+ (void)thr;
+
+void __tsan_java_init(jptr heap_begin, jptr heap_size) {
+ JAVA_FUNC_ENTER(__tsan_java_init);
+ Initialize(thr);
+ DPrintf("#%d: java_init(0x%zx, 0x%zx)\n", thr->tid, heap_begin, heap_size);
+ DCHECK_EQ(jctx, 0);
+ DCHECK_GT(heap_begin, 0);
+ DCHECK_GT(heap_size, 0);
+ DCHECK_EQ(heap_begin % kHeapAlignment, 0);
+ DCHECK_EQ(heap_size % kHeapAlignment, 0);
+ DCHECK_LT(heap_begin, heap_begin + heap_size);
+ jctx = new(jctx_buf) JavaContext(heap_begin, heap_size);
+}
+
+int __tsan_java_fini() {
+ JAVA_FUNC_ENTER(__tsan_java_fini);
+ DPrintf("#%d: java_fini()\n", thr->tid);
+ DCHECK_NE(jctx, 0);
+ // FIXME(dvyukov): this does not call atexit() callbacks.
+ int status = Finalize(thr);
+ DPrintf("#%d: java_fini() = %d\n", thr->tid, status);
+ return status;
+}
+
+void __tsan_java_alloc(jptr ptr, jptr size) {
+ JAVA_FUNC_ENTER(__tsan_java_alloc);
+ DPrintf("#%d: java_alloc(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
+ DCHECK_NE(jctx, 0);
+ DCHECK_NE(size, 0);
+ DCHECK_EQ(ptr % kHeapAlignment, 0);
+ DCHECK_EQ(size % kHeapAlignment, 0);
+ DCHECK_GE(ptr, jctx->heap_begin);
+ DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
+
+ OnUserAlloc(thr, 0, ptr, size, false);
+}
+
+void __tsan_java_free(jptr ptr, jptr size) {
+ JAVA_FUNC_ENTER(__tsan_java_free);
+ DPrintf("#%d: java_free(0x%zx, 0x%zx)\n", thr->tid, ptr, size);
+ DCHECK_NE(jctx, 0);
+ DCHECK_NE(size, 0);
+ DCHECK_EQ(ptr % kHeapAlignment, 0);
+ DCHECK_EQ(size % kHeapAlignment, 0);
+ DCHECK_GE(ptr, jctx->heap_begin);
+ DCHECK_LE(ptr + size, jctx->heap_begin + jctx->heap_size);
+
+ ctx->metamap.FreeRange(thr->proc(), ptr, size, false);
+}
+
+void __tsan_java_move(jptr src, jptr dst, jptr size) {
+ JAVA_FUNC_ENTER(__tsan_java_move);
+ DPrintf("#%d: java_move(0x%zx, 0x%zx, 0x%zx)\n", thr->tid, src, dst, size);
+ DCHECK_NE(jctx, 0);
+ DCHECK_NE(size, 0);
+ DCHECK_EQ(src % kHeapAlignment, 0);
+ DCHECK_EQ(dst % kHeapAlignment, 0);
+ DCHECK_EQ(size % kHeapAlignment, 0);
+ DCHECK_GE(src, jctx->heap_begin);
+ DCHECK_LE(src + size, jctx->heap_begin + jctx->heap_size);
+ DCHECK_GE(dst, jctx->heap_begin);
+ DCHECK_LE(dst + size, jctx->heap_begin + jctx->heap_size);
+ DCHECK_NE(dst, src);
+ DCHECK_NE(size, 0);
+
+ // Assuming it's not running concurrently with threads that do
+ // memory accesses and mutex operations (stop-the-world phase).
+ ctx->metamap.MoveMemory(src, dst, size);
+
+ // Clear the destination shadow range.
+ // We used to move shadow from src to dst, but the trace format does not
+ // support that anymore as it contains addresses of accesses.
+ RawShadow *d = MemToShadow(dst);
+ RawShadow *dend = MemToShadow(dst + size);
+ ShadowSet(d, dend, Shadow::kEmpty);
+}
+
+jptr __tsan_java_find(jptr *from_ptr, jptr to) {
+ JAVA_FUNC_ENTER(__tsan_java_find);
+ DPrintf("#%d: java_find(&0x%zx, 0x%zx)\n", thr->tid, *from_ptr, to);
+ DCHECK_EQ((*from_ptr) % kHeapAlignment, 0);
+ DCHECK_EQ(to % kHeapAlignment, 0);
+ DCHECK_GE(*from_ptr, jctx->heap_begin);
+ DCHECK_LE(to, jctx->heap_begin + jctx->heap_size);
+ for (uptr from = *from_ptr; from < to; from += kHeapAlignment) {
+ MBlock *b = ctx->metamap.GetBlock(from);
+ if (b) {
+ *from_ptr = from;
+ return b->siz;
+ }
+ }
+ return 0;
+}
+
+void __tsan_java_finalize() {
+ JAVA_FUNC_ENTER(__tsan_java_finalize);
+ DPrintf("#%d: java_finalize()\n", thr->tid);
+ AcquireGlobal(thr);
+}
+
+void __tsan_java_mutex_lock(jptr addr) {
+ JAVA_FUNC_ENTER(__tsan_java_mutex_lock);
+ DPrintf("#%d: java_mutex_lock(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+
+ MutexPostLock(thr, 0, addr,
+ MutexFlagLinkerInit | MutexFlagWriteReentrant |
+ MutexFlagDoPreLockOnPostLock);
+}
+
+void __tsan_java_mutex_unlock(jptr addr) {
+ JAVA_FUNC_ENTER(__tsan_java_mutex_unlock);
+ DPrintf("#%d: java_mutex_unlock(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+
+ MutexUnlock(thr, 0, addr);
+}
+
+void __tsan_java_mutex_read_lock(jptr addr) {
+ JAVA_FUNC_ENTER(__tsan_java_mutex_read_lock);
+ DPrintf("#%d: java_mutex_read_lock(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+
+ MutexPostReadLock(thr, 0, addr,
+ MutexFlagLinkerInit | MutexFlagWriteReentrant |
+ MutexFlagDoPreLockOnPostLock);
+}
+
+void __tsan_java_mutex_read_unlock(jptr addr) {
+ JAVA_FUNC_ENTER(__tsan_java_mutex_read_unlock);
+ DPrintf("#%d: java_mutex_read_unlock(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+
+ MutexReadUnlock(thr, 0, addr);
+}
+
+void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
+ JAVA_FUNC_ENTER(__tsan_java_mutex_lock_rec);
+ DPrintf("#%d: java_mutex_lock_rec(0x%zx, %d)\n", thr->tid, addr, rec);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+ DCHECK_GT(rec, 0);
+
+ MutexPostLock(thr, 0, addr,
+ MutexFlagLinkerInit | MutexFlagWriteReentrant |
+ MutexFlagDoPreLockOnPostLock | MutexFlagRecursiveLock,
+ rec);
+}
+
+int __tsan_java_mutex_unlock_rec(jptr addr) {
+ JAVA_FUNC_ENTER(__tsan_java_mutex_unlock_rec);
+ DPrintf("#%d: java_mutex_unlock_rec(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+
+ return MutexUnlock(thr, 0, addr, MutexFlagRecursiveUnlock);
+}
+
+void __tsan_java_acquire(jptr addr) {
+ JAVA_FUNC_ENTER(__tsan_java_acquire);
+ DPrintf("#%d: java_acquire(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+
+ Acquire(thr, 0, addr);
+}
+
+void __tsan_java_release(jptr addr) {
+ JAVA_FUNC_ENTER(__tsan_java_release);
+ DPrintf("#%d: java_release(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+
+ Release(thr, 0, addr);
+}
+
+void __tsan_java_release_store(jptr addr) {
+ JAVA_FUNC_ENTER(__tsan_java_release);
+ DPrintf("#%d: java_release_store(0x%zx)\n", thr->tid, addr);
+ DCHECK_NE(jctx, 0);
+ DCHECK_GE(addr, jctx->heap_begin);
+ DCHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+
+ ReleaseStore(thr, 0, addr);
+}
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_java.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_java.h
new file mode 100644
index 00000000000..51b445251e0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_interface_java.h
@@ -0,0 +1,99 @@
+//===-- tsan_interface_java.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Interface for verification of Java or mixed Java/C++ programs.
+// The interface is intended to be used from within a JVM and notify TSan
+// about such events like Java locks and GC memory compaction.
+//
+// For plain memory accesses and function entry/exit a JVM is intended to use
+// C++ interfaces: __tsan_readN/writeN and __tsan_func_enter/exit.
+//
+// For volatile memory accesses and atomic operations JVM is intended to use
+// standard atomics API: __tsan_atomicN_load/store/etc.
+//
+// For usage examples see lit_tests/java_*.cpp
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_INTERFACE_JAVA_H
+#define TSAN_INTERFACE_JAVA_H
+
+#ifndef INTERFACE_ATTRIBUTE
+# define INTERFACE_ATTRIBUTE __attribute__((visibility("default")))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned long jptr;
+
+// Must be called before any other callback from Java.
+void __tsan_java_init(jptr heap_begin, jptr heap_size) INTERFACE_ATTRIBUTE;
+// Must be called when the application exits.
+// Not necessary the last callback (concurrently running threads are OK).
+// Returns exit status or 0 if tsan does not want to override it.
+int __tsan_java_fini() INTERFACE_ATTRIBUTE;
+
+// Callback for memory allocations.
+// May be omitted for allocations that are not subject to data races
+// nor contain synchronization objects (e.g. String).
+void __tsan_java_alloc(jptr ptr, jptr size) INTERFACE_ATTRIBUTE;
+// Callback for memory free.
+// Can be aggregated for several objects (preferably).
+void __tsan_java_free(jptr ptr, jptr size) INTERFACE_ATTRIBUTE;
+// Callback for memory move by GC.
+// Can be aggregated for several objects (preferably).
+// The ranges can overlap.
+void __tsan_java_move(jptr src, jptr dst, jptr size) INTERFACE_ATTRIBUTE;
+// This function must be called on the finalizer thread
+// before executing a batch of finalizers.
+// It ensures necessary synchronization between
+// java object creation and finalization.
+void __tsan_java_finalize() INTERFACE_ATTRIBUTE;
+// Finds the first allocated memory block in the [*from_ptr, to) range, saves
+// its address in *from_ptr and returns its size. Returns 0 if there are no
+// allocated memory blocks in the range.
+jptr __tsan_java_find(jptr *from_ptr, jptr to) INTERFACE_ATTRIBUTE;
+
+// Mutex lock.
+// Addr is any unique address associated with the mutex.
+// Can be called on recursive reentry.
+void __tsan_java_mutex_lock(jptr addr) INTERFACE_ATTRIBUTE;
+// Mutex unlock.
+void __tsan_java_mutex_unlock(jptr addr) INTERFACE_ATTRIBUTE;
+// Mutex read lock.
+void __tsan_java_mutex_read_lock(jptr addr) INTERFACE_ATTRIBUTE;
+// Mutex read unlock.
+void __tsan_java_mutex_read_unlock(jptr addr) INTERFACE_ATTRIBUTE;
+// Recursive mutex lock, intended for handling of Object.wait().
+// The 'rec' value must be obtained from the previous
+// __tsan_java_mutex_unlock_rec().
+void __tsan_java_mutex_lock_rec(jptr addr, int rec) INTERFACE_ATTRIBUTE;
+// Recursive mutex unlock, intended for handling of Object.wait().
+// The return value says how many times this thread called lock()
+// w/o a pairing unlock() (i.e. how many recursive levels it unlocked).
+// It must be passed back to __tsan_java_mutex_lock_rec() to restore
+// the same recursion level.
+int __tsan_java_mutex_unlock_rec(jptr addr) INTERFACE_ATTRIBUTE;
+
+// Raw acquire/release primitives.
+// Can be used to establish happens-before edges on volatile/final fields,
+// in atomic operations, etc. release_store is the same as release, but it
+// breaks release sequence on addr (see C++ standard 1.10/7 for details).
+void __tsan_java_acquire(jptr addr) INTERFACE_ATTRIBUTE;
+void __tsan_java_release(jptr addr) INTERFACE_ATTRIBUTE;
+void __tsan_java_release_store(jptr addr) INTERFACE_ATTRIBUTE;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#undef INTERFACE_ATTRIBUTE
+
+#endif // #ifndef TSAN_INTERFACE_JAVA_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_malloc_mac.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_malloc_mac.cpp
new file mode 100644
index 00000000000..ac844ae8a44
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_malloc_mac.cpp
@@ -0,0 +1,71 @@
+//===-- tsan_malloc_mac.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Mac-specific malloc interception.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_APPLE
+
+#include "sanitizer_common/sanitizer_errno.h"
+#include "tsan_interceptors.h"
+#include "tsan_stack_trace.h"
+
+using namespace __tsan;
+#define COMMON_MALLOC_ZONE_NAME "tsan"
+#define COMMON_MALLOC_ENTER()
+#define COMMON_MALLOC_SANITIZER_INITIALIZED (cur_thread()->is_inited)
+#define COMMON_MALLOC_FORCE_LOCK()
+#define COMMON_MALLOC_FORCE_UNLOCK()
+#define COMMON_MALLOC_MEMALIGN(alignment, size) \
+ void *p = \
+ user_memalign(cur_thread(), StackTrace::GetCurrentPc(), alignment, size)
+#define COMMON_MALLOC_MALLOC(size) \
+ if (in_symbolizer()) return InternalAlloc(size); \
+ SCOPED_INTERCEPTOR_RAW(malloc, size); \
+ void *p = user_alloc(thr, pc, size)
+#define COMMON_MALLOC_REALLOC(ptr, size) \
+ if (in_symbolizer()) return InternalRealloc(ptr, size); \
+ SCOPED_INTERCEPTOR_RAW(realloc, ptr, size); \
+ void *p = user_realloc(thr, pc, ptr, size)
+#define COMMON_MALLOC_CALLOC(count, size) \
+ if (in_symbolizer()) return InternalCalloc(count, size); \
+ SCOPED_INTERCEPTOR_RAW(calloc, size, count); \
+ void *p = user_calloc(thr, pc, size, count)
+#define COMMON_MALLOC_POSIX_MEMALIGN(memptr, alignment, size) \
+ if (in_symbolizer()) { \
+ void *p = InternalAlloc(size, nullptr, alignment); \
+ if (!p) return errno_ENOMEM; \
+ *memptr = p; \
+ return 0; \
+ } \
+ SCOPED_INTERCEPTOR_RAW(posix_memalign, memptr, alignment, size); \
+ int res = user_posix_memalign(thr, pc, memptr, alignment, size);
+#define COMMON_MALLOC_VALLOC(size) \
+ if (in_symbolizer()) \
+ return InternalAlloc(size, nullptr, GetPageSizeCached()); \
+ SCOPED_INTERCEPTOR_RAW(valloc, size); \
+ void *p = user_valloc(thr, pc, size)
+#define COMMON_MALLOC_FREE(ptr) \
+ if (in_symbolizer()) return InternalFree(ptr); \
+ SCOPED_INTERCEPTOR_RAW(free, ptr); \
+ user_free(thr, pc, ptr)
+#define COMMON_MALLOC_SIZE(ptr) uptr size = user_alloc_usable_size(ptr);
+#define COMMON_MALLOC_FILL_STATS(zone, stats)
+#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \
+ (void)zone_name; \
+ Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", ptr);
+#define COMMON_MALLOC_NAMESPACE __tsan
+#define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0
+#define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 0
+
+#include "sanitizer_common/sanitizer_malloc_mac.inc"
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_md5.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_md5.cpp
new file mode 100644
index 00000000000..72857b773fe
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_md5.cpp
@@ -0,0 +1,250 @@
+//===-- tsan_md5.cpp ------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_defs.h"
+
+namespace __tsan {
+
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+
+#define STEP(f, a, b, c, d, x, t, s) \
+ (a) += f((b), (c), (d)) + (x) + (t); \
+ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
+ (a) += (b);
+
+#define SET(n) \
+ (*(const MD5_u32plus *)&ptr[(n) * 4])
+#define GET(n) \
+ SET(n)
+
+typedef unsigned int MD5_u32plus;
+typedef unsigned long ulong_t;
+
+typedef struct {
+ MD5_u32plus lo, hi;
+ MD5_u32plus a, b, c, d;
+ unsigned char buffer[64];
+ MD5_u32plus block[16];
+} MD5_CTX;
+
+static const void *body(MD5_CTX *ctx, const void *data, ulong_t size) {
+ const unsigned char *ptr = (const unsigned char *)data;
+ MD5_u32plus a, b, c, d;
+ MD5_u32plus saved_a, saved_b, saved_c, saved_d;
+
+ a = ctx->a;
+ b = ctx->b;
+ c = ctx->c;
+ d = ctx->d;
+
+ do {
+ saved_a = a;
+ saved_b = b;
+ saved_c = c;
+ saved_d = d;
+
+ STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
+ STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
+ STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
+ STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
+ STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
+ STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
+ STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
+ STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
+ STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
+ STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
+ STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
+ STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
+ STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
+ STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
+ STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
+ STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
+
+ STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
+ STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
+ STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
+ STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
+ STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
+ STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
+ STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
+ STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
+ STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
+ STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
+ STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
+ STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
+ STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
+ STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
+ STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
+ STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
+
+ STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
+ STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
+ STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
+ STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
+ STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
+ STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
+ STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
+ STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
+ STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
+ STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
+ STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
+ STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
+ STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
+ STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
+ STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
+ STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
+
+ STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
+ STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
+ STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
+ STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
+ STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
+ STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
+ STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
+ STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
+ STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
+ STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
+ STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
+ STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
+ STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
+ STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
+ STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
+ STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
+
+ a += saved_a;
+ b += saved_b;
+ c += saved_c;
+ d += saved_d;
+
+ ptr += 64;
+ } while (size -= 64);
+
+ ctx->a = a;
+ ctx->b = b;
+ ctx->c = c;
+ ctx->d = d;
+
+ return ptr;
+}
+
+#undef F
+#undef G
+#undef H
+#undef I
+#undef STEP
+#undef SET
+#undef GET
+
+void MD5_Init(MD5_CTX *ctx) {
+ ctx->a = 0x67452301;
+ ctx->b = 0xefcdab89;
+ ctx->c = 0x98badcfe;
+ ctx->d = 0x10325476;
+
+ ctx->lo = 0;
+ ctx->hi = 0;
+}
+
+void MD5_Update(MD5_CTX *ctx, const void *data, ulong_t size) {
+ MD5_u32plus saved_lo;
+ ulong_t used, free;
+
+ saved_lo = ctx->lo;
+ if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+ ctx->hi++;
+ ctx->hi += size >> 29;
+
+ used = saved_lo & 0x3f;
+
+ if (used) {
+ free = 64 - used;
+
+ if (size < free) {
+ internal_memcpy(&ctx->buffer[used], data, size);
+ return;
+ }
+
+ internal_memcpy(&ctx->buffer[used], data, free);
+ data = (const unsigned char *)data + free;
+ size -= free;
+ body(ctx, ctx->buffer, 64);
+ }
+
+ if (size >= 64) {
+ data = body(ctx, data, size & ~(ulong_t)0x3f);
+ size &= 0x3f;
+ }
+
+ internal_memcpy(ctx->buffer, data, size);
+}
+
+void MD5_Final(unsigned char *result, MD5_CTX *ctx) {
+ ulong_t used, free;
+
+ used = ctx->lo & 0x3f;
+
+ ctx->buffer[used++] = 0x80;
+
+ free = 64 - used;
+
+ if (free < 8) {
+ internal_memset(&ctx->buffer[used], 0, free);
+ body(ctx, ctx->buffer, 64);
+ used = 0;
+ free = 64;
+ }
+
+ internal_memset(&ctx->buffer[used], 0, free - 8);
+
+ ctx->lo <<= 3;
+ ctx->buffer[56] = ctx->lo;
+ ctx->buffer[57] = ctx->lo >> 8;
+ ctx->buffer[58] = ctx->lo >> 16;
+ ctx->buffer[59] = ctx->lo >> 24;
+ ctx->buffer[60] = ctx->hi;
+ ctx->buffer[61] = ctx->hi >> 8;
+ ctx->buffer[62] = ctx->hi >> 16;
+ ctx->buffer[63] = ctx->hi >> 24;
+
+ body(ctx, ctx->buffer, 64);
+
+ result[0] = ctx->a;
+ result[1] = ctx->a >> 8;
+ result[2] = ctx->a >> 16;
+ result[3] = ctx->a >> 24;
+ result[4] = ctx->b;
+ result[5] = ctx->b >> 8;
+ result[6] = ctx->b >> 16;
+ result[7] = ctx->b >> 24;
+ result[8] = ctx->c;
+ result[9] = ctx->c >> 8;
+ result[10] = ctx->c >> 16;
+ result[11] = ctx->c >> 24;
+ result[12] = ctx->d;
+ result[13] = ctx->d >> 8;
+ result[14] = ctx->d >> 16;
+ result[15] = ctx->d >> 24;
+
+ internal_memset(ctx, 0, sizeof(*ctx));
+}
+
+MD5Hash md5_hash(const void *data, uptr size) {
+ MD5Hash res;
+ MD5_CTX ctx;
+ MD5_Init(&ctx);
+ MD5_Update(&ctx, data, size);
+ MD5_Final((unsigned char*)&res.hash[0], &ctx);
+ return res;
+}
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mman.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mman.cpp
new file mode 100644
index 00000000000..0937e521193
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mman.cpp
@@ -0,0 +1,442 @@
+//===-- tsan_mman.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "sanitizer_common/sanitizer_allocator_checks.h"
+#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_errno.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "tsan_mman.h"
+#include "tsan_rtl.h"
+#include "tsan_report.h"
+#include "tsan_flags.h"
+
+namespace __tsan {
+
+struct MapUnmapCallback {
+ void OnMap(uptr p, uptr size) const { }
+ void OnUnmap(uptr p, uptr size) const {
+ // We are about to unmap a chunk of user memory.
+ // Mark the corresponding shadow memory as not needed.
+ DontNeedShadowFor(p, size);
+ // Mark the corresponding meta shadow memory as not needed.
+ // Note the block does not contain any meta info at this point
+ // (this happens after free).
+ const uptr kMetaRatio = kMetaShadowCell / kMetaShadowSize;
+ const uptr kPageSize = GetPageSizeCached() * kMetaRatio;
+ // Block came from LargeMmapAllocator, so must be large.
+ // We rely on this in the calculations below.
+ CHECK_GE(size, 2 * kPageSize);
+ uptr diff = RoundUp(p, kPageSize) - p;
+ if (diff != 0) {
+ p += diff;
+ size -= diff;
+ }
+ diff = p + size - RoundDown(p + size, kPageSize);
+ if (diff != 0)
+ size -= diff;
+ uptr p_meta = (uptr)MemToMeta(p);
+ ReleaseMemoryPagesToOS(p_meta, p_meta + size / kMetaRatio);
+ }
+};
+
+static char allocator_placeholder[sizeof(Allocator)] ALIGNED(64);
+Allocator *allocator() {
+ return reinterpret_cast<Allocator*>(&allocator_placeholder);
+}
+
+struct GlobalProc {
+ Mutex mtx;
+ Processor *proc;
+ // This mutex represents the internal allocator combined for
+ // the purposes of deadlock detection. The internal allocator
+ // uses multiple mutexes, moreover they are locked only occasionally
+ // and they are spin mutexes which don't support deadlock detection.
+ // So we use this fake mutex to serve as a substitute for these mutexes.
+ CheckedMutex internal_alloc_mtx;
+
+ GlobalProc()
+ : mtx(MutexTypeGlobalProc),
+ proc(ProcCreate()),
+ internal_alloc_mtx(MutexTypeInternalAlloc) {}
+};
+
+static char global_proc_placeholder[sizeof(GlobalProc)] ALIGNED(64);
+GlobalProc *global_proc() {
+ return reinterpret_cast<GlobalProc*>(&global_proc_placeholder);
+}
+
+static void InternalAllocAccess() {
+ global_proc()->internal_alloc_mtx.Lock();
+ global_proc()->internal_alloc_mtx.Unlock();
+}
+
+ScopedGlobalProcessor::ScopedGlobalProcessor() {
+ GlobalProc *gp = global_proc();
+ ThreadState *thr = cur_thread();
+ if (thr->proc())
+ return;
+ // If we don't have a proc, use the global one.
+ // There are currently only two known case where this path is triggered:
+ // __interceptor_free
+ // __nptl_deallocate_tsd
+ // start_thread
+ // clone
+ // and:
+ // ResetRange
+ // __interceptor_munmap
+ // __deallocate_stack
+ // start_thread
+ // clone
+ // Ideally, we destroy thread state (and unwire proc) when a thread actually
+ // exits (i.e. when we join/wait it). Then we would not need the global proc
+ gp->mtx.Lock();
+ ProcWire(gp->proc, thr);
+}
+
+ScopedGlobalProcessor::~ScopedGlobalProcessor() {
+ GlobalProc *gp = global_proc();
+ ThreadState *thr = cur_thread();
+ if (thr->proc() != gp->proc)
+ return;
+ ProcUnwire(gp->proc, thr);
+ gp->mtx.Unlock();
+}
+
+void AllocatorLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ global_proc()->internal_alloc_mtx.Lock();
+ InternalAllocatorLock();
+}
+
+void AllocatorUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ InternalAllocatorUnlock();
+ global_proc()->internal_alloc_mtx.Unlock();
+}
+
+void GlobalProcessorLock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ global_proc()->mtx.Lock();
+}
+
+void GlobalProcessorUnlock() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ global_proc()->mtx.Unlock();
+}
+
+static constexpr uptr kMaxAllowedMallocSize = 1ull << 40;
+static uptr max_user_defined_malloc_size;
+
+void InitializeAllocator() {
+ SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null);
+ allocator()->Init(common_flags()->allocator_release_to_os_interval_ms);
+ max_user_defined_malloc_size = common_flags()->max_allocation_size_mb
+ ? common_flags()->max_allocation_size_mb
+ << 20
+ : kMaxAllowedMallocSize;
+}
+
+void InitializeAllocatorLate() {
+ new(global_proc()) GlobalProc();
+}
+
+void AllocatorProcStart(Processor *proc) {
+ allocator()->InitCache(&proc->alloc_cache);
+ internal_allocator()->InitCache(&proc->internal_alloc_cache);
+}
+
+void AllocatorProcFinish(Processor *proc) {
+ allocator()->DestroyCache(&proc->alloc_cache);
+ internal_allocator()->DestroyCache(&proc->internal_alloc_cache);
+}
+
+void AllocatorPrintStats() {
+ allocator()->PrintStats();
+}
+
+static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
+ if (atomic_load_relaxed(&thr->in_signal_handler) == 0 ||
+ !ShouldReport(thr, ReportTypeSignalUnsafe))
+ return;
+ VarSizeStackTrace stack;
+ ObtainCurrentStack(thr, pc, &stack);
+ if (IsFiredSuppression(ctx, ReportTypeSignalUnsafe, stack))
+ return;
+ ThreadRegistryLock l(&ctx->thread_registry);
+ ScopedReport rep(ReportTypeSignalUnsafe);
+ rep.AddStack(stack, true);
+ OutputReport(thr, rep);
+}
+
+
+void *user_alloc_internal(ThreadState *thr, uptr pc, uptr sz, uptr align,
+ bool signal) {
+ if (sz >= kMaxAllowedMallocSize || align >= kMaxAllowedMallocSize ||
+ sz > max_user_defined_malloc_size) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ uptr malloc_limit =
+ Min(kMaxAllowedMallocSize, max_user_defined_malloc_size);
+ GET_STACK_TRACE_FATAL(thr, pc);
+ ReportAllocationSizeTooBig(sz, malloc_limit, &stack);
+ }
+ if (UNLIKELY(IsRssLimitExceeded())) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ GET_STACK_TRACE_FATAL(thr, pc);
+ ReportRssLimitExceeded(&stack);
+ }
+ void *p = allocator()->Allocate(&thr->proc()->alloc_cache, sz, align);
+ if (UNLIKELY(!p)) {
+ SetAllocatorOutOfMemory();
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ GET_STACK_TRACE_FATAL(thr, pc);
+ ReportOutOfMemory(sz, &stack);
+ }
+ if (ctx && ctx->initialized)
+ OnUserAlloc(thr, pc, (uptr)p, sz, true);
+ if (signal)
+ SignalUnsafeCall(thr, pc);
+ return p;
+}
+
+void user_free(ThreadState *thr, uptr pc, void *p, bool signal) {
+ ScopedGlobalProcessor sgp;
+ if (ctx && ctx->initialized)
+ OnUserFree(thr, pc, (uptr)p, true);
+ allocator()->Deallocate(&thr->proc()->alloc_cache, p);
+ if (signal)
+ SignalUnsafeCall(thr, pc);
+}
+
+void *user_alloc(ThreadState *thr, uptr pc, uptr sz) {
+ return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, kDefaultAlignment));
+}
+
+void *user_calloc(ThreadState *thr, uptr pc, uptr size, uptr n) {
+ if (UNLIKELY(CheckForCallocOverflow(size, n))) {
+ if (AllocatorMayReturnNull())
+ return SetErrnoOnNull(nullptr);
+ GET_STACK_TRACE_FATAL(thr, pc);
+ ReportCallocOverflow(n, size, &stack);
+ }
+ void *p = user_alloc_internal(thr, pc, n * size);
+ if (p)
+ internal_memset(p, 0, n * size);
+ return SetErrnoOnNull(p);
+}
+
+void *user_reallocarray(ThreadState *thr, uptr pc, void *p, uptr size, uptr n) {
+ if (UNLIKELY(CheckForCallocOverflow(size, n))) {
+ if (AllocatorMayReturnNull())
+ return SetErrnoOnNull(nullptr);
+ GET_STACK_TRACE_FATAL(thr, pc);
+ ReportReallocArrayOverflow(size, n, &stack);
+ }
+ return user_realloc(thr, pc, p, size * n);
+}
+
+void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write) {
+ DPrintf("#%d: alloc(%zu) = 0x%zx\n", thr->tid, sz, p);
+ // Note: this can run before thread initialization/after finalization.
+ // As a result this is not necessarily synchronized with DoReset,
+ // which iterates over and resets all sync objects,
+ // but it is fine to create new MBlocks in this context.
+ ctx->metamap.AllocBlock(thr, pc, p, sz);
+ // If this runs before thread initialization/after finalization
+ // and we don't have trace initialized, we can't imitate writes.
+ // In such case just reset the shadow range, it is fine since
+ // it affects only a small fraction of special objects.
+ if (write && thr->ignore_reads_and_writes == 0 &&
+ atomic_load_relaxed(&thr->trace_pos))
+ MemoryRangeImitateWrite(thr, pc, (uptr)p, sz);
+ else
+ MemoryResetRange(thr, pc, (uptr)p, sz);
+}
+
+void OnUserFree(ThreadState *thr, uptr pc, uptr p, bool write) {
+ CHECK_NE(p, (void*)0);
+ if (!thr->slot) {
+ // Very early/late in thread lifetime, or during fork.
+ UNUSED uptr sz = ctx->metamap.FreeBlock(thr->proc(), p, false);
+ DPrintf("#%d: free(0x%zx, %zu) (no slot)\n", thr->tid, p, sz);
+ return;
+ }
+ SlotLocker locker(thr);
+ uptr sz = ctx->metamap.FreeBlock(thr->proc(), p, true);
+ DPrintf("#%d: free(0x%zx, %zu)\n", thr->tid, p, sz);
+ if (write && thr->ignore_reads_and_writes == 0)
+ MemoryRangeFreed(thr, pc, (uptr)p, sz);
+}
+
+void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz) {
+ // FIXME: Handle "shrinking" more efficiently,
+ // it seems that some software actually does this.
+ if (!p)
+ return SetErrnoOnNull(user_alloc_internal(thr, pc, sz));
+ if (!sz) {
+ user_free(thr, pc, p);
+ return nullptr;
+ }
+ void *new_p = user_alloc_internal(thr, pc, sz);
+ if (new_p) {
+ uptr old_sz = user_alloc_usable_size(p);
+ internal_memcpy(new_p, p, min(old_sz, sz));
+ user_free(thr, pc, p);
+ }
+ return SetErrnoOnNull(new_p);
+}
+
+void *user_memalign(ThreadState *thr, uptr pc, uptr align, uptr sz) {
+ if (UNLIKELY(!IsPowerOfTwo(align))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ GET_STACK_TRACE_FATAL(thr, pc);
+ ReportInvalidAllocationAlignment(align, &stack);
+ }
+ return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, align));
+}
+
+int user_posix_memalign(ThreadState *thr, uptr pc, void **memptr, uptr align,
+ uptr sz) {
+ if (UNLIKELY(!CheckPosixMemalignAlignment(align))) {
+ if (AllocatorMayReturnNull())
+ return errno_EINVAL;
+ GET_STACK_TRACE_FATAL(thr, pc);
+ ReportInvalidPosixMemalignAlignment(align, &stack);
+ }
+ void *ptr = user_alloc_internal(thr, pc, sz, align);
+ if (UNLIKELY(!ptr))
+ // OOM error is already taken care of by user_alloc_internal.
+ return errno_ENOMEM;
+ CHECK(IsAligned((uptr)ptr, align));
+ *memptr = ptr;
+ return 0;
+}
+
+void *user_aligned_alloc(ThreadState *thr, uptr pc, uptr align, uptr sz) {
+ if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(align, sz))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ GET_STACK_TRACE_FATAL(thr, pc);
+ ReportInvalidAlignedAllocAlignment(sz, align, &stack);
+ }
+ return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, align));
+}
+
+void *user_valloc(ThreadState *thr, uptr pc, uptr sz) {
+ return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, GetPageSizeCached()));
+}
+
+void *user_pvalloc(ThreadState *thr, uptr pc, uptr sz) {
+ uptr PageSize = GetPageSizeCached();
+ if (UNLIKELY(CheckForPvallocOverflow(sz, PageSize))) {
+ errno = errno_ENOMEM;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ GET_STACK_TRACE_FATAL(thr, pc);
+ ReportPvallocOverflow(sz, &stack);
+ }
+ // pvalloc(0) should allocate one page.
+ sz = sz ? RoundUpTo(sz, PageSize) : PageSize;
+ return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, PageSize));
+}
+
+uptr user_alloc_usable_size(const void *p) {
+ if (p == 0 || !IsAppMem((uptr)p))
+ return 0;
+ MBlock *b = ctx->metamap.GetBlock((uptr)p);
+ if (!b)
+ return 0; // Not a valid pointer.
+ if (b->siz == 0)
+ return 1; // Zero-sized allocations are actually 1 byte.
+ return b->siz;
+}
+
+void invoke_malloc_hook(void *ptr, uptr size) {
+ ThreadState *thr = cur_thread();
+ if (ctx == 0 || !ctx->initialized || thr->ignore_interceptors)
+ return;
+ RunMallocHooks(ptr, size);
+}
+
+void invoke_free_hook(void *ptr) {
+ ThreadState *thr = cur_thread();
+ if (ctx == 0 || !ctx->initialized || thr->ignore_interceptors)
+ return;
+ RunFreeHooks(ptr);
+}
+
+void *Alloc(uptr sz) {
+ ThreadState *thr = cur_thread();
+ if (thr->nomalloc) {
+ thr->nomalloc = 0; // CHECK calls internal_malloc().
+ CHECK(0);
+ }
+ InternalAllocAccess();
+ return InternalAlloc(sz, &thr->proc()->internal_alloc_cache);
+}
+
+void FreeImpl(void *p) {
+ ThreadState *thr = cur_thread();
+ if (thr->nomalloc) {
+ thr->nomalloc = 0; // CHECK calls internal_malloc().
+ CHECK(0);
+ }
+ InternalAllocAccess();
+ InternalFree(p, &thr->proc()->internal_alloc_cache);
+}
+
+} // namespace __tsan
+
+using namespace __tsan;
+
+extern "C" {
+uptr __sanitizer_get_current_allocated_bytes() {
+ uptr stats[AllocatorStatCount];
+ allocator()->GetStats(stats);
+ return stats[AllocatorStatAllocated];
+}
+
+uptr __sanitizer_get_heap_size() {
+ uptr stats[AllocatorStatCount];
+ allocator()->GetStats(stats);
+ return stats[AllocatorStatMapped];
+}
+
+uptr __sanitizer_get_free_bytes() {
+ return 1;
+}
+
+uptr __sanitizer_get_unmapped_bytes() {
+ return 1;
+}
+
+uptr __sanitizer_get_estimated_allocated_size(uptr size) {
+ return size;
+}
+
+int __sanitizer_get_ownership(const void *p) {
+ return allocator()->GetBlockBegin(p) != 0;
+}
+
+uptr __sanitizer_get_allocated_size(const void *p) {
+ return user_alloc_usable_size(p);
+}
+
+void __tsan_on_thread_idle() {
+ ThreadState *thr = cur_thread();
+ allocator()->SwallowCache(&thr->proc()->alloc_cache);
+ internal_allocator()->SwallowCache(&thr->proc()->internal_alloc_cache);
+ ctx->metamap.OnProcIdle(thr->proc());
+}
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mman.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mman.h
new file mode 100644
index 00000000000..2095f28c025
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mman.h
@@ -0,0 +1,80 @@
+//===-- tsan_mman.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_MMAN_H
+#define TSAN_MMAN_H
+
+#include "tsan_defs.h"
+
+namespace __tsan {
+
+const uptr kDefaultAlignment = 16;
+
+void InitializeAllocator();
+void InitializeAllocatorLate();
+void ReplaceSystemMalloc();
+void AllocatorProcStart(Processor *proc);
+void AllocatorProcFinish(Processor *proc);
+void AllocatorPrintStats();
+void AllocatorLock();
+void AllocatorUnlock();
+void GlobalProcessorLock();
+void GlobalProcessorUnlock();
+
+// For user allocations.
+void *user_alloc_internal(ThreadState *thr, uptr pc, uptr sz,
+ uptr align = kDefaultAlignment, bool signal = true);
+// Does not accept NULL.
+void user_free(ThreadState *thr, uptr pc, void *p, bool signal = true);
+// Interceptor implementations.
+void *user_alloc(ThreadState *thr, uptr pc, uptr sz);
+void *user_calloc(ThreadState *thr, uptr pc, uptr sz, uptr n);
+void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz);
+void *user_reallocarray(ThreadState *thr, uptr pc, void *p, uptr sz, uptr n);
+void *user_memalign(ThreadState *thr, uptr pc, uptr align, uptr sz);
+int user_posix_memalign(ThreadState *thr, uptr pc, void **memptr, uptr align,
+ uptr sz);
+void *user_aligned_alloc(ThreadState *thr, uptr pc, uptr align, uptr sz);
+void *user_valloc(ThreadState *thr, uptr pc, uptr sz);
+void *user_pvalloc(ThreadState *thr, uptr pc, uptr sz);
+uptr user_alloc_usable_size(const void *p);
+
+// Invoking malloc/free hooks that may be installed by the user.
+void invoke_malloc_hook(void *ptr, uptr size);
+void invoke_free_hook(void *ptr);
+
+// For internal data structures.
+void *Alloc(uptr sz);
+void FreeImpl(void *p);
+
+template <typename T, typename... Args>
+T *New(Args &&...args) {
+ return new (Alloc(sizeof(T))) T(static_cast<Args &&>(args)...);
+}
+
+template <typename T>
+void Free(T *&p) {
+ if (p == nullptr)
+ return;
+ FreeImpl(p);
+ p = nullptr;
+}
+
+template <typename T>
+void DestroyAndFree(T *&p) {
+ if (p == nullptr)
+ return;
+ p->~T();
+ Free(p);
+}
+
+} // namespace __tsan
+#endif // TSAN_MMAN_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mutexset.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mutexset.cpp
new file mode 100644
index 00000000000..3a75b80ac30
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mutexset.cpp
@@ -0,0 +1,80 @@
+//===-- tsan_mutexset.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_mutexset.h"
+
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "tsan_rtl.h"
+
+namespace __tsan {
+
+MutexSet::MutexSet() {
+}
+
+void MutexSet::Reset() { internal_memset(this, 0, sizeof(*this)); }
+
+void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {
+ // Look up existing mutex with the same id.
+ for (uptr i = 0; i < size_; i++) {
+ if (descs_[i].addr == addr) {
+ descs_[i].count++;
+ descs_[i].seq = seq_++;
+ return;
+ }
+ }
+ // On overflow, find the oldest mutex and drop it.
+ if (size_ == kMaxSize) {
+ uptr min = 0;
+ for (uptr i = 0; i < size_; i++) {
+ if (descs_[i].seq < descs_[min].seq)
+ min = i;
+ }
+ RemovePos(min);
+ CHECK_EQ(size_, kMaxSize - 1);
+ }
+ // Add new mutex descriptor.
+ descs_[size_].addr = addr;
+ descs_[size_].stack_id = stack_id;
+ descs_[size_].write = write;
+ descs_[size_].seq = seq_++;
+ descs_[size_].count = 1;
+ size_++;
+}
+
+void MutexSet::DelAddr(uptr addr, bool destroy) {
+ for (uptr i = 0; i < size_; i++) {
+ if (descs_[i].addr == addr) {
+ if (destroy || --descs_[i].count == 0)
+ RemovePos(i);
+ return;
+ }
+ }
+}
+
+void MutexSet::RemovePos(uptr i) {
+ CHECK_LT(i, size_);
+ descs_[i] = descs_[size_ - 1];
+ size_--;
+}
+
+uptr MutexSet::Size() const {
+ return size_;
+}
+
+MutexSet::Desc MutexSet::Get(uptr i) const {
+ CHECK_LT(i, size_);
+ return descs_[i];
+}
+
+DynamicMutexSet::DynamicMutexSet() : ptr_(New<MutexSet>()) {}
+DynamicMutexSet::~DynamicMutexSet() { DestroyAndFree(ptr_); }
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mutexset.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mutexset.h
new file mode 100644
index 00000000000..aabd361e6af
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_mutexset.h
@@ -0,0 +1,91 @@
+//===-- tsan_mutexset.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// MutexSet holds the set of mutexes currently held by a thread.
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_MUTEXSET_H
+#define TSAN_MUTEXSET_H
+
+#include "tsan_defs.h"
+
+namespace __tsan {
+
+class MutexSet {
+ public:
+ // Holds limited number of mutexes.
+ // The oldest mutexes are discarded on overflow.
+ static constexpr uptr kMaxSize = 16;
+ struct Desc {
+ uptr addr;
+ StackID stack_id;
+ u32 seq;
+ u32 count;
+ bool write;
+
+ Desc() { internal_memset(this, 0, sizeof(*this)); }
+ Desc(const Desc& other) { *this = other; }
+ Desc& operator=(const MutexSet::Desc& other) {
+ internal_memcpy(this, &other, sizeof(*this));
+ return *this;
+ }
+ };
+
+ MutexSet();
+ void Reset();
+ void AddAddr(uptr addr, StackID stack_id, bool write);
+ void DelAddr(uptr addr, bool destroy = false);
+ uptr Size() const;
+ Desc Get(uptr i) const;
+
+ private:
+#if !SANITIZER_GO
+ u32 seq_ = 0;
+ uptr size_ = 0;
+ Desc descs_[kMaxSize];
+
+ void RemovePos(uptr i);
+#endif
+};
+
+// MutexSet is too large to live on stack.
+// DynamicMutexSet can be use used to create local MutexSet's.
+class DynamicMutexSet {
+ public:
+ DynamicMutexSet();
+ ~DynamicMutexSet();
+ MutexSet* operator->() { return ptr_; }
+ operator MutexSet*() { return ptr_; }
+ DynamicMutexSet(const DynamicMutexSet&) = delete;
+ DynamicMutexSet& operator=(const DynamicMutexSet&) = delete;
+
+ private:
+ MutexSet* ptr_;
+#if SANITIZER_GO
+ MutexSet set_;
+#endif
+};
+
+// Go does not have mutexes, so do not spend memory and time.
+// (Go sync.Mutex is actually a semaphore -- can be unlocked
+// in different goroutine).
+#if SANITIZER_GO
+MutexSet::MutexSet() {}
+void MutexSet::Reset() {}
+void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {}
+void MutexSet::DelAddr(uptr addr, bool destroy) {}
+uptr MutexSet::Size() const { return 0; }
+MutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); }
+DynamicMutexSet::DynamicMutexSet() : ptr_(&set_) {}
+DynamicMutexSet::~DynamicMutexSet() {}
+#endif
+
+} // namespace __tsan
+
+#endif // TSAN_MUTEXSET_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_new_delete.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_new_delete.cpp
new file mode 100644
index 00000000000..fc44a5221b5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_new_delete.cpp
@@ -0,0 +1,199 @@
+//===-- tsan_new_delete.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Interceptors for operators new and delete.
+//===----------------------------------------------------------------------===//
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "tsan_interceptors.h"
+#include "tsan_rtl.h"
+
+using namespace __tsan;
+
+namespace std {
+struct nothrow_t {};
+enum class align_val_t: __sanitizer::uptr {};
+} // namespace std
+
+DECLARE_REAL(void *, malloc, uptr size)
+DECLARE_REAL(void, free, void *ptr)
+
+// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
+#define OPERATOR_NEW_BODY(mangled_name, nothrow) \
+ if (in_symbolizer()) \
+ return InternalAlloc(size); \
+ void *p = 0; \
+ { \
+ SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
+ p = user_alloc(thr, pc, size); \
+ if (!nothrow && UNLIKELY(!p)) { \
+ GET_STACK_TRACE_FATAL(thr, pc); \
+ ReportOutOfMemory(size, &stack); \
+ } \
+ } \
+ invoke_malloc_hook(p, size); \
+ return p;
+
+#define OPERATOR_NEW_BODY_ALIGN(mangled_name, nothrow) \
+ if (in_symbolizer()) \
+ return InternalAlloc(size, nullptr, (uptr)align); \
+ void *p = 0; \
+ { \
+ SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
+ p = user_memalign(thr, pc, (uptr)align, size); \
+ if (!nothrow && UNLIKELY(!p)) { \
+ GET_STACK_TRACE_FATAL(thr, pc); \
+ ReportOutOfMemory(size, &stack); \
+ } \
+ } \
+ invoke_malloc_hook(p, size); \
+ return p;
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new(__sanitizer::uptr size);
+void *operator new(__sanitizer::uptr size) {
+ OPERATOR_NEW_BODY(_Znwm, false /*nothrow*/);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new[](__sanitizer::uptr size);
+void *operator new[](__sanitizer::uptr size) {
+ OPERATOR_NEW_BODY(_Znam, false /*nothrow*/);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new(__sanitizer::uptr size, std::nothrow_t const&);
+void *operator new(__sanitizer::uptr size, std::nothrow_t const&) {
+ OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t, true /*nothrow*/);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new[](__sanitizer::uptr size, std::nothrow_t const&);
+void *operator new[](__sanitizer::uptr size, std::nothrow_t const&) {
+ OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t, true /*nothrow*/);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new(__sanitizer::uptr size, std::align_val_t align);
+void *operator new(__sanitizer::uptr size, std::align_val_t align) {
+ OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_t, false /*nothrow*/);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new[](__sanitizer::uptr size, std::align_val_t align);
+void *operator new[](__sanitizer::uptr size, std::align_val_t align) {
+ OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_t, false /*nothrow*/);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new(__sanitizer::uptr size, std::align_val_t align,
+ std::nothrow_t const&);
+void *operator new(__sanitizer::uptr size, std::align_val_t align,
+ std::nothrow_t const&) {
+ OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_tRKSt9nothrow_t,
+ true /*nothrow*/);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new[](__sanitizer::uptr size, std::align_val_t align,
+ std::nothrow_t const&);
+void *operator new[](__sanitizer::uptr size, std::align_val_t align,
+ std::nothrow_t const&) {
+ OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_tRKSt9nothrow_t,
+ true /*nothrow*/);
+}
+
+#define OPERATOR_DELETE_BODY(mangled_name) \
+ if (ptr == 0) return; \
+ if (in_symbolizer()) \
+ return InternalFree(ptr); \
+ invoke_free_hook(ptr); \
+ SCOPED_INTERCEPTOR_RAW(mangled_name, ptr); \
+ user_free(thr, pc, ptr);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr) NOEXCEPT;
+void operator delete(void *ptr) NOEXCEPT {
+ OPERATOR_DELETE_BODY(_ZdlPv);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr) NOEXCEPT;
+void operator delete[](void *ptr) NOEXCEPT {
+ OPERATOR_DELETE_BODY(_ZdaPv);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr, std::nothrow_t const&);
+void operator delete(void *ptr, std::nothrow_t const&) {
+ OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr, std::nothrow_t const&);
+void operator delete[](void *ptr, std::nothrow_t const&) {
+ OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT;
+void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT {
+ OPERATOR_DELETE_BODY(_ZdlPvm);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT;
+void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT {
+ OPERATOR_DELETE_BODY(_ZdaPvm);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align) NOEXCEPT;
+void operator delete(void *ptr, std::align_val_t align) NOEXCEPT {
+ OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT;
+void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
+ OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&);
+void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&) {
+ OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_tRKSt9nothrow_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr, std::align_val_t align,
+ std::nothrow_t const&);
+void operator delete[](void *ptr, std::align_val_t align,
+ std::nothrow_t const&) {
+ OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_tRKSt9nothrow_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr, __sanitizer::uptr size,
+ std::align_val_t align) NOEXCEPT;
+void operator delete(void *ptr, __sanitizer::uptr size,
+ std::align_val_t align) NOEXCEPT {
+ OPERATOR_DELETE_BODY(_ZdlPvmSt11align_val_t);
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr, __sanitizer::uptr size,
+ std::align_val_t align) NOEXCEPT;
+void operator delete[](void *ptr, __sanitizer::uptr size,
+ std::align_val_t align) NOEXCEPT {
+ OPERATOR_DELETE_BODY(_ZdaPvmSt11align_val_t);
+}
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform.h
new file mode 100644
index 00000000000..5a92187f143
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform.h
@@ -0,0 +1,938 @@
+//===-- tsan_platform.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Platform-specific code.
+//===----------------------------------------------------------------------===//
+
+#ifndef TSAN_PLATFORM_H
+#define TSAN_PLATFORM_H
+
+#if !defined(__LP64__) && !defined(_WIN64)
+# error "Only 64-bit is supported"
+#endif
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "tsan_defs.h"
+
+namespace __tsan {
+
+enum {
+ // App memory is not mapped onto shadow memory range.
+ kBrokenMapping = 1 << 0,
+ // Mapping app memory and back does not produce the same address,
+ // this can lead to wrong addresses in reports and potentially
+ // other bad consequences.
+ kBrokenReverseMapping = 1 << 1,
+ // Mapping is non-linear for linear user range.
+ // This is bad and can lead to unpredictable memory corruptions, etc
+ // because range access functions assume linearity.
+ kBrokenLinearity = 1 << 2,
+ // Meta for an app region overlaps with the meta of another app region.
+ // This is determined by recomputing the individual meta regions for
+ // each app region.
+ //
+ // N.B. There is no "kBrokenReverseMetaMapping" constant because there
+ // is no MetaToMem function. However, note that (!kBrokenLinearity
+ // && !kBrokenAliasedMetas) implies that MemToMeta is invertible.
+ kBrokenAliasedMetas = 1 << 3,
+};
+
+/*
+C/C++ on linux/x86_64 and freebsd/x86_64
+0000 0000 1000 - 0080 0000 0000: main binary and/or MAP_32BIT mappings (512GB)
+0040 0000 0000 - 0100 0000 0000: -
+0100 0000 0000 - 1000 0000 0000: shadow
+1000 0000 0000 - 3000 0000 0000: -
+3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
+4000 0000 0000 - 5500 0000 0000: -
+5500 0000 0000 - 5680 0000 0000: pie binaries without ASLR or on 4.1+ kernels
+5680 0000 0000 - 7d00 0000 0000: -
+7b00 0000 0000 - 7c00 0000 0000: heap
+7c00 0000 0000 - 7e80 0000 0000: -
+7e80 0000 0000 - 8000 0000 0000: modules and main thread stack
+
+C/C++ on netbsd/amd64 can reuse the same mapping:
+ * The address space starts from 0x1000 (option with 0x0) and ends with
+ 0x7f7ffffff000.
+ * LoAppMem-kHeapMemEnd can be reused as it is.
+ * No VDSO support.
+ * No MidAppMem region.
+ * No additional HeapMem region.
+ * HiAppMem contains the stack, loader, shared libraries and heap.
+ * Stack on NetBSD/amd64 has prereserved 128MB.
+ * Heap grows downwards (top-down).
+ * ASLR must be disabled per-process or globally.
+*/
+struct Mapping48AddressSpace {
+ static const uptr kMetaShadowBeg = 0x300000000000ull;
+ static const uptr kMetaShadowEnd = 0x340000000000ull;
+ static const uptr kShadowBeg = 0x010000000000ull;
+ static const uptr kShadowEnd = 0x100000000000ull;
+ static const uptr kHeapMemBeg = 0x7b0000000000ull;
+ static const uptr kHeapMemEnd = 0x7c0000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x008000000000ull;
+ static const uptr kMidAppMemBeg = 0x550000000000ull;
+ static const uptr kMidAppMemEnd = 0x568000000000ull;
+ static const uptr kHiAppMemBeg = 0x7e8000000000ull;
+ static const uptr kHiAppMemEnd = 0x800000000000ull;
+ static const uptr kShadowMsk = 0x780000000000ull;
+ static const uptr kShadowXor = 0x040000000000ull;
+ static const uptr kShadowAdd = 0x000000000000ull;
+ static const uptr kVdsoBeg = 0xf000000000000000ull;
+};
+
+/*
+C/C++ on linux/mips64 (40-bit VMA)
+0000 0000 00 - 0100 0000 00: - (4 GB)
+0100 0000 00 - 0200 0000 00: main binary (4 GB)
+0200 0000 00 - 1200 0000 00: - (64 GB)
+1200 0000 00 - 2200 0000 00: shadow (64 GB)
+2200 0000 00 - 4000 0000 00: - (120 GB)
+4000 0000 00 - 5000 0000 00: metainfo (memory blocks and sync objects) (64 GB)
+5000 0000 00 - aa00 0000 00: - (360 GB)
+aa00 0000 00 - ab00 0000 00: main binary (PIE) (4 GB)
+ab00 0000 00 - fe00 0000 00: - (332 GB)
+fe00 0000 00 - ff00 0000 00: heap (4 GB)
+ff00 0000 00 - ff80 0000 00: - (2 GB)
+ff80 0000 00 - ffff ffff ff: modules and main thread stack (<2 GB)
+*/
+struct MappingMips64_40 {
+ static const uptr kMetaShadowBeg = 0x4000000000ull;
+ static const uptr kMetaShadowEnd = 0x5000000000ull;
+ static const uptr kShadowBeg = 0x1200000000ull;
+ static const uptr kShadowEnd = 0x2200000000ull;
+ static const uptr kHeapMemBeg = 0xfe00000000ull;
+ static const uptr kHeapMemEnd = 0xff00000000ull;
+ static const uptr kLoAppMemBeg = 0x0100000000ull;
+ static const uptr kLoAppMemEnd = 0x0200000000ull;
+ static const uptr kMidAppMemBeg = 0xaa00000000ull;
+ static const uptr kMidAppMemEnd = 0xab00000000ull;
+ static const uptr kHiAppMemBeg = 0xff80000000ull;
+ static const uptr kHiAppMemEnd = 0xffffffffffull;
+ static const uptr kShadowMsk = 0xf800000000ull;
+ static const uptr kShadowXor = 0x0800000000ull;
+ static const uptr kShadowAdd = 0x0000000000ull;
+ static const uptr kVdsoBeg = 0xfffff00000ull;
+};
+
+/*
+C/C++ on Darwin/iOS/ARM64 (36-bit VMA, 64 GB VM)
+0000 0000 00 - 0100 0000 00: - (4 GB)
+0100 0000 00 - 0200 0000 00: main binary, modules, thread stacks (4 GB)
+0200 0000 00 - 0300 0000 00: heap (4 GB)
+0300 0000 00 - 0400 0000 00: - (4 GB)
+0400 0000 00 - 0800 0000 00: shadow memory (16 GB)
+0800 0000 00 - 0d00 0000 00: - (20 GB)
+0d00 0000 00 - 0e00 0000 00: metainfo (4 GB)
+0e00 0000 00 - 1000 0000 00: -
+*/
+struct MappingAppleAarch64 {
+ static const uptr kLoAppMemBeg = 0x0100000000ull;
+ static const uptr kLoAppMemEnd = 0x0200000000ull;
+ static const uptr kHeapMemBeg = 0x0200000000ull;
+ static const uptr kHeapMemEnd = 0x0300000000ull;
+ static const uptr kShadowBeg = 0x0400000000ull;
+ static const uptr kShadowEnd = 0x0800000000ull;
+ static const uptr kMetaShadowBeg = 0x0d00000000ull;
+ static const uptr kMetaShadowEnd = 0x0e00000000ull;
+ static const uptr kHiAppMemBeg = 0x0fc0000000ull;
+ static const uptr kHiAppMemEnd = 0x0fc0000000ull;
+ static const uptr kShadowMsk = 0x0ull;
+ static const uptr kShadowXor = 0x0ull;
+ static const uptr kShadowAdd = 0x0200000000ull;
+ static const uptr kVdsoBeg = 0x7000000000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+};
+
+/*
+C/C++ on linux/aarch64 (39-bit VMA)
+0000 0010 00 - 0500 0000 00: main binary (20 GB)
+0100 0000 00 - 2000 0000 00: -
+2000 0000 00 - 4000 0000 00: shadow memory (128 GB)
+4000 0000 00 - 4800 0000 00: metainfo (32 GB)
+4800 0000 00 - 5500 0000 00: -
+5500 0000 00 - 5a00 0000 00: main binary (PIE) (20 GB)
+5600 0000 00 - 7c00 0000 00: -
+7a00 0000 00 - 7d00 0000 00: heap (12 GB)
+7d00 0000 00 - 7fff ffff ff: modules and main thread stack (12 GB)
+*/
+struct MappingAarch64_39 {
+ static const uptr kLoAppMemBeg = 0x0000001000ull;
+ static const uptr kLoAppMemEnd = 0x0500000000ull;
+ static const uptr kShadowBeg = 0x2000000000ull;
+ static const uptr kShadowEnd = 0x4000000000ull;
+ static const uptr kMetaShadowBeg = 0x4000000000ull;
+ static const uptr kMetaShadowEnd = 0x4800000000ull;
+ static const uptr kMidAppMemBeg = 0x5500000000ull;
+ static const uptr kMidAppMemEnd = 0x5a00000000ull;
+ static const uptr kHeapMemBeg = 0x7a00000000ull;
+ static const uptr kHeapMemEnd = 0x7d00000000ull;
+ static const uptr kHiAppMemBeg = 0x7d00000000ull;
+ static const uptr kHiAppMemEnd = 0x7fffffffffull;
+ static const uptr kShadowMsk = 0x7000000000ull;
+ static const uptr kShadowXor = 0x1000000000ull;
+ static const uptr kShadowAdd = 0x0000000000ull;
+ static const uptr kVdsoBeg = 0x7f00000000ull;
+};
+
+/*
+C/C++ on linux/aarch64 (42-bit VMA)
+00000 0010 00 - 02000 0000 00: main binary (128 GB)
+02000 0000 00 - 08000 0000 00: -
+10000 0000 00 - 20000 0000 00: shadow memory (1024 GB)
+20000 0000 00 - 24000 0000 00: metainfo (256 GB)
+24000 0000 00 - 2aa00 0000 00: -
+2aa00 0000 00 - 2c000 0000 00: main binary (PIE) (88 GB)
+2c000 0000 00 - 3c000 0000 00: -
+3c000 0000 00 - 3f000 0000 00: heap (192 GB)
+3f000 0000 00 - 3ffff ffff ff: modules and main thread stack (64 GB)
+*/
+struct MappingAarch64_42 {
+ static const uptr kLoAppMemBeg = 0x00000001000ull;
+ static const uptr kLoAppMemEnd = 0x02000000000ull;
+ static const uptr kShadowBeg = 0x10000000000ull;
+ static const uptr kShadowEnd = 0x20000000000ull;
+ static const uptr kMetaShadowBeg = 0x20000000000ull;
+ static const uptr kMetaShadowEnd = 0x24000000000ull;
+ static const uptr kMidAppMemBeg = 0x2aa00000000ull;
+ static const uptr kMidAppMemEnd = 0x2c000000000ull;
+ static const uptr kHeapMemBeg = 0x3c000000000ull;
+ static const uptr kHeapMemEnd = 0x3f000000000ull;
+ static const uptr kHiAppMemBeg = 0x3f000000000ull;
+ static const uptr kHiAppMemEnd = 0x3ffffffffffull;
+ static const uptr kShadowMsk = 0x38000000000ull;
+ static const uptr kShadowXor = 0x08000000000ull;
+ static const uptr kShadowAdd = 0x00000000000ull;
+ static const uptr kVdsoBeg = 0x37f00000000ull;
+};
+
+/*
+C/C++ on linux/aarch64 (48-bit VMA)
+0000 0000 1000 - 0a00 0000 0000: main binary (10240 GB)
+0a00 0000 1000 - 1554 0000 0000: -
+1554 0000 1000 - 5400 0000 0000: shadow memory (64176 GB)
+5400 0000 1000 - 8000 0000 0000: -
+8000 0000 1000 - 0a00 0000 0000: metainfo (32768 GB)
+a000 0000 1000 - aaaa 0000 0000: -
+aaaa 0000 1000 - ac00 0000 0000: main binary (PIE) (1368 GB)
+ac00 0000 1000 - fc00 0000 0000: -
+fc00 0000 1000 - ffff ffff ffff: modules and main thread stack (4096 GB)
+
+N.B. the shadow memory region has a strange start address, because it
+contains the shadows for the mid, high and low app regions (in this
+unusual order).
+*/
+struct MappingAarch64_48 {
+ static const uptr kLoAppMemBeg = 0x0000000001000ull;
+ static const uptr kLoAppMemEnd = 0x00a0000000000ull;
+ static const uptr kShadowBeg = 0x0155400000000ull;
+ static const uptr kShadowEnd = 0x0540000000000ull;
+ static const uptr kMetaShadowBeg = 0x0800000000000ull;
+ static const uptr kMetaShadowEnd = 0x0a00000000000ull;
+ static const uptr kMidAppMemBeg = 0x0aaaa00000000ull;
+ static const uptr kMidAppMemEnd = 0x0ac0000000000ull;
+ static const uptr kHiAppMemBeg = 0x0fc0000000000ull;
+ static const uptr kHiAppMemEnd = 0x1000000000000ull;
+ static const uptr kHeapMemBeg = 0x0fc0000000000ull;
+ static const uptr kHeapMemEnd = 0x0fc0000000000ull;
+ static const uptr kShadowMsk = 0x0c00000000000ull;
+ static const uptr kShadowXor = 0x0200000000000ull;
+ static const uptr kShadowAdd = 0x0000000000000ull;
+ static const uptr kVdsoBeg = 0xffff000000000ull;
+};
+
+/* C/C++ on linux/loongarch64 (47-bit VMA)
+0000 0000 4000 - 0080 0000 0000: main binary
+0080 0000 0000 - 0100 0000 0000: -
+0100 0000 0000 - 1000 0000 0000: shadow memory
+1000 0000 0000 - 3000 0000 0000: -
+3000 0000 0000 - 3400 0000 0000: metainfo
+3400 0000 0000 - 5555 0000 0000: -
+5555 0000 0000 - 5556 0000 0000: main binary (PIE)
+5556 0000 0000 - 7ffe 0000 0000: -
+7ffe 0000 0000 - 7fff 0000 0000: heap
+7fff 0000 0000 - 7fff 8000 0000: -
+7fff 8000 0000 - 8000 0000 0000: modules and main thread stack
+*/
+struct MappingLoongArch64_47 {
+ static const uptr kMetaShadowBeg = 0x300000000000ull;
+ static const uptr kMetaShadowEnd = 0x340000000000ull;
+ static const uptr kShadowBeg = 0x010000000000ull;
+ static const uptr kShadowEnd = 0x100000000000ull;
+ static const uptr kHeapMemBeg = 0x7ffe00000000ull;
+ static const uptr kHeapMemEnd = 0x7fff00000000ull;
+ static const uptr kLoAppMemBeg = 0x000000004000ull;
+ static const uptr kLoAppMemEnd = 0x008000000000ull;
+ static const uptr kMidAppMemBeg = 0x555500000000ull;
+ static const uptr kMidAppMemEnd = 0x555600000000ull;
+ static const uptr kHiAppMemBeg = 0x7fff80000000ull;
+ static const uptr kHiAppMemEnd = 0x800000000000ull;
+ static const uptr kShadowMsk = 0x780000000000ull;
+ static const uptr kShadowXor = 0x040000000000ull;
+ static const uptr kShadowAdd = 0x000000000000ull;
+ static const uptr kVdsoBeg = 0x7fffffffc000ull;
+};
+
+/*
+C/C++ on linux/powerpc64 (44-bit VMA)
+0000 0000 0100 - 0001 0000 0000: main binary
+0001 0000 0000 - 0001 0000 0000: -
+0001 0000 0000 - 0b00 0000 0000: shadow
+0b00 0000 0000 - 0b00 0000 0000: -
+0b00 0000 0000 - 0d00 0000 0000: metainfo (memory blocks and sync objects)
+0d00 0000 0000 - 0f00 0000 0000: -
+0f00 0000 0000 - 0f50 0000 0000: heap
+0f50 0000 0000 - 0f60 0000 0000: -
+0f60 0000 0000 - 1000 0000 0000: modules and main thread stack
+*/
+struct MappingPPC64_44 {
+ static const uptr kBroken = kBrokenMapping | kBrokenReverseMapping |
+ kBrokenLinearity | kBrokenAliasedMetas;
+ static const uptr kMetaShadowBeg = 0x0b0000000000ull;
+ static const uptr kMetaShadowEnd = 0x0d0000000000ull;
+ static const uptr kShadowBeg = 0x000100000000ull;
+ static const uptr kShadowEnd = 0x0b0000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000000100ull;
+ static const uptr kLoAppMemEnd = 0x000100000000ull;
+ static const uptr kHeapMemBeg = 0x0f0000000000ull;
+ static const uptr kHeapMemEnd = 0x0f5000000000ull;
+ static const uptr kHiAppMemBeg = 0x0f6000000000ull;
+ static const uptr kHiAppMemEnd = 0x100000000000ull; // 44 bits
+ static const uptr kShadowMsk = 0x0f0000000000ull;
+ static const uptr kShadowXor = 0x002100000000ull;
+ static const uptr kShadowAdd = 0x000000000000ull;
+ static const uptr kVdsoBeg = 0x3c0000000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+};
+
+/*
+C/C++ on linux/powerpc64 (46-bit VMA)
+0000 0000 1000 - 0100 0000 0000: main binary
+0100 0000 0000 - 0200 0000 0000: -
+0100 0000 0000 - 0800 0000 0000: shadow
+0800 0000 0000 - 1000 0000 0000: -
+1000 0000 0000 - 1200 0000 0000: metainfo (memory blocks and sync objects)
+1200 0000 0000 - 3d00 0000 0000: -
+3d00 0000 0000 - 3e00 0000 0000: heap
+3e00 0000 0000 - 3e80 0000 0000: -
+3e80 0000 0000 - 4000 0000 0000: modules and main thread stack
+*/
+struct MappingPPC64_46 {
+ static const uptr kMetaShadowBeg = 0x100000000000ull;
+ static const uptr kMetaShadowEnd = 0x120000000000ull;
+ static const uptr kShadowBeg = 0x010000000000ull;
+ static const uptr kShadowEnd = 0x080000000000ull;
+ static const uptr kHeapMemBeg = 0x3d0000000000ull;
+ static const uptr kHeapMemEnd = 0x3e0000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x010000000000ull;
+ static const uptr kHiAppMemBeg = 0x3e8000000000ull;
+ static const uptr kHiAppMemEnd = 0x400000000000ull; // 46 bits
+ static const uptr kShadowMsk = 0x3c0000000000ull;
+ static const uptr kShadowXor = 0x020000000000ull;
+ static const uptr kShadowAdd = 0x000000000000ull;
+ static const uptr kVdsoBeg = 0x7800000000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+};
+
+/*
+C/C++ on linux/powerpc64 (47-bit VMA)
+0000 0000 1000 - 0100 0000 0000: main binary
+0100 0000 0000 - 0200 0000 0000: -
+0100 0000 0000 - 0800 0000 0000: shadow
+0800 0000 0000 - 1000 0000 0000: -
+1000 0000 0000 - 1200 0000 0000: metainfo (memory blocks and sync objects)
+1200 0000 0000 - 7d00 0000 0000: -
+7d00 0000 0000 - 7e00 0000 0000: heap
+7e00 0000 0000 - 7e80 0000 0000: -
+7e80 0000 0000 - 8000 0000 0000: modules and main thread stack
+*/
+struct MappingPPC64_47 {
+ static const uptr kMetaShadowBeg = 0x100000000000ull;
+ static const uptr kMetaShadowEnd = 0x120000000000ull;
+ static const uptr kShadowBeg = 0x010000000000ull;
+ static const uptr kShadowEnd = 0x080000000000ull;
+ static const uptr kHeapMemBeg = 0x7d0000000000ull;
+ static const uptr kHeapMemEnd = 0x7e0000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x010000000000ull;
+ static const uptr kHiAppMemBeg = 0x7e8000000000ull;
+ static const uptr kHiAppMemEnd = 0x800000000000ull; // 47 bits
+ static const uptr kShadowMsk = 0x7c0000000000ull;
+ static const uptr kShadowXor = 0x020000000000ull;
+ static const uptr kShadowAdd = 0x000000000000ull;
+ static const uptr kVdsoBeg = 0x7800000000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+};
+
+/*
+C/C++ on linux/s390x
+While the kernel provides a 64-bit address space, we have to restrict ourselves
+to 48 bits due to how e.g. SyncVar::GetId() works.
+0000 0000 1000 - 0e00 0000 0000: binary, modules, stacks - 14 TiB
+0e00 0000 0000 - 2000 0000 0000: -
+2000 0000 0000 - 4000 0000 0000: shadow - 32TiB (2 * app)
+4000 0000 0000 - 9000 0000 0000: -
+9000 0000 0000 - 9800 0000 0000: metainfo - 8TiB (0.5 * app)
+9800 0000 0000 - be00 0000 0000: -
+be00 0000 0000 - c000 0000 0000: heap - 2TiB (max supported by the allocator)
+*/
+struct MappingS390x {
+ static const uptr kMetaShadowBeg = 0x900000000000ull;
+ static const uptr kMetaShadowEnd = 0x980000000000ull;
+ static const uptr kShadowBeg = 0x200000000000ull;
+ static const uptr kShadowEnd = 0x400000000000ull;
+ static const uptr kHeapMemBeg = 0xbe0000000000ull;
+ static const uptr kHeapMemEnd = 0xc00000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x0e0000000000ull;
+ static const uptr kHiAppMemBeg = 0xc00000004000ull;
+ static const uptr kHiAppMemEnd = 0xc00000004000ull;
+ static const uptr kShadowMsk = 0xb00000000000ull;
+ static const uptr kShadowXor = 0x100000000000ull;
+ static const uptr kShadowAdd = 0x000000000000ull;
+ static const uptr kVdsoBeg = 0xfffffffff000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+};
+
+/* Go on linux, darwin and freebsd on x86_64
+0000 0000 1000 - 0000 1000 0000: executable
+0000 1000 0000 - 00c0 0000 0000: -
+00c0 0000 0000 - 00e0 0000 0000: heap
+00e0 0000 0000 - 2000 0000 0000: -
+2000 0000 0000 - 21c0 0000 0000: shadow
+21c0 0000 0000 - 3000 0000 0000: -
+3000 0000 0000 - 4000 0000 0000: metainfo (memory blocks and sync objects)
+4000 0000 0000 - 8000 0000 0000: -
+*/
+
+struct MappingGo48 {
+ static const uptr kMetaShadowBeg = 0x300000000000ull;
+ static const uptr kMetaShadowEnd = 0x400000000000ull;
+ static const uptr kShadowBeg = 0x200000000000ull;
+ static const uptr kShadowEnd = 0x21c000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x00e000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x200000000000ull;
+};
+
+/* Go on windows
+0000 0000 1000 - 0000 1000 0000: executable
+0000 1000 0000 - 00f8 0000 0000: -
+00c0 0000 0000 - 00e0 0000 0000: heap
+00e0 0000 0000 - 0100 0000 0000: -
+0100 0000 0000 - 0300 0000 0000: shadow
+0300 0000 0000 - 0700 0000 0000: -
+0700 0000 0000 - 0770 0000 0000: metainfo (memory blocks and sync objects)
+07d0 0000 0000 - 8000 0000 0000: -
+PIE binaries currently not supported, but it should be theoretically possible.
+*/
+
+struct MappingGoWindows {
+ static const uptr kMetaShadowBeg = 0x070000000000ull;
+ static const uptr kMetaShadowEnd = 0x077000000000ull;
+ static const uptr kShadowBeg = 0x010000000000ull;
+ static const uptr kShadowEnd = 0x030000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x00e000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x010000000000ull;
+};
+
+/* Go on linux/powerpc64 (46-bit VMA)
+0000 0000 1000 - 0000 1000 0000: executable
+0000 1000 0000 - 00c0 0000 0000: -
+00c0 0000 0000 - 00e0 0000 0000: heap
+00e0 0000 0000 - 2000 0000 0000: -
+2000 0000 0000 - 21c0 0000 0000: shadow
+21c0 0000 0000 - 2400 0000 0000: -
+2400 0000 0000 - 2470 0000 0000: metainfo (memory blocks and sync objects)
+2470 0000 0000 - 4000 0000 0000: -
+*/
+
+struct MappingGoPPC64_46 {
+ static const uptr kMetaShadowBeg = 0x240000000000ull;
+ static const uptr kMetaShadowEnd = 0x247000000000ull;
+ static const uptr kShadowBeg = 0x200000000000ull;
+ static const uptr kShadowEnd = 0x21c000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x00e000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x200000000000ull;
+};
+
+/* Go on linux/powerpc64 (47-bit VMA)
+0000 0000 1000 - 0000 1000 0000: executable
+0000 1000 0000 - 00c0 0000 0000: -
+00c0 0000 0000 - 00e0 0000 0000: heap
+00e0 0000 0000 - 2000 0000 0000: -
+2000 0000 0000 - 2800 0000 0000: shadow
+2800 0000 0000 - 3000 0000 0000: -
+3000 0000 0000 - 3200 0000 0000: metainfo (memory blocks and sync objects)
+3200 0000 0000 - 8000 0000 0000: -
+*/
+
+struct MappingGoPPC64_47 {
+ static const uptr kMetaShadowBeg = 0x300000000000ull;
+ static const uptr kMetaShadowEnd = 0x320000000000ull;
+ static const uptr kShadowBeg = 0x200000000000ull;
+ static const uptr kShadowEnd = 0x280000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x00e000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x200000000000ull;
+};
+
+/* Go on linux/aarch64 (48-bit VMA) and darwin/aarch64 (47-bit VMA)
+0000 0000 1000 - 0000 1000 0000: executable
+0000 1000 0000 - 00c0 0000 0000: -
+00c0 0000 0000 - 00e0 0000 0000: heap
+00e0 0000 0000 - 2000 0000 0000: -
+2000 0000 0000 - 2800 0000 0000: shadow
+2800 0000 0000 - 3000 0000 0000: -
+3000 0000 0000 - 3200 0000 0000: metainfo (memory blocks and sync objects)
+3200 0000 0000 - 8000 0000 0000: -
+*/
+struct MappingGoAarch64 {
+ static const uptr kMetaShadowBeg = 0x300000000000ull;
+ static const uptr kMetaShadowEnd = 0x320000000000ull;
+ static const uptr kShadowBeg = 0x200000000000ull;
+ static const uptr kShadowEnd = 0x280000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x00e000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x200000000000ull;
+};
+
+/*
+Go on linux/mips64 (47-bit VMA)
+0000 0000 1000 - 0000 1000 0000: executable
+0000 1000 0000 - 00c0 0000 0000: -
+00c0 0000 0000 - 00e0 0000 0000: heap
+00e0 0000 0000 - 2000 0000 0000: -
+2000 0000 0000 - 2800 0000 0000: shadow
+2800 0000 0000 - 3000 0000 0000: -
+3000 0000 0000 - 3200 0000 0000: metainfo (memory blocks and sync objects)
+3200 0000 0000 - 8000 0000 0000: -
+*/
+struct MappingGoMips64_47 {
+ static const uptr kMetaShadowBeg = 0x300000000000ull;
+ static const uptr kMetaShadowEnd = 0x320000000000ull;
+ static const uptr kShadowBeg = 0x200000000000ull;
+ static const uptr kShadowEnd = 0x280000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x00e000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x200000000000ull;
+};
+
+/*
+Go on linux/s390x
+0000 0000 1000 - 1000 0000 0000: executable and heap - 16 TiB
+1000 0000 0000 - 4000 0000 0000: -
+4000 0000 0000 - 6000 0000 0000: shadow - 64TiB (4 * app)
+6000 0000 0000 - 9000 0000 0000: -
+9000 0000 0000 - 9800 0000 0000: metainfo - 8TiB (0.5 * app)
+*/
+struct MappingGoS390x {
+ static const uptr kMetaShadowBeg = 0x900000000000ull;
+ static const uptr kMetaShadowEnd = 0x980000000000ull;
+ static const uptr kShadowBeg = 0x400000000000ull;
+ static const uptr kShadowEnd = 0x600000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x100000000000ull;
+ static const uptr kMidAppMemBeg = 0;
+ static const uptr kMidAppMemEnd = 0;
+ static const uptr kHiAppMemBeg = 0;
+ static const uptr kHiAppMemEnd = 0;
+ static const uptr kHeapMemBeg = 0;
+ static const uptr kHeapMemEnd = 0;
+ static const uptr kVdsoBeg = 0;
+ static const uptr kShadowMsk = 0;
+ static const uptr kShadowXor = 0;
+ static const uptr kShadowAdd = 0x400000000000ull;
+};
+
+extern uptr vmaSize;
+
+template <typename Func, typename Arg>
+ALWAYS_INLINE auto SelectMapping(Arg arg) {
+#if SANITIZER_GO
+# if defined(__powerpc64__)
+ switch (vmaSize) {
+ case 46:
+ return Func::template Apply<MappingGoPPC64_46>(arg);
+ case 47:
+ return Func::template Apply<MappingGoPPC64_47>(arg);
+ }
+# elif defined(__mips64)
+ return Func::template Apply<MappingGoMips64_47>(arg);
+# elif defined(__s390x__)
+ return Func::template Apply<MappingGoS390x>(arg);
+# elif defined(__aarch64__)
+ return Func::template Apply<MappingGoAarch64>(arg);
+# elif SANITIZER_WINDOWS
+ return Func::template Apply<MappingGoWindows>(arg);
+# else
+ return Func::template Apply<MappingGo48>(arg);
+# endif
+#else // SANITIZER_GO
+# if SANITIZER_IOS && !SANITIZER_IOSSIM
+ return Func::template Apply<MappingAppleAarch64>(arg);
+# elif defined(__x86_64__) || SANITIZER_APPLE
+ return Func::template Apply<Mapping48AddressSpace>(arg);
+# elif defined(__aarch64__)
+ switch (vmaSize) {
+ case 39:
+ return Func::template Apply<MappingAarch64_39>(arg);
+ case 42:
+ return Func::template Apply<MappingAarch64_42>(arg);
+ case 48:
+ return Func::template Apply<MappingAarch64_48>(arg);
+ }
+# elif SANITIZER_LOONGARCH64
+ return Func::template Apply<MappingLoongArch64_47>(arg);
+# elif defined(__powerpc64__)
+ switch (vmaSize) {
+ case 44:
+ return Func::template Apply<MappingPPC64_44>(arg);
+ case 46:
+ return Func::template Apply<MappingPPC64_46>(arg);
+ case 47:
+ return Func::template Apply<MappingPPC64_47>(arg);
+ }
+# elif defined(__mips64)
+ return Func::template Apply<MappingMips64_40>(arg);
+# elif defined(__s390x__)
+ return Func::template Apply<MappingS390x>(arg);
+# else
+# error "unsupported platform"
+# endif
+#endif
+ Die();
+}
+
+template <typename Func>
+void ForEachMapping() {
+ Func::template Apply<Mapping48AddressSpace>();
+ Func::template Apply<MappingMips64_40>();
+ Func::template Apply<MappingAppleAarch64>();
+ Func::template Apply<MappingAarch64_39>();
+ Func::template Apply<MappingAarch64_42>();
+ Func::template Apply<MappingAarch64_48>();
+ Func::template Apply<MappingLoongArch64_47>();
+ Func::template Apply<MappingPPC64_44>();
+ Func::template Apply<MappingPPC64_46>();
+ Func::template Apply<MappingPPC64_47>();
+ Func::template Apply<MappingS390x>();
+ Func::template Apply<MappingGo48>();
+ Func::template Apply<MappingGoWindows>();
+ Func::template Apply<MappingGoPPC64_46>();
+ Func::template Apply<MappingGoPPC64_47>();
+ Func::template Apply<MappingGoAarch64>();
+ Func::template Apply<MappingGoMips64_47>();
+ Func::template Apply<MappingGoS390x>();
+}
+
+enum MappingType {
+ kLoAppMemBeg,
+ kLoAppMemEnd,
+ kHiAppMemBeg,
+ kHiAppMemEnd,
+ kMidAppMemBeg,
+ kMidAppMemEnd,
+ kHeapMemBeg,
+ kHeapMemEnd,
+ kShadowBeg,
+ kShadowEnd,
+ kMetaShadowBeg,
+ kMetaShadowEnd,
+ kVdsoBeg,
+};
+
+struct MappingField {
+ template <typename Mapping>
+ static uptr Apply(MappingType type) {
+ switch (type) {
+ case kLoAppMemBeg:
+ return Mapping::kLoAppMemBeg;
+ case kLoAppMemEnd:
+ return Mapping::kLoAppMemEnd;
+ case kMidAppMemBeg:
+ return Mapping::kMidAppMemBeg;
+ case kMidAppMemEnd:
+ return Mapping::kMidAppMemEnd;
+ case kHiAppMemBeg:
+ return Mapping::kHiAppMemBeg;
+ case kHiAppMemEnd:
+ return Mapping::kHiAppMemEnd;
+ case kHeapMemBeg:
+ return Mapping::kHeapMemBeg;
+ case kHeapMemEnd:
+ return Mapping::kHeapMemEnd;
+ case kVdsoBeg:
+ return Mapping::kVdsoBeg;
+ case kShadowBeg:
+ return Mapping::kShadowBeg;
+ case kShadowEnd:
+ return Mapping::kShadowEnd;
+ case kMetaShadowBeg:
+ return Mapping::kMetaShadowBeg;
+ case kMetaShadowEnd:
+ return Mapping::kMetaShadowEnd;
+ }
+ Die();
+ }
+};
+
+ALWAYS_INLINE
+uptr LoAppMemBeg(void) { return SelectMapping<MappingField>(kLoAppMemBeg); }
+ALWAYS_INLINE
+uptr LoAppMemEnd(void) { return SelectMapping<MappingField>(kLoAppMemEnd); }
+
+ALWAYS_INLINE
+uptr MidAppMemBeg(void) { return SelectMapping<MappingField>(kMidAppMemBeg); }
+ALWAYS_INLINE
+uptr MidAppMemEnd(void) { return SelectMapping<MappingField>(kMidAppMemEnd); }
+
+ALWAYS_INLINE
+uptr HeapMemBeg(void) { return SelectMapping<MappingField>(kHeapMemBeg); }
+ALWAYS_INLINE
+uptr HeapMemEnd(void) { return SelectMapping<MappingField>(kHeapMemEnd); }
+
+ALWAYS_INLINE
+uptr HiAppMemBeg(void) { return SelectMapping<MappingField>(kHiAppMemBeg); }
+ALWAYS_INLINE
+uptr HiAppMemEnd(void) { return SelectMapping<MappingField>(kHiAppMemEnd); }
+
+ALWAYS_INLINE
+uptr VdsoBeg(void) { return SelectMapping<MappingField>(kVdsoBeg); }
+
+ALWAYS_INLINE
+uptr ShadowBeg(void) { return SelectMapping<MappingField>(kShadowBeg); }
+ALWAYS_INLINE
+uptr ShadowEnd(void) { return SelectMapping<MappingField>(kShadowEnd); }
+
+ALWAYS_INLINE
+uptr MetaShadowBeg(void) { return SelectMapping<MappingField>(kMetaShadowBeg); }
+ALWAYS_INLINE
+uptr MetaShadowEnd(void) { return SelectMapping<MappingField>(kMetaShadowEnd); }
+
+struct IsAppMemImpl {
+ template <typename Mapping>
+ static bool Apply(uptr mem) {
+ return (mem >= Mapping::kHeapMemBeg && mem < Mapping::kHeapMemEnd) ||
+ (mem >= Mapping::kMidAppMemBeg && mem < Mapping::kMidAppMemEnd) ||
+ (mem >= Mapping::kLoAppMemBeg && mem < Mapping::kLoAppMemEnd) ||
+ (mem >= Mapping::kHiAppMemBeg && mem < Mapping::kHiAppMemEnd);
+ }
+};
+
+ALWAYS_INLINE
+bool IsAppMem(uptr mem) { return SelectMapping<IsAppMemImpl>(mem); }
+
+struct IsShadowMemImpl {
+ template <typename Mapping>
+ static bool Apply(uptr mem) {
+ return mem >= Mapping::kShadowBeg && mem <= Mapping::kShadowEnd;
+ }
+};
+
+ALWAYS_INLINE
+bool IsShadowMem(RawShadow *p) {
+ return SelectMapping<IsShadowMemImpl>(reinterpret_cast<uptr>(p));
+}
+
+struct IsMetaMemImpl {
+ template <typename Mapping>
+ static bool Apply(uptr mem) {
+ return mem >= Mapping::kMetaShadowBeg && mem <= Mapping::kMetaShadowEnd;
+ }
+};
+
+ALWAYS_INLINE
+bool IsMetaMem(const u32 *p) {
+ return SelectMapping<IsMetaMemImpl>(reinterpret_cast<uptr>(p));
+}
+
+struct MemToShadowImpl {
+ template <typename Mapping>
+ static uptr Apply(uptr x) {
+ DCHECK(IsAppMemImpl::Apply<Mapping>(x));
+ return (((x) & ~(Mapping::kShadowMsk | (kShadowCell - 1))) ^
+ Mapping::kShadowXor) *
+ kShadowMultiplier +
+ Mapping::kShadowAdd;
+ }
+};
+
+ALWAYS_INLINE
+RawShadow *MemToShadow(uptr x) {
+ return reinterpret_cast<RawShadow *>(SelectMapping<MemToShadowImpl>(x));
+}
+
+struct MemToMetaImpl {
+ template <typename Mapping>
+ static u32 *Apply(uptr x) {
+ DCHECK(IsAppMemImpl::Apply<Mapping>(x));
+ return (u32 *)(((((x) & ~(Mapping::kShadowMsk | (kMetaShadowCell - 1)))) /
+ kMetaShadowCell * kMetaShadowSize) |
+ Mapping::kMetaShadowBeg);
+ }
+};
+
+ALWAYS_INLINE
+u32 *MemToMeta(uptr x) { return SelectMapping<MemToMetaImpl>(x); }
+
+struct ShadowToMemImpl {
+ template <typename Mapping>
+ static uptr Apply(uptr sp) {
+ if (!IsShadowMemImpl::Apply<Mapping>(sp))
+ return 0;
+ // The shadow mapping is non-linear and we've lost some bits, so we don't
+ // have an easy way to restore the original app address. But the mapping is
+ // a bijection, so we try to restore the address as belonging to
+ // low/mid/high range consecutively and see if shadow->app->shadow mapping
+ // gives us the same address.
+ uptr p =
+ ((sp - Mapping::kShadowAdd) / kShadowMultiplier) ^ Mapping::kShadowXor;
+ if (p >= Mapping::kLoAppMemBeg && p < Mapping::kLoAppMemEnd &&
+ MemToShadowImpl::Apply<Mapping>(p) == sp)
+ return p;
+ if (Mapping::kMidAppMemBeg) {
+ uptr p_mid = p + (Mapping::kMidAppMemBeg & Mapping::kShadowMsk);
+ if (p_mid >= Mapping::kMidAppMemBeg && p_mid < Mapping::kMidAppMemEnd &&
+ MemToShadowImpl::Apply<Mapping>(p_mid) == sp)
+ return p_mid;
+ }
+ return p | Mapping::kShadowMsk;
+ }
+};
+
+ALWAYS_INLINE
+uptr ShadowToMem(RawShadow *s) {
+ return SelectMapping<ShadowToMemImpl>(reinterpret_cast<uptr>(s));
+}
+
+// Compresses addr to kCompressedAddrBits stored in least significant bits.
+ALWAYS_INLINE uptr CompressAddr(uptr addr) {
+ return addr & ((1ull << kCompressedAddrBits) - 1);
+}
+
+struct RestoreAddrImpl {
+ typedef uptr Result;
+ template <typename Mapping>
+ static Result Apply(uptr addr) {
+ // To restore the address we go over all app memory ranges and check if top
+ // 3 bits of the compressed addr match that of the app range. If yes, we
+ // assume that the compressed address come from that range and restore the
+ // missing top bits to match the app range address.
+ const uptr ranges[] = {
+ Mapping::kLoAppMemBeg, Mapping::kLoAppMemEnd, Mapping::kMidAppMemBeg,
+ Mapping::kMidAppMemEnd, Mapping::kHiAppMemBeg, Mapping::kHiAppMemEnd,
+ Mapping::kHeapMemBeg, Mapping::kHeapMemEnd,
+ };
+ const uptr indicator = 0x0e0000000000ull;
+ const uptr ind_lsb = 1ull << LeastSignificantSetBitIndex(indicator);
+ for (uptr i = 0; i < ARRAY_SIZE(ranges); i += 2) {
+ uptr beg = ranges[i];
+ uptr end = ranges[i + 1];
+ if (beg == end)
+ continue;
+ for (uptr p = beg; p < end; p = RoundDown(p + ind_lsb, ind_lsb)) {
+ if ((addr & indicator) == (p & indicator))
+ return addr | (p & ~(ind_lsb - 1));
+ }
+ }
+ Printf("ThreadSanitizer: failed to restore address 0x%zx\n", addr);
+ Die();
+ }
+};
+
+// Restores compressed addr from kCompressedAddrBits to full representation.
+// This is called only during reporting and is not performance-critical.
+inline uptr RestoreAddr(uptr addr) {
+ return SelectMapping<RestoreAddrImpl>(addr);
+}
+
+void InitializePlatform();
+void InitializePlatformEarly();
+void CheckAndProtect();
+void InitializeShadowMemoryPlatform();
+void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns);
+int ExtractResolvFDs(void *state, int *fds, int nfd);
+int ExtractRecvmsgFDs(void *msg, int *fds, int nfd);
+uptr ExtractLongJmpSp(uptr *env);
+void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size);
+
+int call_pthread_cancel_with_cleanup(int (*fn)(void *arg),
+ void (*cleanup)(void *arg), void *arg);
+
+void DestroyThreadState();
+void PlatformCleanUpThreadState(ThreadState *thr);
+
+} // namespace __tsan
+
+#endif // TSAN_PLATFORM_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_linux.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_linux.cpp
new file mode 100644
index 00000000000..9094469ba4e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_linux.cpp
@@ -0,0 +1,553 @@
+//===-- tsan_platform_linux.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Linux- and BSD-specific code.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
+#include "sanitizer_common/sanitizer_platform_limits_posix.h"
+#include "sanitizer_common/sanitizer_posix.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_stoptheworld.h"
+#include "tsan_flags.h"
+#include "tsan_platform.h"
+#include "tsan_rtl.h"
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+#if SANITIZER_LINUX
+#include <sys/personality.h>
+#include <setjmp.h>
+#endif
+#include <sys/syscall.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sched.h>
+#include <dlfcn.h>
+#if SANITIZER_LINUX
+#define __need_res_state
+#include <resolv.h>
+#endif
+
+#ifdef sa_handler
+# undef sa_handler
+#endif
+
+#ifdef sa_sigaction
+# undef sa_sigaction
+#endif
+
+#if SANITIZER_FREEBSD
+extern "C" void *__libc_stack_end;
+void *__libc_stack_end = 0;
+#endif
+
+#if SANITIZER_LINUX && defined(__aarch64__) && !SANITIZER_GO
+# define INIT_LONGJMP_XOR_KEY 1
+#else
+# define INIT_LONGJMP_XOR_KEY 0
+#endif
+
+#if INIT_LONGJMP_XOR_KEY
+#include "interception/interception.h"
+// Must be declared outside of other namespaces.
+DECLARE_REAL(int, _setjmp, void *env)
+#endif
+
+namespace __tsan {
+
+#if INIT_LONGJMP_XOR_KEY
+static void InitializeLongjmpXorKey();
+static uptr longjmp_xor_key;
+#endif
+
+// Runtime detected VMA size.
+uptr vmaSize;
+
+enum {
+ MemTotal,
+ MemShadow,
+ MemMeta,
+ MemFile,
+ MemMmap,
+ MemHeap,
+ MemOther,
+ MemCount,
+};
+
+void FillProfileCallback(uptr p, uptr rss, bool file, uptr *mem) {
+ mem[MemTotal] += rss;
+ if (p >= ShadowBeg() && p < ShadowEnd())
+ mem[MemShadow] += rss;
+ else if (p >= MetaShadowBeg() && p < MetaShadowEnd())
+ mem[MemMeta] += rss;
+ else if ((p >= LoAppMemBeg() && p < LoAppMemEnd()) ||
+ (p >= MidAppMemBeg() && p < MidAppMemEnd()) ||
+ (p >= HiAppMemBeg() && p < HiAppMemEnd()))
+ mem[file ? MemFile : MemMmap] += rss;
+ else if (p >= HeapMemBeg() && p < HeapMemEnd())
+ mem[MemHeap] += rss;
+ else
+ mem[MemOther] += rss;
+}
+
+void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns) {
+ uptr mem[MemCount];
+ internal_memset(mem, 0, sizeof(mem));
+ GetMemoryProfile(FillProfileCallback, mem);
+ auto meta = ctx->metamap.GetMemoryStats();
+ StackDepotStats stacks = StackDepotGetStats();
+ uptr nthread, nlive;
+ ctx->thread_registry.GetNumberOfThreads(&nthread, &nlive);
+ uptr trace_mem;
+ {
+ Lock l(&ctx->slot_mtx);
+ trace_mem = ctx->trace_part_total_allocated * sizeof(TracePart);
+ }
+ uptr internal_stats[AllocatorStatCount];
+ internal_allocator()->GetStats(internal_stats);
+ // All these are allocated from the common mmap region.
+ mem[MemMmap] -= meta.mem_block + meta.sync_obj + trace_mem +
+ stacks.allocated + internal_stats[AllocatorStatMapped];
+ if (s64(mem[MemMmap]) < 0)
+ mem[MemMmap] = 0;
+ internal_snprintf(
+ buf, buf_size,
+ "==%zu== %llus [%zu]: RSS %zd MB: shadow:%zd meta:%zd file:%zd"
+ " mmap:%zd heap:%zd other:%zd intalloc:%zd memblocks:%zd syncobj:%zu"
+ " trace:%zu stacks=%zd threads=%zu/%zu\n",
+ internal_getpid(), uptime_ns / (1000 * 1000 * 1000), ctx->global_epoch,
+ mem[MemTotal] >> 20, mem[MemShadow] >> 20, mem[MemMeta] >> 20,
+ mem[MemFile] >> 20, mem[MemMmap] >> 20, mem[MemHeap] >> 20,
+ mem[MemOther] >> 20, internal_stats[AllocatorStatMapped] >> 20,
+ meta.mem_block >> 20, meta.sync_obj >> 20, trace_mem >> 20,
+ stacks.allocated >> 20, nlive, nthread);
+}
+
+#if !SANITIZER_GO
+// Mark shadow for .rodata sections with the special Shadow::kRodata marker.
+// Accesses to .rodata can't race, so this saves time, memory and trace space.
+static void MapRodata() {
+ // First create temp file.
+ const char *tmpdir = GetEnv("TMPDIR");
+ if (tmpdir == 0)
+ tmpdir = GetEnv("TEST_TMPDIR");
+#ifdef P_tmpdir
+ if (tmpdir == 0)
+ tmpdir = P_tmpdir;
+#endif
+ if (tmpdir == 0)
+ return;
+ char name[256];
+ internal_snprintf(name, sizeof(name), "%s/tsan.rodata.%d",
+ tmpdir, (int)internal_getpid());
+ uptr openrv = internal_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
+ if (internal_iserror(openrv))
+ return;
+ internal_unlink(name); // Unlink it now, so that we can reuse the buffer.
+ fd_t fd = openrv;
+ // Fill the file with Shadow::kRodata.
+ const uptr kMarkerSize = 512 * 1024 / sizeof(RawShadow);
+ InternalMmapVector<RawShadow> marker(kMarkerSize);
+ // volatile to prevent insertion of memset
+ for (volatile RawShadow *p = marker.data(); p < marker.data() + kMarkerSize;
+ p++)
+ *p = Shadow::kRodata;
+ internal_write(fd, marker.data(), marker.size() * sizeof(RawShadow));
+ // Map the file into memory.
+ uptr page = internal_mmap(0, GetPageSizeCached(), PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
+ if (internal_iserror(page)) {
+ internal_close(fd);
+ return;
+ }
+ // Map the file into shadow of .rodata sections.
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+ // Reusing the buffer 'name'.
+ MemoryMappedSegment segment(name, ARRAY_SIZE(name));
+ while (proc_maps.Next(&segment)) {
+ if (segment.filename[0] != 0 && segment.filename[0] != '[' &&
+ segment.IsReadable() && segment.IsExecutable() &&
+ !segment.IsWritable() && IsAppMem(segment.start)) {
+ // Assume it's .rodata
+ char *shadow_start = (char *)MemToShadow(segment.start);
+ char *shadow_end = (char *)MemToShadow(segment.end);
+ for (char *p = shadow_start; p < shadow_end;
+ p += marker.size() * sizeof(RawShadow)) {
+ internal_mmap(
+ p, Min<uptr>(marker.size() * sizeof(RawShadow), shadow_end - p),
+ PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, 0);
+ }
+ }
+ }
+ internal_close(fd);
+}
+
+void InitializeShadowMemoryPlatform() {
+ MapRodata();
+}
+
+#endif // #if !SANITIZER_GO
+
+void InitializePlatformEarly() {
+ vmaSize =
+ (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);
+#if defined(__aarch64__)
+# if !SANITIZER_GO
+ if (vmaSize != 39 && vmaSize != 42 && vmaSize != 48) {
+ Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
+ Printf("FATAL: Found %zd - Supported 39, 42 and 48\n", vmaSize);
+ Die();
+ }
+#else
+ if (vmaSize != 48) {
+ Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
+ Printf("FATAL: Found %zd - Supported 48\n", vmaSize);
+ Die();
+ }
+#endif
+#elif SANITIZER_LOONGARCH64
+# if !SANITIZER_GO
+ if (vmaSize != 47) {
+ Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
+ Printf("FATAL: Found %zd - Supported 47\n", vmaSize);
+ Die();
+ }
+# endif
+#elif defined(__powerpc64__)
+# if !SANITIZER_GO
+ if (vmaSize != 44 && vmaSize != 46 && vmaSize != 47) {
+ Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
+ Printf("FATAL: Found %zd - Supported 44, 46, and 47\n", vmaSize);
+ Die();
+ }
+# else
+ if (vmaSize != 46 && vmaSize != 47) {
+ Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
+ Printf("FATAL: Found %zd - Supported 46, and 47\n", vmaSize);
+ Die();
+ }
+# endif
+#elif defined(__mips64)
+# if !SANITIZER_GO
+ if (vmaSize != 40) {
+ Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
+ Printf("FATAL: Found %zd - Supported 40\n", vmaSize);
+ Die();
+ }
+# else
+ if (vmaSize != 47) {
+ Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
+ Printf("FATAL: Found %zd - Supported 47\n", vmaSize);
+ Die();
+ }
+# endif
+#endif
+}
+
+void InitializePlatform() {
+ DisableCoreDumperIfNecessary();
+
+ // Go maps shadow memory lazily and works fine with limited address space.
+ // Unlimited stack is not a problem as well, because the executable
+ // is not compiled with -pie.
+#if !SANITIZER_GO
+ {
+ bool reexec = false;
+ // TSan doesn't play well with unlimited stack size (as stack
+ // overlaps with shadow memory). If we detect unlimited stack size,
+ // we re-exec the program with limited stack size as a best effort.
+ if (StackSizeIsUnlimited()) {
+ const uptr kMaxStackSize = 32 * 1024 * 1024;
+ VReport(1, "Program is run with unlimited stack size, which wouldn't "
+ "work with ThreadSanitizer.\n"
+ "Re-execing with stack size limited to %zd bytes.\n",
+ kMaxStackSize);
+ SetStackSizeLimitInBytes(kMaxStackSize);
+ reexec = true;
+ }
+
+ if (!AddressSpaceIsUnlimited()) {
+ Report("WARNING: Program is run with limited virtual address space,"
+ " which wouldn't work with ThreadSanitizer.\n");
+ Report("Re-execing with unlimited virtual address space.\n");
+ SetAddressSpaceUnlimited();
+ reexec = true;
+ }
+#if SANITIZER_ANDROID && (defined(__aarch64__) || defined(__x86_64__))
+ // After patch "arm64: mm: support ARCH_MMAP_RND_BITS." is introduced in
+ // linux kernel, the random gap between stack and mapped area is increased
+ // from 128M to 36G on 39-bit aarch64. As it is almost impossible to cover
+ // this big range, we should disable randomized virtual space on aarch64.
+ // ASLR personality check.
+ int old_personality = personality(0xffffffff);
+ if (old_personality != -1 && (old_personality & ADDR_NO_RANDOMIZE) == 0) {
+ VReport(1, "WARNING: Program is run with randomized virtual address "
+ "space, which wouldn't work with ThreadSanitizer.\n"
+ "Re-execing with fixed virtual address space.\n");
+ CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
+ reexec = true;
+ }
+
+#endif
+#if SANITIZER_LINUX && defined(__aarch64__)
+ // Initialize the xor key used in {sig}{set,long}jump.
+ InitializeLongjmpXorKey();
+#endif
+ if (reexec)
+ ReExec();
+ }
+
+ CheckAndProtect();
+ InitTlsSize();
+#endif // !SANITIZER_GO
+}
+
+#if !SANITIZER_GO
+// Extract file descriptors passed to glibc internal __res_iclose function.
+// This is required to properly "close" the fds, because we do not see internal
+// closes within glibc. The code is a pure hack.
+int ExtractResolvFDs(void *state, int *fds, int nfd) {
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ int cnt = 0;
+ struct __res_state *statp = (struct __res_state*)state;
+ for (int i = 0; i < MAXNS && cnt < nfd; i++) {
+ if (statp->_u._ext.nsaddrs[i] && statp->_u._ext.nssocks[i] != -1)
+ fds[cnt++] = statp->_u._ext.nssocks[i];
+ }
+ return cnt;
+#else
+ return 0;
+#endif
+}
+
+// Extract file descriptors passed via UNIX domain sockets.
+// This is required to properly handle "open" of these fds.
+// see 'man recvmsg' and 'man 3 cmsg'.
+int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {
+ int res = 0;
+ msghdr *msg = (msghdr*)msgp;
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
+ for (; cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+ if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
+ continue;
+ int n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(fds[0]);
+ for (int i = 0; i < n; i++) {
+ fds[res++] = ((int*)CMSG_DATA(cmsg))[i];
+ if (res == nfd)
+ return res;
+ }
+ }
+ return res;
+}
+
+// Reverse operation of libc stack pointer mangling
+static uptr UnmangleLongJmpSp(uptr mangled_sp) {
+#if defined(__x86_64__)
+# if SANITIZER_LINUX
+ // Reverse of:
+ // xor %fs:0x30, %rsi
+ // rol $0x11, %rsi
+ uptr sp;
+ asm("ror $0x11, %0 \n"
+ "xor %%fs:0x30, %0 \n"
+ : "=r" (sp)
+ : "0" (mangled_sp));
+ return sp;
+# else
+ return mangled_sp;
+# endif
+#elif defined(__aarch64__)
+# if SANITIZER_LINUX
+ return mangled_sp ^ longjmp_xor_key;
+# else
+ return mangled_sp;
+# endif
+#elif defined(__loongarch__)
+ return mangled_sp;
+#elif defined(__powerpc64__)
+ // Reverse of:
+ // ld r4, -28696(r13)
+ // xor r4, r3, r4
+ uptr xor_key;
+ asm("ld %0, -28696(%%r13)" : "=r" (xor_key));
+ return mangled_sp ^ xor_key;
+#elif defined(__mips__)
+ return mangled_sp;
+#elif defined(__s390x__)
+ // tcbhead_t.stack_guard
+ uptr xor_key = ((uptr *)__builtin_thread_pointer())[5];
+ return mangled_sp ^ xor_key;
+#else
+ #error "Unknown platform"
+#endif
+}
+
+#if SANITIZER_NETBSD
+# ifdef __x86_64__
+# define LONG_JMP_SP_ENV_SLOT 6
+# else
+# error unsupported
+# endif
+#elif defined(__powerpc__)
+# define LONG_JMP_SP_ENV_SLOT 0
+#elif SANITIZER_FREEBSD
+# ifdef __aarch64__
+# define LONG_JMP_SP_ENV_SLOT 1
+# else
+# define LONG_JMP_SP_ENV_SLOT 2
+# endif
+#elif SANITIZER_LINUX
+# ifdef __aarch64__
+# define LONG_JMP_SP_ENV_SLOT 13
+# elif defined(__loongarch__)
+# define LONG_JMP_SP_ENV_SLOT 1
+# elif defined(__mips64)
+# define LONG_JMP_SP_ENV_SLOT 1
+# elif defined(__s390x__)
+# define LONG_JMP_SP_ENV_SLOT 9
+# else
+# define LONG_JMP_SP_ENV_SLOT 6
+# endif
+#endif
+
+uptr ExtractLongJmpSp(uptr *env) {
+ uptr mangled_sp = env[LONG_JMP_SP_ENV_SLOT];
+ return UnmangleLongJmpSp(mangled_sp);
+}
+
+#if INIT_LONGJMP_XOR_KEY
+// GLIBC mangles the function pointers in jmp_buf (used in {set,long}*jmp
+// functions) by XORing them with a random key. For AArch64 it is a global
+// variable rather than a TCB one (as for x86_64/powerpc). We obtain the key by
+// issuing a setjmp and XORing the SP pointer values to derive the key.
+static void InitializeLongjmpXorKey() {
+ // 1. Call REAL(setjmp), which stores the mangled SP in env.
+ jmp_buf env;
+ REAL(_setjmp)(env);
+
+ // 2. Retrieve vanilla/mangled SP.
+ uptr sp;
+ asm("mov %0, sp" : "=r" (sp));
+ uptr mangled_sp = ((uptr *)&env)[LONG_JMP_SP_ENV_SLOT];
+
+ // 3. xor SPs to obtain key.
+ longjmp_xor_key = mangled_sp ^ sp;
+}
+#endif
+
+extern "C" void __tsan_tls_initialization() {}
+
+void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
+ // Check that the thr object is in tls;
+ const uptr thr_beg = (uptr)thr;
+ const uptr thr_end = (uptr)thr + sizeof(*thr);
+ CHECK_GE(thr_beg, tls_addr);
+ CHECK_LE(thr_beg, tls_addr + tls_size);
+ CHECK_GE(thr_end, tls_addr);
+ CHECK_LE(thr_end, tls_addr + tls_size);
+ // Since the thr object is huge, skip it.
+ const uptr pc = StackTrace::GetNextInstructionPc(
+ reinterpret_cast<uptr>(__tsan_tls_initialization));
+ MemoryRangeImitateWrite(thr, pc, tls_addr, thr_beg - tls_addr);
+ MemoryRangeImitateWrite(thr, pc, thr_end, tls_addr + tls_size - thr_end);
+}
+
+// Note: this function runs with async signals enabled,
+// so it must not touch any tsan state.
+int call_pthread_cancel_with_cleanup(int (*fn)(void *arg),
+ void (*cleanup)(void *arg), void *arg) {
+ // pthread_cleanup_push/pop are hardcore macros mess.
+ // We can't intercept nor call them w/o including pthread.h.
+ int res;
+ pthread_cleanup_push(cleanup, arg);
+ res = fn(arg);
+ pthread_cleanup_pop(0);
+ return res;
+}
+#endif // !SANITIZER_GO
+
+#if !SANITIZER_GO
+void ReplaceSystemMalloc() { }
+#endif
+
+#if !SANITIZER_GO
+#if SANITIZER_ANDROID
+// On Android, one thread can call intercepted functions after
+// DestroyThreadState(), so add a fake thread state for "dead" threads.
+static ThreadState *dead_thread_state = nullptr;
+
+ThreadState *cur_thread() {
+ ThreadState* thr = reinterpret_cast<ThreadState*>(*get_android_tls_ptr());
+ if (thr == nullptr) {
+ __sanitizer_sigset_t emptyset;
+ internal_sigfillset(&emptyset);
+ __sanitizer_sigset_t oldset;
+ CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &emptyset, &oldset));
+ thr = reinterpret_cast<ThreadState*>(*get_android_tls_ptr());
+ if (thr == nullptr) {
+ thr = reinterpret_cast<ThreadState*>(MmapOrDie(sizeof(ThreadState),
+ "ThreadState"));
+ *get_android_tls_ptr() = reinterpret_cast<uptr>(thr);
+ if (dead_thread_state == nullptr) {
+ dead_thread_state = reinterpret_cast<ThreadState*>(
+ MmapOrDie(sizeof(ThreadState), "ThreadState"));
+ dead_thread_state->fast_state.SetIgnoreBit();
+ dead_thread_state->ignore_interceptors = 1;
+ dead_thread_state->is_dead = true;
+ *const_cast<u32*>(&dead_thread_state->tid) = -1;
+ CHECK_EQ(0, internal_mprotect(dead_thread_state, sizeof(ThreadState),
+ PROT_READ));
+ }
+ }
+ CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr));
+ }
+ return thr;
+}
+
+void set_cur_thread(ThreadState *thr) {
+ *get_android_tls_ptr() = reinterpret_cast<uptr>(thr);
+}
+
+void cur_thread_finalize() {
+ __sanitizer_sigset_t emptyset;
+ internal_sigfillset(&emptyset);
+ __sanitizer_sigset_t oldset;
+ CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &emptyset, &oldset));
+ ThreadState* thr = reinterpret_cast<ThreadState*>(*get_android_tls_ptr());
+ if (thr != dead_thread_state) {
+ *get_android_tls_ptr() = reinterpret_cast<uptr>(dead_thread_state);
+ UnmapOrDie(thr, sizeof(ThreadState));
+ }
+ CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr));
+}
+#endif // SANITIZER_ANDROID
+#endif // if !SANITIZER_GO
+
+} // namespace __tsan
+
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_mac.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_mac.cpp
new file mode 100644
index 00000000000..1aac0fb2752
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_mac.cpp
@@ -0,0 +1,304 @@
+//===-- tsan_platform_mac.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Mac-specific code.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_APPLE
+
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_posix.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
+#include "sanitizer_common/sanitizer_ptrauth.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "tsan_platform.h"
+#include "tsan_rtl.h"
+#include "tsan_flags.h"
+
+#include <limits.h>
+#include <mach/mach.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sched.h>
+
+namespace __tsan {
+
+#if !SANITIZER_GO
+static char main_thread_state[sizeof(ThreadState)] ALIGNED(
+ SANITIZER_CACHE_LINE_SIZE);
+static ThreadState *dead_thread_state;
+static pthread_key_t thread_state_key;
+
+// We rely on the following documented, but Darwin-specific behavior to keep the
+// reference to the ThreadState object alive in TLS:
+// pthread_key_create man page:
+// If, after all the destructors have been called for all non-NULL values with
+// associated destructors, there are still some non-NULL values with
+// associated destructors, then the process is repeated. If, after at least
+// [PTHREAD_DESTRUCTOR_ITERATIONS] iterations of destructor calls for
+// outstanding non-NULL values, there are still some non-NULL values with
+// associated destructors, the implementation stops calling destructors.
+static_assert(PTHREAD_DESTRUCTOR_ITERATIONS == 4, "Small number of iterations");
+static void ThreadStateDestructor(void *thr) {
+ int res = pthread_setspecific(thread_state_key, thr);
+ CHECK_EQ(res, 0);
+}
+
+static void InitializeThreadStateStorage() {
+ int res;
+ CHECK_EQ(thread_state_key, 0);
+ res = pthread_key_create(&thread_state_key, ThreadStateDestructor);
+ CHECK_EQ(res, 0);
+ res = pthread_setspecific(thread_state_key, main_thread_state);
+ CHECK_EQ(res, 0);
+
+ auto dts = (ThreadState *)MmapOrDie(sizeof(ThreadState), "ThreadState");
+ dts->fast_state.SetIgnoreBit();
+ dts->ignore_interceptors = 1;
+ dts->is_dead = true;
+ const_cast<Tid &>(dts->tid) = kInvalidTid;
+ res = internal_mprotect(dts, sizeof(ThreadState), PROT_READ); // immutable
+ CHECK_EQ(res, 0);
+ dead_thread_state = dts;
+}
+
+ThreadState *cur_thread() {
+ // Some interceptors get called before libpthread has been initialized and in
+ // these cases we must avoid calling any pthread APIs.
+ if (UNLIKELY(!thread_state_key)) {
+ return (ThreadState *)main_thread_state;
+ }
+
+ // We only reach this line after InitializeThreadStateStorage() ran, i.e,
+ // after TSan (and therefore libpthread) have been initialized.
+ ThreadState *thr = (ThreadState *)pthread_getspecific(thread_state_key);
+ if (UNLIKELY(!thr)) {
+ thr = (ThreadState *)MmapOrDie(sizeof(ThreadState), "ThreadState");
+ int res = pthread_setspecific(thread_state_key, thr);
+ CHECK_EQ(res, 0);
+ }
+ return thr;
+}
+
+void set_cur_thread(ThreadState *thr) {
+ int res = pthread_setspecific(thread_state_key, thr);
+ CHECK_EQ(res, 0);
+}
+
+void cur_thread_finalize() {
+ ThreadState *thr = (ThreadState *)pthread_getspecific(thread_state_key);
+ CHECK(thr);
+ if (thr == (ThreadState *)main_thread_state) {
+ // Calling dispatch_main() or xpc_main() actually invokes pthread_exit to
+ // exit the main thread. Let's keep the main thread's ThreadState.
+ return;
+ }
+ // Intercepted functions can still get called after cur_thread_finalize()
+ // (called from DestroyThreadState()), so put a fake thread state for "dead"
+ // threads. An alternative solution would be to release the ThreadState
+ // object from THREAD_DESTROY (which is delivered later and on the parent
+ // thread) instead of THREAD_TERMINATE.
+ int res = pthread_setspecific(thread_state_key, dead_thread_state);
+ CHECK_EQ(res, 0);
+ UnmapOrDie(thr, sizeof(ThreadState));
+}
+#endif
+
+static void RegionMemUsage(uptr start, uptr end, uptr *res, uptr *dirty) {
+ vm_address_t address = start;
+ vm_address_t end_address = end;
+ uptr resident_pages = 0;
+ uptr dirty_pages = 0;
+ while (address < end_address) {
+ vm_size_t vm_region_size;
+ mach_msg_type_number_t count = VM_REGION_EXTENDED_INFO_COUNT;
+ vm_region_extended_info_data_t vm_region_info;
+ mach_port_t object_name;
+ kern_return_t ret = vm_region_64(
+ mach_task_self(), &address, &vm_region_size, VM_REGION_EXTENDED_INFO,
+ (vm_region_info_t)&vm_region_info, &count, &object_name);
+ if (ret != KERN_SUCCESS) break;
+
+ resident_pages += vm_region_info.pages_resident;
+ dirty_pages += vm_region_info.pages_dirtied;
+
+ address += vm_region_size;
+ }
+ *res = resident_pages * GetPageSizeCached();
+ *dirty = dirty_pages * GetPageSizeCached();
+}
+
+void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns) {
+ uptr shadow_res, shadow_dirty;
+ uptr meta_res, meta_dirty;
+ RegionMemUsage(ShadowBeg(), ShadowEnd(), &shadow_res, &shadow_dirty);
+ RegionMemUsage(MetaShadowBeg(), MetaShadowEnd(), &meta_res, &meta_dirty);
+
+# if !SANITIZER_GO
+ uptr low_res, low_dirty;
+ uptr high_res, high_dirty;
+ uptr heap_res, heap_dirty;
+ RegionMemUsage(LoAppMemBeg(), LoAppMemEnd(), &low_res, &low_dirty);
+ RegionMemUsage(HiAppMemBeg(), HiAppMemEnd(), &high_res, &high_dirty);
+ RegionMemUsage(HeapMemBeg(), HeapMemEnd(), &heap_res, &heap_dirty);
+#else // !SANITIZER_GO
+ uptr app_res, app_dirty;
+ RegionMemUsage(LoAppMemBeg(), LoAppMemEnd(), &app_res, &app_dirty);
+#endif
+
+ StackDepotStats stacks = StackDepotGetStats();
+ uptr nthread, nlive;
+ ctx->thread_registry.GetNumberOfThreads(&nthread, &nlive);
+ internal_snprintf(
+ buf, buf_size,
+ "shadow (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
+ "meta (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
+# if !SANITIZER_GO
+ "low app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
+ "high app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
+ "heap (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
+# else // !SANITIZER_GO
+ "app (0x%016zx-0x%016zx): resident %zd kB, dirty %zd kB\n"
+# endif
+ "stacks: %zd unique IDs, %zd kB allocated\n"
+ "threads: %zd total, %zd live\n"
+ "------------------------------\n",
+ ShadowBeg(), ShadowEnd(), shadow_res / 1024, shadow_dirty / 1024,
+ MetaShadowBeg(), MetaShadowEnd(), meta_res / 1024, meta_dirty / 1024,
+# if !SANITIZER_GO
+ LoAppMemBeg(), LoAppMemEnd(), low_res / 1024, low_dirty / 1024,
+ HiAppMemBeg(), HiAppMemEnd(), high_res / 1024, high_dirty / 1024,
+ HeapMemBeg(), HeapMemEnd(), heap_res / 1024, heap_dirty / 1024,
+# else // !SANITIZER_GO
+ LoAppMemBeg(), LoAppMemEnd(), app_res / 1024, app_dirty / 1024,
+# endif
+ stacks.n_uniq_ids, stacks.allocated / 1024, nthread, nlive);
+}
+
+# if !SANITIZER_GO
+void InitializeShadowMemoryPlatform() { }
+
+// Register GCD worker threads, which are created without an observable call to
+// pthread_create().
+static void ThreadCreateCallback(uptr thread, bool gcd_worker) {
+ if (gcd_worker) {
+ ThreadState *thr = cur_thread();
+ Processor *proc = ProcCreate();
+ ProcWire(proc, thr);
+ ThreadState *parent_thread_state = nullptr; // No parent.
+ Tid tid = ThreadCreate(parent_thread_state, 0, (uptr)thread, true);
+ CHECK_NE(tid, kMainTid);
+ ThreadStart(thr, tid, GetTid(), ThreadType::Worker);
+ }
+}
+
+// Destroy thread state for *all* threads.
+static void ThreadTerminateCallback(uptr thread) {
+ ThreadState *thr = cur_thread();
+ if (thr->tctx) {
+ DestroyThreadState();
+ }
+}
+#endif
+
+void InitializePlatformEarly() {
+# if !SANITIZER_GO && SANITIZER_IOS
+ uptr max_vm = GetMaxUserVirtualAddress() + 1;
+ if (max_vm != HiAppMemEnd()) {
+ Printf("ThreadSanitizer: unsupported vm address limit %p, expected %p.\n",
+ (void *)max_vm, (void *)HiAppMemEnd());
+ Die();
+ }
+#endif
+}
+
+static uptr longjmp_xor_key = 0;
+
+void InitializePlatform() {
+ DisableCoreDumperIfNecessary();
+#if !SANITIZER_GO
+ CheckAndProtect();
+
+ InitializeThreadStateStorage();
+
+ ThreadEventCallbacks callbacks = {
+ .create = ThreadCreateCallback,
+ .terminate = ThreadTerminateCallback,
+ };
+ InstallPthreadIntrospectionHook(callbacks);
+#endif
+
+ if (GetMacosAlignedVersion() >= MacosVersion(10, 14)) {
+ // Libsystem currently uses a process-global key; this might change.
+ const unsigned kTLSLongjmpXorKeySlot = 0x7;
+ longjmp_xor_key = (uptr)pthread_getspecific(kTLSLongjmpXorKeySlot);
+ }
+}
+
+#ifdef __aarch64__
+# define LONG_JMP_SP_ENV_SLOT \
+ ((GetMacosAlignedVersion() >= MacosVersion(10, 14)) ? 12 : 13)
+#else
+# define LONG_JMP_SP_ENV_SLOT 2
+#endif
+
+uptr ExtractLongJmpSp(uptr *env) {
+ uptr mangled_sp = env[LONG_JMP_SP_ENV_SLOT];
+ uptr sp = mangled_sp ^ longjmp_xor_key;
+ sp = (uptr)ptrauth_auth_data((void *)sp, ptrauth_key_asdb,
+ ptrauth_string_discriminator("sp"));
+ return sp;
+}
+
+#if !SANITIZER_GO
+extern "C" void __tsan_tls_initialization() {}
+
+void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
+ const uptr pc = StackTrace::GetNextInstructionPc(
+ reinterpret_cast<uptr>(__tsan_tls_initialization));
+ // Unlike Linux, we only store a pointer to the ThreadState object in TLS;
+ // just mark the entire range as written to.
+ MemoryRangeImitateWrite(thr, pc, tls_addr, tls_size);
+}
+#endif
+
+#if !SANITIZER_GO
+// Note: this function runs with async signals enabled,
+// so it must not touch any tsan state.
+int call_pthread_cancel_with_cleanup(int (*fn)(void *arg),
+ void (*cleanup)(void *arg), void *arg) {
+ // pthread_cleanup_push/pop are hardcore macros mess.
+ // We can't intercept nor call them w/o including pthread.h.
+ int res;
+ pthread_cleanup_push(cleanup, arg);
+ res = fn(arg);
+ pthread_cleanup_pop(0);
+ return res;
+}
+#endif
+
+} // namespace __tsan
+
+#endif // SANITIZER_APPLE
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_posix.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_posix.cpp
new file mode 100644
index 00000000000..e7dcd664dc0
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_posix.cpp
@@ -0,0 +1,143 @@
+//===-- tsan_platform_posix.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// POSIX-specific code.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_POSIX
+
+# include <dlfcn.h>
+
+# include "sanitizer_common/sanitizer_common.h"
+# include "sanitizer_common/sanitizer_errno.h"
+# include "sanitizer_common/sanitizer_libc.h"
+# include "sanitizer_common/sanitizer_procmaps.h"
+# include "tsan_platform.h"
+# include "tsan_rtl.h"
+
+namespace __tsan {
+
+static const char kShadowMemoryMappingWarning[] =
+ "FATAL: %s can not madvise shadow region [%zx, %zx] with %s (errno: %d)\n";
+static const char kShadowMemoryMappingHint[] =
+ "HINT: if %s is not supported in your environment, you may set "
+ "TSAN_OPTIONS=%s=0\n";
+
+# if !SANITIZER_GO
+void DontDumpShadow(uptr addr, uptr size) {
+ if (common_flags()->use_madv_dontdump)
+ if (!DontDumpShadowMemory(addr, size)) {
+ Printf(kShadowMemoryMappingWarning, SanitizerToolName, addr, addr + size,
+ "MADV_DONTDUMP", errno);
+ Printf(kShadowMemoryMappingHint, "MADV_DONTDUMP", "use_madv_dontdump");
+ Die();
+ }
+}
+
+void InitializeShadowMemory() {
+ // Map memory shadow.
+ if (!MmapFixedSuperNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(),
+ "shadow")) {
+ Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
+ Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n");
+ Die();
+ }
+ // This memory range is used for thread stacks and large user mmaps.
+ // Frequently a thread uses only a small part of stack and similarly
+ // a program uses a small part of large mmap. On some programs
+ // we see 20% memory usage reduction without huge pages for this range.
+ DontDumpShadow(ShadowBeg(), ShadowEnd() - ShadowBeg());
+ DPrintf("memory shadow: %zx-%zx (%zuGB)\n",
+ ShadowBeg(), ShadowEnd(),
+ (ShadowEnd() - ShadowBeg()) >> 30);
+
+ // Map meta shadow.
+ const uptr meta = MetaShadowBeg();
+ const uptr meta_size = MetaShadowEnd() - meta;
+ if (!MmapFixedSuperNoReserve(meta, meta_size, "meta shadow")) {
+ Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
+ Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n");
+ Die();
+ }
+ DontDumpShadow(meta, meta_size);
+ DPrintf("meta shadow: %zx-%zx (%zuGB)\n",
+ meta, meta + meta_size, meta_size >> 30);
+
+ InitializeShadowMemoryPlatform();
+
+ on_initialize = reinterpret_cast<void (*)(void)>(
+ dlsym(RTLD_DEFAULT, "__tsan_on_initialize"));
+ on_finalize =
+ reinterpret_cast<int (*)(int)>(dlsym(RTLD_DEFAULT, "__tsan_on_finalize"));
+}
+
+static bool TryProtectRange(uptr beg, uptr end) {
+ CHECK_LE(beg, end);
+ if (beg == end)
+ return true;
+ return beg == (uptr)MmapFixedNoAccess(beg, end - beg);
+}
+
+static void ProtectRange(uptr beg, uptr end) {
+ if (!TryProtectRange(beg, end)) {
+ Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end);
+ Printf("FATAL: Make sure you are not using unlimited stack\n");
+ Die();
+ }
+}
+
+void CheckAndProtect() {
+ // Ensure that the binary is indeed compiled with -pie.
+ MemoryMappingLayout proc_maps(true);
+ MemoryMappedSegment segment;
+ while (proc_maps.Next(&segment)) {
+ if (IsAppMem(segment.start)) continue;
+ if (segment.start >= HeapMemEnd() && segment.start < HeapEnd()) continue;
+ if (segment.protection == 0) // Zero page or mprotected.
+ continue;
+ if (segment.start >= VdsoBeg()) // vdso
+ break;
+ Printf("FATAL: ThreadSanitizer: unexpected memory mapping 0x%zx-0x%zx\n",
+ segment.start, segment.end);
+ Die();
+ }
+
+# if SANITIZER_IOS && !SANITIZER_IOSSIM
+ ProtectRange(HeapMemEnd(), ShadowBeg());
+ ProtectRange(ShadowEnd(), MetaShadowBeg());
+ ProtectRange(MetaShadowEnd(), HiAppMemBeg());
+# else
+ ProtectRange(LoAppMemEnd(), ShadowBeg());
+ ProtectRange(ShadowEnd(), MetaShadowBeg());
+ if (MidAppMemBeg()) {
+ ProtectRange(MetaShadowEnd(), MidAppMemBeg());
+ ProtectRange(MidAppMemEnd(), HeapMemBeg());
+ } else {
+ ProtectRange(MetaShadowEnd(), HeapMemBeg());
+ }
+ ProtectRange(HeapEnd(), HiAppMemBeg());
+# endif
+
+# if defined(__s390x__)
+ // Protect the rest of the address space.
+ const uptr user_addr_max_l4 = 0x0020000000000000ull;
+ const uptr user_addr_max_l5 = 0xfffffffffffff000ull;
+ // All the maintained s390x kernels support at least 4-level page tables.
+ ProtectRange(HiAppMemEnd(), user_addr_max_l4);
+ // Older s390x kernels may not support 5-level page tables.
+ TryProtectRange(user_addr_max_l4, user_addr_max_l5);
+#endif
+}
+#endif
+
+} // namespace __tsan
+
+#endif // SANITIZER_POSIX
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_windows.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_windows.cpp
new file mode 100644
index 00000000000..eb8f354742f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_platform_windows.cpp
@@ -0,0 +1,33 @@
+//===-- tsan_platform_windows.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Windows-specific code.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_WINDOWS
+
+#include "tsan_platform.h"
+
+#include <stdlib.h>
+
+namespace __tsan {
+
+void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns) {}
+
+void InitializePlatformEarly() {
+}
+
+void InitializePlatform() {
+}
+
+} // namespace __tsan
+
+#endif // SANITIZER_WINDOWS
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_preinit.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_preinit.cpp
new file mode 100644
index 00000000000..205bdbf93b2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_preinit.cpp
@@ -0,0 +1,26 @@
+//===-- tsan_preinit.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer.
+//
+// Call __tsan_init at the very early stage of process startup.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "tsan_interface.h"
+
+#if SANITIZER_CAN_USE_PREINIT_ARRAY
+
+// The symbol is called __local_tsan_preinit, because it's not intended to be
+// exported.
+// This code linked into the main executable when -fsanitize=thread is in
+// the link flags. It can only use exported interface functions.
+__attribute__((section(".preinit_array"), used))
+void (*__local_tsan_preinit)(void) = __tsan_init;
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_report.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_report.cpp
new file mode 100644
index 00000000000..9b03adc16b9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_report.cpp
@@ -0,0 +1,477 @@
+//===-- tsan_report.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_report.h"
+#include "tsan_platform.h"
+#include "tsan_rtl.h"
+#include "sanitizer_common/sanitizer_file.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
+#include "sanitizer_common/sanitizer_stacktrace_printer.h"
+
+namespace __tsan {
+
+class Decorator: public __sanitizer::SanitizerCommonDecorator {
+ public:
+ Decorator() : SanitizerCommonDecorator() { }
+ const char *Access() { return Blue(); }
+ const char *ThreadDescription() { return Cyan(); }
+ const char *Location() { return Green(); }
+ const char *Sleep() { return Yellow(); }
+ const char *Mutex() { return Magenta(); }
+};
+
+ReportDesc::ReportDesc()
+ : tag(kExternalTagNone)
+ , stacks()
+ , mops()
+ , locs()
+ , mutexes()
+ , threads()
+ , unique_tids()
+ , sleep()
+ , count() {
+}
+
+ReportMop::ReportMop()
+ : mset() {
+}
+
+ReportDesc::~ReportDesc() {
+ // FIXME(dvyukov): it must be leaking a lot of memory.
+}
+
+#if !SANITIZER_GO
+
+const int kThreadBufSize = 32;
+const char *thread_name(char *buf, Tid tid) {
+ if (tid == kMainTid)
+ return "main thread";
+ internal_snprintf(buf, kThreadBufSize, "thread T%d", tid);
+ return buf;
+}
+
+static const char *ReportTypeString(ReportType typ, uptr tag) {
+ switch (typ) {
+ case ReportTypeRace:
+ return "data race";
+ case ReportTypeVptrRace:
+ return "data race on vptr (ctor/dtor vs virtual call)";
+ case ReportTypeUseAfterFree:
+ return "heap-use-after-free";
+ case ReportTypeVptrUseAfterFree:
+ return "heap-use-after-free (virtual call vs free)";
+ case ReportTypeExternalRace: {
+ const char *str = GetReportHeaderFromTag(tag);
+ return str ? str : "race on external object";
+ }
+ case ReportTypeThreadLeak:
+ return "thread leak";
+ case ReportTypeMutexDestroyLocked:
+ return "destroy of a locked mutex";
+ case ReportTypeMutexDoubleLock:
+ return "double lock of a mutex";
+ case ReportTypeMutexInvalidAccess:
+ return "use of an invalid mutex (e.g. uninitialized or destroyed)";
+ case ReportTypeMutexBadUnlock:
+ return "unlock of an unlocked mutex (or by a wrong thread)";
+ case ReportTypeMutexBadReadLock:
+ return "read lock of a write locked mutex";
+ case ReportTypeMutexBadReadUnlock:
+ return "read unlock of a write locked mutex";
+ case ReportTypeSignalUnsafe:
+ return "signal-unsafe call inside of a signal";
+ case ReportTypeErrnoInSignal:
+ return "signal handler spoils errno";
+ case ReportTypeDeadlock:
+ return "lock-order-inversion (potential deadlock)";
+ // No default case so compiler warns us if we miss one
+ }
+ UNREACHABLE("missing case");
+}
+
+#if SANITIZER_APPLE
+static const char *const kInterposedFunctionPrefix = "wrap_";
+#else
+static const char *const kInterposedFunctionPrefix = "__interceptor_";
+#endif
+
+void PrintStack(const ReportStack *ent) {
+ if (ent == 0 || ent->frames == 0) {
+ Printf(" [failed to restore the stack]\n\n");
+ return;
+ }
+ SymbolizedStack *frame = ent->frames;
+ for (int i = 0; frame && frame->info.address; frame = frame->next, i++) {
+ InternalScopedString res;
+ RenderFrame(&res, common_flags()->stack_trace_format, i,
+ frame->info.address, &frame->info,
+ common_flags()->symbolize_vs_style,
+ common_flags()->strip_path_prefix, kInterposedFunctionPrefix);
+ Printf("%s\n", res.data());
+ }
+ Printf("\n");
+}
+
+static void PrintMutexSet(Vector<ReportMopMutex> const& mset) {
+ for (uptr i = 0; i < mset.Size(); i++) {
+ if (i == 0)
+ Printf(" (mutexes:");
+ const ReportMopMutex m = mset[i];
+ Printf(" %s M%u", m.write ? "write" : "read", m.id);
+ Printf(i == mset.Size() - 1 ? ")" : ",");
+ }
+}
+
+static const char *MopDesc(bool first, bool write, bool atomic) {
+ return atomic ? (first ? (write ? "Atomic write" : "Atomic read")
+ : (write ? "Previous atomic write" : "Previous atomic read"))
+ : (first ? (write ? "Write" : "Read")
+ : (write ? "Previous write" : "Previous read"));
+}
+
+static const char *ExternalMopDesc(bool first, bool write) {
+ return first ? (write ? "Modifying" : "Read-only")
+ : (write ? "Previous modifying" : "Previous read-only");
+}
+
+static void PrintMop(const ReportMop *mop, bool first) {
+ Decorator d;
+ char thrbuf[kThreadBufSize];
+ Printf("%s", d.Access());
+ if (mop->external_tag == kExternalTagNone) {
+ Printf(" %s of size %d at %p by %s",
+ MopDesc(first, mop->write, mop->atomic), mop->size,
+ (void *)mop->addr, thread_name(thrbuf, mop->tid));
+ } else {
+ const char *object_type = GetObjectTypeFromTag(mop->external_tag);
+ if (object_type == nullptr)
+ object_type = "external object";
+ Printf(" %s access of %s at %p by %s",
+ ExternalMopDesc(first, mop->write), object_type,
+ (void *)mop->addr, thread_name(thrbuf, mop->tid));
+ }
+ PrintMutexSet(mop->mset);
+ Printf(":\n");
+ Printf("%s", d.Default());
+ PrintStack(mop->stack);
+}
+
+static void PrintLocation(const ReportLocation *loc) {
+ Decorator d;
+ char thrbuf[kThreadBufSize];
+ bool print_stack = false;
+ Printf("%s", d.Location());
+ if (loc->type == ReportLocationGlobal) {
+ const DataInfo &global = loc->global;
+ if (global.size != 0)
+ Printf(" Location is global '%s' of size %zu at %p (%s+0x%zx)\n\n",
+ global.name, global.size, reinterpret_cast<void *>(global.start),
+ StripModuleName(global.module), global.module_offset);
+ else
+ Printf(" Location is global '%s' at %p (%s+0x%zx)\n\n", global.name,
+ reinterpret_cast<void *>(global.start),
+ StripModuleName(global.module), global.module_offset);
+ } else if (loc->type == ReportLocationHeap) {
+ char thrbuf[kThreadBufSize];
+ const char *object_type = GetObjectTypeFromTag(loc->external_tag);
+ if (!object_type) {
+ Printf(" Location is heap block of size %zu at %p allocated by %s:\n",
+ loc->heap_chunk_size,
+ reinterpret_cast<void *>(loc->heap_chunk_start),
+ thread_name(thrbuf, loc->tid));
+ } else {
+ Printf(" Location is %s of size %zu at %p allocated by %s:\n",
+ object_type, loc->heap_chunk_size,
+ reinterpret_cast<void *>(loc->heap_chunk_start),
+ thread_name(thrbuf, loc->tid));
+ }
+ print_stack = true;
+ } else if (loc->type == ReportLocationStack) {
+ Printf(" Location is stack of %s.\n\n", thread_name(thrbuf, loc->tid));
+ } else if (loc->type == ReportLocationTLS) {
+ Printf(" Location is TLS of %s.\n\n", thread_name(thrbuf, loc->tid));
+ } else if (loc->type == ReportLocationFD) {
+ Printf(" Location is file descriptor %d %s by %s at:\n", loc->fd,
+ loc->fd_closed ? "destroyed" : "created",
+ thread_name(thrbuf, loc->tid));
+ print_stack = true;
+ }
+ Printf("%s", d.Default());
+ if (print_stack)
+ PrintStack(loc->stack);
+}
+
+static void PrintMutexShort(const ReportMutex *rm, const char *after) {
+ Decorator d;
+ Printf("%sM%d%s%s", d.Mutex(), rm->id, d.Default(), after);
+}
+
+static void PrintMutexShortWithAddress(const ReportMutex *rm,
+ const char *after) {
+ Decorator d;
+ Printf("%sM%d (%p)%s%s", d.Mutex(), rm->id,
+ reinterpret_cast<void *>(rm->addr), d.Default(), after);
+}
+
+static void PrintMutex(const ReportMutex *rm) {
+ Decorator d;
+ Printf("%s", d.Mutex());
+ Printf(" Mutex M%u (%p) created at:\n", rm->id,
+ reinterpret_cast<void *>(rm->addr));
+ Printf("%s", d.Default());
+ PrintStack(rm->stack);
+}
+
+static void PrintThread(const ReportThread *rt) {
+ Decorator d;
+ if (rt->id == kMainTid) // Little sense in describing the main thread.
+ return;
+ Printf("%s", d.ThreadDescription());
+ Printf(" Thread T%d", rt->id);
+ if (rt->name && rt->name[0] != '\0')
+ Printf(" '%s'", rt->name);
+ char thrbuf[kThreadBufSize];
+ const char *thread_status = rt->running ? "running" : "finished";
+ if (rt->thread_type == ThreadType::Worker) {
+ Printf(" (tid=%llu, %s) is a GCD worker thread\n", rt->os_id,
+ thread_status);
+ Printf("\n");
+ Printf("%s", d.Default());
+ return;
+ }
+ Printf(" (tid=%llu, %s) created by %s", rt->os_id, thread_status,
+ thread_name(thrbuf, rt->parent_tid));
+ if (rt->stack)
+ Printf(" at:");
+ Printf("\n");
+ Printf("%s", d.Default());
+ PrintStack(rt->stack);
+}
+
+static void PrintSleep(const ReportStack *s) {
+ Decorator d;
+ Printf("%s", d.Sleep());
+ Printf(" As if synchronized via sleep:\n");
+ Printf("%s", d.Default());
+ PrintStack(s);
+}
+
+static ReportStack *ChooseSummaryStack(const ReportDesc *rep) {
+ if (rep->mops.Size())
+ return rep->mops[0]->stack;
+ if (rep->stacks.Size())
+ return rep->stacks[0];
+ if (rep->mutexes.Size())
+ return rep->mutexes[0]->stack;
+ if (rep->threads.Size())
+ return rep->threads[0]->stack;
+ return 0;
+}
+
+static bool FrameIsInternal(const SymbolizedStack *frame) {
+ if (frame == 0)
+ return false;
+ const char *file = frame->info.file;
+ const char *module = frame->info.module;
+ if (file != 0 &&
+ (internal_strstr(file, "tsan_interceptors_posix.cpp") ||
+ internal_strstr(file, "sanitizer_common_interceptors.inc") ||
+ internal_strstr(file, "tsan_interface_")))
+ return true;
+ if (module != 0 && (internal_strstr(module, "libclang_rt.tsan_")))
+ return true;
+ return false;
+}
+
+static SymbolizedStack *SkipTsanInternalFrames(SymbolizedStack *frames) {
+ while (FrameIsInternal(frames) && frames->next)
+ frames = frames->next;
+ return frames;
+}
+
+void PrintReport(const ReportDesc *rep) {
+ Decorator d;
+ Printf("==================\n");
+ const char *rep_typ_str = ReportTypeString(rep->typ, rep->tag);
+ Printf("%s", d.Warning());
+ Printf("WARNING: ThreadSanitizer: %s (pid=%d)\n", rep_typ_str,
+ (int)internal_getpid());
+ Printf("%s", d.Default());
+
+ if (rep->typ == ReportTypeErrnoInSignal)
+ Printf(" Signal %u handler invoked at:\n", rep->signum);
+
+ if (rep->typ == ReportTypeDeadlock) {
+ char thrbuf[kThreadBufSize];
+ Printf(" Cycle in lock order graph: ");
+ for (uptr i = 0; i < rep->mutexes.Size(); i++)
+ PrintMutexShortWithAddress(rep->mutexes[i], " => ");
+ PrintMutexShort(rep->mutexes[0], "\n\n");
+ CHECK_GT(rep->mutexes.Size(), 0U);
+ CHECK_EQ(rep->mutexes.Size() * (flags()->second_deadlock_stack ? 2 : 1),
+ rep->stacks.Size());
+ for (uptr i = 0; i < rep->mutexes.Size(); i++) {
+ Printf(" Mutex ");
+ PrintMutexShort(rep->mutexes[(i + 1) % rep->mutexes.Size()],
+ " acquired here while holding mutex ");
+ PrintMutexShort(rep->mutexes[i], " in ");
+ Printf("%s", d.ThreadDescription());
+ Printf("%s:\n", thread_name(thrbuf, rep->unique_tids[i]));
+ Printf("%s", d.Default());
+ if (flags()->second_deadlock_stack) {
+ PrintStack(rep->stacks[2*i]);
+ Printf(" Mutex ");
+ PrintMutexShort(rep->mutexes[i],
+ " previously acquired by the same thread here:\n");
+ PrintStack(rep->stacks[2*i+1]);
+ } else {
+ PrintStack(rep->stacks[i]);
+ if (i == 0)
+ Printf(" Hint: use TSAN_OPTIONS=second_deadlock_stack=1 "
+ "to get more informative warning message\n\n");
+ }
+ }
+ } else {
+ for (uptr i = 0; i < rep->stacks.Size(); i++) {
+ if (i)
+ Printf(" and:\n");
+ PrintStack(rep->stacks[i]);
+ }
+ }
+
+ for (uptr i = 0; i < rep->mops.Size(); i++)
+ PrintMop(rep->mops[i], i == 0);
+
+ if (rep->sleep)
+ PrintSleep(rep->sleep);
+
+ for (uptr i = 0; i < rep->locs.Size(); i++)
+ PrintLocation(rep->locs[i]);
+
+ if (rep->typ != ReportTypeDeadlock) {
+ for (uptr i = 0; i < rep->mutexes.Size(); i++)
+ PrintMutex(rep->mutexes[i]);
+ }
+
+ for (uptr i = 0; i < rep->threads.Size(); i++)
+ PrintThread(rep->threads[i]);
+
+ if (rep->typ == ReportTypeThreadLeak && rep->count > 1)
+ Printf(" And %d more similar thread leaks.\n\n", rep->count - 1);
+
+ if (ReportStack *stack = ChooseSummaryStack(rep)) {
+ if (SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames))
+ ReportErrorSummary(rep_typ_str, frame->info);
+ }
+
+ if (common_flags()->print_module_map == 2)
+ DumpProcessMap();
+
+ Printf("==================\n");
+}
+
+#else // #if !SANITIZER_GO
+
+const Tid kMainGoroutineId = 1;
+
+void PrintStack(const ReportStack *ent) {
+ if (ent == 0 || ent->frames == 0) {
+ Printf(" [failed to restore the stack]\n");
+ return;
+ }
+ SymbolizedStack *frame = ent->frames;
+ for (int i = 0; frame; frame = frame->next, i++) {
+ const AddressInfo &info = frame->info;
+ Printf(" %s()\n %s:%d +0x%zx\n", info.function,
+ StripPathPrefix(info.file, common_flags()->strip_path_prefix),
+ info.line, info.module_offset);
+ }
+}
+
+static void PrintMop(const ReportMop *mop, bool first) {
+ Printf("\n");
+ Printf("%s at %p by ",
+ (first ? (mop->write ? "Write" : "Read")
+ : (mop->write ? "Previous write" : "Previous read")),
+ reinterpret_cast<void *>(mop->addr));
+ if (mop->tid == kMainGoroutineId)
+ Printf("main goroutine:\n");
+ else
+ Printf("goroutine %d:\n", mop->tid);
+ PrintStack(mop->stack);
+}
+
+static void PrintLocation(const ReportLocation *loc) {
+ switch (loc->type) {
+ case ReportLocationHeap: {
+ Printf("\n");
+ Printf("Heap block of size %zu at %p allocated by ", loc->heap_chunk_size,
+ reinterpret_cast<void *>(loc->heap_chunk_start));
+ if (loc->tid == kMainGoroutineId)
+ Printf("main goroutine:\n");
+ else
+ Printf("goroutine %d:\n", loc->tid);
+ PrintStack(loc->stack);
+ break;
+ }
+ case ReportLocationGlobal: {
+ Printf("\n");
+ Printf("Global var %s of size %zu at %p declared at %s:%zu\n",
+ loc->global.name, loc->global.size,
+ reinterpret_cast<void *>(loc->global.start), loc->global.file,
+ loc->global.line);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void PrintThread(const ReportThread *rt) {
+ if (rt->id == kMainGoroutineId)
+ return;
+ Printf("\n");
+ Printf("Goroutine %d (%s) created at:\n",
+ rt->id, rt->running ? "running" : "finished");
+ PrintStack(rt->stack);
+}
+
+void PrintReport(const ReportDesc *rep) {
+ Printf("==================\n");
+ if (rep->typ == ReportTypeRace) {
+ Printf("WARNING: DATA RACE");
+ for (uptr i = 0; i < rep->mops.Size(); i++)
+ PrintMop(rep->mops[i], i == 0);
+ for (uptr i = 0; i < rep->locs.Size(); i++)
+ PrintLocation(rep->locs[i]);
+ for (uptr i = 0; i < rep->threads.Size(); i++)
+ PrintThread(rep->threads[i]);
+ } else if (rep->typ == ReportTypeDeadlock) {
+ Printf("WARNING: DEADLOCK\n");
+ for (uptr i = 0; i < rep->mutexes.Size(); i++) {
+ Printf("Goroutine %d lock mutex %u while holding mutex %u:\n", 999,
+ rep->mutexes[i]->id,
+ rep->mutexes[(i + 1) % rep->mutexes.Size()]->id);
+ PrintStack(rep->stacks[2*i]);
+ Printf("\n");
+ Printf("Mutex %u was previously locked here:\n",
+ rep->mutexes[(i + 1) % rep->mutexes.Size()]->id);
+ PrintStack(rep->stacks[2*i + 1]);
+ Printf("\n");
+ }
+ }
+ Printf("==================\n");
+}
+
+#endif
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_report.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_report.h
new file mode 100644
index 00000000000..3c88864af14
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_report.h
@@ -0,0 +1,128 @@
+//===-- tsan_report.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_REPORT_H
+#define TSAN_REPORT_H
+
+#include "sanitizer_common/sanitizer_symbolizer.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
+#include "sanitizer_common/sanitizer_vector.h"
+#include "tsan_defs.h"
+
+namespace __tsan {
+
+enum ReportType {
+ ReportTypeRace,
+ ReportTypeVptrRace,
+ ReportTypeUseAfterFree,
+ ReportTypeVptrUseAfterFree,
+ ReportTypeExternalRace,
+ ReportTypeThreadLeak,
+ ReportTypeMutexDestroyLocked,
+ ReportTypeMutexDoubleLock,
+ ReportTypeMutexInvalidAccess,
+ ReportTypeMutexBadUnlock,
+ ReportTypeMutexBadReadLock,
+ ReportTypeMutexBadReadUnlock,
+ ReportTypeSignalUnsafe,
+ ReportTypeErrnoInSignal,
+ ReportTypeDeadlock
+};
+
+struct ReportStack {
+ SymbolizedStack *frames = nullptr;
+ bool suppressable = false;
+};
+
+struct ReportMopMutex {
+ int id;
+ bool write;
+};
+
+struct ReportMop {
+ int tid;
+ uptr addr;
+ int size;
+ bool write;
+ bool atomic;
+ uptr external_tag;
+ Vector<ReportMopMutex> mset;
+ ReportStack *stack;
+
+ ReportMop();
+};
+
+enum ReportLocationType {
+ ReportLocationGlobal,
+ ReportLocationHeap,
+ ReportLocationStack,
+ ReportLocationTLS,
+ ReportLocationFD
+};
+
+struct ReportLocation {
+ ReportLocationType type = ReportLocationGlobal;
+ DataInfo global = {};
+ uptr heap_chunk_start = 0;
+ uptr heap_chunk_size = 0;
+ uptr external_tag = 0;
+ Tid tid = kInvalidTid;
+ int fd = 0;
+ bool fd_closed = false;
+ bool suppressable = false;
+ ReportStack *stack = nullptr;
+};
+
+struct ReportThread {
+ Tid id;
+ tid_t os_id;
+ bool running;
+ ThreadType thread_type;
+ char *name;
+ Tid parent_tid;
+ ReportStack *stack;
+};
+
+struct ReportMutex {
+ int id;
+ uptr addr;
+ ReportStack *stack;
+};
+
+class ReportDesc {
+ public:
+ ReportType typ;
+ uptr tag;
+ Vector<ReportStack*> stacks;
+ Vector<ReportMop*> mops;
+ Vector<ReportLocation*> locs;
+ Vector<ReportMutex*> mutexes;
+ Vector<ReportThread*> threads;
+ Vector<Tid> unique_tids;
+ ReportStack *sleep;
+ int count;
+ int signum = 0;
+
+ ReportDesc();
+ ~ReportDesc();
+
+ private:
+ ReportDesc(const ReportDesc&);
+ void operator = (const ReportDesc&);
+};
+
+// Format and output the report to the console/log. No additional logic.
+void PrintReport(const ReportDesc *rep);
+void PrintStack(const ReportStack *stack);
+
+} // namespace __tsan
+
+#endif // TSAN_REPORT_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl.cpp
new file mode 100644
index 00000000000..6b1ec1d04fd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl.cpp
@@ -0,0 +1,1123 @@
+//===-- tsan_rtl.cpp ------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Main file (entry points) for the TSan run-time.
+//===----------------------------------------------------------------------===//
+
+#include "tsan_rtl.h"
+
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_file.h"
+#include "sanitizer_common/sanitizer_interface_internal.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+#include "tsan_defs.h"
+#include "tsan_interface.h"
+#include "tsan_mman.h"
+#include "tsan_platform.h"
+#include "tsan_suppressions.h"
+#include "tsan_symbolize.h"
+#include "ubsan/ubsan_init.h"
+
+volatile int __tsan_resumed = 0;
+
+extern "C" void __tsan_resume() {
+ __tsan_resumed = 1;
+}
+
+SANITIZER_WEAK_DEFAULT_IMPL
+void __tsan_test_only_on_fork() {}
+
+namespace __tsan {
+
+#if !SANITIZER_GO
+void (*on_initialize)(void);
+int (*on_finalize)(int);
+#endif
+
+#if !SANITIZER_GO && !SANITIZER_APPLE
+__attribute__((tls_model("initial-exec")))
+THREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(
+ SANITIZER_CACHE_LINE_SIZE);
+#endif
+static char ctx_placeholder[sizeof(Context)] ALIGNED(SANITIZER_CACHE_LINE_SIZE);
+Context *ctx;
+
+// Can be overriden by a front-end.
+#ifdef TSAN_EXTERNAL_HOOKS
+bool OnFinalize(bool failed);
+void OnInitialize();
+#else
+SANITIZER_WEAK_CXX_DEFAULT_IMPL
+bool OnFinalize(bool failed) {
+# if !SANITIZER_GO
+ if (on_finalize)
+ return on_finalize(failed);
+# endif
+ return failed;
+}
+
+SANITIZER_WEAK_CXX_DEFAULT_IMPL
+void OnInitialize() {
+# if !SANITIZER_GO
+ if (on_initialize)
+ on_initialize();
+# endif
+}
+#endif
+
+static TracePart* TracePartAlloc(ThreadState* thr) {
+ TracePart* part = nullptr;
+ {
+ Lock lock(&ctx->slot_mtx);
+ uptr max_parts = Trace::kMinParts + flags()->history_size;
+ Trace* trace = &thr->tctx->trace;
+ if (trace->parts_allocated == max_parts ||
+ ctx->trace_part_finished_excess) {
+ part = ctx->trace_part_recycle.PopFront();
+ DPrintf("#%d: TracePartAlloc: part=%p\n", thr->tid, part);
+ if (part && part->trace) {
+ Trace* trace1 = part->trace;
+ Lock trace_lock(&trace1->mtx);
+ part->trace = nullptr;
+ TracePart* part1 = trace1->parts.PopFront();
+ CHECK_EQ(part, part1);
+ if (trace1->parts_allocated > trace1->parts.Size()) {
+ ctx->trace_part_finished_excess +=
+ trace1->parts_allocated - trace1->parts.Size();
+ trace1->parts_allocated = trace1->parts.Size();
+ }
+ }
+ }
+ if (trace->parts_allocated < max_parts) {
+ trace->parts_allocated++;
+ if (ctx->trace_part_finished_excess)
+ ctx->trace_part_finished_excess--;
+ }
+ if (!part)
+ ctx->trace_part_total_allocated++;
+ else if (ctx->trace_part_recycle_finished)
+ ctx->trace_part_recycle_finished--;
+ }
+ if (!part)
+ part = new (MmapOrDie(sizeof(*part), "TracePart")) TracePart();
+ return part;
+}
+
+static void TracePartFree(TracePart* part) SANITIZER_REQUIRES(ctx->slot_mtx) {
+ DCHECK(part->trace);
+ part->trace = nullptr;
+ ctx->trace_part_recycle.PushFront(part);
+}
+
+void TraceResetForTesting() {
+ Lock lock(&ctx->slot_mtx);
+ while (auto* part = ctx->trace_part_recycle.PopFront()) {
+ if (auto trace = part->trace)
+ CHECK_EQ(trace->parts.PopFront(), part);
+ UnmapOrDie(part, sizeof(*part));
+ }
+ ctx->trace_part_total_allocated = 0;
+ ctx->trace_part_recycle_finished = 0;
+ ctx->trace_part_finished_excess = 0;
+}
+
+static void DoResetImpl(uptr epoch) {
+ ThreadRegistryLock lock0(&ctx->thread_registry);
+ Lock lock1(&ctx->slot_mtx);
+ CHECK_EQ(ctx->global_epoch, epoch);
+ ctx->global_epoch++;
+ CHECK(!ctx->resetting);
+ ctx->resetting = true;
+ for (u32 i = ctx->thread_registry.NumThreadsLocked(); i--;) {
+ ThreadContext* tctx = (ThreadContext*)ctx->thread_registry.GetThreadLocked(
+ static_cast<Tid>(i));
+ // Potentially we could purge all ThreadStatusDead threads from the
+ // registry. Since we reset all shadow, they can't race with anything
+ // anymore. However, their tid's can still be stored in some aux places
+ // (e.g. tid of thread that created something).
+ auto trace = &tctx->trace;
+ Lock lock(&trace->mtx);
+ bool attached = tctx->thr && tctx->thr->slot;
+ auto parts = &trace->parts;
+ bool local = false;
+ while (!parts->Empty()) {
+ auto part = parts->Front();
+ local = local || part == trace->local_head;
+ if (local)
+ CHECK(!ctx->trace_part_recycle.Queued(part));
+ else
+ ctx->trace_part_recycle.Remove(part);
+ if (attached && parts->Size() == 1) {
+ // The thread is running and this is the last/current part.
+ // Set the trace position to the end of the current part
+ // to force the thread to call SwitchTracePart and re-attach
+ // to a new slot and allocate a new trace part.
+ // Note: the thread is concurrently modifying the position as well,
+ // so this is only best-effort. The thread can only modify position
+ // within this part, because switching parts is protected by
+ // slot/trace mutexes that we hold here.
+ atomic_store_relaxed(
+ &tctx->thr->trace_pos,
+ reinterpret_cast<uptr>(&part->events[TracePart::kSize]));
+ break;
+ }
+ parts->Remove(part);
+ TracePartFree(part);
+ }
+ CHECK_LE(parts->Size(), 1);
+ trace->local_head = parts->Front();
+ if (tctx->thr && !tctx->thr->slot) {
+ atomic_store_relaxed(&tctx->thr->trace_pos, 0);
+ tctx->thr->trace_prev_pc = 0;
+ }
+ if (trace->parts_allocated > trace->parts.Size()) {
+ ctx->trace_part_finished_excess +=
+ trace->parts_allocated - trace->parts.Size();
+ trace->parts_allocated = trace->parts.Size();
+ }
+ }
+ while (ctx->slot_queue.PopFront()) {
+ }
+ for (auto& slot : ctx->slots) {
+ slot.SetEpoch(kEpochZero);
+ slot.journal.Reset();
+ slot.thr = nullptr;
+ ctx->slot_queue.PushBack(&slot);
+ }
+
+ DPrintf("Resetting shadow...\n");
+ auto shadow_begin = ShadowBeg();
+ auto shadow_end = ShadowEnd();
+#if SANITIZER_GO
+ CHECK_NE(0, ctx->mapped_shadow_begin);
+ shadow_begin = ctx->mapped_shadow_begin;
+ shadow_end = ctx->mapped_shadow_end;
+ VPrintf(2, "shadow_begin-shadow_end: (0x%zx-0x%zx)\n",
+ shadow_begin, shadow_end);
+#endif
+
+#if SANITIZER_WINDOWS
+ auto resetFailed =
+ !ZeroMmapFixedRegion(shadow_begin, shadow_end - shadow_begin);
+#else
+ auto resetFailed =
+ !MmapFixedSuperNoReserve(shadow_begin, shadow_end-shadow_begin, "shadow");
+# if !SANITIZER_GO
+ DontDumpShadow(shadow_begin, shadow_end - shadow_begin);
+# endif
+#endif
+ if (resetFailed) {
+ Printf("failed to reset shadow memory\n");
+ Die();
+ }
+ DPrintf("Resetting meta shadow...\n");
+ ctx->metamap.ResetClocks();
+ StoreShadow(&ctx->last_spurious_race, Shadow::kEmpty);
+ ctx->resetting = false;
+}
+
+// Clang does not understand locking all slots in the loop:
+// error: expecting mutex 'slot.mtx' to be held at start of each loop
+void DoReset(ThreadState* thr, uptr epoch) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ for (auto& slot : ctx->slots) {
+ slot.mtx.Lock();
+ if (UNLIKELY(epoch == 0))
+ epoch = ctx->global_epoch;
+ if (UNLIKELY(epoch != ctx->global_epoch)) {
+ // Epoch can't change once we've locked the first slot.
+ CHECK_EQ(slot.sid, 0);
+ slot.mtx.Unlock();
+ return;
+ }
+ }
+ DPrintf("#%d: DoReset epoch=%lu\n", thr ? thr->tid : -1, epoch);
+ DoResetImpl(epoch);
+ for (auto& slot : ctx->slots) slot.mtx.Unlock();
+}
+
+void FlushShadowMemory() { DoReset(nullptr, 0); }
+
+static TidSlot* FindSlotAndLock(ThreadState* thr)
+ SANITIZER_ACQUIRE(thr->slot->mtx) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ CHECK(!thr->slot);
+ TidSlot* slot = nullptr;
+ for (;;) {
+ uptr epoch;
+ {
+ Lock lock(&ctx->slot_mtx);
+ epoch = ctx->global_epoch;
+ if (slot) {
+ // This is an exhausted slot from the previous iteration.
+ if (ctx->slot_queue.Queued(slot))
+ ctx->slot_queue.Remove(slot);
+ thr->slot_locked = false;
+ slot->mtx.Unlock();
+ }
+ for (;;) {
+ slot = ctx->slot_queue.PopFront();
+ if (!slot)
+ break;
+ if (slot->epoch() != kEpochLast) {
+ ctx->slot_queue.PushBack(slot);
+ break;
+ }
+ }
+ }
+ if (!slot) {
+ DoReset(thr, epoch);
+ continue;
+ }
+ slot->mtx.Lock();
+ CHECK(!thr->slot_locked);
+ thr->slot_locked = true;
+ if (slot->thr) {
+ DPrintf("#%d: preempting sid=%d tid=%d\n", thr->tid, (u32)slot->sid,
+ slot->thr->tid);
+ slot->SetEpoch(slot->thr->fast_state.epoch());
+ slot->thr = nullptr;
+ }
+ if (slot->epoch() != kEpochLast)
+ return slot;
+ }
+}
+
+void SlotAttachAndLock(ThreadState* thr) {
+ TidSlot* slot = FindSlotAndLock(thr);
+ DPrintf("#%d: SlotAttach: slot=%u\n", thr->tid, static_cast<int>(slot->sid));
+ CHECK(!slot->thr);
+ CHECK(!thr->slot);
+ slot->thr = thr;
+ thr->slot = slot;
+ Epoch epoch = EpochInc(slot->epoch());
+ CHECK(!EpochOverflow(epoch));
+ slot->SetEpoch(epoch);
+ thr->fast_state.SetSid(slot->sid);
+ thr->fast_state.SetEpoch(epoch);
+ if (thr->slot_epoch != ctx->global_epoch) {
+ thr->slot_epoch = ctx->global_epoch;
+ thr->clock.Reset();
+#if !SANITIZER_GO
+ thr->last_sleep_stack_id = kInvalidStackID;
+ thr->last_sleep_clock.Reset();
+#endif
+ }
+ thr->clock.Set(slot->sid, epoch);
+ slot->journal.PushBack({thr->tid, epoch});
+}
+
+static void SlotDetachImpl(ThreadState* thr, bool exiting) {
+ TidSlot* slot = thr->slot;
+ thr->slot = nullptr;
+ if (thr != slot->thr) {
+ slot = nullptr; // we don't own the slot anymore
+ if (thr->slot_epoch != ctx->global_epoch) {
+ TracePart* part = nullptr;
+ auto* trace = &thr->tctx->trace;
+ {
+ Lock l(&trace->mtx);
+ auto* parts = &trace->parts;
+ // The trace can be completely empty in an unlikely event
+ // the thread is preempted right after it acquired the slot
+ // in ThreadStart and did not trace any events yet.
+ CHECK_LE(parts->Size(), 1);
+ part = parts->PopFront();
+ thr->tctx->trace.local_head = nullptr;
+ atomic_store_relaxed(&thr->trace_pos, 0);
+ thr->trace_prev_pc = 0;
+ }
+ if (part) {
+ Lock l(&ctx->slot_mtx);
+ TracePartFree(part);
+ }
+ }
+ return;
+ }
+ CHECK(exiting || thr->fast_state.epoch() == kEpochLast);
+ slot->SetEpoch(thr->fast_state.epoch());
+ slot->thr = nullptr;
+}
+
+void SlotDetach(ThreadState* thr) {
+ Lock lock(&thr->slot->mtx);
+ SlotDetachImpl(thr, true);
+}
+
+void SlotLock(ThreadState* thr) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ DCHECK(!thr->slot_locked);
+#if SANITIZER_DEBUG
+ // Check these mutexes are not locked.
+ // We can call DoReset from SlotAttachAndLock, which will lock
+ // these mutexes, but it happens only every once in a while.
+ { ThreadRegistryLock lock(&ctx->thread_registry); }
+ { Lock lock(&ctx->slot_mtx); }
+#endif
+ TidSlot* slot = thr->slot;
+ slot->mtx.Lock();
+ thr->slot_locked = true;
+ if (LIKELY(thr == slot->thr && thr->fast_state.epoch() != kEpochLast))
+ return;
+ SlotDetachImpl(thr, false);
+ thr->slot_locked = false;
+ slot->mtx.Unlock();
+ SlotAttachAndLock(thr);
+}
+
+void SlotUnlock(ThreadState* thr) {
+ DCHECK(thr->slot_locked);
+ thr->slot_locked = false;
+ thr->slot->mtx.Unlock();
+}
+
+Context::Context()
+ : initialized(),
+ report_mtx(MutexTypeReport),
+ nreported(),
+ thread_registry([](Tid tid) -> ThreadContextBase* {
+ return new (Alloc(sizeof(ThreadContext))) ThreadContext(tid);
+ }),
+ racy_mtx(MutexTypeRacy),
+ racy_stacks(),
+ fired_suppressions_mtx(MutexTypeFired),
+ slot_mtx(MutexTypeSlots),
+ resetting() {
+ fired_suppressions.reserve(8);
+ for (uptr i = 0; i < ARRAY_SIZE(slots); i++) {
+ TidSlot* slot = &slots[i];
+ slot->sid = static_cast<Sid>(i);
+ slot_queue.PushBack(slot);
+ }
+ global_epoch = 1;
+}
+
+TidSlot::TidSlot() : mtx(MutexTypeSlot) {}
+
+// The objects are allocated in TLS, so one may rely on zero-initialization.
+ThreadState::ThreadState(Tid tid)
+ // Do not touch these, rely on zero initialization,
+ // they may be accessed before the ctor.
+ // ignore_reads_and_writes()
+ // ignore_interceptors()
+ : tid(tid) {
+ CHECK_EQ(reinterpret_cast<uptr>(this) % SANITIZER_CACHE_LINE_SIZE, 0);
+#if !SANITIZER_GO
+ // C/C++ uses fixed size shadow stack.
+ const int kInitStackSize = kShadowStackSize;
+ shadow_stack = static_cast<uptr*>(
+ MmapNoReserveOrDie(kInitStackSize * sizeof(uptr), "shadow stack"));
+ SetShadowRegionHugePageMode(reinterpret_cast<uptr>(shadow_stack),
+ kInitStackSize * sizeof(uptr));
+#else
+ // Go uses malloc-allocated shadow stack with dynamic size.
+ const int kInitStackSize = 8;
+ shadow_stack = static_cast<uptr*>(Alloc(kInitStackSize * sizeof(uptr)));
+#endif
+ shadow_stack_pos = shadow_stack;
+ shadow_stack_end = shadow_stack + kInitStackSize;
+}
+
+#if !SANITIZER_GO
+void MemoryProfiler(u64 uptime) {
+ if (ctx->memprof_fd == kInvalidFd)
+ return;
+ InternalMmapVector<char> buf(4096);
+ WriteMemoryProfile(buf.data(), buf.size(), uptime);
+ WriteToFile(ctx->memprof_fd, buf.data(), internal_strlen(buf.data()));
+}
+
+static bool InitializeMemoryProfiler() {
+ ctx->memprof_fd = kInvalidFd;
+ const char *fname = flags()->profile_memory;
+ if (!fname || !fname[0])
+ return false;
+ if (internal_strcmp(fname, "stdout") == 0) {
+ ctx->memprof_fd = 1;
+ } else if (internal_strcmp(fname, "stderr") == 0) {
+ ctx->memprof_fd = 2;
+ } else {
+ InternalScopedString filename;
+ filename.append("%s.%d", fname, (int)internal_getpid());
+ ctx->memprof_fd = OpenFile(filename.data(), WrOnly);
+ if (ctx->memprof_fd == kInvalidFd) {
+ Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
+ filename.data());
+ return false;
+ }
+ }
+ MemoryProfiler(0);
+ return true;
+}
+
+static void *BackgroundThread(void *arg) {
+ // This is a non-initialized non-user thread, nothing to see here.
+ // We don't use ScopedIgnoreInterceptors, because we want ignores to be
+ // enabled even when the thread function exits (e.g. during pthread thread
+ // shutdown code).
+ cur_thread_init()->ignore_interceptors++;
+ const u64 kMs2Ns = 1000 * 1000;
+ const u64 start = NanoTime();
+
+ u64 last_flush = start;
+ uptr last_rss = 0;
+ while (!atomic_load_relaxed(&ctx->stop_background_thread)) {
+ SleepForMillis(100);
+ u64 now = NanoTime();
+
+ // Flush memory if requested.
+ if (flags()->flush_memory_ms > 0) {
+ if (last_flush + flags()->flush_memory_ms * kMs2Ns < now) {
+ VReport(1, "ThreadSanitizer: periodic memory flush\n");
+ FlushShadowMemory();
+ now = last_flush = NanoTime();
+ }
+ }
+ if (flags()->memory_limit_mb > 0) {
+ uptr rss = GetRSS();
+ uptr limit = uptr(flags()->memory_limit_mb) << 20;
+ VReport(1,
+ "ThreadSanitizer: memory flush check"
+ " RSS=%llu LAST=%llu LIMIT=%llu\n",
+ (u64)rss >> 20, (u64)last_rss >> 20, (u64)limit >> 20);
+ if (2 * rss > limit + last_rss) {
+ VReport(1, "ThreadSanitizer: flushing memory due to RSS\n");
+ FlushShadowMemory();
+ rss = GetRSS();
+ now = NanoTime();
+ VReport(1, "ThreadSanitizer: memory flushed RSS=%llu\n",
+ (u64)rss >> 20);
+ }
+ last_rss = rss;
+ }
+
+ MemoryProfiler(now - start);
+
+ // Flush symbolizer cache if requested.
+ if (flags()->flush_symbolizer_ms > 0) {
+ u64 last = atomic_load(&ctx->last_symbolize_time_ns,
+ memory_order_relaxed);
+ if (last != 0 && last + flags()->flush_symbolizer_ms * kMs2Ns < now) {
+ Lock l(&ctx->report_mtx);
+ ScopedErrorReportLock l2;
+ SymbolizeFlush();
+ atomic_store(&ctx->last_symbolize_time_ns, 0, memory_order_relaxed);
+ }
+ }
+ }
+ return nullptr;
+}
+
+static void StartBackgroundThread() {
+ ctx->background_thread = internal_start_thread(&BackgroundThread, 0);
+}
+
+#ifndef __mips__
+static void StopBackgroundThread() {
+ atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed);
+ internal_join_thread(ctx->background_thread);
+ ctx->background_thread = 0;
+}
+#endif
+#endif
+
+void DontNeedShadowFor(uptr addr, uptr size) {
+ ReleaseMemoryPagesToOS(reinterpret_cast<uptr>(MemToShadow(addr)),
+ reinterpret_cast<uptr>(MemToShadow(addr + size)));
+}
+
+#if !SANITIZER_GO
+// We call UnmapShadow before the actual munmap, at that point we don't yet
+// know if the provided address/size are sane. We can't call UnmapShadow
+// after the actual munmap becuase at that point the memory range can
+// already be reused for something else, so we can't rely on the munmap
+// return value to understand is the values are sane.
+// While calling munmap with insane values (non-canonical address, negative
+// size, etc) is an error, the kernel won't crash. We must also try to not
+// crash as the failure mode is very confusing (paging fault inside of the
+// runtime on some derived shadow address).
+static bool IsValidMmapRange(uptr addr, uptr size) {
+ if (size == 0)
+ return true;
+ if (static_cast<sptr>(size) < 0)
+ return false;
+ if (!IsAppMem(addr) || !IsAppMem(addr + size - 1))
+ return false;
+ // Check that if the start of the region belongs to one of app ranges,
+ // end of the region belongs to the same region.
+ const uptr ranges[][2] = {
+ {LoAppMemBeg(), LoAppMemEnd()},
+ {MidAppMemBeg(), MidAppMemEnd()},
+ {HiAppMemBeg(), HiAppMemEnd()},
+ };
+ for (auto range : ranges) {
+ if (addr >= range[0] && addr < range[1])
+ return addr + size <= range[1];
+ }
+ return false;
+}
+
+void UnmapShadow(ThreadState *thr, uptr addr, uptr size) {
+ if (size == 0 || !IsValidMmapRange(addr, size))
+ return;
+ DontNeedShadowFor(addr, size);
+ ScopedGlobalProcessor sgp;
+ SlotLocker locker(thr, true);
+ ctx->metamap.ResetRange(thr->proc(), addr, size, true);
+}
+#endif
+
+void MapShadow(uptr addr, uptr size) {
+ // Ensure thead registry lock held, so as to synchronize
+ // with DoReset, which also access the mapped_shadow_* ctxt fields.
+ ThreadRegistryLock lock0(&ctx->thread_registry);
+ static bool data_mapped = false;
+
+#if !SANITIZER_GO
+ // Global data is not 64K aligned, but there are no adjacent mappings,
+ // so we can get away with unaligned mapping.
+ // CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment
+ const uptr kPageSize = GetPageSizeCached();
+ uptr shadow_begin = RoundDownTo((uptr)MemToShadow(addr), kPageSize);
+ uptr shadow_end = RoundUpTo((uptr)MemToShadow(addr + size), kPageSize);
+ if (!MmapFixedNoReserve(shadow_begin, shadow_end - shadow_begin, "shadow"))
+ Die();
+#else
+ uptr shadow_begin = RoundDownTo((uptr)MemToShadow(addr), (64 << 10));
+ uptr shadow_end = RoundUpTo((uptr)MemToShadow(addr + size), (64 << 10));
+ VPrintf(2, "MapShadow for (0x%zx-0x%zx), begin/end: (0x%zx-0x%zx)\n",
+ addr, addr + size, shadow_begin, shadow_end);
+
+ if (!data_mapped) {
+ // First call maps data+bss.
+ if (!MmapFixedSuperNoReserve(shadow_begin, shadow_end - shadow_begin, "shadow"))
+ Die();
+ } else {
+ VPrintf(2, "ctx->mapped_shadow_{begin,end} = (0x%zx-0x%zx)\n",
+ ctx->mapped_shadow_begin, ctx->mapped_shadow_end);
+ // Second and subsequent calls map heap.
+ if (shadow_end <= ctx->mapped_shadow_end)
+ return;
+ if (!ctx->mapped_shadow_begin || ctx->mapped_shadow_begin > shadow_begin)
+ ctx->mapped_shadow_begin = shadow_begin;
+ if (shadow_begin < ctx->mapped_shadow_end)
+ shadow_begin = ctx->mapped_shadow_end;
+ VPrintf(2, "MapShadow begin/end = (0x%zx-0x%zx)\n",
+ shadow_begin, shadow_end);
+ if (!MmapFixedSuperNoReserve(shadow_begin, shadow_end - shadow_begin,
+ "shadow"))
+ Die();
+ ctx->mapped_shadow_end = shadow_end;
+ }
+#endif
+
+ // Meta shadow is 2:1, so tread carefully.
+ static uptr mapped_meta_end = 0;
+ uptr meta_begin = (uptr)MemToMeta(addr);
+ uptr meta_end = (uptr)MemToMeta(addr + size);
+ meta_begin = RoundDownTo(meta_begin, 64 << 10);
+ meta_end = RoundUpTo(meta_end, 64 << 10);
+ if (!data_mapped) {
+ // First call maps data+bss.
+ data_mapped = true;
+ if (!MmapFixedSuperNoReserve(meta_begin, meta_end - meta_begin,
+ "meta shadow"))
+ Die();
+ } else {
+ // Mapping continuous heap.
+ // Windows wants 64K alignment.
+ meta_begin = RoundDownTo(meta_begin, 64 << 10);
+ meta_end = RoundUpTo(meta_end, 64 << 10);
+ CHECK_GT(meta_end, mapped_meta_end);
+ if (meta_begin < mapped_meta_end)
+ meta_begin = mapped_meta_end;
+ if (!MmapFixedSuperNoReserve(meta_begin, meta_end - meta_begin,
+ "meta shadow"))
+ Die();
+ mapped_meta_end = meta_end;
+ }
+ VPrintf(2, "mapped meta shadow for (0x%zx-0x%zx) at (0x%zx-0x%zx)\n", addr,
+ addr + size, meta_begin, meta_end);
+}
+
+#if !SANITIZER_GO
+static void OnStackUnwind(const SignalContext &sig, const void *,
+ BufferedStackTrace *stack) {
+ stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
+ common_flags()->fast_unwind_on_fatal);
+}
+
+static void TsanOnDeadlySignal(int signo, void *siginfo, void *context) {
+ HandleDeadlySignal(siginfo, context, GetTid(), &OnStackUnwind, nullptr);
+}
+#endif
+
+void CheckUnwind() {
+ // There is high probability that interceptors will check-fail as well,
+ // on the other hand there is no sense in processing interceptors
+ // since we are going to die soon.
+ ScopedIgnoreInterceptors ignore;
+#if !SANITIZER_GO
+ ThreadState* thr = cur_thread();
+ thr->nomalloc = false;
+ thr->ignore_sync++;
+ thr->ignore_reads_and_writes++;
+ atomic_store_relaxed(&thr->in_signal_handler, 0);
+#endif
+ PrintCurrentStackSlow(StackTrace::GetCurrentPc());
+}
+
+bool is_initialized;
+
+void Initialize(ThreadState *thr) {
+ // Thread safe because done before all threads exist.
+ if (is_initialized)
+ return;
+ is_initialized = true;
+ // We are not ready to handle interceptors yet.
+ ScopedIgnoreInterceptors ignore;
+ SanitizerToolName = "ThreadSanitizer";
+ // Install tool-specific callbacks in sanitizer_common.
+ SetCheckUnwindCallback(CheckUnwind);
+
+ ctx = new(ctx_placeholder) Context;
+ const char *env_name = SANITIZER_GO ? "GORACE" : "TSAN_OPTIONS";
+ const char *options = GetEnv(env_name);
+ CacheBinaryName();
+ CheckASLR();
+ InitializeFlags(&ctx->flags, options, env_name);
+ AvoidCVE_2016_2143();
+ __sanitizer::InitializePlatformEarly();
+ __tsan::InitializePlatformEarly();
+
+#if !SANITIZER_GO
+ InitializeAllocator();
+ ReplaceSystemMalloc();
+#endif
+ if (common_flags()->detect_deadlocks)
+ ctx->dd = DDetector::Create(flags());
+ Processor *proc = ProcCreate();
+ ProcWire(proc, thr);
+ InitializeInterceptors();
+ InitializePlatform();
+ InitializeDynamicAnnotations();
+#if !SANITIZER_GO
+ InitializeShadowMemory();
+ InitializeAllocatorLate();
+ InstallDeadlySignalHandlers(TsanOnDeadlySignal);
+#endif
+ // Setup correct file descriptor for error reports.
+ __sanitizer_set_report_path(common_flags()->log_path);
+ InitializeSuppressions();
+#if !SANITIZER_GO
+ InitializeLibIgnore();
+ Symbolizer::GetOrInit()->AddHooks(EnterSymbolizer, ExitSymbolizer);
+#endif
+
+ VPrintf(1, "***** Running under ThreadSanitizer v3 (pid %d) *****\n",
+ (int)internal_getpid());
+
+ // Initialize thread 0.
+ Tid tid = ThreadCreate(nullptr, 0, 0, true);
+ CHECK_EQ(tid, kMainTid);
+ ThreadStart(thr, tid, GetTid(), ThreadType::Regular);
+#if TSAN_CONTAINS_UBSAN
+ __ubsan::InitAsPlugin();
+#endif
+
+#if !SANITIZER_GO
+ Symbolizer::LateInitialize();
+ if (InitializeMemoryProfiler() || flags()->force_background_thread)
+ MaybeSpawnBackgroundThread();
+#endif
+ ctx->initialized = true;
+
+ if (flags()->stop_on_start) {
+ Printf("ThreadSanitizer is suspended at startup (pid %d)."
+ " Call __tsan_resume().\n",
+ (int)internal_getpid());
+ while (__tsan_resumed == 0) {}
+ }
+
+ OnInitialize();
+}
+
+void MaybeSpawnBackgroundThread() {
+ // On MIPS, TSan initialization is run before
+ // __pthread_initialize_minimal_internal() is finished, so we can not spawn
+ // new threads.
+#if !SANITIZER_GO && !defined(__mips__)
+ static atomic_uint32_t bg_thread = {};
+ if (atomic_load(&bg_thread, memory_order_relaxed) == 0 &&
+ atomic_exchange(&bg_thread, 1, memory_order_relaxed) == 0) {
+ StartBackgroundThread();
+ SetSandboxingCallback(StopBackgroundThread);
+ }
+#endif
+}
+
+int Finalize(ThreadState *thr) {
+ bool failed = false;
+
+#if !SANITIZER_GO
+ if (common_flags()->print_module_map == 1)
+ DumpProcessMap();
+#endif
+
+ if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1)
+ internal_usleep(u64(flags()->atexit_sleep_ms) * 1000);
+
+ {
+ // Wait for pending reports.
+ ScopedErrorReportLock lock;
+ }
+
+#if !SANITIZER_GO
+ if (Verbosity()) AllocatorPrintStats();
+#endif
+
+ ThreadFinalize(thr);
+
+ if (ctx->nreported) {
+ failed = true;
+#if !SANITIZER_GO
+ Printf("ThreadSanitizer: reported %d warnings\n", ctx->nreported);
+#else
+ Printf("Found %d data race(s)\n", ctx->nreported);
+#endif
+ }
+
+ if (common_flags()->print_suppressions)
+ PrintMatchedSuppressions();
+
+ failed = OnFinalize(failed);
+
+ return failed ? common_flags()->exitcode : 0;
+}
+
+#if !SANITIZER_GO
+void ForkBefore(ThreadState* thr, uptr pc) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ GlobalProcessorLock();
+ // Detaching from the slot makes OnUserFree skip writing to the shadow.
+ // The slot will be locked so any attempts to use it will deadlock anyway.
+ SlotDetach(thr);
+ for (auto& slot : ctx->slots) slot.mtx.Lock();
+ ctx->thread_registry.Lock();
+ ctx->slot_mtx.Lock();
+ ScopedErrorReportLock::Lock();
+ AllocatorLock();
+ // Suppress all reports in the pthread_atfork callbacks.
+ // Reports will deadlock on the report_mtx.
+ // We could ignore sync operations as well,
+ // but so far it's unclear if it will do more good or harm.
+ // Unnecessarily ignoring things can lead to false positives later.
+ thr->suppress_reports++;
+ // On OS X, REAL(fork) can call intercepted functions (OSSpinLockLock), and
+ // we'll assert in CheckNoLocks() unless we ignore interceptors.
+ // On OS X libSystem_atfork_prepare/parent/child callbacks are called
+ // after/before our callbacks and they call free.
+ thr->ignore_interceptors++;
+ // Disables memory write in OnUserAlloc/Free.
+ thr->ignore_reads_and_writes++;
+
+ __tsan_test_only_on_fork();
+}
+
+static void ForkAfter(ThreadState* thr) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ thr->suppress_reports--; // Enabled in ForkBefore.
+ thr->ignore_interceptors--;
+ thr->ignore_reads_and_writes--;
+ AllocatorUnlock();
+ ScopedErrorReportLock::Unlock();
+ ctx->slot_mtx.Unlock();
+ ctx->thread_registry.Unlock();
+ for (auto& slot : ctx->slots) slot.mtx.Unlock();
+ SlotAttachAndLock(thr);
+ SlotUnlock(thr);
+ GlobalProcessorUnlock();
+}
+
+void ForkParentAfter(ThreadState* thr, uptr pc) { ForkAfter(thr); }
+
+void ForkChildAfter(ThreadState* thr, uptr pc, bool start_thread) {
+ ForkAfter(thr);
+ u32 nthread = ctx->thread_registry.OnFork(thr->tid);
+ VPrintf(1,
+ "ThreadSanitizer: forked new process with pid %d,"
+ " parent had %d threads\n",
+ (int)internal_getpid(), (int)nthread);
+ if (nthread == 1) {
+ if (start_thread)
+ StartBackgroundThread();
+ } else {
+ // We've just forked a multi-threaded process. We cannot reasonably function
+ // after that (some mutexes may be locked before fork). So just enable
+ // ignores for everything in the hope that we will exec soon.
+ ctx->after_multithreaded_fork = true;
+ thr->ignore_interceptors++;
+ thr->suppress_reports++;
+ ThreadIgnoreBegin(thr, pc);
+ ThreadIgnoreSyncBegin(thr, pc);
+ }
+}
+#endif
+
+#if SANITIZER_GO
+NOINLINE
+void GrowShadowStack(ThreadState *thr) {
+ const int sz = thr->shadow_stack_end - thr->shadow_stack;
+ const int newsz = 2 * sz;
+ auto *newstack = (uptr *)Alloc(newsz * sizeof(uptr));
+ internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr));
+ Free(thr->shadow_stack);
+ thr->shadow_stack = newstack;
+ thr->shadow_stack_pos = newstack + sz;
+ thr->shadow_stack_end = newstack + newsz;
+}
+#endif
+
+StackID CurrentStackId(ThreadState *thr, uptr pc) {
+#if !SANITIZER_GO
+ if (!thr->is_inited) // May happen during bootstrap.
+ return kInvalidStackID;
+#endif
+ if (pc != 0) {
+#if !SANITIZER_GO
+ DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
+#else
+ if (thr->shadow_stack_pos == thr->shadow_stack_end)
+ GrowShadowStack(thr);
+#endif
+ thr->shadow_stack_pos[0] = pc;
+ thr->shadow_stack_pos++;
+ }
+ StackID id = StackDepotPut(
+ StackTrace(thr->shadow_stack, thr->shadow_stack_pos - thr->shadow_stack));
+ if (pc != 0)
+ thr->shadow_stack_pos--;
+ return id;
+}
+
+static bool TraceSkipGap(ThreadState* thr) {
+ Trace *trace = &thr->tctx->trace;
+ Event *pos = reinterpret_cast<Event *>(atomic_load_relaxed(&thr->trace_pos));
+ DCHECK_EQ(reinterpret_cast<uptr>(pos + 1) & TracePart::kAlignment, 0);
+ auto *part = trace->parts.Back();
+ DPrintf("#%d: TraceSwitchPart enter trace=%p parts=%p-%p pos=%p\n", thr->tid,
+ trace, trace->parts.Front(), part, pos);
+ if (!part)
+ return false;
+ // We can get here when we still have space in the current trace part.
+ // The fast-path check in TraceAcquire has false positives in the middle of
+ // the part. Check if we are indeed at the end of the current part or not,
+ // and fill any gaps with NopEvent's.
+ Event* end = &part->events[TracePart::kSize];
+ DCHECK_GE(pos, &part->events[0]);
+ DCHECK_LE(pos, end);
+ if (pos + 1 < end) {
+ if ((reinterpret_cast<uptr>(pos) & TracePart::kAlignment) ==
+ TracePart::kAlignment)
+ *pos++ = NopEvent;
+ *pos++ = NopEvent;
+ DCHECK_LE(pos + 2, end);
+ atomic_store_relaxed(&thr->trace_pos, reinterpret_cast<uptr>(pos));
+ return true;
+ }
+ // We are indeed at the end.
+ for (; pos < end; pos++) *pos = NopEvent;
+ return false;
+}
+
+NOINLINE
+void TraceSwitchPart(ThreadState* thr) {
+ if (TraceSkipGap(thr))
+ return;
+#if !SANITIZER_GO
+ if (ctx->after_multithreaded_fork) {
+ // We just need to survive till exec.
+ TracePart* part = thr->tctx->trace.parts.Back();
+ if (part) {
+ atomic_store_relaxed(&thr->trace_pos,
+ reinterpret_cast<uptr>(&part->events[0]));
+ return;
+ }
+ }
+#endif
+ TraceSwitchPartImpl(thr);
+}
+
+void TraceSwitchPartImpl(ThreadState* thr) {
+ SlotLocker locker(thr, true);
+ Trace* trace = &thr->tctx->trace;
+ TracePart* part = TracePartAlloc(thr);
+ part->trace = trace;
+ thr->trace_prev_pc = 0;
+ TracePart* recycle = nullptr;
+ // Keep roughly half of parts local to the thread
+ // (not queued into the recycle queue).
+ uptr local_parts = (Trace::kMinParts + flags()->history_size + 1) / 2;
+ {
+ Lock lock(&trace->mtx);
+ if (trace->parts.Empty())
+ trace->local_head = part;
+ if (trace->parts.Size() >= local_parts) {
+ recycle = trace->local_head;
+ trace->local_head = trace->parts.Next(recycle);
+ }
+ trace->parts.PushBack(part);
+ atomic_store_relaxed(&thr->trace_pos,
+ reinterpret_cast<uptr>(&part->events[0]));
+ }
+ // Make this part self-sufficient by restoring the current stack
+ // and mutex set in the beginning of the trace.
+ TraceTime(thr);
+ {
+ // Pathologically large stacks may not fit into the part.
+ // In these cases we log only fixed number of top frames.
+ const uptr kMaxFrames = 1000;
+ // Check that kMaxFrames won't consume the whole part.
+ static_assert(kMaxFrames < TracePart::kSize / 2, "kMaxFrames is too big");
+ uptr* pos = Max(&thr->shadow_stack[0], thr->shadow_stack_pos - kMaxFrames);
+ for (; pos < thr->shadow_stack_pos; pos++) {
+ if (TryTraceFunc(thr, *pos))
+ continue;
+ CHECK(TraceSkipGap(thr));
+ CHECK(TryTraceFunc(thr, *pos));
+ }
+ }
+ for (uptr i = 0; i < thr->mset.Size(); i++) {
+ MutexSet::Desc d = thr->mset.Get(i);
+ for (uptr i = 0; i < d.count; i++)
+ TraceMutexLock(thr, d.write ? EventType::kLock : EventType::kRLock, 0,
+ d.addr, d.stack_id);
+ }
+ // Callers of TraceSwitchPart expect that TraceAcquire will always succeed
+ // after the call. It's possible that TryTraceFunc/TraceMutexLock above
+ // filled the trace part exactly up to the TracePart::kAlignment gap
+ // and the next TraceAcquire won't succeed. Skip the gap to avoid that.
+ EventFunc *ev;
+ if (!TraceAcquire(thr, &ev)) {
+ CHECK(TraceSkipGap(thr));
+ CHECK(TraceAcquire(thr, &ev));
+ }
+ {
+ Lock lock(&ctx->slot_mtx);
+ // There is a small chance that the slot may be not queued at this point.
+ // This can happen if the slot has kEpochLast epoch and another thread
+ // in FindSlotAndLock discovered that it's exhausted and removed it from
+ // the slot queue. kEpochLast can happen in 2 cases: (1) if TraceSwitchPart
+ // was called with the slot locked and epoch already at kEpochLast,
+ // or (2) if we've acquired a new slot in SlotLock in the beginning
+ // of the function and the slot was at kEpochLast - 1, so after increment
+ // in SlotAttachAndLock it become kEpochLast.
+ if (ctx->slot_queue.Queued(thr->slot)) {
+ ctx->slot_queue.Remove(thr->slot);
+ ctx->slot_queue.PushBack(thr->slot);
+ }
+ if (recycle)
+ ctx->trace_part_recycle.PushBack(recycle);
+ }
+ DPrintf("#%d: TraceSwitchPart exit parts=%p-%p pos=0x%zx\n", thr->tid,
+ trace->parts.Front(), trace->parts.Back(),
+ atomic_load_relaxed(&thr->trace_pos));
+}
+
+void ThreadIgnoreBegin(ThreadState* thr, uptr pc) {
+ DPrintf("#%d: ThreadIgnoreBegin\n", thr->tid);
+ thr->ignore_reads_and_writes++;
+ CHECK_GT(thr->ignore_reads_and_writes, 0);
+ thr->fast_state.SetIgnoreBit();
+#if !SANITIZER_GO
+ if (pc && !ctx->after_multithreaded_fork)
+ thr->mop_ignore_set.Add(CurrentStackId(thr, pc));
+#endif
+}
+
+void ThreadIgnoreEnd(ThreadState *thr) {
+ DPrintf("#%d: ThreadIgnoreEnd\n", thr->tid);
+ CHECK_GT(thr->ignore_reads_and_writes, 0);
+ thr->ignore_reads_and_writes--;
+ if (thr->ignore_reads_and_writes == 0) {
+ thr->fast_state.ClearIgnoreBit();
+#if !SANITIZER_GO
+ thr->mop_ignore_set.Reset();
+#endif
+ }
+}
+
+#if !SANITIZER_GO
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+uptr __tsan_testonly_shadow_stack_current_size() {
+ ThreadState *thr = cur_thread();
+ return thr->shadow_stack_pos - thr->shadow_stack;
+}
+#endif
+
+void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc) {
+ DPrintf("#%d: ThreadIgnoreSyncBegin\n", thr->tid);
+ thr->ignore_sync++;
+ CHECK_GT(thr->ignore_sync, 0);
+#if !SANITIZER_GO
+ if (pc && !ctx->after_multithreaded_fork)
+ thr->sync_ignore_set.Add(CurrentStackId(thr, pc));
+#endif
+}
+
+void ThreadIgnoreSyncEnd(ThreadState *thr) {
+ DPrintf("#%d: ThreadIgnoreSyncEnd\n", thr->tid);
+ CHECK_GT(thr->ignore_sync, 0);
+ thr->ignore_sync--;
+#if !SANITIZER_GO
+ if (thr->ignore_sync == 0)
+ thr->sync_ignore_set.Reset();
+#endif
+}
+
+bool MD5Hash::operator==(const MD5Hash &other) const {
+ return hash[0] == other.hash[0] && hash[1] == other.hash[1];
+}
+
+#if SANITIZER_DEBUG
+void build_consistency_debug() {}
+#else
+void build_consistency_release() {}
+#endif
+} // namespace __tsan
+
+#if SANITIZER_CHECK_DEADLOCKS
+namespace __sanitizer {
+using namespace __tsan;
+MutexMeta mutex_meta[] = {
+ {MutexInvalid, "Invalid", {}},
+ {MutexThreadRegistry,
+ "ThreadRegistry",
+ {MutexTypeSlots, MutexTypeTrace, MutexTypeReport}},
+ {MutexTypeReport, "Report", {MutexTypeTrace}},
+ {MutexTypeSyncVar, "SyncVar", {MutexTypeReport, MutexTypeTrace}},
+ {MutexTypeAnnotations, "Annotations", {}},
+ {MutexTypeAtExit, "AtExit", {}},
+ {MutexTypeFired, "Fired", {MutexLeaf}},
+ {MutexTypeRacy, "Racy", {MutexLeaf}},
+ {MutexTypeGlobalProc, "GlobalProc", {MutexTypeSlot, MutexTypeSlots}},
+ {MutexTypeInternalAlloc, "InternalAlloc", {MutexLeaf}},
+ {MutexTypeTrace, "Trace", {}},
+ {MutexTypeSlot,
+ "Slot",
+ {MutexMulti, MutexTypeTrace, MutexTypeSyncVar, MutexThreadRegistry,
+ MutexTypeSlots}},
+ {MutexTypeSlots, "Slots", {MutexTypeTrace, MutexTypeReport}},
+ {},
+};
+
+void PrintMutexPC(uptr pc) { StackTrace(&pc, 1).Print(); }
+
+} // namespace __sanitizer
+#endif
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl.h
new file mode 100644
index 00000000000..a5606dbc7f8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl.h
@@ -0,0 +1,813 @@
+//===-- tsan_rtl.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Main internal TSan header file.
+//
+// Ground rules:
+// - C++ run-time should not be used (static CTORs, RTTI, exceptions, static
+// function-scope locals)
+// - All functions/classes/etc reside in namespace __tsan, except for those
+// declared in tsan_interface.h.
+// - Platform-specific files should be used instead of ifdefs (*).
+// - No system headers included in header files (*).
+// - Platform specific headres included only into platform-specific files (*).
+//
+// (*) Except when inlining is critical for performance.
+//===----------------------------------------------------------------------===//
+
+#ifndef TSAN_RTL_H
+#define TSAN_RTL_H
+
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_internal.h"
+#include "sanitizer_common/sanitizer_asm.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
+#include "sanitizer_common/sanitizer_libignore.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
+#include "sanitizer_common/sanitizer_vector.h"
+#include "tsan_defs.h"
+#include "tsan_flags.h"
+#include "tsan_ignoreset.h"
+#include "tsan_ilist.h"
+#include "tsan_mman.h"
+#include "tsan_mutexset.h"
+#include "tsan_platform.h"
+#include "tsan_report.h"
+#include "tsan_shadow.h"
+#include "tsan_stack_trace.h"
+#include "tsan_sync.h"
+#include "tsan_trace.h"
+#include "tsan_vector_clock.h"
+
+#if SANITIZER_WORDSIZE != 64
+# error "ThreadSanitizer is supported only on 64-bit platforms"
+#endif
+
+namespace __tsan {
+
+#if !SANITIZER_GO
+struct MapUnmapCallback;
+#if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \
+ defined(__powerpc__)
+
+struct AP32 {
+ static const uptr kSpaceBeg = 0;
+ static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
+ static const uptr kMetadataSize = 0;
+ typedef __sanitizer::CompactSizeClassMap SizeClassMap;
+ static const uptr kRegionSizeLog = 20;
+ using AddressSpaceView = LocalAddressSpaceView;
+ typedef __tsan::MapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+};
+typedef SizeClassAllocator32<AP32> PrimaryAllocator;
+#else
+struct AP64 { // Allocator64 parameters. Deliberately using a short name.
+# if defined(__s390x__)
+ typedef MappingS390x Mapping;
+# else
+ typedef Mapping48AddressSpace Mapping;
+# endif
+ static const uptr kSpaceBeg = Mapping::kHeapMemBeg;
+ static const uptr kSpaceSize = Mapping::kHeapMemEnd - Mapping::kHeapMemBeg;
+ static const uptr kMetadataSize = 0;
+ typedef DefaultSizeClassMap SizeClassMap;
+ typedef __tsan::MapUnmapCallback MapUnmapCallback;
+ static const uptr kFlags = 0;
+ using AddressSpaceView = LocalAddressSpaceView;
+};
+typedef SizeClassAllocator64<AP64> PrimaryAllocator;
+#endif
+typedef CombinedAllocator<PrimaryAllocator> Allocator;
+typedef Allocator::AllocatorCache AllocatorCache;
+Allocator *allocator();
+#endif
+
+struct ThreadSignalContext;
+
+struct JmpBuf {
+ uptr sp;
+ int int_signal_send;
+ bool in_blocking_func;
+ uptr in_signal_handler;
+ uptr *shadow_stack_pos;
+};
+
+// A Processor represents a physical thread, or a P for Go.
+// It is used to store internal resources like allocate cache, and does not
+// participate in race-detection logic (invisible to end user).
+// In C++ it is tied to an OS thread just like ThreadState, however ideally
+// it should be tied to a CPU (this way we will have fewer allocator caches).
+// In Go it is tied to a P, so there are significantly fewer Processor's than
+// ThreadState's (which are tied to Gs).
+// A ThreadState must be wired with a Processor to handle events.
+struct Processor {
+ ThreadState *thr; // currently wired thread, or nullptr
+#if !SANITIZER_GO
+ AllocatorCache alloc_cache;
+ InternalAllocatorCache internal_alloc_cache;
+#endif
+ DenseSlabAllocCache block_cache;
+ DenseSlabAllocCache sync_cache;
+ DDPhysicalThread *dd_pt;
+};
+
+#if !SANITIZER_GO
+// ScopedGlobalProcessor temporary setups a global processor for the current
+// thread, if it does not have one. Intended for interceptors that can run
+// at the very thread end, when we already destroyed the thread processor.
+struct ScopedGlobalProcessor {
+ ScopedGlobalProcessor();
+ ~ScopedGlobalProcessor();
+};
+#endif
+
+struct TidEpoch {
+ Tid tid;
+ Epoch epoch;
+};
+
+struct TidSlot {
+ Mutex mtx;
+ Sid sid;
+ atomic_uint32_t raw_epoch;
+ ThreadState *thr;
+ Vector<TidEpoch> journal;
+ INode node;
+
+ Epoch epoch() const {
+ return static_cast<Epoch>(atomic_load(&raw_epoch, memory_order_relaxed));
+ }
+
+ void SetEpoch(Epoch v) {
+ atomic_store(&raw_epoch, static_cast<u32>(v), memory_order_relaxed);
+ }
+
+ TidSlot();
+} ALIGNED(SANITIZER_CACHE_LINE_SIZE);
+
+// This struct is stored in TLS.
+struct ThreadState {
+ FastState fast_state;
+ int ignore_sync;
+#if !SANITIZER_GO
+ int ignore_interceptors;
+#endif
+ uptr *shadow_stack_pos;
+
+ // Current position in tctx->trace.Back()->events (Event*).
+ atomic_uintptr_t trace_pos;
+ // PC of the last memory access, used to compute PC deltas in the trace.
+ uptr trace_prev_pc;
+
+ // Technically `current` should be a separate THREADLOCAL variable;
+ // but it is placed here in order to share cache line with previous fields.
+ ThreadState* current;
+
+ atomic_sint32_t pending_signals;
+
+ VectorClock clock;
+
+ // This is a slow path flag. On fast path, fast_state.GetIgnoreBit() is read.
+ // We do not distinguish beteween ignoring reads and writes
+ // for better performance.
+ int ignore_reads_and_writes;
+ int suppress_reports;
+ // Go does not support ignores.
+#if !SANITIZER_GO
+ IgnoreSet mop_ignore_set;
+ IgnoreSet sync_ignore_set;
+#endif
+ uptr *shadow_stack;
+ uptr *shadow_stack_end;
+#if !SANITIZER_GO
+ Vector<JmpBuf> jmp_bufs;
+ int in_symbolizer;
+ atomic_uintptr_t in_blocking_func;
+ bool in_ignored_lib;
+ bool is_inited;
+#endif
+ MutexSet mset;
+ bool is_dead;
+ const Tid tid;
+ uptr stk_addr;
+ uptr stk_size;
+ uptr tls_addr;
+ uptr tls_size;
+ ThreadContext *tctx;
+
+ DDLogicalThread *dd_lt;
+
+ TidSlot *slot;
+ uptr slot_epoch;
+ bool slot_locked;
+
+ // Current wired Processor, or nullptr. Required to handle any events.
+ Processor *proc1;
+#if !SANITIZER_GO
+ Processor *proc() { return proc1; }
+#else
+ Processor *proc();
+#endif
+
+ atomic_uintptr_t in_signal_handler;
+ atomic_uintptr_t signal_ctx;
+
+#if !SANITIZER_GO
+ StackID last_sleep_stack_id;
+ VectorClock last_sleep_clock;
+#endif
+
+ // Set in regions of runtime that must be signal-safe and fork-safe.
+ // If set, malloc must not be called.
+ int nomalloc;
+
+ const ReportDesc *current_report;
+
+ explicit ThreadState(Tid tid);
+} ALIGNED(SANITIZER_CACHE_LINE_SIZE);
+
+#if !SANITIZER_GO
+#if SANITIZER_APPLE || SANITIZER_ANDROID
+ThreadState *cur_thread();
+void set_cur_thread(ThreadState *thr);
+void cur_thread_finalize();
+inline ThreadState *cur_thread_init() { return cur_thread(); }
+# else
+__attribute__((tls_model("initial-exec")))
+extern THREADLOCAL char cur_thread_placeholder[];
+inline ThreadState *cur_thread() {
+ return reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current;
+}
+inline ThreadState *cur_thread_init() {
+ ThreadState *thr = reinterpret_cast<ThreadState *>(cur_thread_placeholder);
+ if (UNLIKELY(!thr->current))
+ thr->current = thr;
+ return thr->current;
+}
+inline void set_cur_thread(ThreadState *thr) {
+ reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current = thr;
+}
+inline void cur_thread_finalize() { }
+# endif // SANITIZER_APPLE || SANITIZER_ANDROID
+#endif // SANITIZER_GO
+
+class ThreadContext final : public ThreadContextBase {
+ public:
+ explicit ThreadContext(Tid tid);
+ ~ThreadContext();
+ ThreadState *thr;
+ StackID creation_stack_id;
+ VectorClock *sync;
+ uptr sync_epoch;
+ Trace trace;
+
+ // Override superclass callbacks.
+ void OnDead() override;
+ void OnJoined(void *arg) override;
+ void OnFinished() override;
+ void OnStarted(void *arg) override;
+ void OnCreated(void *arg) override;
+ void OnReset() override;
+ void OnDetached(void *arg) override;
+};
+
+struct RacyStacks {
+ MD5Hash hash[2];
+ bool operator==(const RacyStacks &other) const;
+};
+
+struct RacyAddress {
+ uptr addr_min;
+ uptr addr_max;
+};
+
+struct FiredSuppression {
+ ReportType type;
+ uptr pc_or_addr;
+ Suppression *supp;
+};
+
+struct Context {
+ Context();
+
+ bool initialized;
+#if !SANITIZER_GO
+ bool after_multithreaded_fork;
+#endif
+
+ MetaMap metamap;
+
+ Mutex report_mtx;
+ int nreported;
+ atomic_uint64_t last_symbolize_time_ns;
+
+ void *background_thread;
+ atomic_uint32_t stop_background_thread;
+
+ ThreadRegistry thread_registry;
+
+ // This is used to prevent a very unlikely but very pathological behavior.
+ // Since memory access handling is not synchronized with DoReset,
+ // a thread running concurrently with DoReset can leave a bogus shadow value
+ // that will be later falsely detected as a race. For such false races
+ // RestoreStack will return false and we will not report it.
+ // However, consider that a thread leaves a whole lot of such bogus values
+ // and these values are later read by a whole lot of threads.
+ // This will cause massive amounts of ReportRace calls and lots of
+ // serialization. In very pathological cases the resulting slowdown
+ // can be >100x. This is very unlikely, but it was presumably observed
+ // in practice: https://github.com/google/sanitizers/issues/1552
+ // If this happens, previous access sid+epoch will be the same for all of
+ // these false races b/c if the thread will try to increment epoch, it will
+ // notice that DoReset has happened and will stop producing bogus shadow
+ // values. So, last_spurious_race is used to remember the last sid+epoch
+ // for which RestoreStack returned false. Then it is used to filter out
+ // races with the same sid+epoch very early and quickly.
+ // It is of course possible that multiple threads left multiple bogus shadow
+ // values and all of them are read by lots of threads at the same time.
+ // In such case last_spurious_race will only be able to deduplicate a few
+ // races from one thread, then few from another and so on. An alternative
+ // would be to hold an array of such sid+epoch, but we consider such scenario
+ // as even less likely.
+ // Note: this can lead to some rare false negatives as well:
+ // 1. When a legit access with the same sid+epoch participates in a race
+ // as the "previous" memory access, it will be wrongly filtered out.
+ // 2. When RestoreStack returns false for a legit memory access because it
+ // was already evicted from the thread trace, we will still remember it in
+ // last_spurious_race. Then if there is another racing memory access from
+ // the same thread that happened in the same epoch, but was stored in the
+ // next thread trace part (which is still preserved in the thread trace),
+ // we will also wrongly filter it out while RestoreStack would actually
+ // succeed for that second memory access.
+ RawShadow last_spurious_race;
+
+ Mutex racy_mtx;
+ Vector<RacyStacks> racy_stacks;
+ // Number of fired suppressions may be large enough.
+ Mutex fired_suppressions_mtx;
+ InternalMmapVector<FiredSuppression> fired_suppressions;
+ DDetector *dd;
+
+ Flags flags;
+ fd_t memprof_fd;
+
+ // The last slot index (kFreeSid) is used to denote freed memory.
+ TidSlot slots[kThreadSlotCount - 1];
+
+ // Protects global_epoch, slot_queue, trace_part_recycle.
+ Mutex slot_mtx;
+ uptr global_epoch; // guarded by slot_mtx and by all slot mutexes
+ bool resetting; // global reset is in progress
+ IList<TidSlot, &TidSlot::node> slot_queue SANITIZER_GUARDED_BY(slot_mtx);
+ IList<TraceHeader, &TraceHeader::global, TracePart> trace_part_recycle
+ SANITIZER_GUARDED_BY(slot_mtx);
+ uptr trace_part_total_allocated SANITIZER_GUARDED_BY(slot_mtx);
+ uptr trace_part_recycle_finished SANITIZER_GUARDED_BY(slot_mtx);
+ uptr trace_part_finished_excess SANITIZER_GUARDED_BY(slot_mtx);
+#if SANITIZER_GO
+ uptr mapped_shadow_begin;
+ uptr mapped_shadow_end;
+#endif
+};
+
+extern Context *ctx; // The one and the only global runtime context.
+
+ALWAYS_INLINE Flags *flags() {
+ return &ctx->flags;
+}
+
+struct ScopedIgnoreInterceptors {
+ ScopedIgnoreInterceptors() {
+#if !SANITIZER_GO
+ cur_thread()->ignore_interceptors++;
+#endif
+ }
+
+ ~ScopedIgnoreInterceptors() {
+#if !SANITIZER_GO
+ cur_thread()->ignore_interceptors--;
+#endif
+ }
+};
+
+const char *GetObjectTypeFromTag(uptr tag);
+const char *GetReportHeaderFromTag(uptr tag);
+uptr TagFromShadowStackFrame(uptr pc);
+
+class ScopedReportBase {
+ public:
+ void AddMemoryAccess(uptr addr, uptr external_tag, Shadow s, Tid tid,
+ StackTrace stack, const MutexSet *mset);
+ void AddStack(StackTrace stack, bool suppressable = false);
+ void AddThread(const ThreadContext *tctx, bool suppressable = false);
+ void AddThread(Tid tid, bool suppressable = false);
+ void AddUniqueTid(Tid unique_tid);
+ int AddMutex(uptr addr, StackID creation_stack_id);
+ void AddLocation(uptr addr, uptr size);
+ void AddSleep(StackID stack_id);
+ void SetCount(int count);
+ void SetSigNum(int sig);
+
+ const ReportDesc *GetReport() const;
+
+ protected:
+ ScopedReportBase(ReportType typ, uptr tag);
+ ~ScopedReportBase();
+
+ private:
+ ReportDesc *rep_;
+ // Symbolizer makes lots of intercepted calls. If we try to process them,
+ // at best it will cause deadlocks on internal mutexes.
+ ScopedIgnoreInterceptors ignore_interceptors_;
+
+ ScopedReportBase(const ScopedReportBase &) = delete;
+ void operator=(const ScopedReportBase &) = delete;
+};
+
+class ScopedReport : public ScopedReportBase {
+ public:
+ explicit ScopedReport(ReportType typ, uptr tag = kExternalTagNone);
+ ~ScopedReport();
+
+ private:
+ ScopedErrorReportLock lock_;
+};
+
+bool ShouldReport(ThreadState *thr, ReportType typ);
+ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack);
+
+// The stack could look like:
+// <start> | <main> | <foo> | tag | <bar>
+// This will extract the tag and keep:
+// <start> | <main> | <foo> | <bar>
+template<typename StackTraceTy>
+void ExtractTagFromStack(StackTraceTy *stack, uptr *tag = nullptr) {
+ if (stack->size < 2) return;
+ uptr possible_tag_pc = stack->trace[stack->size - 2];
+ uptr possible_tag = TagFromShadowStackFrame(possible_tag_pc);
+ if (possible_tag == kExternalTagNone) return;
+ stack->trace_buffer[stack->size - 2] = stack->trace_buffer[stack->size - 1];
+ stack->size -= 1;
+ if (tag) *tag = possible_tag;
+}
+
+template<typename StackTraceTy>
+void ObtainCurrentStack(ThreadState *thr, uptr toppc, StackTraceTy *stack,
+ uptr *tag = nullptr) {
+ uptr size = thr->shadow_stack_pos - thr->shadow_stack;
+ uptr start = 0;
+ if (size + !!toppc > kStackTraceMax) {
+ start = size + !!toppc - kStackTraceMax;
+ size = kStackTraceMax - !!toppc;
+ }
+ stack->Init(&thr->shadow_stack[start], size, toppc);
+ ExtractTagFromStack(stack, tag);
+}
+
+#define GET_STACK_TRACE_FATAL(thr, pc) \
+ VarSizeStackTrace stack; \
+ ObtainCurrentStack(thr, pc, &stack); \
+ stack.ReverseOrder();
+
+void MapShadow(uptr addr, uptr size);
+void MapThreadTrace(uptr addr, uptr size, const char *name);
+void DontNeedShadowFor(uptr addr, uptr size);
+void UnmapShadow(ThreadState *thr, uptr addr, uptr size);
+void InitializeShadowMemory();
+void DontDumpShadow(uptr addr, uptr size);
+void InitializeInterceptors();
+void InitializeLibIgnore();
+void InitializeDynamicAnnotations();
+
+void ForkBefore(ThreadState *thr, uptr pc);
+void ForkParentAfter(ThreadState *thr, uptr pc);
+void ForkChildAfter(ThreadState *thr, uptr pc, bool start_thread);
+
+void ReportRace(ThreadState *thr, RawShadow *shadow_mem, Shadow cur, Shadow old,
+ AccessType typ);
+bool OutputReport(ThreadState *thr, const ScopedReport &srep);
+bool IsFiredSuppression(Context *ctx, ReportType type, StackTrace trace);
+bool IsExpectedReport(uptr addr, uptr size);
+
+#if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 1
+# define DPrintf Printf
+#else
+# define DPrintf(...)
+#endif
+
+#if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 2
+# define DPrintf2 Printf
+#else
+# define DPrintf2(...)
+#endif
+
+StackID CurrentStackId(ThreadState *thr, uptr pc);
+ReportStack *SymbolizeStackId(StackID stack_id);
+void PrintCurrentStack(ThreadState *thr, uptr pc);
+void PrintCurrentStackSlow(uptr pc); // uses libunwind
+MBlock *JavaHeapBlock(uptr addr, uptr *start);
+
+void Initialize(ThreadState *thr);
+void MaybeSpawnBackgroundThread();
+int Finalize(ThreadState *thr);
+
+void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write);
+void OnUserFree(ThreadState *thr, uptr pc, uptr p, bool write);
+
+void MemoryAccess(ThreadState *thr, uptr pc, uptr addr, uptr size,
+ AccessType typ);
+void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr, uptr size,
+ AccessType typ);
+// This creates 2 non-inlined specialized versions of MemoryAccessRange.
+template <bool is_read>
+void MemoryAccessRangeT(ThreadState *thr, uptr pc, uptr addr, uptr size);
+
+ALWAYS_INLINE
+void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size,
+ bool is_write) {
+ if (size == 0)
+ return;
+ if (is_write)
+ MemoryAccessRangeT<false>(thr, pc, addr, size);
+ else
+ MemoryAccessRangeT<true>(thr, pc, addr, size);
+}
+
+void ShadowSet(RawShadow *p, RawShadow *end, RawShadow v);
+void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size);
+void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size);
+void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size);
+void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr,
+ uptr size);
+
+void ThreadIgnoreBegin(ThreadState *thr, uptr pc);
+void ThreadIgnoreEnd(ThreadState *thr);
+void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc);
+void ThreadIgnoreSyncEnd(ThreadState *thr);
+
+Tid ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached);
+void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
+ ThreadType thread_type);
+void ThreadFinish(ThreadState *thr);
+Tid ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid);
+void ThreadJoin(ThreadState *thr, uptr pc, Tid tid);
+void ThreadDetach(ThreadState *thr, uptr pc, Tid tid);
+void ThreadFinalize(ThreadState *thr);
+void ThreadSetName(ThreadState *thr, const char *name);
+int ThreadCount(ThreadState *thr);
+void ProcessPendingSignalsImpl(ThreadState *thr);
+void ThreadNotJoined(ThreadState *thr, uptr pc, Tid tid, uptr uid);
+
+Processor *ProcCreate();
+void ProcDestroy(Processor *proc);
+void ProcWire(Processor *proc, ThreadState *thr);
+void ProcUnwire(Processor *proc, ThreadState *thr);
+
+// Note: the parameter is called flagz, because flags is already taken
+// by the global function that returns flags.
+void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
+void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
+void MutexPreLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
+void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0,
+ int rec = 1);
+int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
+void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
+void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
+void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr);
+void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr);
+void MutexRepair(ThreadState *thr, uptr pc, uptr addr); // call on EOWNERDEAD
+void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr);
+
+void Acquire(ThreadState *thr, uptr pc, uptr addr);
+// AcquireGlobal synchronizes the current thread with all other threads.
+// In terms of happens-before relation, it draws a HB edge from all threads
+// (where they happen to execute right now) to the current thread. We use it to
+// handle Go finalizers. Namely, finalizer goroutine executes AcquireGlobal
+// right before executing finalizers. This provides a coarse, but simple
+// approximation of the actual required synchronization.
+void AcquireGlobal(ThreadState *thr);
+void Release(ThreadState *thr, uptr pc, uptr addr);
+void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr);
+void ReleaseStore(ThreadState *thr, uptr pc, uptr addr);
+void AfterSleep(ThreadState *thr, uptr pc);
+void IncrementEpoch(ThreadState *thr);
+
+#if !SANITIZER_GO
+uptr ALWAYS_INLINE HeapEnd() {
+ return HeapMemEnd() + PrimaryAllocator::AdditionalSize();
+}
+#endif
+
+void SlotAttachAndLock(ThreadState *thr) SANITIZER_ACQUIRE(thr->slot->mtx);
+void SlotDetach(ThreadState *thr);
+void SlotLock(ThreadState *thr) SANITIZER_ACQUIRE(thr->slot->mtx);
+void SlotUnlock(ThreadState *thr) SANITIZER_RELEASE(thr->slot->mtx);
+void DoReset(ThreadState *thr, uptr epoch);
+void FlushShadowMemory();
+
+ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags);
+void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber);
+void FiberSwitch(ThreadState *thr, uptr pc, ThreadState *fiber, unsigned flags);
+
+// These need to match __tsan_switch_to_fiber_* flags defined in
+// tsan_interface.h. See documentation there as well.
+enum FiberSwitchFlags {
+ FiberSwitchFlagNoSync = 1 << 0, // __tsan_switch_to_fiber_no_sync
+};
+
+class SlotLocker {
+ public:
+ ALWAYS_INLINE
+ SlotLocker(ThreadState *thr, bool recursive = false)
+ : thr_(thr), locked_(recursive ? thr->slot_locked : false) {
+#if !SANITIZER_GO
+ // We are in trouble if we are here with in_blocking_func set.
+ // If in_blocking_func is set, all signals will be delivered synchronously,
+ // which means we can't lock slots since the signal handler will try
+ // to lock it recursively and deadlock.
+ DCHECK(!atomic_load(&thr->in_blocking_func, memory_order_relaxed));
+#endif
+ if (!locked_)
+ SlotLock(thr_);
+ }
+
+ ALWAYS_INLINE
+ ~SlotLocker() {
+ if (!locked_)
+ SlotUnlock(thr_);
+ }
+
+ private:
+ ThreadState *thr_;
+ bool locked_;
+};
+
+class SlotUnlocker {
+ public:
+ SlotUnlocker(ThreadState *thr) : thr_(thr), locked_(thr->slot_locked) {
+ if (locked_)
+ SlotUnlock(thr_);
+ }
+
+ ~SlotUnlocker() {
+ if (locked_)
+ SlotLock(thr_);
+ }
+
+ private:
+ ThreadState *thr_;
+ bool locked_;
+};
+
+ALWAYS_INLINE void ProcessPendingSignals(ThreadState *thr) {
+ if (UNLIKELY(atomic_load_relaxed(&thr->pending_signals)))
+ ProcessPendingSignalsImpl(thr);
+}
+
+extern bool is_initialized;
+
+ALWAYS_INLINE
+void LazyInitialize(ThreadState *thr) {
+ // If we can use .preinit_array, assume that __tsan_init
+ // called from .preinit_array initializes runtime before
+ // any instrumented code except when tsan is used as a
+ // shared library.
+#if (!SANITIZER_CAN_USE_PREINIT_ARRAY || defined(SANITIZER_SHARED))
+ if (UNLIKELY(!is_initialized))
+ Initialize(thr);
+#endif
+}
+
+void TraceResetForTesting();
+void TraceSwitchPart(ThreadState *thr);
+void TraceSwitchPartImpl(ThreadState *thr);
+bool RestoreStack(EventType type, Sid sid, Epoch epoch, uptr addr, uptr size,
+ AccessType typ, Tid *ptid, VarSizeStackTrace *pstk,
+ MutexSet *pmset, uptr *ptag);
+
+template <typename EventT>
+ALWAYS_INLINE WARN_UNUSED_RESULT bool TraceAcquire(ThreadState *thr,
+ EventT **ev) {
+ // TraceSwitchPart accesses shadow_stack, but it's called infrequently,
+ // so we check it here proactively.
+ DCHECK(thr->shadow_stack);
+ Event *pos = reinterpret_cast<Event *>(atomic_load_relaxed(&thr->trace_pos));
+#if SANITIZER_DEBUG
+ // TraceSwitch acquires these mutexes,
+ // so we lock them here to detect deadlocks more reliably.
+ { Lock lock(&ctx->slot_mtx); }
+ { Lock lock(&thr->tctx->trace.mtx); }
+ TracePart *current = thr->tctx->trace.parts.Back();
+ if (current) {
+ DCHECK_GE(pos, &current->events[0]);
+ DCHECK_LE(pos, &current->events[TracePart::kSize]);
+ } else {
+ DCHECK_EQ(pos, nullptr);
+ }
+#endif
+ // TracePart is allocated with mmap and is at least 4K aligned.
+ // So the following check is a faster way to check for part end.
+ // It may have false positives in the middle of the trace,
+ // they are filtered out in TraceSwitch.
+ if (UNLIKELY(((uptr)(pos + 1) & TracePart::kAlignment) == 0))
+ return false;
+ *ev = reinterpret_cast<EventT *>(pos);
+ return true;
+}
+
+template <typename EventT>
+ALWAYS_INLINE void TraceRelease(ThreadState *thr, EventT *evp) {
+ DCHECK_LE(evp + 1, &thr->tctx->trace.parts.Back()->events[TracePart::kSize]);
+ atomic_store_relaxed(&thr->trace_pos, (uptr)(evp + 1));
+}
+
+template <typename EventT>
+void TraceEvent(ThreadState *thr, EventT ev) {
+ EventT *evp;
+ if (!TraceAcquire(thr, &evp)) {
+ TraceSwitchPart(thr);
+ UNUSED bool res = TraceAcquire(thr, &evp);
+ DCHECK(res);
+ }
+ *evp = ev;
+ TraceRelease(thr, evp);
+}
+
+ALWAYS_INLINE WARN_UNUSED_RESULT bool TryTraceFunc(ThreadState *thr,
+ uptr pc = 0) {
+ if (!kCollectHistory)
+ return true;
+ EventFunc *ev;
+ if (UNLIKELY(!TraceAcquire(thr, &ev)))
+ return false;
+ ev->is_access = 0;
+ ev->is_func = 1;
+ ev->pc = pc;
+ TraceRelease(thr, ev);
+ return true;
+}
+
+WARN_UNUSED_RESULT
+bool TryTraceMemoryAccess(ThreadState *thr, uptr pc, uptr addr, uptr size,
+ AccessType typ);
+WARN_UNUSED_RESULT
+bool TryTraceMemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size,
+ AccessType typ);
+void TraceMemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size,
+ AccessType typ);
+void TraceFunc(ThreadState *thr, uptr pc = 0);
+void TraceMutexLock(ThreadState *thr, EventType type, uptr pc, uptr addr,
+ StackID stk);
+void TraceMutexUnlock(ThreadState *thr, uptr addr);
+void TraceTime(ThreadState *thr);
+
+void TraceRestartFuncExit(ThreadState *thr);
+void TraceRestartFuncEntry(ThreadState *thr, uptr pc);
+
+void GrowShadowStack(ThreadState *thr);
+
+ALWAYS_INLINE
+void FuncEntry(ThreadState *thr, uptr pc) {
+ DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.sid(), (void *)pc);
+ if (UNLIKELY(!TryTraceFunc(thr, pc)))
+ return TraceRestartFuncEntry(thr, pc);
+ DCHECK_GE(thr->shadow_stack_pos, thr->shadow_stack);
+#if !SANITIZER_GO
+ DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
+#else
+ if (thr->shadow_stack_pos == thr->shadow_stack_end)
+ GrowShadowStack(thr);
+#endif
+ thr->shadow_stack_pos[0] = pc;
+ thr->shadow_stack_pos++;
+}
+
+ALWAYS_INLINE
+void FuncExit(ThreadState *thr) {
+ DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.sid());
+ if (UNLIKELY(!TryTraceFunc(thr, 0)))
+ return TraceRestartFuncExit(thr);
+ DCHECK_GT(thr->shadow_stack_pos, thr->shadow_stack);
+#if !SANITIZER_GO
+ DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
+#endif
+ thr->shadow_stack_pos--;
+}
+
+#if !SANITIZER_GO
+extern void (*on_initialize)(void);
+extern int (*on_finalize)(int);
+#endif
+} // namespace __tsan
+
+#endif // TSAN_RTL_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_aarch64.S b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_aarch64.S
new file mode 100644
index 00000000000..e0b4c71dfed
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_aarch64.S
@@ -0,0 +1,245 @@
+// The content of this file is AArch64-only:
+#if defined(__aarch64__)
+
+#include "sanitizer_common/sanitizer_asm.h"
+
+#if defined(__APPLE__)
+.align 2
+
+.section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers
+.long _setjmp$non_lazy_ptr
+_setjmp$non_lazy_ptr:
+.indirect_symbol _setjmp
+.long 0
+
+.section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers
+.long __setjmp$non_lazy_ptr
+__setjmp$non_lazy_ptr:
+.indirect_symbol __setjmp
+.long 0
+
+.section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers
+.long _sigsetjmp$non_lazy_ptr
+_sigsetjmp$non_lazy_ptr:
+.indirect_symbol _sigsetjmp
+.long 0
+#endif
+
+#if !defined(__APPLE__)
+.section .text
+#else
+.section __TEXT,__text
+.align 3
+#endif
+
+ASM_HIDDEN(__tsan_setjmp)
+.comm _ZN14__interception11real_setjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(setjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(setjmp))
+ASM_SYMBOL_INTERCEPTOR(setjmp):
+ CFI_STARTPROC
+
+ // Save frame/link register
+ stp x29, x30, [sp, -32]!
+ CFI_DEF_CFA_OFFSET (32)
+ CFI_OFFSET (29, -32)
+ CFI_OFFSET (30, -24)
+
+ // Adjust the SP for previous frame
+ add x29, sp, 0
+ CFI_DEF_CFA_REGISTER (29)
+
+ // Save env parameter
+ str x0, [sp, 16]
+ CFI_OFFSET (0, -16)
+
+ // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
+ add x0, x29, 32
+
+ // call tsan interceptor
+ bl ASM_SYMBOL(__tsan_setjmp)
+
+ // Restore env parameter
+ ldr x0, [sp, 16]
+ CFI_RESTORE (0)
+
+ // Restore frame/link register
+ ldp x29, x30, [sp], 32
+ CFI_RESTORE (29)
+ CFI_RESTORE (30)
+ CFI_DEF_CFA (31, 0)
+
+ // tail jump to libc setjmp
+#if !defined(__APPLE__)
+ adrp x1, :got:_ZN14__interception11real_setjmpE
+ ldr x1, [x1, #:got_lo12:_ZN14__interception11real_setjmpE]
+ ldr x1, [x1]
+#else
+ adrp x1, _setjmp$non_lazy_ptr@page
+ add x1, x1, _setjmp$non_lazy_ptr@pageoff
+ ldr x1, [x1]
+#endif
+ br x1
+
+ CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(setjmp))
+
+.comm _ZN14__interception12real__setjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(_setjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(_setjmp))
+ASM_SYMBOL_INTERCEPTOR(_setjmp):
+ CFI_STARTPROC
+
+ // Save frame/link register
+ stp x29, x30, [sp, -32]!
+ CFI_DEF_CFA_OFFSET (32)
+ CFI_OFFSET (29, -32)
+ CFI_OFFSET (30, -24)
+
+ // Adjust the SP for previous frame
+ add x29, sp, 0
+ CFI_DEF_CFA_REGISTER (29)
+
+ // Save env parameter
+ str x0, [sp, 16]
+ CFI_OFFSET (0, -16)
+
+ // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
+ add x0, x29, 32
+
+ // call tsan interceptor
+ bl ASM_SYMBOL(__tsan_setjmp)
+
+ // Restore env parameter
+ ldr x0, [sp, 16]
+ CFI_RESTORE (0)
+
+ // Restore frame/link register
+ ldp x29, x30, [sp], 32
+ CFI_RESTORE (29)
+ CFI_RESTORE (30)
+ CFI_DEF_CFA (31, 0)
+
+ // tail jump to libc setjmp
+#if !defined(__APPLE__)
+ adrp x1, :got:_ZN14__interception12real__setjmpE
+ ldr x1, [x1, #:got_lo12:_ZN14__interception12real__setjmpE]
+ ldr x1, [x1]
+#else
+ adrp x1, __setjmp$non_lazy_ptr@page
+ add x1, x1, __setjmp$non_lazy_ptr@pageoff
+ ldr x1, [x1]
+#endif
+ br x1
+
+ CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(_setjmp))
+
+.comm _ZN14__interception14real_sigsetjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(sigsetjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
+ASM_SYMBOL_INTERCEPTOR(sigsetjmp):
+ CFI_STARTPROC
+
+ // Save frame/link register
+ stp x29, x30, [sp, -32]!
+ CFI_DEF_CFA_OFFSET (32)
+ CFI_OFFSET (29, -32)
+ CFI_OFFSET (30, -24)
+
+ // Adjust the SP for previous frame
+ add x29, sp, 0
+ CFI_DEF_CFA_REGISTER (29)
+
+ // Save env and savesigs parameter
+ stp x0, x1, [sp, 16]
+ CFI_OFFSET (0, -16)
+ CFI_OFFSET (1, -8)
+
+ // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
+ add x0, x29, 32
+
+ // call tsan interceptor
+ bl ASM_SYMBOL(__tsan_setjmp)
+
+ // Restore env and savesigs parameter
+ ldp x0, x1, [sp, 16]
+ CFI_RESTORE (0)
+ CFI_RESTORE (1)
+
+ // Restore frame/link register
+ ldp x29, x30, [sp], 32
+ CFI_RESTORE (29)
+ CFI_RESTORE (30)
+ CFI_DEF_CFA (31, 0)
+
+ // tail jump to libc sigsetjmp
+#if !defined(__APPLE__)
+ adrp x2, :got:_ZN14__interception14real_sigsetjmpE
+ ldr x2, [x2, #:got_lo12:_ZN14__interception14real_sigsetjmpE]
+ ldr x2, [x2]
+#else
+ adrp x2, _sigsetjmp$non_lazy_ptr@page
+ add x2, x2, _sigsetjmp$non_lazy_ptr@pageoff
+ ldr x2, [x2]
+#endif
+ br x2
+ CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
+
+#if !defined(__APPLE__)
+.comm _ZN14__interception16real___sigsetjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(__sigsetjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
+ASM_SYMBOL_INTERCEPTOR(__sigsetjmp):
+ CFI_STARTPROC
+
+ // Save frame/link register
+ stp x29, x30, [sp, -32]!
+ CFI_DEF_CFA_OFFSET (32)
+ CFI_OFFSET (29, -32)
+ CFI_OFFSET (30, -24)
+
+ // Adjust the SP for previous frame
+ add x29, sp, 0
+ CFI_DEF_CFA_REGISTER (29)
+
+ // Save env and savesigs parameter
+ stp x0, x1, [sp, 16]
+ CFI_OFFSET (0, -16)
+ CFI_OFFSET (1, -8)
+
+ // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
+ add x0, x29, 32
+
+ // call tsan interceptor
+ bl ASM_SYMBOL(__tsan_setjmp)
+
+ // Restore env and savesigs parameter
+ ldp x0, x1, [sp, 16]
+ CFI_RESTORE (0)
+ CFI_RESTORE (1)
+
+ // Restore frame/link register
+ ldp x29, x30, [sp], 32
+ CFI_RESTORE (29)
+ CFI_RESTORE (30)
+ CFI_DEF_CFA (31, 0)
+
+ // tail jump to libc __sigsetjmp
+#if !defined(__APPLE__)
+ adrp x2, :got:_ZN14__interception16real___sigsetjmpE
+ ldr x2, [x2, #:got_lo12:_ZN14__interception16real___sigsetjmpE]
+ ldr x2, [x2]
+#else
+ adrp x2, ASM_SYMBOL(__sigsetjmp)@page
+ add x2, x2, ASM_SYMBOL(__sigsetjmp)@pageoff
+#endif
+ br x2
+ CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
+#endif
+
+NO_EXEC_STACK_DIRECTIVE
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_access.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_access.cpp
new file mode 100644
index 00000000000..8b20984a010
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_access.cpp
@@ -0,0 +1,744 @@
+//===-- tsan_rtl_access.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+// Definitions of memory access and function entry/exit entry points.
+//===----------------------------------------------------------------------===//
+
+#include "tsan_rtl.h"
+
+namespace __tsan {
+
+ALWAYS_INLINE USED bool TryTraceMemoryAccess(ThreadState* thr, uptr pc,
+ uptr addr, uptr size,
+ AccessType typ) {
+ DCHECK(size == 1 || size == 2 || size == 4 || size == 8);
+ if (!kCollectHistory)
+ return true;
+ EventAccess* ev;
+ if (UNLIKELY(!TraceAcquire(thr, &ev)))
+ return false;
+ u64 size_log = size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : 3;
+ uptr pc_delta = pc - thr->trace_prev_pc + (1 << (EventAccess::kPCBits - 1));
+ thr->trace_prev_pc = pc;
+ if (LIKELY(pc_delta < (1 << EventAccess::kPCBits))) {
+ ev->is_access = 1;
+ ev->is_read = !!(typ & kAccessRead);
+ ev->is_atomic = !!(typ & kAccessAtomic);
+ ev->size_log = size_log;
+ ev->pc_delta = pc_delta;
+ DCHECK_EQ(ev->pc_delta, pc_delta);
+ ev->addr = CompressAddr(addr);
+ TraceRelease(thr, ev);
+ return true;
+ }
+ auto* evex = reinterpret_cast<EventAccessExt*>(ev);
+ evex->is_access = 0;
+ evex->is_func = 0;
+ evex->type = EventType::kAccessExt;
+ evex->is_read = !!(typ & kAccessRead);
+ evex->is_atomic = !!(typ & kAccessAtomic);
+ evex->size_log = size_log;
+ // Note: this is important, see comment in EventAccessExt.
+ evex->_ = 0;
+ evex->addr = CompressAddr(addr);
+ evex->pc = pc;
+ TraceRelease(thr, evex);
+ return true;
+}
+
+ALWAYS_INLINE
+bool TryTraceMemoryAccessRange(ThreadState* thr, uptr pc, uptr addr, uptr size,
+ AccessType typ) {
+ if (!kCollectHistory)
+ return true;
+ EventAccessRange* ev;
+ if (UNLIKELY(!TraceAcquire(thr, &ev)))
+ return false;
+ thr->trace_prev_pc = pc;
+ ev->is_access = 0;
+ ev->is_func = 0;
+ ev->type = EventType::kAccessRange;
+ ev->is_read = !!(typ & kAccessRead);
+ ev->is_free = !!(typ & kAccessFree);
+ ev->size_lo = size;
+ ev->pc = CompressAddr(pc);
+ ev->addr = CompressAddr(addr);
+ ev->size_hi = size >> EventAccessRange::kSizeLoBits;
+ TraceRelease(thr, ev);
+ return true;
+}
+
+void TraceMemoryAccessRange(ThreadState* thr, uptr pc, uptr addr, uptr size,
+ AccessType typ) {
+ if (LIKELY(TryTraceMemoryAccessRange(thr, pc, addr, size, typ)))
+ return;
+ TraceSwitchPart(thr);
+ UNUSED bool res = TryTraceMemoryAccessRange(thr, pc, addr, size, typ);
+ DCHECK(res);
+}
+
+void TraceFunc(ThreadState* thr, uptr pc) {
+ if (LIKELY(TryTraceFunc(thr, pc)))
+ return;
+ TraceSwitchPart(thr);
+ UNUSED bool res = TryTraceFunc(thr, pc);
+ DCHECK(res);
+}
+
+NOINLINE void TraceRestartFuncEntry(ThreadState* thr, uptr pc) {
+ TraceSwitchPart(thr);
+ FuncEntry(thr, pc);
+}
+
+NOINLINE void TraceRestartFuncExit(ThreadState* thr) {
+ TraceSwitchPart(thr);
+ FuncExit(thr);
+}
+
+void TraceMutexLock(ThreadState* thr, EventType type, uptr pc, uptr addr,
+ StackID stk) {
+ DCHECK(type == EventType::kLock || type == EventType::kRLock);
+ if (!kCollectHistory)
+ return;
+ EventLock ev;
+ ev.is_access = 0;
+ ev.is_func = 0;
+ ev.type = type;
+ ev.pc = CompressAddr(pc);
+ ev.stack_lo = stk;
+ ev.stack_hi = stk >> EventLock::kStackIDLoBits;
+ ev._ = 0;
+ ev.addr = CompressAddr(addr);
+ TraceEvent(thr, ev);
+}
+
+void TraceMutexUnlock(ThreadState* thr, uptr addr) {
+ if (!kCollectHistory)
+ return;
+ EventUnlock ev;
+ ev.is_access = 0;
+ ev.is_func = 0;
+ ev.type = EventType::kUnlock;
+ ev._ = 0;
+ ev.addr = CompressAddr(addr);
+ TraceEvent(thr, ev);
+}
+
+void TraceTime(ThreadState* thr) {
+ if (!kCollectHistory)
+ return;
+ FastState fast_state = thr->fast_state;
+ EventTime ev;
+ ev.is_access = 0;
+ ev.is_func = 0;
+ ev.type = EventType::kTime;
+ ev.sid = static_cast<u64>(fast_state.sid());
+ ev.epoch = static_cast<u64>(fast_state.epoch());
+ ev._ = 0;
+ TraceEvent(thr, ev);
+}
+
+NOINLINE void DoReportRace(ThreadState* thr, RawShadow* shadow_mem, Shadow cur,
+ Shadow old,
+ AccessType typ) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
+ // For the free shadow markers the first element (that contains kFreeSid)
+ // triggers the race, but the second element contains info about the freeing
+ // thread, take it.
+ if (old.sid() == kFreeSid)
+ old = Shadow(LoadShadow(&shadow_mem[1]));
+ // This prevents trapping on this address in future.
+ for (uptr i = 0; i < kShadowCnt; i++)
+ StoreShadow(&shadow_mem[i], i == 0 ? Shadow::kRodata : Shadow::kEmpty);
+ // See the comment in MemoryRangeFreed as to why the slot is locked
+ // for free memory accesses. ReportRace must not be called with
+ // the slot locked because of the fork. But MemoryRangeFreed is not
+ // called during fork because fork sets ignore_reads_and_writes,
+ // so simply unlocking the slot should be fine.
+ if (typ & kAccessSlotLocked)
+ SlotUnlock(thr);
+ ReportRace(thr, shadow_mem, cur, Shadow(old), typ);
+ if (typ & kAccessSlotLocked)
+ SlotLock(thr);
+}
+
+#if !TSAN_VECTORIZE
+ALWAYS_INLINE
+bool ContainsSameAccess(RawShadow* s, Shadow cur, int unused0, int unused1,
+ AccessType typ) {
+ for (uptr i = 0; i < kShadowCnt; i++) {
+ auto old = LoadShadow(&s[i]);
+ if (!(typ & kAccessRead)) {
+ if (old == cur.raw())
+ return true;
+ continue;
+ }
+ auto masked = static_cast<RawShadow>(static_cast<u32>(old) |
+ static_cast<u32>(Shadow::kRodata));
+ if (masked == cur.raw())
+ return true;
+ if (!(typ & kAccessNoRodata) && !SANITIZER_GO) {
+ if (old == Shadow::kRodata)
+ return true;
+ }
+ }
+ return false;
+}
+
+ALWAYS_INLINE
+bool CheckRaces(ThreadState* thr, RawShadow* shadow_mem, Shadow cur,
+ int unused0, int unused1, AccessType typ) {
+ bool stored = false;
+ for (uptr idx = 0; idx < kShadowCnt; idx++) {
+ RawShadow* sp = &shadow_mem[idx];
+ Shadow old(LoadShadow(sp));
+ if (LIKELY(old.raw() == Shadow::kEmpty)) {
+ if (!(typ & kAccessCheckOnly) && !stored)
+ StoreShadow(sp, cur.raw());
+ return false;
+ }
+ if (LIKELY(!(cur.access() & old.access())))
+ continue;
+ if (LIKELY(cur.sid() == old.sid())) {
+ if (!(typ & kAccessCheckOnly) &&
+ LIKELY(cur.access() == old.access() && old.IsRWWeakerOrEqual(typ))) {
+ StoreShadow(sp, cur.raw());
+ stored = true;
+ }
+ continue;
+ }
+ if (LIKELY(old.IsBothReadsOrAtomic(typ)))
+ continue;
+ if (LIKELY(thr->clock.Get(old.sid()) >= old.epoch()))
+ continue;
+ DoReportRace(thr, shadow_mem, cur, old, typ);
+ return true;
+ }
+ // We did not find any races and had already stored
+ // the current access info, so we are done.
+ if (LIKELY(stored))
+ return false;
+ // Choose a random candidate slot and replace it.
+ uptr index =
+ atomic_load_relaxed(&thr->trace_pos) / sizeof(Event) % kShadowCnt;
+ StoreShadow(&shadow_mem[index], cur.raw());
+ return false;
+}
+
+# define LOAD_CURRENT_SHADOW(cur, shadow_mem) UNUSED int access = 0, shadow = 0
+
+#else /* !TSAN_VECTORIZE */
+
+ALWAYS_INLINE
+bool ContainsSameAccess(RawShadow* unused0, Shadow unused1, m128 shadow,
+ m128 access, AccessType typ) {
+ // Note: we could check if there is a larger access of the same type,
+ // e.g. we just allocated/memset-ed a block (so it contains 8 byte writes)
+ // and now do smaller reads/writes, these can also be considered as "same
+ // access". However, it will make the check more expensive, so it's unclear
+ // if it's worth it. But this would conserve trace space, so it's useful
+ // besides potential speed up.
+ if (!(typ & kAccessRead)) {
+ const m128 same = _mm_cmpeq_epi32(shadow, access);
+ return _mm_movemask_epi8(same);
+ }
+ // For reads we need to reset read bit in the shadow,
+ // because we need to match read with both reads and writes.
+ // Shadow::kRodata has only read bit set, so it does what we want.
+ // We also abuse it for rodata check to save few cycles
+ // since we already loaded Shadow::kRodata into a register.
+ // Reads from rodata can't race.
+ // Measurements show that they can be 10-20% of all memory accesses.
+ // Shadow::kRodata has epoch 0 which cannot appear in shadow normally
+ // (thread epochs start from 1). So the same read bit mask
+ // serves as rodata indicator.
+ const m128 read_mask = _mm_set1_epi32(static_cast<u32>(Shadow::kRodata));
+ const m128 masked_shadow = _mm_or_si128(shadow, read_mask);
+ m128 same = _mm_cmpeq_epi32(masked_shadow, access);
+ // Range memory accesses check Shadow::kRodata before calling this,
+ // Shadow::kRodatas is not possible for free memory access
+ // and Go does not use Shadow::kRodata.
+ if (!(typ & kAccessNoRodata) && !SANITIZER_GO) {
+ const m128 ro = _mm_cmpeq_epi32(shadow, read_mask);
+ same = _mm_or_si128(ro, same);
+ }
+ return _mm_movemask_epi8(same);
+}
+
+NOINLINE void DoReportRaceV(ThreadState* thr, RawShadow* shadow_mem, Shadow cur,
+ u32 race_mask, m128 shadow, AccessType typ) {
+ // race_mask points which of the shadow elements raced with the current
+ // access. Extract that element.
+ CHECK_NE(race_mask, 0);
+ u32 old;
+ // Note: _mm_extract_epi32 index must be a constant value.
+ switch (__builtin_ffs(race_mask) / 4) {
+ case 0:
+ old = _mm_extract_epi32(shadow, 0);
+ break;
+ case 1:
+ old = _mm_extract_epi32(shadow, 1);
+ break;
+ case 2:
+ old = _mm_extract_epi32(shadow, 2);
+ break;
+ case 3:
+ old = _mm_extract_epi32(shadow, 3);
+ break;
+ }
+ Shadow prev(static_cast<RawShadow>(old));
+ // For the free shadow markers the first element (that contains kFreeSid)
+ // triggers the race, but the second element contains info about the freeing
+ // thread, take it.
+ if (prev.sid() == kFreeSid)
+ prev = Shadow(static_cast<RawShadow>(_mm_extract_epi32(shadow, 1)));
+ DoReportRace(thr, shadow_mem, cur, prev, typ);
+}
+
+ALWAYS_INLINE
+bool CheckRaces(ThreadState* thr, RawShadow* shadow_mem, Shadow cur,
+ m128 shadow, m128 access, AccessType typ) {
+ // Note: empty/zero slots don't intersect with any access.
+ const m128 zero = _mm_setzero_si128();
+ const m128 mask_access = _mm_set1_epi32(0x000000ff);
+ const m128 mask_sid = _mm_set1_epi32(0x0000ff00);
+ const m128 mask_read_atomic = _mm_set1_epi32(0xc0000000);
+ const m128 access_and = _mm_and_si128(access, shadow);
+ const m128 access_xor = _mm_xor_si128(access, shadow);
+ const m128 intersect = _mm_and_si128(access_and, mask_access);
+ const m128 not_intersect = _mm_cmpeq_epi32(intersect, zero);
+ const m128 not_same_sid = _mm_and_si128(access_xor, mask_sid);
+ const m128 same_sid = _mm_cmpeq_epi32(not_same_sid, zero);
+ const m128 both_read_or_atomic = _mm_and_si128(access_and, mask_read_atomic);
+ const m128 no_race =
+ _mm_or_si128(_mm_or_si128(not_intersect, same_sid), both_read_or_atomic);
+ const int race_mask = _mm_movemask_epi8(_mm_cmpeq_epi32(no_race, zero));
+ if (UNLIKELY(race_mask))
+ goto SHARED;
+
+STORE : {
+ if (typ & kAccessCheckOnly)
+ return false;
+ // We could also replace different sid's if access is the same,
+ // rw weaker and happens before. However, just checking access below
+ // is not enough because we also need to check that !both_read_or_atomic
+ // (reads from different sids can be concurrent).
+ // Theoretically we could replace smaller accesses with larger accesses,
+ // but it's unclear if it's worth doing.
+ const m128 mask_access_sid = _mm_set1_epi32(0x0000ffff);
+ const m128 not_same_sid_access = _mm_and_si128(access_xor, mask_access_sid);
+ const m128 same_sid_access = _mm_cmpeq_epi32(not_same_sid_access, zero);
+ const m128 access_read_atomic =
+ _mm_set1_epi32((typ & (kAccessRead | kAccessAtomic)) << 30);
+ const m128 rw_weaker =
+ _mm_cmpeq_epi32(_mm_max_epu32(shadow, access_read_atomic), shadow);
+ const m128 rewrite = _mm_and_si128(same_sid_access, rw_weaker);
+ const int rewrite_mask = _mm_movemask_epi8(rewrite);
+ int index = __builtin_ffs(rewrite_mask);
+ if (UNLIKELY(index == 0)) {
+ const m128 empty = _mm_cmpeq_epi32(shadow, zero);
+ const int empty_mask = _mm_movemask_epi8(empty);
+ index = __builtin_ffs(empty_mask);
+ if (UNLIKELY(index == 0))
+ index = (atomic_load_relaxed(&thr->trace_pos) / 2) % 16;
+ }
+ StoreShadow(&shadow_mem[index / 4], cur.raw());
+ // We could zero other slots determined by rewrite_mask.
+ // That would help other threads to evict better slots,
+ // but it's unclear if it's worth it.
+ return false;
+}
+
+SHARED:
+ m128 thread_epochs = _mm_set1_epi32(0x7fffffff);
+ // Need to unwind this because _mm_extract_epi8/_mm_insert_epi32
+ // indexes must be constants.
+# define LOAD_EPOCH(idx) \
+ if (LIKELY(race_mask & (1 << (idx * 4)))) { \
+ u8 sid = _mm_extract_epi8(shadow, idx * 4 + 1); \
+ u16 epoch = static_cast<u16>(thr->clock.Get(static_cast<Sid>(sid))); \
+ thread_epochs = _mm_insert_epi32(thread_epochs, u32(epoch) << 16, idx); \
+ }
+ LOAD_EPOCH(0);
+ LOAD_EPOCH(1);
+ LOAD_EPOCH(2);
+ LOAD_EPOCH(3);
+# undef LOAD_EPOCH
+ const m128 mask_epoch = _mm_set1_epi32(0x3fff0000);
+ const m128 shadow_epochs = _mm_and_si128(shadow, mask_epoch);
+ const m128 concurrent = _mm_cmplt_epi32(thread_epochs, shadow_epochs);
+ const int concurrent_mask = _mm_movemask_epi8(concurrent);
+ if (LIKELY(concurrent_mask == 0))
+ goto STORE;
+
+ DoReportRaceV(thr, shadow_mem, cur, concurrent_mask, shadow, typ);
+ return true;
+}
+
+# define LOAD_CURRENT_SHADOW(cur, shadow_mem) \
+ const m128 access = _mm_set1_epi32(static_cast<u32>((cur).raw())); \
+ const m128 shadow = _mm_load_si128(reinterpret_cast<m128*>(shadow_mem))
+#endif
+
+char* DumpShadow(char* buf, RawShadow raw) {
+ if (raw == Shadow::kEmpty) {
+ internal_snprintf(buf, 64, "0");
+ return buf;
+ }
+ Shadow s(raw);
+ AccessType typ;
+ s.GetAccess(nullptr, nullptr, &typ);
+ internal_snprintf(buf, 64, "{tid=%u@%u access=0x%x typ=%x}",
+ static_cast<u32>(s.sid()), static_cast<u32>(s.epoch()),
+ s.access(), static_cast<u32>(typ));
+ return buf;
+}
+
+// TryTrace* and TraceRestart* functions allow to turn memory access and func
+// entry/exit callbacks into leaf functions with all associated performance
+// benefits. These hottest callbacks do only 2 slow path calls: report a race
+// and trace part switching. Race reporting is easy to turn into a tail call, we
+// just always return from the runtime after reporting a race. But trace part
+// switching is harder because it needs to be in the middle of callbacks. To
+// turn it into a tail call we immidiately return after TraceRestart* functions,
+// but TraceRestart* functions themselves recurse into the callback after
+// switching trace part. As the result the hottest callbacks contain only tail
+// calls, which effectively makes them leaf functions (can use all registers,
+// no frame setup, etc).
+NOINLINE void TraceRestartMemoryAccess(ThreadState* thr, uptr pc, uptr addr,
+ uptr size, AccessType typ) {
+ TraceSwitchPart(thr);
+ MemoryAccess(thr, pc, addr, size, typ);
+}
+
+ALWAYS_INLINE USED void MemoryAccess(ThreadState* thr, uptr pc, uptr addr,
+ uptr size, AccessType typ) {
+ RawShadow* shadow_mem = MemToShadow(addr);
+ UNUSED char memBuf[4][64];
+ DPrintf2("#%d: Access: %d@%d %p/%zd typ=0x%x {%s, %s, %s, %s}\n", thr->tid,
+ static_cast<int>(thr->fast_state.sid()),
+ static_cast<int>(thr->fast_state.epoch()), (void*)addr, size,
+ static_cast<int>(typ), DumpShadow(memBuf[0], shadow_mem[0]),
+ DumpShadow(memBuf[1], shadow_mem[1]),
+ DumpShadow(memBuf[2], shadow_mem[2]),
+ DumpShadow(memBuf[3], shadow_mem[3]));
+
+ FastState fast_state = thr->fast_state;
+ Shadow cur(fast_state, addr, size, typ);
+
+ LOAD_CURRENT_SHADOW(cur, shadow_mem);
+ if (LIKELY(ContainsSameAccess(shadow_mem, cur, shadow, access, typ)))
+ return;
+ if (UNLIKELY(fast_state.GetIgnoreBit()))
+ return;
+ if (!TryTraceMemoryAccess(thr, pc, addr, size, typ))
+ return TraceRestartMemoryAccess(thr, pc, addr, size, typ);
+ CheckRaces(thr, shadow_mem, cur, shadow, access, typ);
+}
+
+void MemoryAccess16(ThreadState* thr, uptr pc, uptr addr, AccessType typ);
+
+NOINLINE
+void RestartMemoryAccess16(ThreadState* thr, uptr pc, uptr addr,
+ AccessType typ) {
+ TraceSwitchPart(thr);
+ MemoryAccess16(thr, pc, addr, typ);
+}
+
+ALWAYS_INLINE USED void MemoryAccess16(ThreadState* thr, uptr pc, uptr addr,
+ AccessType typ) {
+ const uptr size = 16;
+ FastState fast_state = thr->fast_state;
+ if (UNLIKELY(fast_state.GetIgnoreBit()))
+ return;
+ Shadow cur(fast_state, 0, 8, typ);
+ RawShadow* shadow_mem = MemToShadow(addr);
+ bool traced = false;
+ {
+ LOAD_CURRENT_SHADOW(cur, shadow_mem);
+ if (LIKELY(ContainsSameAccess(shadow_mem, cur, shadow, access, typ)))
+ goto SECOND;
+ if (!TryTraceMemoryAccessRange(thr, pc, addr, size, typ))
+ return RestartMemoryAccess16(thr, pc, addr, typ);
+ traced = true;
+ if (UNLIKELY(CheckRaces(thr, shadow_mem, cur, shadow, access, typ)))
+ return;
+ }
+SECOND:
+ shadow_mem += kShadowCnt;
+ LOAD_CURRENT_SHADOW(cur, shadow_mem);
+ if (LIKELY(ContainsSameAccess(shadow_mem, cur, shadow, access, typ)))
+ return;
+ if (!traced && !TryTraceMemoryAccessRange(thr, pc, addr, size, typ))
+ return RestartMemoryAccess16(thr, pc, addr, typ);
+ CheckRaces(thr, shadow_mem, cur, shadow, access, typ);
+}
+
+NOINLINE
+void RestartUnalignedMemoryAccess(ThreadState* thr, uptr pc, uptr addr,
+ uptr size, AccessType typ) {
+ TraceSwitchPart(thr);
+ UnalignedMemoryAccess(thr, pc, addr, size, typ);
+}
+
+ALWAYS_INLINE USED void UnalignedMemoryAccess(ThreadState* thr, uptr pc,
+ uptr addr, uptr size,
+ AccessType typ) {
+ DCHECK_LE(size, 8);
+ FastState fast_state = thr->fast_state;
+ if (UNLIKELY(fast_state.GetIgnoreBit()))
+ return;
+ RawShadow* shadow_mem = MemToShadow(addr);
+ bool traced = false;
+ uptr size1 = Min<uptr>(size, RoundUp(addr + 1, kShadowCell) - addr);
+ {
+ Shadow cur(fast_state, addr, size1, typ);
+ LOAD_CURRENT_SHADOW(cur, shadow_mem);
+ if (LIKELY(ContainsSameAccess(shadow_mem, cur, shadow, access, typ)))
+ goto SECOND;
+ if (!TryTraceMemoryAccessRange(thr, pc, addr, size, typ))
+ return RestartUnalignedMemoryAccess(thr, pc, addr, size, typ);
+ traced = true;
+ if (UNLIKELY(CheckRaces(thr, shadow_mem, cur, shadow, access, typ)))
+ return;
+ }
+SECOND:
+ uptr size2 = size - size1;
+ if (LIKELY(size2 == 0))
+ return;
+ shadow_mem += kShadowCnt;
+ Shadow cur(fast_state, 0, size2, typ);
+ LOAD_CURRENT_SHADOW(cur, shadow_mem);
+ if (LIKELY(ContainsSameAccess(shadow_mem, cur, shadow, access, typ)))
+ return;
+ if (!traced && !TryTraceMemoryAccessRange(thr, pc, addr, size, typ))
+ return RestartUnalignedMemoryAccess(thr, pc, addr, size, typ);
+ CheckRaces(thr, shadow_mem, cur, shadow, access, typ);
+}
+
+void ShadowSet(RawShadow* p, RawShadow* end, RawShadow v) {
+ DCHECK_LE(p, end);
+ DCHECK(IsShadowMem(p));
+ DCHECK(IsShadowMem(end));
+ UNUSED const uptr kAlign = kShadowCnt * kShadowSize;
+ DCHECK_EQ(reinterpret_cast<uptr>(p) % kAlign, 0);
+ DCHECK_EQ(reinterpret_cast<uptr>(end) % kAlign, 0);
+#if !TSAN_VECTORIZE
+ for (; p < end; p += kShadowCnt) {
+ p[0] = v;
+ for (uptr i = 1; i < kShadowCnt; i++) p[i] = Shadow::kEmpty;
+ }
+#else
+ m128 vv = _mm_setr_epi32(
+ static_cast<u32>(v), static_cast<u32>(Shadow::kEmpty),
+ static_cast<u32>(Shadow::kEmpty), static_cast<u32>(Shadow::kEmpty));
+ m128* vp = reinterpret_cast<m128*>(p);
+ m128* vend = reinterpret_cast<m128*>(end);
+ for (; vp < vend; vp++) _mm_store_si128(vp, vv);
+#endif
+}
+
+static void MemoryRangeSet(uptr addr, uptr size, RawShadow val) {
+ if (size == 0)
+ return;
+ DCHECK_EQ(addr % kShadowCell, 0);
+ DCHECK_EQ(size % kShadowCell, 0);
+ // If a user passes some insane arguments (memset(0)),
+ // let it just crash as usual.
+ if (!IsAppMem(addr) || !IsAppMem(addr + size - 1))
+ return;
+ RawShadow* begin = MemToShadow(addr);
+ RawShadow* end = begin + size / kShadowCell * kShadowCnt;
+ // Don't want to touch lots of shadow memory.
+ // If a program maps 10MB stack, there is no need reset the whole range.
+ // UnmapOrDie/MmapFixedNoReserve does not work on Windows.
+ if (SANITIZER_WINDOWS ||
+ size <= common_flags()->clear_shadow_mmap_threshold) {
+ ShadowSet(begin, end, val);
+ return;
+ }
+ // The region is big, reset only beginning and end.
+ const uptr kPageSize = GetPageSizeCached();
+ // Set at least first kPageSize/2 to page boundary.
+ RawShadow* mid1 =
+ Min(end, reinterpret_cast<RawShadow*>(RoundUp(
+ reinterpret_cast<uptr>(begin) + kPageSize / 2, kPageSize)));
+ ShadowSet(begin, mid1, val);
+ // Reset middle part.
+ RawShadow* mid2 = RoundDown(end, kPageSize);
+ if (mid2 > mid1) {
+ if (!MmapFixedSuperNoReserve((uptr)mid1, (uptr)mid2 - (uptr)mid1))
+ Die();
+ }
+ // Set the ending.
+ ShadowSet(mid2, end, val);
+}
+
+void MemoryResetRange(ThreadState* thr, uptr pc, uptr addr, uptr size) {
+ uptr addr1 = RoundDown(addr, kShadowCell);
+ uptr size1 = RoundUp(size + addr - addr1, kShadowCell);
+ MemoryRangeSet(addr1, size1, Shadow::kEmpty);
+}
+
+void MemoryRangeFreed(ThreadState* thr, uptr pc, uptr addr, uptr size) {
+ // Callers must lock the slot to ensure synchronization with the reset.
+ // The problem with "freed" memory is that it's not "monotonic"
+ // with respect to bug detection: freed memory is bad to access,
+ // but then if the heap block is reallocated later, it's good to access.
+ // As the result a garbage "freed" shadow can lead to a false positive
+ // if it happens to match a real free in the thread trace,
+ // but the heap block was reallocated before the current memory access,
+ // so it's still good to access. It's not the case with data races.
+ DCHECK(thr->slot_locked);
+ DCHECK_EQ(addr % kShadowCell, 0);
+ size = RoundUp(size, kShadowCell);
+ // Processing more than 1k (2k of shadow) is expensive,
+ // can cause excessive memory consumption (user does not necessary touch
+ // the whole range) and most likely unnecessary.
+ size = Min<uptr>(size, 1024);
+ const AccessType typ = kAccessWrite | kAccessFree | kAccessSlotLocked |
+ kAccessCheckOnly | kAccessNoRodata;
+ TraceMemoryAccessRange(thr, pc, addr, size, typ);
+ RawShadow* shadow_mem = MemToShadow(addr);
+ Shadow cur(thr->fast_state, 0, kShadowCell, typ);
+#if TSAN_VECTORIZE
+ const m128 access = _mm_set1_epi32(static_cast<u32>(cur.raw()));
+ const m128 freed = _mm_setr_epi32(
+ static_cast<u32>(Shadow::FreedMarker()),
+ static_cast<u32>(Shadow::FreedInfo(cur.sid(), cur.epoch())), 0, 0);
+ for (; size; size -= kShadowCell, shadow_mem += kShadowCnt) {
+ const m128 shadow = _mm_load_si128((m128*)shadow_mem);
+ if (UNLIKELY(CheckRaces(thr, shadow_mem, cur, shadow, access, typ)))
+ return;
+ _mm_store_si128((m128*)shadow_mem, freed);
+ }
+#else
+ for (; size; size -= kShadowCell, shadow_mem += kShadowCnt) {
+ if (UNLIKELY(CheckRaces(thr, shadow_mem, cur, 0, 0, typ)))
+ return;
+ StoreShadow(&shadow_mem[0], Shadow::FreedMarker());
+ StoreShadow(&shadow_mem[1], Shadow::FreedInfo(cur.sid(), cur.epoch()));
+ StoreShadow(&shadow_mem[2], Shadow::kEmpty);
+ StoreShadow(&shadow_mem[3], Shadow::kEmpty);
+ }
+#endif
+}
+
+void MemoryRangeImitateWrite(ThreadState* thr, uptr pc, uptr addr, uptr size) {
+ DCHECK_EQ(addr % kShadowCell, 0);
+ size = RoundUp(size, kShadowCell);
+ TraceMemoryAccessRange(thr, pc, addr, size, kAccessWrite);
+ Shadow cur(thr->fast_state, 0, 8, kAccessWrite);
+ MemoryRangeSet(addr, size, cur.raw());
+}
+
+void MemoryRangeImitateWriteOrResetRange(ThreadState* thr, uptr pc, uptr addr,
+ uptr size) {
+ if (thr->ignore_reads_and_writes == 0)
+ MemoryRangeImitateWrite(thr, pc, addr, size);
+ else
+ MemoryResetRange(thr, pc, addr, size);
+}
+
+ALWAYS_INLINE
+bool MemoryAccessRangeOne(ThreadState* thr, RawShadow* shadow_mem, Shadow cur,
+ AccessType typ) {
+ LOAD_CURRENT_SHADOW(cur, shadow_mem);
+ if (LIKELY(ContainsSameAccess(shadow_mem, cur, shadow, access, typ)))
+ return false;
+ return CheckRaces(thr, shadow_mem, cur, shadow, access, typ);
+}
+
+template <bool is_read>
+NOINLINE void RestartMemoryAccessRange(ThreadState* thr, uptr pc, uptr addr,
+ uptr size) {
+ TraceSwitchPart(thr);
+ MemoryAccessRangeT<is_read>(thr, pc, addr, size);
+}
+
+template <bool is_read>
+void MemoryAccessRangeT(ThreadState* thr, uptr pc, uptr addr, uptr size) {
+ const AccessType typ =
+ (is_read ? kAccessRead : kAccessWrite) | kAccessNoRodata;
+ RawShadow* shadow_mem = MemToShadow(addr);
+ DPrintf2("#%d: MemoryAccessRange: @%p %p size=%d is_read=%d\n", thr->tid,
+ (void*)pc, (void*)addr, (int)size, is_read);
+
+#if SANITIZER_DEBUG
+ if (!IsAppMem(addr)) {
+ Printf("Access to non app mem %zx\n", addr);
+ DCHECK(IsAppMem(addr));
+ }
+ if (!IsAppMem(addr + size - 1)) {
+ Printf("Access to non app mem %zx\n", addr + size - 1);
+ DCHECK(IsAppMem(addr + size - 1));
+ }
+ if (!IsShadowMem(shadow_mem)) {
+ Printf("Bad shadow addr %p (%zx)\n", static_cast<void*>(shadow_mem), addr);
+ DCHECK(IsShadowMem(shadow_mem));
+ }
+ if (!IsShadowMem(shadow_mem + size * kShadowCnt - 1)) {
+ Printf("Bad shadow addr %p (%zx)\n",
+ static_cast<void*>(shadow_mem + size * kShadowCnt - 1),
+ addr + size - 1);
+ DCHECK(IsShadowMem(shadow_mem + size * kShadowCnt - 1));
+ }
+#endif
+
+ // Access to .rodata section, no races here.
+ // Measurements show that it can be 10-20% of all memory accesses.
+ // Check here once to not check for every access separately.
+ // Note: we could (and should) do this only for the is_read case
+ // (writes shouldn't go to .rodata). But it happens in Chromium tests:
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=1275581#c19
+ // Details are unknown since it happens only on CI machines.
+ if (*shadow_mem == Shadow::kRodata)
+ return;
+
+ FastState fast_state = thr->fast_state;
+ if (UNLIKELY(fast_state.GetIgnoreBit()))
+ return;
+
+ if (!TryTraceMemoryAccessRange(thr, pc, addr, size, typ))
+ return RestartMemoryAccessRange<is_read>(thr, pc, addr, size);
+
+ if (UNLIKELY(addr % kShadowCell)) {
+ // Handle unaligned beginning, if any.
+ uptr size1 = Min(size, RoundUp(addr, kShadowCell) - addr);
+ size -= size1;
+ Shadow cur(fast_state, addr, size1, typ);
+ if (UNLIKELY(MemoryAccessRangeOne(thr, shadow_mem, cur, typ)))
+ return;
+ shadow_mem += kShadowCnt;
+ }
+ // Handle middle part, if any.
+ Shadow cur(fast_state, 0, kShadowCell, typ);
+ for (; size >= kShadowCell; size -= kShadowCell, shadow_mem += kShadowCnt) {
+ if (UNLIKELY(MemoryAccessRangeOne(thr, shadow_mem, cur, typ)))
+ return;
+ }
+ // Handle ending, if any.
+ if (UNLIKELY(size)) {
+ Shadow cur(fast_state, 0, size, typ);
+ if (UNLIKELY(MemoryAccessRangeOne(thr, shadow_mem, cur, typ)))
+ return;
+ }
+}
+
+template void MemoryAccessRangeT<true>(ThreadState* thr, uptr pc, uptr addr,
+ uptr size);
+template void MemoryAccessRangeT<false>(ThreadState* thr, uptr pc, uptr addr,
+ uptr size);
+
+} // namespace __tsan
+
+#if !SANITIZER_GO
+// Must be included in this file to make sure everything is inlined.
+# include "tsan_interface.inc"
+#endif
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_amd64.S b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_amd64.S
new file mode 100644
index 00000000000..f848be9dd46
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_amd64.S
@@ -0,0 +1,210 @@
+// The content of this file is x86_64-only:
+#if defined(__x86_64__)
+
+#include "sanitizer_common/sanitizer_asm.h"
+
+#if !defined(__APPLE__)
+.section .text
+#else
+.section __TEXT,__text
+#endif
+
+ASM_HIDDEN(__tsan_setjmp)
+#if defined(__NetBSD__)
+.comm _ZN14__interception15real___setjmp14E,8,8
+#elif !defined(__APPLE__)
+.comm _ZN14__interception11real_setjmpE,8,8
+#endif
+#if defined(__NetBSD__)
+.globl ASM_SYMBOL_INTERCEPTOR(__setjmp14)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__setjmp14))
+ASM_SYMBOL_INTERCEPTOR(__setjmp14):
+#else
+.globl ASM_SYMBOL_INTERCEPTOR(setjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(setjmp))
+ASM_SYMBOL_INTERCEPTOR(setjmp):
+#endif
+ CFI_STARTPROC
+ _CET_ENDBR
+ // save env parameter
+ push %rdi
+ CFI_ADJUST_CFA_OFFSET(8)
+ CFI_REL_OFFSET(%rdi, 0)
+ // obtain SP, store in %rdi, first argument to `void __tsan_setjmp(uptr sp)`
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+ lea 8(%rsp), %rdi
+#elif defined(__linux__) || defined(__APPLE__)
+ lea 16(%rsp), %rdi
+#else
+# error "Unknown platform"
+#endif
+ // call tsan interceptor
+ call ASM_SYMBOL(__tsan_setjmp)
+ // restore env parameter
+ pop %rdi
+ CFI_ADJUST_CFA_OFFSET(-8)
+ CFI_RESTORE(%rdi)
+ // tail jump to libc setjmp
+ movl $0, %eax
+#if defined(__NetBSD__)
+ movq _ZN14__interception15real___setjmp14E@GOTPCREL(%rip), %rdx
+ jmp *(%rdx)
+#elif !defined(__APPLE__)
+ movq _ZN14__interception11real_setjmpE@GOTPCREL(%rip), %rdx
+ jmp *(%rdx)
+#else
+ jmp ASM_SYMBOL(setjmp)
+#endif
+ CFI_ENDPROC
+#if defined(__NetBSD__)
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__setjmp14))
+#else
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(setjmp))
+#endif
+
+.comm _ZN14__interception12real__setjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(_setjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(_setjmp))
+ASM_SYMBOL_INTERCEPTOR(_setjmp):
+ CFI_STARTPROC
+ _CET_ENDBR
+ // save env parameter
+ push %rdi
+ CFI_ADJUST_CFA_OFFSET(8)
+ CFI_REL_OFFSET(%rdi, 0)
+ // obtain SP, store in %rdi, first argument to `void __tsan_setjmp(uptr sp)`
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+ lea 8(%rsp), %rdi
+#elif defined(__linux__) || defined(__APPLE__)
+ lea 16(%rsp), %rdi
+#else
+# error "Unknown platform"
+#endif
+ // call tsan interceptor
+ call ASM_SYMBOL(__tsan_setjmp)
+ // restore env parameter
+ pop %rdi
+ CFI_ADJUST_CFA_OFFSET(-8)
+ CFI_RESTORE(%rdi)
+ // tail jump to libc setjmp
+ movl $0, %eax
+#if !defined(__APPLE__)
+ movq _ZN14__interception12real__setjmpE@GOTPCREL(%rip), %rdx
+ jmp *(%rdx)
+#else
+ jmp ASM_SYMBOL(_setjmp)
+#endif
+ CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(_setjmp))
+
+#if defined(__NetBSD__)
+.comm _ZN14__interception18real___sigsetjmp14E,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(__sigsetjmp14)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp14))
+ASM_SYMBOL_INTERCEPTOR(__sigsetjmp14):
+#else
+.comm _ZN14__interception14real_sigsetjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(sigsetjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
+ASM_SYMBOL_INTERCEPTOR(sigsetjmp):
+#endif
+ CFI_STARTPROC
+ _CET_ENDBR
+ // save env parameter
+ push %rdi
+ CFI_ADJUST_CFA_OFFSET(8)
+ CFI_REL_OFFSET(%rdi, 0)
+ // save savesigs parameter
+ push %rsi
+ CFI_ADJUST_CFA_OFFSET(8)
+ CFI_REL_OFFSET(%rsi, 0)
+ // align stack frame
+ sub $8, %rsp
+ CFI_ADJUST_CFA_OFFSET(8)
+ // obtain SP, store in %rdi, first argument to `void __tsan_setjmp(uptr sp)`
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+ lea 24(%rsp), %rdi
+#elif defined(__linux__) || defined(__APPLE__)
+ lea 32(%rsp), %rdi
+#else
+# error "Unknown platform"
+#endif
+ // call tsan interceptor
+ call ASM_SYMBOL(__tsan_setjmp)
+ // unalign stack frame
+ add $8, %rsp
+ CFI_ADJUST_CFA_OFFSET(-8)
+ // restore savesigs parameter
+ pop %rsi
+ CFI_ADJUST_CFA_OFFSET(-8)
+ CFI_RESTORE(%rsi)
+ // restore env parameter
+ pop %rdi
+ CFI_ADJUST_CFA_OFFSET(-8)
+ CFI_RESTORE(%rdi)
+ // tail jump to libc sigsetjmp
+ movl $0, %eax
+#if defined(__NetBSD__)
+ movq _ZN14__interception18real___sigsetjmp14E@GOTPCREL(%rip), %rdx
+ jmp *(%rdx)
+#elif !defined(__APPLE__)
+ movq _ZN14__interception14real_sigsetjmpE@GOTPCREL(%rip), %rdx
+ jmp *(%rdx)
+#else
+ jmp ASM_SYMBOL(sigsetjmp)
+#endif
+ CFI_ENDPROC
+#if defined(__NetBSD__)
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp14))
+#else
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
+#endif
+
+#if !defined(__APPLE__) && !defined(__NetBSD__)
+.comm _ZN14__interception16real___sigsetjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(__sigsetjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
+ASM_SYMBOL_INTERCEPTOR(__sigsetjmp):
+ CFI_STARTPROC
+ _CET_ENDBR
+ // save env parameter
+ push %rdi
+ CFI_ADJUST_CFA_OFFSET(8)
+ CFI_REL_OFFSET(%rdi, 0)
+ // save savesigs parameter
+ push %rsi
+ CFI_ADJUST_CFA_OFFSET(8)
+ CFI_REL_OFFSET(%rsi, 0)
+ // align stack frame
+ sub $8, %rsp
+ CFI_ADJUST_CFA_OFFSET(8)
+ // obtain SP, store in %rdi, first argument to `void __tsan_setjmp(uptr sp)`
+#if defined(__FreeBSD__)
+ lea 24(%rsp), %rdi
+#else
+ lea 32(%rsp), %rdi
+#endif
+ // call tsan interceptor
+ call ASM_SYMBOL(__tsan_setjmp)
+ // unalign stack frame
+ add $8, %rsp
+ CFI_ADJUST_CFA_OFFSET(-8)
+ // restore savesigs parameter
+ pop %rsi
+ CFI_ADJUST_CFA_OFFSET(-8)
+ CFI_RESTORE(%rsi)
+ // restore env parameter
+ pop %rdi
+ CFI_ADJUST_CFA_OFFSET(-8)
+ CFI_RESTORE(%rdi)
+ // tail jump to libc sigsetjmp
+ movl $0, %eax
+ movq _ZN14__interception16real___sigsetjmpE@GOTPCREL(%rip), %rdx
+ jmp *(%rdx)
+ CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
+#endif // !defined(__APPLE__) && !defined(__NetBSD__)
+
+NO_EXEC_STACK_DIRECTIVE
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_loongarch64.S b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_loongarch64.S
new file mode 100644
index 00000000000..12856bd110c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_loongarch64.S
@@ -0,0 +1,196 @@
+#include "sanitizer_common/sanitizer_asm.h"
+
+.section .text
+
+ASM_HIDDEN(__tsan_setjmp)
+.comm _ZN14__interception11real_setjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(setjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(setjmp))
+ASM_SYMBOL_INTERCEPTOR(setjmp):
+ CFI_STARTPROC
+
+ // Save frame pointer and return address register
+ addi.d $sp, $sp, -32
+ st.d $ra, $sp, 24
+ st.d $fp, $sp, 16
+ CFI_DEF_CFA_OFFSET (32)
+ CFI_OFFSET (1, -8)
+ CFI_OFFSET (22, -16)
+
+ // Adjust the SP for previous frame
+ addi.d $fp, $sp, 32
+ CFI_DEF_CFA_REGISTER (22)
+
+ // Save env parameter
+ st.d $a0, $sp, 8
+ CFI_OFFSET (4, -24)
+
+ // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
+ addi.d $a0, $fp, 0
+
+ // call tsan interceptor
+ bl ASM_SYMBOL(__tsan_setjmp)
+
+ // Restore env parameter
+ ld.d $a0, $sp, 8
+ CFI_RESTORE (4)
+
+ // Restore frame/link register
+ ld.d $fp, $sp, 16
+ ld.d $ra, $sp, 24
+ addi.d $sp, $sp, 32
+ CFI_RESTORE (22)
+ CFI_RESTORE (1)
+ CFI_DEF_CFA (3, 0)
+
+ // tail jump to libc setjmp
+ la.local $a1, _ZN14__interception11real_setjmpE
+ ld.d $a1, $a1, 0
+ jr $a1
+
+ CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(setjmp))
+
+.comm _ZN14__interception12real__setjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(_setjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(_setjmp))
+ASM_SYMBOL_INTERCEPTOR(_setjmp):
+ CFI_STARTPROC
+
+ // Save frame pointer and return address register
+ addi.d $sp, $sp, -32
+ st.d $ra, $sp, 24
+ st.d $fp, $sp, 16
+ CFI_DEF_CFA_OFFSET (32)
+ CFI_OFFSET (1, -8)
+ CFI_OFFSET (22, -16)
+
+ // Adjust the SP for previous frame
+ addi.d $fp, $sp, 32
+ CFI_DEF_CFA_REGISTER (22)
+
+ // Save env parameter
+ st.d $a0, $sp, 8
+ CFI_OFFSET (4, -24)
+
+ // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
+ addi.d $a0, $fp, 0
+
+ // call tsan interceptor
+ bl ASM_SYMBOL(__tsan_setjmp)
+
+ // Restore env parameter
+ ld.d $a0, $sp, 8
+ CFI_RESTORE (4)
+
+ // Restore frame/link register
+ ld.d $fp, $sp, 16
+ ld.d $ra, $sp, 24
+ addi.d $sp, $sp, 32
+ CFI_RESTORE (22)
+ CFI_RESTORE (1)
+ CFI_DEF_CFA (3, 0)
+
+ // tail jump to libc setjmp
+ la.local $a1, _ZN14__interception12real__setjmpE
+ ld.d $a1, $a1, 0
+ jr $a1
+
+ CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(_setjmp))
+
+.comm _ZN14__interception14real_sigsetjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(sigsetjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
+ASM_SYMBOL_INTERCEPTOR(sigsetjmp):
+ CFI_STARTPROC
+
+ // Save frame pointer and return address register
+ addi.d $sp, $sp, -32
+ st.d $ra, $sp, 24
+ st.d $fp, $sp, 16
+ CFI_DEF_CFA_OFFSET (32)
+ CFI_OFFSET (1, -8)
+ CFI_OFFSET (22, -16)
+
+ // Adjust the SP for previous frame
+ addi.d $fp, $sp, 32
+ CFI_DEF_CFA_REGISTER (22)
+
+ // Save env parameter
+ st.d $a0, $sp, 8
+ CFI_OFFSET (4, -24)
+
+ // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
+ addi.d $a0, $fp, 0
+
+ // call tsan interceptor
+ bl ASM_SYMBOL(__tsan_setjmp)
+
+ // Restore env parameter
+ ld.d $a0, $sp, 8
+ CFI_RESTORE (4)
+
+ // Restore frame/link register
+ ld.d $fp, $sp, 16
+ ld.d $ra, $sp, 24
+ addi.d $sp, $sp, 32
+ CFI_RESTORE (22)
+ CFI_RESTORE (1)
+ CFI_DEF_CFA (3, 0)
+
+ // tail jump to libc setjmp
+ la.local $a1, _ZN14__interception14real_sigsetjmpE
+ ld.d $a1, $a1, 0
+ jr $a1
+
+ CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
+
+.comm _ZN14__interception16real___sigsetjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(__sigsetjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
+ASM_SYMBOL_INTERCEPTOR(__sigsetjmp):
+ CFI_STARTPROC
+
+ // Save frame pointer and return address register
+ addi.d $sp, $sp, -32
+ st.d $ra, $sp, 24
+ st.d $fp, $sp, 16
+ CFI_DEF_CFA_OFFSET (32)
+ CFI_OFFSET (1, -8)
+ CFI_OFFSET (22, -16)
+
+ // Adjust the SP for previous frame
+ addi.d $fp, $sp, 32
+ CFI_DEF_CFA_REGISTER (22)
+
+ // Save env parameter
+ st.d $a0, $sp, 8
+ CFI_OFFSET (4, -24)
+
+ // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
+ addi.d $a0, $fp, 0
+
+ // call tsan interceptor
+ bl ASM_SYMBOL(__tsan_setjmp)
+
+ // Restore env parameter
+ ld.d $a0, $sp, 8
+ CFI_RESTORE (4)
+
+ // Restore frame/link register
+ ld.d $fp, $sp, 16
+ ld.d $ra, $sp, 24
+ addi.d $sp, $sp, 32
+ CFI_RESTORE (22)
+ CFI_RESTORE (1)
+ CFI_DEF_CFA (3, 0)
+
+ // tail jump to libc setjmp
+ la.local $a1, _ZN14__interception16real___sigsetjmpE
+ ld.d $a1, $a1, 0
+ jr $a1
+
+ CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_mips64.S b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_mips64.S
new file mode 100644
index 00000000000..d0f7a3f9af9
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_mips64.S
@@ -0,0 +1,214 @@
+.section .text
+.set noreorder
+
+.hidden __tsan_setjmp
+.comm _ZN14__interception11real_setjmpE,8,8
+.globl setjmp
+.type setjmp, @function
+setjmp:
+
+ // save env parameters
+ daddiu $sp,$sp,-40
+ sd $s0,32($sp)
+ sd $ra,24($sp)
+ sd $fp,16($sp)
+ sd $gp,8($sp)
+
+ // calculate and save pointer to GOT
+ lui $gp,%hi(%neg(%gp_rel(setjmp)))
+ daddu $gp,$gp,$t9
+ daddiu $gp,$gp,%lo(%neg(%gp_rel(setjmp)))
+ move $s0,$gp
+
+ // save jmp_buf
+ sd $a0,0($sp)
+
+ // obtain $sp
+ dadd $a0,$zero,$sp
+
+ // call tsan interceptor
+ jal __tsan_setjmp
+ daddiu $a1,$a0,40
+
+ // restore jmp_buf
+ ld $a0,0($sp)
+
+ // restore gp
+ move $gp,$s0
+
+ // load pointer of libc setjmp to t9
+ dla $t9,(_ZN14__interception11real_setjmpE)
+
+ // restore env parameters
+ ld $gp,8($sp)
+ ld $fp,16($sp)
+ ld $ra,24($sp)
+ ld $s0,32($sp)
+ daddiu $sp,$sp,40
+
+ // tail jump to libc setjmp
+ ld $t9,0($t9)
+ jr $t9
+ nop
+
+.size setjmp, .-setjmp
+
+.hidden __tsan_setjmp
+.globl _setjmp
+.comm _ZN14__interception12real__setjmpE,8,8
+.type _setjmp, @function
+_setjmp:
+
+ // Save env parameters
+ daddiu $sp,$sp,-40
+ sd $s0,32($sp)
+ sd $ra,24($sp)
+ sd $fp,16($sp)
+ sd $gp,8($sp)
+
+ // calculate and save pointer to GOT
+ lui $gp,%hi(%neg(%gp_rel(_setjmp)))
+ daddu $gp,$gp,$t9
+ daddiu $gp,$gp,%lo(%neg(%gp_rel(_setjmp)))
+ move $s0,$gp
+
+ // save jmp_buf
+ sd $a0,0($sp)
+
+ // obtain $sp
+ dadd $a0,$zero,$sp
+
+ // call tsan interceptor
+ jal __tsan_setjmp
+ daddiu $a1,$a0,40
+
+ // restore jmp_buf
+ ld $a0,0($sp)
+
+ // restore gp
+ move $gp,$s0
+
+ // load pointer of libc _setjmp to t9
+ dla $t9,(_ZN14__interception12real__setjmpE)
+
+ // restore env parameters
+ ld $gp,8($sp)
+ ld $fp,16($sp)
+ ld $ra,24($sp)
+ ld $s0,32($sp)
+ daddiu $sp,$sp,40
+
+ // tail jump to libc _setjmp
+ ld $t9,0($t9)
+ jr $t9
+ nop
+
+.size _setjmp, .-_setjmp
+
+.hidden __tsan_setjmp
+.globl sigsetjmp
+.comm _ZN14__interception14real_sigsetjmpE,8,8
+.type sigsetjmp, @function
+sigsetjmp:
+
+ // Save env parameters
+ daddiu $sp,$sp,-48
+ sd $s0,40($sp)
+ sd $ra,32($sp)
+ sd $fp,24($sp)
+ sd $gp,16($sp)
+
+ // calculate and save pointer to GOT
+ lui $gp,%hi(%neg(%gp_rel(sigsetjmp)))
+ daddu $gp,$gp,$t9
+ daddiu $gp,$gp,%lo(%neg(%gp_rel(sigsetjmp)))
+ move $s0,$gp
+
+ // save jmp_buf and savesig
+ sd $a0,0($sp)
+ sd $a1,8($sp)
+
+ // obtain $sp
+ dadd $a0,$zero,$sp
+
+ // call tsan interceptor
+ jal __tsan_setjmp
+ daddiu $a1,$a0,48
+
+ // restore jmp_buf and savesig
+ ld $a0,0($sp)
+ ld $a1,8($sp)
+
+ // restore gp
+ move $gp,$s0
+
+ // load pointer of libc sigsetjmp to t9
+ dla $t9,(_ZN14__interception14real_sigsetjmpE)
+
+ // restore env parameters
+ ld $gp,16($sp)
+ ld $fp,24($sp)
+ ld $ra,32($sp)
+ ld $s0,40($sp)
+ daddiu $sp,$sp,48
+
+ // tail jump to libc sigsetjmp
+ ld $t9,0($t9)
+ jr $t9
+ nop
+
+.size sigsetjmp, .-sigsetjmp
+
+.hidden __tsan_setjmp
+.comm _ZN14__interception16real___sigsetjmpE,8,8
+.globl __sigsetjmp
+.type __sigsetjmp, @function
+__sigsetjmp:
+
+ // Save env parameters
+ daddiu $sp,$sp,-48
+ sd $s0,40($sp)
+ sd $ra,32($sp)
+ sd $fp,24($sp)
+ sd $gp,16($sp)
+
+ // calculate and save pointer to GOT
+ lui $gp,%hi(%neg(%gp_rel(__sigsetjmp)))
+ daddu $gp,$gp,$t9
+ daddiu $gp,$gp,%lo(%neg(%gp_rel(__sigsetjmp)))
+ move $s0,$gp
+
+ // save jmp_buf and savesig
+ sd $a0,0($sp)
+ sd $a1,8($sp)
+
+ // obtain $sp
+ dadd $a0,$zero,$sp
+
+ // call tsan interceptor
+ jal __tsan_setjmp
+ daddiu $a1,$a0,48
+
+ // restore jmp_buf and savesig
+ ld $a0,0($sp)
+ ld $a1,8($sp)
+
+ // restore gp
+ move $gp,$s0
+
+ // load pointer to libc __sigsetjmp in t9
+ dla $t9,(_ZN14__interception16real___sigsetjmpE)
+
+ // restore env parameters
+ ld $gp,16($sp)
+ ld $fp,24($sp)
+ ld $ra,32($sp)
+ ld $s0,40($sp)
+ daddiu $sp,$sp,48
+
+ // tail jump to libc __sigsetjmp
+ ld $t9,0($t9)
+ jr $t9
+ nop
+
+.size __sigsetjmp, .-__sigsetjmp
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
new file mode 100644
index 00000000000..2e978852ea7
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
@@ -0,0 +1,578 @@
+//===-- tsan_rtl_mutex.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#include <sanitizer_common/sanitizer_deadlock_detector_interface.h>
+#include <sanitizer_common/sanitizer_stackdepot.h>
+
+#include "tsan_rtl.h"
+#include "tsan_flags.h"
+#include "tsan_sync.h"
+#include "tsan_report.h"
+#include "tsan_symbolize.h"
+#include "tsan_platform.h"
+
+namespace __tsan {
+
+void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r);
+void ReportDestroyLocked(ThreadState *thr, uptr pc, uptr addr,
+ FastState last_lock, StackID creation_stack_id);
+
+struct Callback final : public DDCallback {
+ ThreadState *thr;
+ uptr pc;
+
+ Callback(ThreadState *thr, uptr pc)
+ : thr(thr)
+ , pc(pc) {
+ DDCallback::pt = thr->proc()->dd_pt;
+ DDCallback::lt = thr->dd_lt;
+ }
+
+ StackID Unwind() override { return CurrentStackId(thr, pc); }
+ int UniqueTid() override { return thr->tid; }
+};
+
+void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexInit(&cb, &s->dd);
+ s->dd.ctx = s->addr;
+}
+
+static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ,
+ uptr addr, StackID creation_stack_id) {
+ // In Go, these misuses are either impossible, or detected by std lib,
+ // or false positives (e.g. unlock in a different thread).
+ if (SANITIZER_GO)
+ return;
+ if (!ShouldReport(thr, typ))
+ return;
+ ThreadRegistryLock l(&ctx->thread_registry);
+ ScopedReport rep(typ);
+ rep.AddMutex(addr, creation_stack_id);
+ VarSizeStackTrace trace;
+ ObtainCurrentStack(thr, pc, &trace);
+ rep.AddStack(trace, true);
+ rep.AddLocation(addr, 1);
+ OutputReport(thr, rep);
+}
+
+static void RecordMutexLock(ThreadState *thr, uptr pc, uptr addr,
+ StackID stack_id, bool write) {
+ auto typ = write ? EventType::kLock : EventType::kRLock;
+ // Note: it's important to trace before modifying mutex set
+ // because tracing can switch trace part and we write the current
+ // mutex set in the beginning of each part.
+ // If we do it in the opposite order, we will write already reduced
+ // mutex set in the beginning of the part and then trace unlock again.
+ TraceMutexLock(thr, typ, pc, addr, stack_id);
+ thr->mset.AddAddr(addr, stack_id, write);
+}
+
+static void RecordMutexUnlock(ThreadState *thr, uptr addr) {
+ // See the comment in RecordMutexLock re order of operations.
+ TraceMutexUnlock(thr, addr);
+ thr->mset.DelAddr(addr);
+}
+
+void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
+ DPrintf("#%d: MutexCreate %zx flagz=0x%x\n", thr->tid, addr, flagz);
+ if (!(flagz & MutexFlagLinkerInit) && pc && IsAppMem(addr))
+ MemoryAccess(thr, pc, addr, 1, kAccessWrite);
+ SlotLocker locker(thr);
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ s->SetFlags(flagz & MutexCreationFlagMask);
+ // Save stack in the case the sync object was created before as atomic.
+ if (!SANITIZER_GO && s->creation_stack_id == kInvalidStackID)
+ s->creation_stack_id = CurrentStackId(thr, pc);
+}
+
+void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
+ DPrintf("#%d: MutexDestroy %zx\n", thr->tid, addr);
+ bool unlock_locked = false;
+ StackID creation_stack_id;
+ FastState last_lock;
+ {
+ auto s = ctx->metamap.GetSyncIfExists(addr);
+ if (!s)
+ return;
+ SlotLocker locker(thr);
+ {
+ Lock lock(&s->mtx);
+ creation_stack_id = s->creation_stack_id;
+ last_lock = s->last_lock;
+ if ((flagz & MutexFlagLinkerInit) || s->IsFlagSet(MutexFlagLinkerInit) ||
+ ((flagz & MutexFlagNotStatic) && !s->IsFlagSet(MutexFlagNotStatic))) {
+ // Destroy is no-op for linker-initialized mutexes.
+ return;
+ }
+ if (common_flags()->detect_deadlocks) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexDestroy(&cb, &s->dd);
+ ctx->dd->MutexInit(&cb, &s->dd);
+ }
+ if (flags()->report_destroy_locked && s->owner_tid != kInvalidTid &&
+ !s->IsFlagSet(MutexFlagBroken)) {
+ s->SetFlags(MutexFlagBroken);
+ unlock_locked = true;
+ }
+ s->Reset();
+ }
+ // Imitate a memory write to catch unlock-destroy races.
+ if (pc && IsAppMem(addr))
+ MemoryAccess(thr, pc, addr, 1,
+ kAccessWrite | kAccessFree | kAccessSlotLocked);
+ }
+ if (unlock_locked && ShouldReport(thr, ReportTypeMutexDestroyLocked))
+ ReportDestroyLocked(thr, pc, addr, last_lock, creation_stack_id);
+ thr->mset.DelAddr(addr, true);
+ // s will be destroyed and freed in MetaMap::FreeBlock.
+}
+
+void MutexPreLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
+ DPrintf("#%d: MutexPreLock %zx flagz=0x%x\n", thr->tid, addr, flagz);
+ if (flagz & MutexFlagTryLock)
+ return;
+ if (!common_flags()->detect_deadlocks)
+ return;
+ Callback cb(thr, pc);
+ {
+ SlotLocker locker(thr);
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ ReadLock lock(&s->mtx);
+ s->UpdateFlags(flagz);
+ if (s->owner_tid != thr->tid)
+ ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
+ }
+ ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
+}
+
+void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz, int rec) {
+ DPrintf("#%d: MutexPostLock %zx flag=0x%x rec=%d\n",
+ thr->tid, addr, flagz, rec);
+ if (flagz & MutexFlagRecursiveLock)
+ CHECK_GT(rec, 0);
+ else
+ rec = 1;
+ if (pc && IsAppMem(addr))
+ MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
+ bool report_double_lock = false;
+ bool pre_lock = false;
+ bool first = false;
+ StackID creation_stack_id = kInvalidStackID;
+ {
+ SlotLocker locker(thr);
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ creation_stack_id = s->creation_stack_id;
+ RecordMutexLock(thr, pc, addr, creation_stack_id, true);
+ {
+ Lock lock(&s->mtx);
+ first = s->recursion == 0;
+ s->UpdateFlags(flagz);
+ if (s->owner_tid == kInvalidTid) {
+ CHECK_EQ(s->recursion, 0);
+ s->owner_tid = thr->tid;
+ s->last_lock = thr->fast_state;
+ } else if (s->owner_tid == thr->tid) {
+ CHECK_GT(s->recursion, 0);
+ } else if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
+ s->SetFlags(MutexFlagBroken);
+ report_double_lock = true;
+ }
+ s->recursion += rec;
+ if (first) {
+ if (!thr->ignore_sync) {
+ thr->clock.Acquire(s->clock);
+ thr->clock.Acquire(s->read_clock);
+ }
+ }
+ if (first && common_flags()->detect_deadlocks) {
+ pre_lock = (flagz & MutexFlagDoPreLockOnPostLock) &&
+ !(flagz & MutexFlagTryLock);
+ Callback cb(thr, pc);
+ if (pre_lock)
+ ctx->dd->MutexBeforeLock(&cb, &s->dd, true);
+ ctx->dd->MutexAfterLock(&cb, &s->dd, true, flagz & MutexFlagTryLock);
+ }
+ }
+ }
+ if (report_double_lock)
+ ReportMutexMisuse(thr, pc, ReportTypeMutexDoubleLock, addr,
+ creation_stack_id);
+ if (first && pre_lock && common_flags()->detect_deadlocks) {
+ Callback cb(thr, pc);
+ ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
+ }
+}
+
+int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
+ DPrintf("#%d: MutexUnlock %zx flagz=0x%x\n", thr->tid, addr, flagz);
+ if (pc && IsAppMem(addr))
+ MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
+ StackID creation_stack_id;
+ RecordMutexUnlock(thr, addr);
+ bool report_bad_unlock = false;
+ int rec = 0;
+ {
+ SlotLocker locker(thr);
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ bool released = false;
+ {
+ Lock lock(&s->mtx);
+ creation_stack_id = s->creation_stack_id;
+ if (!SANITIZER_GO && (s->recursion == 0 || s->owner_tid != thr->tid)) {
+ if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
+ s->SetFlags(MutexFlagBroken);
+ report_bad_unlock = true;
+ }
+ } else {
+ rec = (flagz & MutexFlagRecursiveUnlock) ? s->recursion : 1;
+ s->recursion -= rec;
+ if (s->recursion == 0) {
+ s->owner_tid = kInvalidTid;
+ if (!thr->ignore_sync) {
+ thr->clock.ReleaseStore(&s->clock);
+ released = true;
+ }
+ }
+ }
+ if (common_flags()->detect_deadlocks && s->recursion == 0 &&
+ !report_bad_unlock) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexBeforeUnlock(&cb, &s->dd, true);
+ }
+ }
+ if (released)
+ IncrementEpoch(thr);
+ }
+ if (report_bad_unlock)
+ ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr,
+ creation_stack_id);
+ if (common_flags()->detect_deadlocks && !report_bad_unlock) {
+ Callback cb(thr, pc);
+ ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
+ }
+ return rec;
+}
+
+void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
+ DPrintf("#%d: MutexPreReadLock %zx flagz=0x%x\n", thr->tid, addr, flagz);
+ if ((flagz & MutexFlagTryLock) || !common_flags()->detect_deadlocks)
+ return;
+ Callback cb(thr, pc);
+ {
+ SlotLocker locker(thr);
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ ReadLock lock(&s->mtx);
+ s->UpdateFlags(flagz);
+ ctx->dd->MutexBeforeLock(&cb, &s->dd, false);
+ }
+ ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
+}
+
+void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz) {
+ DPrintf("#%d: MutexPostReadLock %zx flagz=0x%x\n", thr->tid, addr, flagz);
+ if (pc && IsAppMem(addr))
+ MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
+ bool report_bad_lock = false;
+ bool pre_lock = false;
+ StackID creation_stack_id = kInvalidStackID;
+ {
+ SlotLocker locker(thr);
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ creation_stack_id = s->creation_stack_id;
+ RecordMutexLock(thr, pc, addr, creation_stack_id, false);
+ {
+ ReadLock lock(&s->mtx);
+ s->UpdateFlags(flagz);
+ if (s->owner_tid != kInvalidTid) {
+ if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
+ s->SetFlags(MutexFlagBroken);
+ report_bad_lock = true;
+ }
+ }
+ if (!thr->ignore_sync)
+ thr->clock.Acquire(s->clock);
+ s->last_lock = thr->fast_state;
+ if (common_flags()->detect_deadlocks) {
+ pre_lock = (flagz & MutexFlagDoPreLockOnPostLock) &&
+ !(flagz & MutexFlagTryLock);
+ Callback cb(thr, pc);
+ if (pre_lock)
+ ctx->dd->MutexBeforeLock(&cb, &s->dd, false);
+ ctx->dd->MutexAfterLock(&cb, &s->dd, false, flagz & MutexFlagTryLock);
+ }
+ }
+ }
+ if (report_bad_lock)
+ ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadLock, addr,
+ creation_stack_id);
+ if (pre_lock && common_flags()->detect_deadlocks) {
+ Callback cb(thr, pc);
+ ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
+ }
+}
+
+void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
+ DPrintf("#%d: MutexReadUnlock %zx\n", thr->tid, addr);
+ if (pc && IsAppMem(addr))
+ MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
+ RecordMutexUnlock(thr, addr);
+ StackID creation_stack_id;
+ bool report_bad_unlock = false;
+ {
+ SlotLocker locker(thr);
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ bool released = false;
+ {
+ Lock lock(&s->mtx);
+ creation_stack_id = s->creation_stack_id;
+ if (s->owner_tid != kInvalidTid) {
+ if (flags()->report_mutex_bugs && !s->IsFlagSet(MutexFlagBroken)) {
+ s->SetFlags(MutexFlagBroken);
+ report_bad_unlock = true;
+ }
+ }
+ if (!thr->ignore_sync) {
+ thr->clock.Release(&s->read_clock);
+ released = true;
+ }
+ if (common_flags()->detect_deadlocks && s->recursion == 0) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexBeforeUnlock(&cb, &s->dd, false);
+ }
+ }
+ if (released)
+ IncrementEpoch(thr);
+ }
+ if (report_bad_unlock)
+ ReportMutexMisuse(thr, pc, ReportTypeMutexBadReadUnlock, addr,
+ creation_stack_id);
+ if (common_flags()->detect_deadlocks) {
+ Callback cb(thr, pc);
+ ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
+ }
+}
+
+void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
+ DPrintf("#%d: MutexReadOrWriteUnlock %zx\n", thr->tid, addr);
+ if (pc && IsAppMem(addr))
+ MemoryAccess(thr, pc, addr, 1, kAccessRead | kAccessAtomic);
+ RecordMutexUnlock(thr, addr);
+ StackID creation_stack_id;
+ bool report_bad_unlock = false;
+ bool write = true;
+ {
+ SlotLocker locker(thr);
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ bool released = false;
+ {
+ Lock lock(&s->mtx);
+ creation_stack_id = s->creation_stack_id;
+ if (s->owner_tid == kInvalidTid) {
+ // Seems to be read unlock.
+ write = false;
+ if (!thr->ignore_sync) {
+ thr->clock.Release(&s->read_clock);
+ released = true;
+ }
+ } else if (s->owner_tid == thr->tid) {
+ // Seems to be write unlock.
+ CHECK_GT(s->recursion, 0);
+ s->recursion--;
+ if (s->recursion == 0) {
+ s->owner_tid = kInvalidTid;
+ if (!thr->ignore_sync) {
+ thr->clock.ReleaseStore(&s->clock);
+ released = true;
+ }
+ }
+ } else if (!s->IsFlagSet(MutexFlagBroken)) {
+ s->SetFlags(MutexFlagBroken);
+ report_bad_unlock = true;
+ }
+ if (common_flags()->detect_deadlocks && s->recursion == 0) {
+ Callback cb(thr, pc);
+ ctx->dd->MutexBeforeUnlock(&cb, &s->dd, write);
+ }
+ }
+ if (released)
+ IncrementEpoch(thr);
+ }
+ if (report_bad_unlock)
+ ReportMutexMisuse(thr, pc, ReportTypeMutexBadUnlock, addr,
+ creation_stack_id);
+ if (common_flags()->detect_deadlocks) {
+ Callback cb(thr, pc);
+ ReportDeadlock(thr, pc, ctx->dd->GetReport(&cb));
+ }
+}
+
+void MutexRepair(ThreadState *thr, uptr pc, uptr addr) {
+ DPrintf("#%d: MutexRepair %zx\n", thr->tid, addr);
+ SlotLocker locker(thr);
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ Lock lock(&s->mtx);
+ s->owner_tid = kInvalidTid;
+ s->recursion = 0;
+}
+
+void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr) {
+ DPrintf("#%d: MutexInvalidAccess %zx\n", thr->tid, addr);
+ StackID creation_stack_id = kInvalidStackID;
+ {
+ SlotLocker locker(thr);
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, true);
+ if (s)
+ creation_stack_id = s->creation_stack_id;
+ }
+ ReportMutexMisuse(thr, pc, ReportTypeMutexInvalidAccess, addr,
+ creation_stack_id);
+}
+
+void Acquire(ThreadState *thr, uptr pc, uptr addr) {
+ DPrintf("#%d: Acquire %zx\n", thr->tid, addr);
+ if (thr->ignore_sync)
+ return;
+ auto s = ctx->metamap.GetSyncIfExists(addr);
+ if (!s)
+ return;
+ SlotLocker locker(thr);
+ if (!s->clock)
+ return;
+ ReadLock lock(&s->mtx);
+ thr->clock.Acquire(s->clock);
+}
+
+void AcquireGlobal(ThreadState *thr) {
+ DPrintf("#%d: AcquireGlobal\n", thr->tid);
+ if (thr->ignore_sync)
+ return;
+ SlotLocker locker(thr);
+ for (auto &slot : ctx->slots) thr->clock.Set(slot.sid, slot.epoch());
+}
+
+void Release(ThreadState *thr, uptr pc, uptr addr) {
+ DPrintf("#%d: Release %zx\n", thr->tid, addr);
+ if (thr->ignore_sync)
+ return;
+ SlotLocker locker(thr);
+ {
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, false);
+ Lock lock(&s->mtx);
+ thr->clock.Release(&s->clock);
+ }
+ IncrementEpoch(thr);
+}
+
+void ReleaseStore(ThreadState *thr, uptr pc, uptr addr) {
+ DPrintf("#%d: ReleaseStore %zx\n", thr->tid, addr);
+ if (thr->ignore_sync)
+ return;
+ SlotLocker locker(thr);
+ {
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, false);
+ Lock lock(&s->mtx);
+ thr->clock.ReleaseStore(&s->clock);
+ }
+ IncrementEpoch(thr);
+}
+
+void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr) {
+ DPrintf("#%d: ReleaseStoreAcquire %zx\n", thr->tid, addr);
+ if (thr->ignore_sync)
+ return;
+ SlotLocker locker(thr);
+ {
+ auto s = ctx->metamap.GetSyncOrCreate(thr, pc, addr, false);
+ Lock lock(&s->mtx);
+ thr->clock.ReleaseStoreAcquire(&s->clock);
+ }
+ IncrementEpoch(thr);
+}
+
+void IncrementEpoch(ThreadState *thr) {
+ DCHECK(!thr->ignore_sync);
+ DCHECK(thr->slot_locked);
+ Epoch epoch = EpochInc(thr->fast_state.epoch());
+ if (!EpochOverflow(epoch)) {
+ Sid sid = thr->fast_state.sid();
+ thr->clock.Set(sid, epoch);
+ thr->fast_state.SetEpoch(epoch);
+ thr->slot->SetEpoch(epoch);
+ TraceTime(thr);
+ }
+}
+
+#if !SANITIZER_GO
+void AfterSleep(ThreadState *thr, uptr pc) {
+ DPrintf("#%d: AfterSleep\n", thr->tid);
+ if (thr->ignore_sync)
+ return;
+ thr->last_sleep_stack_id = CurrentStackId(thr, pc);
+ thr->last_sleep_clock.Reset();
+ SlotLocker locker(thr);
+ for (auto &slot : ctx->slots)
+ thr->last_sleep_clock.Set(slot.sid, slot.epoch());
+}
+#endif
+
+void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
+ if (r == 0 || !ShouldReport(thr, ReportTypeDeadlock))
+ return;
+ ThreadRegistryLock l(&ctx->thread_registry);
+ ScopedReport rep(ReportTypeDeadlock);
+ for (int i = 0; i < r->n; i++) {
+ rep.AddMutex(r->loop[i].mtx_ctx0, r->loop[i].stk[0]);
+ rep.AddUniqueTid((int)r->loop[i].thr_ctx);
+ rep.AddThread((int)r->loop[i].thr_ctx);
+ }
+ uptr dummy_pc = 0x42;
+ for (int i = 0; i < r->n; i++) {
+ for (int j = 0; j < (flags()->second_deadlock_stack ? 2 : 1); j++) {
+ u32 stk = r->loop[i].stk[j];
+ if (stk && stk != kInvalidStackID) {
+ rep.AddStack(StackDepotGet(stk), true);
+ } else {
+ // Sometimes we fail to extract the stack trace (FIXME: investigate),
+ // but we should still produce some stack trace in the report.
+ rep.AddStack(StackTrace(&dummy_pc, 1), true);
+ }
+ }
+ }
+ OutputReport(thr, rep);
+}
+
+void ReportDestroyLocked(ThreadState *thr, uptr pc, uptr addr,
+ FastState last_lock, StackID creation_stack_id) {
+ // We need to lock the slot during RestoreStack because it protects
+ // the slot journal.
+ Lock slot_lock(&ctx->slots[static_cast<uptr>(last_lock.sid())].mtx);
+ ThreadRegistryLock l0(&ctx->thread_registry);
+ Lock slots_lock(&ctx->slot_mtx);
+ ScopedReport rep(ReportTypeMutexDestroyLocked);
+ rep.AddMutex(addr, creation_stack_id);
+ VarSizeStackTrace trace;
+ ObtainCurrentStack(thr, pc, &trace);
+ rep.AddStack(trace, true);
+
+ Tid tid;
+ DynamicMutexSet mset;
+ uptr tag;
+ if (!RestoreStack(EventType::kLock, last_lock.sid(), last_lock.epoch(), addr,
+ 0, kAccessWrite, &tid, &trace, mset, &tag))
+ return;
+ rep.AddStack(trace, true);
+ rep.AddLocation(addr, 1);
+ OutputReport(thr, rep);
+}
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_ppc64.S b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_ppc64.S
new file mode 100644
index 00000000000..8285e21aa1e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_ppc64.S
@@ -0,0 +1,288 @@
+#include "tsan_ppc_regs.h"
+
+ .section .text
+ .hidden __tsan_setjmp
+ .globl _setjmp
+ .type _setjmp, @function
+ .align 4
+#if _CALL_ELF == 2
+_setjmp:
+#else
+ .section ".opd","aw"
+ .align 3
+_setjmp:
+ .quad .L._setjmp,.TOC.@tocbase,0
+ .previous
+#endif
+.L._setjmp:
+ mflr r0
+ stdu r1,-48(r1)
+ std r2,24(r1)
+ std r3,32(r1)
+ std r0,40(r1)
+ // r3 is the original stack pointer.
+ addi r3,r1,48
+ // r4 is the mangled stack pointer (see glibc)
+ ld r4,-28696(r13)
+ xor r4,r3,r4
+ // Materialize a TOC in case we were called from libc.
+ // For big-endian, we load the TOC from the OPD. For little-
+ // endian, we use the .TOC. symbol to find it.
+ nop
+ bcl 20,31,0f
+0:
+ mflr r2
+#if _CALL_ELF == 2
+ addis r2,r2,.TOC.-0b@ha
+ addi r2,r2,.TOC.-0b@l
+#else
+ addis r2,r2,_setjmp-0b@ha
+ addi r2,r2,_setjmp-0b@l
+ ld r2,8(r2)
+#endif
+ // Call the interceptor.
+ bl __tsan_setjmp
+ nop
+ // Restore regs needed for setjmp.
+ ld r3,32(r1)
+ ld r0,40(r1)
+ // Emulate the real setjmp function. We do this because we can't
+ // perform a sibcall: The real setjmp function trashes the TOC
+ // pointer, and with a sibcall we have no way to restore it.
+ // This way we can make sure our caller's stack pointer and
+ // link register are saved correctly in the jmpbuf.
+ ld r6,-28696(r13)
+ addi r5,r1,48 // original stack ptr of caller
+ xor r5,r6,r5
+ std r5,0(r3) // mangled stack ptr of caller
+ ld r5,24(r1)
+ std r5,8(r3) // caller's saved TOC pointer
+ xor r0,r6,r0
+ std r0,16(r3) // caller's mangled return address
+ mfcr r0
+ // Nonvolatiles.
+ std r14,24(r3)
+ stfd f14,176(r3)
+ stw r0,172(r3) // CR
+ std r15,32(r3)
+ stfd f15,184(r3)
+ std r16,40(r3)
+ stfd f16,192(r3)
+ std r17,48(r3)
+ stfd f17,200(r3)
+ std r18,56(r3)
+ stfd f18,208(r3)
+ std r19,64(r3)
+ stfd f19,216(r3)
+ std r20,72(r3)
+ stfd f20,224(r3)
+ std r21,80(r3)
+ stfd f21,232(r3)
+ std r22,88(r3)
+ stfd f22,240(r3)
+ std r23,96(r3)
+ stfd f23,248(r3)
+ std r24,104(r3)
+ stfd f24,256(r3)
+ std r25,112(r3)
+ stfd f25,264(r3)
+ std r26,120(r3)
+ stfd f26,272(r3)
+ std r27,128(r3)
+ stfd f27,280(r3)
+ std r28,136(r3)
+ stfd f28,288(r3)
+ std r29,144(r3)
+ stfd f29,296(r3)
+ std r30,152(r3)
+ stfd f30,304(r3)
+ std r31,160(r3)
+ stfd f31,312(r3)
+ addi r5,r3,320
+ mfspr r0,256
+ stw r0,168(r3) // VRSAVE
+ addi r6,r5,16
+ stvx v20,0,r5
+ addi r5,r5,32
+ stvx v21,0,r6
+ addi r6,r6,32
+ stvx v22,0,r5
+ addi r5,r5,32
+ stvx v23,0,r6
+ addi r6,r6,32
+ stvx v24,0,r5
+ addi r5,r5,32
+ stvx v25,0,r6
+ addi r6,r6,32
+ stvx v26,0,r5
+ addi r5,r5,32
+ stvx v27,0,r6
+ addi r6,r6,32
+ stvx v28,0,r5
+ addi r5,r5,32
+ stvx v29,0,r6
+ addi r6,r6,32
+ stvx v30,0,r5
+ stvx v31,0,r6
+ // Clear the "mask-saved" slot.
+ li r4,0
+ stw r4,512(r3)
+ // Restore TOC, LR, and stack and return to caller.
+ ld r2,24(r1)
+ ld r0,40(r1)
+ addi r1,r1,48
+ li r3,0 // This is the setjmp return path
+ mtlr r0
+ blr
+ .size _setjmp, .-.L._setjmp
+
+ .globl setjmp
+ .type setjmp, @function
+ .align 4
+setjmp:
+ b _setjmp
+ .size setjmp, .-setjmp
+
+ // sigsetjmp is like setjmp, except that the mask in r4 needs
+ // to be saved at offset 512 of the jump buffer.
+ .globl __sigsetjmp
+ .type __sigsetjmp, @function
+ .align 4
+#if _CALL_ELF == 2
+__sigsetjmp:
+#else
+ .section ".opd","aw"
+ .align 3
+__sigsetjmp:
+ .quad .L.__sigsetjmp,.TOC.@tocbase,0
+ .previous
+#endif
+.L.__sigsetjmp:
+ mflr r0
+ stdu r1,-64(r1)
+ std r2,24(r1)
+ std r3,32(r1)
+ std r4,40(r1)
+ std r0,48(r1)
+ // r3 is the original stack pointer.
+ addi r3,r1,64
+ // r4 is the mangled stack pointer (see glibc)
+ ld r4,-28696(r13)
+ xor r4,r3,r4
+ // Materialize a TOC in case we were called from libc.
+ // For big-endian, we load the TOC from the OPD. For little-
+ // endian, we use the .TOC. symbol to find it.
+ nop
+ bcl 20,31,1f
+1:
+ mflr r2
+#if _CALL_ELF == 2
+ addis r2,r2,.TOC.-1b@ha
+ addi r2,r2,.TOC.-1b@l
+#else
+ addis r2,r2,_setjmp-1b@ha
+ addi r2,r2,_setjmp-1b@l
+ ld r2,8(r2)
+#endif
+ // Call the interceptor.
+ bl __tsan_setjmp
+ nop
+ // Restore regs needed for __sigsetjmp.
+ ld r3,32(r1)
+ ld r4,40(r1)
+ ld r0,48(r1)
+ // Emulate the real sigsetjmp function. We do this because we can't
+ // perform a sibcall: The real sigsetjmp function trashes the TOC
+ // pointer, and with a sibcall we have no way to restore it.
+ // This way we can make sure our caller's stack pointer and
+ // link register are saved correctly in the jmpbuf.
+ ld r6,-28696(r13)
+ addi r5,r1,64 // original stack ptr of caller
+ xor r5,r6,r5
+ std r5,0(r3) // mangled stack ptr of caller
+ ld r5,24(r1)
+ std r5,8(r3) // caller's saved TOC pointer
+ xor r0,r6,r0
+ std r0,16(r3) // caller's mangled return address
+ mfcr r0
+ // Nonvolatiles.
+ std r14,24(r3)
+ stfd f14,176(r3)
+ stw r0,172(r3) // CR
+ std r15,32(r3)
+ stfd f15,184(r3)
+ std r16,40(r3)
+ stfd f16,192(r3)
+ std r17,48(r3)
+ stfd f17,200(r3)
+ std r18,56(r3)
+ stfd f18,208(r3)
+ std r19,64(r3)
+ stfd f19,216(r3)
+ std r20,72(r3)
+ stfd f20,224(r3)
+ std r21,80(r3)
+ stfd f21,232(r3)
+ std r22,88(r3)
+ stfd f22,240(r3)
+ std r23,96(r3)
+ stfd f23,248(r3)
+ std r24,104(r3)
+ stfd f24,256(r3)
+ std r25,112(r3)
+ stfd f25,264(r3)
+ std r26,120(r3)
+ stfd f26,272(r3)
+ std r27,128(r3)
+ stfd f27,280(r3)
+ std r28,136(r3)
+ stfd f28,288(r3)
+ std r29,144(r3)
+ stfd f29,296(r3)
+ std r30,152(r3)
+ stfd f30,304(r3)
+ std r31,160(r3)
+ stfd f31,312(r3)
+ addi r5,r3,320
+ mfspr r0,256
+ stw r0,168(r3) // VRSAVE
+ addi r6,r5,16
+ stvx v20,0,r5
+ addi r5,r5,32
+ stvx v21,0,r6
+ addi r6,r6,32
+ stvx v22,0,r5
+ addi r5,r5,32
+ stvx v23,0,r6
+ addi r6,r6,32
+ stvx v24,0,r5
+ addi r5,r5,32
+ stvx v25,0,r6
+ addi r6,r6,32
+ stvx v26,0,r5
+ addi r5,r5,32
+ stvx v27,0,r6
+ addi r6,r6,32
+ stvx v28,0,r5
+ addi r5,r5,32
+ stvx v29,0,r6
+ addi r6,r6,32
+ stvx v30,0,r5
+ stvx v31,0,r6
+ // Save into the "mask-saved" slot.
+ stw r4,512(r3)
+ // Restore TOC, LR, and stack and return to caller.
+ ld r2,24(r1)
+ ld r0,48(r1)
+ addi r1,r1,64
+ li r3,0 // This is the sigsetjmp return path
+ mtlr r0
+ blr
+ .size __sigsetjmp, .-.L.__sigsetjmp
+
+ .globl sigsetjmp
+ .type sigsetjmp, @function
+ .align 4
+sigsetjmp:
+ b __sigsetjmp
+ .size sigsetjmp, .-sigsetjmp
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_proc.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_proc.cpp
new file mode 100644
index 00000000000..5acc3967208
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_proc.cpp
@@ -0,0 +1,59 @@
+//===-- tsan_rtl_proc.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "tsan_rtl.h"
+#include "tsan_mman.h"
+#include "tsan_flags.h"
+
+namespace __tsan {
+
+Processor *ProcCreate() {
+ void *mem = InternalAlloc(sizeof(Processor));
+ internal_memset(mem, 0, sizeof(Processor));
+ Processor *proc = new(mem) Processor;
+ proc->thr = nullptr;
+#if !SANITIZER_GO
+ AllocatorProcStart(proc);
+#endif
+ if (common_flags()->detect_deadlocks)
+ proc->dd_pt = ctx->dd->CreatePhysicalThread();
+ return proc;
+}
+
+void ProcDestroy(Processor *proc) {
+ CHECK_EQ(proc->thr, nullptr);
+#if !SANITIZER_GO
+ AllocatorProcFinish(proc);
+#endif
+ ctx->metamap.OnProcIdle(proc);
+ if (common_flags()->detect_deadlocks)
+ ctx->dd->DestroyPhysicalThread(proc->dd_pt);
+ proc->~Processor();
+ InternalFree(proc);
+}
+
+void ProcWire(Processor *proc, ThreadState *thr) {
+ CHECK_EQ(thr->proc1, nullptr);
+ CHECK_EQ(proc->thr, nullptr);
+ thr->proc1 = proc;
+ proc->thr = thr;
+}
+
+void ProcUnwire(Processor *proc, ThreadState *thr) {
+ CHECK_EQ(thr->proc1, proc);
+ CHECK_EQ(proc->thr, thr);
+ thr->proc1 = nullptr;
+ proc->thr = nullptr;
+}
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_report.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_report.cpp
new file mode 100644
index 00000000000..c2cff60e2da
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_report.cpp
@@ -0,0 +1,862 @@
+//===-- tsan_rtl_report.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "tsan_platform.h"
+#include "tsan_rtl.h"
+#include "tsan_suppressions.h"
+#include "tsan_symbolize.h"
+#include "tsan_report.h"
+#include "tsan_sync.h"
+#include "tsan_mman.h"
+#include "tsan_flags.h"
+#include "tsan_fd.h"
+
+namespace __tsan {
+
+using namespace __sanitizer;
+
+static ReportStack *SymbolizeStack(StackTrace trace);
+
+// Can be overriden by an application/test to intercept reports.
+#ifdef TSAN_EXTERNAL_HOOKS
+bool OnReport(const ReportDesc *rep, bool suppressed);
+#else
+SANITIZER_WEAK_CXX_DEFAULT_IMPL
+bool OnReport(const ReportDesc *rep, bool suppressed) {
+ (void)rep;
+ return suppressed;
+}
+#endif
+
+SANITIZER_WEAK_DEFAULT_IMPL
+void __tsan_on_report(const ReportDesc *rep) {
+ (void)rep;
+}
+
+static void StackStripMain(SymbolizedStack *frames) {
+ SymbolizedStack *last_frame = nullptr;
+ SymbolizedStack *last_frame2 = nullptr;
+ for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
+ last_frame2 = last_frame;
+ last_frame = cur;
+ }
+
+ if (last_frame2 == 0)
+ return;
+#if !SANITIZER_GO
+ const char *last = last_frame->info.function;
+ const char *last2 = last_frame2->info.function;
+ // Strip frame above 'main'
+ if (last2 && 0 == internal_strcmp(last2, "main")) {
+ last_frame->ClearAll();
+ last_frame2->next = nullptr;
+ // Strip our internal thread start routine.
+ } else if (last && 0 == internal_strcmp(last, "__tsan_thread_start_func")) {
+ last_frame->ClearAll();
+ last_frame2->next = nullptr;
+ // Strip global ctors init, .preinit_array and main caller.
+ } else if (last && (0 == internal_strcmp(last, "__do_global_ctors_aux") ||
+ 0 == internal_strcmp(last, "__libc_csu_init") ||
+ 0 == internal_strcmp(last, "__libc_start_main"))) {
+ last_frame->ClearAll();
+ last_frame2->next = nullptr;
+ // If both are 0, then we probably just failed to symbolize.
+ } else if (last || last2) {
+ // Ensure that we recovered stack completely. Trimmed stack
+ // can actually happen if we do not instrument some code,
+ // so it's only a debug print. However we must try hard to not miss it
+ // due to our fault.
+ DPrintf("Bottom stack frame is missed\n");
+ }
+#else
+ // The last frame always point into runtime (gosched0, goexit0, runtime.main).
+ last_frame->ClearAll();
+ last_frame2->next = nullptr;
+#endif
+}
+
+ReportStack *SymbolizeStackId(u32 stack_id) {
+ if (stack_id == 0)
+ return 0;
+ StackTrace stack = StackDepotGet(stack_id);
+ if (stack.trace == nullptr)
+ return nullptr;
+ return SymbolizeStack(stack);
+}
+
+static ReportStack *SymbolizeStack(StackTrace trace) {
+ if (trace.size == 0)
+ return 0;
+ SymbolizedStack *top = nullptr;
+ for (uptr si = 0; si < trace.size; si++) {
+ const uptr pc = trace.trace[si];
+ uptr pc1 = pc;
+ // We obtain the return address, but we're interested in the previous
+ // instruction.
+ if ((pc & kExternalPCBit) == 0)
+ pc1 = StackTrace::GetPreviousInstructionPc(pc);
+ SymbolizedStack *ent = SymbolizeCode(pc1);
+ CHECK_NE(ent, 0);
+ SymbolizedStack *last = ent;
+ while (last->next) {
+ last->info.address = pc; // restore original pc for report
+ last = last->next;
+ }
+ last->info.address = pc; // restore original pc for report
+ last->next = top;
+ top = ent;
+ }
+ StackStripMain(top);
+
+ auto *stack = New<ReportStack>();
+ stack->frames = top;
+ return stack;
+}
+
+bool ShouldReport(ThreadState *thr, ReportType typ) {
+ // We set thr->suppress_reports in the fork context.
+ // Taking any locking in the fork context can lead to deadlocks.
+ // If any locks are already taken, it's too late to do this check.
+ CheckedMutex::CheckNoLocks();
+ // For the same reason check we didn't lock thread_registry yet.
+ if (SANITIZER_DEBUG)
+ ThreadRegistryLock l(&ctx->thread_registry);
+ if (!flags()->report_bugs || thr->suppress_reports)
+ return false;
+ switch (typ) {
+ case ReportTypeSignalUnsafe:
+ return flags()->report_signal_unsafe;
+ case ReportTypeThreadLeak:
+#if !SANITIZER_GO
+ // It's impossible to join phantom threads
+ // in the child after fork.
+ if (ctx->after_multithreaded_fork)
+ return false;
+#endif
+ return flags()->report_thread_leaks;
+ case ReportTypeMutexDestroyLocked:
+ return flags()->report_destroy_locked;
+ default:
+ return true;
+ }
+}
+
+ScopedReportBase::ScopedReportBase(ReportType typ, uptr tag) {
+ ctx->thread_registry.CheckLocked();
+ rep_ = New<ReportDesc>();
+ rep_->typ = typ;
+ rep_->tag = tag;
+ ctx->report_mtx.Lock();
+}
+
+ScopedReportBase::~ScopedReportBase() {
+ ctx->report_mtx.Unlock();
+ DestroyAndFree(rep_);
+}
+
+void ScopedReportBase::AddStack(StackTrace stack, bool suppressable) {
+ ReportStack **rs = rep_->stacks.PushBack();
+ *rs = SymbolizeStack(stack);
+ (*rs)->suppressable = suppressable;
+}
+
+void ScopedReportBase::AddMemoryAccess(uptr addr, uptr external_tag, Shadow s,
+ Tid tid, StackTrace stack,
+ const MutexSet *mset) {
+ uptr addr0, size;
+ AccessType typ;
+ s.GetAccess(&addr0, &size, &typ);
+ auto *mop = New<ReportMop>();
+ rep_->mops.PushBack(mop);
+ mop->tid = tid;
+ mop->addr = addr + addr0;
+ mop->size = size;
+ mop->write = !(typ & kAccessRead);
+ mop->atomic = typ & kAccessAtomic;
+ mop->stack = SymbolizeStack(stack);
+ mop->external_tag = external_tag;
+ if (mop->stack)
+ mop->stack->suppressable = true;
+ for (uptr i = 0; i < mset->Size(); i++) {
+ MutexSet::Desc d = mset->Get(i);
+ int id = this->AddMutex(d.addr, d.stack_id);
+ ReportMopMutex mtx = {id, d.write};
+ mop->mset.PushBack(mtx);
+ }
+}
+
+void ScopedReportBase::AddUniqueTid(Tid unique_tid) {
+ rep_->unique_tids.PushBack(unique_tid);
+}
+
+void ScopedReportBase::AddThread(const ThreadContext *tctx, bool suppressable) {
+ for (uptr i = 0; i < rep_->threads.Size(); i++) {
+ if ((u32)rep_->threads[i]->id == tctx->tid)
+ return;
+ }
+ auto *rt = New<ReportThread>();
+ rep_->threads.PushBack(rt);
+ rt->id = tctx->tid;
+ rt->os_id = tctx->os_id;
+ rt->running = (tctx->status == ThreadStatusRunning);
+ rt->name = internal_strdup(tctx->name);
+ rt->parent_tid = tctx->parent_tid;
+ rt->thread_type = tctx->thread_type;
+ rt->stack = 0;
+ rt->stack = SymbolizeStackId(tctx->creation_stack_id);
+ if (rt->stack)
+ rt->stack->suppressable = suppressable;
+}
+
+#if !SANITIZER_GO
+static ThreadContext *FindThreadByTidLocked(Tid tid) {
+ ctx->thread_registry.CheckLocked();
+ return static_cast<ThreadContext *>(
+ ctx->thread_registry.GetThreadLocked(tid));
+}
+
+static bool IsInStackOrTls(ThreadContextBase *tctx_base, void *arg) {
+ uptr addr = (uptr)arg;
+ ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
+ if (tctx->status != ThreadStatusRunning)
+ return false;
+ ThreadState *thr = tctx->thr;
+ CHECK(thr);
+ return ((addr >= thr->stk_addr && addr < thr->stk_addr + thr->stk_size) ||
+ (addr >= thr->tls_addr && addr < thr->tls_addr + thr->tls_size));
+}
+
+ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack) {
+ ctx->thread_registry.CheckLocked();
+ ThreadContext *tctx =
+ static_cast<ThreadContext *>(ctx->thread_registry.FindThreadContextLocked(
+ IsInStackOrTls, (void *)addr));
+ if (!tctx)
+ return 0;
+ ThreadState *thr = tctx->thr;
+ CHECK(thr);
+ *is_stack = (addr >= thr->stk_addr && addr < thr->stk_addr + thr->stk_size);
+ return tctx;
+}
+#endif
+
+void ScopedReportBase::AddThread(Tid tid, bool suppressable) {
+#if !SANITIZER_GO
+ if (const ThreadContext *tctx = FindThreadByTidLocked(tid))
+ AddThread(tctx, suppressable);
+#endif
+}
+
+int ScopedReportBase::AddMutex(uptr addr, StackID creation_stack_id) {
+ for (uptr i = 0; i < rep_->mutexes.Size(); i++) {
+ if (rep_->mutexes[i]->addr == addr)
+ return rep_->mutexes[i]->id;
+ }
+ auto *rm = New<ReportMutex>();
+ rep_->mutexes.PushBack(rm);
+ rm->id = rep_->mutexes.Size() - 1;
+ rm->addr = addr;
+ rm->stack = SymbolizeStackId(creation_stack_id);
+ return rm->id;
+}
+
+void ScopedReportBase::AddLocation(uptr addr, uptr size) {
+ if (addr == 0)
+ return;
+#if !SANITIZER_GO
+ int fd = -1;
+ Tid creat_tid = kInvalidTid;
+ StackID creat_stack = 0;
+ bool closed = false;
+ if (FdLocation(addr, &fd, &creat_tid, &creat_stack, &closed)) {
+ auto *loc = New<ReportLocation>();
+ loc->type = ReportLocationFD;
+ loc->fd_closed = closed;
+ loc->fd = fd;
+ loc->tid = creat_tid;
+ loc->stack = SymbolizeStackId(creat_stack);
+ rep_->locs.PushBack(loc);
+ AddThread(creat_tid);
+ return;
+ }
+ MBlock *b = 0;
+ uptr block_begin = 0;
+ Allocator *a = allocator();
+ if (a->PointerIsMine((void*)addr)) {
+ block_begin = (uptr)a->GetBlockBegin((void *)addr);
+ if (block_begin)
+ b = ctx->metamap.GetBlock(block_begin);
+ }
+ if (!b)
+ b = JavaHeapBlock(addr, &block_begin);
+ if (b != 0) {
+ auto *loc = New<ReportLocation>();
+ loc->type = ReportLocationHeap;
+ loc->heap_chunk_start = block_begin;
+ loc->heap_chunk_size = b->siz;
+ loc->external_tag = b->tag;
+ loc->tid = b->tid;
+ loc->stack = SymbolizeStackId(b->stk);
+ rep_->locs.PushBack(loc);
+ AddThread(b->tid);
+ return;
+ }
+ bool is_stack = false;
+ if (ThreadContext *tctx = IsThreadStackOrTls(addr, &is_stack)) {
+ auto *loc = New<ReportLocation>();
+ loc->type = is_stack ? ReportLocationStack : ReportLocationTLS;
+ loc->tid = tctx->tid;
+ rep_->locs.PushBack(loc);
+ AddThread(tctx);
+ }
+#endif
+ if (ReportLocation *loc = SymbolizeData(addr)) {
+ loc->suppressable = true;
+ rep_->locs.PushBack(loc);
+ return;
+ }
+}
+
+#if !SANITIZER_GO
+void ScopedReportBase::AddSleep(StackID stack_id) {
+ rep_->sleep = SymbolizeStackId(stack_id);
+}
+#endif
+
+void ScopedReportBase::SetCount(int count) { rep_->count = count; }
+
+void ScopedReportBase::SetSigNum(int sig) { rep_->signum = sig; }
+
+const ReportDesc *ScopedReportBase::GetReport() const { return rep_; }
+
+ScopedReport::ScopedReport(ReportType typ, uptr tag)
+ : ScopedReportBase(typ, tag) {}
+
+ScopedReport::~ScopedReport() {}
+
+// Replays the trace up to last_pos position in the last part
+// or up to the provided epoch/sid (whichever is earlier)
+// and calls the provided function f for each event.
+template <typename Func>
+void TraceReplay(Trace *trace, TracePart *last, Event *last_pos, Sid sid,
+ Epoch epoch, Func f) {
+ TracePart *part = trace->parts.Front();
+ Sid ev_sid = kFreeSid;
+ Epoch ev_epoch = kEpochOver;
+ for (;;) {
+ DCHECK_EQ(part->trace, trace);
+ // Note: an event can't start in the last element.
+ // Since an event can take up to 2 elements,
+ // we ensure we have at least 2 before adding an event.
+ Event *end = &part->events[TracePart::kSize - 1];
+ if (part == last)
+ end = last_pos;
+ f(kFreeSid, kEpochOver, nullptr); // notify about part start
+ for (Event *evp = &part->events[0]; evp < end; evp++) {
+ Event *evp0 = evp;
+ if (!evp->is_access && !evp->is_func) {
+ switch (evp->type) {
+ case EventType::kTime: {
+ auto *ev = reinterpret_cast<EventTime *>(evp);
+ ev_sid = static_cast<Sid>(ev->sid);
+ ev_epoch = static_cast<Epoch>(ev->epoch);
+ if (ev_sid == sid && ev_epoch > epoch)
+ return;
+ break;
+ }
+ case EventType::kAccessExt:
+ FALLTHROUGH;
+ case EventType::kAccessRange:
+ FALLTHROUGH;
+ case EventType::kLock:
+ FALLTHROUGH;
+ case EventType::kRLock:
+ // These take 2 Event elements.
+ evp++;
+ break;
+ case EventType::kUnlock:
+ // This takes 1 Event element.
+ break;
+ }
+ }
+ CHECK_NE(ev_sid, kFreeSid);
+ CHECK_NE(ev_epoch, kEpochOver);
+ f(ev_sid, ev_epoch, evp0);
+ }
+ if (part == last)
+ return;
+ part = trace->parts.Next(part);
+ CHECK(part);
+ }
+ CHECK(0);
+}
+
+static void RestoreStackMatch(VarSizeStackTrace *pstk, MutexSet *pmset,
+ Vector<uptr> *stack, MutexSet *mset, uptr pc,
+ bool *found) {
+ DPrintf2(" MATCHED\n");
+ *pmset = *mset;
+ stack->PushBack(pc);
+ pstk->Init(&(*stack)[0], stack->Size());
+ stack->PopBack();
+ *found = true;
+}
+
+// Checks if addr1|size1 is fully contained in addr2|size2.
+// We check for fully contained instread of just overlapping
+// because a memory access is always traced once, but can be
+// split into multiple accesses in the shadow.
+static constexpr bool IsWithinAccess(uptr addr1, uptr size1, uptr addr2,
+ uptr size2) {
+ return addr1 >= addr2 && addr1 + size1 <= addr2 + size2;
+}
+
+// Replays the trace of slot sid up to the target event identified
+// by epoch/addr/size/typ and restores and returns tid, stack, mutex set
+// and tag for that event. If there are multiple such events, it returns
+// the last one. Returns false if the event is not present in the trace.
+bool RestoreStack(EventType type, Sid sid, Epoch epoch, uptr addr, uptr size,
+ AccessType typ, Tid *ptid, VarSizeStackTrace *pstk,
+ MutexSet *pmset, uptr *ptag) {
+ // This function restores stack trace and mutex set for the thread/epoch.
+ // It does so by getting stack trace and mutex set at the beginning of
+ // trace part, and then replaying the trace till the given epoch.
+ DPrintf2("RestoreStack: sid=%u@%u addr=0x%zx/%zu typ=%x\n",
+ static_cast<int>(sid), static_cast<int>(epoch), addr, size,
+ static_cast<int>(typ));
+ ctx->slot_mtx.CheckLocked(); // needed to prevent trace part recycling
+ ctx->thread_registry.CheckLocked();
+ TidSlot *slot = &ctx->slots[static_cast<uptr>(sid)];
+ Tid tid = kInvalidTid;
+ // Need to lock the slot mutex as it protects slot->journal.
+ slot->mtx.CheckLocked();
+ for (uptr i = 0; i < slot->journal.Size(); i++) {
+ DPrintf2(" journal: epoch=%d tid=%d\n",
+ static_cast<int>(slot->journal[i].epoch), slot->journal[i].tid);
+ if (i == slot->journal.Size() - 1 || slot->journal[i + 1].epoch > epoch) {
+ tid = slot->journal[i].tid;
+ break;
+ }
+ }
+ if (tid == kInvalidTid)
+ return false;
+ *ptid = tid;
+ ThreadContext *tctx =
+ static_cast<ThreadContext *>(ctx->thread_registry.GetThreadLocked(tid));
+ Trace *trace = &tctx->trace;
+ // Snapshot first/last parts and the current position in the last part.
+ TracePart *first_part;
+ TracePart *last_part;
+ Event *last_pos;
+ {
+ Lock lock(&trace->mtx);
+ first_part = trace->parts.Front();
+ if (!first_part) {
+ DPrintf2("RestoreStack: tid=%d trace=%p no trace parts\n", tid, trace);
+ return false;
+ }
+ last_part = trace->parts.Back();
+ last_pos = trace->final_pos;
+ if (tctx->thr)
+ last_pos = (Event *)atomic_load_relaxed(&tctx->thr->trace_pos);
+ }
+ DynamicMutexSet mset;
+ Vector<uptr> stack;
+ uptr prev_pc = 0;
+ bool found = false;
+ bool is_read = typ & kAccessRead;
+ bool is_atomic = typ & kAccessAtomic;
+ bool is_free = typ & kAccessFree;
+ DPrintf2("RestoreStack: tid=%d parts=[%p-%p] last_pos=%p\n", tid,
+ trace->parts.Front(), last_part, last_pos);
+ TraceReplay(
+ trace, last_part, last_pos, sid, epoch,
+ [&](Sid ev_sid, Epoch ev_epoch, Event *evp) {
+ if (evp == nullptr) {
+ // Each trace part is self-consistent, so we reset state.
+ stack.Resize(0);
+ mset->Reset();
+ prev_pc = 0;
+ return;
+ }
+ bool match = ev_sid == sid && ev_epoch == epoch;
+ if (evp->is_access) {
+ if (evp->is_func == 0 && evp->type == EventType::kAccessExt &&
+ evp->_ == 0) // NopEvent
+ return;
+ auto *ev = reinterpret_cast<EventAccess *>(evp);
+ uptr ev_addr = RestoreAddr(ev->addr);
+ uptr ev_size = 1 << ev->size_log;
+ uptr ev_pc =
+ prev_pc + ev->pc_delta - (1 << (EventAccess::kPCBits - 1));
+ prev_pc = ev_pc;
+ DPrintf2(" Access: pc=0x%zx addr=0x%zx/%zu type=%u/%u\n", ev_pc,
+ ev_addr, ev_size, ev->is_read, ev->is_atomic);
+ if (match && type == EventType::kAccessExt &&
+ IsWithinAccess(addr, size, ev_addr, ev_size) &&
+ is_read == ev->is_read && is_atomic == ev->is_atomic && !is_free)
+ RestoreStackMatch(pstk, pmset, &stack, mset, ev_pc, &found);
+ return;
+ }
+ if (evp->is_func) {
+ auto *ev = reinterpret_cast<EventFunc *>(evp);
+ if (ev->pc) {
+ DPrintf2(" FuncEnter: pc=0x%llx\n", ev->pc);
+ stack.PushBack(ev->pc);
+ } else {
+ DPrintf2(" FuncExit\n");
+ // We don't log pathologically large stacks in each part,
+ // if the stack was truncated we can have more func exits than
+ // entries.
+ if (stack.Size())
+ stack.PopBack();
+ }
+ return;
+ }
+ switch (evp->type) {
+ case EventType::kAccessExt: {
+ auto *ev = reinterpret_cast<EventAccessExt *>(evp);
+ uptr ev_addr = RestoreAddr(ev->addr);
+ uptr ev_size = 1 << ev->size_log;
+ prev_pc = ev->pc;
+ DPrintf2(" AccessExt: pc=0x%llx addr=0x%zx/%zu type=%u/%u\n",
+ ev->pc, ev_addr, ev_size, ev->is_read, ev->is_atomic);
+ if (match && type == EventType::kAccessExt &&
+ IsWithinAccess(addr, size, ev_addr, ev_size) &&
+ is_read == ev->is_read && is_atomic == ev->is_atomic &&
+ !is_free)
+ RestoreStackMatch(pstk, pmset, &stack, mset, ev->pc, &found);
+ break;
+ }
+ case EventType::kAccessRange: {
+ auto *ev = reinterpret_cast<EventAccessRange *>(evp);
+ uptr ev_addr = RestoreAddr(ev->addr);
+ uptr ev_size =
+ (ev->size_hi << EventAccessRange::kSizeLoBits) + ev->size_lo;
+ uptr ev_pc = RestoreAddr(ev->pc);
+ prev_pc = ev_pc;
+ DPrintf2(" Range: pc=0x%zx addr=0x%zx/%zu type=%u/%u\n", ev_pc,
+ ev_addr, ev_size, ev->is_read, ev->is_free);
+ if (match && type == EventType::kAccessExt &&
+ IsWithinAccess(addr, size, ev_addr, ev_size) &&
+ is_read == ev->is_read && !is_atomic && is_free == ev->is_free)
+ RestoreStackMatch(pstk, pmset, &stack, mset, ev_pc, &found);
+ break;
+ }
+ case EventType::kLock:
+ FALLTHROUGH;
+ case EventType::kRLock: {
+ auto *ev = reinterpret_cast<EventLock *>(evp);
+ bool is_write = ev->type == EventType::kLock;
+ uptr ev_addr = RestoreAddr(ev->addr);
+ uptr ev_pc = RestoreAddr(ev->pc);
+ StackID stack_id =
+ (ev->stack_hi << EventLock::kStackIDLoBits) + ev->stack_lo;
+ DPrintf2(" Lock: pc=0x%zx addr=0x%zx stack=%u write=%d\n", ev_pc,
+ ev_addr, stack_id, is_write);
+ mset->AddAddr(ev_addr, stack_id, is_write);
+ // Events with ev_pc == 0 are written to the beginning of trace
+ // part as initial mutex set (are not real).
+ if (match && type == EventType::kLock && addr == ev_addr && ev_pc)
+ RestoreStackMatch(pstk, pmset, &stack, mset, ev_pc, &found);
+ break;
+ }
+ case EventType::kUnlock: {
+ auto *ev = reinterpret_cast<EventUnlock *>(evp);
+ uptr ev_addr = RestoreAddr(ev->addr);
+ DPrintf2(" Unlock: addr=0x%zx\n", ev_addr);
+ mset->DelAddr(ev_addr);
+ break;
+ }
+ case EventType::kTime:
+ // TraceReplay already extracted sid/epoch from it,
+ // nothing else to do here.
+ break;
+ }
+ });
+ ExtractTagFromStack(pstk, ptag);
+ return found;
+}
+
+bool RacyStacks::operator==(const RacyStacks &other) const {
+ if (hash[0] == other.hash[0] && hash[1] == other.hash[1])
+ return true;
+ if (hash[0] == other.hash[1] && hash[1] == other.hash[0])
+ return true;
+ return false;
+}
+
+static bool FindRacyStacks(const RacyStacks &hash) {
+ for (uptr i = 0; i < ctx->racy_stacks.Size(); i++) {
+ if (hash == ctx->racy_stacks[i]) {
+ VPrintf(2, "ThreadSanitizer: suppressing report as doubled (stack)\n");
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool HandleRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2]) {
+ if (!flags()->suppress_equal_stacks)
+ return false;
+ RacyStacks hash;
+ hash.hash[0] = md5_hash(traces[0].trace, traces[0].size * sizeof(uptr));
+ hash.hash[1] = md5_hash(traces[1].trace, traces[1].size * sizeof(uptr));
+ {
+ ReadLock lock(&ctx->racy_mtx);
+ if (FindRacyStacks(hash))
+ return true;
+ }
+ Lock lock(&ctx->racy_mtx);
+ if (FindRacyStacks(hash))
+ return true;
+ ctx->racy_stacks.PushBack(hash);
+ return false;
+}
+
+bool OutputReport(ThreadState *thr, const ScopedReport &srep) {
+ // These should have been checked in ShouldReport.
+ // It's too late to check them here, we have already taken locks.
+ CHECK(flags()->report_bugs);
+ CHECK(!thr->suppress_reports);
+ atomic_store_relaxed(&ctx->last_symbolize_time_ns, NanoTime());
+ const ReportDesc *rep = srep.GetReport();
+ CHECK_EQ(thr->current_report, nullptr);
+ thr->current_report = rep;
+ Suppression *supp = 0;
+ uptr pc_or_addr = 0;
+ for (uptr i = 0; pc_or_addr == 0 && i < rep->mops.Size(); i++)
+ pc_or_addr = IsSuppressed(rep->typ, rep->mops[i]->stack, &supp);
+ for (uptr i = 0; pc_or_addr == 0 && i < rep->stacks.Size(); i++)
+ pc_or_addr = IsSuppressed(rep->typ, rep->stacks[i], &supp);
+ for (uptr i = 0; pc_or_addr == 0 && i < rep->threads.Size(); i++)
+ pc_or_addr = IsSuppressed(rep->typ, rep->threads[i]->stack, &supp);
+ for (uptr i = 0; pc_or_addr == 0 && i < rep->locs.Size(); i++)
+ pc_or_addr = IsSuppressed(rep->typ, rep->locs[i], &supp);
+ if (pc_or_addr != 0) {
+ Lock lock(&ctx->fired_suppressions_mtx);
+ FiredSuppression s = {srep.GetReport()->typ, pc_or_addr, supp};
+ ctx->fired_suppressions.push_back(s);
+ }
+ {
+ bool suppressed = OnReport(rep, pc_or_addr != 0);
+ if (suppressed) {
+ thr->current_report = nullptr;
+ return false;
+ }
+ }
+ PrintReport(rep);
+ __tsan_on_report(rep);
+ ctx->nreported++;
+ if (flags()->halt_on_error)
+ Die();
+ thr->current_report = nullptr;
+ return true;
+}
+
+bool IsFiredSuppression(Context *ctx, ReportType type, StackTrace trace) {
+ ReadLock lock(&ctx->fired_suppressions_mtx);
+ for (uptr k = 0; k < ctx->fired_suppressions.size(); k++) {
+ if (ctx->fired_suppressions[k].type != type)
+ continue;
+ for (uptr j = 0; j < trace.size; j++) {
+ FiredSuppression *s = &ctx->fired_suppressions[k];
+ if (trace.trace[j] == s->pc_or_addr) {
+ if (s->supp)
+ atomic_fetch_add(&s->supp->hit_count, 1, memory_order_relaxed);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static bool IsFiredSuppression(Context *ctx, ReportType type, uptr addr) {
+ ReadLock lock(&ctx->fired_suppressions_mtx);
+ for (uptr k = 0; k < ctx->fired_suppressions.size(); k++) {
+ if (ctx->fired_suppressions[k].type != type)
+ continue;
+ FiredSuppression *s = &ctx->fired_suppressions[k];
+ if (addr == s->pc_or_addr) {
+ if (s->supp)
+ atomic_fetch_add(&s->supp->hit_count, 1, memory_order_relaxed);
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool SpuriousRace(Shadow old) {
+ Shadow last(LoadShadow(&ctx->last_spurious_race));
+ return last.sid() == old.sid() && last.epoch() == old.epoch();
+}
+
+void ReportRace(ThreadState *thr, RawShadow *shadow_mem, Shadow cur, Shadow old,
+ AccessType typ0) {
+ CheckedMutex::CheckNoLocks();
+
+ // Symbolizer makes lots of intercepted calls. If we try to process them,
+ // at best it will cause deadlocks on internal mutexes.
+ ScopedIgnoreInterceptors ignore;
+
+ uptr addr = ShadowToMem(shadow_mem);
+ DPrintf("#%d: ReportRace %p\n", thr->tid, (void *)addr);
+ if (!ShouldReport(thr, ReportTypeRace))
+ return;
+ uptr addr_off0, size0;
+ cur.GetAccess(&addr_off0, &size0, nullptr);
+ uptr addr_off1, size1, typ1;
+ old.GetAccess(&addr_off1, &size1, &typ1);
+ if (!flags()->report_atomic_races &&
+ ((typ0 & kAccessAtomic) || (typ1 & kAccessAtomic)) &&
+ !(typ0 & kAccessFree) && !(typ1 & kAccessFree))
+ return;
+ if (SpuriousRace(old))
+ return;
+
+ const uptr kMop = 2;
+ Shadow s[kMop] = {cur, old};
+ uptr addr0 = addr + addr_off0;
+ uptr addr1 = addr + addr_off1;
+ uptr end0 = addr0 + size0;
+ uptr end1 = addr1 + size1;
+ uptr addr_min = min(addr0, addr1);
+ uptr addr_max = max(end0, end1);
+ if (IsExpectedReport(addr_min, addr_max - addr_min))
+ return;
+
+ ReportType rep_typ = ReportTypeRace;
+ if ((typ0 & kAccessVptr) && (typ1 & kAccessFree))
+ rep_typ = ReportTypeVptrUseAfterFree;
+ else if (typ0 & kAccessVptr)
+ rep_typ = ReportTypeVptrRace;
+ else if (typ1 & kAccessFree)
+ rep_typ = ReportTypeUseAfterFree;
+
+ if (IsFiredSuppression(ctx, rep_typ, addr))
+ return;
+
+ VarSizeStackTrace traces[kMop];
+ Tid tids[kMop] = {thr->tid, kInvalidTid};
+ uptr tags[kMop] = {kExternalTagNone, kExternalTagNone};
+
+ ObtainCurrentStack(thr, thr->trace_prev_pc, &traces[0], &tags[0]);
+ if (IsFiredSuppression(ctx, rep_typ, traces[0]))
+ return;
+
+ DynamicMutexSet mset1;
+ MutexSet *mset[kMop] = {&thr->mset, mset1};
+
+ // We need to lock the slot during RestoreStack because it protects
+ // the slot journal.
+ Lock slot_lock(&ctx->slots[static_cast<uptr>(s[1].sid())].mtx);
+ ThreadRegistryLock l0(&ctx->thread_registry);
+ Lock slots_lock(&ctx->slot_mtx);
+ if (SpuriousRace(old))
+ return;
+ if (!RestoreStack(EventType::kAccessExt, s[1].sid(), s[1].epoch(), addr1,
+ size1, typ1, &tids[1], &traces[1], mset[1], &tags[1])) {
+ StoreShadow(&ctx->last_spurious_race, old.raw());
+ return;
+ }
+
+ if (IsFiredSuppression(ctx, rep_typ, traces[1]))
+ return;
+
+ if (HandleRacyStacks(thr, traces))
+ return;
+
+ // If any of the accesses has a tag, treat this as an "external" race.
+ uptr tag = kExternalTagNone;
+ for (uptr i = 0; i < kMop; i++) {
+ if (tags[i] != kExternalTagNone) {
+ rep_typ = ReportTypeExternalRace;
+ tag = tags[i];
+ break;
+ }
+ }
+
+ ScopedReport rep(rep_typ, tag);
+ for (uptr i = 0; i < kMop; i++)
+ rep.AddMemoryAccess(addr, tags[i], s[i], tids[i], traces[i], mset[i]);
+
+ for (uptr i = 0; i < kMop; i++) {
+ ThreadContext *tctx = static_cast<ThreadContext *>(
+ ctx->thread_registry.GetThreadLocked(tids[i]));
+ rep.AddThread(tctx);
+ }
+
+ rep.AddLocation(addr_min, addr_max - addr_min);
+
+ if (flags()->print_full_thread_history) {
+ const ReportDesc *rep_desc = rep.GetReport();
+ for (uptr i = 0; i < rep_desc->threads.Size(); i++) {
+ Tid parent_tid = rep_desc->threads[i]->parent_tid;
+ if (parent_tid == kMainTid || parent_tid == kInvalidTid)
+ continue;
+ ThreadContext *parent_tctx = static_cast<ThreadContext *>(
+ ctx->thread_registry.GetThreadLocked(parent_tid));
+ rep.AddThread(parent_tctx);
+ }
+ }
+
+#if !SANITIZER_GO
+ if (!((typ0 | typ1) & kAccessFree) &&
+ s[1].epoch() <= thr->last_sleep_clock.Get(s[1].sid()))
+ rep.AddSleep(thr->last_sleep_stack_id);
+#endif
+ OutputReport(thr, rep);
+}
+
+void PrintCurrentStack(ThreadState *thr, uptr pc) {
+ VarSizeStackTrace trace;
+ ObtainCurrentStack(thr, pc, &trace);
+ PrintStack(SymbolizeStack(trace));
+}
+
+// Always inlining PrintCurrentStackSlow, because LocatePcInTrace assumes
+// __sanitizer_print_stack_trace exists in the actual unwinded stack, but
+// tail-call to PrintCurrentStackSlow breaks this assumption because
+// __sanitizer_print_stack_trace disappears after tail-call.
+// However, this solution is not reliable enough, please see dvyukov's comment
+// http://reviews.llvm.org/D19148#406208
+// Also see PR27280 comment 2 and 3 for breaking examples and analysis.
+ALWAYS_INLINE USED void PrintCurrentStackSlow(uptr pc) {
+#if !SANITIZER_GO
+ uptr bp = GET_CURRENT_FRAME();
+ auto *ptrace = New<BufferedStackTrace>();
+ ptrace->Unwind(pc, bp, nullptr, false);
+
+ for (uptr i = 0; i < ptrace->size / 2; i++) {
+ uptr tmp = ptrace->trace_buffer[i];
+ ptrace->trace_buffer[i] = ptrace->trace_buffer[ptrace->size - i - 1];
+ ptrace->trace_buffer[ptrace->size - i - 1] = tmp;
+ }
+ PrintStack(SymbolizeStack(*ptrace));
+#endif
+}
+
+} // namespace __tsan
+
+using namespace __tsan;
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_print_stack_trace() {
+ PrintCurrentStackSlow(StackTrace::GetCurrentPc());
+}
+} // extern "C"
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_s390x.S b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_s390x.S
new file mode 100644
index 00000000000..2f445e8f1b2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_s390x.S
@@ -0,0 +1,49 @@
+#include "sanitizer_common/sanitizer_asm.h"
+
+#define CFA_OFFSET 160
+#define R2_REL_OFFSET 16
+#define R3_REL_OFFSET 24
+#define R14_REL_OFFSET 112
+#define R15_REL_OFFSET 120
+#define FRAME_SIZE 160
+
+.text
+
+ASM_HIDDEN(__tsan_setjmp)
+
+.macro intercept symbol, real
+.comm \real, 8, 8
+.globl ASM_SYMBOL_INTERCEPTOR(\symbol)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(\symbol))
+ASM_SYMBOL_INTERCEPTOR(\symbol):
+ CFI_STARTPROC
+ stmg %r2, %r3, R2_REL_OFFSET(%r15)
+ CFI_REL_OFFSET(%r2, R2_REL_OFFSET)
+ CFI_REL_OFFSET(%r3, R3_REL_OFFSET)
+ stmg %r14, %r15, R14_REL_OFFSET(%r15)
+ CFI_REL_OFFSET(%r14, R14_REL_OFFSET)
+ CFI_REL_OFFSET(%r15, R15_REL_OFFSET)
+ aghi %r15, -FRAME_SIZE
+ CFI_ADJUST_CFA_OFFSET(FRAME_SIZE)
+ la %r2, FRAME_SIZE(%r15)
+ brasl %r14, ASM_SYMBOL(__tsan_setjmp)
+ lmg %r14, %r15, FRAME_SIZE + R14_REL_OFFSET(%r15)
+ CFI_RESTORE(%r14)
+ CFI_RESTORE(%r15)
+ CFI_DEF_CFA_OFFSET(CFA_OFFSET)
+ lmg %r2, %r3, R2_REL_OFFSET(%r15)
+ CFI_RESTORE(%r2)
+ CFI_RESTORE(%r3)
+ larl %r1, \real
+ lg %r1, 0(%r1)
+ br %r1
+ CFI_ENDPROC
+ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(\symbol))
+.endm
+
+intercept setjmp, _ZN14__interception11real_setjmpE
+intercept _setjmp, _ZN14__interception12real__setjmpE
+intercept sigsetjmp, _ZN14__interception14real_sigsetjmpE
+intercept __sigsetjmp, _ZN14__interception16real___sigsetjmpE
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_thread.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_thread.cpp
new file mode 100644
index 00000000000..77488f84328
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_rtl_thread.cpp
@@ -0,0 +1,368 @@
+//===-- tsan_rtl_thread.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "tsan_rtl.h"
+#include "tsan_mman.h"
+#include "tsan_platform.h"
+#include "tsan_report.h"
+#include "tsan_sync.h"
+
+namespace __tsan {
+
+// ThreadContext implementation.
+
+ThreadContext::ThreadContext(Tid tid) : ThreadContextBase(tid), thr(), sync() {}
+
+#if !SANITIZER_GO
+ThreadContext::~ThreadContext() {
+}
+#endif
+
+void ThreadContext::OnReset() { CHECK(!sync); }
+
+#if !SANITIZER_GO
+struct ThreadLeak {
+ ThreadContext *tctx;
+ int count;
+};
+
+static void CollectThreadLeaks(ThreadContextBase *tctx_base, void *arg) {
+ auto &leaks = *static_cast<Vector<ThreadLeak> *>(arg);
+ auto *tctx = static_cast<ThreadContext *>(tctx_base);
+ if (tctx->detached || tctx->status != ThreadStatusFinished)
+ return;
+ for (uptr i = 0; i < leaks.Size(); i++) {
+ if (leaks[i].tctx->creation_stack_id == tctx->creation_stack_id) {
+ leaks[i].count++;
+ return;
+ }
+ }
+ leaks.PushBack({tctx, 1});
+}
+#endif
+
+// Disabled on Mac because lldb test TestTsanBasic fails:
+// https://reviews.llvm.org/D112603#3163158
+#if !SANITIZER_GO && !SANITIZER_APPLE
+static void ReportIgnoresEnabled(ThreadContext *tctx, IgnoreSet *set) {
+ if (tctx->tid == kMainTid) {
+ Printf("ThreadSanitizer: main thread finished with ignores enabled\n");
+ } else {
+ Printf("ThreadSanitizer: thread T%d %s finished with ignores enabled,"
+ " created at:\n", tctx->tid, tctx->name);
+ PrintStack(SymbolizeStackId(tctx->creation_stack_id));
+ }
+ Printf(" One of the following ignores was not ended"
+ " (in order of probability)\n");
+ for (uptr i = 0; i < set->Size(); i++) {
+ Printf(" Ignore was enabled at:\n");
+ PrintStack(SymbolizeStackId(set->At(i)));
+ }
+ Die();
+}
+
+static void ThreadCheckIgnore(ThreadState *thr) {
+ if (ctx->after_multithreaded_fork)
+ return;
+ if (thr->ignore_reads_and_writes)
+ ReportIgnoresEnabled(thr->tctx, &thr->mop_ignore_set);
+ if (thr->ignore_sync)
+ ReportIgnoresEnabled(thr->tctx, &thr->sync_ignore_set);
+}
+#else
+static void ThreadCheckIgnore(ThreadState *thr) {}
+#endif
+
+void ThreadFinalize(ThreadState *thr) {
+ ThreadCheckIgnore(thr);
+#if !SANITIZER_GO
+ if (!ShouldReport(thr, ReportTypeThreadLeak))
+ return;
+ ThreadRegistryLock l(&ctx->thread_registry);
+ Vector<ThreadLeak> leaks;
+ ctx->thread_registry.RunCallbackForEachThreadLocked(CollectThreadLeaks,
+ &leaks);
+ for (uptr i = 0; i < leaks.Size(); i++) {
+ ScopedReport rep(ReportTypeThreadLeak);
+ rep.AddThread(leaks[i].tctx, true);
+ rep.SetCount(leaks[i].count);
+ OutputReport(thr, rep);
+ }
+#endif
+}
+
+int ThreadCount(ThreadState *thr) {
+ uptr result;
+ ctx->thread_registry.GetNumberOfThreads(0, 0, &result);
+ return (int)result;
+}
+
+struct OnCreatedArgs {
+ VectorClock *sync;
+ uptr sync_epoch;
+ StackID stack;
+};
+
+Tid ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
+ // The main thread and GCD workers don't have a parent thread.
+ Tid parent = kInvalidTid;
+ OnCreatedArgs arg = {nullptr, 0, kInvalidStackID};
+ if (thr) {
+ parent = thr->tid;
+ arg.stack = CurrentStackId(thr, pc);
+ if (!thr->ignore_sync) {
+ SlotLocker locker(thr);
+ thr->clock.ReleaseStore(&arg.sync);
+ arg.sync_epoch = ctx->global_epoch;
+ IncrementEpoch(thr);
+ }
+ }
+ Tid tid = ctx->thread_registry.CreateThread(uid, detached, parent, &arg);
+ DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", parent, tid, uid);
+ return tid;
+}
+
+void ThreadContext::OnCreated(void *arg) {
+ OnCreatedArgs *args = static_cast<OnCreatedArgs *>(arg);
+ sync = args->sync;
+ sync_epoch = args->sync_epoch;
+ creation_stack_id = args->stack;
+}
+
+extern "C" void __tsan_stack_initialization() {}
+
+struct OnStartedArgs {
+ ThreadState *thr;
+ uptr stk_addr;
+ uptr stk_size;
+ uptr tls_addr;
+ uptr tls_size;
+};
+
+void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
+ ThreadType thread_type) {
+ ctx->thread_registry.StartThread(tid, os_id, thread_type, thr);
+ if (!thr->ignore_sync) {
+ SlotAttachAndLock(thr);
+ if (thr->tctx->sync_epoch == ctx->global_epoch)
+ thr->clock.Acquire(thr->tctx->sync);
+ SlotUnlock(thr);
+ }
+ Free(thr->tctx->sync);
+
+ uptr stk_addr = 0;
+ uptr stk_size = 0;
+ uptr tls_addr = 0;
+ uptr tls_size = 0;
+#if !SANITIZER_GO
+ if (thread_type != ThreadType::Fiber)
+ GetThreadStackAndTls(tid == kMainTid, &stk_addr, &stk_size, &tls_addr,
+ &tls_size);
+#endif
+ thr->stk_addr = stk_addr;
+ thr->stk_size = stk_size;
+ thr->tls_addr = tls_addr;
+ thr->tls_size = tls_size;
+
+#if !SANITIZER_GO
+ if (ctx->after_multithreaded_fork) {
+ thr->ignore_interceptors++;
+ ThreadIgnoreBegin(thr, 0);
+ ThreadIgnoreSyncBegin(thr, 0);
+ }
+#endif
+
+#if !SANITIZER_GO
+ // Don't imitate stack/TLS writes for the main thread,
+ // because its initialization is synchronized with all
+ // subsequent threads anyway.
+ if (tid != kMainTid) {
+ if (stk_addr && stk_size) {
+ const uptr pc = StackTrace::GetNextInstructionPc(
+ reinterpret_cast<uptr>(__tsan_stack_initialization));
+ MemoryRangeImitateWrite(thr, pc, stk_addr, stk_size);
+ }
+
+ if (tls_addr && tls_size)
+ ImitateTlsWrite(thr, tls_addr, tls_size);
+ }
+#endif
+}
+
+void ThreadContext::OnStarted(void *arg) {
+ thr = static_cast<ThreadState *>(arg);
+ DPrintf("#%d: ThreadStart\n", tid);
+ new (thr) ThreadState(tid);
+ if (common_flags()->detect_deadlocks)
+ thr->dd_lt = ctx->dd->CreateLogicalThread(tid);
+ thr->tctx = this;
+#if !SANITIZER_GO
+ thr->is_inited = true;
+#endif
+}
+
+void ThreadFinish(ThreadState *thr) {
+ DPrintf("#%d: ThreadFinish\n", thr->tid);
+ ThreadCheckIgnore(thr);
+ if (thr->stk_addr && thr->stk_size)
+ DontNeedShadowFor(thr->stk_addr, thr->stk_size);
+ if (thr->tls_addr && thr->tls_size)
+ DontNeedShadowFor(thr->tls_addr, thr->tls_size);
+ thr->is_dead = true;
+#if !SANITIZER_GO
+ thr->is_inited = false;
+ thr->ignore_interceptors++;
+ PlatformCleanUpThreadState(thr);
+#endif
+ if (!thr->ignore_sync) {
+ SlotLocker locker(thr);
+ ThreadRegistryLock lock(&ctx->thread_registry);
+ // Note: detached is protected by the thread registry mutex,
+ // the thread may be detaching concurrently in another thread.
+ if (!thr->tctx->detached) {
+ thr->clock.ReleaseStore(&thr->tctx->sync);
+ thr->tctx->sync_epoch = ctx->global_epoch;
+ IncrementEpoch(thr);
+ }
+ }
+#if !SANITIZER_GO
+ UnmapOrDie(thr->shadow_stack, kShadowStackSize * sizeof(uptr));
+#else
+ Free(thr->shadow_stack);
+#endif
+ thr->shadow_stack = nullptr;
+ thr->shadow_stack_pos = nullptr;
+ thr->shadow_stack_end = nullptr;
+ if (common_flags()->detect_deadlocks)
+ ctx->dd->DestroyLogicalThread(thr->dd_lt);
+ SlotDetach(thr);
+ ctx->thread_registry.FinishThread(thr->tid);
+ thr->~ThreadState();
+}
+
+void ThreadContext::OnFinished() {
+ Lock lock(&ctx->slot_mtx);
+ Lock lock1(&trace.mtx);
+ // Queue all trace parts into the global recycle queue.
+ auto parts = &trace.parts;
+ while (trace.local_head) {
+ CHECK(parts->Queued(trace.local_head));
+ ctx->trace_part_recycle.PushBack(trace.local_head);
+ trace.local_head = parts->Next(trace.local_head);
+ }
+ ctx->trace_part_recycle_finished += parts->Size();
+ if (ctx->trace_part_recycle_finished > Trace::kFinishedThreadHi) {
+ ctx->trace_part_finished_excess += parts->Size();
+ trace.parts_allocated = 0;
+ } else if (ctx->trace_part_recycle_finished > Trace::kFinishedThreadLo &&
+ parts->Size() > 1) {
+ ctx->trace_part_finished_excess += parts->Size() - 1;
+ trace.parts_allocated = 1;
+ }
+ // From now on replay will use trace->final_pos.
+ trace.final_pos = (Event *)atomic_load_relaxed(&thr->trace_pos);
+ atomic_store_relaxed(&thr->trace_pos, 0);
+ thr->tctx = nullptr;
+ thr = nullptr;
+}
+
+struct ConsumeThreadContext {
+ uptr uid;
+ ThreadContextBase *tctx;
+};
+
+Tid ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid) {
+ return ctx->thread_registry.ConsumeThreadUserId(uid);
+}
+
+struct JoinArg {
+ VectorClock *sync;
+ uptr sync_epoch;
+};
+
+void ThreadJoin(ThreadState *thr, uptr pc, Tid tid) {
+ CHECK_GT(tid, 0);
+ DPrintf("#%d: ThreadJoin tid=%d\n", thr->tid, tid);
+ JoinArg arg = {};
+ ctx->thread_registry.JoinThread(tid, &arg);
+ if (!thr->ignore_sync) {
+ SlotLocker locker(thr);
+ if (arg.sync_epoch == ctx->global_epoch)
+ thr->clock.Acquire(arg.sync);
+ }
+ Free(arg.sync);
+}
+
+void ThreadContext::OnJoined(void *ptr) {
+ auto arg = static_cast<JoinArg *>(ptr);
+ arg->sync = sync;
+ arg->sync_epoch = sync_epoch;
+ sync = nullptr;
+ sync_epoch = 0;
+}
+
+void ThreadContext::OnDead() { CHECK_EQ(sync, nullptr); }
+
+void ThreadDetach(ThreadState *thr, uptr pc, Tid tid) {
+ CHECK_GT(tid, 0);
+ ctx->thread_registry.DetachThread(tid, thr);
+}
+
+void ThreadContext::OnDetached(void *arg) { Free(sync); }
+
+void ThreadNotJoined(ThreadState *thr, uptr pc, Tid tid, uptr uid) {
+ CHECK_GT(tid, 0);
+ ctx->thread_registry.SetThreadUserId(tid, uid);
+}
+
+void ThreadSetName(ThreadState *thr, const char *name) {
+ ctx->thread_registry.SetThreadName(thr->tid, name);
+}
+
+#if !SANITIZER_GO
+void FiberSwitchImpl(ThreadState *from, ThreadState *to) {
+ Processor *proc = from->proc();
+ ProcUnwire(proc, from);
+ ProcWire(proc, to);
+ set_cur_thread(to);
+}
+
+ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags) {
+ void *mem = Alloc(sizeof(ThreadState));
+ ThreadState *fiber = static_cast<ThreadState *>(mem);
+ internal_memset(fiber, 0, sizeof(*fiber));
+ Tid tid = ThreadCreate(thr, pc, 0, true);
+ FiberSwitchImpl(thr, fiber);
+ ThreadStart(fiber, tid, 0, ThreadType::Fiber);
+ FiberSwitchImpl(fiber, thr);
+ return fiber;
+}
+
+void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber) {
+ FiberSwitchImpl(thr, fiber);
+ ThreadFinish(fiber);
+ FiberSwitchImpl(fiber, thr);
+ Free(fiber);
+}
+
+void FiberSwitch(ThreadState *thr, uptr pc,
+ ThreadState *fiber, unsigned flags) {
+ if (!(flags & FiberSwitchFlagNoSync))
+ Release(thr, pc, (uptr)fiber);
+ FiberSwitchImpl(thr, fiber);
+ if (!(flags & FiberSwitchFlagNoSync))
+ Acquire(fiber, pc, (uptr)fiber);
+}
+#endif
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_shadow.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_shadow.h
new file mode 100644
index 00000000000..6b8114ef513
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_shadow.h
@@ -0,0 +1,193 @@
+//===-- tsan_shadow.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TSAN_SHADOW_H
+#define TSAN_SHADOW_H
+
+#include "tsan_defs.h"
+
+namespace __tsan {
+
+class FastState {
+ public:
+ FastState() { Reset(); }
+
+ void Reset() {
+ part_.unused0_ = 0;
+ part_.sid_ = static_cast<u8>(kFreeSid);
+ part_.epoch_ = static_cast<u16>(kEpochLast);
+ part_.unused1_ = 0;
+ part_.ignore_accesses_ = false;
+ }
+
+ void SetSid(Sid sid) { part_.sid_ = static_cast<u8>(sid); }
+
+ Sid sid() const { return static_cast<Sid>(part_.sid_); }
+
+ Epoch epoch() const { return static_cast<Epoch>(part_.epoch_); }
+
+ void SetEpoch(Epoch epoch) { part_.epoch_ = static_cast<u16>(epoch); }
+
+ void SetIgnoreBit() { part_.ignore_accesses_ = 1; }
+ void ClearIgnoreBit() { part_.ignore_accesses_ = 0; }
+ bool GetIgnoreBit() const { return part_.ignore_accesses_; }
+
+ private:
+ friend class Shadow;
+ struct Parts {
+ u32 unused0_ : 8;
+ u32 sid_ : 8;
+ u32 epoch_ : kEpochBits;
+ u32 unused1_ : 1;
+ u32 ignore_accesses_ : 1;
+ };
+ union {
+ Parts part_;
+ u32 raw_;
+ };
+};
+
+static_assert(sizeof(FastState) == kShadowSize, "bad FastState size");
+
+class Shadow {
+ public:
+ static constexpr RawShadow kEmpty = static_cast<RawShadow>(0);
+
+ Shadow(FastState state, u32 addr, u32 size, AccessType typ) {
+ raw_ = state.raw_;
+ DCHECK_GT(size, 0);
+ DCHECK_LE(size, 8);
+ UNUSED Sid sid0 = part_.sid_;
+ UNUSED u16 epoch0 = part_.epoch_;
+ raw_ |= (!!(typ & kAccessAtomic) << kIsAtomicShift) |
+ (!!(typ & kAccessRead) << kIsReadShift) |
+ (((((1u << size) - 1) << (addr & 0x7)) & 0xff) << kAccessShift);
+ // Note: we don't check kAccessAtomic because it overlaps with
+ // FastState::ignore_accesses_ and it may be set spuriously.
+ DCHECK_EQ(part_.is_read_, !!(typ & kAccessRead));
+ DCHECK_EQ(sid(), sid0);
+ DCHECK_EQ(epoch(), epoch0);
+ }
+
+ explicit Shadow(RawShadow x = Shadow::kEmpty) { raw_ = static_cast<u32>(x); }
+
+ RawShadow raw() const { return static_cast<RawShadow>(raw_); }
+ Sid sid() const { return part_.sid_; }
+ Epoch epoch() const { return static_cast<Epoch>(part_.epoch_); }
+ u8 access() const { return part_.access_; }
+
+ void GetAccess(uptr *addr, uptr *size, AccessType *typ) const {
+ DCHECK(part_.access_ != 0 || raw_ == static_cast<u32>(Shadow::kRodata));
+ if (addr)
+ *addr = part_.access_ ? __builtin_ffs(part_.access_) - 1 : 0;
+ if (size)
+ *size = part_.access_ == kFreeAccess ? kShadowCell
+ : __builtin_popcount(part_.access_);
+ if (typ) {
+ *typ = part_.is_read_ ? kAccessRead : kAccessWrite;
+ if (part_.is_atomic_)
+ *typ |= kAccessAtomic;
+ if (part_.access_ == kFreeAccess)
+ *typ |= kAccessFree;
+ }
+ }
+
+ ALWAYS_INLINE
+ bool IsBothReadsOrAtomic(AccessType typ) const {
+ u32 is_read = !!(typ & kAccessRead);
+ u32 is_atomic = !!(typ & kAccessAtomic);
+ bool res =
+ raw_ & ((is_atomic << kIsAtomicShift) | (is_read << kIsReadShift));
+ DCHECK_EQ(res,
+ (part_.is_read_ && is_read) || (part_.is_atomic_ && is_atomic));
+ return res;
+ }
+
+ ALWAYS_INLINE
+ bool IsRWWeakerOrEqual(AccessType typ) const {
+ u32 is_read = !!(typ & kAccessRead);
+ u32 is_atomic = !!(typ & kAccessAtomic);
+ UNUSED u32 res0 =
+ (part_.is_atomic_ > is_atomic) ||
+ (part_.is_atomic_ == is_atomic && part_.is_read_ >= is_read);
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ const u32 kAtomicReadMask = (1 << kIsAtomicShift) | (1 << kIsReadShift);
+ bool res = (raw_ & kAtomicReadMask) >=
+ ((is_atomic << kIsAtomicShift) | (is_read << kIsReadShift));
+
+ DCHECK_EQ(res, res0);
+ return res;
+#else
+ return res0;
+#endif
+ }
+
+ // The FreedMarker must not pass "the same access check" so that we don't
+ // return from the race detection algorithm early.
+ static RawShadow FreedMarker() {
+ FastState fs;
+ fs.SetSid(kFreeSid);
+ fs.SetEpoch(kEpochLast);
+ Shadow s(fs, 0, 8, kAccessWrite);
+ return s.raw();
+ }
+
+ static RawShadow FreedInfo(Sid sid, Epoch epoch) {
+ Shadow s;
+ s.part_.sid_ = sid;
+ s.part_.epoch_ = static_cast<u16>(epoch);
+ s.part_.access_ = kFreeAccess;
+ return s.raw();
+ }
+
+ private:
+ struct Parts {
+ u8 access_;
+ Sid sid_;
+ u16 epoch_ : kEpochBits;
+ u16 is_read_ : 1;
+ u16 is_atomic_ : 1;
+ };
+ union {
+ Parts part_;
+ u32 raw_;
+ };
+
+ static constexpr u8 kFreeAccess = 0x81;
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ static constexpr uptr kAccessShift = 0;
+ static constexpr uptr kIsReadShift = 30;
+ static constexpr uptr kIsAtomicShift = 31;
+#else
+ static constexpr uptr kAccessShift = 24;
+ static constexpr uptr kIsReadShift = 1;
+ static constexpr uptr kIsAtomicShift = 0;
+#endif
+
+ public:
+ // .rodata shadow marker, see MapRodata and ContainsSameAccessFast.
+ static constexpr RawShadow kRodata =
+ static_cast<RawShadow>(1 << kIsReadShift);
+};
+
+static_assert(sizeof(Shadow) == kShadowSize, "bad Shadow size");
+
+ALWAYS_INLINE RawShadow LoadShadow(RawShadow *p) {
+ return static_cast<RawShadow>(
+ atomic_load((atomic_uint32_t *)p, memory_order_relaxed));
+}
+
+ALWAYS_INLINE void StoreShadow(RawShadow *sp, RawShadow s) {
+ atomic_store((atomic_uint32_t *)sp, static_cast<u32>(s),
+ memory_order_relaxed);
+}
+
+} // namespace __tsan
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_stack_trace.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_stack_trace.cpp
new file mode 100644
index 00000000000..9bbaafb3a85
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_stack_trace.cpp
@@ -0,0 +1,57 @@
+//===-- tsan_stack_trace.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_stack_trace.h"
+#include "tsan_rtl.h"
+#include "tsan_mman.h"
+
+namespace __tsan {
+
+VarSizeStackTrace::VarSizeStackTrace()
+ : StackTrace(nullptr, 0), trace_buffer(nullptr) {}
+
+VarSizeStackTrace::~VarSizeStackTrace() {
+ ResizeBuffer(0);
+}
+
+void VarSizeStackTrace::ResizeBuffer(uptr new_size) {
+ Free(trace_buffer);
+ trace_buffer = (new_size > 0)
+ ? (uptr *)Alloc(new_size * sizeof(trace_buffer[0]))
+ : nullptr;
+ trace = trace_buffer;
+ size = new_size;
+}
+
+void VarSizeStackTrace::Init(const uptr *pcs, uptr cnt, uptr extra_top_pc) {
+ ResizeBuffer(cnt + !!extra_top_pc);
+ internal_memcpy(trace_buffer, pcs, cnt * sizeof(trace_buffer[0]));
+ if (extra_top_pc)
+ trace_buffer[cnt] = extra_top_pc;
+}
+
+void VarSizeStackTrace::ReverseOrder() {
+ for (u32 i = 0; i < (size >> 1); i++)
+ Swap(trace_buffer[i], trace_buffer[size - 1 - i]);
+}
+
+} // namespace __tsan
+
+#if !SANITIZER_GO
+void __sanitizer::BufferedStackTrace::UnwindImpl(
+ uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
+ uptr top = 0;
+ uptr bottom = 0;
+ GetThreadStackTopAndBottom(false, &top, &bottom);
+ bool fast = StackTrace::WillUseFastUnwind(request_fast);
+ Unwind(max_depth, pc, bp, context, top, bottom, fast);
+}
+#endif // SANITIZER_GO
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_stack_trace.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_stack_trace.h
new file mode 100644
index 00000000000..3eb8ce156e8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_stack_trace.h
@@ -0,0 +1,42 @@
+//===-- tsan_stack_trace.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_STACK_TRACE_H
+#define TSAN_STACK_TRACE_H
+
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "tsan_defs.h"
+
+namespace __tsan {
+
+// StackTrace which calls malloc/free to allocate the buffer for
+// addresses in stack traces.
+struct VarSizeStackTrace : public StackTrace {
+ uptr *trace_buffer; // Owned.
+
+ VarSizeStackTrace();
+ ~VarSizeStackTrace();
+ void Init(const uptr *pcs, uptr cnt, uptr extra_top_pc = 0);
+
+ // Reverses the current stack trace order, the top frame goes to the bottom,
+ // the last frame goes to the top.
+ void ReverseOrder();
+
+ private:
+ void ResizeBuffer(uptr new_size);
+
+ VarSizeStackTrace(const VarSizeStackTrace &);
+ void operator=(const VarSizeStackTrace &);
+};
+
+} // namespace __tsan
+
+#endif // TSAN_STACK_TRACE_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_suppressions.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_suppressions.cpp
new file mode 100644
index 00000000000..a1c1bf81bf6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_suppressions.cpp
@@ -0,0 +1,161 @@
+//===-- tsan_suppressions.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
+#include "tsan_suppressions.h"
+#include "tsan_rtl.h"
+#include "tsan_flags.h"
+#include "tsan_mman.h"
+#include "tsan_platform.h"
+
+#if !SANITIZER_GO
+// Suppressions for true/false positives in standard libraries.
+static const char *const std_suppressions =
+// Libstdc++ 4.4 has data races in std::string.
+// See http://crbug.com/181502 for an example.
+"race:^_M_rep$\n"
+"race:^_M_is_leaked$\n"
+// False positive when using std <thread>.
+// Happens because we miss atomic synchronization in libstdc++.
+// See http://llvm.org/bugs/show_bug.cgi?id=17066 for details.
+"race:std::_Sp_counted_ptr_inplace<std::thread::_Impl\n";
+
+// Can be overriden in frontend.
+SANITIZER_WEAK_DEFAULT_IMPL
+const char *__tsan_default_suppressions() {
+ return 0;
+}
+#endif
+
+namespace __tsan {
+
+ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
+static SuppressionContext *suppression_ctx = nullptr;
+static const char *kSuppressionTypes[] = {
+ kSuppressionRace, kSuppressionRaceTop, kSuppressionMutex,
+ kSuppressionThread, kSuppressionSignal, kSuppressionLib,
+ kSuppressionDeadlock};
+
+void InitializeSuppressions() {
+ CHECK_EQ(nullptr, suppression_ctx);
+ suppression_ctx = new (suppression_placeholder)
+ SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
+ suppression_ctx->ParseFromFile(flags()->suppressions);
+#if !SANITIZER_GO
+ suppression_ctx->Parse(__tsan_default_suppressions());
+ suppression_ctx->Parse(std_suppressions);
+#endif
+}
+
+SuppressionContext *Suppressions() {
+ CHECK(suppression_ctx);
+ return suppression_ctx;
+}
+
+static const char *conv(ReportType typ) {
+ switch (typ) {
+ case ReportTypeRace:
+ case ReportTypeVptrRace:
+ case ReportTypeUseAfterFree:
+ case ReportTypeVptrUseAfterFree:
+ case ReportTypeExternalRace:
+ return kSuppressionRace;
+ case ReportTypeThreadLeak:
+ return kSuppressionThread;
+ case ReportTypeMutexDestroyLocked:
+ case ReportTypeMutexDoubleLock:
+ case ReportTypeMutexInvalidAccess:
+ case ReportTypeMutexBadUnlock:
+ case ReportTypeMutexBadReadLock:
+ case ReportTypeMutexBadReadUnlock:
+ return kSuppressionMutex;
+ case ReportTypeSignalUnsafe:
+ case ReportTypeErrnoInSignal:
+ return kSuppressionSignal;
+ case ReportTypeDeadlock:
+ return kSuppressionDeadlock;
+ // No default case so compiler warns us if we miss one
+ }
+ UNREACHABLE("missing case");
+}
+
+static uptr IsSuppressed(const char *stype, const AddressInfo &info,
+ Suppression **sp) {
+ if (suppression_ctx->Match(info.function, stype, sp) ||
+ suppression_ctx->Match(info.file, stype, sp) ||
+ suppression_ctx->Match(info.module, stype, sp)) {
+ VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", (*sp)->templ);
+ atomic_fetch_add(&(*sp)->hit_count, 1, memory_order_relaxed);
+ return info.address;
+ }
+ return 0;
+}
+
+uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
+ CHECK(suppression_ctx);
+ if (!suppression_ctx->SuppressionCount() || stack == 0 ||
+ !stack->suppressable)
+ return 0;
+ const char *stype = conv(typ);
+ if (0 == internal_strcmp(stype, kSuppressionNone))
+ return 0;
+ for (const SymbolizedStack *frame = stack->frames; frame;
+ frame = frame->next) {
+ uptr pc = IsSuppressed(stype, frame->info, sp);
+ if (pc != 0)
+ return pc;
+ }
+ if (0 == internal_strcmp(stype, kSuppressionRace) && stack->frames != nullptr)
+ return IsSuppressed(kSuppressionRaceTop, stack->frames->info, sp);
+ return 0;
+}
+
+uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
+ CHECK(suppression_ctx);
+ if (!suppression_ctx->SuppressionCount() || loc == 0 ||
+ loc->type != ReportLocationGlobal || !loc->suppressable)
+ return 0;
+ const char *stype = conv(typ);
+ if (0 == internal_strcmp(stype, kSuppressionNone))
+ return 0;
+ Suppression *s;
+ const DataInfo &global = loc->global;
+ if (suppression_ctx->Match(global.name, stype, &s) ||
+ suppression_ctx->Match(global.module, stype, &s)) {
+ VPrintf(2, "ThreadSanitizer: matched suppression '%s'\n", s->templ);
+ atomic_fetch_add(&s->hit_count, 1, memory_order_relaxed);
+ *sp = s;
+ return global.start;
+ }
+ return 0;
+}
+
+void PrintMatchedSuppressions() {
+ InternalMmapVector<Suppression *> matched;
+ CHECK(suppression_ctx);
+ suppression_ctx->GetMatched(&matched);
+ if (!matched.size())
+ return;
+ int hit_count = 0;
+ for (uptr i = 0; i < matched.size(); i++)
+ hit_count += atomic_load_relaxed(&matched[i]->hit_count);
+ Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n", hit_count,
+ (int)internal_getpid());
+ for (uptr i = 0; i < matched.size(); i++) {
+ Printf("%d %s:%s\n", atomic_load_relaxed(&matched[i]->hit_count),
+ matched[i]->type, matched[i]->templ);
+ }
+}
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_suppressions.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_suppressions.h
new file mode 100644
index 00000000000..f430aeb6c4c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_suppressions.h
@@ -0,0 +1,37 @@
+//===-- tsan_suppressions.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_SUPPRESSIONS_H
+#define TSAN_SUPPRESSIONS_H
+
+#include "sanitizer_common/sanitizer_suppressions.h"
+#include "tsan_report.h"
+
+namespace __tsan {
+
+const char kSuppressionNone[] = "none";
+const char kSuppressionRace[] = "race";
+const char kSuppressionRaceTop[] = "race_top";
+const char kSuppressionMutex[] = "mutex";
+const char kSuppressionThread[] = "thread";
+const char kSuppressionSignal[] = "signal";
+const char kSuppressionLib[] = "called_from_lib";
+const char kSuppressionDeadlock[] = "deadlock";
+
+void InitializeSuppressions();
+SuppressionContext *Suppressions();
+void PrintMatchedSuppressions();
+uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp);
+uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp);
+
+} // namespace __tsan
+
+#endif // TSAN_SUPPRESSIONS_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_symbolize.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_symbolize.cpp
new file mode 100644
index 00000000000..2e2744d2eae
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_symbolize.cpp
@@ -0,0 +1,123 @@
+//===-- tsan_symbolize.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "tsan_symbolize.h"
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+#include "tsan_flags.h"
+#include "tsan_report.h"
+#include "tsan_rtl.h"
+
+namespace __tsan {
+
+void EnterSymbolizer() {
+ ThreadState *thr = cur_thread();
+ CHECK(!thr->in_symbolizer);
+ thr->in_symbolizer = true;
+ thr->ignore_interceptors++;
+}
+
+void ExitSymbolizer() {
+ ThreadState *thr = cur_thread();
+ CHECK(thr->in_symbolizer);
+ thr->in_symbolizer = false;
+ thr->ignore_interceptors--;
+}
+
+// Legacy API.
+// May be overriden by JIT/JAVA/etc,
+// whatever produces PCs marked with kExternalPCBit.
+SANITIZER_WEAK_DEFAULT_IMPL
+bool __tsan_symbolize_external(uptr pc, char *func_buf, uptr func_siz,
+ char *file_buf, uptr file_siz, int *line,
+ int *col) {
+ return false;
+}
+
+// New API: call __tsan_symbolize_external_ex only when it exists.
+// Once old clients are gone, provide dummy implementation.
+SANITIZER_WEAK_DEFAULT_IMPL
+void __tsan_symbolize_external_ex(uptr pc,
+ void (*add_frame)(void *, const char *,
+ const char *, int, int),
+ void *ctx) {}
+
+struct SymbolizedStackBuilder {
+ SymbolizedStack *head;
+ SymbolizedStack *tail;
+ uptr addr;
+};
+
+static void AddFrame(void *ctx, const char *function_name, const char *file,
+ int line, int column) {
+ SymbolizedStackBuilder *ssb = (struct SymbolizedStackBuilder *)ctx;
+ if (ssb->tail) {
+ ssb->tail->next = SymbolizedStack::New(ssb->addr);
+ ssb->tail = ssb->tail->next;
+ } else {
+ ssb->head = ssb->tail = SymbolizedStack::New(ssb->addr);
+ }
+ AddressInfo *info = &ssb->tail->info;
+ if (function_name) {
+ info->function = internal_strdup(function_name);
+ }
+ if (file) {
+ info->file = internal_strdup(file);
+ }
+ info->line = line;
+ info->column = column;
+}
+
+SymbolizedStack *SymbolizeCode(uptr addr) {
+ // Check if PC comes from non-native land.
+ if (addr & kExternalPCBit) {
+ SymbolizedStackBuilder ssb = {nullptr, nullptr, addr};
+ __tsan_symbolize_external_ex(addr, AddFrame, &ssb);
+ if (ssb.head)
+ return ssb.head;
+ // Legacy code: remove along with the declaration above
+ // once all clients using this API are gone.
+ // Declare static to not consume too much stack space.
+ // We symbolize reports in a single thread, so this is fine.
+ static char func_buf[1024];
+ static char file_buf[1024];
+ int line, col;
+ SymbolizedStack *frame = SymbolizedStack::New(addr);
+ if (__tsan_symbolize_external(addr, func_buf, sizeof(func_buf), file_buf,
+ sizeof(file_buf), &line, &col)) {
+ frame->info.function = internal_strdup(func_buf);
+ frame->info.file = internal_strdup(file_buf);
+ frame->info.line = line;
+ frame->info.column = col;
+ }
+ return frame;
+ }
+ return Symbolizer::GetOrInit()->SymbolizePC(addr);
+}
+
+ReportLocation *SymbolizeData(uptr addr) {
+ DataInfo info;
+ if (!Symbolizer::GetOrInit()->SymbolizeData(addr, &info))
+ return 0;
+ auto *ent = New<ReportLocation>();
+ ent->type = ReportLocationGlobal;
+ internal_memcpy(&ent->global, &info, sizeof(info));
+ return ent;
+}
+
+void SymbolizeFlush() {
+ Symbolizer::GetOrInit()->Flush();
+}
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_symbolize.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_symbolize.h
new file mode 100644
index 00000000000..7adaa04dc27
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_symbolize.h
@@ -0,0 +1,30 @@
+//===-- tsan_symbolize.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_SYMBOLIZE_H
+#define TSAN_SYMBOLIZE_H
+
+#include "tsan_defs.h"
+#include "tsan_report.h"
+
+namespace __tsan {
+
+void EnterSymbolizer();
+void ExitSymbolizer();
+SymbolizedStack *SymbolizeCode(uptr addr);
+ReportLocation *SymbolizeData(uptr addr);
+void SymbolizeFlush();
+
+ReportStack *NewReportStackEntry(uptr addr);
+
+} // namespace __tsan
+
+#endif // TSAN_SYMBOLIZE_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_sync.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_sync.cpp
new file mode 100644
index 00000000000..09d41780d18
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_sync.cpp
@@ -0,0 +1,289 @@
+//===-- tsan_sync.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "tsan_sync.h"
+#include "tsan_rtl.h"
+#include "tsan_mman.h"
+
+namespace __tsan {
+
+void DDMutexInit(ThreadState *thr, uptr pc, SyncVar *s);
+
+SyncVar::SyncVar() : mtx(MutexTypeSyncVar) { Reset(); }
+
+void SyncVar::Init(ThreadState *thr, uptr pc, uptr addr, bool save_stack) {
+ Reset();
+ this->addr = addr;
+ next = 0;
+ if (save_stack && !SANITIZER_GO) // Go does not use them
+ creation_stack_id = CurrentStackId(thr, pc);
+ if (common_flags()->detect_deadlocks)
+ DDMutexInit(thr, pc, this);
+}
+
+void SyncVar::Reset() {
+ CHECK(!ctx->resetting);
+ creation_stack_id = kInvalidStackID;
+ owner_tid = kInvalidTid;
+ last_lock.Reset();
+ recursion = 0;
+ atomic_store_relaxed(&flags, 0);
+ Free(clock);
+ Free(read_clock);
+}
+
+MetaMap::MetaMap()
+ : block_alloc_("heap block allocator"), sync_alloc_("sync allocator") {}
+
+void MetaMap::AllocBlock(ThreadState *thr, uptr pc, uptr p, uptr sz) {
+ u32 idx = block_alloc_.Alloc(&thr->proc()->block_cache);
+ MBlock *b = block_alloc_.Map(idx);
+ b->siz = sz;
+ b->tag = 0;
+ b->tid = thr->tid;
+ b->stk = CurrentStackId(thr, pc);
+ u32 *meta = MemToMeta(p);
+ DCHECK_EQ(*meta, 0);
+ *meta = idx | kFlagBlock;
+}
+
+uptr MetaMap::FreeBlock(Processor *proc, uptr p, bool reset) {
+ MBlock* b = GetBlock(p);
+ if (b == 0)
+ return 0;
+ uptr sz = RoundUpTo(b->siz, kMetaShadowCell);
+ FreeRange(proc, p, sz, reset);
+ return sz;
+}
+
+bool MetaMap::FreeRange(Processor *proc, uptr p, uptr sz, bool reset) {
+ bool has_something = false;
+ u32 *meta = MemToMeta(p);
+ u32 *end = MemToMeta(p + sz);
+ if (end == meta)
+ end++;
+ for (; meta < end; meta++) {
+ u32 idx = *meta;
+ if (idx == 0) {
+ // Note: don't write to meta in this case -- the block can be huge.
+ continue;
+ }
+ *meta = 0;
+ has_something = true;
+ while (idx != 0) {
+ if (idx & kFlagBlock) {
+ block_alloc_.Free(&proc->block_cache, idx & ~kFlagMask);
+ break;
+ } else if (idx & kFlagSync) {
+ DCHECK(idx & kFlagSync);
+ SyncVar *s = sync_alloc_.Map(idx & ~kFlagMask);
+ u32 next = s->next;
+ if (reset)
+ s->Reset();
+ sync_alloc_.Free(&proc->sync_cache, idx & ~kFlagMask);
+ idx = next;
+ } else {
+ CHECK(0);
+ }
+ }
+ }
+ return has_something;
+}
+
+// ResetRange removes all meta objects from the range.
+// It is called for large mmap-ed regions. The function is best-effort wrt
+// freeing of meta objects, because we don't want to page in the whole range
+// which can be huge. The function probes pages one-by-one until it finds a page
+// without meta objects, at this point it stops freeing meta objects. Because
+// thread stacks grow top-down, we do the same starting from end as well.
+void MetaMap::ResetRange(Processor *proc, uptr p, uptr sz, bool reset) {
+ if (SANITIZER_GO) {
+ // UnmapOrDie/MmapFixedNoReserve does not work on Windows,
+ // so we do the optimization only for C/C++.
+ FreeRange(proc, p, sz, reset);
+ return;
+ }
+ const uptr kMetaRatio = kMetaShadowCell / kMetaShadowSize;
+ const uptr kPageSize = GetPageSizeCached() * kMetaRatio;
+ if (sz <= 4 * kPageSize) {
+ // If the range is small, just do the normal free procedure.
+ FreeRange(proc, p, sz, reset);
+ return;
+ }
+ // First, round both ends of the range to page size.
+ uptr diff = RoundUp(p, kPageSize) - p;
+ if (diff != 0) {
+ FreeRange(proc, p, diff, reset);
+ p += diff;
+ sz -= diff;
+ }
+ diff = p + sz - RoundDown(p + sz, kPageSize);
+ if (diff != 0) {
+ FreeRange(proc, p + sz - diff, diff, reset);
+ sz -= diff;
+ }
+ // Now we must have a non-empty page-aligned range.
+ CHECK_GT(sz, 0);
+ CHECK_EQ(p, RoundUp(p, kPageSize));
+ CHECK_EQ(sz, RoundUp(sz, kPageSize));
+ const uptr p0 = p;
+ const uptr sz0 = sz;
+ // Probe start of the range.
+ for (uptr checked = 0; sz > 0; checked += kPageSize) {
+ bool has_something = FreeRange(proc, p, kPageSize, reset);
+ p += kPageSize;
+ sz -= kPageSize;
+ if (!has_something && checked > (128 << 10))
+ break;
+ }
+ // Probe end of the range.
+ for (uptr checked = 0; sz > 0; checked += kPageSize) {
+ bool has_something = FreeRange(proc, p + sz - kPageSize, kPageSize, reset);
+ sz -= kPageSize;
+ // Stacks grow down, so sync object are most likely at the end of the region
+ // (if it is a stack). The very end of the stack is TLS and tsan increases
+ // TLS by at least 256K, so check at least 512K.
+ if (!has_something && checked > (512 << 10))
+ break;
+ }
+ // Finally, page out the whole range (including the parts that we've just
+ // freed). Note: we can't simply madvise, because we need to leave a zeroed
+ // range (otherwise __tsan_java_move can crash if it encounters a left-over
+ // meta objects in java heap).
+ uptr metap = (uptr)MemToMeta(p0);
+ uptr metasz = sz0 / kMetaRatio;
+ UnmapOrDie((void*)metap, metasz);
+ if (!MmapFixedSuperNoReserve(metap, metasz))
+ Die();
+}
+
+void MetaMap::ResetClocks() {
+ // This can be called from the background thread
+ // which does not have proc/cache.
+ // The cache is too large for stack.
+ static InternalAllocatorCache cache;
+ internal_memset(&cache, 0, sizeof(cache));
+ internal_allocator()->InitCache(&cache);
+ sync_alloc_.ForEach([&](SyncVar *s) {
+ if (s->clock) {
+ InternalFree(s->clock, &cache);
+ s->clock = nullptr;
+ }
+ if (s->read_clock) {
+ InternalFree(s->read_clock, &cache);
+ s->read_clock = nullptr;
+ }
+ s->last_lock.Reset();
+ });
+ internal_allocator()->DestroyCache(&cache);
+}
+
+MBlock* MetaMap::GetBlock(uptr p) {
+ u32 *meta = MemToMeta(p);
+ u32 idx = *meta;
+ for (;;) {
+ if (idx == 0)
+ return 0;
+ if (idx & kFlagBlock)
+ return block_alloc_.Map(idx & ~kFlagMask);
+ DCHECK(idx & kFlagSync);
+ SyncVar * s = sync_alloc_.Map(idx & ~kFlagMask);
+ idx = s->next;
+ }
+}
+
+SyncVar *MetaMap::GetSync(ThreadState *thr, uptr pc, uptr addr, bool create,
+ bool save_stack) {
+ DCHECK(!create || thr->slot_locked);
+ u32 *meta = MemToMeta(addr);
+ u32 idx0 = *meta;
+ u32 myidx = 0;
+ SyncVar *mys = nullptr;
+ for (;;) {
+ for (u32 idx = idx0; idx && !(idx & kFlagBlock);) {
+ DCHECK(idx & kFlagSync);
+ SyncVar * s = sync_alloc_.Map(idx & ~kFlagMask);
+ if (LIKELY(s->addr == addr)) {
+ if (UNLIKELY(myidx != 0)) {
+ mys->Reset();
+ sync_alloc_.Free(&thr->proc()->sync_cache, myidx);
+ }
+ return s;
+ }
+ idx = s->next;
+ }
+ if (!create)
+ return nullptr;
+ if (UNLIKELY(*meta != idx0)) {
+ idx0 = *meta;
+ continue;
+ }
+
+ if (LIKELY(myidx == 0)) {
+ myidx = sync_alloc_.Alloc(&thr->proc()->sync_cache);
+ mys = sync_alloc_.Map(myidx);
+ mys->Init(thr, pc, addr, save_stack);
+ }
+ mys->next = idx0;
+ if (atomic_compare_exchange_strong((atomic_uint32_t*)meta, &idx0,
+ myidx | kFlagSync, memory_order_release)) {
+ return mys;
+ }
+ }
+}
+
+void MetaMap::MoveMemory(uptr src, uptr dst, uptr sz) {
+ // src and dst can overlap,
+ // there are no concurrent accesses to the regions (e.g. stop-the-world).
+ CHECK_NE(src, dst);
+ CHECK_NE(sz, 0);
+ uptr diff = dst - src;
+ u32 *src_meta = MemToMeta(src);
+ u32 *dst_meta = MemToMeta(dst);
+ u32 *src_meta_end = MemToMeta(src + sz);
+ uptr inc = 1;
+ if (dst > src) {
+ src_meta = MemToMeta(src + sz) - 1;
+ dst_meta = MemToMeta(dst + sz) - 1;
+ src_meta_end = MemToMeta(src) - 1;
+ inc = -1;
+ }
+ for (; src_meta != src_meta_end; src_meta += inc, dst_meta += inc) {
+ CHECK_EQ(*dst_meta, 0);
+ u32 idx = *src_meta;
+ *src_meta = 0;
+ *dst_meta = idx;
+ // Patch the addresses in sync objects.
+ while (idx != 0) {
+ if (idx & kFlagBlock)
+ break;
+ CHECK(idx & kFlagSync);
+ SyncVar *s = sync_alloc_.Map(idx & ~kFlagMask);
+ s->addr += diff;
+ idx = s->next;
+ }
+ }
+}
+
+void MetaMap::OnProcIdle(Processor *proc) {
+ block_alloc_.FlushCache(&proc->block_cache);
+ sync_alloc_.FlushCache(&proc->sync_cache);
+}
+
+MetaMap::MemoryStats MetaMap::GetMemoryStats() const {
+ MemoryStats stats;
+ stats.mem_block = block_alloc_.AllocatedMemory();
+ stats.sync_obj = sync_alloc_.AllocatedMemory();
+ return stats;
+}
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_sync.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_sync.h
new file mode 100644
index 00000000000..67d3c0b5e7d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_sync.h
@@ -0,0 +1,148 @@
+//===-- tsan_sync.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_SYNC_H
+#define TSAN_SYNC_H
+
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
+#include "tsan_defs.h"
+#include "tsan_dense_alloc.h"
+#include "tsan_shadow.h"
+#include "tsan_vector_clock.h"
+
+namespace __tsan {
+
+// These need to match __tsan_mutex_* flags defined in tsan_interface.h.
+// See documentation there as well.
+enum MutexFlags {
+ MutexFlagLinkerInit = 1 << 0, // __tsan_mutex_linker_init
+ MutexFlagWriteReentrant = 1 << 1, // __tsan_mutex_write_reentrant
+ MutexFlagReadReentrant = 1 << 2, // __tsan_mutex_read_reentrant
+ MutexFlagReadLock = 1 << 3, // __tsan_mutex_read_lock
+ MutexFlagTryLock = 1 << 4, // __tsan_mutex_try_lock
+ MutexFlagTryLockFailed = 1 << 5, // __tsan_mutex_try_lock_failed
+ MutexFlagRecursiveLock = 1 << 6, // __tsan_mutex_recursive_lock
+ MutexFlagRecursiveUnlock = 1 << 7, // __tsan_mutex_recursive_unlock
+ MutexFlagNotStatic = 1 << 8, // __tsan_mutex_not_static
+
+ // The following flags are runtime private.
+ // Mutex API misuse was detected, so don't report any more.
+ MutexFlagBroken = 1 << 30,
+ // We did not intercept pre lock event, so handle it on post lock.
+ MutexFlagDoPreLockOnPostLock = 1 << 29,
+ // Must list all mutex creation flags.
+ MutexCreationFlagMask = MutexFlagLinkerInit |
+ MutexFlagWriteReentrant |
+ MutexFlagReadReentrant |
+ MutexFlagNotStatic,
+};
+
+// SyncVar is a descriptor of a user synchronization object
+// (mutex or an atomic variable).
+struct SyncVar {
+ SyncVar();
+
+ uptr addr; // overwritten by DenseSlabAlloc freelist
+ Mutex mtx;
+ StackID creation_stack_id;
+ Tid owner_tid; // Set only by exclusive owners.
+ FastState last_lock;
+ int recursion;
+ atomic_uint32_t flags;
+ u32 next; // in MetaMap
+ DDMutex dd;
+ VectorClock *read_clock; // Used for rw mutexes only.
+ VectorClock *clock;
+
+ void Init(ThreadState *thr, uptr pc, uptr addr, bool save_stack);
+ void Reset();
+
+ bool IsFlagSet(u32 f) const {
+ return atomic_load_relaxed(&flags) & f;
+ }
+
+ void SetFlags(u32 f) {
+ atomic_store_relaxed(&flags, atomic_load_relaxed(&flags) | f);
+ }
+
+ void UpdateFlags(u32 flagz) {
+ // Filter out operation flags.
+ if (!(flagz & MutexCreationFlagMask))
+ return;
+ u32 current = atomic_load_relaxed(&flags);
+ if (current & MutexCreationFlagMask)
+ return;
+ // Note: this can be called from MutexPostReadLock which holds only read
+ // lock on the SyncVar.
+ atomic_store_relaxed(&flags, current | (flagz & MutexCreationFlagMask));
+ }
+};
+
+// MetaMap maps app addresses to heap block (MBlock) and sync var (SyncVar)
+// descriptors. It uses 1/2 direct shadow, see tsan_platform.h for the mapping.
+class MetaMap {
+ public:
+ MetaMap();
+
+ void AllocBlock(ThreadState *thr, uptr pc, uptr p, uptr sz);
+
+ // FreeBlock resets all sync objects in the range if reset=true and must not
+ // run concurrently with ResetClocks which resets all sync objects
+ // w/o any synchronization (as part of DoReset).
+ // If we don't have a thread slot (very early/late in thread lifetime or
+ // Go/Java callbacks) or the slot is not locked, then reset must be set to
+ // false. In such case sync object clocks will be reset later (when it's
+ // reused or during the next ResetClocks).
+ uptr FreeBlock(Processor *proc, uptr p, bool reset);
+ bool FreeRange(Processor *proc, uptr p, uptr sz, bool reset);
+ void ResetRange(Processor *proc, uptr p, uptr sz, bool reset);
+ // Reset vector clocks of all sync objects.
+ // Must be called when no other threads access sync objects.
+ void ResetClocks();
+ MBlock* GetBlock(uptr p);
+
+ SyncVar *GetSyncOrCreate(ThreadState *thr, uptr pc, uptr addr,
+ bool save_stack) {
+ return GetSync(thr, pc, addr, true, save_stack);
+ }
+ SyncVar *GetSyncIfExists(uptr addr) {
+ return GetSync(nullptr, 0, addr, false, false);
+ }
+
+ void MoveMemory(uptr src, uptr dst, uptr sz);
+
+ void OnProcIdle(Processor *proc);
+
+ struct MemoryStats {
+ uptr mem_block;
+ uptr sync_obj;
+ };
+
+ MemoryStats GetMemoryStats() const;
+
+ private:
+ static const u32 kFlagMask = 3u << 30;
+ static const u32 kFlagBlock = 1u << 30;
+ static const u32 kFlagSync = 2u << 30;
+ typedef DenseSlabAlloc<MBlock, 1 << 18, 1 << 12, kFlagMask> BlockAlloc;
+ typedef DenseSlabAlloc<SyncVar, 1 << 20, 1 << 10, kFlagMask> SyncAlloc;
+ BlockAlloc block_alloc_;
+ SyncAlloc sync_alloc_;
+
+ SyncVar *GetSync(ThreadState *thr, uptr pc, uptr addr, bool create,
+ bool save_stack);
+};
+
+} // namespace __tsan
+
+#endif // TSAN_SYNC_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_trace.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_trace.h
new file mode 100644
index 00000000000..01bb7b34f43
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_trace.h
@@ -0,0 +1,215 @@
+//===-- tsan_trace.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_TRACE_H
+#define TSAN_TRACE_H
+
+#include "tsan_defs.h"
+#include "tsan_ilist.h"
+#include "tsan_mutexset.h"
+#include "tsan_stack_trace.h"
+
+namespace __tsan {
+
+enum class EventType : u64 {
+ kAccessExt,
+ kAccessRange,
+ kLock,
+ kRLock,
+ kUnlock,
+ kTime,
+};
+
+// "Base" type for all events for type dispatch.
+struct Event {
+ // We use variable-length type encoding to give more bits to some event
+ // types that need them. If is_access is set, this is EventAccess.
+ // Otherwise, if is_func is set, this is EventFunc.
+ // Otherwise type denotes the type.
+ u64 is_access : 1;
+ u64 is_func : 1;
+ EventType type : 3;
+ u64 _ : 59;
+};
+static_assert(sizeof(Event) == 8, "bad Event size");
+
+// Nop event used as padding and does not affect state during replay.
+static constexpr Event NopEvent = {1, 0, EventType::kAccessExt, 0};
+
+// Compressed memory access can represent only some events with PCs
+// close enough to each other. Otherwise we fall back to EventAccessExt.
+struct EventAccess {
+ static constexpr uptr kPCBits = 15;
+ static_assert(kPCBits + kCompressedAddrBits + 5 == 64,
+ "unused bits in EventAccess");
+
+ u64 is_access : 1; // = 1
+ u64 is_read : 1;
+ u64 is_atomic : 1;
+ u64 size_log : 2;
+ u64 pc_delta : kPCBits; // signed delta from the previous memory access PC
+ u64 addr : kCompressedAddrBits;
+};
+static_assert(sizeof(EventAccess) == 8, "bad EventAccess size");
+
+// Function entry (pc != 0) or exit (pc == 0).
+struct EventFunc {
+ u64 is_access : 1; // = 0
+ u64 is_func : 1; // = 1
+ u64 pc : 62;
+};
+static_assert(sizeof(EventFunc) == 8, "bad EventFunc size");
+
+// Extended memory access with full PC.
+struct EventAccessExt {
+ // Note: precisely specifying the unused parts of the bitfield is critical for
+ // performance. If we don't specify them, compiler will generate code to load
+ // the old value and shuffle it to extract the unused bits to apply to the new
+ // value. If we specify the unused part and store 0 in there, all that
+ // unnecessary code goes away (store of the 0 const is combined with other
+ // constant parts).
+ static constexpr uptr kUnusedBits = 11;
+ static_assert(kCompressedAddrBits + kUnusedBits + 9 == 64,
+ "unused bits in EventAccessExt");
+
+ u64 is_access : 1; // = 0
+ u64 is_func : 1; // = 0
+ EventType type : 3; // = EventType::kAccessExt
+ u64 is_read : 1;
+ u64 is_atomic : 1;
+ u64 size_log : 2;
+ u64 _ : kUnusedBits;
+ u64 addr : kCompressedAddrBits;
+ u64 pc;
+};
+static_assert(sizeof(EventAccessExt) == 16, "bad EventAccessExt size");
+
+// Access to a memory range.
+struct EventAccessRange {
+ static constexpr uptr kSizeLoBits = 13;
+ static_assert(kCompressedAddrBits + kSizeLoBits + 7 == 64,
+ "unused bits in EventAccessRange");
+
+ u64 is_access : 1; // = 0
+ u64 is_func : 1; // = 0
+ EventType type : 3; // = EventType::kAccessRange
+ u64 is_read : 1;
+ u64 is_free : 1;
+ u64 size_lo : kSizeLoBits;
+ u64 pc : kCompressedAddrBits;
+ u64 addr : kCompressedAddrBits;
+ u64 size_hi : 64 - kCompressedAddrBits;
+};
+static_assert(sizeof(EventAccessRange) == 16, "bad EventAccessRange size");
+
+// Mutex lock.
+struct EventLock {
+ static constexpr uptr kStackIDLoBits = 15;
+ static constexpr uptr kStackIDHiBits =
+ sizeof(StackID) * kByteBits - kStackIDLoBits;
+ static constexpr uptr kUnusedBits = 3;
+ static_assert(kCompressedAddrBits + kStackIDLoBits + 5 == 64,
+ "unused bits in EventLock");
+ static_assert(kCompressedAddrBits + kStackIDHiBits + kUnusedBits == 64,
+ "unused bits in EventLock");
+
+ u64 is_access : 1; // = 0
+ u64 is_func : 1; // = 0
+ EventType type : 3; // = EventType::kLock or EventType::kRLock
+ u64 pc : kCompressedAddrBits;
+ u64 stack_lo : kStackIDLoBits;
+ u64 stack_hi : sizeof(StackID) * kByteBits - kStackIDLoBits;
+ u64 _ : kUnusedBits;
+ u64 addr : kCompressedAddrBits;
+};
+static_assert(sizeof(EventLock) == 16, "bad EventLock size");
+
+// Mutex unlock.
+struct EventUnlock {
+ static constexpr uptr kUnusedBits = 15;
+ static_assert(kCompressedAddrBits + kUnusedBits + 5 == 64,
+ "unused bits in EventUnlock");
+
+ u64 is_access : 1; // = 0
+ u64 is_func : 1; // = 0
+ EventType type : 3; // = EventType::kUnlock
+ u64 _ : kUnusedBits;
+ u64 addr : kCompressedAddrBits;
+};
+static_assert(sizeof(EventUnlock) == 8, "bad EventUnlock size");
+
+// Time change event.
+struct EventTime {
+ static constexpr uptr kUnusedBits = 37;
+ static_assert(kUnusedBits + sizeof(Sid) * kByteBits + kEpochBits + 5 == 64,
+ "unused bits in EventTime");
+
+ u64 is_access : 1; // = 0
+ u64 is_func : 1; // = 0
+ EventType type : 3; // = EventType::kTime
+ u64 sid : sizeof(Sid) * kByteBits;
+ u64 epoch : kEpochBits;
+ u64 _ : kUnusedBits;
+};
+static_assert(sizeof(EventTime) == 8, "bad EventTime size");
+
+struct Trace;
+
+struct TraceHeader {
+ Trace* trace = nullptr; // back-pointer to Trace containing this part
+ INode trace_parts; // in Trace::parts
+ INode global; // in Contex::trace_part_recycle
+};
+
+struct TracePart : TraceHeader {
+ // There are a lot of goroutines in Go, so we use smaller parts.
+ static constexpr uptr kByteSize = (SANITIZER_GO ? 128 : 256) << 10;
+ static constexpr uptr kSize =
+ (kByteSize - sizeof(TraceHeader)) / sizeof(Event);
+ // TraceAcquire does a fast event pointer overflow check by comparing
+ // pointer into TracePart::events with kAlignment mask. Since TracePart's
+ // are allocated page-aligned, this check detects end of the array
+ // (it also have false positives in the middle that are filtered separately).
+ // This also requires events to be the last field.
+ static constexpr uptr kAlignment = 0xff0;
+ Event events[kSize];
+
+ TracePart() {}
+};
+static_assert(sizeof(TracePart) == TracePart::kByteSize, "bad TracePart size");
+
+struct Trace {
+ Mutex mtx;
+ IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
+ // First node non-queued into ctx->trace_part_recycle.
+ TracePart* local_head;
+ // Final position in the last part for finished threads.
+ Event* final_pos = nullptr;
+ // Number of trace parts allocated on behalf of this trace specifically.
+ // Total number of parts in this trace can be larger if we retake some
+ // parts from other traces.
+ uptr parts_allocated = 0;
+
+ Trace() : mtx(MutexTypeTrace) {}
+
+ // We need at least 3 parts per thread, because we want to keep at last
+ // 2 parts per thread that are not queued into ctx->trace_part_recycle
+ // (the current one being filled and one full part that ensures that
+ // we always have at least one part worth of previous memory accesses).
+ static constexpr uptr kMinParts = 3;
+
+ static constexpr uptr kFinishedThreadLo = 16;
+ static constexpr uptr kFinishedThreadHi = 64;
+};
+
+} // namespace __tsan
+
+#endif // TSAN_TRACE_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_vector_clock.cpp b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_vector_clock.cpp
new file mode 100644
index 00000000000..278298565d3
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_vector_clock.cpp
@@ -0,0 +1,126 @@
+//===-- tsan_vector_clock.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#include "tsan_vector_clock.h"
+
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "tsan_mman.h"
+
+namespace __tsan {
+
+#if TSAN_VECTORIZE
+const uptr kVectorClockSize = kThreadSlotCount * sizeof(Epoch) / sizeof(m128);
+#endif
+
+VectorClock::VectorClock() { Reset(); }
+
+void VectorClock::Reset() {
+#if !TSAN_VECTORIZE
+ for (uptr i = 0; i < kThreadSlotCount; i++)
+ clk_[i] = kEpochZero;
+#else
+ m128 z = _mm_setzero_si128();
+ m128* vclk = reinterpret_cast<m128*>(clk_);
+ for (uptr i = 0; i < kVectorClockSize; i++) _mm_store_si128(&vclk[i], z);
+#endif
+}
+
+void VectorClock::Acquire(const VectorClock* src) {
+ if (!src)
+ return;
+#if !TSAN_VECTORIZE
+ for (uptr i = 0; i < kThreadSlotCount; i++)
+ clk_[i] = max(clk_[i], src->clk_[i]);
+#else
+ m128* __restrict vdst = reinterpret_cast<m128*>(clk_);
+ m128 const* __restrict vsrc = reinterpret_cast<m128 const*>(src->clk_);
+ for (uptr i = 0; i < kVectorClockSize; i++) {
+ m128 s = _mm_load_si128(&vsrc[i]);
+ m128 d = _mm_load_si128(&vdst[i]);
+ m128 m = _mm_max_epu16(s, d);
+ _mm_store_si128(&vdst[i], m);
+ }
+#endif
+}
+
+static VectorClock* AllocClock(VectorClock** dstp) {
+ if (UNLIKELY(!*dstp))
+ *dstp = New<VectorClock>();
+ return *dstp;
+}
+
+void VectorClock::Release(VectorClock** dstp) const {
+ VectorClock* dst = AllocClock(dstp);
+ dst->Acquire(this);
+}
+
+void VectorClock::ReleaseStore(VectorClock** dstp) const {
+ VectorClock* dst = AllocClock(dstp);
+ *dst = *this;
+}
+
+VectorClock& VectorClock::operator=(const VectorClock& other) {
+#if !TSAN_VECTORIZE
+ for (uptr i = 0; i < kThreadSlotCount; i++)
+ clk_[i] = other.clk_[i];
+#else
+ m128* __restrict vdst = reinterpret_cast<m128*>(clk_);
+ m128 const* __restrict vsrc = reinterpret_cast<m128 const*>(other.clk_);
+ for (uptr i = 0; i < kVectorClockSize; i++) {
+ m128 s = _mm_load_si128(&vsrc[i]);
+ _mm_store_si128(&vdst[i], s);
+ }
+#endif
+ return *this;
+}
+
+void VectorClock::ReleaseStoreAcquire(VectorClock** dstp) {
+ VectorClock* dst = AllocClock(dstp);
+#if !TSAN_VECTORIZE
+ for (uptr i = 0; i < kThreadSlotCount; i++) {
+ Epoch tmp = dst->clk_[i];
+ dst->clk_[i] = clk_[i];
+ clk_[i] = max(clk_[i], tmp);
+ }
+#else
+ m128* __restrict vdst = reinterpret_cast<m128*>(dst->clk_);
+ m128* __restrict vclk = reinterpret_cast<m128*>(clk_);
+ for (uptr i = 0; i < kVectorClockSize; i++) {
+ m128 t = _mm_load_si128(&vdst[i]);
+ m128 c = _mm_load_si128(&vclk[i]);
+ m128 m = _mm_max_epu16(c, t);
+ _mm_store_si128(&vdst[i], c);
+ _mm_store_si128(&vclk[i], m);
+ }
+#endif
+}
+
+void VectorClock::ReleaseAcquire(VectorClock** dstp) {
+ VectorClock* dst = AllocClock(dstp);
+#if !TSAN_VECTORIZE
+ for (uptr i = 0; i < kThreadSlotCount; i++) {
+ dst->clk_[i] = max(dst->clk_[i], clk_[i]);
+ clk_[i] = dst->clk_[i];
+ }
+#else
+ m128* __restrict vdst = reinterpret_cast<m128*>(dst->clk_);
+ m128* __restrict vclk = reinterpret_cast<m128*>(clk_);
+ for (uptr i = 0; i < kVectorClockSize; i++) {
+ m128 c = _mm_load_si128(&vclk[i]);
+ m128 d = _mm_load_si128(&vdst[i]);
+ m128 m = _mm_max_epu16(c, d);
+ _mm_store_si128(&vdst[i], m);
+ _mm_store_si128(&vclk[i], m);
+ }
+#endif
+}
+
+} // namespace __tsan
diff --git a/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_vector_clock.h b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_vector_clock.h
new file mode 100644
index 00000000000..63b20630219
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/rtl/tsan_vector_clock.h
@@ -0,0 +1,51 @@
+//===-- tsan_vector_clock.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TSAN_VECTOR_CLOCK_H
+#define TSAN_VECTOR_CLOCK_H
+
+#include "tsan_defs.h"
+
+namespace __tsan {
+
+// Fixed-size vector clock, used both for threads and sync objects.
+class VectorClock {
+ public:
+ VectorClock();
+
+ Epoch Get(Sid sid) const;
+ void Set(Sid sid, Epoch v);
+
+ void Reset();
+ void Acquire(const VectorClock* src);
+ void Release(VectorClock** dstp) const;
+ void ReleaseStore(VectorClock** dstp) const;
+ void ReleaseStoreAcquire(VectorClock** dstp);
+ void ReleaseAcquire(VectorClock** dstp);
+
+ VectorClock& operator=(const VectorClock& other);
+
+ private:
+ Epoch clk_[kThreadSlotCount] VECTOR_ALIGNED;
+};
+
+ALWAYS_INLINE Epoch VectorClock::Get(Sid sid) const {
+ return clk_[static_cast<u8>(sid)];
+}
+
+ALWAYS_INLINE void VectorClock::Set(Sid sid, Epoch v) {
+ DCHECK_GE(v, clk_[static_cast<u8>(sid)]);
+ clk_[static_cast<u8>(sid)] = v;
+}
+
+} // namespace __tsan
+
+#endif // TSAN_VECTOR_CLOCK_H
diff --git a/contrib/libs/clang16-rt/lib/tsan/ya.make b/contrib/libs/clang16-rt/lib/tsan/ya.make
new file mode 100644
index 00000000000..f930e7e0590
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan/ya.make
@@ -0,0 +1,173 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.tsan${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHAVE_RPC_XDR_H=0
+ -DUBSAN_CAN_USE_CXXABI
+ -fPIE
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ interception/interception_linux.cpp
+ interception/interception_mac.cpp
+ interception/interception_type_test.cpp
+ interception/interception_win.cpp
+ sanitizer_common/sancov_flags.cpp
+ sanitizer_common/sanitizer_allocator.cpp
+ sanitizer_common/sanitizer_allocator_checks.cpp
+ sanitizer_common/sanitizer_allocator_report.cpp
+ sanitizer_common/sanitizer_chained_origin_depot.cpp
+ sanitizer_common/sanitizer_common.cpp
+ sanitizer_common/sanitizer_common_libcdep.cpp
+ sanitizer_common/sanitizer_coverage_fuchsia.cpp
+ sanitizer_common/sanitizer_coverage_libcdep_new.cpp
+ sanitizer_common/sanitizer_coverage_win_sections.cpp
+ sanitizer_common/sanitizer_deadlock_detector1.cpp
+ sanitizer_common/sanitizer_deadlock_detector2.cpp
+ sanitizer_common/sanitizer_errno.cpp
+ sanitizer_common/sanitizer_file.cpp
+ sanitizer_common/sanitizer_flag_parser.cpp
+ sanitizer_common/sanitizer_flags.cpp
+ sanitizer_common/sanitizer_fuchsia.cpp
+ sanitizer_common/sanitizer_libc.cpp
+ sanitizer_common/sanitizer_libignore.cpp
+ sanitizer_common/sanitizer_linux.cpp
+ sanitizer_common/sanitizer_linux_libcdep.cpp
+ sanitizer_common/sanitizer_linux_s390.cpp
+ sanitizer_common/sanitizer_mac.cpp
+ sanitizer_common/sanitizer_mac_libcdep.cpp
+ sanitizer_common/sanitizer_mutex.cpp
+ sanitizer_common/sanitizer_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+ sanitizer_common/sanitizer_platform_limits_linux.cpp
+ sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_posix.cpp
+ sanitizer_common/sanitizer_platform_limits_solaris.cpp
+ sanitizer_common/sanitizer_posix.cpp
+ sanitizer_common/sanitizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_printf.cpp
+ sanitizer_common/sanitizer_procmaps_bsd.cpp
+ sanitizer_common/sanitizer_procmaps_common.cpp
+ sanitizer_common/sanitizer_procmaps_fuchsia.cpp
+ sanitizer_common/sanitizer_procmaps_linux.cpp
+ sanitizer_common/sanitizer_procmaps_mac.cpp
+ sanitizer_common/sanitizer_procmaps_solaris.cpp
+ sanitizer_common/sanitizer_solaris.cpp
+ sanitizer_common/sanitizer_stack_store.cpp
+ sanitizer_common/sanitizer_stackdepot.cpp
+ sanitizer_common/sanitizer_stacktrace.cpp
+ sanitizer_common/sanitizer_stacktrace_libcdep.cpp
+ sanitizer_common/sanitizer_stacktrace_printer.cpp
+ sanitizer_common/sanitizer_stacktrace_sparc.cpp
+ sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
+ sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_mac.cpp
+ sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_win.cpp
+ sanitizer_common/sanitizer_suppressions.cpp
+ sanitizer_common/sanitizer_symbolizer.cpp
+ sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
+ sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_mac.cpp
+ sanitizer_common/sanitizer_symbolizer_markup.cpp
+ sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_report.cpp
+ sanitizer_common/sanitizer_symbolizer_win.cpp
+ sanitizer_common/sanitizer_termination.cpp
+ sanitizer_common/sanitizer_thread_registry.cpp
+ sanitizer_common/sanitizer_tls_get_addr.cpp
+ sanitizer_common/sanitizer_type_traits.cpp
+ sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
+ sanitizer_common/sanitizer_unwind_win.cpp
+ sanitizer_common/sanitizer_win.cpp
+ tsan/rtl/tsan_debugging.cpp
+ tsan/rtl/tsan_external.cpp
+ tsan/rtl/tsan_fd.cpp
+ tsan/rtl/tsan_flags.cpp
+ tsan/rtl/tsan_ignoreset.cpp
+ tsan/rtl/tsan_interceptors_posix.cpp
+ tsan/rtl/tsan_interface.cpp
+ tsan/rtl/tsan_interface_ann.cpp
+ tsan/rtl/tsan_interface_atomic.cpp
+ tsan/rtl/tsan_interface_java.cpp
+ tsan/rtl/tsan_malloc_mac.cpp
+ tsan/rtl/tsan_md5.cpp
+ tsan/rtl/tsan_mman.cpp
+ tsan/rtl/tsan_mutexset.cpp
+ tsan/rtl/tsan_platform_posix.cpp
+ tsan/rtl/tsan_preinit.cpp
+ tsan/rtl/tsan_report.cpp
+ tsan/rtl/tsan_rtl.cpp
+ tsan/rtl/tsan_rtl_aarch64.S
+ tsan/rtl/tsan_rtl_access.cpp
+ tsan/rtl/tsan_rtl_amd64.S
+ tsan/rtl/tsan_rtl_mutex.cpp
+ tsan/rtl/tsan_rtl_proc.cpp
+ tsan/rtl/tsan_rtl_report.cpp
+ tsan/rtl/tsan_rtl_thread.cpp
+ tsan/rtl/tsan_stack_trace.cpp
+ tsan/rtl/tsan_suppressions.cpp
+ tsan/rtl/tsan_symbolize.cpp
+ tsan/rtl/tsan_sync.cpp
+ tsan/rtl/tsan_vector_clock.cpp
+ ubsan/ubsan_diag.cpp
+ ubsan/ubsan_flags.cpp
+ ubsan/ubsan_handlers.cpp
+ ubsan/ubsan_init.cpp
+ ubsan/ubsan_monitor.cpp
+ ubsan/ubsan_value.cpp
+)
+
+IF (ARCH_PPC64LE)
+ SRCS(
+ tsan/rtl/tsan_rtl_ppc64.S
+ )
+ENDIF()
+
+IF (OS_DARWIN)
+ SRCS(
+ tsan/rtl/tsan_interceptors_mac.cpp
+ tsan/rtl/tsan_interceptors_mach_vm.cpp
+ tsan/rtl/tsan_platform_mac.cpp
+ )
+ELSEIF (OS_LINUX)
+ SRCS(
+ tsan/rtl/tsan_platform_linux.cpp
+ )
+ENDIF()
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/tsan_cxx/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/tsan_cxx/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan_cxx/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/tsan_cxx/ya.make b/contrib/libs/clang16-rt/lib/tsan_cxx/ya.make
new file mode 100644
index 00000000000..faf3f7bd55c
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/tsan_cxx/ya.make
@@ -0,0 +1,52 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.tsan_cxx${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DUBSAN_CAN_USE_CXXABI
+ -fPIE
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -frtti
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ tsan/rtl/tsan_new_delete.cpp
+ ubsan/ubsan_handlers_cxx.cpp
+ ubsan/ubsan_type_hash.cpp
+ ubsan/ubsan_type_hash_itanium.cpp
+ ubsan/ubsan_type_hash_win.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_checks.inc b/contrib/libs/clang16-rt/lib/ubsan/ubsan_checks.inc
new file mode 100644
index 00000000000..846cd89ee19
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_checks.inc
@@ -0,0 +1,71 @@
+//===-- ubsan_checks.inc ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// List of checks handled by UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_CHECK
+# error "Define UBSAN_CHECK prior to including this file!"
+#endif
+
+// UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName)
+// SummaryKind and FSanitizeFlagName should be string literals.
+
+UBSAN_CHECK(GenericUB, "undefined-behavior", "undefined")
+UBSAN_CHECK(NullPointerUse, "null-pointer-use", "null")
+UBSAN_CHECK(NullPointerUseWithNullability, "null-pointer-use",
+ "nullability-assign")
+UBSAN_CHECK(NullptrWithOffset, "nullptr-with-offset", "pointer-overflow")
+UBSAN_CHECK(NullptrWithNonZeroOffset, "nullptr-with-nonzero-offset",
+ "pointer-overflow")
+UBSAN_CHECK(NullptrAfterNonZeroOffset, "nullptr-after-nonzero-offset",
+ "pointer-overflow")
+UBSAN_CHECK(PointerOverflow, "pointer-overflow", "pointer-overflow")
+UBSAN_CHECK(MisalignedPointerUse, "misaligned-pointer-use", "alignment")
+UBSAN_CHECK(AlignmentAssumption, "alignment-assumption", "alignment")
+UBSAN_CHECK(InsufficientObjectSize, "insufficient-object-size", "object-size")
+UBSAN_CHECK(SignedIntegerOverflow, "signed-integer-overflow",
+ "signed-integer-overflow")
+UBSAN_CHECK(UnsignedIntegerOverflow, "unsigned-integer-overflow",
+ "unsigned-integer-overflow")
+UBSAN_CHECK(IntegerDivideByZero, "integer-divide-by-zero",
+ "integer-divide-by-zero")
+UBSAN_CHECK(FloatDivideByZero, "float-divide-by-zero", "float-divide-by-zero")
+UBSAN_CHECK(InvalidBuiltin, "invalid-builtin-use", "invalid-builtin-use")
+UBSAN_CHECK(InvalidObjCCast, "invalid-objc-cast", "invalid-objc-cast")
+UBSAN_CHECK(ImplicitUnsignedIntegerTruncation,
+ "implicit-unsigned-integer-truncation",
+ "implicit-unsigned-integer-truncation")
+UBSAN_CHECK(ImplicitSignedIntegerTruncation,
+ "implicit-signed-integer-truncation",
+ "implicit-signed-integer-truncation")
+UBSAN_CHECK(ImplicitIntegerSignChange,
+ "implicit-integer-sign-change",
+ "implicit-integer-sign-change")
+UBSAN_CHECK(ImplicitSignedIntegerTruncationOrSignChange,
+ "implicit-signed-integer-truncation-or-sign-change",
+ "implicit-signed-integer-truncation,implicit-integer-sign-change")
+UBSAN_CHECK(InvalidShiftBase, "invalid-shift-base", "shift-base")
+UBSAN_CHECK(InvalidShiftExponent, "invalid-shift-exponent", "shift-exponent")
+UBSAN_CHECK(OutOfBoundsIndex, "out-of-bounds-index", "bounds")
+UBSAN_CHECK(UnreachableCall, "unreachable-call", "unreachable")
+UBSAN_CHECK(MissingReturn, "missing-return", "return")
+UBSAN_CHECK(NonPositiveVLAIndex, "non-positive-vla-index", "vla-bound")
+UBSAN_CHECK(FloatCastOverflow, "float-cast-overflow", "float-cast-overflow")
+UBSAN_CHECK(InvalidBoolLoad, "invalid-bool-load", "bool")
+UBSAN_CHECK(InvalidEnumLoad, "invalid-enum-load", "enum")
+UBSAN_CHECK(FunctionTypeMismatch, "function-type-mismatch", "function")
+UBSAN_CHECK(InvalidNullReturn, "invalid-null-return",
+ "returns-nonnull-attribute")
+UBSAN_CHECK(InvalidNullReturnWithNullability, "invalid-null-return",
+ "nullability-return")
+UBSAN_CHECK(InvalidNullArgument, "invalid-null-argument", "nonnull-attribute")
+UBSAN_CHECK(InvalidNullArgumentWithNullability, "invalid-null-argument",
+ "nullability-arg")
+UBSAN_CHECK(DynamicTypeMismatch, "dynamic-type-mismatch", "vptr")
+UBSAN_CHECK(CFIBadType, "cfi-bad-type", "cfi")
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_diag.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_diag.cpp
new file mode 100644
index 00000000000..3673e66539d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_diag.cpp
@@ -0,0 +1,445 @@
+//===-- ubsan_diag.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Diagnostic reporting for the UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
+#include "ubsan_diag.h"
+#include "ubsan_init.h"
+#include "ubsan_flags.h"
+#include "ubsan_monitor.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_stacktrace_printer.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+#include <stdio.h>
+
+using namespace __ubsan;
+
+// UBSan is combined with runtimes that already provide this functionality
+// (e.g., ASan) as well as runtimes that lack it (e.g., scudo). Tried to use
+// weak linkage to resolve this issue which is not portable and breaks on
+// Windows.
+// TODO(yln): This is a temporary workaround. GetStackTrace functions will be
+// removed in the future.
+void ubsan_GetStackTrace(BufferedStackTrace *stack, uptr max_depth, uptr pc,
+ uptr bp, void *context, bool request_fast) {
+ uptr top = 0;
+ uptr bottom = 0;
+ GetThreadStackTopAndBottom(false, &top, &bottom);
+ bool fast = StackTrace::WillUseFastUnwind(request_fast);
+ stack->Unwind(max_depth, pc, bp, context, top, bottom, fast);
+}
+
+static void MaybePrintStackTrace(uptr pc, uptr bp) {
+ // We assume that flags are already parsed, as UBSan runtime
+ // will definitely be called when we print the first diagnostics message.
+ if (!flags()->print_stacktrace)
+ return;
+
+ BufferedStackTrace stack;
+ ubsan_GetStackTrace(&stack, kStackTraceMax, pc, bp, nullptr,
+ common_flags()->fast_unwind_on_fatal);
+ stack.Print();
+}
+
+static const char *ConvertTypeToString(ErrorType Type) {
+ switch (Type) {
+#define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) \
+ case ErrorType::Name: \
+ return SummaryKind;
+#include "ubsan_checks.inc"
+#undef UBSAN_CHECK
+ }
+ UNREACHABLE("unknown ErrorType!");
+}
+
+static const char *ConvertTypeToFlagName(ErrorType Type) {
+ switch (Type) {
+#define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) \
+ case ErrorType::Name: \
+ return FSanitizeFlagName;
+#include "ubsan_checks.inc"
+#undef UBSAN_CHECK
+ }
+ UNREACHABLE("unknown ErrorType!");
+}
+
+static void MaybeReportErrorSummary(Location Loc, ErrorType Type) {
+ if (!common_flags()->print_summary)
+ return;
+ if (!flags()->report_error_type)
+ Type = ErrorType::GenericUB;
+ const char *ErrorKind = ConvertTypeToString(Type);
+ if (Loc.isSourceLocation()) {
+ SourceLocation SLoc = Loc.getSourceLocation();
+ if (!SLoc.isInvalid()) {
+ AddressInfo AI;
+ AI.file = internal_strdup(SLoc.getFilename());
+ AI.line = SLoc.getLine();
+ AI.column = SLoc.getColumn();
+ AI.function = internal_strdup(""); // Avoid printing ?? as function name.
+ ReportErrorSummary(ErrorKind, AI, GetSanititizerToolName());
+ AI.Clear();
+ return;
+ }
+ } else if (Loc.isSymbolizedStack()) {
+ const AddressInfo &AI = Loc.getSymbolizedStack()->info;
+ ReportErrorSummary(ErrorKind, AI, GetSanititizerToolName());
+ return;
+ }
+ ReportErrorSummary(ErrorKind, GetSanititizerToolName());
+}
+
+namespace {
+class Decorator : public SanitizerCommonDecorator {
+ public:
+ Decorator() : SanitizerCommonDecorator() {}
+ const char *Highlight() const { return Green(); }
+ const char *Note() const { return Black(); }
+};
+}
+
+SymbolizedStack *__ubsan::getSymbolizedLocation(uptr PC) {
+ InitAsStandaloneIfNecessary();
+ return Symbolizer::GetOrInit()->SymbolizePC(PC);
+}
+
+Diag &Diag::operator<<(const TypeDescriptor &V) {
+ return AddArg(V.getTypeName());
+}
+
+Diag &Diag::operator<<(const Value &V) {
+ if (V.getType().isSignedIntegerTy())
+ AddArg(V.getSIntValue());
+ else if (V.getType().isUnsignedIntegerTy())
+ AddArg(V.getUIntValue());
+ else if (V.getType().isFloatTy())
+ AddArg(V.getFloatValue());
+ else
+ AddArg("<unknown>");
+ return *this;
+}
+
+/// Hexadecimal printing for numbers too large for Printf to handle directly.
+static void RenderHex(InternalScopedString *Buffer, UIntMax Val) {
+#if HAVE_INT128_T
+ Buffer->append("0x%08x%08x%08x%08x", (unsigned int)(Val >> 96),
+ (unsigned int)(Val >> 64), (unsigned int)(Val >> 32),
+ (unsigned int)(Val));
+#else
+ UNREACHABLE("long long smaller than 64 bits?");
+#endif
+}
+
+static void RenderLocation(InternalScopedString *Buffer, Location Loc) {
+ switch (Loc.getKind()) {
+ case Location::LK_Source: {
+ SourceLocation SLoc = Loc.getSourceLocation();
+ if (SLoc.isInvalid())
+ Buffer->append("<unknown>");
+ else
+ RenderSourceLocation(Buffer, SLoc.getFilename(), SLoc.getLine(),
+ SLoc.getColumn(), common_flags()->symbolize_vs_style,
+ common_flags()->strip_path_prefix);
+ return;
+ }
+ case Location::LK_Memory:
+ Buffer->append("%p", reinterpret_cast<void *>(Loc.getMemoryLocation()));
+ return;
+ case Location::LK_Symbolized: {
+ const AddressInfo &Info = Loc.getSymbolizedStack()->info;
+ if (Info.file)
+ RenderSourceLocation(Buffer, Info.file, Info.line, Info.column,
+ common_flags()->symbolize_vs_style,
+ common_flags()->strip_path_prefix);
+ else if (Info.module)
+ RenderModuleLocation(Buffer, Info.module, Info.module_offset,
+ Info.module_arch, common_flags()->strip_path_prefix);
+ else
+ Buffer->append("%p", reinterpret_cast<void *>(Info.address));
+ return;
+ }
+ case Location::LK_Null:
+ Buffer->append("<unknown>");
+ return;
+ }
+}
+
+static void RenderText(InternalScopedString *Buffer, const char *Message,
+ const Diag::Arg *Args) {
+ for (const char *Msg = Message; *Msg; ++Msg) {
+ if (*Msg != '%') {
+ Buffer->append("%c", *Msg);
+ continue;
+ }
+ const Diag::Arg &A = Args[*++Msg - '0'];
+ switch (A.Kind) {
+ case Diag::AK_String:
+ Buffer->append("%s", A.String);
+ break;
+ case Diag::AK_TypeName: {
+ if (SANITIZER_WINDOWS)
+ // The Windows implementation demangles names early.
+ Buffer->append("'%s'", A.String);
+ else
+ Buffer->append("'%s'", Symbolizer::GetOrInit()->Demangle(A.String));
+ break;
+ }
+ case Diag::AK_SInt:
+ // 'long long' is guaranteed to be at least 64 bits wide.
+ if (A.SInt >= INT64_MIN && A.SInt <= INT64_MAX)
+ Buffer->append("%lld", (long long)A.SInt);
+ else
+ RenderHex(Buffer, A.SInt);
+ break;
+ case Diag::AK_UInt:
+ if (A.UInt <= UINT64_MAX)
+ Buffer->append("%llu", (unsigned long long)A.UInt);
+ else
+ RenderHex(Buffer, A.UInt);
+ break;
+ case Diag::AK_Float: {
+ // FIXME: Support floating-point formatting in sanitizer_common's
+ // printf, and stop using snprintf here.
+ char FloatBuffer[32];
+#if SANITIZER_WINDOWS
+ sprintf_s(FloatBuffer, sizeof(FloatBuffer), "%Lg", (long double)A.Float);
+#else
+ snprintf(FloatBuffer, sizeof(FloatBuffer), "%Lg", (long double)A.Float);
+#endif
+ Buffer->append("%s", FloatBuffer);
+ break;
+ }
+ case Diag::AK_Pointer:
+ Buffer->append("%p", A.Pointer);
+ break;
+ }
+ }
+}
+
+/// Find the earliest-starting range in Ranges which ends after Loc.
+static Range *upperBound(MemoryLocation Loc, Range *Ranges,
+ unsigned NumRanges) {
+ Range *Best = 0;
+ for (unsigned I = 0; I != NumRanges; ++I)
+ if (Ranges[I].getEnd().getMemoryLocation() > Loc &&
+ (!Best ||
+ Best->getStart().getMemoryLocation() >
+ Ranges[I].getStart().getMemoryLocation()))
+ Best = &Ranges[I];
+ return Best;
+}
+
+static inline uptr subtractNoOverflow(uptr LHS, uptr RHS) {
+ return (LHS < RHS) ? 0 : LHS - RHS;
+}
+
+static inline uptr addNoOverflow(uptr LHS, uptr RHS) {
+ const uptr Limit = (uptr)-1;
+ return (LHS > Limit - RHS) ? Limit : LHS + RHS;
+}
+
+/// Render a snippet of the address space near a location.
+static void PrintMemorySnippet(const Decorator &Decor, MemoryLocation Loc,
+ Range *Ranges, unsigned NumRanges,
+ const Diag::Arg *Args) {
+ // Show at least the 8 bytes surrounding Loc.
+ const unsigned MinBytesNearLoc = 4;
+ MemoryLocation Min = subtractNoOverflow(Loc, MinBytesNearLoc);
+ MemoryLocation Max = addNoOverflow(Loc, MinBytesNearLoc);
+ MemoryLocation OrigMin = Min;
+ for (unsigned I = 0; I < NumRanges; ++I) {
+ Min = __sanitizer::Min(Ranges[I].getStart().getMemoryLocation(), Min);
+ Max = __sanitizer::Max(Ranges[I].getEnd().getMemoryLocation(), Max);
+ }
+
+ // If we have too many interesting bytes, prefer to show bytes after Loc.
+ const unsigned BytesToShow = 32;
+ if (Max - Min > BytesToShow)
+ Min = __sanitizer::Min(Max - BytesToShow, OrigMin);
+ Max = addNoOverflow(Min, BytesToShow);
+
+ if (!IsAccessibleMemoryRange(Min, Max - Min)) {
+ Printf("<memory cannot be printed>\n");
+ return;
+ }
+
+ // Emit data.
+ InternalScopedString Buffer;
+ for (uptr P = Min; P != Max; ++P) {
+ unsigned char C = *reinterpret_cast<const unsigned char*>(P);
+ Buffer.append("%s%02x", (P % 8 == 0) ? " " : " ", C);
+ }
+ Buffer.append("\n");
+
+ // Emit highlights.
+ Buffer.append("%s", Decor.Highlight());
+ Range *InRange = upperBound(Min, Ranges, NumRanges);
+ for (uptr P = Min; P != Max; ++P) {
+ char Pad = ' ', Byte = ' ';
+ if (InRange && InRange->getEnd().getMemoryLocation() == P)
+ InRange = upperBound(P, Ranges, NumRanges);
+ if (!InRange && P > Loc)
+ break;
+ if (InRange && InRange->getStart().getMemoryLocation() < P)
+ Pad = '~';
+ if (InRange && InRange->getStart().getMemoryLocation() <= P)
+ Byte = '~';
+ if (P % 8 == 0)
+ Buffer.append("%c", Pad);
+ Buffer.append("%c", Pad);
+ Buffer.append("%c", P == Loc ? '^' : Byte);
+ Buffer.append("%c", Byte);
+ }
+ Buffer.append("%s\n", Decor.Default());
+
+ // Go over the line again, and print names for the ranges.
+ InRange = 0;
+ unsigned Spaces = 0;
+ for (uptr P = Min; P != Max; ++P) {
+ if (!InRange || InRange->getEnd().getMemoryLocation() == P)
+ InRange = upperBound(P, Ranges, NumRanges);
+ if (!InRange)
+ break;
+
+ Spaces += (P % 8) == 0 ? 2 : 1;
+
+ if (InRange && InRange->getStart().getMemoryLocation() == P) {
+ while (Spaces--)
+ Buffer.append(" ");
+ RenderText(&Buffer, InRange->getText(), Args);
+ Buffer.append("\n");
+ // FIXME: We only support naming one range for now!
+ break;
+ }
+
+ Spaces += 2;
+ }
+
+ Printf("%s", Buffer.data());
+ // FIXME: Print names for anything we can identify within the line:
+ //
+ // * If we can identify the memory itself as belonging to a particular
+ // global, stack variable, or dynamic allocation, then do so.
+ //
+ // * If we have a pointer-size, pointer-aligned range highlighted,
+ // determine whether the value of that range is a pointer to an
+ // entity which we can name, and if so, print that name.
+ //
+ // This needs an external symbolizer, or (preferably) ASan instrumentation.
+}
+
+Diag::~Diag() {
+ // All diagnostics should be printed under report mutex.
+ ScopedReport::CheckLocked();
+ Decorator Decor;
+ InternalScopedString Buffer;
+
+ // Prepare a report that a monitor process can inspect.
+ if (Level == DL_Error) {
+ RenderText(&Buffer, Message, Args);
+ UndefinedBehaviorReport UBR{ConvertTypeToString(ET), Loc, Buffer};
+ Buffer.clear();
+ }
+
+ Buffer.append("%s", Decor.Bold());
+ RenderLocation(&Buffer, Loc);
+ Buffer.append(":");
+
+ switch (Level) {
+ case DL_Error:
+ Buffer.append("%s runtime error: %s%s", Decor.Warning(), Decor.Default(),
+ Decor.Bold());
+ break;
+
+ case DL_Note:
+ Buffer.append("%s note: %s", Decor.Note(), Decor.Default());
+ break;
+ }
+
+ RenderText(&Buffer, Message, Args);
+
+ Buffer.append("%s\n", Decor.Default());
+ Printf("%s", Buffer.data());
+
+ if (Loc.isMemoryLocation())
+ PrintMemorySnippet(Decor, Loc.getMemoryLocation(), Ranges, NumRanges, Args);
+}
+
+ScopedReport::Initializer::Initializer() { InitAsStandaloneIfNecessary(); }
+
+ScopedReport::ScopedReport(ReportOptions Opts, Location SummaryLoc,
+ ErrorType Type)
+ : Opts(Opts), SummaryLoc(SummaryLoc), Type(Type) {}
+
+ScopedReport::~ScopedReport() {
+ MaybePrintStackTrace(Opts.pc, Opts.bp);
+ MaybeReportErrorSummary(SummaryLoc, Type);
+
+ if (common_flags()->print_module_map >= 2)
+ DumpProcessMap();
+
+ if (flags()->halt_on_error)
+ Die();
+}
+
+ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
+static SuppressionContext *suppression_ctx = nullptr;
+static const char kVptrCheck[] = "vptr_check";
+static const char *kSuppressionTypes[] = {
+#define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) FSanitizeFlagName,
+#include "ubsan_checks.inc"
+#undef UBSAN_CHECK
+ kVptrCheck,
+};
+
+void __ubsan::InitializeSuppressions() {
+ CHECK_EQ(nullptr, suppression_ctx);
+ suppression_ctx = new (suppression_placeholder)
+ SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
+ suppression_ctx->ParseFromFile(flags()->suppressions);
+}
+
+bool __ubsan::IsVptrCheckSuppressed(const char *TypeName) {
+ InitAsStandaloneIfNecessary();
+ CHECK(suppression_ctx);
+ Suppression *s;
+ return suppression_ctx->Match(TypeName, kVptrCheck, &s);
+}
+
+bool __ubsan::IsPCSuppressed(ErrorType ET, uptr PC, const char *Filename) {
+ InitAsStandaloneIfNecessary();
+ CHECK(suppression_ctx);
+ const char *SuppType = ConvertTypeToFlagName(ET);
+ // Fast path: don't symbolize PC if there is no suppressions for given UB
+ // type.
+ if (!suppression_ctx->HasSuppressionType(SuppType))
+ return false;
+ Suppression *s = nullptr;
+ // Suppress by file name known to runtime.
+ if (Filename != nullptr && suppression_ctx->Match(Filename, SuppType, &s))
+ return true;
+ // Suppress by module name.
+ if (const char *Module = Symbolizer::GetOrInit()->GetModuleNameForPc(PC)) {
+ if (suppression_ctx->Match(Module, SuppType, &s))
+ return true;
+ }
+ // Suppress by function or source file name from debug info.
+ SymbolizedStackHolder Stack(Symbolizer::GetOrInit()->SymbolizePC(PC));
+ const AddressInfo &AI = Stack.get()->info;
+ return suppression_ctx->Match(AI.function, SuppType, &s) ||
+ suppression_ctx->Match(AI.file, SuppType, &s);
+}
+
+#endif // CAN_SANITIZE_UB
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_diag.h b/contrib/libs/clang16-rt/lib/ubsan/ubsan_diag.h
new file mode 100644
index 00000000000..b444e971b22
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_diag.h
@@ -0,0 +1,266 @@
+//===-- ubsan_diag.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Diagnostics emission for Clang's undefined behavior sanitizer.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_DIAG_H
+#define UBSAN_DIAG_H
+
+#include "ubsan_value.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+
+namespace __ubsan {
+
+class SymbolizedStackHolder {
+ SymbolizedStack *Stack;
+
+ void clear() {
+ if (Stack)
+ Stack->ClearAll();
+ }
+
+public:
+ explicit SymbolizedStackHolder(SymbolizedStack *Stack = nullptr)
+ : Stack(Stack) {}
+ ~SymbolizedStackHolder() { clear(); }
+ void reset(SymbolizedStack *S) {
+ if (Stack != S)
+ clear();
+ Stack = S;
+ }
+ const SymbolizedStack *get() const { return Stack; }
+};
+
+SymbolizedStack *getSymbolizedLocation(uptr PC);
+
+inline SymbolizedStack *getCallerLocation(uptr CallerPC) {
+ CHECK(CallerPC);
+ uptr PC = StackTrace::GetPreviousInstructionPc(CallerPC);
+ return getSymbolizedLocation(PC);
+}
+
+/// A location of some data within the program's address space.
+typedef uptr MemoryLocation;
+
+/// \brief Location at which a diagnostic can be emitted. Either a
+/// SourceLocation, a MemoryLocation, or a SymbolizedStack.
+class Location {
+public:
+ enum LocationKind { LK_Null, LK_Source, LK_Memory, LK_Symbolized };
+
+private:
+ LocationKind Kind;
+ // FIXME: In C++11, wrap these in an anonymous union.
+ SourceLocation SourceLoc;
+ MemoryLocation MemoryLoc;
+ const SymbolizedStack *SymbolizedLoc; // Not owned.
+
+public:
+ Location() : Kind(LK_Null) {}
+ Location(SourceLocation Loc) :
+ Kind(LK_Source), SourceLoc(Loc) {}
+ Location(MemoryLocation Loc) :
+ Kind(LK_Memory), MemoryLoc(Loc) {}
+ // SymbolizedStackHolder must outlive Location object.
+ Location(const SymbolizedStackHolder &Stack) :
+ Kind(LK_Symbolized), SymbolizedLoc(Stack.get()) {}
+
+ LocationKind getKind() const { return Kind; }
+
+ bool isSourceLocation() const { return Kind == LK_Source; }
+ bool isMemoryLocation() const { return Kind == LK_Memory; }
+ bool isSymbolizedStack() const { return Kind == LK_Symbolized; }
+
+ SourceLocation getSourceLocation() const {
+ CHECK(isSourceLocation());
+ return SourceLoc;
+ }
+ MemoryLocation getMemoryLocation() const {
+ CHECK(isMemoryLocation());
+ return MemoryLoc;
+ }
+ const SymbolizedStack *getSymbolizedStack() const {
+ CHECK(isSymbolizedStack());
+ return SymbolizedLoc;
+ }
+};
+
+/// A diagnostic severity level.
+enum DiagLevel {
+ DL_Error, ///< An error.
+ DL_Note ///< A note, attached to a prior diagnostic.
+};
+
+/// \brief Annotation for a range of locations in a diagnostic.
+class Range {
+ Location Start, End;
+ const char *Text;
+
+public:
+ Range() : Start(), End(), Text() {}
+ Range(MemoryLocation Start, MemoryLocation End, const char *Text)
+ : Start(Start), End(End), Text(Text) {}
+ Location getStart() const { return Start; }
+ Location getEnd() const { return End; }
+ const char *getText() const { return Text; }
+};
+
+/// \brief A C++ type name. Really just a strong typedef for 'const char*'.
+class TypeName {
+ const char *Name;
+public:
+ TypeName(const char *Name) : Name(Name) {}
+ const char *getName() const { return Name; }
+};
+
+enum class ErrorType {
+#define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) Name,
+#include "ubsan_checks.inc"
+#undef UBSAN_CHECK
+};
+
+/// \brief Representation of an in-flight diagnostic.
+///
+/// Temporary \c Diag instances are created by the handler routines to
+/// accumulate arguments for a diagnostic. The destructor emits the diagnostic
+/// message.
+class Diag {
+ /// The location at which the problem occurred.
+ Location Loc;
+
+ /// The diagnostic level.
+ DiagLevel Level;
+
+ /// The error type.
+ ErrorType ET;
+
+ /// The message which will be emitted, with %0, %1, ... placeholders for
+ /// arguments.
+ const char *Message;
+
+public:
+ /// Kinds of arguments, corresponding to members of \c Arg's union.
+ enum ArgKind {
+ AK_String, ///< A string argument, displayed as-is.
+ AK_TypeName,///< A C++ type name, possibly demangled before display.
+ AK_UInt, ///< An unsigned integer argument.
+ AK_SInt, ///< A signed integer argument.
+ AK_Float, ///< A floating-point argument.
+ AK_Pointer ///< A pointer argument, displayed in hexadecimal.
+ };
+
+ /// An individual diagnostic message argument.
+ struct Arg {
+ Arg() {}
+ Arg(const char *String) : Kind(AK_String), String(String) {}
+ Arg(TypeName TN) : Kind(AK_TypeName), String(TN.getName()) {}
+ Arg(UIntMax UInt) : Kind(AK_UInt), UInt(UInt) {}
+ Arg(SIntMax SInt) : Kind(AK_SInt), SInt(SInt) {}
+ Arg(FloatMax Float) : Kind(AK_Float), Float(Float) {}
+ Arg(const void *Pointer) : Kind(AK_Pointer), Pointer(Pointer) {}
+
+ ArgKind Kind;
+ union {
+ const char *String;
+ UIntMax UInt;
+ SIntMax SInt;
+ FloatMax Float;
+ const void *Pointer;
+ };
+ };
+
+private:
+ static const unsigned MaxArgs = 8;
+ static const unsigned MaxRanges = 1;
+
+ /// The arguments which have been added to this diagnostic so far.
+ Arg Args[MaxArgs];
+ unsigned NumArgs;
+
+ /// The ranges which have been added to this diagnostic so far.
+ Range Ranges[MaxRanges];
+ unsigned NumRanges;
+
+ Diag &AddArg(Arg A) {
+ CHECK(NumArgs != MaxArgs);
+ Args[NumArgs++] = A;
+ return *this;
+ }
+
+ Diag &AddRange(Range A) {
+ CHECK(NumRanges != MaxRanges);
+ Ranges[NumRanges++] = A;
+ return *this;
+ }
+
+ /// \c Diag objects are not copyable.
+ Diag(const Diag &); // NOT IMPLEMENTED
+ Diag &operator=(const Diag &);
+
+public:
+ Diag(Location Loc, DiagLevel Level, ErrorType ET, const char *Message)
+ : Loc(Loc), Level(Level), ET(ET), Message(Message), NumArgs(0),
+ NumRanges(0) {}
+ ~Diag();
+
+ Diag &operator<<(const char *Str) { return AddArg(Str); }
+ Diag &operator<<(TypeName TN) { return AddArg(TN); }
+ Diag &operator<<(unsigned long long V) { return AddArg(UIntMax(V)); }
+ Diag &operator<<(const void *V) { return AddArg(V); }
+ Diag &operator<<(const TypeDescriptor &V);
+ Diag &operator<<(const Value &V);
+ Diag &operator<<(const Range &R) { return AddRange(R); }
+};
+
+struct ReportOptions {
+ // If FromUnrecoverableHandler is specified, UBSan runtime handler is not
+ // expected to return.
+ bool FromUnrecoverableHandler;
+ /// pc/bp are used to unwind the stack trace.
+ uptr pc;
+ uptr bp;
+};
+
+bool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET);
+
+#define GET_REPORT_OPTIONS(unrecoverable_handler) \
+ GET_CALLER_PC_BP; \
+ ReportOptions Opts = {unrecoverable_handler, pc, bp}
+
+/// \brief Instantiate this class before printing diagnostics in the error
+/// report. This class ensures that reports from different threads and from
+/// different sanitizers won't be mixed.
+class ScopedReport {
+ struct Initializer {
+ Initializer();
+ };
+ Initializer initializer_;
+ ScopedErrorReportLock report_lock_;
+
+ ReportOptions Opts;
+ Location SummaryLoc;
+ ErrorType Type;
+
+public:
+ ScopedReport(ReportOptions Opts, Location SummaryLoc, ErrorType Type);
+ ~ScopedReport();
+
+ static void CheckLocked() { ScopedErrorReportLock::CheckLocked(); }
+};
+
+void InitializeSuppressions();
+bool IsVptrCheckSuppressed(const char *TypeName);
+// Sometimes UBSan runtime can know filename from handlers arguments, even if
+// debug info is missing.
+bool IsPCSuppressed(ErrorType ET, uptr PC, const char *Filename);
+
+} // namespace __ubsan
+
+#endif // UBSAN_DIAG_H
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_diag_standalone.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_diag_standalone.cpp
new file mode 100644
index 00000000000..5526ae05165
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_diag_standalone.cpp
@@ -0,0 +1,38 @@
+//===-- ubsan_diag_standalone.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Diagnostic reporting for the standalone UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
+#include "ubsan_diag.h"
+
+using namespace __ubsan;
+
+void __sanitizer::BufferedStackTrace::UnwindImpl(
+ uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
+ uptr top = 0;
+ uptr bottom = 0;
+ GetThreadStackTopAndBottom(false, &top, &bottom);
+ bool fast = StackTrace::WillUseFastUnwind(request_fast);
+ Unwind(max_depth, pc, bp, context, top, bottom, fast);
+}
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_print_stack_trace() {
+ GET_CURRENT_PC_BP;
+ BufferedStackTrace stack;
+ stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal);
+ stack.Print();
+}
+} // extern "C"
+
+#endif // CAN_SANITIZE_UB
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_flags.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_flags.cpp
new file mode 100644
index 00000000000..25cefd46ce2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_flags.cpp
@@ -0,0 +1,80 @@
+//===-- ubsan_flags.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Runtime flags for UndefinedBehaviorSanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
+#include "ubsan_flags.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+
+#include <stdlib.h>
+
+namespace __ubsan {
+
+static const char *GetFlag(const char *flag) {
+ // We cannot call getenv() from inside a preinit array initializer
+ if (SANITIZER_CAN_USE_PREINIT_ARRAY) {
+ return GetEnv(flag);
+ } else {
+ return getenv(flag);
+ }
+}
+
+Flags ubsan_flags;
+
+void Flags::SetDefaults() {
+#define UBSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "ubsan_flags.inc"
+#undef UBSAN_FLAG
+}
+
+void RegisterUbsanFlags(FlagParser *parser, Flags *f) {
+#define UBSAN_FLAG(Type, Name, DefaultValue, Description) \
+ RegisterFlag(parser, #Name, Description, &f->Name);
+#include "ubsan_flags.inc"
+#undef UBSAN_FLAG
+}
+
+void InitializeFlags() {
+ SetCommonFlagsDefaults();
+ {
+ CommonFlags cf;
+ cf.CopyFrom(*common_flags());
+ cf.external_symbolizer_path = GetFlag("UBSAN_SYMBOLIZER_PATH");
+ OverrideCommonFlags(cf);
+ }
+
+ Flags *f = flags();
+ f->SetDefaults();
+
+ FlagParser parser;
+ RegisterCommonFlags(&parser);
+ RegisterUbsanFlags(&parser, f);
+
+ // Override from user-specified string.
+ parser.ParseString(__ubsan_default_options());
+ // Override from environment variable.
+ parser.ParseStringFromEnv("UBSAN_OPTIONS");
+ InitializeCommonFlags();
+ if (Verbosity()) ReportUnrecognizedFlags();
+
+ if (common_flags()->help) parser.PrintFlagDescriptions();
+}
+
+} // namespace __ubsan
+
+SANITIZER_INTERFACE_WEAK_DEF(const char *, __ubsan_default_options, void) {
+ return "";
+}
+
+#endif // CAN_SANITIZE_UB
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_flags.h b/contrib/libs/clang16-rt/lib/ubsan/ubsan_flags.h
new file mode 100644
index 00000000000..c47009bafe5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_flags.h
@@ -0,0 +1,46 @@
+//===-- ubsan_flags.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Runtime flags for UndefinedBehaviorSanitizer.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_FLAGS_H
+#define UBSAN_FLAGS_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+class FlagParser;
+}
+
+namespace __ubsan {
+
+struct Flags {
+#define UBSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "ubsan_flags.inc"
+#undef UBSAN_FLAG
+
+ void SetDefaults();
+};
+
+extern Flags ubsan_flags;
+inline Flags *flags() { return &ubsan_flags; }
+
+void InitializeFlags();
+void RegisterUbsanFlags(FlagParser *parser, Flags *f);
+
+} // namespace __ubsan
+
+extern "C" {
+// Users may provide their own implementation of __ubsan_default_options to
+// override the default flag values.
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+const char *__ubsan_default_options();
+} // extern "C"
+
+#endif // UBSAN_FLAGS_H
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_flags.inc b/contrib/libs/clang16-rt/lib/ubsan/ubsan_flags.inc
new file mode 100644
index 00000000000..a4d0e6109e3
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_flags.inc
@@ -0,0 +1,28 @@
+//===-- ubsan_flags.inc -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// UBSan runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_FLAG
+# error "Define UBSAN_FLAG prior to including this file!"
+#endif
+
+// UBSAN_FLAG(Type, Name, DefaultValue, Description)
+// See COMMON_FLAG in sanitizer_flags.inc for more details.
+
+UBSAN_FLAG(bool, halt_on_error, false,
+ "Crash the program after printing the first error report")
+UBSAN_FLAG(bool, print_stacktrace, false,
+ "Include full stacktrace into an error report")
+UBSAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
+UBSAN_FLAG(bool, report_error_type, false,
+ "Print specific error type instead of 'undefined-behavior' in summary.")
+UBSAN_FLAG(bool, silence_unsigned_overflow, false,
+ "Do not print non-fatal error reports for unsigned integer overflow. "
+ "Used to provide fuzzing signal without blowing up logs.")
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers.cpp
new file mode 100644
index 00000000000..410292a0d53
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers.cpp
@@ -0,0 +1,918 @@
+//===-- ubsan_handlers.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Error logging entry points for the UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
+#include "ubsan_handlers.h"
+#include "ubsan_diag.h"
+#include "ubsan_flags.h"
+#include "ubsan_monitor.h"
+#include "ubsan_value.h"
+
+#include "sanitizer_common/sanitizer_common.h"
+
+using namespace __sanitizer;
+using namespace __ubsan;
+
+namespace __ubsan {
+bool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET) {
+ // We are not allowed to skip error report: if we are in unrecoverable
+ // handler, we have to terminate the program right now, and therefore
+ // have to print some diagnostic.
+ //
+ // Even if source location is disabled, it doesn't mean that we have
+ // already report an error to the user: some concurrently running
+ // thread could have acquired it, but not yet printed the report.
+ if (Opts.FromUnrecoverableHandler)
+ return false;
+ return SLoc.isDisabled() || IsPCSuppressed(ET, Opts.pc, SLoc.getFilename());
+}
+
+/// Situations in which we might emit a check for the suitability of a
+/// pointer or glvalue. Needs to be kept in sync with CodeGenFunction.h in
+/// clang.
+enum TypeCheckKind {
+ /// Checking the operand of a load. Must be suitably sized and aligned.
+ TCK_Load,
+ /// Checking the destination of a store. Must be suitably sized and aligned.
+ TCK_Store,
+ /// Checking the bound value in a reference binding. Must be suitably sized
+ /// and aligned, but is not required to refer to an object (until the
+ /// reference is used), per core issue 453.
+ TCK_ReferenceBinding,
+ /// Checking the object expression in a non-static data member access. Must
+ /// be an object within its lifetime.
+ TCK_MemberAccess,
+ /// Checking the 'this' pointer for a call to a non-static member function.
+ /// Must be an object within its lifetime.
+ TCK_MemberCall,
+ /// Checking the 'this' pointer for a constructor call.
+ TCK_ConstructorCall,
+ /// Checking the operand of a static_cast to a derived pointer type. Must be
+ /// null or an object within its lifetime.
+ TCK_DowncastPointer,
+ /// Checking the operand of a static_cast to a derived reference type. Must
+ /// be an object within its lifetime.
+ TCK_DowncastReference,
+ /// Checking the operand of a cast to a base object. Must be suitably sized
+ /// and aligned.
+ TCK_Upcast,
+ /// Checking the operand of a cast to a virtual base object. Must be an
+ /// object within its lifetime.
+ TCK_UpcastToVirtualBase,
+ /// Checking the value assigned to a _Nonnull pointer. Must not be null.
+ TCK_NonnullAssign,
+ /// Checking the operand of a dynamic_cast or a typeid expression. Must be
+ /// null or an object within its lifetime.
+ TCK_DynamicOperation
+};
+
+extern const char *const TypeCheckKinds[] = {
+ "load of", "store to", "reference binding to", "member access within",
+ "member call on", "constructor call on", "downcast of", "downcast of",
+ "upcast of", "cast to virtual base of", "_Nonnull binding to",
+ "dynamic operation on"};
+}
+
+static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
+ ReportOptions Opts) {
+ Location Loc = Data->Loc.acquire();
+
+ uptr Alignment = (uptr)1 << Data->LogAlignment;
+ ErrorType ET;
+ if (!Pointer)
+ ET = (Data->TypeCheckKind == TCK_NonnullAssign)
+ ? ErrorType::NullPointerUseWithNullability
+ : ErrorType::NullPointerUse;
+ else if (Pointer & (Alignment - 1))
+ ET = ErrorType::MisalignedPointerUse;
+ else
+ ET = ErrorType::InsufficientObjectSize;
+
+ // Use the SourceLocation from Data to track deduplication, even if it's
+ // invalid.
+ if (ignoreReport(Loc.getSourceLocation(), Opts, ET))
+ return;
+
+ SymbolizedStackHolder FallbackLoc;
+ if (Data->Loc.isInvalid()) {
+ FallbackLoc.reset(getCallerLocation(Opts.pc));
+ Loc = FallbackLoc;
+ }
+
+ ScopedReport R(Opts, Loc, ET);
+
+ switch (ET) {
+ case ErrorType::NullPointerUse:
+ case ErrorType::NullPointerUseWithNullability:
+ Diag(Loc, DL_Error, ET, "%0 null pointer of type %1")
+ << TypeCheckKinds[Data->TypeCheckKind] << Data->Type;
+ break;
+ case ErrorType::MisalignedPointerUse:
+ Diag(Loc, DL_Error, ET, "%0 misaligned address %1 for type %3, "
+ "which requires %2 byte alignment")
+ << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Alignment
+ << Data->Type;
+ break;
+ case ErrorType::InsufficientObjectSize:
+ Diag(Loc, DL_Error, ET, "%0 address %1 with insufficient space "
+ "for an object of type %2")
+ << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Data->Type;
+ break;
+ default:
+ UNREACHABLE("unexpected error type!");
+ }
+
+ if (Pointer)
+ Diag(Pointer, DL_Note, ET, "pointer points here");
+}
+
+void __ubsan::__ubsan_handle_type_mismatch_v1(TypeMismatchData *Data,
+ ValueHandle Pointer) {
+ GET_REPORT_OPTIONS(false);
+ handleTypeMismatchImpl(Data, Pointer, Opts);
+}
+void __ubsan::__ubsan_handle_type_mismatch_v1_abort(TypeMismatchData *Data,
+ ValueHandle Pointer) {
+ GET_REPORT_OPTIONS(true);
+ handleTypeMismatchImpl(Data, Pointer, Opts);
+ Die();
+}
+
+static void handleAlignmentAssumptionImpl(AlignmentAssumptionData *Data,
+ ValueHandle Pointer,
+ ValueHandle Alignment,
+ ValueHandle Offset,
+ ReportOptions Opts) {
+ Location Loc = Data->Loc.acquire();
+ SourceLocation AssumptionLoc = Data->AssumptionLoc.acquire();
+
+ ErrorType ET = ErrorType::AlignmentAssumption;
+
+ if (ignoreReport(Loc.getSourceLocation(), Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ uptr RealPointer = Pointer - Offset;
+ uptr LSB = LeastSignificantSetBitIndex(RealPointer);
+ uptr ActualAlignment = uptr(1) << LSB;
+
+ uptr Mask = Alignment - 1;
+ uptr MisAlignmentOffset = RealPointer & Mask;
+
+ if (!Offset) {
+ Diag(Loc, DL_Error, ET,
+ "assumption of %0 byte alignment for pointer of type %1 failed")
+ << Alignment << Data->Type;
+ } else {
+ Diag(Loc, DL_Error, ET,
+ "assumption of %0 byte alignment (with offset of %1 byte) for pointer "
+ "of type %2 failed")
+ << Alignment << Offset << Data->Type;
+ }
+
+ if (!AssumptionLoc.isInvalid())
+ Diag(AssumptionLoc, DL_Note, ET, "alignment assumption was specified here");
+
+ Diag(RealPointer, DL_Note, ET,
+ "%0address is %1 aligned, misalignment offset is %2 bytes")
+ << (Offset ? "offset " : "") << ActualAlignment << MisAlignmentOffset;
+}
+
+void __ubsan::__ubsan_handle_alignment_assumption(AlignmentAssumptionData *Data,
+ ValueHandle Pointer,
+ ValueHandle Alignment,
+ ValueHandle Offset) {
+ GET_REPORT_OPTIONS(false);
+ handleAlignmentAssumptionImpl(Data, Pointer, Alignment, Offset, Opts);
+}
+void __ubsan::__ubsan_handle_alignment_assumption_abort(
+ AlignmentAssumptionData *Data, ValueHandle Pointer, ValueHandle Alignment,
+ ValueHandle Offset) {
+ GET_REPORT_OPTIONS(true);
+ handleAlignmentAssumptionImpl(Data, Pointer, Alignment, Offset, Opts);
+ Die();
+}
+
+/// \brief Common diagnostic emission for various forms of integer overflow.
+template <typename T>
+static void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS,
+ const char *Operator, T RHS,
+ ReportOptions Opts) {
+ SourceLocation Loc = Data->Loc.acquire();
+ bool IsSigned = Data->Type.isSignedIntegerTy();
+ ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow
+ : ErrorType::UnsignedIntegerOverflow;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ // If this is an unsigned overflow in non-fatal mode, potentially ignore it.
+ if (!IsSigned && !Opts.FromUnrecoverableHandler &&
+ flags()->silence_unsigned_overflow)
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ Diag(Loc, DL_Error, ET, "%0 integer overflow: "
+ "%1 %2 %3 cannot be represented in type %4")
+ << (IsSigned ? "signed" : "unsigned") << Value(Data->Type, LHS)
+ << Operator << RHS << Data->Type;
+}
+
+#define UBSAN_OVERFLOW_HANDLER(handler_name, op, unrecoverable) \
+ void __ubsan::handler_name(OverflowData *Data, ValueHandle LHS, \
+ ValueHandle RHS) { \
+ GET_REPORT_OPTIONS(unrecoverable); \
+ handleIntegerOverflowImpl(Data, LHS, op, Value(Data->Type, RHS), Opts); \
+ if (unrecoverable) \
+ Die(); \
+ }
+
+UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow, "+", false)
+UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow_abort, "+", true)
+UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow, "-", false)
+UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow_abort, "-", true)
+UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow, "*", false)
+UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow_abort, "*", true)
+
+static void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal,
+ ReportOptions Opts) {
+ SourceLocation Loc = Data->Loc.acquire();
+ bool IsSigned = Data->Type.isSignedIntegerTy();
+ ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow
+ : ErrorType::UnsignedIntegerOverflow;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ if (!IsSigned && flags()->silence_unsigned_overflow)
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ if (IsSigned)
+ Diag(Loc, DL_Error, ET,
+ "negation of %0 cannot be represented in type %1; "
+ "cast to an unsigned type to negate this value to itself")
+ << Value(Data->Type, OldVal) << Data->Type;
+ else
+ Diag(Loc, DL_Error, ET, "negation of %0 cannot be represented in type %1")
+ << Value(Data->Type, OldVal) << Data->Type;
+}
+
+void __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data,
+ ValueHandle OldVal) {
+ GET_REPORT_OPTIONS(false);
+ handleNegateOverflowImpl(Data, OldVal, Opts);
+}
+void __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data,
+ ValueHandle OldVal) {
+ GET_REPORT_OPTIONS(true);
+ handleNegateOverflowImpl(Data, OldVal, Opts);
+ Die();
+}
+
+static void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS,
+ ValueHandle RHS, ReportOptions Opts) {
+ SourceLocation Loc = Data->Loc.acquire();
+ Value LHSVal(Data->Type, LHS);
+ Value RHSVal(Data->Type, RHS);
+
+ ErrorType ET;
+ if (RHSVal.isMinusOne())
+ ET = ErrorType::SignedIntegerOverflow;
+ else if (Data->Type.isIntegerTy())
+ ET = ErrorType::IntegerDivideByZero;
+ else
+ ET = ErrorType::FloatDivideByZero;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ switch (ET) {
+ case ErrorType::SignedIntegerOverflow:
+ Diag(Loc, DL_Error, ET,
+ "division of %0 by -1 cannot be represented in type %1")
+ << LHSVal << Data->Type;
+ break;
+ default:
+ Diag(Loc, DL_Error, ET, "division by zero");
+ break;
+ }
+}
+
+void __ubsan::__ubsan_handle_divrem_overflow(OverflowData *Data,
+ ValueHandle LHS, ValueHandle RHS) {
+ GET_REPORT_OPTIONS(false);
+ handleDivremOverflowImpl(Data, LHS, RHS, Opts);
+}
+void __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data,
+ ValueHandle LHS,
+ ValueHandle RHS) {
+ GET_REPORT_OPTIONS(true);
+ handleDivremOverflowImpl(Data, LHS, RHS, Opts);
+ Die();
+}
+
+static void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data,
+ ValueHandle LHS, ValueHandle RHS,
+ ReportOptions Opts) {
+ SourceLocation Loc = Data->Loc.acquire();
+ Value LHSVal(Data->LHSType, LHS);
+ Value RHSVal(Data->RHSType, RHS);
+
+ ErrorType ET;
+ if (RHSVal.isNegative() ||
+ RHSVal.getPositiveIntValue() >= Data->LHSType.getIntegerBitWidth())
+ ET = ErrorType::InvalidShiftExponent;
+ else
+ ET = ErrorType::InvalidShiftBase;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ if (ET == ErrorType::InvalidShiftExponent) {
+ if (RHSVal.isNegative())
+ Diag(Loc, DL_Error, ET, "shift exponent %0 is negative") << RHSVal;
+ else
+ Diag(Loc, DL_Error, ET,
+ "shift exponent %0 is too large for %1-bit type %2")
+ << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType;
+ } else {
+ if (LHSVal.isNegative())
+ Diag(Loc, DL_Error, ET, "left shift of negative value %0") << LHSVal;
+ else
+ Diag(Loc, DL_Error, ET,
+ "left shift of %0 by %1 places cannot be represented in type %2")
+ << LHSVal << RHSVal << Data->LHSType;
+ }
+}
+
+void __ubsan::__ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data,
+ ValueHandle LHS,
+ ValueHandle RHS) {
+ GET_REPORT_OPTIONS(false);
+ handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
+}
+void __ubsan::__ubsan_handle_shift_out_of_bounds_abort(
+ ShiftOutOfBoundsData *Data,
+ ValueHandle LHS,
+ ValueHandle RHS) {
+ GET_REPORT_OPTIONS(true);
+ handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
+ Die();
+}
+
+static void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index,
+ ReportOptions Opts) {
+ SourceLocation Loc = Data->Loc.acquire();
+ ErrorType ET = ErrorType::OutOfBoundsIndex;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ Value IndexVal(Data->IndexType, Index);
+ Diag(Loc, DL_Error, ET, "index %0 out of bounds for type %1")
+ << IndexVal << Data->ArrayType;
+}
+
+void __ubsan::__ubsan_handle_out_of_bounds(OutOfBoundsData *Data,
+ ValueHandle Index) {
+ GET_REPORT_OPTIONS(false);
+ handleOutOfBoundsImpl(Data, Index, Opts);
+}
+void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data,
+ ValueHandle Index) {
+ GET_REPORT_OPTIONS(true);
+ handleOutOfBoundsImpl(Data, Index, Opts);
+ Die();
+}
+
+static void handleBuiltinUnreachableImpl(UnreachableData *Data,
+ ReportOptions Opts) {
+ ErrorType ET = ErrorType::UnreachableCall;
+ ScopedReport R(Opts, Data->Loc, ET);
+ Diag(Data->Loc, DL_Error, ET,
+ "execution reached an unreachable program point");
+}
+
+void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) {
+ GET_REPORT_OPTIONS(true);
+ handleBuiltinUnreachableImpl(Data, Opts);
+ Die();
+}
+
+static void handleMissingReturnImpl(UnreachableData *Data, ReportOptions Opts) {
+ ErrorType ET = ErrorType::MissingReturn;
+ ScopedReport R(Opts, Data->Loc, ET);
+ Diag(Data->Loc, DL_Error, ET,
+ "execution reached the end of a value-returning function "
+ "without returning a value");
+}
+
+void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) {
+ GET_REPORT_OPTIONS(true);
+ handleMissingReturnImpl(Data, Opts);
+ Die();
+}
+
+static void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound,
+ ReportOptions Opts) {
+ SourceLocation Loc = Data->Loc.acquire();
+ ErrorType ET = ErrorType::NonPositiveVLAIndex;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ Diag(Loc, DL_Error, ET, "variable length array bound evaluates to "
+ "non-positive value %0")
+ << Value(Data->Type, Bound);
+}
+
+void __ubsan::__ubsan_handle_vla_bound_not_positive(VLABoundData *Data,
+ ValueHandle Bound) {
+ GET_REPORT_OPTIONS(false);
+ handleVLABoundNotPositive(Data, Bound, Opts);
+}
+void __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data,
+ ValueHandle Bound) {
+ GET_REPORT_OPTIONS(true);
+ handleVLABoundNotPositive(Data, Bound, Opts);
+ Die();
+}
+
+static bool looksLikeFloatCastOverflowDataV1(void *Data) {
+ // First field is either a pointer to filename or a pointer to a
+ // TypeDescriptor.
+ u8 *FilenameOrTypeDescriptor;
+ internal_memcpy(&FilenameOrTypeDescriptor, Data,
+ sizeof(FilenameOrTypeDescriptor));
+
+ // Heuristic: For float_cast_overflow, the TypeKind will be either TK_Integer
+ // (0x0), TK_Float (0x1) or TK_Unknown (0xff). If both types are known,
+ // adding both bytes will be 0 or 1 (for BE or LE). If it were a filename,
+ // adding two printable characters will not yield such a value. Otherwise,
+ // if one of them is 0xff, this is most likely TK_Unknown type descriptor.
+ u16 MaybeFromTypeKind =
+ FilenameOrTypeDescriptor[0] + FilenameOrTypeDescriptor[1];
+ return MaybeFromTypeKind < 2 || FilenameOrTypeDescriptor[0] == 0xff ||
+ FilenameOrTypeDescriptor[1] == 0xff;
+}
+
+static void handleFloatCastOverflow(void *DataPtr, ValueHandle From,
+ ReportOptions Opts) {
+ SymbolizedStackHolder CallerLoc;
+ Location Loc;
+ const TypeDescriptor *FromType, *ToType;
+ ErrorType ET = ErrorType::FloatCastOverflow;
+
+ if (looksLikeFloatCastOverflowDataV1(DataPtr)) {
+ auto Data = reinterpret_cast<FloatCastOverflowData *>(DataPtr);
+ CallerLoc.reset(getCallerLocation(Opts.pc));
+ Loc = CallerLoc;
+ FromType = &Data->FromType;
+ ToType = &Data->ToType;
+ } else {
+ auto Data = reinterpret_cast<FloatCastOverflowDataV2 *>(DataPtr);
+ SourceLocation SLoc = Data->Loc.acquire();
+ if (ignoreReport(SLoc, Opts, ET))
+ return;
+ Loc = SLoc;
+ FromType = &Data->FromType;
+ ToType = &Data->ToType;
+ }
+
+ ScopedReport R(Opts, Loc, ET);
+
+ Diag(Loc, DL_Error, ET,
+ "%0 is outside the range of representable values of type %2")
+ << Value(*FromType, From) << *FromType << *ToType;
+}
+
+void __ubsan::__ubsan_handle_float_cast_overflow(void *Data, ValueHandle From) {
+ GET_REPORT_OPTIONS(false);
+ handleFloatCastOverflow(Data, From, Opts);
+}
+void __ubsan::__ubsan_handle_float_cast_overflow_abort(void *Data,
+ ValueHandle From) {
+ GET_REPORT_OPTIONS(true);
+ handleFloatCastOverflow(Data, From, Opts);
+ Die();
+}
+
+static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val,
+ ReportOptions Opts) {
+ SourceLocation Loc = Data->Loc.acquire();
+ // This check could be more precise if we used different handlers for
+ // -fsanitize=bool and -fsanitize=enum.
+ bool IsBool = (0 == internal_strcmp(Data->Type.getTypeName(), "'bool'")) ||
+ (0 == internal_strncmp(Data->Type.getTypeName(), "'BOOL'", 6));
+ ErrorType ET =
+ IsBool ? ErrorType::InvalidBoolLoad : ErrorType::InvalidEnumLoad;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ Diag(Loc, DL_Error, ET,
+ "load of value %0, which is not a valid value for type %1")
+ << Value(Data->Type, Val) << Data->Type;
+}
+
+void __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data,
+ ValueHandle Val) {
+ GET_REPORT_OPTIONS(false);
+ handleLoadInvalidValue(Data, Val, Opts);
+}
+void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data,
+ ValueHandle Val) {
+ GET_REPORT_OPTIONS(true);
+ handleLoadInvalidValue(Data, Val, Opts);
+ Die();
+}
+
+static void handleImplicitConversion(ImplicitConversionData *Data,
+ ReportOptions Opts, ValueHandle Src,
+ ValueHandle Dst) {
+ SourceLocation Loc = Data->Loc.acquire();
+ ErrorType ET = ErrorType::GenericUB;
+
+ const TypeDescriptor &SrcTy = Data->FromType;
+ const TypeDescriptor &DstTy = Data->ToType;
+
+ bool SrcSigned = SrcTy.isSignedIntegerTy();
+ bool DstSigned = DstTy.isSignedIntegerTy();
+
+ switch (Data->Kind) {
+ case ICCK_IntegerTruncation: { // Legacy, no longer used.
+ // Let's figure out what it should be as per the new types, and upgrade.
+ // If both types are unsigned, then it's an unsigned truncation.
+ // Else, it is a signed truncation.
+ if (!SrcSigned && !DstSigned) {
+ ET = ErrorType::ImplicitUnsignedIntegerTruncation;
+ } else {
+ ET = ErrorType::ImplicitSignedIntegerTruncation;
+ }
+ break;
+ }
+ case ICCK_UnsignedIntegerTruncation:
+ ET = ErrorType::ImplicitUnsignedIntegerTruncation;
+ break;
+ case ICCK_SignedIntegerTruncation:
+ ET = ErrorType::ImplicitSignedIntegerTruncation;
+ break;
+ case ICCK_IntegerSignChange:
+ ET = ErrorType::ImplicitIntegerSignChange;
+ break;
+ case ICCK_SignedIntegerTruncationOrSignChange:
+ ET = ErrorType::ImplicitSignedIntegerTruncationOrSignChange;
+ break;
+ }
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ // FIXME: is it possible to dump the values as hex with fixed width?
+
+ Diag(Loc, DL_Error, ET,
+ "implicit conversion from type %0 of value %1 (%2-bit, %3signed) to "
+ "type %4 changed the value to %5 (%6-bit, %7signed)")
+ << SrcTy << Value(SrcTy, Src) << SrcTy.getIntegerBitWidth()
+ << (SrcSigned ? "" : "un") << DstTy << Value(DstTy, Dst)
+ << DstTy.getIntegerBitWidth() << (DstSigned ? "" : "un");
+}
+
+void __ubsan::__ubsan_handle_implicit_conversion(ImplicitConversionData *Data,
+ ValueHandle Src,
+ ValueHandle Dst) {
+ GET_REPORT_OPTIONS(false);
+ handleImplicitConversion(Data, Opts, Src, Dst);
+}
+void __ubsan::__ubsan_handle_implicit_conversion_abort(
+ ImplicitConversionData *Data, ValueHandle Src, ValueHandle Dst) {
+ GET_REPORT_OPTIONS(true);
+ handleImplicitConversion(Data, Opts, Src, Dst);
+ Die();
+}
+
+static void handleInvalidBuiltin(InvalidBuiltinData *Data, ReportOptions Opts) {
+ SourceLocation Loc = Data->Loc.acquire();
+ ErrorType ET = ErrorType::InvalidBuiltin;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ Diag(Loc, DL_Error, ET,
+ "passing zero to %0, which is not a valid argument")
+ << ((Data->Kind == BCK_CTZPassedZero) ? "ctz()" : "clz()");
+}
+
+void __ubsan::__ubsan_handle_invalid_builtin(InvalidBuiltinData *Data) {
+ GET_REPORT_OPTIONS(true);
+ handleInvalidBuiltin(Data, Opts);
+}
+void __ubsan::__ubsan_handle_invalid_builtin_abort(InvalidBuiltinData *Data) {
+ GET_REPORT_OPTIONS(true);
+ handleInvalidBuiltin(Data, Opts);
+ Die();
+}
+
+static void handleInvalidObjCCast(InvalidObjCCast *Data, ValueHandle Pointer,
+ ReportOptions Opts) {
+ SourceLocation Loc = Data->Loc.acquire();
+ ErrorType ET = ErrorType::InvalidObjCCast;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ const char *GivenClass = getObjCClassName(Pointer);
+ const char *GivenClassStr = GivenClass ? GivenClass : "<unknown type>";
+
+ Diag(Loc, DL_Error, ET,
+ "invalid ObjC cast, object is a '%0', but expected a %1")
+ << GivenClassStr << Data->ExpectedType;
+}
+
+void __ubsan::__ubsan_handle_invalid_objc_cast(InvalidObjCCast *Data,
+ ValueHandle Pointer) {
+ GET_REPORT_OPTIONS(false);
+ handleInvalidObjCCast(Data, Pointer, Opts);
+}
+void __ubsan::__ubsan_handle_invalid_objc_cast_abort(InvalidObjCCast *Data,
+ ValueHandle Pointer) {
+ GET_REPORT_OPTIONS(true);
+ handleInvalidObjCCast(Data, Pointer, Opts);
+ Die();
+}
+
+static void handleNonNullReturn(NonNullReturnData *Data, SourceLocation *LocPtr,
+ ReportOptions Opts, bool IsAttr) {
+ if (!LocPtr)
+ UNREACHABLE("source location pointer is null!");
+
+ SourceLocation Loc = LocPtr->acquire();
+ ErrorType ET = IsAttr ? ErrorType::InvalidNullReturn
+ : ErrorType::InvalidNullReturnWithNullability;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ Diag(Loc, DL_Error, ET,
+ "null pointer returned from function declared to never return null");
+ if (!Data->AttrLoc.isInvalid())
+ Diag(Data->AttrLoc, DL_Note, ET, "%0 specified here")
+ << (IsAttr ? "returns_nonnull attribute"
+ : "_Nonnull return type annotation");
+}
+
+void __ubsan::__ubsan_handle_nonnull_return_v1(NonNullReturnData *Data,
+ SourceLocation *LocPtr) {
+ GET_REPORT_OPTIONS(false);
+ handleNonNullReturn(Data, LocPtr, Opts, true);
+}
+
+void __ubsan::__ubsan_handle_nonnull_return_v1_abort(NonNullReturnData *Data,
+ SourceLocation *LocPtr) {
+ GET_REPORT_OPTIONS(true);
+ handleNonNullReturn(Data, LocPtr, Opts, true);
+ Die();
+}
+
+void __ubsan::__ubsan_handle_nullability_return_v1(NonNullReturnData *Data,
+ SourceLocation *LocPtr) {
+ GET_REPORT_OPTIONS(false);
+ handleNonNullReturn(Data, LocPtr, Opts, false);
+}
+
+void __ubsan::__ubsan_handle_nullability_return_v1_abort(
+ NonNullReturnData *Data, SourceLocation *LocPtr) {
+ GET_REPORT_OPTIONS(true);
+ handleNonNullReturn(Data, LocPtr, Opts, false);
+ Die();
+}
+
+static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts,
+ bool IsAttr) {
+ SourceLocation Loc = Data->Loc.acquire();
+ ErrorType ET = IsAttr ? ErrorType::InvalidNullArgument
+ : ErrorType::InvalidNullArgumentWithNullability;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ Diag(Loc, DL_Error, ET,
+ "null pointer passed as argument %0, which is declared to "
+ "never be null")
+ << Data->ArgIndex;
+ if (!Data->AttrLoc.isInvalid())
+ Diag(Data->AttrLoc, DL_Note, ET, "%0 specified here")
+ << (IsAttr ? "nonnull attribute" : "_Nonnull type annotation");
+}
+
+void __ubsan::__ubsan_handle_nonnull_arg(NonNullArgData *Data) {
+ GET_REPORT_OPTIONS(false);
+ handleNonNullArg(Data, Opts, true);
+}
+
+void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) {
+ GET_REPORT_OPTIONS(true);
+ handleNonNullArg(Data, Opts, true);
+ Die();
+}
+
+void __ubsan::__ubsan_handle_nullability_arg(NonNullArgData *Data) {
+ GET_REPORT_OPTIONS(false);
+ handleNonNullArg(Data, Opts, false);
+}
+
+void __ubsan::__ubsan_handle_nullability_arg_abort(NonNullArgData *Data) {
+ GET_REPORT_OPTIONS(true);
+ handleNonNullArg(Data, Opts, false);
+ Die();
+}
+
+static void handlePointerOverflowImpl(PointerOverflowData *Data,
+ ValueHandle Base,
+ ValueHandle Result,
+ ReportOptions Opts) {
+ SourceLocation Loc = Data->Loc.acquire();
+ ErrorType ET;
+
+ if (Base == 0 && Result == 0)
+ ET = ErrorType::NullptrWithOffset;
+ else if (Base == 0 && Result != 0)
+ ET = ErrorType::NullptrWithNonZeroOffset;
+ else if (Base != 0 && Result == 0)
+ ET = ErrorType::NullptrAfterNonZeroOffset;
+ else
+ ET = ErrorType::PointerOverflow;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ if (ET == ErrorType::NullptrWithOffset) {
+ Diag(Loc, DL_Error, ET, "applying zero offset to null pointer");
+ } else if (ET == ErrorType::NullptrWithNonZeroOffset) {
+ Diag(Loc, DL_Error, ET, "applying non-zero offset %0 to null pointer")
+ << Result;
+ } else if (ET == ErrorType::NullptrAfterNonZeroOffset) {
+ Diag(
+ Loc, DL_Error, ET,
+ "applying non-zero offset to non-null pointer %0 produced null pointer")
+ << (void *)Base;
+ } else if ((sptr(Base) >= 0) == (sptr(Result) >= 0)) {
+ if (Base > Result)
+ Diag(Loc, DL_Error, ET,
+ "addition of unsigned offset to %0 overflowed to %1")
+ << (void *)Base << (void *)Result;
+ else
+ Diag(Loc, DL_Error, ET,
+ "subtraction of unsigned offset from %0 overflowed to %1")
+ << (void *)Base << (void *)Result;
+ } else {
+ Diag(Loc, DL_Error, ET,
+ "pointer index expression with base %0 overflowed to %1")
+ << (void *)Base << (void *)Result;
+ }
+}
+
+void __ubsan::__ubsan_handle_pointer_overflow(PointerOverflowData *Data,
+ ValueHandle Base,
+ ValueHandle Result) {
+ GET_REPORT_OPTIONS(false);
+ handlePointerOverflowImpl(Data, Base, Result, Opts);
+}
+
+void __ubsan::__ubsan_handle_pointer_overflow_abort(PointerOverflowData *Data,
+ ValueHandle Base,
+ ValueHandle Result) {
+ GET_REPORT_OPTIONS(true);
+ handlePointerOverflowImpl(Data, Base, Result, Opts);
+ Die();
+}
+
+static void handleCFIBadIcall(CFICheckFailData *Data, ValueHandle Function,
+ ReportOptions Opts) {
+ if (Data->CheckKind != CFITCK_ICall && Data->CheckKind != CFITCK_NVMFCall)
+ Die();
+
+ SourceLocation Loc = Data->Loc.acquire();
+ ErrorType ET = ErrorType::CFIBadType;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ const char *CheckKindStr = Data->CheckKind == CFITCK_NVMFCall
+ ? "non-virtual pointer to member function call"
+ : "indirect function call";
+ Diag(Loc, DL_Error, ET,
+ "control flow integrity check for type %0 failed during %1")
+ << Data->Type << CheckKindStr;
+
+ SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
+ const char *FName = FLoc.get()->info.function;
+ if (!FName)
+ FName = "(unknown)";
+ Diag(FLoc, DL_Note, ET, "%0 defined here") << FName;
+
+ // If the failure involved different DSOs for the check location and icall
+ // target, report the DSO names.
+ const char *DstModule = FLoc.get()->info.module;
+ if (!DstModule)
+ DstModule = "(unknown)";
+
+ const char *SrcModule = Symbolizer::GetOrInit()->GetModuleNameForPc(Opts.pc);
+ if (!SrcModule)
+ SrcModule = "(unknown)";
+
+ if (internal_strcmp(SrcModule, DstModule))
+ Diag(Loc, DL_Note, ET,
+ "check failed in %0, destination function located in %1")
+ << SrcModule << DstModule;
+}
+
+namespace __ubsan {
+
+#ifdef UBSAN_CAN_USE_CXXABI
+
+#ifdef _WIN32
+
+extern "C" void __ubsan_handle_cfi_bad_type_default(CFICheckFailData *Data,
+ ValueHandle Vtable,
+ bool ValidVtable,
+ ReportOptions Opts) {
+ Die();
+}
+
+WIN_WEAK_ALIAS(__ubsan_handle_cfi_bad_type, __ubsan_handle_cfi_bad_type_default)
+#else
+SANITIZER_WEAK_ATTRIBUTE
+#endif
+void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
+ bool ValidVtable, ReportOptions Opts);
+
+#else
+void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
+ bool ValidVtable, ReportOptions Opts) {
+ Die();
+}
+#endif
+
+} // namespace __ubsan
+
+void __ubsan::__ubsan_handle_cfi_check_fail(CFICheckFailData *Data,
+ ValueHandle Value,
+ uptr ValidVtable) {
+ GET_REPORT_OPTIONS(false);
+ if (Data->CheckKind == CFITCK_ICall || Data->CheckKind == CFITCK_NVMFCall)
+ handleCFIBadIcall(Data, Value, Opts);
+ else
+ __ubsan_handle_cfi_bad_type(Data, Value, ValidVtable, Opts);
+}
+
+void __ubsan::__ubsan_handle_cfi_check_fail_abort(CFICheckFailData *Data,
+ ValueHandle Value,
+ uptr ValidVtable) {
+ GET_REPORT_OPTIONS(true);
+ if (Data->CheckKind == CFITCK_ICall || Data->CheckKind == CFITCK_NVMFCall)
+ handleCFIBadIcall(Data, Value, Opts);
+ else
+ __ubsan_handle_cfi_bad_type(Data, Value, ValidVtable, Opts);
+ Die();
+}
+
+#endif // CAN_SANITIZE_UB
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers.h b/contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers.h
new file mode 100644
index 00000000000..219fb15de55
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers.h
@@ -0,0 +1,236 @@
+//===-- ubsan_handlers.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Entry points to the runtime library for Clang's undefined behavior sanitizer.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_HANDLERS_H
+#define UBSAN_HANDLERS_H
+
+#include "ubsan_value.h"
+
+namespace __ubsan {
+
+struct TypeMismatchData {
+ SourceLocation Loc;
+ const TypeDescriptor &Type;
+ unsigned char LogAlignment;
+ unsigned char TypeCheckKind;
+};
+
+#define UNRECOVERABLE(checkname, ...) \
+ extern "C" SANITIZER_INTERFACE_ATTRIBUTE NORETURN \
+ void __ubsan_handle_ ## checkname( __VA_ARGS__ );
+
+#define RECOVERABLE(checkname, ...) \
+ extern "C" SANITIZER_INTERFACE_ATTRIBUTE \
+ void __ubsan_handle_ ## checkname( __VA_ARGS__ ); \
+ extern "C" SANITIZER_INTERFACE_ATTRIBUTE NORETURN \
+ void __ubsan_handle_ ## checkname ## _abort( __VA_ARGS__ );
+
+/// \brief Handle a runtime type check failure, caused by either a misaligned
+/// pointer, a null pointer, or a pointer to insufficient storage for the
+/// type.
+RECOVERABLE(type_mismatch_v1, TypeMismatchData *Data, ValueHandle Pointer)
+
+struct AlignmentAssumptionData {
+ SourceLocation Loc;
+ SourceLocation AssumptionLoc;
+ const TypeDescriptor &Type;
+};
+
+/// \brief Handle a runtime alignment assumption check failure,
+/// caused by a misaligned pointer.
+RECOVERABLE(alignment_assumption, AlignmentAssumptionData *Data,
+ ValueHandle Pointer, ValueHandle Alignment, ValueHandle Offset)
+
+struct OverflowData {
+ SourceLocation Loc;
+ const TypeDescriptor &Type;
+};
+
+/// \brief Handle an integer addition overflow.
+RECOVERABLE(add_overflow, OverflowData *Data, ValueHandle LHS, ValueHandle RHS)
+
+/// \brief Handle an integer subtraction overflow.
+RECOVERABLE(sub_overflow, OverflowData *Data, ValueHandle LHS, ValueHandle RHS)
+
+/// \brief Handle an integer multiplication overflow.
+RECOVERABLE(mul_overflow, OverflowData *Data, ValueHandle LHS, ValueHandle RHS)
+
+/// \brief Handle a signed integer overflow for a unary negate operator.
+RECOVERABLE(negate_overflow, OverflowData *Data, ValueHandle OldVal)
+
+/// \brief Handle an INT_MIN/-1 overflow or division by zero.
+RECOVERABLE(divrem_overflow, OverflowData *Data,
+ ValueHandle LHS, ValueHandle RHS)
+
+struct ShiftOutOfBoundsData {
+ SourceLocation Loc;
+ const TypeDescriptor &LHSType;
+ const TypeDescriptor &RHSType;
+};
+
+/// \brief Handle a shift where the RHS is out of bounds or a left shift where
+/// the LHS is negative or overflows.
+RECOVERABLE(shift_out_of_bounds, ShiftOutOfBoundsData *Data,
+ ValueHandle LHS, ValueHandle RHS)
+
+struct OutOfBoundsData {
+ SourceLocation Loc;
+ const TypeDescriptor &ArrayType;
+ const TypeDescriptor &IndexType;
+};
+
+/// \brief Handle an array index out of bounds error.
+RECOVERABLE(out_of_bounds, OutOfBoundsData *Data, ValueHandle Index)
+
+struct UnreachableData {
+ SourceLocation Loc;
+};
+
+/// \brief Handle a __builtin_unreachable which is reached.
+UNRECOVERABLE(builtin_unreachable, UnreachableData *Data)
+/// \brief Handle reaching the end of a value-returning function.
+UNRECOVERABLE(missing_return, UnreachableData *Data)
+
+struct VLABoundData {
+ SourceLocation Loc;
+ const TypeDescriptor &Type;
+};
+
+/// \brief Handle a VLA with a non-positive bound.
+RECOVERABLE(vla_bound_not_positive, VLABoundData *Data, ValueHandle Bound)
+
+// Keeping this around for binary compatibility with (sanitized) programs
+// compiled with older compilers.
+struct FloatCastOverflowData {
+ const TypeDescriptor &FromType;
+ const TypeDescriptor &ToType;
+};
+
+struct FloatCastOverflowDataV2 {
+ SourceLocation Loc;
+ const TypeDescriptor &FromType;
+ const TypeDescriptor &ToType;
+};
+
+/// Handle overflow in a conversion to or from a floating-point type.
+/// void *Data is one of FloatCastOverflowData* or FloatCastOverflowDataV2*
+RECOVERABLE(float_cast_overflow, void *Data, ValueHandle From)
+
+struct InvalidValueData {
+ SourceLocation Loc;
+ const TypeDescriptor &Type;
+};
+
+/// \brief Handle a load of an invalid value for the type.
+RECOVERABLE(load_invalid_value, InvalidValueData *Data, ValueHandle Val)
+
+/// Known implicit conversion check kinds.
+/// Keep in sync with the enum of the same name in CGExprScalar.cpp
+enum ImplicitConversionCheckKind : unsigned char {
+ ICCK_IntegerTruncation = 0, // Legacy, was only used by clang 7.
+ ICCK_UnsignedIntegerTruncation = 1,
+ ICCK_SignedIntegerTruncation = 2,
+ ICCK_IntegerSignChange = 3,
+ ICCK_SignedIntegerTruncationOrSignChange = 4,
+};
+
+struct ImplicitConversionData {
+ SourceLocation Loc;
+ const TypeDescriptor &FromType;
+ const TypeDescriptor &ToType;
+ /* ImplicitConversionCheckKind */ unsigned char Kind;
+};
+
+/// \brief Implict conversion that changed the value.
+RECOVERABLE(implicit_conversion, ImplicitConversionData *Data, ValueHandle Src,
+ ValueHandle Dst)
+
+/// Known builtin check kinds.
+/// Keep in sync with the enum of the same name in CodeGenFunction.h
+enum BuiltinCheckKind : unsigned char {
+ BCK_CTZPassedZero,
+ BCK_CLZPassedZero,
+};
+
+struct InvalidBuiltinData {
+ SourceLocation Loc;
+ unsigned char Kind;
+};
+
+/// Handle a builtin called in an invalid way.
+RECOVERABLE(invalid_builtin, InvalidBuiltinData *Data)
+
+struct InvalidObjCCast {
+ SourceLocation Loc;
+ const TypeDescriptor &ExpectedType;
+};
+
+/// Handle an invalid ObjC cast.
+RECOVERABLE(invalid_objc_cast, InvalidObjCCast *Data, ValueHandle Pointer)
+
+struct NonNullReturnData {
+ SourceLocation AttrLoc;
+};
+
+/// \brief Handle returning null from function with the returns_nonnull
+/// attribute, or a return type annotated with _Nonnull.
+RECOVERABLE(nonnull_return_v1, NonNullReturnData *Data, SourceLocation *Loc)
+RECOVERABLE(nullability_return_v1, NonNullReturnData *Data, SourceLocation *Loc)
+
+struct NonNullArgData {
+ SourceLocation Loc;
+ SourceLocation AttrLoc;
+ int ArgIndex;
+};
+
+/// \brief Handle passing null pointer to a function parameter with the nonnull
+/// attribute, or a _Nonnull type annotation.
+RECOVERABLE(nonnull_arg, NonNullArgData *Data)
+RECOVERABLE(nullability_arg, NonNullArgData *Data)
+
+struct PointerOverflowData {
+ SourceLocation Loc;
+};
+
+RECOVERABLE(pointer_overflow, PointerOverflowData *Data, ValueHandle Base,
+ ValueHandle Result)
+
+/// \brief Known CFI check kinds.
+/// Keep in sync with the enum of the same name in CodeGenFunction.h
+enum CFITypeCheckKind : unsigned char {
+ CFITCK_VCall,
+ CFITCK_NVCall,
+ CFITCK_DerivedCast,
+ CFITCK_UnrelatedCast,
+ CFITCK_ICall,
+ CFITCK_NVMFCall,
+ CFITCK_VMFCall,
+};
+
+struct CFICheckFailData {
+ CFITypeCheckKind CheckKind;
+ SourceLocation Loc;
+ const TypeDescriptor &Type;
+};
+
+/// \brief Handle control flow integrity failures.
+RECOVERABLE(cfi_check_fail, CFICheckFailData *Data, ValueHandle Function,
+ uptr VtableIsValid)
+
+struct ReportOptions;
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __ubsan_handle_cfi_bad_type(
+ CFICheckFailData *Data, ValueHandle Vtable, bool ValidVtable,
+ ReportOptions Opts);
+
+}
+
+#endif // UBSAN_HANDLERS_H
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers_cxx.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers_cxx.cpp
new file mode 100644
index 00000000000..0317a3d1428
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers_cxx.cpp
@@ -0,0 +1,205 @@
+//===-- ubsan_handlers_cxx.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Error logging entry points for the UBSan runtime, which are only used for C++
+// compilations. This file is permitted to use language features which require
+// linking against a C++ ABI library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
+#include "ubsan_handlers.h"
+#include "ubsan_handlers_cxx.h"
+#include "ubsan_diag.h"
+#include "ubsan_type_hash.h"
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
+
+using namespace __sanitizer;
+using namespace __ubsan;
+
+namespace __ubsan {
+ extern const char *const TypeCheckKinds[];
+}
+
+// Returns true if UBSan has printed an error report.
+static bool HandleDynamicTypeCacheMiss(
+ DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash,
+ ReportOptions Opts) {
+ if (checkDynamicType((void*)Pointer, Data->TypeInfo, Hash))
+ // Just a cache miss. The type matches after all.
+ return false;
+
+ // Check if error report should be suppressed.
+ DynamicTypeInfo DTI = getDynamicTypeInfoFromObject((void*)Pointer);
+ if (DTI.isValid() && IsVptrCheckSuppressed(DTI.getMostDerivedTypeName()))
+ return false;
+
+ SourceLocation Loc = Data->Loc.acquire();
+ ErrorType ET = ErrorType::DynamicTypeMismatch;
+ if (ignoreReport(Loc, Opts, ET))
+ return false;
+
+ ScopedReport R(Opts, Loc, ET);
+
+ Diag(Loc, DL_Error, ET,
+ "%0 address %1 which does not point to an object of type %2")
+ << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type;
+
+ // If possible, say what type it actually points to.
+ if (!DTI.isValid()) {
+ if (DTI.getOffset() < -VptrMaxOffsetToTop || DTI.getOffset() > VptrMaxOffsetToTop) {
+ Diag(Pointer, DL_Note, ET,
+ "object has a possibly invalid vptr: abs(offset to top) too big")
+ << TypeName(DTI.getMostDerivedTypeName())
+ << Range(Pointer, Pointer + sizeof(uptr), "possibly invalid vptr");
+ } else {
+ Diag(Pointer, DL_Note, ET, "object has invalid vptr")
+ << TypeName(DTI.getMostDerivedTypeName())
+ << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr");
+ }
+ } else if (!DTI.getOffset())
+ Diag(Pointer, DL_Note, ET, "object is of type %0")
+ << TypeName(DTI.getMostDerivedTypeName())
+ << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0");
+ else
+ // FIXME: Find the type at the specified offset, and include that
+ // in the note.
+ Diag(Pointer - DTI.getOffset(), DL_Note, ET,
+ "object is base class subobject at offset %0 within object of type %1")
+ << DTI.getOffset() << TypeName(DTI.getMostDerivedTypeName())
+ << TypeName(DTI.getSubobjectTypeName())
+ << Range(Pointer, Pointer + sizeof(uptr),
+ "vptr for %2 base class of %1");
+ return true;
+}
+
+void __ubsan::__ubsan_handle_dynamic_type_cache_miss(
+ DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {
+ GET_REPORT_OPTIONS(false);
+ HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts);
+}
+void __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort(
+ DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {
+ // Note: -fsanitize=vptr is always recoverable.
+ GET_REPORT_OPTIONS(false);
+ if (HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts))
+ Die();
+}
+
+namespace __ubsan {
+void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
+ bool ValidVtable, ReportOptions Opts) {
+ SourceLocation Loc = Data->Loc.acquire();
+ ErrorType ET = ErrorType::CFIBadType;
+
+ if (ignoreReport(Loc, Opts, ET))
+ return;
+
+ ScopedReport R(Opts, Loc, ET);
+ DynamicTypeInfo DTI = ValidVtable
+ ? getDynamicTypeInfoFromVtable((void *)Vtable)
+ : DynamicTypeInfo(0, 0, 0);
+
+ const char *CheckKindStr;
+ switch (Data->CheckKind) {
+ case CFITCK_VCall:
+ CheckKindStr = "virtual call";
+ break;
+ case CFITCK_NVCall:
+ CheckKindStr = "non-virtual call";
+ break;
+ case CFITCK_DerivedCast:
+ CheckKindStr = "base-to-derived cast";
+ break;
+ case CFITCK_UnrelatedCast:
+ CheckKindStr = "cast to unrelated type";
+ break;
+ case CFITCK_VMFCall:
+ CheckKindStr = "virtual pointer to member function call";
+ break;
+ case CFITCK_ICall:
+ case CFITCK_NVMFCall:
+ Die();
+ }
+
+ Diag(Loc, DL_Error, ET,
+ "control flow integrity check for type %0 failed during "
+ "%1 (vtable address %2)")
+ << Data->Type << CheckKindStr << (void *)Vtable;
+
+ // If possible, say what type it actually points to.
+ if (!DTI.isValid())
+ Diag(Vtable, DL_Note, ET, "invalid vtable");
+ else
+ Diag(Vtable, DL_Note, ET, "vtable is of type %0")
+ << TypeName(DTI.getMostDerivedTypeName());
+
+ // If the failure involved different DSOs for the check location and vtable,
+ // report the DSO names.
+ const char *DstModule = Symbolizer::GetOrInit()->GetModuleNameForPc(Vtable);
+ if (!DstModule)
+ DstModule = "(unknown)";
+
+ const char *SrcModule = Symbolizer::GetOrInit()->GetModuleNameForPc(Opts.pc);
+ if (!SrcModule)
+ SrcModule = "(unknown)";
+
+ if (internal_strcmp(SrcModule, DstModule))
+ Diag(Loc, DL_Note, ET, "check failed in %0, vtable located in %1")
+ << SrcModule << DstModule;
+}
+
+static bool handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
+ ValueHandle Function,
+ ValueHandle calleeRTTI,
+ ValueHandle fnRTTI, ReportOptions Opts) {
+ if (checkTypeInfoEquality(reinterpret_cast<void *>(calleeRTTI),
+ reinterpret_cast<void *>(fnRTTI)))
+ return false;
+
+ SourceLocation CallLoc = Data->Loc.acquire();
+ ErrorType ET = ErrorType::FunctionTypeMismatch;
+
+ if (ignoreReport(CallLoc, Opts, ET))
+ return true;
+
+ ScopedReport R(Opts, CallLoc, ET);
+
+ SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
+ const char *FName = FLoc.get()->info.function;
+ if (!FName)
+ FName = "(unknown)";
+
+ Diag(CallLoc, DL_Error, ET,
+ "call to function %0 through pointer to incorrect function type %1")
+ << FName << Data->Type;
+ Diag(FLoc, DL_Note, ET, "%0 defined here") << FName;
+ return true;
+}
+
+void __ubsan_handle_function_type_mismatch_v1(FunctionTypeMismatchData *Data,
+ ValueHandle Function,
+ ValueHandle calleeRTTI,
+ ValueHandle fnRTTI) {
+ GET_REPORT_OPTIONS(false);
+ handleFunctionTypeMismatch(Data, Function, calleeRTTI, fnRTTI, Opts);
+}
+
+void __ubsan_handle_function_type_mismatch_v1_abort(
+ FunctionTypeMismatchData *Data, ValueHandle Function,
+ ValueHandle calleeRTTI, ValueHandle fnRTTI) {
+ GET_REPORT_OPTIONS(true);
+ if (handleFunctionTypeMismatch(Data, Function, calleeRTTI, fnRTTI, Opts))
+ Die();
+}
+} // namespace __ubsan
+
+#endif // CAN_SANITIZE_UB
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers_cxx.h b/contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers_cxx.h
new file mode 100644
index 00000000000..fd534c2573f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_handlers_cxx.h
@@ -0,0 +1,54 @@
+//===-- ubsan_handlers_cxx.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Entry points to the runtime library for Clang's undefined behavior sanitizer,
+// for C++-specific checks. This code is not linked into C binaries.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_HANDLERS_CXX_H
+#define UBSAN_HANDLERS_CXX_H
+
+#include "ubsan_value.h"
+
+namespace __ubsan {
+
+struct DynamicTypeCacheMissData {
+ SourceLocation Loc;
+ const TypeDescriptor &Type;
+ void *TypeInfo;
+ unsigned char TypeCheckKind;
+};
+
+/// \brief Handle a runtime type check failure, caused by an incorrect vptr.
+/// When this handler is called, all we know is that the type was not in the
+/// cache; this does not necessarily imply the existence of a bug.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __ubsan_handle_dynamic_type_cache_miss(
+ DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash);
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __ubsan_handle_dynamic_type_cache_miss_abort(
+ DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash);
+
+struct FunctionTypeMismatchData {
+ SourceLocation Loc;
+ const TypeDescriptor &Type;
+};
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__ubsan_handle_function_type_mismatch_v1(FunctionTypeMismatchData *Data,
+ ValueHandle Val,
+ ValueHandle calleeRTTI,
+ ValueHandle fnRTTI);
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__ubsan_handle_function_type_mismatch_v1_abort(FunctionTypeMismatchData *Data,
+ ValueHandle Val,
+ ValueHandle calleeRTTI,
+ ValueHandle fnRTTI);
+}
+
+#endif // UBSAN_HANDLERS_CXX_H
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_init.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_init.cpp
new file mode 100644
index 00000000000..5802d58896f
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_init.cpp
@@ -0,0 +1,76 @@
+//===-- ubsan_init.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Initialization of UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_interface_internal.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+#include "ubsan_diag.h"
+#include "ubsan_flags.h"
+#include "ubsan_init.h"
+
+using namespace __ubsan;
+
+const char *__ubsan::GetSanititizerToolName() {
+ return "UndefinedBehaviorSanitizer";
+}
+
+static bool ubsan_initialized;
+static StaticSpinMutex ubsan_init_mu;
+
+static void CommonInit() {
+ InitializeSuppressions();
+}
+
+static void UbsanDie() {
+ if (common_flags()->print_module_map >= 1)
+ DumpProcessMap();
+}
+
+static void CommonStandaloneInit() {
+ SanitizerToolName = GetSanititizerToolName();
+ CacheBinaryName();
+ InitializeFlags();
+ __sanitizer::InitializePlatformEarly();
+ __sanitizer_set_report_path(common_flags()->log_path);
+ AndroidLogInit();
+ InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
+ CommonInit();
+
+ // Only add die callback when running in standalone mode to avoid printing
+ // the same information from multiple sanitizers' output
+ AddDieCallback(UbsanDie);
+ Symbolizer::LateInitialize();
+}
+
+void __ubsan::InitAsStandalone() {
+ SpinMutexLock l(&ubsan_init_mu);
+ if (!ubsan_initialized) {
+ CommonStandaloneInit();
+ ubsan_initialized = true;
+ }
+}
+
+void __ubsan::InitAsStandaloneIfNecessary() { return InitAsStandalone(); }
+
+void __ubsan::InitAsPlugin() {
+ SpinMutexLock l(&ubsan_init_mu);
+ if (!ubsan_initialized) {
+ CommonInit();
+ ubsan_initialized = true;
+ }
+}
+
+#endif // CAN_SANITIZE_UB
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_init.h b/contrib/libs/clang16-rt/lib/ubsan/ubsan_init.h
new file mode 100644
index 00000000000..0510385b13d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_init.h
@@ -0,0 +1,33 @@
+//===-- ubsan_init.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Initialization function for UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_INIT_H
+#define UBSAN_INIT_H
+
+namespace __ubsan {
+
+// Get the full tool name for UBSan.
+const char *GetSanititizerToolName();
+
+// Initialize UBSan as a standalone tool. Typically should be called early
+// during initialization.
+void InitAsStandalone();
+
+// Initialize UBSan as a standalone tool, if it hasn't been initialized before.
+void InitAsStandaloneIfNecessary();
+
+// Initializes UBSan as a plugin tool. This function should be called once
+// from "parent tool" (e.g. ASan) initialization.
+void InitAsPlugin();
+
+} // namespace __ubsan
+
+#endif // UBSAN_INIT_H
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_init_standalone.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_init_standalone.cpp
new file mode 100644
index 00000000000..91c3f57b424
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_init_standalone.cpp
@@ -0,0 +1,33 @@
+//===-- ubsan_init_standalone.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Initialization of standalone UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_platform.h"
+#if !CAN_SANITIZE_UB
+# error "UBSan is not supported on this platform!"
+#endif
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "ubsan_init.h"
+#include "ubsan_signals_standalone.h"
+
+namespace __ubsan {
+
+class UbsanStandaloneInitializer {
+ public:
+ UbsanStandaloneInitializer() {
+ InitAsStandalone();
+ InitializeDeadlySignals();
+ }
+};
+static UbsanStandaloneInitializer ubsan_standalone_initializer;
+
+} // namespace __ubsan
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_init_standalone_preinit.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_init_standalone_preinit.cpp
new file mode 100644
index 00000000000..fabbf919a40
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_init_standalone_preinit.cpp
@@ -0,0 +1,35 @@
+//===-- ubsan_init_standalone_preinit.cpp --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Initialization of standalone UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_platform.h"
+#if !CAN_SANITIZE_UB
+#error "UBSan is not supported on this platform!"
+#endif
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "ubsan_init.h"
+#include "ubsan_signals_standalone.h"
+
+#if SANITIZER_CAN_USE_PREINIT_ARRAY
+
+namespace __ubsan {
+
+static void PreInitAsStandalone() {
+ InitAsStandalone();
+ InitializeDeadlySignals();
+}
+
+} // namespace __ubsan
+
+__attribute__((section(".preinit_array"), used)) void (*__local_ubsan_preinit)(
+ void) = __ubsan::PreInitAsStandalone;
+#endif // SANITIZER_CAN_USE_PREINIT_ARRAY
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_monitor.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_monitor.cpp
new file mode 100644
index 00000000000..69dd986f9bd
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_monitor.cpp
@@ -0,0 +1,75 @@
+//===-- ubsan_monitor.cpp ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Hooks which allow a monitor process to inspect UBSan's diagnostics.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_monitor.h"
+
+using namespace __ubsan;
+
+UndefinedBehaviorReport::UndefinedBehaviorReport(const char *IssueKind,
+ Location &Loc,
+ InternalScopedString &Msg)
+ : IssueKind(IssueKind), Loc(Loc) {
+ // We have the common sanitizer reporting lock, so it's safe to register a
+ // new UB report.
+ RegisterUndefinedBehaviorReport(this);
+
+ // Make a copy of the diagnostic.
+ Buffer.append("%s", Msg.data());
+
+ // Let the monitor know that a report is available.
+ __ubsan_on_report();
+}
+
+static UndefinedBehaviorReport *CurrentUBR;
+
+void __ubsan::RegisterUndefinedBehaviorReport(UndefinedBehaviorReport *UBR) {
+ CurrentUBR = UBR;
+}
+
+SANITIZER_WEAK_DEFAULT_IMPL
+void __ubsan::__ubsan_on_report(void) {}
+
+void __ubsan::__ubsan_get_current_report_data(const char **OutIssueKind,
+ const char **OutMessage,
+ const char **OutFilename,
+ unsigned *OutLine,
+ unsigned *OutCol,
+ char **OutMemoryAddr) {
+ if (!OutIssueKind || !OutMessage || !OutFilename || !OutLine || !OutCol ||
+ !OutMemoryAddr)
+ UNREACHABLE("Invalid arguments passed to __ubsan_get_current_report_data");
+
+ InternalScopedString &Buf = CurrentUBR->Buffer;
+
+ // Ensure that the first character of the diagnostic text can't start with a
+ // lowercase letter.
+ char FirstChar = *Buf.data();
+ if (FirstChar >= 'a' && FirstChar <= 'z')
+ *Buf.data() += 'A' - 'a';
+
+ *OutIssueKind = CurrentUBR->IssueKind;
+ *OutMessage = Buf.data();
+ if (!CurrentUBR->Loc.isSourceLocation()) {
+ *OutFilename = "<unknown>";
+ *OutLine = *OutCol = 0;
+ } else {
+ SourceLocation SL = CurrentUBR->Loc.getSourceLocation();
+ *OutFilename = SL.getFilename();
+ *OutLine = SL.getLine();
+ *OutCol = SL.getColumn();
+ }
+
+ if (CurrentUBR->Loc.isMemoryLocation())
+ *OutMemoryAddr = (char *)CurrentUBR->Loc.getMemoryLocation();
+ else
+ *OutMemoryAddr = nullptr;
+}
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_monitor.h b/contrib/libs/clang16-rt/lib/ubsan/ubsan_monitor.h
new file mode 100644
index 00000000000..3bfd7be8916
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_monitor.h
@@ -0,0 +1,48 @@
+//===-- ubsan_monitor.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Hooks which allow a monitor process to inspect UBSan's diagnostics.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef UBSAN_MONITOR_H
+#define UBSAN_MONITOR_H
+
+#include "ubsan_diag.h"
+#include "ubsan_value.h"
+
+namespace __ubsan {
+
+struct UndefinedBehaviorReport {
+ const char *IssueKind;
+ Location &Loc;
+ InternalScopedString Buffer;
+
+ UndefinedBehaviorReport(const char *IssueKind, Location &Loc,
+ InternalScopedString &Msg);
+};
+
+SANITIZER_INTERFACE_ATTRIBUTE void
+RegisterUndefinedBehaviorReport(UndefinedBehaviorReport *UBR);
+
+/// Called after a report is prepared. This serves to alert monitor processes
+/// that a UB report is available.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __ubsan_on_report(void);
+
+/// Used by the monitor process to extract information from a UB report. The
+/// data is only available until the next time __ubsan_on_report is called. The
+/// caller is responsible for copying and preserving the data if needed.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__ubsan_get_current_report_data(const char **OutIssueKind,
+ const char **OutMessage,
+ const char **OutFilename, unsigned *OutLine,
+ unsigned *OutCol, char **OutMemoryAddr);
+
+} // end namespace __ubsan
+
+#endif // UBSAN_MONITOR_H
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_platform.h b/contrib/libs/clang16-rt/lib/ubsan/ubsan_platform.h
new file mode 100644
index 00000000000..d2cc2e10bd2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_platform.h
@@ -0,0 +1,25 @@
+//===-- ubsan_platform.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the platforms which UBSan is supported at.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_PLATFORM_H
+#define UBSAN_PLATFORM_H
+
+// Other platforms should be easy to add, and probably work as-is.
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
+ defined(__NetBSD__) || defined(__DragonFly__) || \
+ (defined(__sun__) && defined(__svr4__)) || defined(_WIN32) || \
+ defined(__Fuchsia__)
+#define CAN_SANITIZE_UB 1
+#else
+# define CAN_SANITIZE_UB 0
+#endif
+
+#endif
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_signals_standalone.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_signals_standalone.cpp
new file mode 100644
index 00000000000..2c91db8ca39
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_signals_standalone.cpp
@@ -0,0 +1,71 @@
+//=-- ubsan_signals_standalone.cpp ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Installs signal handlers and related interceptors for UBSan standalone.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_platform.h"
+#include "sanitizer_common/sanitizer_platform.h"
+#if CAN_SANITIZE_UB
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "ubsan_diag.h"
+#include "ubsan_init.h"
+
+// Interception of signals breaks too many things on Android.
+// * It requires that ubsan is the first dependency of the main executable for
+// the interceptors to work correctly. This complicates deployment, as it
+// prevents us from enabling ubsan on random platform modules independently.
+// * For this to work with ART VM, ubsan signal handler has to be set after the
+// debuggerd handler, but before the ART handler.
+// * Interceptors don't work at all when ubsan runtime is loaded late, ex. when
+// it is part of an APK that does not use wrap.sh method.
+#if SANITIZER_FUCHSIA || SANITIZER_ANDROID
+
+namespace __ubsan {
+void InitializeDeadlySignals() {}
+}
+
+#else
+
+#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
+#include "sanitizer_common/sanitizer_signal_interceptors.inc"
+
+// TODO(yln): Temporary workaround. Will be removed.
+void ubsan_GetStackTrace(BufferedStackTrace *stack, uptr max_depth,
+ uptr pc, uptr bp, void *context, bool fast);
+
+namespace __ubsan {
+
+static void OnStackUnwind(const SignalContext &sig, const void *,
+ BufferedStackTrace *stack) {
+ ubsan_GetStackTrace(stack, kStackTraceMax,
+ StackTrace::GetNextInstructionPc(sig.pc), sig.bp,
+ sig.context, common_flags()->fast_unwind_on_fatal);
+}
+
+static void UBsanOnDeadlySignal(int signo, void *siginfo, void *context) {
+ HandleDeadlySignal(siginfo, context, GetTid(), &OnStackUnwind, nullptr);
+}
+
+static bool is_initialized = false;
+
+void InitializeDeadlySignals() {
+ if (is_initialized)
+ return;
+ is_initialized = true;
+ InitializeSignalInterceptors();
+ InstallDeadlySignalHandlers(&UBsanOnDeadlySignal);
+}
+
+} // namespace __ubsan
+
+#endif
+
+#endif // CAN_SANITIZE_UB
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_signals_standalone.h b/contrib/libs/clang16-rt/lib/ubsan/ubsan_signals_standalone.h
new file mode 100644
index 00000000000..128eff266fb
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_signals_standalone.h
@@ -0,0 +1,24 @@
+//=-- ubsan_signals_standalone.h
+//------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Installs signal handlers and related interceptors for UBSan standalone.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef UBSAN_SIGNALS_STANDALONE_H
+#define UBSAN_SIGNALS_STANDALONE_H
+
+namespace __ubsan {
+
+// Initializes signal handlers and interceptors.
+void InitializeDeadlySignals();
+
+} // namespace __ubsan
+
+#endif // UBSAN_SIGNALS_STANDALONE_H
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash.cpp
new file mode 100644
index 00000000000..8f4b9aee50b
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash.cpp
@@ -0,0 +1,33 @@
+//===-- ubsan_type_hash.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of a hash table for fast checking of inheritance
+// relationships. This file is only linked into C++ compilations, and is
+// permitted to use language features which require a C++ ABI library.
+//
+// Most of the implementation lives in an ABI-specific source file
+// (ubsan_type_hash_{itanium,win}.cpp).
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
+#include "ubsan_type_hash.h"
+
+#include "sanitizer_common/sanitizer_common.h"
+
+/// A cache of recently-checked hashes. Mini hash table with "random" evictions.
+__ubsan::HashValue
+__ubsan::__ubsan_vptr_type_cache[__ubsan::VptrTypeCacheSize];
+
+__ubsan::DynamicTypeInfo __ubsan::getDynamicTypeInfoFromObject(void *Object) {
+ void *VtablePtr = *reinterpret_cast<void **>(Object);
+ return getDynamicTypeInfoFromVtable(VtablePtr);
+}
+
+#endif // CAN_SANITIZE_UB
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash.h b/contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash.h
new file mode 100644
index 00000000000..e42884b765a
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash.h
@@ -0,0 +1,73 @@
+//===-- ubsan_type_hash.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Hashing of types for Clang's undefined behavior checker.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_TYPE_HASH_H
+#define UBSAN_TYPE_HASH_H
+
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace __ubsan {
+
+typedef uptr HashValue;
+
+/// \brief Information about the dynamic type of an object (extracted from its
+/// vptr).
+class DynamicTypeInfo {
+ const char *MostDerivedTypeName;
+ sptr Offset;
+ const char *SubobjectTypeName;
+
+public:
+ DynamicTypeInfo(const char *MDTN, sptr Offset, const char *STN)
+ : MostDerivedTypeName(MDTN), Offset(Offset), SubobjectTypeName(STN) {}
+
+ /// Determine whether the object had a valid dynamic type.
+ bool isValid() const { return MostDerivedTypeName; }
+ /// Get the name of the most-derived type of the object.
+ const char *getMostDerivedTypeName() const { return MostDerivedTypeName; }
+ /// Get the offset from the most-derived type to this base class.
+ sptr getOffset() const { return Offset; }
+ /// Get the name of the most-derived type at the specified offset.
+ const char *getSubobjectTypeName() const { return SubobjectTypeName; }
+};
+
+/// \brief Get information about the dynamic type of an object.
+DynamicTypeInfo getDynamicTypeInfoFromObject(void *Object);
+
+/// \brief Get information about the dynamic type of an object from its vtable.
+DynamicTypeInfo getDynamicTypeInfoFromVtable(void *Vtable);
+
+/// \brief Check whether the dynamic type of \p Object has a \p Type subobject
+/// at offset 0.
+/// \return \c true if the type matches, \c false if not.
+bool checkDynamicType(void *Object, void *Type, HashValue Hash);
+
+const unsigned VptrTypeCacheSize = 128;
+
+/// A sanity check for Vtable. Offsets to top must be reasonably small
+/// numbers (by absolute value). It's a weak check for Vtable corruption.
+const int VptrMaxOffsetToTop = 1<<20;
+
+/// \brief A cache of the results of checkDynamicType. \c checkDynamicType would
+/// return \c true (modulo hash collisions) if
+/// \code
+/// __ubsan_vptr_type_cache[Hash % VptrTypeCacheSize] == Hash
+/// \endcode
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+HashValue __ubsan_vptr_type_cache[VptrTypeCacheSize];
+
+/// \brief Do whatever is required by the ABI to check for std::type_info
+/// equivalence beyond simple pointer comparison.
+bool checkTypeInfoEquality(const void *TypeInfo1, const void *TypeInfo2);
+
+} // namespace __ubsan
+
+#endif // UBSAN_TYPE_HASH_H
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash_itanium.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash_itanium.cpp
new file mode 100644
index 00000000000..468a8fcd603
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash_itanium.cpp
@@ -0,0 +1,281 @@
+//===-- ubsan_type_hash_itanium.cpp ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of type hashing/lookup for Itanium C++ ABI.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB && !defined(_MSC_VER)
+#include "ubsan_type_hash.h"
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_ptrauth.h"
+#include <stdint.h>
+
+// The following are intended to be binary compatible with the definitions
+// given in the Itanium ABI. We make no attempt to be ODR-compatible with
+// those definitions, since existing ABI implementations aren't.
+
+namespace std {
+ class type_info {
+ public:
+ typedef const char *__type_name_t;
+ virtual ~type_info();
+
+ const char *__type_name;
+
+ __type_name_t name() const {
+#if defined(__APPLE__) && defined(__LP64__) && !defined(__x86_64__)
+ uintptr_t __non_unique_rtti_bit =
+ (1ULL << ((__CHAR_BIT__ * sizeof(__type_name_t)) - 1));
+ return (__type_name_t)((uintptr_t)__type_name & ~__non_unique_rtti_bit);
+#else
+ return __type_name;
+#endif
+ }
+ };
+}
+
+namespace __cxxabiv1 {
+
+/// Type info for classes with no bases, and base class for type info for
+/// classes with bases.
+class __class_type_info : public std::type_info {
+ ~__class_type_info() override;
+};
+
+/// Type info for classes with simple single public inheritance.
+class __si_class_type_info : public __class_type_info {
+public:
+ ~__si_class_type_info() override;
+
+ const __class_type_info *__base_type;
+};
+
+class __base_class_type_info {
+public:
+ const __class_type_info *__base_type;
+ long __offset_flags;
+
+ enum __offset_flags_masks {
+ __virtual_mask = 0x1,
+ __public_mask = 0x2,
+ __offset_shift = 8
+ };
+};
+
+/// Type info for classes with multiple, virtual, or non-public inheritance.
+class __vmi_class_type_info : public __class_type_info {
+public:
+ ~__vmi_class_type_info() override;
+
+ unsigned int flags;
+ unsigned int base_count;
+ __base_class_type_info base_info[1];
+};
+
+}
+
+namespace abi = __cxxabiv1;
+
+using namespace __sanitizer;
+
+// We implement a simple two-level cache for type-checking results. For each
+// (vptr,type) pair, a hash is computed. This hash is assumed to be globally
+// unique; if it collides, we will get false negatives, but:
+// * such a collision would have to occur on the *first* bad access,
+// * the probability of such a collision is low (and for a 64-bit target, is
+// negligible), and
+// * the vptr, and thus the hash, can be affected by ASLR, so multiple runs
+// give better coverage.
+//
+// The first caching layer is a small hash table with no chaining; buckets are
+// reused as needed. The second caching layer is a large hash table with open
+// chaining. We can freely evict from either layer since this is just a cache.
+//
+// FIXME: Make these hash table accesses thread-safe. The races here are benign:
+// assuming the unsequenced loads and stores don't misbehave too badly,
+// the worst case is false negatives or poor cache behavior, not false
+// positives or crashes.
+
+/// Find a bucket to store the given hash value in.
+static __ubsan::HashValue *getTypeCacheHashTableBucket(__ubsan::HashValue V) {
+ static const unsigned HashTableSize = 65537;
+ static __ubsan::HashValue __ubsan_vptr_hash_set[HashTableSize];
+
+ unsigned First = (V & 65535) ^ 1;
+ unsigned Probe = First;
+ for (int Tries = 5; Tries; --Tries) {
+ if (!__ubsan_vptr_hash_set[Probe] || __ubsan_vptr_hash_set[Probe] == V)
+ return &__ubsan_vptr_hash_set[Probe];
+ Probe += ((V >> 16) & 65535) + 1;
+ if (Probe >= HashTableSize)
+ Probe -= HashTableSize;
+ }
+ // FIXME: Pick a random entry from the probe sequence to evict rather than
+ // just taking the first.
+ return &__ubsan_vptr_hash_set[First];
+}
+
+/// \brief Determine whether \p Derived has a \p Base base class subobject at
+/// offset \p Offset.
+static bool isDerivedFromAtOffset(const abi::__class_type_info *Derived,
+ const abi::__class_type_info *Base,
+ sptr Offset) {
+ if (Derived->name() == Base->name() ||
+ __ubsan::checkTypeInfoEquality(Derived, Base))
+ return Offset == 0;
+
+ if (const abi::__si_class_type_info *SI =
+ dynamic_cast<const abi::__si_class_type_info*>(Derived))
+ return isDerivedFromAtOffset(SI->__base_type, Base, Offset);
+
+ const abi::__vmi_class_type_info *VTI =
+ dynamic_cast<const abi::__vmi_class_type_info*>(Derived);
+ if (!VTI)
+ // No base class subobjects.
+ return false;
+
+ // Look for a base class which is derived from \p Base at the right offset.
+ for (unsigned int base = 0; base != VTI->base_count; ++base) {
+ // FIXME: Curtail the recursion if this base can't possibly contain the
+ // given offset.
+ sptr OffsetHere = VTI->base_info[base].__offset_flags >>
+ abi::__base_class_type_info::__offset_shift;
+ if (VTI->base_info[base].__offset_flags &
+ abi::__base_class_type_info::__virtual_mask)
+ // For now, just punt on virtual bases and say 'yes'.
+ // FIXME: OffsetHere is the offset in the vtable of the virtual base
+ // offset. Read the vbase offset out of the vtable and use it.
+ return true;
+ if (isDerivedFromAtOffset(VTI->base_info[base].__base_type,
+ Base, Offset - OffsetHere))
+ return true;
+ }
+
+ return false;
+}
+
+/// \brief Find the derived-most dynamic base class of \p Derived at offset
+/// \p Offset.
+static const abi::__class_type_info *findBaseAtOffset(
+ const abi::__class_type_info *Derived, sptr Offset) {
+ if (!Offset)
+ return Derived;
+
+ if (const abi::__si_class_type_info *SI =
+ dynamic_cast<const abi::__si_class_type_info*>(Derived))
+ return findBaseAtOffset(SI->__base_type, Offset);
+
+ const abi::__vmi_class_type_info *VTI =
+ dynamic_cast<const abi::__vmi_class_type_info*>(Derived);
+ if (!VTI)
+ // No base class subobjects.
+ return nullptr;
+
+ for (unsigned int base = 0; base != VTI->base_count; ++base) {
+ sptr OffsetHere = VTI->base_info[base].__offset_flags >>
+ abi::__base_class_type_info::__offset_shift;
+ if (VTI->base_info[base].__offset_flags &
+ abi::__base_class_type_info::__virtual_mask)
+ // FIXME: Can't handle virtual bases yet.
+ continue;
+ if (const abi::__class_type_info *Base =
+ findBaseAtOffset(VTI->base_info[base].__base_type,
+ Offset - OffsetHere))
+ return Base;
+ }
+
+ return nullptr;
+}
+
+namespace {
+
+struct VtablePrefix {
+ /// The offset from the vptr to the start of the most-derived object.
+ /// This will only be greater than zero in some virtual base class vtables
+ /// used during object con-/destruction, and will usually be exactly zero.
+ sptr Offset;
+ /// The type_info object describing the most-derived class type.
+ std::type_info *TypeInfo;
+};
+VtablePrefix *getVtablePrefix(void *Vtable) {
+ Vtable = ptrauth_auth_data(Vtable, ptrauth_key_cxx_vtable_pointer, 0);
+ VtablePrefix *Vptr = reinterpret_cast<VtablePrefix*>(Vtable);
+ VtablePrefix *Prefix = Vptr - 1;
+ if (!IsAccessibleMemoryRange((uptr)Prefix, sizeof(VtablePrefix)))
+ return nullptr;
+ if (!Prefix->TypeInfo)
+ // This can't possibly be a valid vtable.
+ return nullptr;
+ return Prefix;
+}
+
+}
+
+bool __ubsan::checkDynamicType(void *Object, void *Type, HashValue Hash) {
+ // A crash anywhere within this function probably means the vptr is corrupted.
+ // FIXME: Perform these checks more cautiously.
+
+ // Check whether this is something we've evicted from the cache.
+ HashValue *Bucket = getTypeCacheHashTableBucket(Hash);
+ if (*Bucket == Hash) {
+ __ubsan_vptr_type_cache[Hash % VptrTypeCacheSize] = Hash;
+ return true;
+ }
+
+ void *VtablePtr = *reinterpret_cast<void **>(Object);
+ VtablePrefix *Vtable = getVtablePrefix(VtablePtr);
+ if (!Vtable)
+ return false;
+ if (Vtable->Offset < -VptrMaxOffsetToTop || Vtable->Offset > VptrMaxOffsetToTop) {
+ // Too large or too small offset are signs of Vtable corruption.
+ return false;
+ }
+
+ // Check that this is actually a type_info object for a class type.
+ abi::__class_type_info *Derived =
+ dynamic_cast<abi::__class_type_info*>(Vtable->TypeInfo);
+ if (!Derived)
+ return false;
+
+ abi::__class_type_info *Base = (abi::__class_type_info*)Type;
+ if (!isDerivedFromAtOffset(Derived, Base, -Vtable->Offset))
+ return false;
+
+ // Success. Cache this result.
+ __ubsan_vptr_type_cache[Hash % VptrTypeCacheSize] = Hash;
+ *Bucket = Hash;
+ return true;
+}
+
+__ubsan::DynamicTypeInfo
+__ubsan::getDynamicTypeInfoFromVtable(void *VtablePtr) {
+ VtablePrefix *Vtable = getVtablePrefix(VtablePtr);
+ if (!Vtable)
+ return DynamicTypeInfo(nullptr, 0, nullptr);
+ if (Vtable->Offset < -VptrMaxOffsetToTop || Vtable->Offset > VptrMaxOffsetToTop)
+ return DynamicTypeInfo(nullptr, Vtable->Offset, nullptr);
+ const abi::__class_type_info *ObjectType = findBaseAtOffset(
+ static_cast<const abi::__class_type_info*>(Vtable->TypeInfo),
+ -Vtable->Offset);
+ return DynamicTypeInfo(Vtable->TypeInfo->name(), -Vtable->Offset,
+ ObjectType ? ObjectType->name() : "<unknown>");
+}
+
+bool __ubsan::checkTypeInfoEquality(const void *TypeInfo1,
+ const void *TypeInfo2) {
+ auto TI1 = static_cast<const std::type_info *>(TypeInfo1);
+ auto TI2 = static_cast<const std::type_info *>(TypeInfo2);
+ return SANITIZER_NON_UNIQUE_TYPEINFO && TI1->name()[0] != '*' &&
+ TI2->name()[0] != '*' && !internal_strcmp(TI1->name(), TI2->name());
+}
+
+#endif // CAN_SANITIZE_UB && !SANITIZER_WINDOWS
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash_win.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash_win.cpp
new file mode 100644
index 00000000000..106fa1b85a5
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_type_hash_win.cpp
@@ -0,0 +1,84 @@
+//===-- ubsan_type_hash_win.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of type hashing/lookup for Microsoft C++ ABI.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB && defined(_MSC_VER)
+#include "ubsan_type_hash.h"
+
+#include "sanitizer_common/sanitizer_common.h"
+
+#include <typeinfo>
+
+struct CompleteObjectLocator {
+ int is_image_relative;
+ int offset_to_top;
+ int vfptr_offset;
+ int rtti_addr;
+ int chd_addr;
+ int obj_locator_addr;
+};
+
+struct CompleteObjectLocatorAbs {
+ int is_image_relative;
+ int offset_to_top;
+ int vfptr_offset;
+ std::type_info *rtti_addr;
+ void *chd_addr;
+ CompleteObjectLocator *obj_locator_addr;
+};
+
+bool __ubsan::checkDynamicType(void *Object, void *Type, HashValue Hash) {
+ // FIXME: Implement.
+ return false;
+}
+
+__ubsan::DynamicTypeInfo
+__ubsan::getDynamicTypeInfoFromVtable(void *VtablePtr) {
+ // The virtual table may not have a complete object locator if the object
+ // was compiled without RTTI (i.e. we might be reading from some other global
+ // laid out before the virtual table), so we need to carefully validate each
+ // pointer dereference and perform sanity checks.
+ CompleteObjectLocator **obj_locator_ptr =
+ ((CompleteObjectLocator**)VtablePtr)-1;
+ if (!IsAccessibleMemoryRange((uptr)obj_locator_ptr, sizeof(void*)))
+ return DynamicTypeInfo(0, 0, 0);
+
+ CompleteObjectLocator *obj_locator = *obj_locator_ptr;
+ if (!IsAccessibleMemoryRange((uptr)obj_locator,
+ sizeof(CompleteObjectLocator)))
+ return DynamicTypeInfo(0, 0, 0);
+
+ std::type_info *tinfo;
+ if (obj_locator->is_image_relative == 1) {
+ char *image_base = ((char *)obj_locator) - obj_locator->obj_locator_addr;
+ tinfo = (std::type_info *)(image_base + obj_locator->rtti_addr);
+ } else if (obj_locator->is_image_relative == 0)
+ tinfo = ((CompleteObjectLocatorAbs *)obj_locator)->rtti_addr;
+ else
+ // Probably not a complete object locator.
+ return DynamicTypeInfo(0, 0, 0);
+
+ if (!IsAccessibleMemoryRange((uptr)tinfo, sizeof(std::type_info)))
+ return DynamicTypeInfo(0, 0, 0);
+
+ // Okay, this is probably a std::type_info. Request its name.
+ // FIXME: Implement a base class search like we do for Itanium.
+ return DynamicTypeInfo(tinfo->name(), obj_locator->offset_to_top,
+ "<unknown>");
+}
+
+bool __ubsan::checkTypeInfoEquality(const void *, const void *) {
+ return false;
+}
+
+#endif // CAN_SANITIZE_UB && SANITIZER_WINDOWS
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_value.cpp b/contrib/libs/clang16-rt/lib/ubsan/ubsan_value.cpp
new file mode 100644
index 00000000000..dc61e5b939d
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_value.cpp
@@ -0,0 +1,158 @@
+//===-- ubsan_value.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Representation of a runtime value, as marshaled from the generated code to
+// the ubsan runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_platform.h"
+#if CAN_SANITIZE_UB
+#include "ubsan_value.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+
+#if SANITIZER_APPLE
+#include <dlfcn.h>
+#endif
+
+using namespace __ubsan;
+
+typedef const char *(*ObjCGetClassNameTy)(void *);
+
+const char *__ubsan::getObjCClassName(ValueHandle Pointer) {
+#if SANITIZER_APPLE
+ // We need to query the ObjC runtime for some information, but do not want
+ // to introduce a static dependency from the ubsan runtime onto ObjC. Try to
+ // grab a handle to the ObjC runtime used by the process.
+ static bool AttemptedDlopen = false;
+ static void *ObjCHandle = nullptr;
+ static void *ObjCObjectGetClassName = nullptr;
+
+ // Prevent threads from racing to dlopen().
+ static __sanitizer::StaticSpinMutex Lock;
+ {
+ __sanitizer::SpinMutexLock Guard(&Lock);
+
+ if (!AttemptedDlopen) {
+ ObjCHandle = dlopen(
+ "/usr/lib/libobjc.A.dylib",
+ RTLD_LAZY // Only bind symbols when used.
+ | RTLD_LOCAL // Only make symbols available via the handle.
+ | RTLD_NOLOAD // Do not load the dylib, just grab a handle if the
+ // image is already loaded.
+ | RTLD_FIRST // Only search the image pointed-to by the handle.
+ );
+ AttemptedDlopen = true;
+ if (!ObjCHandle)
+ return nullptr;
+ ObjCObjectGetClassName = dlsym(ObjCHandle, "object_getClassName");
+ }
+ }
+
+ if (!ObjCObjectGetClassName)
+ return nullptr;
+
+ return ObjCGetClassNameTy(ObjCObjectGetClassName)((void *)Pointer);
+#else
+ return nullptr;
+#endif
+}
+
+SIntMax Value::getSIntValue() const {
+ CHECK(getType().isSignedIntegerTy());
+ if (isInlineInt()) {
+ // Val was zero-extended to ValueHandle. Sign-extend from original width
+ // to SIntMax.
+ const unsigned ExtraBits =
+ sizeof(SIntMax) * 8 - getType().getIntegerBitWidth();
+ return SIntMax(UIntMax(Val) << ExtraBits) >> ExtraBits;
+ }
+ if (getType().getIntegerBitWidth() == 64)
+ return *reinterpret_cast<s64*>(Val);
+#if HAVE_INT128_T
+ if (getType().getIntegerBitWidth() == 128)
+ return *reinterpret_cast<s128*>(Val);
+#else
+ if (getType().getIntegerBitWidth() == 128)
+ UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
+#endif
+ UNREACHABLE("unexpected bit width");
+}
+
+UIntMax Value::getUIntValue() const {
+ CHECK(getType().isUnsignedIntegerTy());
+ if (isInlineInt())
+ return Val;
+ if (getType().getIntegerBitWidth() == 64)
+ return *reinterpret_cast<u64*>(Val);
+#if HAVE_INT128_T
+ if (getType().getIntegerBitWidth() == 128)
+ return *reinterpret_cast<u128*>(Val);
+#else
+ if (getType().getIntegerBitWidth() == 128)
+ UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
+#endif
+ UNREACHABLE("unexpected bit width");
+}
+
+UIntMax Value::getPositiveIntValue() const {
+ if (getType().isUnsignedIntegerTy())
+ return getUIntValue();
+ SIntMax Val = getSIntValue();
+ CHECK(Val >= 0);
+ return Val;
+}
+
+/// Get the floating-point value of this object, extended to a long double.
+/// These are always passed by address (our calling convention doesn't allow
+/// them to be passed in floating-point registers, so this has little cost).
+FloatMax Value::getFloatValue() const {
+ CHECK(getType().isFloatTy());
+ if (isInlineFloat()) {
+ switch (getType().getFloatBitWidth()) {
+#if 0
+ // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion
+ // from '__fp16' to 'long double'.
+ case 16: {
+ __fp16 Value;
+ internal_memcpy(&Value, &Val, 4);
+ return Value;
+ }
+#endif
+ case 32: {
+ float Value;
+#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ // For big endian the float value is in the last 4 bytes.
+ // On some targets we may only have 4 bytes so we count backwards from
+ // the end of Val to account for both the 32-bit and 64-bit cases.
+ internal_memcpy(&Value, ((const char*)(&Val + 1)) - 4, 4);
+#else
+ internal_memcpy(&Value, &Val, 4);
+#endif
+ return Value;
+ }
+ case 64: {
+ double Value;
+ internal_memcpy(&Value, &Val, 8);
+ return Value;
+ }
+ }
+ } else {
+ switch (getType().getFloatBitWidth()) {
+ case 64: return *reinterpret_cast<double*>(Val);
+ case 80: return *reinterpret_cast<long double*>(Val);
+ case 96: return *reinterpret_cast<long double*>(Val);
+ case 128: return *reinterpret_cast<long double*>(Val);
+ }
+ }
+ UNREACHABLE("unexpected floating point bit width");
+}
+
+#endif // CAN_SANITIZE_UB
diff --git a/contrib/libs/clang16-rt/lib/ubsan/ubsan_value.h b/contrib/libs/clang16-rt/lib/ubsan/ubsan_value.h
new file mode 100644
index 00000000000..e0957276dd2
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan/ubsan_value.h
@@ -0,0 +1,199 @@
+//===-- ubsan_value.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Representation of data which is passed from the compiler-generated calls into
+// the ubsan runtime.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_VALUE_H
+#define UBSAN_VALUE_H
+
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+// FIXME: Move this out to a config header.
+#if __SIZEOF_INT128__
+__extension__ typedef __int128 s128;
+__extension__ typedef unsigned __int128 u128;
+#define HAVE_INT128_T 1
+#else
+#define HAVE_INT128_T 0
+#endif
+
+namespace __ubsan {
+
+/// \brief Largest integer types we support.
+#if HAVE_INT128_T
+typedef s128 SIntMax;
+typedef u128 UIntMax;
+#else
+typedef s64 SIntMax;
+typedef u64 UIntMax;
+#endif
+
+/// \brief Largest floating-point type we support.
+typedef long double FloatMax;
+
+/// \brief A description of a source location. This corresponds to Clang's
+/// \c PresumedLoc type.
+class SourceLocation {
+ const char *Filename;
+ u32 Line;
+ u32 Column;
+
+public:
+ SourceLocation() : Filename(), Line(), Column() {}
+ SourceLocation(const char *Filename, unsigned Line, unsigned Column)
+ : Filename(Filename), Line(Line), Column(Column) {}
+
+ /// \brief Determine whether the source location is known.
+ bool isInvalid() const { return !Filename; }
+
+ /// \brief Atomically acquire a copy, disabling original in-place.
+ /// Exactly one call to acquire() returns a copy that isn't disabled.
+ SourceLocation acquire() {
+ u32 OldColumn = __sanitizer::atomic_exchange(
+ (__sanitizer::atomic_uint32_t *)&Column, ~u32(0),
+ __sanitizer::memory_order_relaxed);
+ return SourceLocation(Filename, Line, OldColumn);
+ }
+
+ /// \brief Determine if this Location has been disabled.
+ /// Disabled SourceLocations are invalid to use.
+ bool isDisabled() {
+ return Column == ~u32(0);
+ }
+
+ /// \brief Get the presumed filename for the source location.
+ const char *getFilename() const { return Filename; }
+ /// \brief Get the presumed line number.
+ unsigned getLine() const { return Line; }
+ /// \brief Get the column within the presumed line.
+ unsigned getColumn() const { return Column; }
+};
+
+
+/// \brief A description of a type.
+class TypeDescriptor {
+ /// A value from the \c Kind enumeration, specifying what flavor of type we
+ /// have.
+ u16 TypeKind;
+
+ /// A \c Type-specific value providing information which allows us to
+ /// interpret the meaning of a ValueHandle of this type.
+ u16 TypeInfo;
+
+ /// The name of the type follows, in a format suitable for including in
+ /// diagnostics.
+ char TypeName[1];
+
+public:
+ enum Kind {
+ /// An integer type. Lowest bit is 1 for a signed value, 0 for an unsigned
+ /// value. Remaining bits are log_2(bit width). The value representation is
+ /// the integer itself if it fits into a ValueHandle, and a pointer to the
+ /// integer otherwise.
+ TK_Integer = 0x0000,
+ /// A floating-point type. Low 16 bits are bit width. The value
+ /// representation is that of bitcasting the floating-point value to an
+ /// integer type.
+ TK_Float = 0x0001,
+ /// Any other type. The value representation is unspecified.
+ TK_Unknown = 0xffff
+ };
+
+ const char *getTypeName() const { return TypeName; }
+
+ Kind getKind() const {
+ return static_cast<Kind>(TypeKind);
+ }
+
+ bool isIntegerTy() const { return getKind() == TK_Integer; }
+ bool isSignedIntegerTy() const {
+ return isIntegerTy() && (TypeInfo & 1);
+ }
+ bool isUnsignedIntegerTy() const {
+ return isIntegerTy() && !(TypeInfo & 1);
+ }
+ unsigned getIntegerBitWidth() const {
+ CHECK(isIntegerTy());
+ return 1 << (TypeInfo >> 1);
+ }
+
+ bool isFloatTy() const { return getKind() == TK_Float; }
+ unsigned getFloatBitWidth() const {
+ CHECK(isFloatTy());
+ return TypeInfo;
+ }
+};
+
+/// \brief An opaque handle to a value.
+typedef uptr ValueHandle;
+
+/// Returns the class name of the given ObjC object, or null if the name
+/// cannot be found.
+const char *getObjCClassName(ValueHandle Pointer);
+
+/// \brief Representation of an operand value provided by the instrumented code.
+///
+/// This is a combination of a TypeDescriptor (which is emitted as constant data
+/// as an operand to a handler function) and a ValueHandle (which is passed at
+/// runtime when a check failure occurs).
+class Value {
+ /// The type of the value.
+ const TypeDescriptor &Type;
+ /// The encoded value itself.
+ ValueHandle Val;
+
+ /// Is \c Val a (zero-extended) integer?
+ bool isInlineInt() const {
+ CHECK(getType().isIntegerTy());
+ const unsigned InlineBits = sizeof(ValueHandle) * 8;
+ const unsigned Bits = getType().getIntegerBitWidth();
+ return Bits <= InlineBits;
+ }
+
+ /// Is \c Val a (zero-extended) integer representation of a float?
+ bool isInlineFloat() const {
+ CHECK(getType().isFloatTy());
+ const unsigned InlineBits = sizeof(ValueHandle) * 8;
+ const unsigned Bits = getType().getFloatBitWidth();
+ return Bits <= InlineBits;
+ }
+
+public:
+ Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {}
+
+ const TypeDescriptor &getType() const { return Type; }
+
+ /// \brief Get this value as a signed integer.
+ SIntMax getSIntValue() const;
+
+ /// \brief Get this value as an unsigned integer.
+ UIntMax getUIntValue() const;
+
+ /// \brief Decode this value, which must be a positive or unsigned integer.
+ UIntMax getPositiveIntValue() const;
+
+ /// Is this an integer with value -1?
+ bool isMinusOne() const {
+ return getType().isSignedIntegerTy() && getSIntValue() == -1;
+ }
+
+ /// Is this a negative integer?
+ bool isNegative() const {
+ return getType().isSignedIntegerTy() && getSIntValue() < 0;
+ }
+
+ /// \brief Get this value as a floating-point quantity.
+ FloatMax getFloatValue() const;
+};
+
+} // namespace __ubsan
+
+#endif // UBSAN_VALUE_H
diff --git a/contrib/libs/clang16-rt/lib/ubsan_minimal/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/ubsan_minimal/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan_minimal/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp b/contrib/libs/clang16-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp
new file mode 100644
index 00000000000..53a3273e4e6
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp
@@ -0,0 +1,143 @@
+#include "sanitizer_common/sanitizer_atomic.h"
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef KERNEL_USE
+extern "C" void ubsan_message(const char *msg);
+static void message(const char *msg) { ubsan_message(msg); }
+#else
+static void message(const char *msg) {
+ (void)write(2, msg, strlen(msg));
+}
+#endif
+
+static const int kMaxCallerPcs = 20;
+static __sanitizer::atomic_uintptr_t caller_pcs[kMaxCallerPcs];
+// Number of elements in caller_pcs. A special value of kMaxCallerPcs + 1 means
+// that "too many errors" has already been reported.
+static __sanitizer::atomic_uint32_t caller_pcs_sz;
+
+__attribute__((noinline)) static bool report_this_error(uintptr_t caller) {
+ if (caller == 0)
+ return false;
+ while (true) {
+ unsigned sz = __sanitizer::atomic_load_relaxed(&caller_pcs_sz);
+ if (sz > kMaxCallerPcs) return false; // early exit
+ // when sz==kMaxCallerPcs print "too many errors", but only when cmpxchg
+ // succeeds in order to not print it multiple times.
+ if (sz > 0 && sz < kMaxCallerPcs) {
+ uintptr_t p;
+ for (unsigned i = 0; i < sz; ++i) {
+ p = __sanitizer::atomic_load_relaxed(&caller_pcs[i]);
+ if (p == 0) break; // Concurrent update.
+ if (p == caller) return false;
+ }
+ if (p == 0) continue; // FIXME: yield?
+ }
+
+ if (!__sanitizer::atomic_compare_exchange_strong(
+ &caller_pcs_sz, &sz, sz + 1, __sanitizer::memory_order_seq_cst))
+ continue; // Concurrent update! Try again from the start.
+
+ if (sz == kMaxCallerPcs) {
+ message("ubsan: too many errors\n");
+ return false;
+ }
+ __sanitizer::atomic_store_relaxed(&caller_pcs[sz], caller);
+ return true;
+ }
+}
+
+__attribute__((noinline)) static void decorate_msg(char *buf,
+ uintptr_t caller) {
+ // print the address by nibbles
+ for (unsigned shift = sizeof(uintptr_t) * 8; shift;) {
+ shift -= 4;
+ unsigned nibble = (caller >> shift) & 0xf;
+ *(buf++) = nibble < 10 ? nibble + '0' : nibble - 10 + 'a';
+ }
+ // finish the message
+ buf[0] = '\n';
+ buf[1] = '\0';
+}
+
+#if defined(__ANDROID__)
+extern "C" __attribute__((weak)) void android_set_abort_message(const char *);
+static void abort_with_message(const char *msg) {
+ if (&android_set_abort_message) android_set_abort_message(msg);
+ abort();
+}
+#else
+static void abort_with_message(const char *) { abort(); }
+#endif
+
+#if SANITIZER_DEBUG
+namespace __sanitizer {
+// The DCHECK macro needs this symbol to be defined.
+void NORETURN CheckFailed(const char *file, int, const char *cond, u64, u64) {
+ message("Sanitizer CHECK failed: ");
+ message(file);
+ message(":?? : "); // FIXME: Show line number.
+ message(cond);
+ abort();
+}
+} // namespace __sanitizer
+#endif
+
+#define INTERFACE extern "C" __attribute__((visibility("default")))
+
+// How many chars we need to reserve to print an address.
+constexpr unsigned kAddrBuf = SANITIZER_WORDSIZE / 4;
+#define MSG_TMPL(msg) "ubsan: " msg " by 0x"
+#define MSG_TMPL_END(buf, msg) (buf + sizeof(MSG_TMPL(msg)) - 1)
+// Reserve an additional byte for '\n'.
+#define MSG_BUF_LEN(msg) (sizeof(MSG_TMPL(msg)) + kAddrBuf + 1)
+
+#define HANDLER_RECOVER(name, msg) \
+ INTERFACE void __ubsan_handle_##name##_minimal() { \
+ uintptr_t caller = GET_CALLER_PC(); \
+ if (!report_this_error(caller)) return; \
+ char msg_buf[MSG_BUF_LEN(msg)] = MSG_TMPL(msg); \
+ decorate_msg(MSG_TMPL_END(msg_buf, msg), caller); \
+ message(msg_buf); \
+ }
+
+#define HANDLER_NORECOVER(name, msg) \
+ INTERFACE void __ubsan_handle_##name##_minimal_abort() { \
+ char msg_buf[MSG_BUF_LEN(msg)] = MSG_TMPL(msg); \
+ decorate_msg(MSG_TMPL_END(msg_buf, msg), GET_CALLER_PC()); \
+ message(msg_buf); \
+ abort_with_message(msg_buf); \
+ }
+
+#define HANDLER(name, msg) \
+ HANDLER_RECOVER(name, msg) \
+ HANDLER_NORECOVER(name, msg)
+
+HANDLER(type_mismatch, "type-mismatch")
+HANDLER(alignment_assumption, "alignment-assumption")
+HANDLER(add_overflow, "add-overflow")
+HANDLER(sub_overflow, "sub-overflow")
+HANDLER(mul_overflow, "mul-overflow")
+HANDLER(negate_overflow, "negate-overflow")
+HANDLER(divrem_overflow, "divrem-overflow")
+HANDLER(shift_out_of_bounds, "shift-out-of-bounds")
+HANDLER(out_of_bounds, "out-of-bounds")
+HANDLER_RECOVER(builtin_unreachable, "builtin-unreachable")
+HANDLER_RECOVER(missing_return, "missing-return")
+HANDLER(vla_bound_not_positive, "vla-bound-not-positive")
+HANDLER(float_cast_overflow, "float-cast-overflow")
+HANDLER(load_invalid_value, "load-invalid-value")
+HANDLER(invalid_builtin, "invalid-builtin")
+HANDLER(invalid_objc_cast, "invalid-objc-cast")
+HANDLER(function_type_mismatch, "function-type-mismatch")
+HANDLER(implicit_conversion, "implicit-conversion")
+HANDLER(nonnull_arg, "nonnull-arg")
+HANDLER(nonnull_return, "nonnull-return")
+HANDLER(nullability_arg, "nullability-arg")
+HANDLER(nullability_return, "nullability-return")
+HANDLER(pointer_overflow, "pointer-overflow")
+HANDLER(cfi_check_fail, "cfi-check-fail")
diff --git a/contrib/libs/clang16-rt/lib/ubsan_minimal/ya.make b/contrib/libs/clang16-rt/lib/ubsan_minimal/ya.make
new file mode 100644
index 00000000000..b96cad85790
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan_minimal/ya.make
@@ -0,0 +1,43 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.ubsan_minimal${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCS(
+ ubsan_minimal_handlers.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/ubsan_standalone/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/ubsan_standalone/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan_standalone/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/ubsan_standalone/ya.make b/contrib/libs/clang16-rt/lib/ubsan_standalone/ya.make
new file mode 100644
index 00000000000..d9d32d7658e
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan_standalone/ya.make
@@ -0,0 +1,128 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.ubsan_standalone${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DHAVE_RPC_XDR_H=0
+ -DUBSAN_CAN_USE_CXXABI
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-rtti
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib)
+
+SRCS(
+ interception/interception_linux.cpp
+ interception/interception_mac.cpp
+ interception/interception_type_test.cpp
+ interception/interception_win.cpp
+ sanitizer_common/sancov_flags.cpp
+ sanitizer_common/sanitizer_allocator.cpp
+ sanitizer_common/sanitizer_allocator_checks.cpp
+ sanitizer_common/sanitizer_allocator_report.cpp
+ sanitizer_common/sanitizer_chained_origin_depot.cpp
+ sanitizer_common/sanitizer_common.cpp
+ sanitizer_common/sanitizer_common_libcdep.cpp
+ sanitizer_common/sanitizer_coverage_fuchsia.cpp
+ sanitizer_common/sanitizer_coverage_libcdep_new.cpp
+ sanitizer_common/sanitizer_coverage_win_sections.cpp
+ sanitizer_common/sanitizer_deadlock_detector1.cpp
+ sanitizer_common/sanitizer_deadlock_detector2.cpp
+ sanitizer_common/sanitizer_errno.cpp
+ sanitizer_common/sanitizer_file.cpp
+ sanitizer_common/sanitizer_flag_parser.cpp
+ sanitizer_common/sanitizer_flags.cpp
+ sanitizer_common/sanitizer_fuchsia.cpp
+ sanitizer_common/sanitizer_libc.cpp
+ sanitizer_common/sanitizer_libignore.cpp
+ sanitizer_common/sanitizer_linux.cpp
+ sanitizer_common/sanitizer_linux_libcdep.cpp
+ sanitizer_common/sanitizer_linux_s390.cpp
+ sanitizer_common/sanitizer_mac.cpp
+ sanitizer_common/sanitizer_mac_libcdep.cpp
+ sanitizer_common/sanitizer_mutex.cpp
+ sanitizer_common/sanitizer_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+ sanitizer_common/sanitizer_platform_limits_linux.cpp
+ sanitizer_common/sanitizer_platform_limits_netbsd.cpp
+ sanitizer_common/sanitizer_platform_limits_posix.cpp
+ sanitizer_common/sanitizer_platform_limits_solaris.cpp
+ sanitizer_common/sanitizer_posix.cpp
+ sanitizer_common/sanitizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_printf.cpp
+ sanitizer_common/sanitizer_procmaps_bsd.cpp
+ sanitizer_common/sanitizer_procmaps_common.cpp
+ sanitizer_common/sanitizer_procmaps_fuchsia.cpp
+ sanitizer_common/sanitizer_procmaps_linux.cpp
+ sanitizer_common/sanitizer_procmaps_mac.cpp
+ sanitizer_common/sanitizer_procmaps_solaris.cpp
+ sanitizer_common/sanitizer_solaris.cpp
+ sanitizer_common/sanitizer_stack_store.cpp
+ sanitizer_common/sanitizer_stackdepot.cpp
+ sanitizer_common/sanitizer_stacktrace.cpp
+ sanitizer_common/sanitizer_stacktrace_libcdep.cpp
+ sanitizer_common/sanitizer_stacktrace_printer.cpp
+ sanitizer_common/sanitizer_stacktrace_sparc.cpp
+ sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp
+ sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_mac.cpp
+ sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp
+ sanitizer_common/sanitizer_stoptheworld_win.cpp
+ sanitizer_common/sanitizer_suppressions.cpp
+ sanitizer_common/sanitizer_symbolizer.cpp
+ sanitizer_common/sanitizer_symbolizer_libbacktrace.cpp
+ sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_mac.cpp
+ sanitizer_common/sanitizer_symbolizer_markup.cpp
+ sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp
+ sanitizer_common/sanitizer_symbolizer_report.cpp
+ sanitizer_common/sanitizer_symbolizer_win.cpp
+ sanitizer_common/sanitizer_termination.cpp
+ sanitizer_common/sanitizer_thread_registry.cpp
+ sanitizer_common/sanitizer_tls_get_addr.cpp
+ sanitizer_common/sanitizer_type_traits.cpp
+ sanitizer_common/sanitizer_unwind_linux_libcdep.cpp
+ sanitizer_common/sanitizer_unwind_win.cpp
+ sanitizer_common/sanitizer_win.cpp
+ ubsan/ubsan_diag.cpp
+ ubsan/ubsan_diag_standalone.cpp
+ ubsan/ubsan_flags.cpp
+ ubsan/ubsan_handlers.cpp
+ ubsan/ubsan_init.cpp
+ ubsan/ubsan_init_standalone.cpp
+ ubsan/ubsan_init_standalone_preinit.cpp
+ ubsan/ubsan_monitor.cpp
+ ubsan/ubsan_signals_standalone.cpp
+ ubsan/ubsan_value.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/lib/ubsan_standalone_cxx/.yandex_meta/licenses.list.txt b/contrib/libs/clang16-rt/lib/ubsan_standalone_cxx/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..0dd5fc5a3c8
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan_standalone_cxx/.yandex_meta/licenses.list.txt
@@ -0,0 +1,377 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+|* See https://llvm.org/LICENSE.txt for license information.
+
+
+====================Apache-2.0 WITH LLVM-exception====================
+|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+====================COPYRIGHT====================
+ InitCache(c);
+ TransferBatch *b = allocator->AllocateBatch(&stats_, this, class_id);
+ if (UNLIKELY(!b))
+
+
+====================COPYRIGHT====================
+ initCacheMaybe(C);
+ TransferBatch *B = Allocator->popBatch(this, ClassId);
+ if (UNLIKELY(!B))
+
+
+====================COPYRIGHT====================
+// Calling getenv should be fine (c)(tm) at any time.
+const char *getEnv(const char *Name) { return getenv(Name); }
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+
+====================COPYRIGHT====================
+Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
+
+
+====================File: CREDITS.TXT====================
+This file is a partial list of people who have contributed to the LLVM/CompilerRT
+project. If you have contributed a patch or made some other contribution to
+LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Craig van Vliet
+E: cvanvliet@auroraux.org
+W: http://www.auroraux.org
+D: Code style and Readability fixes.
+
+N: Edward O'Callaghan
+E: eocallaghan@auroraux.org
+W: http://www.auroraux.org
+D: CMake'ify Compiler-RT build system
+D: Maintain Solaris & AuroraUX ports of Compiler-RT
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
+
+N: Guan-Hong Liu
+E: koviankevin@hotmail.com
+D: IEEE Quad-precision functions
+
+N: Joerg Sonnenberger
+E: joerg@NetBSD.org
+D: Maintains NetBSD port.
+
+N: Matt Thomas
+E: matt@NetBSD.org
+D: ARM improvements.
+
+
+====================MIT====================
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+====================NCSA====================
+Compiler-RT is open source software. You may freely distribute it under the
+terms of the license agreement found in LICENSE.txt.
+
+
+====================NCSA====================
+Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+
+
+====================NCSA====================
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+
+====================NCSA====================
+University of Illinois/NCSA
+Open Source License
+
+
+====================NCSA AND MIT====================
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
diff --git a/contrib/libs/clang16-rt/lib/ubsan_standalone_cxx/ya.make b/contrib/libs/clang16-rt/lib/ubsan_standalone_cxx/ya.make
new file mode 100644
index 00000000000..b3872de32da
--- /dev/null
+++ b/contrib/libs/clang16-rt/lib/ubsan_standalone_cxx/ya.make
@@ -0,0 +1,49 @@
+# Generated by devtools/yamaker.
+
+INCLUDE(${ARCADIA_ROOT}/build/platform/clang/arch.cmake)
+
+LIBRARY(clang_rt.ubsan_standalone_cxx${CLANG_RT_SUFFIX})
+
+LICENSE(
+ Apache-2.0 AND
+ Apache-2.0 WITH LLVM-exception AND
+ MIT AND
+ NCSA
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+OWNER(g:cpp-contrib)
+
+ADDINCL(
+ contrib/libs/clang16-rt/lib
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+NO_SANITIZE()
+
+CFLAGS(
+ -DUBSAN_CAN_USE_CXXABI
+ -fno-builtin
+ -fno-exceptions
+ -fno-lto
+ -fno-stack-protector
+ -fomit-frame-pointer
+ -frtti
+ -funwind-tables
+ -fvisibility=hidden
+)
+
+SRCDIR(contrib/libs/clang16-rt/lib/ubsan)
+
+SRCS(
+ ubsan_handlers_cxx.cpp
+ ubsan_type_hash.cpp
+ ubsan_type_hash_itanium.cpp
+ ubsan_type_hash_win.cpp
+)
+
+END()
diff --git a/contrib/libs/clang16-rt/ya.make b/contrib/libs/clang16-rt/ya.make
new file mode 100644
index 00000000000..8559121308e
--- /dev/null
+++ b/contrib/libs/clang16-rt/ya.make
@@ -0,0 +1,45 @@
+# Generated by devtools/yamaker from nixpkgs 23.05.
+
+OWNER(g:cpp-contrib)
+
+VERSION(16.0.6)
+
+ORIGINAL_SOURCE(https://github.com/llvm/llvm-project/archive/llvmorg-16.0.6.tar.gz)
+
+RECURSE(
+ lib/asan
+ lib/asan-preinit
+ lib/asan_cxx
+ lib/asan_static
+ lib/lsan
+ lib/profile
+ lib/stats
+ lib/stats_client
+ lib/tsan
+ lib/tsan_cxx
+ lib/ubsan_minimal
+ lib/ubsan_standalone
+ lib/ubsan_standalone_cxx
+)
+
+IF (OS_LINUX)
+ RECURSE(
+ lib/cfi
+ lib/cfi_diag
+ lib/dd
+ lib/dfsan
+ lib/gwp_asan
+ lib/hwasan
+ lib/hwasan_aliases
+ lib/hwasan_aliases_cxx
+ lib/hwasan_cxx
+ lib/memprof
+ lib/memprof-preinit
+ lib/memprof_cxx
+ lib/msan
+ lib/msan_cxx
+ lib/safestack
+ lib/scudo_standalone
+ lib/scudo_standalone_cxx
+ )
+ENDIF()