tests: LD_PRELOAD libstdc++.so in bt_run_in_py_env
authorSimon Marchi <simon.marchi@efficios.com>
Tue, 23 Apr 2024 03:44:04 +0000 (23:44 -0400)
committerSimon Marchi <simon.marchi@efficios.com>
Tue, 23 Apr 2024 15:03:08 +0000 (11:03 -0400)
With an ASan build on Debian 12 or Ubuntu 22.04 (and probably others),
some tests (test-query-trace-info.sh, test-python-bt2.sh), fail because
of what boils down to this:

    $ /home/smarchi/src/babeltrace/tests/utils/run-in-py-env.sh  python3 /home/smarchi/src/babeltrace/tests/plugins/src.ctf.fs/query/test_query_trace_info.py
    ..AddressSanitizer: CHECK failed: asan_interceptors.cpp:320 "((__interception::real___cxa_throw)) != (0)" (0x0, 0x0) (tid=139166)
        #0 0x7fc2bbf9b2aa in CheckUnwind ../../../../src/libsanitizer/asan/asan_rtl.cpp:67
        #1 0x7fc2bbfbbc55 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) ../../../../src/libsanitizer/sanitizer_common/sanitizer_termination.cpp:86
        #2 0x7fc2bbf22924 in __interceptor___cxa_throw ../../../../src/libsanitizer/asan/asan_interceptors.cpp:320
        #3 0x7fc2b8f5ea05 in void bt2c::Logger::logErrorAndThrow<true, bt2c::Error, char*&>(char const*, char const*, unsigned int, char const*, char*&) const /home/smarchi/src/babeltrace/src/cpp-common/bt2c/logging.hpp:316
        #4 0x7fc2b8f5ea05 in read_src_fs_parameters(bt2::CommonMapValue<bt_value const>, bt2c::Logger const&) /home/smarchi/src/babeltrace/src/plugins/ctf/fs-src/fs.cpp:1516
        #5 0x7fc2b903e4ca in trace_infos_query(bt2::CommonMapValue<bt_value const>, bt2c::Logger const&) /home/smarchi/src/babeltrace/src/plugins/ctf/fs-src/query.cpp:168
        #6 0x7fc2b9019206 in ctf_fs_query(bt_self_component_class_source*, bt_private_query_executor*, char const*, bt_value const*, void*, bt_value const**) /home/smarchi/src/babeltrace/src/plugins/ctf/fs-src/fs.cpp:1609
        #7 0x7fc2b980eed0 in bt_query_executor_query /home/smarchi/src/babeltrace/src/lib/graph/query-executor.c:221
        #8 0x7fc2ba2d8c86 in _wrap_query_executor_query bt2/native_bt.c:19262
        #9 0x5458a2 in cfunction_vectorcall_O ../Objects/methodobject.c:514
... lots of Python stack frames ...
        #75 0x64f90e in pymain_run_file_obj ../Modules/main.c:360
        #76 0x64f90e in pymain_run_file ../Modules/main.c:379
        #77 0x64f90e in pymain_run_python ../Modules/main.c:601
        #78 0x64f90e in Py_RunMain ../Modules/main.c:680
        #79 0x6275c6 in Py_BytesMain ../Modules/main.c:734
        #80 0x7fc2bbbf0249 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
        #81 0x7fc2bbbf0304 in __libc_start_main_impl ../csu/libc-start.c:360
        #82 0x627460 in _start (/usr/bin/python3.11+0x627460)

The problem is documented here [1].

The summary is (to the best of my understanding):

 - we run python3 with a script that imports the bt2 Python module,
   which eventually loads libbabeltrace2.so
 - libbabeltrace2.so is built with ASan, so depends on libasan.so
 - if we just try to run this as is, libasan.so complains that it's not
   the first loaded shared library, so we LD_PRELOAD it
 - now, when libasan.so is initialized, libstdc++ is not loaded, so some
   things related to C++ (like the __interception::real___cxa_throw
   variable) are not initialized
 - libbabeltrace2.so and libstdc++.so are eventually loaded, something
   in the test happens to throw an exception
 - this is intercepted by libasan.so (through symbol interposition of
   __cxa_throw I suppose)
 - the assertion that real___cxa_throw must not be NULL fails

Debian and Ubuntu systems are affected because of their use of
-Wl,--as-needed.  The build system of ASan makes libasan.so link against
libstdc++ (to ensure that libstdc++ is loaded along with libasan.so),
but that dependency is dropped du to -Wl,--as-needed.

A solution I used during development (and this is why I failed to see
the problem sooner I suppose) was to add a libstdc++ dependency in
/usr/bin/python3.  This is obviously not possible at large.

The only applicable solution I see to keep ASan builds working is to
LD_PRELOAD libstdc++.so along with libasan.so.  This emulates the
missing libasan.so -> libstdc++.so dependency.

[1] https://github.com/google/sanitizers/issues/934

Change-Id: I10c53347167a7f68cb2fb2e8c08a98ff2b638ffc
Reviewed-on: https://review.lttng.org/c/babeltrace/+/12446
Reviewed-by: Michael Jeanson <mjeanson@efficios.com>
CI-Build: Simon Marchi <simon.marchi@efficios.com>
Tested-by: jenkins <jenkins@lttng.org>
tests/utils/utils.sh

index 9081a88e2e871324448adfc0620bae33db4cc4fb..692def5d7656d58e7b68e39b99481b038dbdf401 100644 (file)
@@ -430,7 +430,8 @@ bt_run_in_py_env() {
        if [[ ${BT_TESTS_ENABLE_ASAN:-} == 1 ]]; then
                if $BT_TESTS_CC_BIN --version | head -n 1 | bt_grep -q '^gcc'; then
                        local -r lib_asan=$($BT_TESTS_CC_BIN -print-file-name=libasan.so)
-                       local -x LD_PRELOAD=$lib_asan${LD_PRELOAD:+:}${LD_PRELOAD:-}
+                       local -r lib_stdcxx=$($BT_TESTS_CC_BIN -print-file-name=libstdc++.so)
+                       local -x LD_PRELOAD=$lib_asan:$lib_stdcxx${LD_PRELOAD:+:}${LD_PRELOAD:-}
                fi
 
                local -x ASAN_OPTIONS=${ASAN_OPTIONS:-}${ASAN_OPTIONS:+,}detect_leaks=0
This page took 0.02554 seconds and 4 git commands to generate.