jeremy-rifkin/cpptrace

Tests fails when compiling with LTO

Closed this issue · 10 comments

Not critical, but thought it would be good to keep a record of it.

gcc: 14.2.1
cpptrace: 0.7.2
gtest: 1.14.0

Full log:

Running main() from /var/tmp/portage/dev-cpp/gtest-1.14.0-r1/work/googletest-1.14.0/googletest/src/gtest_main.cc
[==========] Running 18 tests from 6 test suites.
[----------] Global test environment set-up.
[----------] 1 test from TracedException
[ RUN      ] TracedException.Basic
[       OK ] TracedException.Basic (30 ms)
[----------] 1 test from TracedException (30 ms total)

[----------] 3 tests from FromCurrentZ
[ RUN      ] FromCurrentZ.Basic
/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/from_current_z.cpp:56: Failure
Expected equality of these values:
  trace.frames[i].line.value()
    Which is: 37
  line_numbers[j]
    Which is: 20

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/from_current_z.cpp:57: Failure
Value of: trace.frames[i].symbol
Expected: has substring "stacktrace_from_current_z_3"
  Actual: "FromCurrentZ_Basic_Test::TestBody()"

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/from_current_z.cpp:62: Failure
Value of: trace.frames[i].filename
Expected: ends with "from_current_z.cpp"
  Actual: "/usr/lib64/libgtest.so.1.14.0"

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/from_current_z.cpp:63: Failure
Expected equality of these values:
  trace.frames[i].line.value()
    Which is: 4294967295
  line_numbers[j]
    Which is: 25

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/from_current_z.cpp:64: Failure
Value of: trace.frames[i].symbol
Expected: has substring "stacktrace_from_current_z_2"
  Actual: ""

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/from_current_z.cpp:69: Failure
Value of: trace.frames[i].filename
Expected: ends with "from_current_z.cpp"
  Actual: "/usr/lib64/libgtest.so.1.14.0"

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/from_current_z.cpp:70: Failure
Expected equality of these values:
  trace.frames[i].line.value()
    Which is: 4294967295
  line_numbers[j]
    Which is: 30

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/from_current_z.cpp:71: Failure
Value of: trace.frames[i].symbol
Expected: has substring "stacktrace_from_current_z_1"
  Actual: ""

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/from_current_z.cpp:76: Failure
Value of: trace.frames[i].filename
Expected: ends with "from_current_z.cpp"
  Actual: "/usr/lib64/libgtest.so.1.14.0"

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/from_current_z.cpp:77: Failure
Expected equality of these values:
  trace.frames[i].line.value()
    Which is: 4294967295
  line_numbers[j]
    Which is: 37

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/from_current_z.cpp:78: Failure
Value of: trace.frames[i].symbol
Expected: has substring "FromCurrentZ_Basic_Test::TestBody"
  Actual: ""

[  FAILED  ] FromCurrentZ.Basic (3 ms)
[ RUN      ] FromCurrentZ.CorrectHandler
[       OK ] FromCurrentZ.CorrectHandler (0 ms)
[ RUN      ] FromCurrentZ.RawTrace
[       OK ] FromCurrentZ.RawTrace (0 ms)
[----------] 3 tests from FromCurrentZ (3 ms total)

[----------] 3 tests from FromCurrent
[ RUN      ] FromCurrent.Basic
[       OK ] FromCurrent.Basic (0 ms)
[ RUN      ] FromCurrent.CorrectHandler
[       OK ] FromCurrent.CorrectHandler (0 ms)
[ RUN      ] FromCurrent.RawTrace
[       OK ] FromCurrent.RawTrace (0 ms)
[----------] 3 tests from FromCurrent (0 ms total)

