ndk-gdb

El NDK incluye una secuencia de comandos de shell denominada ndk-gdb para iniciar una sesión de depuración nativa en la línea de comandos. Por su parte, los usuarios que prefieren usar una GUI deben leer la documentación sobre depuración en Android Studio.

Requisitos

Para que la depuración nativa de líneas de comandos funcione, debes cumplir los siguientes requisitos:

  • Compila tu app con la secuencia de comandos ndk-build. La secuencia de comandos ndk-gdb no admite el uso del método heredado make APP=<name> para la compilación.
  • Habilita la depuración de apps en tu archivo AndroidManifest.xml incluyendo un elemento <application> que establezca el atributo android:debuggable en true.
  • Compila tu app para que se ejecute en Android 2.2 (API nivel 8) o versiones posteriores.
  • Realiza la depuración en un dispositivo o emulador con Android 2.2 o versiones posteriores. Para la depuración, el nivel de API de destino que declaras en el archivo AndroidManifest.xml no tiene importancia.
  • Desarrolla tu app en un shell Unix. En Windows, usa Cygwin o la implementación experimental ndk-gdb-py de Python.
  • Usa GNU Make 3.81 o versiones posteriores.

Uso

Para invocar la secuencia de comandos ndk-gdb, ubícate en el directorio de la aplicación o en cualquier directorio debajo de él. Por ejemplo:

cd $PROJECT
$NDK/ndk-gdb

En este caso, $PROJECT apunta al directorio raíz de tu proyecto y $NDK apunta a la ruta de instalación del NDK.

Cuando invocas a ndk-gdb, esta configura la sesión para buscar tus archivos de origen y las versiones de símbolo y depuración de las bibliotecas nativas generadas. Cuando la adjuntas correctamente al proceso de tu app, ndk-gdb genera una larga serie de mensajes de error donde indica que no puede encontrar varias bibliotecas del sistema. Esto es normal, ya que tu máquina anfitrión no contiene versiones de símbolo y depuración de esas bibliotecas en el dispositivo de destino. Puedes ignorar esos mensajes.

A continuación, ndk-gdb muestra una solicitud de GDB normal.

Debes interactuar con ndk-gdb de la misma manera que con GDB de GNU. Por ejemplo, puedes usar b <location> para establecer interrupciones y c (de "continuar") a fin de reanudar la ejecución. Para acceder a una lista completa de comandos, consulta el manual de GDB.

Ten en cuenta que, cuando sales de la ventana de GDB, el proceso de la app que depuras se detiene. Este comportamiento es una limitación de gdb.

ndk-gdb controla muchas condiciones de error y muestra un mensaje de error informativo si encuentra un problema. Estas son algunas de las comprobaciones que realiza:

  • Comprueba que adb esté presente en tu ruta de acceso.
  • Comprueba que la app esté declarada como depurable en el manifiesto.
  • Comprueba que, en el dispositivo, la aplicación instalada con el mismo nombre de paquete también sea depurable.

De forma predeterminada, ndk-gdb busca un proceso de la app que ya esté en ejecución y muestra un error si no encuentra ninguno. Sin embargo, puedes usar la opción --start o --launch=<name> para iniciar automáticamente tu actividad antes de la sesión de depuración. Para obtener más información, consulta Opciones.

Opciones

Si deseas ver una lista completa de opciones, escribe ndk-gdb --help en la línea de comandos. En la Tabla 1, se muestran algunas de las más empleadas, junto con descripciones breves.

Tabla 1: Opciones de ndk-gdb comunes y sus descripciones

Cuando se inicia ndk-gdb con esta opción especificada, se inicia la primera actividad que se puede iniciar y que se indica en el manifiesto de tu app. Usa --launch=<name> para iniciar la próxima actividad que se puede iniciar. Para descartar la lista de actividades que se pueden iniciar, ejecuta --launch-list desde la línea de comandos.

Opción Descripción>
--verbose

