Skip to main content

How to Debug Userland Native Code

Setup

To begin, connect to the virtual device with ADB and start a shell. Until noted otherwise, all commands should be run in the shell on the virtual device.

You will need root privileges. Run su to switch to the root user. Your shell prompt should be #, not $, and the output of the id command should include uid=0(root).

Run ps to see the processes running on the virtual device. Find the process you're interested in debugging, and note its process identifier, or PID.

Attach to the process with a GDB server:

gdbserver64 --attach :<PORT> <PID>

or

gdbserver --attach :<PORT> <PID>

If the process you're interested in debugging is a 64-bit process, you must use gdbserver64. If the process is a 32-bit process, you must use gdbserver. Most processes are 64-bit. If you're unsure whether the process is 32-bit or 64-bit, run cat /proc/<PID>/personality, replacing <PID> with the PID of the process you're interested in debugging. If the output is zero, like 00000000, it's a 64-bit process. If the output is non-zero, it's likely a 32-bit process.

Replace <PORT> with a valid port number (between 1 and 65535) that's unused on the virtual device and on your computer.

Replace <PID> with the PID of the process you're interested in debugging.

The remaining commands should be run on your computer, not on the virtual device.

Run adb forward tcp:<PORT> tcp:<PORT>, replacing <PORT> with the port number you chose above. Now, connections to local port <PORT> on your computer will be forwarded to port <PORT> on the virtual device.

Debug the Process

Now everything is configured. To debug the process, run aarch64-linux-gnu-gdb. aarch64-linux-gnu-gdb is packaged in most major Linux distributions. Linaro also provides prebuilt toolchains for download.

At the (gdb) prompt, run target remote :<PORT>. Note that GDB will first transfer the executable file and its dynamic libraries, and this process will take a long time.