Debugging Dalvik
Debugging Dalvik
Preface
Starting with v6.6 IDA Pro can debug Android applications written for the Dalvik Virtual Machine. It includes
the source level debugging too. This tutorial explains how to set up and run a Dalvik debugging session.
We do not need the ADT Bundle, so selecting the “SDK Tools Only” download is enough.
Environment variables
IDA needs to know where the adb utility resides, and tries various methods to locate it automatically.
Usually IDA finds the path to adb, but if it fails then we can define the ANDROID_SDK_HOME or the
ANDROID_HOME environment variable to point to the directory where the Android SDK is installed to.
Android device
Start the Android Emulator or connect the Android device to a USB port.
The information about creating AVDs (Android Virtual Devices) and starting the emulator can be found at
the official site: Using the Emulator.
The information about preparing a physical device for development can be found at Using Hardware
Devices.
$ adb devices
List of devices attached
emulator-5554 device
Install application
IDA presumes that the debugged application is already installed on the Android emulator/device.
Please download MyFirstApp.apk and MyFirstApp.src.zip from our site. We will use this application in the
tutorial.
Preset BPTs
IDA can help us to start debugging by setting breakpoints for all methods of the application activity class.
Path to sources
To use source-level debugging we have to set paths to the application source files. We can do it using the
“Options/Sources path …” menu item.
Our Dalvik debugger presumes that the application sources reside in the current (“.”) directory. If this is not
the case, we can map current directory (“.”) to the directory where the source files are located.
Let us place the source files DisplayMessageActivity.java and MainActivity.java in the same directory as the
MyFirstApp.apk package. This way we do not need any mapping.
Set breakpoints
Before launching the application it is reasonable to set a few breakpoints. We can rely on the decision made
by IDA (see above the presetBPTs option) or set breakpoints ourselves. A good candidate is the “onCreate”
method of the application's main activity.
We can use the activity name and the method name “onCreate” to set a breakpoint:
Naturally, we can set any other breakpoints any time. For example, we can do it later, when we suspend the
application.
Starting the debugger
At last we can start the debugger. Check that the Dalvik debugger backend is selected. Usually it should be
done automatically by IDA:
If the debugger backend is correct, we are ready to start a debugger session. There are two ways to do it:
1. Start process
To start a new copy of the application just press <F9> or use the “Debugger/Start process” menu item. The
Dalvik debugger will launch the application, wait until application is ready and open a debugger session to
it.
We may wait for the execution to reach a breakpoint or press the “Cancel” button to suspend the
application.
In our case let us wait until execution reach of onCreate() method breakpoint.
2. Attach to process
Instead of launching a new process we could attach to a running process and debug it. For that we could
have selected the “Debugger/Attach to process…” menu item. IDA will display a list of active processes.
In Dalvik there is no stack and there is no SP register. The only available register is IP.
The method frame registers and slots (v0, v1, …) are represented as local variables in IDA.
We can see them in the Debugger/Debugger Windows/Locals window (see below)
The stack trace is available from “Debugger/Windows/Stack trace” (the hot key is <Ctrl-Alt-
S>).
When the application is running, it may execute some system code. If we break the
execution by clicking on the “Cancel” button, quite often we may find ourselves outside of
the application, in the system code. The value of the IP register is 0xFFFFFFFF in this case,
and stack trace shows only system calls and a lot of 0xFFFFFFFFs. It means that IDA could
not locate the current execution position inside the application. We recommend to set
more breakpoints inside the application, resume the execution and interact with
application by clicking on its windows, selecting menu items, etc. The same thing can occur
when we step out the application.
Use “Run until return” command to return to the source-level debugging if you
occasionally step into a method and the value of the IP register becomes 0xFFFFFFFF.
Locals window
IDA considers the method frame registers, slots, and variables (v0, v1, …) as local variables. To see their
values we have to open the “Locals” window from the “Debugger/Debugger windows/Locals” menu item.
At the moment the debugger stopped the execution at the breakpoint which we set on onCreate() method.
Let us open the “Locals” window and we will see something like the following:
If the information about the frame is available (the symbol table is intact) then IDA shows the method
arguments, the method local variables with names and other non-named variables. Otherwise some
variable values will not be displayed because IDA does not know their types.
Variables without type information are marked with “Bad type” in the “Locals” window. To see the variable
value in this case please use the “Watch view” window (see below).
Watch view window
To open the “Watch view” window please select the “Debugger/Debugger windows/Watch view” menu
item. In this window we can add any variable to watch its value.
Please note that we have to specify type of variable if it is not known. Use C-style casts:
(Object*)v0
(String)v6
(char*)v17
(int)v7
We do not need to specify the real type of an object variable, the “(Object*)” cast is enough. IDA can derive
the real object type itself.
Attention! An incorrect type may cause the Dalvik VM to crash. There is not much we can do about it. Our
recommendation is to never cast an integer variable to an object type, the Dalvik VM usually crashes if we
do that. But the integer cast “(int)” is safe in practice. If the “object ID safety check” debugger option is
selected then IDA tries to prevent such a situation. The only drawback is that this option adds some
overhead.
Keeping the above in the mind, do not leave the cast entries in the “Watch view” window for a long time.
Delete them before any executing instruction that may change the type of the watched variable.
Check that the emulator is working and was registered as an adb device. Try to restart the
adb daemon.
Turn on more debug print in IDA with the -z50000 command line switch.