diff --git a/kotlin-native/runtime/src/main/cpp/StackTrace.cpp b/kotlin-native/runtime/src/main/cpp/StackTrace.cpp index f79339b5d99..fc18ed80a87 100644 --- a/kotlin-native/runtime/src/main/cpp/StackTrace.cpp +++ b/kotlin-native/runtime/src/main/cpp/StackTrace.cpp @@ -157,6 +157,32 @@ static size_t snprintf_with_addr(char* buf, size_t size, size_t frame, const voi } #endif // ! KONAN_NO_BACKTRACE + +/* + * This is hack for better traces. + * In some cases backtrace function returns address after call instruction, while address detection need call instruction itself. + * adjustAddressForSourceInfo function tries to fix it with some heuristics. + * + * For honest solution, we should distinguish backtrace symbols got from signal handlers frames, ordinary frames, + * and addresses got from somewhere else. But for now, we assume all addresses are ordinary backtrace frames. + */ + +#if (defined(KONAN_X64) || defined(KONAN_X86)) && !defined(KONAN_WINDOWS) +KNativePtr adjustAddressForSourceInfo(KNativePtr address) { + return reinterpret_cast(reinterpret_cast(address) - 1); +} +#elif (defined(KONAN_ARM32) || defined(KONAN_ARM64)) && !defined(KONAN_WINDOWS) +KNativePtr adjustAddressForSourceInfo(KNativePtr address) { + /* + * On arm instructions are always 2-bytes aligned. But odd bit can be used to encode instruction set. + * Not sure, if this can happen in our code, but let's just clear it. + */ + return reinterpret_cast((reinterpret_cast(address) & ~1) - 1); +} +#else +KNativePtr adjustAddressForSourceInfo(KNativePtr address) { return address; } +#endif + KStdVector kotlin::GetStackTraceStrings(void* const* stackTrace, size_t stackTraceSize) noexcept { #if KONAN_NO_BACKTRACE KStdVector strings; @@ -170,6 +196,7 @@ KStdVector kotlin::GetStackTraceStrings(void* const* stackTrace, siz for (size_t index = 0; index < stackTraceSize; ++index) { KNativePtr address = stackTrace[index]; if (!address || reinterpret_cast(address) == 1) continue; + address = adjustAddressForSourceInfo(address); int frames_or_overflow = getSourceInfo(address, buffer, std::size(buffer)); int frames = std::min(frames_or_overflow, std::size(buffer)); bool isSomethingPrinted = false; diff --git a/kotlin-native/runtime/src/source_info/libbacktrace/cpp/SourceInfo.cpp b/kotlin-native/runtime/src/source_info/libbacktrace/cpp/SourceInfo.cpp index e425cac71ef..41a0c3780f3 100644 --- a/kotlin-native/runtime/src/source_info/libbacktrace/cpp/SourceInfo.cpp +++ b/kotlin-native/runtime/src/source_info/libbacktrace/cpp/SourceInfo.cpp @@ -10,13 +10,6 @@ extern "C" int Kotlin_getSourceInfo_libbacktrace(void* addr, SourceInfo *result, int result_size) { if (result_size == 0) return 0; - /** - * This is hack for better traces. - * backtrace function returns address after call instruction, and address detection need call instruction itself - * For honest solution, we should distinguish backtrace symbols got from signal handlers frames, ordinary frames, - * and addresses got from somewhere else. But for now, we assume all addresses are ordinary backtrace frames. - */ - addr = reinterpret_cast(reinterpret_cast(addr) - 1); auto ignore_error = [](void*, const char*, int){}; static auto state = backtrace_create_state(nullptr, 1, ignore_error, nullptr); if (!state) return 0;