Sie sind auf Seite 1von 29

Android debugging

Summary


Overview

Debugging Environment

ADB

Reading and writing logs

Logcat

Progress


Overview

Debugging Environment

ADB

Reading and writing logs

Logcat

Overview (1/3)


The Android SDK provides most of the tools that you need to debug your
applications

You need a JDWP-compliant debugger if you want to be able to do things


such as:


Step through code

View variable values

Pause execution of an application

If you are using Eclipse, a JDWP-compliant debugger is already included


and there is no setup required

If you are using another IDE, you can use the debugger that comes with it
and attach the debugger to a special port so it can communicate with the
application VMs on your devices

Overview (2/3)


The main components that comprise a typical Android debugging


environment are:


adb - acts as a middleman between a device and your development system. It provides
various device management capabilities, including moving and syncing files to the emulator,
running a UNIX shell on the device or emulator, and providing a general means to
communicate with connected emulators and devices.

Dalvik Debug Monitor Server - DDMS is a graphical program that communicates with your
devices through adb. DDMS can capture screenshots, gather thread and stack information,
spoof incoming calls and SMS messages, and has many other features.

Device/Android Virtual Device - Your application must run in a device or in an AVD so that
it can be debugged. An adb device daemon runs on the device or emulator and provides a
means for the adb host daemon to communicate with the device or emulator.

JDWP - The Dalvik VM (Virtual Machine) supports the JDWP protocol to allow debuggers to
attach to a VM. Each application runs in a VM and exposes a unique port that you can attach
a debugger to via DDMS. Most modern Java IDEs include a JDWP debugger, or you can use
a command line debugger such as jdb.

Overview (3/3)


We will focus on the following:




Debugging native code

Locating the problem using one of the (or usually all of the) following:


adb

Loging using Log class/Logcat

Debugging using GDB

What is the best solution for debugging on Android?

Progress


Overview

Debugging Environment

ADB

Reading and writing logs

Logcat

Debugging Environment

Progress


Overview

Debugging Environment

ADB

Reading and writing logs

Logcat

Android Debug Bridge


ADB


Android Debug Bridge (adb) is a versatile tool lets you manage the state of
an emulator instance or Android-powered device. It is a client-server
program that includes three components:


A client, which runs on your development machine. You can invoke a client from a shell by
issuing an adb command. Other Android tools such as the ADT plugin and DDMS also create
adb clients.

A server, which runs as a background process on your development machine. The server
manages communication between the client and the adb daemon running on an emulator or
device.

A daemon, which runs as a background process on each emulator or device instance.

When you start an adb client, the client first checks whether there is an adb
server process already running.

If there isn't, it starts the server process. When the server starts, it binds to
local TCP port 5037 and listens for commands sent from adb clientsall
adb clients use port 5037 to communicate with the adb server.

ADB
Issuing adb Commands


You can issue adb commands from a command line on your development
machine or from a script. The usage is:
adb [-d|-e|-s <serialNumber>] <command>

When you issue a command, the program invokes an adb client.

The client is not specifically associated with any emulator instance, so if


multiple emulators/devices are running, you need to use the -d option to
specify the target instance to which the command should be directed.

ADB
Emulator/Device Instances


Before issuing adb commands, it is helpful to know what emulator/device


instances are connected to the adb server.

You can generate a


the devices command:

list

of

attached

emulators/devices

adb devices


Here's an example showing the devices command and its output:


$ adb devices
List of devices attached
emulator-5554 device
emulator-5556 device
emulator-5558 device

using

ADB
Directing Commands to a Specific
Emulator/Device Instance


If multiple emulator/device instances are running, you need to specify a


target instance when issuing adb commands.

To do so, use the -s option in the commands. The usage for the -s option is:
adb -s <serialNumber> <command>

As shown, you specify the target instance for a command using its adbassigned serial number. You can use the devices command to obtain the
serial numbers of running emulator/device instances.
Here is an example:
adb -s emulator-5556 install helloWorld.apk

Note that, if you issue a command without specifying a target


emulator/device instance using -s, adb generates an error.

ADB
More useful tips
Forwarding Ports


You can use the forward command to set up arbitrary port forwarding
forwarding of requests on a specific host port to a different port on an
emulator/device instance.

Here's how you would set up forwarding of host port 6100 to


