diff --git a/test/unit/from_current.cpp b/test/unit/from_current.cpp index 990afbe..02d4346 100644 --- a/test/unit/from_current.cpp +++ b/test/unit/from_current.cpp @@ -13,21 +13,24 @@ using namespace std::literals; -// NOTE: returning something and then return stacktrace_from_current_3(line_numbers) * 2; later helps prevent the call from -// being optimized to a jmp +// NOTE: returning something and then return stacktrace_multi_3(line_numbers) * rand(); is done to prevent TCO even +// under LTO https://github.com/jeremy-rifkin/cpptrace/issues/179#issuecomment-2467302052 CPPTRACE_FORCE_NO_INLINE int stacktrace_from_current_3(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); throw std::runtime_error("foobar"); } CPPTRACE_FORCE_NO_INLINE int stacktrace_from_current_2(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); - return stacktrace_from_current_3(line_numbers) * 2; + return stacktrace_from_current_3(line_numbers) * rand(); } CPPTRACE_FORCE_NO_INLINE int stacktrace_from_current_1(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); - return stacktrace_from_current_2(line_numbers) * 2; + return stacktrace_from_current_2(line_numbers) * rand(); } TEST(FromCurrent, Basic) { diff --git a/test/unit/from_current_z.cpp b/test/unit/from_current_z.cpp index 95462ac..e3b837f 100644 --- a/test/unit/from_current_z.cpp +++ b/test/unit/from_current_z.cpp @@ -13,27 +13,24 @@ using namespace std::literals; -// NOTE: returning something and then return stacktrace_from_current_3(line_numbers) * 2; later helps prevent the call from -// being optimized to a jmp +// NOTE: returning something and then return stacktrace_multi_3(line_numbers) * rand(); is done to prevent TCO even +// under LTO https://github.com/jeremy-rifkin/cpptrace/issues/179#issuecomment-2467302052 CPPTRACE_FORCE_NO_INLINE int stacktrace_from_current_z_3(std::vector& line_numbers) { - // just here to differentiate from the non-z version to prevent ICF if LTO is being used - [[maybe_unused]] volatile int x = 1; + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); throw std::runtime_error("foobar"); } CPPTRACE_FORCE_NO_INLINE int stacktrace_from_current_z_2(std::vector& line_numbers) { - // just here to differentiate from the non-z version to prevent ICF if LTO is being used - [[maybe_unused]] volatile int x = 1; + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); - return stacktrace_from_current_z_3(line_numbers) * 2; + return stacktrace_from_current_z_3(line_numbers) * rand(); } CPPTRACE_FORCE_NO_INLINE int stacktrace_from_current_z_1(std::vector& line_numbers) { - // just here to differentiate from the non-z version to prevent ICF if LTO is being used - [[maybe_unused]] volatile int x = 1; + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); - return stacktrace_from_current_z_2(line_numbers) * 2; + return stacktrace_from_current_z_2(line_numbers) * rand(); } TEST(FromCurrentZ, Basic) { diff --git a/test/unit/object_trace.cpp b/test/unit/object_trace.cpp index b34155e..232bec1 100644 --- a/test/unit/object_trace.cpp +++ b/test/unit/object_trace.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -19,6 +20,7 @@ TEST(ObjectTrace, Empty) { CPPTRACE_FORCE_NO_INLINE void object_basic() { + static volatile int lto_guard; lto_guard = lto_guard + 1; auto trace = cpptrace::generate_object_trace(); EXPECT_FALSE(trace.empty()); EXPECT_NE(trace.frames[0].raw_address, 0); @@ -33,6 +35,7 @@ TEST(ObjectTrace, Basic) { CPPTRACE_FORCE_NO_INLINE void object_basic_resolution() { + static volatile int lto_guard; lto_guard = lto_guard + 1; auto line = __LINE__ + 1; auto trace = cpptrace::generate_object_trace().resolve(); ASSERT_GE(trace.frames.size(), 1); @@ -49,6 +52,7 @@ TEST(ObjectTrace, BasicResolution) { // TODO: dbghelp uses raw address, not object #ifndef _MSC_VER CPPTRACE_FORCE_NO_INLINE int object_resolve_3(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); auto dummy = cpptrace::generate_trace(); auto dummy_otrace = cpptrace::generate_object_trace(); @@ -89,14 +93,18 @@ CPPTRACE_FORCE_NO_INLINE int object_resolve_3(std::vector& line_numbers) { return 2; } +// NOTE: returning something and then return stacktrace_multi_3(line_numbers) * rand(); is done to prevent TCO even +// under LTO https://github.com/jeremy-rifkin/cpptrace/issues/179#issuecomment-2467302052 CPPTRACE_FORCE_NO_INLINE int object_resolve_2(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); - return object_resolve_3(line_numbers) * 2; + return object_resolve_3(line_numbers) * rand(); } CPPTRACE_FORCE_NO_INLINE int object_resolve_1(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); - return object_resolve_2(line_numbers) * 2; + return object_resolve_2(line_numbers) * rand(); } TEST(ObjectTrace, Resolution) { diff --git a/test/unit/raw_trace.cpp b/test/unit/raw_trace.cpp index b5a2715..2f72e31 100644 --- a/test/unit/raw_trace.cpp +++ b/test/unit/raw_trace.cpp @@ -18,6 +18,7 @@ using namespace std::literals; // NOTE: MSVC likes creating trampoline-like entries for non-static functions CPPTRACE_FORCE_NO_INLINE static void raw_trace_basic() { + static volatile int lto_guard; lto_guard = lto_guard + 1; auto raw_trace = cpptrace::generate_raw_trace(); // look for within 90 bytes of the start of the function ASSERT_GE(raw_trace.frames.size(), 1); @@ -27,6 +28,7 @@ CPPTRACE_FORCE_NO_INLINE static void raw_trace_basic() { #ifndef _MSC_VER CPPTRACE_FORCE_NO_INLINE void raw_trace_basic_precise() { + static volatile int lto_guard; lto_guard = lto_guard + 1; a: auto raw_trace = cpptrace::generate_raw_trace(); b: @@ -58,6 +60,7 @@ CPPTRACE_FORCE_NO_INLINE static void raw_trace_multi_2( cpptrace::frame_ptr parent_low_bound, cpptrace::frame_ptr parent_high_bound ) { + static volatile int lto_guard; lto_guard = lto_guard + 1; auto raw_trace = cpptrace::generate_raw_trace(); ASSERT_GE(raw_trace.frames.size(), 2); EXPECT_GE(raw_trace.frames[0], reinterpret_cast(raw_trace_multi_2)); @@ -67,6 +70,7 @@ CPPTRACE_FORCE_NO_INLINE static void raw_trace_multi_2( } CPPTRACE_FORCE_NO_INLINE static void raw_trace_multi_1() { + static volatile int lto_guard; lto_guard = lto_guard + 1; auto raw_trace = cpptrace::generate_raw_trace(); raw_trace_multi_2(reinterpret_cast(raw_trace_multi_1), reinterpret_cast(raw_trace_multi_1) + 300); ASSERT_GE(raw_trace.frames.size(), 1); @@ -77,11 +81,13 @@ CPPTRACE_FORCE_NO_INLINE static void raw_trace_multi_1() { std::vector> parents; CPPTRACE_FORCE_NO_INLINE void record_parent(uintptr_t low_bound, uintptr_t high_bound) { + static volatile int lto_guard; lto_guard = lto_guard + 1; parents.insert(parents.begin(), {low_bound, high_bound}); } #ifndef _MSC_VER CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_precise_3() { + static volatile int lto_guard; lto_guard = lto_guard + 1; a: auto raw_trace = cpptrace::generate_raw_trace(); b: @@ -102,6 +108,7 @@ CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_precise_3() { } CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_precise_2() { + static volatile int lto_guard; lto_guard = lto_guard + 1; a: auto raw_trace = cpptrace::generate_raw_trace(); b: @@ -132,6 +139,7 @@ CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_precise_2() { } CPPTRACE_FORCE_NO_INLINE void raw_trace_multi_precise_1() { + static volatile int lto_guard; lto_guard = lto_guard + 1; a: auto raw_trace = cpptrace::generate_raw_trace(); b: diff --git a/test/unit/stacktrace.cpp b/test/unit/stacktrace.cpp index 82e162c..5b6a492 100644 --- a/test/unit/stacktrace.cpp +++ b/test/unit/stacktrace.cpp @@ -25,6 +25,7 @@ TEST(Stacktrace, Empty) { CPPTRACE_FORCE_NO_INLINE void stacktrace_basic() { + static volatile int lto_guard; lto_guard = lto_guard + 1; auto line = __LINE__ + 1; auto trace = cpptrace::generate_trace(); ASSERT_GE(trace.frames.size(), 1); @@ -39,9 +40,10 @@ TEST(Stacktrace, Basic) { -// NOTE: returning something and then return stacktrace_multi_3(line_numbers) * 2; later helps prevent the call from -// being optimized to a jmp +// NOTE: returning something and then return stacktrace_multi_3(line_numbers) * rand(); is done to prevent TCO even +// under LTO https://github.com/jeremy-rifkin/cpptrace/issues/179#issuecomment-2467302052 CPPTRACE_FORCE_NO_INLINE int stacktrace_multi_3(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); auto trace = cpptrace::generate_trace(); if(trace.frames.size() < 4) { @@ -68,13 +70,15 @@ CPPTRACE_FORCE_NO_INLINE int stacktrace_multi_3(std::vector& line_numbers) } CPPTRACE_FORCE_NO_INLINE int stacktrace_multi_2(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); - return stacktrace_multi_3(line_numbers) * 2; + return stacktrace_multi_3(line_numbers) * rand(); } CPPTRACE_FORCE_NO_INLINE int stacktrace_multi_1(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); - return stacktrace_multi_2(line_numbers) * 2; + return stacktrace_multi_2(line_numbers) * rand(); } TEST(Stacktrace, MultipleFrames) { @@ -86,16 +90,19 @@ TEST(Stacktrace, MultipleFrames) { CPPTRACE_FORCE_NO_INLINE cpptrace::raw_trace stacktrace_raw_resolve_3(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); return cpptrace::generate_raw_trace(); } CPPTRACE_FORCE_NO_INLINE cpptrace::raw_trace stacktrace_raw_resolve_2(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); return stacktrace_raw_resolve_3(line_numbers); } CPPTRACE_FORCE_NO_INLINE cpptrace::raw_trace stacktrace_raw_resolve_1(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); return stacktrace_raw_resolve_2(line_numbers); } @@ -127,6 +134,7 @@ TEST(Stacktrace, RawTraceResolution) { #ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF CPPTRACE_FORCE_NO_INLINE int stacktrace_inline_resolution_3(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); auto trace = cpptrace::generate_trace(); if(trace.frames.size() < 4) { @@ -165,13 +173,15 @@ CPPTRACE_FORCE_NO_INLINE int stacktrace_inline_resolution_3(std::vector& li } CPPTRACE_FORCE_INLINE int stacktrace_inline_resolution_2(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); - return stacktrace_inline_resolution_3(line_numbers) * 2; + return stacktrace_inline_resolution_3(line_numbers) * rand(); } CPPTRACE_FORCE_NO_INLINE int stacktrace_inline_resolution_1(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); - return stacktrace_inline_resolution_2(line_numbers) * 2; + return stacktrace_inline_resolution_2(line_numbers) * rand(); } TEST(Stacktrace, InlineResolution) { diff --git a/test/unit/traced_exception.cpp b/test/unit/traced_exception.cpp index c93f25b..ee69d96 100644 --- a/test/unit/traced_exception.cpp +++ b/test/unit/traced_exception.cpp @@ -11,21 +11,24 @@ using namespace std::literals; -// NOTE: returning something and then return stacktrace_traced_object_3(line_numbers) * 2; later helps prevent the call from -// being optimized to a jmp +// NOTE: returning something and then return stacktrace_multi_3(line_numbers) * rand(); is done to prevent TCO even +// under LTO https://github.com/jeremy-rifkin/cpptrace/issues/179#issuecomment-2467302052 CPPTRACE_FORCE_NO_INLINE int stacktrace_traced_object_3(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); throw cpptrace::runtime_error("foobar"); } CPPTRACE_FORCE_NO_INLINE int stacktrace_traced_object_2(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); - return stacktrace_traced_object_3(line_numbers) * 2; + return stacktrace_traced_object_3(line_numbers) * rand(); } CPPTRACE_FORCE_NO_INLINE int stacktrace_traced_object_1(std::vector& line_numbers) { + static volatile int lto_guard; lto_guard = lto_guard + 1; line_numbers.insert(line_numbers.begin(), __LINE__ + 1); - return stacktrace_traced_object_2(line_numbers) * 2; + return stacktrace_traced_object_2(line_numbers) * rand(); } TEST(TracedException, Basic) {