This is an archive of the discontinued LLVM Phabricator instance.

[test] Fix asan/scudo -shared-libsan tests with -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=on
ClosedPublic

Authored by MaskRay on Aug 27 2021, 10:43 PM.

Details

Summary

On x86_64-unknown-linux-gnu, -m32 tests set LD_LIBRARY_PATH to
config.compiler_rt_libdir ($build/lib/clang/14.0.0/lib/x86_64-unknown-linux-gnu)
instead of i386-unknown-linux-gnu, so -shared-libsan executables
cannot find their runtime (e.g. TestCases/replaceable_new_delete.cpp).

Detect -m32 and -m64 in config.target_cflags, and adjust config.compiler_rt_libdir.

Diff Detail

Event Timeline

MaskRay created this revision.Aug 27 2021, 10:43 PM
MaskRay requested review of this revision.Aug 27 2021, 10:43 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 27 2021, 10:43 PM
MaskRay edited the summary of this revision. (Show Details)Aug 27 2021, 10:49 PM
MaskRay edited the summary of this revision. (Show Details)
delcypher requested changes to this revision.Aug 27 2021, 11:40 PM

I'm not a fan of this change because it breaks the COMPILER_RT_TEST_STANDALONE_BUILD_LIBS feature in a really non-intuitive way because the presence of the -m32 or -m64 flags causes the value of COMPILER_RT_TEST_STANDALONE_BUILD_LIBS to be ignored.

Given that it looks like you're trying to patch the value of config.compiler_rt_libdir it suggests to me that this isn't being set correctly in the CMake code. The initial value of config.compiler_rt_libdir (i.e. before this lit configuration file tries to change it) should always point to the directory where the build system will place those files. Can we fix your issue using that approach instead?

Seeing as you said you didn't understand the COMPILER_RT_TEST_STANDALONE_BUILD_LIBS option in https://reviews.llvm.org/D101681 here's a quick summary.

The whole point of the COMPILER_RT_TEST_STANDALONE_BUILD_LIBS option is to make it explicit which libraries to test when doing a standalone build of compiler-rt. There are two choices when doing a standalone build,

  • the runtime libraries that are part of the toolchain used for the CMake configure of compiler-rt (COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=OFF). This made is very useful for testing arbitrary toolchains (i.e. you can take an arbitrary build of clang and run the Sanitizer test suites against that build of clang). In this mode we don't actually build any libraries, we are assuming they've already been built and are included in the toolchain used by the CMake configure.

OR

  • the runtime libraries built by the standalone build of compiler-rt (COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=ON).

In non standalone configurations (the common case) these happen to be the same. However, in the standalone case it's possible for these to be different. The compiler-rt test suites don't really handle this distinction very well:

  • The majority of the Sanitizer tests assume clang knows where to find the library so changing config.compiler_rt_libdir has no effect. So these test suites don't support COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=ON, currently a warning is emitted when that's the case but it's supposed to be an error.
  • The builtin tests explicitly tell clang where to find the library by using config.compiler_rt_libdir. So these test suites support COMPILER_RT_TEST_STANDALONE_BUILD_LIBS being set to either value.
compiler-rt/test/lit.common.cfg.py
58–60

Why do you need to add config.target_c_flags here?.

get_path_from_clang() already sets the target triple. Isn't that enough?

This revision now requires changes to proceed.Aug 27 2021, 11:40 PM
MaskRay added a comment.EditedAug 27 2021, 11:50 PM

I'm not a fan of this change because it breaks the COMPILER_RT_TEST_STANDALONE_BUILD_LIBS feature in a really non-intuitive way because the presence of the -m32 or -m64 flags causes the value of COMPILER_RT_TEST_STANDALONE_BUILD_LIBS to be ignored.

Given that it looks like you're trying to patch the value of config.compiler_rt_libdir it suggests to me that this isn't being set correctly in the CMake code. The initial value of config.compiler_rt_libdir (i.e. before this lit configuration file tries to change it) should always point to the directory where the build system will place those files. Can we fix your issue using that approach instead?

The Linux multilib scheme tests both i386-unknown-linux-gnu and x86_64-unknown-linux-gnu on x86_64.

compiler-rt/unittests/lit.common.unit.configured.in sets config.compiler_rt_libdir = "@COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR@".

COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR has only one value. how to make config.compiler_rt_libdir $build/lib/clang/14.0.0/lib/i386-unknown-linux-gnu for $build/projects/compiler-rt/test/asan/I386LinuxConfig/lit.site.cfg.py?

MaskRay marked an inline comment as done.Aug 30 2021, 1:01 PM
MaskRay added inline comments.
compiler-rt/test/lit.common.cfg.py
58–60

config.target_cflags is needed to get -m32.

-m32 (not included by get_path_from_clang()) can effectively change the --target= specified triple.