Esta opción indica al sistema de compilación que imprima información detallada sobre la configuración de la sesión de depuración nativa. Esto solo es necesario para depurar problemas cuando el depurador no puede conectarse con la app y los mensajes de error que muestra ndk-gdb no son suficientes.

--force De forma predeterminada, se anula ndk-gdb si detecta otra sesión de depuración nativa en ejecución en el mismo dispositivo. Esta opción cierra la otra sesión y la reemplaza por una nueva. Ten en cuenta que no cierra la app que se está depurando, que debes cerrar por separado.
--start

Cuando inicias ndk-gdb, de forma predeterminada, este intenta adjuntarse a una instancia de ejecución existente de tu app en el dispositivo de destino. Puedes anular este comportamiento predeterminado usando --start para iniciar de manera explícita la aplicación en el dispositivo de destino antes de la sesión de depuración.

--launch=<name>

Esta opción es similar a --start, con la excepción de que te permite iniciar una actividad específica desde tu aplicación. Esta función solo es útil si tu manifiesto define varias actividades que se pueden iniciar.

--launch-list

Esta opción conveniente imprime la lista de todos los nombres de las actividades que se pueden iniciar del manifiesto de tu app. --start usa el nombre de la primera actividad.

--project=<path> Esta opción especifica el directorio del proyecto de la app. Resulta útil si quieres iniciar la secuencia de comandos sin tener que realizar primero un cambio al directorio del proyecto.
--port=<port>

De forma predeterminada, ndk-gdb usa el puerto local TCP 5039 para comunicarse con la app que depura en el dispositivo de destino. El uso de un puerto diferente te permite depurar de forma nativa programas que estén en ejecución en otros dispositivos o emuladores conectados a la misma máquina anfitrión.

--adb=<file>

Esta opción especifica el ejecutable de la herramienta adb. Solo es necesaria si no configuraste tu ruta de acceso para que incluya ese ejecutable.

  • -d
  • -e
  • -s <serial>
  • Estas marcas son similares a los comandos adb con los mismos nombres. Configúralas si hay varios dispositivos o emuladores conectados a tu máquina anfitrión. Sus significados son los siguientes:

    -d
    Establece conexión con un solo dispositivo físico.
    -e
    Establece conexión con un solo dispositivo emulador.
    -s <serial>
    Establece conexión con un dispositivo o emulador específico. Aquí, <serial> es el nombre del dispositivo según lo indica el comando adb devices.

    También puedes definir la variable de entorno ADB_SERIAL para indicar un dispositivo determinado, sin la necesidad de usar una opción específica.

  • --exec=<file>
  • -x <file>
  • Esta opción le indica a ndk-gdb que debe ejecutar los comandos de inicialización de GDB que se encuentran en <file> después de conectarse con el proceso que está depurando. Esta función es útil si quieres realizar una acción de forma repetida, como configurar una lista de interrupciones y, luego, reanudar la ejecución automáticamente.

    --nowait

    Inhabilita el pausado del código Java hasta que GDB se conecte. Pasar esta opción puede hacer que el depurador omita interrupciones anteriores.

    --tui -t

    Habilita la interfaz textual del usuario, si se encuentra disponible.

    --gnumake-flag=<flag>

    Esta opción representa una o varias marcas adicionales que se pasarán al sistema ndk-build cuando se busque información del proyecto. Puedes usar varias instancias de esta opción en el mismo comando.

    Nota: Las tres opciones finales de esta tabla son solo para la versión de ndk-gdb para Python.

    Compatibilidad con subprocesos

    Si tu app se ejecuta en una plataforma anterior a Android 2.3 (API nivel 9), ndk-gdb no puede depurar correctamente subprocesos nativos. El depurador solo puede depurar el subproceso principal; adb ignora por completo la ejecución de otros subprocesos.

    Si colocas una interrupción en una función ejecutada en un subproceso que no es el principal, el programa se cierra y GDB muestra el siguiente mensaje:

    Program terminated with signal SIGTRAP, Trace/breakpoint trap.
          The program no longer exists.