The GNU Project debugger (GDB) is a commonly used Unix debugger. This page
details using gdb
to debug Android apps and processes.
To connect to an already-running app or native daemon, use
gdbclient
with a PID. For example, to debug the process with PID
1234, run:
gdbclient 1234
The script sets up port forwarding, starts the appropriate
gdbserver
on the device, starts the appropriate gdb
on
the host, configures gdb
to find symbols, and connects
gdb
to the remote gdbserver
.
To debug a process as it starts, use gdbserver
or
gdbserver64
(for 64-bit processes). For example:
adb shell gdbserver :5039 /system/bin/MY_TEST_APP
Example output:
Process MY_TEST_APP created; pid = 3460 Listening on port 5039
Next, identify the application PID from the gdbserver
output and
use it in another terminal window:
gdbclient APP_PID
Finally, enter continue at the gdb
prompt.
Note: If you specify the wrong
gdbserver
, you'll get an unhelpful error message (such as
"Reply contains invalid hex digit 59
").
Sometimes you want to debug an app as it starts, such as when there's a crash
and you want to step through code to see what happens before the crash.
Attaching works in some cases, but in other cases is
impossible because the app crashes before you can attach. The
logwrapper
approach (used for strace
and
valgrind
) does not always work because the app might not have
permissions to open a port, and gdbserver
inherits that
restriction.
To debug app startup, use the developer options in Settings to instruct the app to wait for a Java debugger to attach:
am start -a android.intent.action.MAIN -n APP_NAME/.APP_ACTIVITY
gdbserver
/gdbclient
normally, set
breakpoints, then continue the process.To let the app actually run, attach a Java Debug Wire Protocol (JDWP) debugger such as Java Debugger (jdb):
adb forward tcp:12345 jdwp:XXX # (Where XXX is the pid of the debugged process.)
jdb -attach localhost:12345
If you want debuggerd
to suspend crashed processes so you can
attach gdb
, set the appropriate property:
# Android 7.0 Nougat and later.
adb shell setprop debug.debuggerd.wait_for_gdb true
# Android 6.0 Marshmallow and earlier.
adb shell setprop debug.db.uid 999999
At the end of the usual crash output, debuggerd
provides
instructions on how to connect gdb
using the command:
gdbclient PID
For 32-bit ARM, if you don’t have symbols, gdb
can get confused
about the instruction set it is disassembling (ARM or Thumb). To specify the
instruction set chosen as the default when symbol information is missing, set
the following property:
set arm fallback-mode arm # or thumb