diff --git a/cmake/utils.cmake b/cmake/utils.cmake index b8a9a75419..c5ad776c6c 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -285,6 +285,8 @@ function(make_third_party_configuration PIC_ENABLED PROJECT_GENERIC_NAME PROJECT set(${OUT_LIB_SPECIFIER} ${NO_PIC_LIBRARY_SPECIFIER} PARENT_SCOPE) endif() + set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -fno-omit-frame-pointer") + if(COMPILE_RUNTIME_LIGHT) set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} ${RUNTIME_LIGHT_VISIBILITY}") endif() diff --git a/common/fast-backtrace.cpp b/common/fast-backtrace.cpp index 644ba0c4fd..e89d738238 100644 --- a/common/fast-backtrace.cpp +++ b/common/fast-backtrace.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include "common/sanitizer.h" @@ -43,9 +44,13 @@ int fast_backtrace(void** buffer, int size) { } int fast_backtrace_by_bp(void* bp, void* stack_end_, void** buffer, int size) { - stack_frame* current_bp = static_cast(bp); + if (stack_end_ == nullptr) { + return 0; + } + const auto last_frame_addr = reinterpret_cast(stack_end_) - sizeof(stack_frame); + auto* current_bp = static_cast(bp); int i = 0; - while (i < size && reinterpret_cast(current_bp) <= stack_end_ && !(reinterpret_cast(current_bp) & (sizeof(long) - 1))) { + while (i < size && reinterpret_cast(current_bp) <= last_frame_addr && !(reinterpret_cast(current_bp) & (sizeof(long) - 1))) { void* ip = current_bp->ip; buffer[i++] = ip; stack_frame* p = current_bp->bp; @@ -67,9 +72,13 @@ int fast_backtrace_without_recursions(void** buffer, int size) noexcept { } int fast_backtrace_without_recursions_by_bp(void* bp, void* stack_end_, void** buffer, int size) noexcept { - stack_frame* current_bp = static_cast(bp); + if (stack_end_ == nullptr) { + return 0; + } + const auto last_frame_addr = reinterpret_cast(stack_end_) - sizeof(stack_frame); + auto* current_bp = static_cast(bp); int i = 0; - while (i < size && reinterpret_cast(current_bp) <= stack_end_ && !(reinterpret_cast(current_bp) & (sizeof(long) - 1))) { + while (i < size && reinterpret_cast(current_bp) <= last_frame_addr && !(reinterpret_cast(current_bp) & (sizeof(long) - 1))) { buffer[i++] = current_bp->ip; for (int possible_recursion_len = 1; i >= 2 * possible_recursion_len; ++possible_recursion_len) { if (std::equal(buffer + i - possible_recursion_len, buffer + i, buffer + i - possible_recursion_len * 2)) { diff --git a/runtime-light/stdlib/diagnostics/backtrace.cpp b/runtime-light/stdlib/diagnostics/backtrace.cpp index 5d11fb0771..7ccc2fc74e 100644 --- a/runtime-light/stdlib/diagnostics/backtrace.cpp +++ b/runtime-light/stdlib/diagnostics/backtrace.cpp @@ -3,6 +3,7 @@ // Distributed under the GPL v3 License, see LICENSE.notice.txt #include +#include #include #include @@ -14,14 +15,24 @@ namespace { +bool is_aligned(const void* ptr, std::size_t alignment) noexcept { + return (reinterpret_cast(ptr) & (alignment - 1)) == 0; +} + size_t sync_frames(std::span addresses, kphp::coro::stack_frame* start_frame, kphp::coro::stack_frame* stop_frame) noexcept { kphp::log::assertion(start_frame != nullptr && stop_frame != nullptr); auto address{addresses.begin()}; - for (auto* current_stack_frame{start_frame}; current_stack_frame != stop_frame && address != addresses.end(); + for (auto* current_stack_frame{start_frame}; + address != addresses.end() && reinterpret_cast(current_stack_frame) < reinterpret_cast(stop_frame) && + is_aligned(current_stack_frame, alignof(void*)); current_stack_frame = current_stack_frame->caller_stack_frame) { *address = current_stack_frame->return_address; address = std::next(address); + auto* next{current_stack_frame->caller_stack_frame}; + if (reinterpret_cast(next) <= reinterpret_cast(current_stack_frame)) { + break; + } } return std::distance(addresses.begin(), address); }