Debugging Kotlin/Native
The Kotlin/Native compiler can generate binaries with debug information, as well as create debug symbol files for symbolicating crash reports.
The debug information is compatible with the DWARF 2 specification, so modern debugger tools, like LLDB and GDB can:
Generate binaries with debug information
When debugging in IntelliJ IDEA, Android Studio, or Xcode, binaries with debug information are generated automatically (unless the build is configured differently).
You can enable debugging manually and produce binaries that include debug information by:
Using Gradle tasks. To get debug binaries, use
linkDebug*
Gradle tasks, for example:./gradlew linkDebugFrameworkNativeThe tasks differ depending on the binary type (for example,
linkDebugSharedNative
) or your target (for example,linkDebugExecutableMacosX64
).Using the command-line compiler. In the command line, compile your Kotlin/Native binary with the
-g
option:kotlinc-native hello.kt -g -o terminator
Then launch your debugger tool. For example:
The debugger outputs:
Set breakpoints
Modern debuggers provide several ways to set a breakpoint. See below for a tool-by-tool breakdown:
LLDB
By name:
(lldb) b -n kfun:main(kotlin.Array<kotlin.String>) Breakpoint 4: where = terminator.kexe`kfun:main(kotlin.Array<kotlin.String>) + 4 at hello.kt:2, address = 0x00000001000012e4-n
is optional, it's applied by default.By location (filename, line number):
(lldb) b -f hello.kt -l 1 Breakpoint 1: where = terminator.kexe`kfun:main(kotlin.Array<kotlin.String>) + 4 at hello.kt:2, address = 0x00000001000012e4By address:
(lldb) b -a 0x00000001000012e4 Breakpoint 2: address = 0x00000001000012e4By regex. You might find it useful for debugging generated artifacts, like a lambda (with the
#
symbol in the name):(lldb) b -r main\( 3: regex = 'main\(', locations = 1 3.1: where = terminator.kexe`kfun:main(kotlin.Array<kotlin.String>) + 4 at hello.kt:2, address = terminator.kexe[0x00000001000012e4], unresolved, hit count = 0
GDB
By regex:
(gdb) rbreak main( Breakpoint 1 at 0x1000109b4 struct ktype:kotlin.Unit &kfun:main(kotlin.Array<kotlin.String>);By name is not possible because
:
is a separator for the breakpoint by location:(gdb) b kfun:main(kotlin.Array<kotlin.String>) No source file named kfun. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (kfun:main(kotlin.Array<kotlin.String>)) pendingBy location:
(gdb) b hello.kt:1 Breakpoint 2 at 0x100001704: file /Users/minamoto/ws/.git-trees/hello.kt, line 1.By address:
(gdb) b *0x100001704 Note: breakpoint 2 also set at pc 0x100001704. Breakpoint 3 at 0x100001704: file /Users/minamoto/ws/.git-trees/hello.kt, line 2.
Use stepping
Stepping through functions works mostly the same way as for C/C++ programs.
Inspect variables
Variable inspection for var
variables works out of the box for primitive types. For non-primitive types, there are custom pretty printers for LLDB in konan_lldb.py
:
Getting representation of the object variable (var
) could also be done using the built-in runtime function Konan_DebugPrint
(this approach also works for GDB, using a module-specific syntax):
Debug iOS applications
Debugging iOS applications sometimes involves analyzing crash reports in detail. Crash reports typically require symbolication, the process of translating memory addresses into readable source code locations.
To symbolicate addresses in Kotlin code (for example, for stack trace elements corresponding to Kotlin code), you need a special debug symbol (.dSYM
) file. This file maps memory addresses in crash reports with actual locations in the source code, such as functions or line numbers.
The Kotlin/Native compiler generates .dSYM
files for release (optimized) binaries on Apple platforms by default. When building in Xcode, the IDE looks for .dSYM
files in standard locations and uses them automatically for symbolication. Xcode automatically detects .dSYM
files in projects created from IntelliJ IDEA templates.
On other platforms, you can add debug information into the produced binaries (which increases their size) using the -Xadd-light-debug
compiler option:
For more information about crash reports, see the Apple documentation.
Known issues
Performance of Python bindings.
Expression evaluation in debugger tools is not supported, and currently there are no plans for implementing it.