[----------] 5 tests from Stacktrace
[ RUN      ] Stacktrace.Empty
[       OK ] Stacktrace.Empty (0 ms)
[ RUN      ] Stacktrace.Basic
[       OK ] Stacktrace.Basic (8 ms)
[ RUN      ] Stacktrace.MultipleFrames
/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/stacktrace.cpp:57: Failure
Expected equality of these values:
  trace.frames[i].line.value()
    Which is: 77
  line_numbers[i]
    Which is: 72

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/stacktrace.cpp:58: Failure
Value of: trace.frames[i].symbol
Expected: has substring "stacktrace_multi_2"
  Actual: "stacktrace_multi_1(std::vector<int, std::allocator<int> >&)"

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/stacktrace.cpp:61: Failure
Expected equality of these values:
  trace.frames[i].line.value()
    Which is: 83
  line_numbers[i]
    Which is: 77

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/stacktrace.cpp:62: Failure
Value of: trace.frames[i].symbol
Expected: has substring "stacktrace_multi_1"
  Actual: "Stacktrace_MultipleFrames_Test::TestBody()"

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/stacktrace.cpp:64: Failure
Value of: trace.frames[i].filename
Expected: ends with "stacktrace.cpp"
  Actual: "/usr/lib64/libgtest.so.1.14.0"

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/stacktrace.cpp:65: Failure
Expected equality of these values:
  trace.frames[i].line.value()
    Which is: 4294967295
  line_numbers[i]
    Which is: 83

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/stacktrace.cpp:66: Failure
Value of: trace.frames[i].symbol
Expected: has substring "Stacktrace_MultipleFrames_Test::TestBody"
  Actual: ""

[  FAILED  ] Stacktrace.MultipleFrames (0 ms)
[ RUN      ] Stacktrace.RawTraceResolution
[       OK ] Stacktrace.RawTraceResolution (0 ms)
[ RUN      ] Stacktrace.InlineResolution
[       OK ] Stacktrace.InlineResolution (0 ms)
[----------] 5 tests from Stacktrace (8 ms total)

[----------] 4 tests from ObjectTrace
[ RUN      ] ObjectTrace.Empty
[       OK ] ObjectTrace.Empty (0 ms)
[ RUN      ] ObjectTrace.Basic
[       OK ] ObjectTrace.Basic (0 ms)
[ RUN      ] ObjectTrace.BasicResolution
[       OK ] ObjectTrace.BasicResolution (0 ms)
[ RUN      ] ObjectTrace.Resolution
/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/object_trace.cpp:79: Failure
Expected equality of these values:
  trace.frames[i].line.value()
    Which is: 99
  line_numbers[i]
    Which is: 94

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/object_trace.cpp:80: Failure
Value of: trace.frames[i].symbol
Expected: has substring "object_resolve_2"
  Actual: "object_resolve_1(std::vector<int, std::allocator<int> >&)"

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/object_trace.cpp:83: Failure
Expected equality of these values:
  trace.frames[i].line.value()
    Which is: 105
  line_numbers[i]
    Which is: 99

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/object_trace.cpp:84: Failure
Value of: trace.frames[i].symbol
Expected: has substring "object_resolve_1"
  Actual: "ObjectTrace_Resolution_Test::TestBody()"

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/object_trace.cpp:86: Failure
Value of: trace.frames[i].filename
Expected: ends with "object_trace.cpp"
  Actual: "/usr/lib64/libgtest.so.1.14.0"

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/object_trace.cpp:87: Failure
Expected equality of these values:
  trace.frames[i].line.value()
    Which is: 4294967295
  line_numbers[i]
    Which is: 105

/var/tmp/portage/dev-cpp/cpptrace-0.7.2/work/cpptrace-0.7.2/test/unit/object_trace.cpp:88: Failure
Value of: trace.frames[i].symbol
Expected: has substring "ObjectTrace_Resolution_Test::TestBody"
  Actual: ""

[  FAILED  ] ObjectTrace.Resolution (0 ms)
[----------] 4 tests from ObjectTrace (0 ms total)

[----------] 2 tests from RawTrace
[ RUN      ] RawTrace.Basic
[       OK ] RawTrace.Basic (0 ms)
[ RUN      ] RawTrace.MultipleCalls
[       OK ] RawTrace.MultipleCalls (0 ms)
[----------] 2 tests from RawTrace (0 ms total)

