Android Native (NDK) code debugging and how Virtual Platforms can help you now

56 views
Skip to first unread message

AchimNohl

unread,
Feb 10, 2010, 3:58:10 AM2/10/10
to Virtual Platform-Users
Complementing the JAVA Application Software Development Kit (SDK)
Google has release the so called Native Code Development (NDK). The
NDK allows application developers package native (e.g. ARM) object
code libraries together with their JAVA application. The libraries are
typically written using C/C++ but can also contain highly optimized
assembly level routines. The reason for Google going that path is to
enable application writers to sort out performance critical code into
optimized C/assembly functions, as well as re-using huge amount of
legacy C code. The NDK goes along with the SDK. This means, you still
need the SDK to setup a project etc. From the Java code in the SDK you
can now call functions that you implement in C/C++ and export within a
shared object (.so) that is part of the SDK project.

The problem for application writers using the NDK is the weak
debugging support for native code. As soon as your application leaves
the Java world and executes your routines written in C, debugging ends
within the Java SDK. Under the hood the Java Virtual Machine loads the
shared object and makes sure the routines get called. Typically you
have no insight into what happens now from a debug point of view.
There are some useful tutorials on the web about how to debug native
applications using gdb-server (which is already very cumbersome). I
have not found good guidance on how to apply that with the NDK and
mixed Java/C applications. Anyway, the pain to set-up a debugger for
native code debugging of shared objects lets people (according to what
I read in the forums on a daily basis) put hundreds of “printfs” in
their code as this is currently the most efficient method for
debugging. Google has announced better debugging support in a next
release, but it is unclear when and how this will work.

Already today Virtual Platforms and their instant tracing capabilities
are of great help for Android NDK developers. A good example is our
Virtual Platform in the cloud and you can try it out yourself. The
solution allows you to instantly trace C functions within your library
without any need for instrumentation. This gives you immediately
insight into your application function execution and also interaction
with the OS or the Java layer. E.g. you can easily find out when your
application seg-faults (triggers a data-abort) or validate that the
right code is executed. You can observer how your code talks to OS
drivers or the Android middleware. No more need for printfs and it
will significantly speed-up your debug efforts.

I think this is a good and practical example how Virtual Platforms
help Application Development through new tools that are enabled by
their advanced controllability and visibility. On top of debugging,
VPs also provide you instantly with performance profiling information
of your native code.In a reply to this post I will indicate the steps
you need to take to try it out yourself using our VP in the cloud.

How can this be done? The Android Linker is responsible for loading
shared libraries. Using the scripting capabilities of Virtual
Platforms we have put a breakpoint in the function where the linker
loads a shared object. We attach a callback script that reads the
filename and the link address. Now the callback reads the symbols from
the host. You can read more about the scripting capabilities using the
“Scripting Solutions” PDF on the desktop of the VP on the cloud. You
can read more about the OS aware tracing and anaylsis using the
"User's guide" PDF on the desktop of the VP on the cloud.

AchimNohl

unread,
Feb 11, 2010, 3:43:11 AM2/11/10
to Virtual Platform-Users
Hi all,
Find below the details steps to build an Android NDK application and
SDK project (Step 1,2) and configure our VP to debug the NDK code
(Step 3,4,5,6):

Step 1: “Build the application native shared library”
- Click desktop icon „Download and Install Google’s NDK/SDK“
- Open a terminal “Applications->System Tools->Terminal”
- Change directory to “cd ARM926EJS-CoWareVP-VersatilePB-QuadCore-
Free-1.20/other/android_r1/sdk/android-ndk-1.6_r1”
- Launch the NDL setup “build/host-setup.sh”
- Select an application via setting the environment variable APP to an
application in the apps directory “export APP=san-angeles”
o You find the native C code in e.g. “apps/san-sangeles/jni”
- Build the application shared library by calling “make”

