diff --git a/kotlin-native/runtime/src/debug/cpp/SourceInfo.cpp b/kotlin-native/runtime/src/debug/cpp/SourceInfo.cpp index aa45852d3be..ca50bd1312b 100644 --- a/kotlin-native/runtime/src/debug/cpp/SourceInfo.cpp +++ b/kotlin-native/runtime/src/debug/cpp/SourceInfo.cpp @@ -127,7 +127,8 @@ typedef struct { int end; } SymbolSourceInfoLimits; -extern "C" struct SourceInfo Kotlin_getSourceInfo(void* addr) { +extern "C" int Kotlin_getSourceInfo(void* addr, SourceInfo *result_buffer, int result_size) { + if (result_size == 0) return 0; __block SourceInfo result = { .fileName = nullptr, .lineNumber = -1, .column = -1 }; __block bool continueUpdateResult = true; __block SymbolSourceInfoLimits limits = {.start = -1, .end = -1}; @@ -139,10 +140,10 @@ extern "C" struct SourceInfo Kotlin_getSourceInfo(void* addr) { CSSymbolOwnerRef symbolOwner = CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator, address, kCSNow); if (CSIsNull(symbolOwner)) - return result; + return 0; CSSymbolRef symbol = CSSymbolOwnerGetSymbolWithAddress(symbolOwner, address); if (CSIsNull(symbol)) - return result; + return 0; SYM_LOG("Kotlin_getSourceInfo: address: (%p) {\n", addr); SYM_DUMP(symbol); @@ -204,13 +205,14 @@ extern "C" struct SourceInfo Kotlin_getSourceInfo(void* addr) { }); } SYM_LOG("}\n"); - return result; + result_buffer[0] = result; + return 1; } #else // KONAN_CORE_SYMBOLICATION -extern "C" struct SourceInfo Kotlin_getSourceInfo(void* addr) { - return (SourceInfo) { .fileName = nullptr, .lineNumber = -1, .column = -1 }; +extern "C" int Kotlin_getSourceInfo(void* addr, SourceInfo *result, int result_size) { + return 0; } #endif // KONAN_CORE_SYMBOLICATION diff --git a/kotlin-native/runtime/src/main/cpp/SourceInfo.h b/kotlin-native/runtime/src/main/cpp/SourceInfo.h index 5e92548a1cb..41e33256acc 100644 --- a/kotlin-native/runtime/src/main/cpp/SourceInfo.h +++ b/kotlin-native/runtime/src/main/cpp/SourceInfo.h @@ -27,7 +27,9 @@ struct SourceInfo { extern "C" { #endif -struct SourceInfo Kotlin_getSourceInfo(void* addr); +// returns number of filled elements in buffer +// there can be several frames because of inlining +int Kotlin_getSourceInfo(void* addr, SourceInfo *result, int result_size); #ifdef __cplusplus } // extern "C" diff --git a/kotlin-native/runtime/src/main/cpp/StackTrace.cpp b/kotlin-native/runtime/src/main/cpp/StackTrace.cpp index f09aecbc15a..1ae99a1a8b3 100644 --- a/kotlin-native/runtime/src/main/cpp/StackTrace.cpp +++ b/kotlin-native/runtime/src/main/cpp/StackTrace.cpp @@ -70,8 +70,8 @@ _Unwind_Reason_Code unwindCallback(struct _Unwind_Context* context, void* arg) { THREAD_LOCAL_VARIABLE bool disallowSourceInfo = false; #if !KONAN_NO_BACKTRACE && !USE_GCC_UNWIND -SourceInfo getSourceInfo(void* symbol) { - return disallowSourceInfo ? SourceInfo{.fileName = nullptr, .lineNumber = -1, .column = -1} : Kotlin_getSourceInfo(symbol); +int getSourceInfo(void* symbol, SourceInfo *result, int result_len) { + return disallowSourceInfo ? 0 : Kotlin_getSourceInfo(symbol, result, result_len); } #endif @@ -137,22 +137,37 @@ KStdVector kotlin::GetStackTraceStrings(void* const* stackTrace, siz for (size_t index = 0; index < stackTraceSize; ++index) { KNativePtr address = stackTrace[index]; - auto sourceInfo = getSourceInfo(address); + SourceInfo buffer[10]; + int frames = getSourceInfo(address, buffer, std::size(buffer)); const char* symbol = symbols[index]; - const char* result; + // returned symbol starts with frame number + // we need to override it, because of inlining, so let's just drop first token + while (*symbol != '\0' && *symbol != ' ') symbol++; + while (*symbol == ' ') symbol++; + // probably, this can't happen, but let's print at least something + if (*symbol == '\0') symbol = symbols[index]; + bool isSomethingPrinted = false; char line[1024]; - if (sourceInfo.fileName != nullptr) { - if (sourceInfo.lineNumber != -1) { - konan::snprintf( - line, sizeof(line) - 1, "%s (%s:%d:%d)", symbol, sourceInfo.fileName, sourceInfo.lineNumber, sourceInfo.column); - } else { - konan::snprintf(line, sizeof(line) - 1, "%s (%s:)", symbol, sourceInfo.fileName); + for (int frame = 0; frame < frames; frame++) { + auto &sourceInfo = buffer[frame]; + if (sourceInfo.fileName != nullptr) { + const char* inline_tag = (frame == frames - 1) ? "" : "[inlined] "; + if (sourceInfo.lineNumber != -1) { + konan::snprintf( + line, sizeof(line) - 1, "%-4zd %s %s(%s:%d:%d)", strings.size(), symbol, inline_tag, + sourceInfo.fileName, sourceInfo.lineNumber, buffer[frame].column); + } else { + konan::snprintf(line, sizeof(line) - 1, "%-4zd %s %s(%s:)", strings.size(), symbol, inline_tag, + sourceInfo.fileName); + } + isSomethingPrinted = true; + strings.push_back(line); } - result = line; - } else { - result = symbol; } - strings.push_back(result); + if (!isSomethingPrinted) { + konan::snprintf(line, sizeof(line) - 1, "%-4zd %s", strings.size(), symbol); + strings.push_back(line); + } } // Not konan::free. Used to free memory allocated in backtrace_symbols where malloc is used. free(symbols); diff --git a/kotlin-native/runtime/src/release/cpp/SourceInfo.cpp b/kotlin-native/runtime/src/release/cpp/SourceInfo.cpp index 653cea5050f..b07098290e3 100644 --- a/kotlin-native/runtime/src/release/cpp/SourceInfo.cpp +++ b/kotlin-native/runtime/src/release/cpp/SourceInfo.cpp @@ -16,6 +16,6 @@ #include "SourceInfo.h" -struct SourceInfo Kotlin_getSourceInfo(void* addr) { - return (SourceInfo) { .fileName = nullptr, .lineNumber = -1, .column = -1 }; +int Kotlin_getSourceInfo(void* addr, SourceInfo *result, int result_size) { + return 0; } \ No newline at end of file