cocos2d-xでandroidのコアダンプ（tombstone）からどこで死んだか取得する方法


cocos2d-xの開発は基本Xcodeとシミュレータで行い、androidはたまに動作確認するといったスタンスでの開発になると思いますが、いざandroidでアプリが落ちた時にデバッガと繋がっていなくて困ることが多いと思います。

実はandroidではアプリがクラッシュした時に、logcatにtombstoneという以下の様なコアダンプを吐いています。

```
I/DEBUG   (  219): debuggerd: 2014-06-11 18:19:57
I/DEBUG   (  219): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG   (  219): Build fingerprint: 'xxx'
I/DEBUG   (  219): pid: 15992, tid: 16012, name: Thread-27308  >>> xxx <<<
I/DEBUG   (  219): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000004
I/DEBUG   (  219):     r0 00000000  r1 00000001  r2 00000001  r3 00000000
I/DEBUG   (  219):     r4 60eb1b84  r5 60af4364  r6 62b93e68  r7 5e097f30
I/DEBUG   (  219):     r8 60788c50  r9 5e097f28  sl 40478510  fp 60788b54
I/DEBUG   (  219):     ip 00000000  sp 60788b40  lr 609fe144  pc 60b87d18  cpsr 60000010
I/DEBUG   (  219):     d0  6f50726564616853  d1  65546e6f69746973
I/DEBUG   (  219):     d2  6c6f436572757478  d3  50564d6f6e5f726f
I/DEBUG   (  219):     d4  ff04091aff01081e  d5  ff020a21ff050a1c
I/DEBUG   (  219):     d6  ee070b1cee03091f  d7  ee030c24ee070c1e
I/DEBUG   (  219):     d8  0000000000000000  d9  0000000000000000
I/DEBUG   (  219):     d10 0000000000000000  d11 0000000000000000
I/DEBUG   (  219):     d12 0000000000000000  d13 0000000000000000
I/DEBUG   (  219):     d14 0000000000000000  d15 0000000000000000
I/DEBUG   (  219):     d16 6f50726564616853  d17 65546e6f69746973
I/DEBUG   (  219):     d18 0000000000000000  d19 0000000000000000
I/DEBUG   (  219):     d20 0000000000000000  d21 0000000000000000
I/DEBUG   (  219):     d22 0000000000000000  d23 0000000000000000
I/DEBUG   (  219):     d24 0000000000000000  d25 0000000000000000
I/DEBUG   (  219):     d26 0000000000000000  d27 0000000000000000
I/DEBUG   (  219):     d28 0100010001000100  d29 0100010001000100
I/DEBUG   (  219):     d30 0000000000000000  d31 0000000000000000
I/DEBUG   (  219):     scr 6000001a
I/DEBUG   (  219):
I/DEBUG   (  219): backtrace:
I/DEBUG   (  219):     #00  pc 003fed18  /data/data/xxx/lib/libcocos2dcpp.so (cocos2d::Ref::retain()+20)
I/DEBUG   (  219):     #01  pc 00275140  /data/data/xxx/lib/libcocos2dcpp.so (SplashScene::init()+192)
I/DEBUG   (  219):
I/DEBUG   (  219): stack:
I/DEBUG   (  219):          60788b00  60788b14  [stack:16012]
I/DEBUG   (  219):          60788b04  00000000
I/DEBUG   (  219):          60788b08  00000001
I/DEBUG   (  219):          60788b0c  647af210
I/DEBUG   (  219):          60788b10  60788b3c  [stack:16012]
I/DEBUG   (  219):          60788b14  60abad30  /data/data/xxx/lib/libcocos2dcpp.so (cocos2d::Node::addChild(cocos2d::Node*, int, int)+324)
I/DEBUG   (  219):          60788b18  43a00000  /dev/ashmem/dalvik-heap (deleted)
I/DEBUG   (  219):          60788b1c  647af234
I/DEBUG   (  219):          60788b20  ffffffff
I/DEBUG   (  219):          60788b24  00000000
I/DEBUG   (  219):          60788b28  647af210
I/DEBUG   (  219):          60788b2c  647af040
I/DEBUG   (  219):          60788b30  60788b44  [stack:16012]
I/DEBUG   (  219):          60788b34  60eb1b84  /data/data/xxx/lib/libcocos2dcpp.so
I/DEBUG   (  219):          60788b38  df0027ad
I/DEBUG   (  219):          60788b3c  00000000
I/DEBUG   (  219):     #00  60788b40  60788b54  [stack:16012]
I/DEBUG   (  219):          ........  ........
I/DEBUG   (  219):     #01  60788b40  60788b54  [stack:16012]
I/DEBUG   (  219):          60788b44  60af4388  /data/data/xxx/lib/libcocos2dcpp.so (cocos2d::Sprite::setPosition(cocos2d::Point const&)+36)
I/DEBUG   (  219):          60788b48  647af210
I/DEBUG   (  219):          60788b4c  00000000
I/DEBUG   (  219):          60788b50  60788b94  [stack:16012]
I/DEBUG   (  219):          60788b54  609fe144  /data/data/xxx/lib/libcocos2dcpp.so (SplashScene::init()+196)
I/DEBUG   (  219):          60788b58  60788b7c  [stack:16012]
I/DEBUG   (  219):          60788b5c  647af040
I/DEBUG   (  219):          60788b60  00000000
I/DEBUG   (  219):          60788b64  43a00000  /dev/ashmem/dalvik-heap (deleted)
I/DEBUG   (  219):          60788b68  440e0000  /dev/ashmem/dalvik-heap (deleted)

・・・
```

レジスタの状態、バックトレース、スタックなどが表示されるのですが、レジスタはもとよりバックトレースやスタックも一部の情報しかありません。
この場合、SplashScene::init()の中で死んだんだろうなーということが分かりますが、ここまで出ることもあまり多くなく、このままではデバッグで死ぬことになります。

そこで `ndk-stack` を使うと、以下のように実際のソースコードにおける場所をバックトレースに表示してくれます。

```
$ ndk-stack -sym proj.android/obj/local/armeabi/ -dump logcat2
********** Crash dump: **********
Build fingerprint: 'xxx'
pid: 15992, tid: 16012, name: Thread-27308  >>> xxx <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000004
Stack frame #00  pc 003fed18  /data/data/xxx/lib/libcocos2dcpp.so (cocos2d::Ref::retain()+20): Routine cocos2d::Ref::retain() at /${PROJECT_ROOT}/proj.android/../cocos2d/cocos/2d/../base/CCRef.cpp:64
Stack frame #01  pc 00275140  /data/data/xxx/lib/libcocos2dcpp.so (SplashScene::init()+192): Routine SplashScene::init() at /${PROJECT_ROOT}/proj.android/jni/../../Classes/Scene/SplashScene.cpp:38
```

無事バックトレースにソースコードの行番号が表示されました。

## ndk-stack
`ndk-stack` は、 `android NDK` についてくるツールの一つです。

使い方はおもに以下の2通りぐらいです。

### logcatから直接使う場合

```
$ adb logcat | ndk-stack -sym proj.android/obj/local/armeabi/
```

### 保存してあるlogcatを読み込む場合

```
$ ndk-stack -sym proj.android/obj/local/armeabi/ -dump logcat.log
```

### ポイント
カレントディレクトリはプロジェクトルート（proj.android）があるフォルダでないと、失敗すると思います。