About Android toolchains and system images

Native Android debugging has always been somewhat tricky. In addition to common source path issues and random gdbserver failures, many VisualGDB users reported that they can debug code on their device only if they use certain versions of NDK toolchains. To figure it out once and for all we have added a VisualGDB feature that allows testing a certain Android device with all the toolchains available in the NDK. To get a general overview we have tested the standard ARM emulator images that come with the Android SDK.

Android 4.x

On most Android 4.x ARM images (except the latest 4.4) all toolchains can debug the native code, but fail to detect shared library loads and load the symbols. As a result, you normally cannot debug the code running during startup of the app. A workaround is to manually find the address of the “library loaded” callback, set a breakpoint on it and run the “sharedlibrary” command when it’s hit. VisualGDB does that automatically as doing it manually would be a significant annoyance. However, that’s not all: some combinations of GDB and the Android linker need the breakpoint address to include the thumb mode bit, making it even more complicated. E.g. on Android 4.0.3 the 4.6 toolchain does no need the thumb adjustment, while the 4.8 and 4.9 toolchains need it:1Here’s a table that summarizes how the NDK toolchains perform on the 4.x Android ARM images. Workaround A means that a manual breakpoint without Thumb bit adjustment is required. Workaround B means that a breakpoint with the Thumb adjustment bit is needed:

Android version 4.6 Toolchain 4.8 Toolchain 4.9 Toolchain
4.0.3 Workaround A Workaround B Workaround B
4.1.2 Workaround A Workaround B Workaround B
4.2.2 Workaround A Workaround A Workaround A
4.3.1 Workaround A Workaround A Workaround A
4.4.1 Out-of-the-box Out-of-the-box Out-of-the-box

From the table above it might look like the problems are over for Android 4.4 and later, but unfortunately this is not the case.

Android 5.x

While the newest Android 5.1 actually works without needing any special workarounds, the earlier 5.0 release still needs the same type of workaround as 4.2 and 4.3:

Android version 4.6 Toolchain 4.8 Toolchain 4.9 Toolchain
5.0.1 Workaround A Workaround A Workaround A
5.1.1 Out-of-the-box Out-of-the-box Out-of-the-box

Recommendations

If you want to get stable debugging experience with your native Android code, pick either Android 4.4.1 or 5.1.1 as your primary OS. If you debug other Android versions with VisualGDB, it will automatically detect and apply the correct workaround, but that will reduce the overall performance.

Another good idea would be to use an x86 device that does not have the symbol loading problem. You can also use VirtualBox or VMWare to setup  an x86 Android VM and use it for debugging. This will be much faster than the default Android emulator (even when accelerated by HAXM).