This makes sure that COMPILER_RT_ARMHF_TARGET is set properly for
targets without a specific "armhf" target name, such as armv7 windows.
This fixes the builtins test comparesf2_test.c on Windows on armv7.
Compiler-rt libraries on arm use "arm" or "armhf" as suffix, not the
full exact arch name like "armv7".
This matches what was done for the build system in
8e11bede3a, to match the names that Clang
expects (in getArchNameForCompilerRTLib in Clang).
This fixes building a large number of the compiler-rt tests for
Windows/armv7.
This avoids building asan when targeting Windows on armv7 or aarch64. It
is possible to build asan successfully for those configurations (since
5ea9dd8c70 and
0c391133c9), but asan isn't functional
there.
This change skips building asan for targets other than x86_32 and
x86_64.
By excluding asan from the build, we fix the "check-ubsan" target for
armv7 and aarch64 Windows. If asan is included in the build, an
ubsan-asan configuration gets added to the tests, and as asan isn't
functional for these targets, it produces a lot of test failures even
when just trying to run "check-ubsan".
This removes a leftover workaround from
00f3f6e296 from 2016. Currently the tests
seem to work fine on x86_64 in both MSVC and mingw configurations with
this workaround removed.
(On aarch64, asan isn't functional at all; this workaround used to hide
that issue when running "check-ubsan", but the issue is apparent if
running all tests with "check-compiler-rt" anyway.)
Same approach as in Asan.
Now it's going to print:
```
Failed Tests (2):
UBSan-Minimal-i386-linux :: TestCases/icall.c
UBSan-Minimal-x86_64-linux :: TestCases/icall.c
```
Before it was:
```
Failed Tests (2):
UBSan-Minimal-x86_64 :: TestCases/icall.c
UBSan-Minimal-x86_64 :: TestCases/icall.c
```
PR #131756 introduced a patch to fix a deadlock between LSan and ASan.
The relevant deadlock only occurs when LSan is enabled and
`dl_iterate_phdr` is used for Stop-the-World, i.e., under the condition
`CAN_SANITIZE_LEAKS && (SANITIZER_LINUX || SANITIZER_NETBSD)`.
Therefore, this commit also sets the effective condition of this patch
to the above condition, avoiding unnecessary problems in other
environments, e.g., stack overflow on MSVC/Windows.
This PR is based on my last PR #132752 (the first commit of this PR),
but addressing a different issue.
This commit addresses the limitation in `PointerMayBeCaptured` analysis
when dealing with derived pointers (e.g. arr+1) as described in issue
#132739.
The current implementation of `PointerMayBeCaptured` may miss captures
of the underlying `alloca` when analyzing derived pointers, leading to
some FNs in TSan, as follows:
```cpp
void *Thread(void *a) {
((int*)a)[1] = 43;
return 0;
}
int main() {
int Arr[2] = {41, 42};
pthread_t t;
pthread_create(&t, 0, Thread, &Arr[0]);
// Missed instrumentation here due to the FN of PointerMayBeCaptured
Arr[1] = 43;
barrier_wait(&barrier);
pthread_join(t, 0);
}
```
Refer to this [godbolt page](https://godbolt.org/z/n67GrxdcE) to get the
compilation result of TSan.
Even when `PointerMayBeCaptured` working correctly, it should backtrack
to the original `alloca` firstly during analysis, causing redundancy to
the outer's `findAllocaForValue`.
```cpp
const AllocaInst *AI = findAllocaForValue(Addr);
// Instead of Addr, we should check whether its base pointer is captured.
if (AI && !PointerMayBeCaptured(Addr, true)) ...
```
Key changes:
Directly analyze the capture status of the underlying `alloca` instead
of derived pointers to ensure accurate capture detection
```cpp
const AllocaInst *AI = findAllocaForValue(Addr);
// Instead of Addr, we should check whether its base pointer is captured.
if (AI && !PointerMayBeCaptured(AI, true)) ...
```
I'm trying to put together an LLVM built toolchain (including LLVM libc)
targeting UEFI, currently I get an error saying "Unknown target". This
PR enables compiling compiler-rt for UEFI.
- _Float16 is now accepted by Clang.
- The half IR type is fully handled by the backend.
- These values are passed in FP registers and converted to/from float around
each operation.
- Compiler-rt conversion functions are now built for s390x including the missing
extendhfdf2 which was added.
Fixes#50374
[compiler-rt] The test `addtf3_test.c` is currently guarded by `#if
defined(CRT_HAS_IEEE_TF)`, a macro that is declared in `int_lib.h`.
However, `int_lib.h` is included *after* the preprocessor check, which
results in the macro not being defined in time and causes the test to
always be skipped.
This patch moves the includes of `fp_test.h` and `int_lib.h` to the top
of the file so that `CRT_HAS_IEEE_TF` is defined before it is checked.
Co-authored-by: Kostiantyn Lazukin <koslaz01@ip-10-252-21-142.eu-west-1.compute.internal>
### Description
This PR resolves a deadlock between AddressSanitizer (ASan) and
LeakSanitizer (LSan)
that occurs when both sanitizers attempt to acquire locks in conflicting
orders across
threads. The fix ensures safe lock acquisition ordering by preloading
module information
before error reporting.
---
### Issue Details
**Reproducer**
```cpp
// Thread 1: ASan error path
int arr[1] = {0};
std::thread t([&]() {
arr[1] = 1; // Triggers ASan OOB error
});
// Thread 2: LSan check path
__lsan_do_leak_check();
```
**Lock Order Conflict**:
- Thread 1 (ASan error reporting):
1. Acquires ASan thread registry lock (B)
1. Attempts to acquire libdl lock (A) via `dl_iterate_phdr`
- Thread 2 (LSan leak check):
1. Acquires libdl lock (A) via `dl_iterate_phdr`
1. Attempts to acquire ASan thread registry lock (B)
This creates a circular wait condition (A -> B -> A) meeting all four
Coffman deadlock criteria.
---
### Fix Strategy
The root cause lies in ASan's error reporting path needing
`dl_iterate_phdr` (requiring lock A)
while already holding its thread registry lock (B). The solution:
1. **Preload Modules Early**: Force module list initialization _before_
acquiring ASan's thread lock
2. **Avoid Nested Locking**: Ensure symbolization (via dl_iterate_phdr)
completes before error reporting locks
Key code change:
```cpp
// Before acquiring ASan's thread registry lock:
Symbolizer::GetOrInit()->GetRefreshedListOfModules();
```
This guarantees module information is cached before lock acquisition,
eliminating
the need for `dl_iterate_phdr` calls during error reporting.
---
### Testing
Added **asan_lsan_deadlock.cpp** test case:
- Reproduces deadlock reliably without fix **under idle system
conditions**
- Uses watchdog thread to detect hangs
- Verifies ASan error reports correctly without deadlock
**Note**: Due to the inherent non-determinism of thread scheduling and
lock acquisition timing,
this test may not reliably reproduce the deadlock on busy systems (e.g.,
during parallel
`ninja check-asan` runs).
---
### Impact
- Fixes rare but severe deadlocks in mixed ASan+LSan environments
- Maintains thread safety guarantees for both sanitizers
- No user-visible behavior changes except deadlock elimination
---
### Relevant Buggy Code
- Code in ASan's asan_report.cpp
```cpp
explicit ScopedInErrorReport(bool fatal = false)
: halt_on_error_(fatal || flags()->halt_on_error) {
// Acquire lock B
asanThreadRegistry().Lock();
}
~ScopedInErrorReport() {
...
// Try to acquire lock A under holding lock B via the following path
// #4 0x000071a353d83e93 in __GI___dl_iterate_phdr (
// callback=0x5d1a07a39580 <__sanitizer::dl_iterate_phdr_cb(dl_phdr_info*, unsigned long, void*)>,
// data=0x6da3510fd3f0) at ./elf/dl-iteratephdr.c:39
// #5 0x00005d1a07a39574 in __sanitizer::ListOfModules::init (this=0x71a353ebc080)
// at llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp:784
// #6 0x00005d1a07a429e3 in __sanitizer::Symbolizer::RefreshModules (this=0x71a353ebc058)
// at llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp:188
// #7 __sanitizer::Symbolizer::FindModuleForAddress (this=this@entry=0x71a353ebc058,
// address=address@entry=102366378805727)
// at llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp:214
// #8 0x00005d1a07a4291b in __sanitizer::Symbolizer::SymbolizePC (this=0x71a353ebc058, addr=102366378805727)
// at llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp:88
// #9 0x00005d1a07a40df7 in __sanitizer::(anonymous namespace)::StackTraceTextPrinter::ProcessAddressFrames (
// this=this@entry=0x6da3510fd520, pc=102366378805727)
// at llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp:37
// #10 0x00005d1a07a40d27 in __sanitizer::StackTrace::PrintTo (this=this@entry=0x6da3510fd5e8,
// output=output@entry=0x6da3510fd588)
// at llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp:110
// #11 0x00005d1a07a410a1 in __sanitizer::StackTrace::Print (this=0x6da3510fd5e8)
// at llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp:133
// #12 0x00005d1a0798758d in __asan::ErrorGeneric::Print (
// this=0x5d1a07aa4e08 <__asan::ScopedInErrorReport::current_error_+8>)
// at llvm-project/compiler-rt/lib/asan/asan_errors.cpp:617
current_error_.Print();
...
}
```
- Code in LSan's lsan_common_linux.cpp
```cpp
void LockStuffAndStopTheWorld(StopTheWorldCallback callback,
CheckForLeaksParam *argument) {
// Acquire lock A
dl_iterate_phdr(LockStuffAndStopTheWorldCallback, ¶m);
}
static int LockStuffAndStopTheWorldCallback(struct dl_phdr_info *info,
size_t size, void *data) {
// Try to acquire lock B under holding lock A via the following path
// #3 0x000055555562b34a in __sanitizer::ThreadRegistry::Lock (this=<optimized out>)
// at llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_thread_registry.h:99
// #4 __lsan::LockThreads () at llvm-project/compiler-rt/lib/asan/asan_thread.cpp:484
// #5 0x0000555555652629 in __lsan::ScopedStopTheWorldLock::ScopedStopTheWorldLock (this=<optimized out>)
// at llvm-project/compiler-rt/lib/lsan/lsan_common.h:164
// #6 __lsan::LockStuffAndStopTheWorldCallback (info=<optimized out>, size=<optimized out>, data=0x0,
// data@entry=0x7fffffffd158) at llvm-project/compiler-rt/lib/lsan/lsan_common_linux.cpp:120
ScopedStopTheWorldLock lock;
DoStopTheWorldParam *param = reinterpret_cast<DoStopTheWorldParam *>(data);
StopTheWorld(param->callback, param->argument);
return 1;
}
```
Because of the nature of this test (mmap stress-test) it tests too large
of memory allocations to be stable on watchos. WatchOS has memory limits
that can lead to the termination of this process before it reaches the
limit set by the flag. Typical only on devices that are under heavy
load. disable on watchOS.
rdar://147222346
Functions with `musttail` calls can't be roots because we can't instrument their `ret` to release the context. This patch tags their `CtxRoot` field in their `FunctionData`. In compiler-rt we then know not to allow such functions become roots, and also not confuse `CtxRoot == 0x1` with there being a context root.
Currently we also lose the context tree under such cases. We can, in a subsequent patch, have the root detector search past these functions.
Fixes:
```
[6113/7139] Building CXX object projects\compiler-rt\lib\interception\CMakeFiles\RTInterception.x86_64.dir\interception_win.cpp.obj
C:\git\llvm-project\compiler-rt\lib\interception\interception_win.cpp(746,5): warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough]
746 | case 0xB841: // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
| ^
C:\git\llvm-project\compiler-rt\lib\interception\interception_win.cpp(746,5): note: insert 'FALLTHROUGH;' to silence this warning
746 | case 0xB841: // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
| ^
| FALLTHROUGH;
C:\git\llvm-project\compiler-rt\lib\interception\interception_win.cpp(746,5): note: insert 'break;' to avoid fall-through
746 | case 0xB841: // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
| ^
| break;
1 warning generated.
```
Fixes error: ISO C++20 considers use of overloaded operator '==' (with
operand types 'MacosVersion' and 'MacosVersion') to be ambiguous despite
there being a unique best viable function
[-Werror,-Wambiguous-reversed-operator].
This converts the comparison operator from a non-symmetric operator
(const VersionBase<VersionType>& (as "this") and const VersionType &).
into a symmetric operator
Relands #135068
Co-authored-by: Ivan Tadeu Ferreira Antunes Filho <antunesi@google.com>
In powerpc64-unknown-linux-musl, signal.h does not include asm/ptrace.h,
which causes "member access into incomplete type 'struct pt_regs'"
errors. Include the header explicitly to fix this.
Also in sanitizer_linux_libcdep.cpp, there is a usage of TlsPreTcbSize
which is not defined in such a platform. Guard the branch with macro.
This adds an experimental flag that will keep track of where the manual memory poisoning (`__asan_poison_memory_region`) is called from, and print the stack trace if the poisoned region is accessed. (Absent this flag, ASan will tell you what code accessed a poisoned region, but not which code set the poison.)
This implementation performs best-effort record keeping using ring buffers, as suggested by Vitaly. The size of each ring buffer is set by the `poison_history_size` flag.
Summary:
Previously, we removed the special handling for the code object version
global. I erroneously thought that this meant we cold get rid of this
weird `-Xclang` option. However, this also emits an LLVM IR module flag,
which will then cause linking issues.
Fixes error: ISO C++20 considers use of overloaded operator '==' (with
operand types 'MacosVersion' and 'MacosVersion') to be ambiguous despite
there being a unique best viable function
[-Werror,-Wambiguous-reversed-operator].
This converts the comparison operator from a non-symmetric operator
(const VersionBase<VersionType>& (as "this") and const VersionType &).
into a symmetric operator
TestCases/Linux/asan_rt_confict_test-2.cpp started failing in https://lab.llvm.org/buildbot/#/builders/66/builds/12265/steps/9/logs/stdio
The only change is "[LLD][ELF] Allow merging XO and RX sections, and add --[no-]xosegment flag (#132412)" (2c1bdd4a08). Based on the test case (which deliberately tries to mix static and dynamically linked ASan), I suspect it's actually the test case that needs to be fixed (probably with a different error message check).
This patch disables TestCases/Linux/asan_rt_confict_test-2.cpp to make the buildbots green while I investigate.
This is an optional mechanism that automatically detects roots. It's a best-effort mechanism, and its main goal is to *avoid* pointing at the message pump function as a root. This is the function that polls message queue(s) in an infinite loop, and is thus a bad root (it never exits).
High-level, when collection is requested - which should happen when a server has already been set up and handing requests - we spend a bit of time sampling all the server's threads. Each sample is a stack which we insert in a `PerThreadCallsiteTrie`. After a while, we run for each `PerThreadCallsiteTrie` the root detection logic. We then traverse all the `FunctionData`, find the ones matching the detected roots, and allocate a `ContextRoot` for them. From here, we special case `FunctionData` objects, in `__llvm_ctx_profile_get_context, that have a `CtxRoot` and route them to `__llvm_ctx_profile_start_context`.
For this to work, on the llvm side, we need to have all functions call `__llvm_ctx_profile_release_context` because they _might_ be roots. This comes at a slight (percentages) penalty during collection - which we can afford since the overall technique is ~5x faster than normal instrumentation. We can later explore conditionally enabling autoroot detection and avoiding this penalty, if desired.
Note that functions that `musttail call` can't have their return instrumented this way, and a subsequent patch will harden the mechanism against this case.
The mechanism could be used in combination with explicit root specification, too.
The try-compile mechanism requires that `CMAKE_REQUIRED_FLAGS` is a
space-separated string instead of a list of flags. The original code
expanded `BUILTIN_FLAGS` into `CMAKE_REQUIRED_FLAGS` as a
space-separated string and then would overwrite `CMAKE_REQUIRED_FLAGS`
with `TARGET_${arch}_CFLAGS` prepended to the unexpanded
`BUILTIN_CFLAGS_${arch}`. This resulted in the first two arguments being
passed into the try-compile invocation, but dropping the other arguments
listed in `BUILTIN_CFLAGS_${arch}`.
This patch appends `TARGET_${arch}_CFLAGS` and `BUILTIN_CFLAGS_${arch}` to
`CMAKE_REQUIRED_FLAGS` before expanding CMAKE_REQUIRED_FLAGS as a
space-separated string. This passes any pre-set required flags, in addition to
all of the builtin and target flags to the Float16 detection.
…ncorrect name
Clang needs variables to be represented with unique names. This means
that if a variable shadows another, its given a different name
internally to ensure it has a unique name. If ASan tries to use this
name when printing an error, it will print the modified unique name,
rather than the variable's source code name
Fixes#47326