[----------] Global test environment tear-down
[==========] 18 tests from 6 test suites ran. (42 ms total)
[  PASSED  ] 15 tests.
[  FAILED  ] 3 tests, listed below:
[  FAILED  ] FromCurrentZ.Basic
[  FAILED  ] Stacktrace.MultipleFrames
[  FAILED  ] ObjectTrace.Resolution

 3 FAILED TESTS

Thanks for opening this, definitely feels worth investigating.

I tried throwing set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) in the cmake and building with cmake -S . -B build -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DCPPTRACE_BUILD_TESTING=On -DBUILD_SHARED_LIBS=Off && cmake --build build but I wasn't able to reproduce the unit tests failing. More info would be helpful.

I used the next commands

export CFLAGS=-flto=auto
export CXXFLAGS=-flto=auto
export LDFLAGS=-flto=auto
mkdir build && cd build && cmake -DCPPTRACE_BUILD_TESTING=On -DBUILD_SHARED_LIBS=Off ..

Thanks, I gave that a try and saw failures with FromCurrentZ.Basic but not any of the other failures. I'll take a look and test on some other platforms too.

Pushed a fix for why FromCurrentZ.Basic was failing for me locally

Great! I don't know why the other tests fails only for me though. May be related with the GCC version? Which version do you use?

Yeah it could very well be that gcc 14 is doing something new with LTO. I would have to check what version I used but definitely older. I’ll give it a try with 14 when I am able. What platform are you on btw? And do you know what linker?

Gentoo. I'm using the default GCC linker, ld.bfd (GNU ld (Gentoo 2.43 p2) 2.43.1)

I reproduced with

export CFLAGS=-flto=auto
export CXXFLAGS=-flto=auto
export LDFLAGS=-flto=auto
mkdir build && cd build && cmake && cmake .. -DCPPTRACE_BUILD_TESTING=On -DBUILD_SHARED_LIBS=Off -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_C_COMPILER=gcc-14
make -j && ./unittest

Looking into ObjectTrace.Resolution:
The trace generated by the test is

Stack trace (most recent call first):
#0 0x0000000000000000 in object_resolve_3(std::vector<int, std::allocator<int> >&) at /mnt/c/Users/rifkin/home/projects/cpptrace/test/unit/object_trace.cpp:56:43
#1 0x0000000000000000 in object_resolve_1(std::vector<int, std::allocator<int> >&) at /mnt/c/Users/rifkin/home/projects/cpptrace/test/unit/object_trace.cpp:105:28
#2 0x0000000000000000 in ObjectTrace_Resolution_Test::TestBody() at /mnt/c/Users/rifkin/home/projects/cpptrace/test/unit/object_trace.cpp:111:21
#3 0x0000000000000000 at /mnt/c/Users/rifkin/home/projects/cpptrace/build/unittest

The frame for object_resolve_2 is missing. This frame is also missing in gdb so I don't think it's a library bug.

Looking at objdump:

0000000000024650 <ObjectTrace_Resolution_Test::TestBody()>:
...
   2469f:	e8 3c fe ff ff       	call   244e0 <object_resolve_1(std::vector<int, std::allocator<int> >&)>

00000000000244e0 <object_resolve_1(std::vector<int, std::allocator<int> >&)>:
...
   24546:	e8 f5 b0 0a 00       	call   cf640 <object_resolve_2(std::vector<int, std::allocator<int> >&) [clone .isra.0]>

00000000000cf640 <object_resolve_2(std::vector<int, std::allocator<int> >&) [clone .isra.0]>:
...
   cf6b8:	e9 63 e6 ff ff       	jmp    cdd20 <object_resolve_3(std::vector<int, std::allocator<int> >&) [clone .isra.0]>

I think it's just an issue of the call being TCO'd by LTO, despite my effort to prevent that from happening

0.7.3 is released