MaskRay marked an inline comment as done.Aug 31 2021, 1:52 PM

Ping other reviewers.

I'm not a fan of this change because it breaks the COMPILER_RT_TEST_STANDALONE_BUILD_LIBS feature in a really non-intuitive way because the presence of the -m32 or -m64 flags causes the value of COMPILER_RT_TEST_STANDALONE_BUILD_LIBS to be ignored.

Given that it looks like you're trying to patch the value of config.compiler_rt_libdir it suggests to me that this isn't being set correctly in the CMake code. The initial value of config.compiler_rt_libdir (i.e. before this lit configuration file tries to change it) should always point to the directory where the build system will place those files. Can we fix your issue using that approach instead?

The Linux multilib scheme tests both i386-unknown-linux-gnu and x86_64-unknown-linux-gnu on x86_64.

Is that something that's actually supported? The only compiler-rt configuration that supports building and testing multiple architectures in the same build that I know of is Apple's build. I think we need to establish if what you're doing is actually supported.

compiler-rt/unittests/lit.common.unit.configured.in sets config.compiler_rt_libdir = "@COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR@".

COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR has only one value. how to make config.compiler_rt_libdir $build/lib/clang/14.0.0/lib/i386-unknown-linux-gnu for $build/projects/compiler-rt/test/asan/I386LinuxConfig/lit.site.cfg.py?

Looking at how config.compiler_rt_libdir gets set now leads to

function(configure_compiler_rt_lit_site_cfg input output)
  set_llvm_build_mode()

  get_compiler_rt_output_dir(${COMPILER_RT_DEFAULT_TARGET_ARCH} output_dir)

  string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} COMPILER_RT_RESOLVED_TEST_COMPILER ${COMPILER_RT_TEST_COMPILER})
  string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR ${output_dir})

  configure_lit_site_cfg(${input} ${output})
endfunction()

There are a few going on here:

  • get_compiler_rt_output_dir() sets the value for output_dir
  • COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR is set to be a modified version of output_dir that supports multi configuration builds. setup_llvm_build_mode() sets LLVM_BUILD_MODE set_llvm_build_mode() will cause LLVM_BUILD_MODE to be set to . or %(build_mode)s. The %(build_mode)s substitution relies on the doing the actually substitution when the lit test suite configuration happens (i.e. config.compiler_rt_libdir = config.compiler_rt_libdir % lit_config.params) see https://reviews.llvm.org/D38471. This complexity exists because at CMake configure time there isn't a single build configuration.

For your particular problem, I think the problem here is that configure_compiler_rt_lit_site_cfg hardcodes the architecture to be COMPILER_RT_DEFAULT_TARGET_ARCH. What you probably want to do is change the configure_compiler_rt_lit_site_cfg function to take an architecture argument so at the use sites of configure_compiler_rt_lit_site_cfg can specify the architecture if you are generating multiple test suites for different architectures.

This on it's own doesn't look like its enough because the function doesn't appear to go over architectures in a loop

configure_compiler_rt_lit_site_cfg(
  ${CMAKE_CURRENT_SOURCE_DIR}/lit.common.unit.configured.in
  ${CMAKE_CURRENT_BINARY_DIR}/lit.common.unit.configured)

So it's unclear to me how you're having multiple lit configurations generated for each architecture in a single build.

If you're not having multiple lit configurations (i.e. you're only building for i386) then looking at the CMake code suggests you need to change COMPILER_RT_DEFAULT_TARGET_ARCH. I think configuring with -DCOMPILER_RT_DEFAULT_TARGET_TRIPLE=i386-unknown-linux-gnu should set COMPILER_RT_DEFAULT_TARGET_ARCH appropriately.

MaskRay added a comment.EditedSep 9 2021, 2:37 PM

I'm not a fan of this change because it breaks the COMPILER_RT_TEST_STANDALONE_BUILD_LIBS feature in a really non-intuitive way because the presence of the -m32 or -m64 flags causes the value of COMPILER_RT_TEST_STANDALONE_BUILD_LIBS to be ignored.

Given that it looks like you're trying to patch the value of config.compiler_rt_libdir it suggests to me that this isn't being set correctly in the CMake code. The initial value of config.compiler_rt_libdir (i.e. before this lit configuration file tries to change it) should always point to the directory where the build system will place those files. Can we fix your issue using that approach instead?

The Linux multilib scheme tests both i386-unknown-linux-gnu and x86_64-unknown-linux-gnu on x86_64.

Is that something that's actually supported? The only compiler-rt configuration that supports building and testing multiple architectures in the same build that I know of is Apple's build. I think we need to establish if what you're doing is actually supported.