Step 2: “Create an SDK project”
- Click desktop icon “Launch Google’s Eclipse Android SDK”
- In Ecplise: Select “File->New->Android Project”
- Choose “Create project from existing source”
- Click “Browse” and select your application e.g “sdk\android-
ndk-1.6_r1\apps\san-angeles\project”
- Press “Finish”
- In the “Package Explorer”, right click on your project and select
“Build Path->Configure Buildpath”
- Check the box “Android 2.0” and press “Ok”

Step 3: “Launch the Android skin on the VP”
- Click desktop icon “Launch CoWare Virtual Platform” and press the
green “Play” button
- Wait until the phone GUI is visible and press “Debug->Continue” in
the VPA (F5)


Step 4: “Prepare the VP to trace your NDK application”
- Wait until the phone has booted and the Android desktop is visible
- Suspend the simulation via “Debug->Suspend” in the VPA (F9)
- Enable automatic loading of symbol files via the Android Linker
- We do not want all Android Middleware symbols. Set system symbols to
a bogus location such as “/home/demo” via “Android->Software Analysis-
>Symbolfile Directories->Set System Symbols Directory”
- Set the NDK directory to your application via “Android->Software
Analysis->Symbolfile Directories->Set NDK Symbols Directory” to sdk
\android-ndk-1.6_r1\apps\ san-angeles \project\libs\armeabi
- Enable process tracing via “Analysis->Configure” and Choose “Context
Trace” and “Function Trace”
- Click desktop icon “Restart SDK-VP Android Debug Bridge”
- Continue the simulation in the VPA via press “Debug->Continue” in
the VPA (F5)

Step 5: “Upload your application to your phone using the SDK”
- In Eclipse press the green “Play” button
- Choose “Android Application” and press “Ok”
- Now your application will get uploaded on the phone, sometimes the
adb times out->just press “Play” again to launch

Step 6: “Analyze/Debug”
- In VPA choose “Analysis->View”
- Double click on “Context Trace”
- At the time you see the “San-Angeles” process gets invoked you will
the launch of a new Thread
- Position the time curser somewhere in the thread
- Open the “Function Trace” via a double click on “Function Trace” in
“Results”
- Click into the function trace when the thread is active and you
will see the function history of your native library
- In the Details View you will see profiling information for the
selected time range
- You can filter out the linker symbols via “Configure->Filter”, Enter
“__dl.*”, Add “+” and choose “Exclude”

You can now modify/rebuild your NDK application as many times (see
Step 1) as you want and upload it on the VP (Step 5) to analyze it
using the process/function tracing. Note: In order to let the SDK
create a new updated package after modifying the native code, you need
to touch the Java code (just add/delete whitespaces).

Best regards,
Achim


AchimNohl

unread,
Feb 12, 2010, 4:09:14 AM2/12/10
to Virtual Platform-Users
Hi all,

following up with this discussion I have uploaded a screenshot of the
previously described software analysis on the Android NDK. You can
(hopefully) access the screenshot via:

http://virtual-platform-users.googlegroups.com/web/software_analysis_android_and_ndk.png

What does it show:
- Row 1: The "Function Trace" over time within the thread started from
the NDK library san-angeles
- Row 2: The "Context Trace" shows the Linux processes over time
- Row 3,4,5: The points refer to software messages coming from Anroid
Logger/Logcat (Row3), Kernel Debug Messages/printk (Row4), Sys-Open
systemcall (Row5).
- Bottom left window: Stack trace at the point in time selected with
the time cursor
- Bottom mid window: Performance information of the region slected
within the NDK thread
- Bottom right window: Messages coming from Android Logger/logcat

Note that all those information where dynamically extracted from
Android running on a Virtual Platform. There were no changes/
instrumentation required in the Android application ,middleware
neither are changes required in the Linux kernel. This level of
visibility is of great help when debugging accross multiple layers in
an embedded software stack.

Reply all
Reply to author
Forward
0 new messages