Android NDK comes with GDB, somewhere in the NDK folder one can find gdbserver and gdb binaries. The idea is obviously to run gdbserver on the device and then connect to it from local host with gdb. For that to work - both server and client need to have available binary that both are debugging (that’s because both need to have debugging symbols).

Let say I want to debug something which is called main. First step would be to export some variables

# Change line below to wherever you keep NDK
NDK_DIR=/opt/android-ndk

HOST_GDBSERVER=${NDK_DIR}/prebuilt/android-arm64/gdbserver/gdbserver
HOST_GDB=${NDK_DIR}/prebuilt/linux-x86_64/bin/gdb

HOST_APP=/tmp/main
TARGET_APP=/data/app/main
TARGET_GDBSERVER=/data/app/gdbserver
PORT=5039

Then in one terminal I would start gdbserver

adb forward tcp:${PORT} tcp:${PORT}
adb push ${HOST_GDBSERVER} ${TARGET_GDBSERVER}
adb shell ${TARGET_GDBSERVER} :${PORT} ${TARGET_APP}

And gdb in another terminal:

${HOST_GDB} ${HOST_APP}

While in gdb, you can connect to gdb server

target remote :5039

That’s it, easy-peasy. Happy debugging!