llvm / llvm/llvm-project

Testing flang and flang-rt with sanitizers enabled

Open
#221,752 3 comments 0 reactions 0 assignees View on GitHub
flang flang:runtime test-suite
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

This is a feature request / progress report for the following:
* Ability to build Flang and flang-rt built with sanitizers enabled.
* Ability to check-flang, check-flang-rt, and run the llvm-test-suite's Fortran
tests.

Which is something we have been experimenting with but is not yet supported. I'll show how far we can get with no changes fist, then finally what we can do with some hacks (https://github.com/llvm/llvm-project/pull/221753) to prove the concept.

All of these need `export ASAN_OPTIONS=detect_leaks=0`.

# Version 1: All-in-one / bootstrapping build

```console
$ export ASAN_OPTIONS=detect_leaks=0
$ mkdir build-llvm && cd build-llvm
$ cmake -DCMAKE_CXX_STANDARD=17 -DLLVM_ENABLE_WERROR=OFF \
-DLLVM_ENABLE_ASSERTIONS=OFF -DCMAKE_BUILD_TYPE=Release \
'-DLLVM_ENABLE_PROJECTS=clang;mlir;llvm;flang' \
-DLLVM_ENABLE_RUNTIMES="compiler-rt;flang-rt" \
-DCOMPILER_RT_BUILD_SANITIZERS=OFF \
'-DCMAKE_INSTALL_PREFIX=/home/davspi01/llvm.install/' \
-DLLVM_USE_SANITIZER="Address;Undefined" \
-DLLVM_CCACHE_BUILD=ON \
-GNinja ../llvm-project/llvm
$ ninja && ninja check-flang && ninja check-flang-rt
```

We do not enable sanitizers here because we want everything to be using the host
compiler's sanitizer libraries.

(HEAD is 8436dd4a2bfe57d0b3fb6c9c11c69d75c1d1bccb)

Flang is sanitized:

```console
$ nm ./bin/flang-24 | grep __asan_report
00000000097553a8 t ____asan_report_load16_veneer
<...>
```

We get 1 test failure:

```
Failed Tests (1):
Flang :: Semantics/oversized-storage-sequence.f90
```

`ninja check-flang-rt` fails to link the unit tests:

```
/usr/bin/aarch64-linux-gnu-ld.bfd: /usr/lib/gcc/aarch64-linux-gnu/15/../../../../include/c++/15/bits/stl_algobase.h:407:(.text._ZSt14__copy_move_a2ILb0EPPKN4llvm16itanium_demangle4NodeES5_S5_ET2_T0_T1_S6_[_ZSt14__copy_move_a2ILb0EPPKN4llvm16itanium_demangle4NodeES5_S5_ET2_T0_T1_S6_]+0x13c): undefined reference to `__asan_report_store8'
<...and many others...>
```
This happens not because flang-rt is sanitized:
```
$ nm lib/clang/24/lib/aarch64-unknown-linux-gnu/libflang_rt.runtime.a | grep asan

