Perfect Debugging Experience with QtCreator on Android
While I was working on a yet-to-be-announced super secret and cool Qt on Android project, I had to do a lot of debugging. This way I found that debugging Qt apps on Android using QtCreator was ok, but it had some issues, which was kinda frustrating.
- First issue was that I could not debug on an Android 8 device.
- Second issue was that, even if the debugger was almost ok for debugging Qt apps, debugging Qt itself was not that good.
Long story short, these problems will be fixed starting with QtCreator 4.6.1 (was too late for 4.6.0) or 4.7, and I also paved the way for using lldb if necessary, though, gdb works perfectly for me. And in the (distant) future MAYBE even being able to do java debugging from QtCreator as well!
Keep reading if you are interested in technical details.
How the debugging worked until now: it used a handshake technique:
- The application built for debugging bundles gdbserver into the apk.
- We start the application from QtC with some special params.
- The app checks these params, it starts gdbserver, it creates a socket, then it waits for QtCreator to connect to this socket.
- QtCreator uses adb to forward gdbservers and the socket port to your host.
- QtCreator tries to connect to the socket created by your application. When it succeeds to connect to that socket it attaches host gdb to gdbserver. At this moment all the application’s .so files are loaded and gdb will search for their symbols on the host side. It sets the breakpoints.
- At the end it signals the java application (using the previous socket) that it can continue the execution.
How it works now: it’s using the same technique that Android Studio uses:
- The application built for debugging bundles gdbserver into the apk.
- The application is started in debug mode (we add “-D” param to adb shell am start).
- The default wait for debugger dialog appears which waits for a jdb connection.
- QtCreator uses “adb shell run-as” to search for gdbserver and it starts it.
- QtCreator uses adb to forward gdbservers and the socket port to your host. At this moment no .so files are loaded by your application.
- QtCreator connects to gdbserver.
- QtCreator uses jdb to attach to the java debugger and it signals the application to continue the execution.
At first glance, both ways look similar, but …. there is a big difference 🙂
- First and foremost the application doesn’t need the handshake hack, this means that we can soon drop that code from Android Qt apps.
- The second difference, which makes the debugging perfect, is at the point when we attach gdbserver to the application. As you can see, in the first way we attach gdbserver to the application after we load all .so file, this means that all breakpoints to static vars constructors or to JNI_Onload will not work, because these functions are already called by the linker.
- Now, because QtCreator is in control of the gdbserver part, with some effort it can search for lldbserver instead, and start it.
- Last but not least, because it’s using jdb to start the application, it might be possible to use it also to debug the java part of the application!
The downside of the new way is that the start up is a little bit slower, because instead of loading the symbols for all the .so files at once, it will load them one by one as they are loaded by the application, which on my Ryzen 1700X is from 2 to 5 seconds slower.
If you can’t wait for QtCreator 4.6.1/4.7 you can cherry-pick the following two patches and rebuild QtCreator yourself:
In the end I want to thank The Qt Company folks who helped me in testing these patches on all platforms and on as many devices as we had!
If you like this article and want to read similar material, consider subscribing via our RSS feed.
Subscribe to KDAB TV for similar informative short video content.
KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.
Thanks, debugging on android really worked 20% of the time previously in my experience !
Hi BogDan, sorry for the off-topic but I know you are the master of Qt for Android and maybe can help with this. I opened this bug couple of months ago:
https://bugreports.qt.io/browse/QTBUG-65894
I think it is rather important but unfortunately it did not receive any attention. I hope you can take a look at it or at least give it a boost.
Thanks for your hard work and advice on Qt for Android!
I’m using Qt Creator 4.9.0-beta1 (Build Date = Feb 20 2019), on Ubuntu 16.04, Qt 5.12.1, NDK 19.1, Android SDK 26.1.
I can Build and Run apps for Android but I’ve never been able to get debugging to work.
I keep getting the error:
The command “…/Android/Sdk/platform-tools/adb” terminated with exit code 1.error: listener ‘tcp:5039’ not found
What configuration do you develop with to get debugging to work (Qt Creator version, OS, Android SDK, NDK)?
I didn’t tried yet QtCreator 4.9-beta1. QtCreator 4.8.1 should work perfectly.
Please use https://bugreports.qt.io to report your problem.