emulator/device port 7100:
adb forward tcp:6100 tcp:7100

ADB
More useful tips
Copying Files to or from an Emulator/Device Instance


You can use the adb commands pull and push to copy files to and from an
emulator/device instance's data file. The pull and push commands let you
copy arbitrary directories and files to any location in an emulator/device
instance.

To copy a file or directory (recursively) from the emulator or device, use:


adb pull <remote> <local>

To copy a file or directory (recursively) to the emulator or device, use:


adb push <local> <remote>

In the commands, <local> and <remote> refer to the paths to the target
files/directory on your development machine (local) and on the
emulator/device instance (remote).
Here's an example:
adb push foo.txt /sdcard/foo.txt

ADB
More useful tips
Issuing Shell Commands


Adb provides an ash shell that you can use to run a variety of commands on
an emulator or device. The command binaries are stored in the file system
of the emulator or device, in this location:
/system/bin/...




You can use the shell command to issue commands, with or without
entering the adb remote shell on the emulator/device.
To issue a single command without entering a remote shell, use
the shell command like this:
adb [-d|-e|-s {<serialNumber>}] shell <shellCommand>

When you are ready to exit the remote shell, use CTRL+D or exit to end the
shell session.

ADB
Other Shell Commands


The list below shows several of the adb shell commands available. For a
complete list of commands and programs, start an emulator instance and
use the adb -help command.


dumpsys

- Dumps system data to the screen.

dumpstate

- Dumps state to a file.

logcat [<option>]... [<filter-spec>]... - Enables radio logging and prints output to the screen.

dmesg

- Prints kernel debugging messages to the screen.

start

- Starts (restarts) an emulator/device instance.

stop

- Stops execution of an emulator/device instance.

Progress


Overview

Debugging Environment

ADB

Reading and writing logs

Logcat

Reading and Writing Logs




The Android logging system provides a mechanism for collecting and


viewing system debug output.

Logcat dumps a log of system messages, which include things such as


stack traces when the emulator throws an error and messages that you
have written from your application by using the Log class.

You can run LogCat through ADB or from DDMS, which allows you to read
the messages in real time.

The Log class




Log is a logging class that you can utilize in your code to print out messages
to the LogCat.

Common logging methods include:

v(String, String)

(verbose)

d(String, String)

(debug)

i(String, String)

(information)

w(String, String)

(warning)

e(String, String)

(error)

For example:
Log.i("MyActivity", "MyClass.getView() get item number " + position);

The LogCat will then output something like:


I/MyActivity( 1557): MyClass.getView() get item number 1

Progress


Overview

Debugging Environment

ADB

Reading and writing logs

Logcat

Using LogCat
Basics


You can use LogCat from within DDMS or call it on an ADB shell.

To run LogCat, through the ADB shell, the general usage is:
[adb] logcat [<option>] ... [<filter-spec>] ...

You can use the logcat command from your development computer or from
a remote adb shell in an emulator/device instance. To view log output in
your development computer, you use:
$ adb logcat

and from a remote adb shell you use:


# logcat

Using LogCat
Commands


The following table describes the logcat command line options:




-c,

Clears (flushes) the entire log and exits.

-d,

Dumps the log to the screen and exits.

-f <filename>, Writes log message output to <filename>. The default is stdout.

-g,

Prints the size of the specified log buffer and exits.

-n <count>,

Sets the maximum number of rotated logs to <count>. Requires the -r option.

-r <kbytes>, Rotates the log file every <kbytes> of output. Requires the -f option.

-s,

-v <format>, Sets the output format for log messages. The default is brief format.

Sets the default filter spec to silent.

Using LogCat
Filtering log output



Every Android log message has a tag and a priority associated with it.
The tag of a log message is a short string indicating the system component
from which the message originates (for example, "View" for the view
system).
The priority is one of the following character values, ordered from lowest to
highest priority:








V
D
I
W
E
F
S

Verbose (lowest priority)


Debug
Info
Warning
Error
Fatal
Silent (highest priority, on which nothing is ever printed)

To reduce the log output to a manageable level, you can restrict log output
using filter expressions.

Filter expressions let you indicate to the system the tags-priority


combinations that you are interested in the system suppresses other
messages for the specified tags.

Using LogCat
Filtering log output


Here's an example of a filter expression that suppresses all log messages