```

It's because the llvm support libraries that the unit test uses are sanitized:

```
FAILED: [code=1] flang-rt/unittests/Evaluate/ISO-Fortran-binding.test
<...>
usr/bin/aarch64-linux-gnu-ld.bfd: /home/davspi01/build-llvm/lib/libLLVMSupport.a(raw_ostream.cpp.o): in function `llvm::raw_ostream::~raw_ostream()':
/home/davspi01/llvm-project/llvm/lib/Support/raw_ostream.cpp:65:(.text.unlikely._ZN4llvm11raw_ostreamD0Ev+0x8): undefined reference to `__asan_handle_no_return'
```

## Summary

* Can check sanitized flang.
* Cannot check flang-rt (and it's not sanitized).
* Can run llvm-test-suite (but flang-rt is not sanitized).

# Version 2: Out of tree flang only

Assume we care only about the flang binary. The only way to stop flang adding
flang-rt to ENABLE_RUNTIMES is to build flang standalone. So first build
llvm/clang/mlir and builtins:

```console
$ mkdir build-clang && cd build-clang
$ cmake -DCMAKE_CXX_STANDARD=17 -DLLVM_ENABLE_WERROR=OFF \
-DLLVM_ENABLE_ASSERTIONS=OFF -DCMAKE_BUILD_TYPE=Release \
'-DLLVM_ENABLE_PROJECTS=clang;mlir;llvm' \
-DLLVM_ENABLE_RUNTIMES="compiler-rt" \
-DCOMPILER_RT_BUILD_SANITIZERS=OFF \
'-DCMAKE_INSTALL_PREFIX=/home/davspi01/llvm.install/' \
-DLLVM_USE_SANITIZER="Address;Undefined" \
-DLLVM_CCACHE_BUILD=ON \
-GNinja ../llvm-project/llvm
$ ninja && ninja install
$ cd ..
```

Then build flang using the previous build's components:

```console
$ mkdir build-flang && cd build-flang
$ cmake -DFLANG_ENABLE_WERROR=ON -DCMAKE_BUILD_TYPE=Release -GNinja \
-DLLVM_USE_SANITIZER="Address;Undefined" \
-DLLVM_DIR:PATH=../build-clang/lib/cmake/llvm \
-DMLIR_DIR:PATH=../build-clang/lib/cmake/mlir \
-DCLANG_DIR:PATH=../build-clang/lib/cmake/clang \
-DCMAKE_INSTALL_PREFIX=/home/davspi01/llvm.install ../llvm-project/flang/
$ ninja && ninja check-flang
$ cd ..
```

And you could run the llvm-test-suite, I'll show that command later, it's pretty
standard though.

## Summary

* Can check flang.
* Cannot check flang-rt.
* Cannot run llvm-test-suite.

# Version 3: Out of tree flang + unsanitized flang-rt + llvm-test-suite

Do the previous build and then install flang:

```console
$ ninja install
```

Then build flang-rt standalone without sanitizers:

```console
$ mkdir build-flang-rt && cd build-flang-rt
$ /home/davspi01/cmake-3.31.12/bin/cmake -G Ninja \
../llvm-project/runtimes \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/home/davspi01/llvm.install \
-DLLVM_ENABLE_RUNTIMES=flang-rt \
-DLLVM_BINARY_DIR=/home/davspi01/build-clang \
-DCMAKE_Fortran_COMPILER=/home/davspi01/llvm.install/bin/flang \
-DCMAKE_Fortran_COMPILER_WORKS=ON
$ ninja && ninja install
$ cd ..
```

`ninja check-flang-rt` fails because the unit tests use llvm support libraries
that need sanitizers.

## Summary

* Can check flang.
* ~~Can check flang-rt, but it is not sanitized.~~ You cannot check flang-rt, because the llvm libraries it uses are themselves sanitised. You need to add the library path to get it to compile.
* Can run llvm-test suite, but flang-rt is not sanitized.

This is the closest you can get today without source changes.

# Version 4: Out of tree flang, out of tree flang-rt, llvm-test-suite (requires patches)

Redo the version 3 flang-rt build but with the following patches applied https://github.com/llvm/llvm-project/pull/221753.

Then build flang-rt with sanitizers enabled:

```console
$ mkdir build-flang-rt && cd build-flang-rt
$ /home/davspi01/cmake-3.31.12/bin/cmake -G Ninja \
../llvm-project/runtimes \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/home/davspi01/llvm.install \
-DLLVM_ENABLE_RUNTIMES=flang-rt \
-DLLVM_BINARY_DIR=/home/davspi01/build-clang \
-DCMAKE_Fortran_COMPILER=/home/davspi01/llvm.install/bin/flang \
-DCMAKE_Fortran_COMPILER_WORKS=ON \
-DLLVM_USE_SANITIZER='Address;Undefined'
$ ninja && ninja install
$ ninja check-flang-rt
$ cd ..
```

* The Fortran compiler is the one built in the previous step.
* You need a recent enough CMake for it to recognise Flang out of the box.
* `CMAKE_Fortran_COMPILER_WORKS` saves us from having to pass extra linker flags
to Flang just to pass the CMake compiler checks. You'll see those flags later.
* The C++ compiler is the host compiler.

Some tests have been marked as unsupported with ASAN because they break two assumptions flang-rt makes:
* It will have no C++ dependencies (we have just added one in the form of a sanitizer)
* It will have no extra symbols than some expected set (ASAN makes a bunch of prefixed names)

Now we have a full toolchain, we can run llvm-test-suite:

```console
$ mkdir build-llvm-test-suite && cd build-llvm-test-suite
$ /home/davspi01/cmake-3.31.12/bin/cmake -G Ninja ../llvm-test-suite/ \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_Fortran_COMPILER=/home/davspi01/llvm.install/bin/flang \
-DCMAKE_Fortran_FLAGS="-Wl,--whole-archive,$($CC --print-runtime-dir)/libclang_rt.asan_static.a,--no-whole-archive -Wl,--whole-archive,$($CC --print-runtime-dir)/libclang_rt.asan.a,--no-whole-archive" \
-DTEST_SUITE_FORTRAN=ON \
-DTEST_SUITE_SUBDIRS=Fortran
$ ninja
$ ~/build-clang/bin/llvm-lit -sv .
```

* The linker flags are required because flang-rt requires the sanitizer
libraries.
* As these are passed in `CMAKE_Fortran_FLAGS`, you will get piles of warnings
about unused linker inputs. I tried moving the flags to
`CMAKE_EXE_LINKER_FLAGS`, but that broke C++ compiler detection.

Several tests fail and at least one times out:

```
Failed Tests (7):
test-suite :: Fortran/gfortran/regression/gfortran-regression-execute-regression__PR100136_f90.test
test-suite :: Fortran/gfortran/regression/gfortran-regression-execute-regression__bounds_check_fail_5_f90.test
test-suite :: Fortran/gfortran/regression/gfortran-regression-execute-regression__pointer_check_1_f90.test
test-suite :: Fortran/gfortran/regression/gfortran-regression-execute-regression__pointer_check_2_f90.test
test-suite :: Fortran/gfortran/regression/gfortran-regression-execute-regression__pointer_check_3_f90.test
test-suite :: Fortran/gfortran/regression/gfortran-regression-execute-regression__pointer_check_4_f90.test
test-suite :: Fortran/gfortran/regression/gfortran-regression-execute-regression__pr92050_f90.test
```

Many of these are to do with Flang's own safety checks. Perhaps the addition of
ASAN gets in the way of those. I did not dig any further.

## Summary

* Can check flang.
* Can check flang-rt.
* Can run llvm-test-suite.
* Needs a significant amount of work to get there.

Contributor guide

Open the contributing guide

Research direction

Start with the build commands in the issue for flang, flang-rt, and llvm-test-suite, then inspect the linked PR 221753 and the relevant CMake configuration under flang and runtimes. Reproduce the sanitizer-enabled checks and identify the changes needed for sanitized flang-rt and the Fortran test suite. Done means the flang and flang-rt checks and llvm-test-suite Fortran tests run successfully with sanitizers.

Written by the indexing model from the issue text.

Assessment

Tech stack
cmake, fortran
Domain
build-system, compilers, testing-qa
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.