Unlike the other compiler-rt unit tests MemProf was not using the
`generate_compiler_rt_tests()` helper that ensures the test is compiled
using the test compiler (generally the Clang binary built earlier).
This was exposed by https://github.com/llvm/llvm-project/pull/83088
because it started adding Clang-specific flags to
COMPILER_RT_UNITTEST_CFLAGS if the compiler ID matched "Clang".
This change should fix the buildbots that compile compiler-rt using
a GCC compiler with LLVM_ENABLE_PROJECTS=compiler-rt.
Reviewed By: vitalybuka
Pull Request: https://github.com/llvm/llvm-project/pull/88074
memprof often fails when ASLR entropy is too high ('sudo sysctl
vm.mmap_rnd_bits=32; ninja check-memprof'), which is the default setting
for newer versions of Ubuntu
(https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/jammy/commit/?h=hwe-6.5-next--2024.03.04-1--auto&id=6b522637c6a7dabd8530026ae933fb5ff17e877f).
This patch fixes the issue by moving the allocator base, analogously to
ASan (https://reviews.llvm.org/D148280).
Explanation from the ASan patch: when CONFIG_ARCH_MMAP_RND_BITS == 32,
it will frequently conflict with memprof's allocator, because the PIE
program segment base address of 0x555555555554 plus an ASLR shift of up
to ((2**32) * 4K == 0x100000000000) will sometimes exceed memprof's
hardcoded base address of 0x600000000000. We fix this by simply moving
the allocator base to 0x500000000000, which is below the PIE program
segment base address. This is cleaner than trying to move it to another
location that is sandwiched between the PIE program and library
segments, because if either of those grow too large, it will collide
with the allocator region.
Note that we will never need to change this base address again (unless
we want to increase the size of the allocator), because ASLR cannot be
set above 32-bits for x86-64 Linux (the PIE program segment and library
segments would collide with each other; see also ARCH_MMAP_RND_BITS_MAX
in https://github.com/torvalds/linux/blob/master/arch/x86/Kconfig).
The `_DYNAMIC` reference from `AsanDoesNotSupportStaticLinkage` ensures
that `clang++ -fsanitize=address -static` gets a linker error.
`MemprofDoesNotSupportStaticLinkage` is similar for `-fmemory-profile`.
Move the functions to sanitizer_common.h to be used by more sanitizers
on ELF platforms.
Fuchsia does not use interposition and opts out the check (its
`AsanDoesNotSupportStaticLinkage` is a no-op).
…DOW_SCALE
As MEM_GRANULARITY represents the size of memory block mapped to a
single shadow entry, and SHADOW_SCALE represents the scale of shadow
mapping, so the single shadow entry size can be computed as
(MEM_GRANULARITY >> SHADOW_SCALE).
This patch replaces the hardcoded SHADOW_ENTRY_SIZE with
(MEM_GRANULARITY >> SHADOW_SCALE).
Add __memprof_profile_reset() interface which can be used to facilitate
dumping multiple rounds of profiles from a single binary run. This
closes the current file descriptor and resets the internal file
descriptor to invalid (-1), which ensures the underlying writer reopens
the recorded profile filename. This can be used once the client is done
moving or copying a dumped profile, to prepare for reinvoking profile
dumping.
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").
v4:
- Add interface attribute to __sanitizer_internal_mem* declarations as
well, as otherwise some compilers (MSVC) will complain.
- Add SANITIZER_COMMON_NO_REDEFINE_BUILTINS to source files using
C++STL, since this could lead to ODR violations (see added comment).
v3:
- Don't use ALIAS() to alias internal_mem*() functions to
__sanitizer_internal_mem*() functions, but just define them as
ALWAYS_INLINE functions instead. This will work on darwin and windows.
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
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").
v3:
- Don't use ALIAS() to alias internal_mem*() functions to
__sanitizer_internal_mem*() functions, but just define them as
ALWAYS_INLINE functions instead. This will work on darwin and windows.
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
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
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").
Reviewed By: vitalybuka, dvyukov
Differential Revision: https://reviews.llvm.org/D151152
This moves memintrinsic interceptors (memcpy/memmove/memset) into a new
file sanitizer_common_interceptors_memintrinsics.inc.
This is in preparation of redefining builtins, however, we must be
careful to not redefine builtins in TUs that define interceptors of the
same name.
In all cases except for MSan, memintrinsic interceptors were moved to a
new TU $tool_interceptors_memintrinsics.cpp. In the case of MSan, it
turns out this is not yet necessary (as shown by the later patch
introducing memcpy tests).
NFC.
Reviewed By: vitalybuka
Differential Revision: https://reviews.llvm.org/D151552
The primary motivation for this change is to allow FreeHooks to obtain
the allocated size of the pointer being freed in a fast, efficient manner.
Differential Revision: https://reviews.llvm.org/D151360
Most uses of ALIAS() are in conjunction with WRAPPER_NAME().
Simplify the code and just make ALIAS() turn its argument into a string
(similar to Linux kernel's __alias macro). This in turn allows removing
WRAPPER_NAME().
NFC.
Reviewed By: dvyukov
Differential Revision: https://reviews.llvm.org/D151216
D147005 introduced __sanitizer_get_allocated_begin, with a return
value of void*. This involved a few naughty casts that dropped the
const. This patch adds back the const qualifier.
Differential Revision: https://reviews.llvm.org/D147489
This patch adds support for recording BuildIds usng the sanitizer
ListOfModules API. We add another entry to the SegmentEntry struct and
change the memprof raw version.
Reviewed By: tejohnson
Differential Revision: https://reviews.llvm.org/D145190
This patch adds support for recording BuildIds usng the sanitizer
ListOfModules API. We add another entry to the SegmentEntry struct and
change the memprof raw version.
Reviewed By: tejohnson
Differential Revision: https://reviews.llvm.org/D145190
As discussed in D145428, the memprof_init_is_running check can be moved
to the end of the initialization routine to avoid intercepting
allocations during initialization. Also, the memprof_init_done flag can
be removed and replaced with memprof_inited. Finally, memprof_inited can
also be moved to the end of the method.
Tested on the existing check-memprof tests; memprof profile collection
succeeded on a large internal workload.
Reviewed By: tejohnson
Differential Revision: https://reviews.llvm.org/D145528
The pointer `Buffer` is not changed, so there is no need to use reference, and the `Pod` here should use reference to avoid meaningless copy.
Reviewed By: snehasish
Differential Revision: https://reviews.llvm.org/D145024
This reverts commit ea1826ee57.
This change is breaking the ability of tests to override the profile
output file. Need to add a mechanism to do that before resubmitting.
For the RAII lock usage we need to create a local var. There were some headers which clang-tidy identified as unused.
Reviewed By: tejohnson
Differential Revision: https://reviews.llvm.org/D138593
With all of the writing of the memprof profile consolidated into one
place, there is no need to set up the profile file (which creates the
file and also redirects all printing from the runtime to it) until we
are ready to dump the profile.
This allows errors and other messages to be dumped to stderr instead of
the profile file, which by default is in a binary format. Additionally,
reset the output file to stderr after dumping the profile so that any
requested memprof allocator statistics are printed to stderr.
Differential Revision: https://reviews.llvm.org/D138175
When in-tree libcxx is selected as the sanitizer C++ ABI, use
libcxx-abi-* targets rather than libcxxabi and libunwind directly.
Differential Revision: https://reviews.llvm.org/D134855
Currently memprof profile is dumped when program exits (call `FinishAndWrite()` in ~Allocator) or `__memprof_profile_dump` is manually called.
For programs that never exit (e.g. server-side application), it will be useful to dump memprof profile when specific signal is received.
This patch installs a signal handler for deadly signals(SIGSEGV, SIGBUS, SIGABRT, SIGILL, SIGTRAP, SIGFPE) like we do in other sanitizers. In the signal handler `__memprof_profile_dump` is called to dump memprof profile.
Reviewed By: tejohnson
Differential Revision: https://reviews.llvm.org/D134795
It casued some runtimes builds to fail with cmake error
No target "libcxx-abi-static"
see code review.
> When in-tree libcxx is selected as the sanitizer C++ ABI, use
> libcxx-abi-* targets rather than libcxxabi and libunwind directly.
>
> Differential Revision: https://reviews.llvm.org/D134855
This reverts commit 414f9b7d2f.
When in-tree libcxx is selected as the sanitizer C++ ABI, use
libcxx-abi-* targets rather than libcxxabi and libunwind directly.
Differential Revision: https://reviews.llvm.org/D134855
We already link libunwind explicitly so avoid trying to link toolchain's
default libunwind which may be missing. This matches what we already do
for libcxx and libcxxabi.
Differential Revision: https://reviews.llvm.org/D129472
This is a follow up to D118200 which applies a similar cleanup to
headers when using in-tree libc++ to avoid accidentally picking up
the system headers.
Differential Revision: https://reviews.llvm.org/D128035
This is a follow up to D118200 which applies a similar cleanup to
headers when using in-tree libc++ to avoid accidentally picking up
the system headers.
Differential Revision: https://reviews.llvm.org/D128035
While investigating another issue, I noticed that `MaybeReexec()` never
actually "re-executes via `execv()`" anymore. `DyldNeedsEnvVariable()`
only returned true on macOS 10.10 and below.
Usually, I try to avoid "unnecessary" cleanups (it's hard to be certain
that there truly is no fallout), but I decided to do this one because:
* I initially tricked myself into thinking that `MaybeReexec()` was
relevant to my original investigation (instead of being dead code).
* The deleted code itself is quite complicated.
* Over time a few other things were mushed into `MaybeReexec()`:
initializing `MonotonicNanoTime()`, verifying interceptors are
working, and stripping the `DYLD_INSERT_LIBRARIES` env var to avoid
problems when forking.
* This platform-specific thing leaked into `sanitizer_common.h`.
* The `ReexecDisabled()` config nob relies on the "strong overrides weak
pattern", which is now problematic and can be completely removed.
* `ReexecDisabled()` actually hid another issue with interceptors not
working in unit tests. I added an explicit `verify_interceptors`
(defaults to `true`) option instead.
Differential Revision: https://reviews.llvm.org/D129157