[compiler-rt] Avoid memintrinsic calls inserted by the compiler
authorMarco Elver <elver@google.com>
Tue, 30 May 2023 09:59:22 +0000 (11:59 +0200)
committerMarco Elver <elver@google.com>
Wed, 31 May 2023 14:58:53 +0000 (16:58 +0200)
commit4369de7af46605522bf7dbe3bc31d00b0eb4bee6
tree25de61a2a615845203ed4e61308f6f8fa8b425ec
parent26d7b7bb8ff982b6cdcd9bf7538405356135b724
[compiler-rt] Avoid memintrinsic calls inserted by the compiler

D135716 introduced -ftrivial-auto-var-init=pattern where supported.
Unfortunately this introduces unwanted memset() for large stack arrays,
as shown by the new tests added for asan and msan (tsan already had this
test).

In general, the problem of compiler-inserted memintrinsic calls
(memset/memcpy/memmove) is not new to compiler-rt, and has been a
problem before.

To avoid introducing unwanted memintrinsic calls, we redefine
memintrinsics as __sanitizer_internal_mem* at the assembly level for
most source files automatically (where sanitizer_common_internal_defs.h
is included).

In few cases, redefining a symbol in this way causes issues for
interceptors, namely the memintrinsic interceptor themselves. For such
source files we have to selectively disable the redefinition.

Other alternatives have been considered, but simply do not work well in
the context of compiler-rt:

1. Linker --wrap:  this does not work because --wrap only
   applies to the final link, and would not apply when building
   sanitizer static libraries.

2. Changing references to memset() via objcopy:  this may work,
   but due to the complexities of the build system, introducing
   such a post-processing step for the right object files (in
   particular object files defining memset cannot be touched)
   seems infeasible.

The chosen solution works well (as shown by the tests). Other libraries
have chosen the same solution where nothing else works (see e.g. glibc's
"symbol-hacks.h").

v2:
- Fix ubsan_minimal build where compiler decides to insert
  memset/memcpy: ubsan_minimal has work without RTSanitizerCommonLibc,
  therefore do not redefine the builtins.
- Fix definition of internal_mem* functions with compilers that want the
  aliased function to already be defined before.
- Fix definition of __sanitizer_internal_mem* functions with compilers
  more pedantic about attribute placement around extern "C".

Reviewed By: vitalybuka, dvyukov

Differential Revision: https://reviews.llvm.org/D151152
16 files changed:
compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp
compiler-rt/lib/hwasan/hwasan_interceptors.cpp
compiler-rt/lib/interception/tests/CMakeLists.txt
compiler-rt/lib/memprof/memprof_interceptors_memintrinsics.cpp
compiler-rt/lib/msan/msan_interceptors.cpp
compiler-rt/lib/sanitizer_common/CMakeLists.txt
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc
compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc
compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h
compiler-rt/lib/sanitizer_common/sanitizer_libc.cpp
compiler-rt/lib/sanitizer_common/sanitizer_redefine_builtins.h [new file with mode: 0644]
compiler-rt/lib/tsan/rtl/tsan_interceptors_memintrinsics.cpp
compiler-rt/lib/ubsan_minimal/CMakeLists.txt
compiler-rt/test/asan/TestCases/Linux/check_memcpy.c [new file with mode: 0644]
compiler-rt/test/msan/Linux/check_memcpy.c [new file with mode: 0644]
compiler-rt/test/tsan/Linux/check_memcpy.c