Debugging an Android NDK application with NDK GDB

Android NDK introduces a shell script named ndk-gdb to help one to launch a debugging session to debug the native code.

Getting ready

The project must meet the following requirements in order to debug it with ndk-gdb:

  • The application is built with the ndk-build command.
  • AndroidManifest.xml has the android:debuggable attribute of the <application> element set to true. This indicates that the application is debuggable even when it is running on a device in the user mode.
  • The application should be running on Android 2.2 or higher.

Please read the Building Android NDK Application at Eclipse recipe before going through this one.

How to do it...

The following steps create a sample Android project and debug it using NDK GDB.

  1. Create an Android application named HelloNDKGDB. Set the package name as cookbook.chapter3. Create an activity named HelloNDKGDBActivity. Please refer to the Loading native libraries and registering native methods recipe of Chapter 2, Java Native Interface, if you want more detailed instructions.
  2. Right-click on the project HelloNDKGDB, select Android Tools | Add Native Support. A window appears; click on Finish to dismiss it.
  3. Add the following code to HelloNDKGDB.cpp:
    #include <jni.h>
    #include <unistd.h>
    
    int multiply(int i, int j) {
      int x = i * j;
      return x;
    }
    
    extern "C" {
      JNIEXPORT jint JNICALL Java_cookbook_chapter3_HelloNDKGDBActivity_multiply(JNIEnv* env, jobject o, jint pi, jint pj){
        int i = 1, j = 0;
        while (i) {
          j=(++j)/100; 
    
        }
        return multiply(pi, pj);
      }
    }
  4. Change the content of HelloNDKGDBActivity.java to the following:
    package cookbook.chapter3;
    
    import android.os.Bundle;
    import android.widget.TextView;
    import android.app.Activity;
    
    public class HelloNDKGDBActivity extends Activity {
    
       @Overridepublic void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           TextView tv = new TextView(this);
           tv.setTextSize(30);
           tv.setText("10 x 20 = " + multiply(10, 20));
           this.setContentView(tv);
       }
       public native int multiply(int a, int b);
       static {
           System.loadLibrary("HelloNDKGDB");
       }
    }
  5. Make sure that the debuggable attribute in AndroidManifest.xml is set to true. The following code snippet is a part of the application element extracted from AndroidManifest.xml of our sample project:
    <application
           android:icon="@drawable/ic_launcher"
           android:label="@string/app_name"
           android:theme="@style/AppTheme"
           android:debuggable="true"
           >
  6. Build the native library with the command "ndk-build NDK_DEBUG=1". Alternatively, we can configure the build command at Eclipse under C/C++ Build of the project Properties. This is demonstrated in the Debugging Android NDK application at Eclipse recipe .
  7. Run the application on an Android device. Then, start a terminal and enter the following command:
    $ ndk-gdb
    
  8. Once the debugger is attached to the remote process, we can issue GDB commands to start debugging the app. This is shown as follows:
    How to do it...

How it works...

Along with Android NDK comes a shell script named as ndk-gdb to launch a native debugging session with the native code. In order to use ndk-gdb, we must build the native code in the debug mode. This will produce a gdbserver binary and a gdb.setup file along with the native library. At installation, gdbserver will be installed and ndk-gdb will start gdbserver on the Android device.

By default, ndk-gdb searches for a running application and attaches gdbserver to it. There also are options to launch the application automatically before starting the debugging. Because the application starts first before gdbserver is attached to it, some code will be executed before debugging. If we want to debug the code that is executed at the application start up, we can insert a while(true) block. After the debugging session starts, we change the flag value to escape from the while(true)block. This is demonstrated in our sample project.

Once the debug session starts, we can use gdb commands to debug our code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset