SlideShare a Scribd company logo
Eclipseを使ってAndroid
Nativeデバッグしてみる
とちょっとおまけ
2010/08/29
@l_b__
日本Androidの会横浜支部
PF部第1回勉強会
目次
1. Androidのデバッグの仕組み
2. EclipseにAndroidのソースを読み込ませる まずは全部
3. EclipseにAndroidのアプリだけのNativeソースを読み込ませる
4. EclipseでNativeアプリをデバッグしてみる
5. EclipseでAndroidJavaフレームワークをデバッグしてみる
最初にごめんなさい
今回Windows使っていないです。
環境はUbuntuLinux10.04(Lucid Lynx)で試しています。
Android NDK使っていないです。
(というかNDK使ったことありません)
Androidのソースを落として来てください。
(http://source.android.com/source/download.html 参照)
仕組み的にはNDKでも大差無いのではと思います。
Eclipseは3.5(Galileo)、JavaはSun JDK 1.5です。
Ubuntu10.04へのJava1.5のインストールは http://blog.sola-
dolphin-1.net/archives/2613458.html を参照してください。
1.Androidのデバッグの仕組み
AndroidのNativeデバッグ
● ターゲット上のGDBServerとホスト上のGDBをTCPで接続
●  ホスト上のGDBはARM向けクロスターゲットデバッガ。PCに入っている
x86向けではないことに注意。
Target Android Device
process
Host PC
GDBServer
Target Application
ADBGDB
Eclipse
クロスターゲット向け
のデバッガ
AndroidのNativeライブラリデバッグ
● ライブラリをデバッグする場合は別プロセスでGDBServerを立ち
上げて、ターゲットのプロセスにアタッチ。
Target Android Device
process
Host PC
Target Library
ADBGDB
Eclipse
クロスターゲット向け
のデバッガ
process
GDB
Server
AndroidのJavaデバッグ
● DalvikのJDWP(Java Debug Wire Protocol)を使ってTCP経由でリ
モートデバッグ。
● 詳細はソースの/dalvik/docs/debugger.html,debugmon.html参照。
Target Android Device
process
Host PC
DalvikVM
Target Android
Application
ADBJDB
Eclipse
2.EclipseにAndroidのソースを
読み込ませる
まずは全部
まずEclipseの準備
● Eclipse3.5(Galileo)をeclipse.orgから取得してください。
○ubuntu標準の奴は使いません。
● Eclipseを起動、Install New SoftwareでGalileoのサイトを選
び、CDT(Eclipse C/C++ Development Tools)をインストールし
てください。
● 同じくInstall New Software→Mobile and Device
DevelopmentにあるEclipse C/C++ DSF Debugger
Integration,Memory View Enhancements,Remote Launchを
入れとくといいかもしれません。(すみません、こいつらが何か詳細
わかってません)
● 他にもSubclipseなりEGitなりFindBugsなりお好きなプラグインを
どうぞ。
Androidのソース落とす
● 落とし方はhttp://source.android.com/source/download.
htmlなりhttp://blog.sola-dolphin-1.net/archives/2613458.
htmlなり見て下さい。
● 今回はFroyo(Android2.2)のブランチ、ソース
は$HOME/android/myfroyo にあるものとします。
○もちろんソースを置く場所はご自由に。以降をご自分の環境に
置き換えて読んでください。
Eclipseの初期設定
● デフォルトの設定だとヒープ容量が足りないので、以下をEclipse
インストールディレクトリにあるeclipse.iniに追加します。
 
-Xms=128m
-Xmx512m
-XX:MaxPermSize=256m
● 上はAndroid公式の推奨値。PCにメモリを十分積んでいるなら
もっと大きくてもよいかも。
Eclipseに読み込ませる
● Eclipseを起動。File→New→C++Projectで新しくC++のプロジェ
クトを作成します。
Eclipseのプロジェクトに読み込ませる
● すでにMakefileがあるので、Makefile projectのEmpty
Projectを選択。Use default locationのチェックを外し、
Androidのソース位置をLocationに設定。
Eclipseのプロジェクトに読み込ませる
● Finishを押してしばし待ちます。C/C++ファイルのインデックスの
生成にそれなりに時間がかかります。
● バックグラウンドタスクも完了し、無事読み込まれたら
Project→Properties→C/C++ Buildを選択、Behaviourタブを
選択。
●  Use Parallel Buildをチェックし、Use Parallel Jobsに並列ビル
ドするプロセス数を設定。(make の -jオプション。 -j8は速いで
す。)
●  Build(Incremental build)のallを削除。AndroidのMakefile
にはmake allの定義がありません。
Eclipseのプロジェクト設定
 
Eclipseでプロジェクトをビルド
● ここまで設定するとProject→Build Projectでビルドできます。
● ソース全体をビルドするので時間かかります。
●  ProjectのBuild Automaticallyのチェックは外しといたほうがよ
いかも。
Eclipseで全ソース読み込んで良いことは
何?
●  C/C++のソースインデックスが作成されているので、ソースを読む
ときに宣言元や定義元を右クリックで簡単に呼び出せる。
○ただしC/C++ソースのみ。Javaはダメ。Javaについては後述し
ます。
● Nativeフレームワークをがしがし改造するなら改造して全体ビル
ドをEclipse上だけで行える。
しかし...
● とにかくリソース喰い。一部アプリをいじるだけならソース全体読み
込むと余計な時間ばかりかかります。
● 特にVMwareなどの仮想環境上で作業していたり、ノートPCで作
業したりするときはつらいです。
3.EclipseにAndroidのアプリ
だけのNativeソースを
読み込ませる
Nativeアプリの作成
● 例としてHelloWorldをAndroidのログに出力する実行形式のア
プリを作成します。
●  アプリの配置位置として/external/helloworldディレクトリを作
成します。
○フレームワークに手を入れるのではないので、本来は/device/
(ベンダー)/(機種)のような個別向けのディレクトリに配置すべ
きかも。
○ただ、/externalの下に置くと、mm(ビルドコマンド。後述しま
す。)呼んで簡単にビルドできるので。/device以下に置いた時
にどうビルドするかは調べていません。知っていたら教えてくだ
さい。
Nativeアプリの配置例
● HelloWorldアプリはこんな
感じで配置。
● build/build.sh
○ Eclipse向けのビルドスクリプト 実
行権限を付加しておくこと
● libhelloworld
○ ログ書き込み処理を行うstaticラ
イブラリ
● main
○ アプリのメイン関数
● Android.mk
○ 各ディレクトリのビルドスクリプト
Eclipseのビルド設定
● Nativeアプリをビルドするbuild.shを読み込ませる設定は
Project→Propertiesから以下のようにBuild commandを設定。
Eclipseのパス設定
● ソースを全部読み込ませた場合と違い、フレームワークのインク
ルードファイルを自動でインデックス化してくれない。
● なので、フレームワークのインクルードディレクトリを
Project→Propertiesで次ページのように設定するとインクルード
ファイルの依存関係をEclipseが解決してくれるようになる。
● ただし、ビルド時の依存解決は手動で書くAndroid.mkに必要な
インクルードディレクトリを定義することに注意。Eclipseはビルドの
依存関係は解決してくれません。
Eclipseのパス設定
 
Eclipseのパス設定
● パス設定を行う際は下記のチェックを入れておくとC/C++を一度に
設定出来て便利。
HelloWorldアプリ
● 今回のアプリは以下の通り
●  /Android.mk
include $(all-subdir-makefiles)
●  /main/main_helloworld.c
#include <helloworld.h>
int main(int argc, char** argv) {
writeLog();
return 0;
}
HelloWorldアプリ
● /main/Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= main_helloworld.c
LOCAL_STATIC_LIBRARIES += libhelloworld
LOCAL_SHARED_LIBRARIES:= 
libcutils
LOCAL_C_INCLUDES:= $(LOCAL_PATH)/../libhelloworld
LOCAL_MODULE:= helloworld
include $(BUILD_EXECUTABLE)
HelloWorldアプリ
● /libhelloworld/helloworld.c
#define LOG_TAG "HELLOWORLD"
#include <helloworld.h>
#include <cutils/log.h>
void writeLog() {
int i = 0;
for(;i < 5; i++) {
LOGD("Hello Android World. :%d", i);
}
}
HelloWorldアプリ
● /libhelloworld/helloworld.h
#ifndef HELLOWORLD_H_
#define HELLOWORLD_H_
void writeLog();
#endif /* HELLOWORLD_H_ */
HelloWorldアプリ
● /libhelloworld/Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= 
helloworld.c
LOCAL_SHARED_LIBRARIES:= 
libcutils
LOCAL_MODULE:= libhelloworld
include $(BUILD_STATIC_LIBRARY)
HelloWorldアプリ
● /build/build.sh
#!/bin/bash
source ~/android/myfroyo/build/envsetup.sh
cd ~/android/myfroyo/external/helloworld
mm
envsetup.shの便利なコマンド
● Androidの/build/envsetup.shには色々便利なコマンドがありま
す。これらのコマンドを使うには $source build/envsetup.sh を
実行します。
○envsetup.shは実行権限が無いので、sourceコマンドで読み
込ませます。
●  croot ソースツリーのトップに移動
●  cgrep ソースツリーのC/C++ファイルからgrep
●  jgrep ソースツリーのJavaファイルからgrep
●  resgrep ソースツリーのres/*.xmlからgrep
●  godir 指定した名前のファイルを含むディレクトリに移動
●  m ソース全体のビルド
●  mm 現在のディレクトリ以下をビルド(そのディレクトリにAndroid.mkが必要)
●  mmm 現在のディレクトリから相対パスで指定したディレクトリ以下をビルド
●  choosecombo ビルドターゲット用の環境変数を設定する(lunchの方が便利そう)
アプリのビルド
● EclipseでProject→Build Projectとやるとビルドされます。
(build/build.shを呼んでいるだけです)
● ビルドされたアプリはデバッグシンボル付きが
out/target/product/generic/symbols/system/binに、デ
バッグシンボル無しが
out/target/product/generic/system/bin に配置されます。
Nativeのビルド出力
● Nativeアプリ/ライブラリは一般的に以下の手順でビルドされま
す。
●  out/target/product/generic/objの下でオブジェクトファイル
がコンパイルされる。アプリはEXECUTABLES、ライブラリは静的
がSTATIC_LIBRARIES、動的がSHARED_LIBRARIES以下
にそれぞれのディレクトリが生成されます。
○helloworldの場合、
out/target/product/generic/obj/EXECUTABLES/
          helloworld_intermediates
Nativeのビルド出力
● それぞれのディレクトリのLINKEDディレクトリにデバッグシンボル
付きバイナリがリンクされます。
● stripコマンドでデバッグシンボルが取り除かれたバイナリが各
ディレクトリに配置されます。
○helloworldの場合、デバッグシンボル付きバイナリは
out/target/product/generic/obj/EXECUTABLES/
           helloworld_intermediates/LINKED に、
          デバッグシンボル無しは
   out/target/product/generic/obj/EXECUTABLES/
   helloworld_intermediates に出来ます。
Nativeのビルド出力
● 最終的にinstallコマンドによって、各バイナリは
out/target/product/generic/ 以下のディレクトリに配置され
ます。
○デバッグシンボル付きアプリはsymbols/system/bin
○デバッグシンボル無しアプリはsystem/bin
○デバッグシンボル付き動的ライブラリはsymbols/system/lib
○デバッグシンボル無し動的ライブラリはsystem/lib
HelloWorldの実行結果
● デバイスやエミュレータを起動し、adbで接続できることを確認しま
す。
● helloworldのバイナリをadbでデバイスに転送します。
○adb push helloworld /data/local/tmp
● adbでデバイスにログインし、アプリを実行します。
○adb shell chmod +x /data/local/tmp/helloworld
○adb shell /data/local/tmp/helloworld
● logcatでログにHelloWorldの結果が出力されているのを確認し
ます。
HelloWorldの実行結果
● adb logcatした結果
D/HELLOWORLD(  366): Hello Android World. :0
D/HELLOWORLD(  366): Hello Android World. :1
D/HELLOWORLD(  366): Hello Android World. :2
D/HELLOWORLD(  366): Hello Android World. :3
D/HELLOWORLD(  366): Hello Android World. :4
4.EclipseでNativeアプリを
デバッグしてみる
ようやく本題
● 大雑把なデバッグの手順は以下の通りです。
○デバイス/エミュレータにシンボル付きバイナリとgdbserverを
転送します。
○デバイス上でgdbserverを起動。
○adbでgdbserverのポートをフォワード。
○Eclipseのデバッグ構成を設定。
○EclipseのC/C++アプリリモートデバッグでadbがフォワードした
ポートに接続してデバッグ。
ファイルのデバイスへの転送
● まずはgdbserverを転送します。
○adb push prebuilt/android-arm/gdbserver/gdbserver
/data/local/tmp
○adb shell chmod +x /data/local/tmp/gdbserver
● 次にデバッグシンボル付き実行ファイルを転送します。
○adb
push  out/target/product/generic/symbols/system/bin
/helloworld /data/local/tmp
○adb shell chmod +x /data/local/tmp/helloworld
GDBServerの起動
● GDBServerをadb経由で起動します。
○adb shell /data/local/tmp/gdbserver :5039
/data/local/tmp/helloworld
● これでデバイスのポート5039でgdbserverが起動し、接続待ち
状態になります。
GDBServerのポートをフォワード
● ADBを使ってホストのポートをGDBServerの待ち受けポートに転
送します。
○adb forward tcp:5039 tcp:5039
● ホストのTCPポート5039への接続がデバイスのTCPポート5039
に転送されます。
● ファイルの転送からポートのフォワードまではスクリプト化しておく
と楽でしょう。
Eclipseのデバッグ構成
● Eclipseのデバッグの構成を開き、C/C++ Applicationに新しい構
成を作成します。
○ C/C++ Remote Applicationでは無いので注意。
● MainタブのC/C++ Applicationにデバッグシンボル付きバイナリ
の位置を設定します。
Eclipseのデバッグ構成 Debuggerタブ
● デバッグ構成のDebuggerタブでDebuggerにgdbserver
Debuggerを選択、Stop on start at mainにチェックします。
●  MainタブのGDB debuggerにクロスターゲットデバッガを設定し
ます。
Eclipseのデバッグ構成 Debuggerタブ
● SharedLibrariesタブにデバッグシンボル付き動的ライブラリの
ディレクトリを設定します。
Eclipseのデバッグ構成 Debuggerタブ
● ConnectionタブでTypeをTCP、Port Numberを5039に設定し
ます。
Eclipseのデバッグ構成 Sourceタブ
● Sourceタブは特に修正していません。デフォルトで以下のように
設定されます。
デバッグの実行
● デバッグを実行するとmain関数で止まった状態でデバッグパース
ペクティブが開きます。
再度ごめんなさい
JNI使ったAndroidアプリのNativeライブラリ側デバッグについても
書こうと思っていましたが、力尽きました。
機会があったらまたということで。
5.EclipseでAndroid
Javaフレームワークを
デバッグしてみる
おまけですが...
● EclipseにAndroidのソースを読み込ませて、Javaフレームワーク
をデバッグすることができます。
●  DDMSにプロセス毎のDalvik JDWP待ち受けポートが表示され
るので、Javaリモートアプリケーションのデバッグ機能を使って接
続します。
Eclipseプロジェクトへの読み込み
● Eclipseを起動。File→New→JavaProjectで新しくJavaのプロ
ジェクトを作成します。
● その後、Nextを押してしばらく
  待ちます。
プロジェクトを読み込むときの注意
● 同一のディレクトリを複数のプロジェクトで共有することはできませ
ん。
○外部のソースをインポートしてプロジェクトを作成した場合、.
projectファイルがディレクトリに作成されるため、一つのディレ
クトリは一つのプロジェクトとしか結びつかない。
● シンボリックリンクを使ってみたが、どうも深いディレクトリにある
POLICY系のファイルを読んでくれずに、makeするとビルドエラー
が発生。
● しょうがないので、C向けとJava向けにFroyoのディレクトリを別に
作りました... いい対処方法あったら教えてください。
Eclipseプロジェクトへの読み込み
● プロジェクトの作成でしばらく待つと、ソースを自動でインポートし
てくれます。(Linux版のみ。Windows版の場合は自分でソース
ディレクトリを設定する必要があります。)
DDMSでデバッグしたいプロセスの選択
● DDMSを開き、DevicesのViewでデバッグしたいプロセスを確認
します。右側にJDWPのポート番号が表示されます。
● launcherをデバッグするので、ポート8603か8700を選びます。
○8603はVM毎にユニークなポート番号、8700はDDMSで選択
されたVMに割り当てられるポート番号?
DDMSでデバッグしたいプロセスの選択
 
Javaのデバッグ構成
● Eclipseのデバッグの構成を開き、Remote Java Applicationに
新しい構成を作成します。
● 接続先のポートに8603か8700を指定し、デバッグを実行しま
す。
デバッグの実行
● デバッグパースペクティブでデバッグ情報が表示されます。
● なぜかソースとステップ実行中の行が連動しませんが、変数や行
番号情報は表示され、ステップ実行も可能です。ブレークポイント
もきちんと設定されます。 (ソースディレクトリとして登録されたの
が多すぎか?)
デバッグの実行
 
最後に
ご質問があったら日本Androidの会横浜支部のGoogle Groups
(http://groups.google.com/group/android-jp-yokohama)まで
どうぞ。

More Related Content

PPTX
Welding and cutting safety
PDF
Open binder
ODP
Stagefright入門
ODP
Yapf2013
PDF
JellyBeanのソースをとりあえず眺めてみた(手抜き)
PDF
ABS2015 のセッション紹介
PDF
PF開発に使えるAOSPのツール達
PDF
Stagefright入門
Welding and cutting safety
Open binder
Stagefright入門
Yapf2013
JellyBeanのソースをとりあえず眺めてみた(手抜き)
ABS2015 のセッション紹介
PF開発に使えるAOSPのツール達
Stagefright入門

Similar to Eclipseを使ったandroid nativeデバッグ (20)

PPT
Android Hacks - Hack40
PDF
Getting Started GraalVM (再アップロード)
PDF
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
PDF
Pf部2011年10月勉強会.1@androidsola
PDF
Androidアプリ開発ごっこ
PDF
GDKとLLVM(横浜PF部向け)
PDF
0621 ndk game
PPT
Android Hacks - Hack47
PDF
Let's play with Goldfish
PDF
第1回名古屋Android勉強会Lt用資料
PDF
Android App Development with Gradle & Android Studio
PDF
20150425 DroidKaigi つかえるGradleプロジェクトの作り方
PPTX
Rhodes mobile Framework (Japanese)
ODP
Android デバッグ小ネタ
PDF
Android起動周りのノウハウ
PDF
20161125 Unity-Android連携の発表資料
PPTX
CMake multiplatform build-tool
PDF
Introduction of Rhodes
PDF
Android Dev Tools Knowledge
ODP
How to use GPL software in closed source Android application
Android Hacks - Hack40
Getting Started GraalVM (再アップロード)
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Pf部2011年10月勉強会.1@androidsola
Androidアプリ開発ごっこ
GDKとLLVM(横浜PF部向け)
0621 ndk game
Android Hacks - Hack47
Let's play with Goldfish
第1回名古屋Android勉強会Lt用資料
Android App Development with Gradle & Android Studio
20150425 DroidKaigi つかえるGradleプロジェクトの作り方
Rhodes mobile Framework (Japanese)
Android デバッグ小ネタ
Android起動周りのノウハウ
20161125 Unity-Android連携の発表資料
CMake multiplatform build-tool
Introduction of Rhodes
Android Dev Tools Knowledge
How to use GPL software in closed source Android application
Ad

More from l_b__ (7)

ODP
Fuchsia概略その1
PDF
Android,Brillo,ChromeOS
PDF
Androidの新ビルドシステム
PDF
Androidのリカバリシステム (Androidのシステムアップデート)
PDF
Binderのはじめの一歩とAndroid
PDF
Binderのはじめの一歩
ODP
Intentの概要
Fuchsia概略その1
Android,Brillo,ChromeOS
Androidの新ビルドシステム
Androidのリカバリシステム (Androidのシステムアップデート)
Binderのはじめの一歩とAndroid
Binderのはじめの一歩
Intentの概要
Ad

Eclipseを使ったandroid nativeデバッグ