It's supported. On an x86_64 Linux, including compiler-rt in LLVM_ENABLE_PROJECTS will test both x86_64 and i386, probably when the host compiler supports -m32.
This is the multilib scheme which is the default on Debian/Ubuntu and their derivatives.
Supporting -m32 is fairly common for other Linux distributions.

Actually I believe -m32 on x86_64 is the only way sanitizers's i386 ports are currently tested on build bots. AFAIK there is no dedicate build bot running i386 Linux.

The be clear, I just want to fix the tests so that D107799 can be re-commited.
The fact that these i386-unknown-linux-gnu tests (through -m32) actually run is the motivation I have to fix this.

If you're not having multiple lit configurations (i.e. you're only building for i386) then looking at the CMake code suggests you need to change COMPILER_RT_DEFAULT_TARGET_ARCH. I think configuring with -DCOMPILER_RT_DEFAULT_TARGET_TRIPLE=i386-unknown-linux-gnu should set COMPILER_RT_DEFAULT_TARGET_ARCH appropriately.

No. The Linux setup doesn't need to touch any of these -DCOMPILER_RT_*.

Running two builds with different -DCOMPILER_RT_DEFAULT_TARGET_TRIPLE is not desired on Linux x86_64.

I don't know what macOS does on this front, but what I said is the Linux x86_64 reality.

@delcypher If COMPILER_RT_TEST_STANDALONE_BUILD_LIBS is really a macOS thing, please give ELF users a way to proceed.

delcypher added a comment.EditedSep 14 2021, 11:57 AM

@delcypher If COMPILER_RT_TEST_STANDALONE_BUILD_LIBS is really a macOS thing, please give ELF users a way to proceed.

COMPILER_RT_TEST_STANDALONE_BUILD_LIBS is not a macOS specific thing at all.

To proceed you need to either

Investigate fixing COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR to be set correctly in CMake for your configuration so that when the lit configuration file is generated it is correct for your configuration. This would be my preference because everything you've said so far suggests this value is wrong for your configuration, so fixing it the wrong information at its source seems like the right fix.

OR if that isn't possible (please explain why)

Change compiler-rt/test/lit.common.cfg.py to modify config.compiler_rt_libdir but do that before the logic under # Ask the compiler for the path to libraries it is going to use... runs so that config.test_standalone_build_libs is respected regardless of what is in config.target_c_flags. Your current patch breaks the semantics of config.test_standalone_build_libs and also makes the code harder to read which is why I don't approve of the patch in its current form.

MaskRay updated this revision to Diff 372549.Sep 14 2021, 1:23 PM
MaskRay edited the summary of this revision. (Show Details)

better fix

When the build directory is /tmp/RelA, /tmp/RelA/projects/compiler-rt/test/lit.common.configured says config.compiler_rt_libdir = "/tmp/RelA/./lib/clang/14.0.0/lib/x86_64-unknown-linux-gnu"

The x86_64 asan archive is at /tmp/RelA/lib/clang/14.0.0/lib/x86_64-unknown-linux-gnu/libclang_rt.asan.a and the i386 archive is at /tmp/RelA/./lib/clang/14.0.0/lib/i386-unknown-linux-gnu/libclang_rt.asan.a.

COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR is the native library directory "/tmp/RelA/./lib/clang/14.0.0/lib/x86_64-unknown-linux-gnu".
For multilib -m32, adjusting the trailing path component seems to make the most sense.


I cannot find any useful documentation about "standalone build" but I guess I figured it out:

# my ~/llvm is llvm-project
% cd /tmp/out/play
% cmake -GNinja -H~/llvm/compiler-rt -B/tmp/out/play -DCMAKE_C_COMPILER=/tmp/RelA/bin/clang -DCMAKE_CXX_COMPILER=/tmp/RelA/bin/clang++ -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=on -DCOMPILER_RT_DEFAULT_TARGET_TRIPLE=x86_64-unknown-linux-gnu -DCOMPILER_RT_INCLUDE_TESTS=on -DCOMPILER_RT_TEST_STANDALONE_BUILD_LIBS=on
% ninja check-asan

All tests passed. So this patch makes -DCOMPILER_RT_TEST_STANDALONE_BUILD_LIBS=on work as well, though I don't understand why ... we want to support the extra (standalone) configuration mode for tests.
Test a clang built at slightly different commit to test runtime stability?

For some reason I need to specify -DCOMPILER_RT_DEFAULT_TARGET_TRIPLE=x86_64-unknown-linux-gnu, otherwise it would be incorrect (x86_64-pc-linux-gnu).

I don't understand why ... we want to support the extra (standalone) configuration mode for tests.

GCC uses these libs as well

vitalybuka accepted this revision as: vitalybuka.Sep 14 2021, 3:28 PM
This revision was not accepted when it landed; it landed in state Needs Review.Sep 15 2021, 9:07 AM
This revision was automatically updated to reflect the committed changes.