except those with the tag "ActivityManager", at priority "Info" or above, and
all log messages with tag "MyApp", with priority "Debug" or above:
adb logcat ActivityManager:I MyApp:D *:S

The final element in the above expression, *:S, sets the priority level for all
tags to "silent", thus ensuring only log messages with "View" and "MyApp"
are displayed.
Using *:S is an excellent way to ensure that log output is restricted to the
filters that you have explicitly specified it lets your filters serve as a
"whitelist" for log output.
The following filter expression displays all log messages with priority level
"warning" and higher, on all tags:
adb logcat *:W

Using LogCat
Viewing stdout and stderr



By default, the Android system sends stdout and stderr (System.out and
System.err) output to /dev/null.
In processes that run the Dalvik VM, you can have the system write a copy
of the output to the log file. In this case, the system writes the messages to
the log using the log tags stdout and stderr, both with priority I.
To route the output in this way, you stop a running emulator/device instance
and then use the shell command setprop to enable the redirection of output.
Here's how you do it:
$ adb shell stop
$ adb shell setprop log.redirect-stdio true
$ adb shell start

The system retains this setting until you terminate the emulator/device
instance. To use the setting as a default on the emulator/device instance,
you can add an entry to /data/local.prop on the device.

Using LogCat
Crash caught in logcat


Youll see something like this:


I/DEBUG
( 1326): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG
( 1326): Build fingerprint:
'SigmaDesigns/smp86xx/smp86xx/:2.2.1/FRG83/eng.janjic.20110531.154325:eng/testkeys'
I/DEBUG
( 1326): pid: 1716, tid: 1729 >>> com.android.browser <<<
I/DEBUG
( 1326): signal 11 (SIGSEGV), fault addr 203e1a20
I/DEBUG
( 1326): zr 00000000 at 00000001 v0 30e589c9 v1 00000003
I/DEBUG
( 1326): a0 30e589c9 a1 303f9e31 a2 00000001 a3 2d498240
I/DEBUG
( 1326): t0 00000001 t1 2ff16ea1 t2 3020f4f0 t3 2d4893e1
I/DEBUG
( 1326): t4 2d498240 t5 7ba64110 t6 000000a3 t7 00000001
I/DEBUG
( 1326): s0 00000002 s1 3028f6b8 s2 7b6f57d4 s3 2d46805d
I/DEBUG
( 1326): s4 2ff140a1 s5 2ff140a1 s6 7ba68794 s7 30405149
I/DEBUG
( 1326): t8 7ba77bf4 t9 303e1a20 k0 00000000 k1 00000000
I/DEBUG
( 1326): gp 7ba55330 sp 3028f6ec s8 3028f6f8 ra 2d4a5d5c
I/DEBUG
( 1326): hi 00000000 lo 00000000 bva 203e1a20 epc 203e1a20
I/DEBUG
( 1326):
#00 pc 203e1a20 <unknown>
I/DEBUG
( 1326):
#01 ra 2d4a5d5c <unknown>

I/DEBUG

( 1326): stack:

I/DEBUG

( 1326):

3028f7d0

Where is the problem?

7b64dea0

/system/lib/libwebcore.so

Using LogCat
Crash caught in logcat


Obviously somewhere in libwebcore.so is the problem?





First we look at the pc (program counter)







Hold the address of the instruction that caused crash

Then we look at the prelink-map for our architecture




What is the line of the code that caused this?


Maybe libwebcore.so uses some other library (statically linked)?

First we obtain address of the libwebcore.so library (absolute address)


Subtract value in pc (absolute address) from address of the library in prelink-map
This gives us the address of the instruction, inside library (relative), that caused crash.

What to do then?
We need binary that has all of the symbols in it:
./out/target/product/generic/symbols/system/lib/libwebcore.so

Dump the symbols to a file, and look four our relative address:


This will give us the correct line in code that caused the crash

./prebuilt/linux-x86/toolchain/mips-4.4.3/bin/mips-linux-gnu-objdump DSgltC
./out/target/product/generic/symbols/system/lib/libwebcore.so > objdump.log

References/Usefull links


http://developer.android.com/guide/developing/debugging/index.html

http://androidcore.com/android-programming-tutorials/

http://www.kandroid.org/online-pdk/guide/debugging_gdb.html

Das könnte Ihnen auch gefallen