title: Debugging native code in Defold
Defold is well tested and should very rarely crash under normal circumstances. It is however impossible to guarantee that it will never crash, especially if your game uses native extensions. If you run into problems with crashes or native code that doesn't behave as expected there are a number of different ways forward:
Symbolicate a callstack
If Defold crashes it will store information about the crash that can be used to help pinpoint what went wrong.
You can also read game and system logs to help you figure out what went wrong.
The most common way is to run the code via a debugger. It let's you step through the code, set breakpoints and it will stop the execution if you get a crash.
There are several debuggers for each platform.
Each tool can debug certain platforms:
The simplest way to debug your native code is to use print debugging. Use the functions in the dmLog namespace to watch variables or indicate the flow of execution. Using any of the log functions will print to the Console view in the editor and to the game log.
The Defold engine saves a _crash file if it does a hard crash. The crash file will contain information about the system as well as the crash.
You can use the crash module to read this file in the subsequent session. It is recommended that you read the file, gather the information, print it to the console and send it to an analytics services that supports collection of crash logs.
If a crash happens on a mobile device you can chose to download the crash file to your own computer and parse it locally.
The game log output will write where the crash file is located (it varies from device to device and application to application). If the app is debuggable, you can get the crash log using the Android Debug Bridge (ADB) tool and the adb shell command:
$ adb shell "run-as com.defold.example sh -c 'cat /data/data/com.defold.example/files/_crash'" > ./_crash
In iTunes, you can view/download an apps container.
In the XCode -> Devices window, you can also select the crash logs
If you get a callstack from either a _crash file or a log file, you can symbolicate it. This means translating each address in the callstack into a filename and line number, which in turn helps when finding out the root cause.
It is important that you match the correct engine with the callstack. Otherwise it's very likely to send you debugging the incorrect things.
Also, if you are building with native extensions, be sure to add the flag --with-symbols so that you get all the needed data from the build server. For instance, in the build.zip you'll find the dmengine.dSYM folder for iOS/macOS builds.
Android/Linux executables already contain the debug symbols.
Also, you should keep an unstripped version of the engine. This allows for the best symbolication of the callstack.
Get it from your build folder
$ ls /build//[lib]dmengine[.exe|.so]
Unzip to a folder:
$ unzip dmengine.apk -d dmengine_1_2_105
Find the callstack address
E.g. in the non symbolicated callstack on Crash Analytics, it could look like this
#00 pc 00257224 libmy_game_name.so
Where 00257224 is the address
Resolve the address
$ arm-linux-androideabi-addr2line -C -f -e dmengine_1_2_105/lib/armeabi-v7a/libdmengine.so address
Note: If you get hold of a stack trace from the Android logs, you might be able to symbolicate it using ndk-stack
If you are using Native Extensions, the server can provide the symbols (.dSYM) for you (pass --with-symbols to bob.jar)
$ unzip /build/arm64-darwin/build.zip
If you're not using Native Extensions, download the vanilla symbols:
$ wget http://d.defold.com/archive//engine/arm64-darwin/dmengine.dSYM
Symbolicate using load address
For some reason, simply putting the address from the callstack doesn't work (i.e. load address 0x0)
$ atos -arch arm64 -o Contents/Resources/DWARF/dmengine 0x1492c4
$ atos -arch arm64 -o MyApp.dSYM/Contents/Resources/DWARF/MyApp -l0x100000000 0x1492c4
Adding the load address to the address works:
$ atos -arch arm64 -o MyApp.dSYM/Contents/Resources/DWARF/MyApp 0x1001492c4
dmCrash::OnCrash(int) (in MyApp) (backtrace_execinfo.cpp:27)