Eclipse配合NDK写so文件不错, 但是调试是个麻烦事, 老是报错. 一会这样一会那样. 目前可能用NDK写so并且调试的毕竟还是太少啊. 调试体验非常差, 所以如果在有源码的情况下, 我一般还是用VisualGDB这个软件来写so文件, 这个软件的调试体验比Eclipse好多了. 而且是用Visual Studio来写, 更习惯些.

在没有源码的情况下, 一般就是使用ida 来进行调试, ida的6.6已经可以支持调试apk了, 不过现在我手上还没有拿到. 目前只能用网上泄露的6.5, ida 6.5调试android 的so文件已经是非常好的体验了. 使用6.1的时候老是有莫名其妙的错误. 其实调试so文件也分成两种情况, 一种是apk运行起来以后慢慢才会调用so文件中的函数, 比如按钮单击什么的. 一种是在程序初始化的时候就调用so文件. 这种麻烦一些.

第一种情况讨论也比较多. 这边就简单说, 不展开:

首先复制ida目录下的android_server上传到android机器上. 既然是调试, 那么给个root权限应该也不过份.

1
2
3
4
5
6
7
adb push android data/local/tmp
adb shell
su
cd data/local/tmp
chown 0.0 *
chmod 777 *
./android_server

然后做一下转发

adb forward tcp:23946 tcp:23946

启动ida pro,选择调试器remote android debugger,设置网络127.0.0.1端口23946在debugger菜单选attach 然后在Modules窗口找到要调试的so. 点击进去就可以看到导出函数, 下上断点, 然后触发断点就可以了. 这种方式, so的断点时机无所谓, 那么调试起来还是比较简单的, 网上教程也不少. easy.

第二种是讨论的就相对少一些, 需要在apk启动的时候就断下来. 这边总结下.  android ndk 的samples目录下, 有一个项目叫hello-jni, 对我们就用这个, hello-jni在onCreate的地方就调用了stringFromJNI()如果用上面那种方法, 那么断下来的时候stringFromJNI()已经调用完了. 所以不能这样. 得这样, 首先使用am start -D -n 包名/类名  以开启调试的方式启动apk. 这样启动的程序会等待调试器连接上来. 当然这时候别自作聪明的开着android eclipse. 开着的话会一闪而过. 要是固定下面这个画面, 说明就成功了!

am start -D -n com.example.hellojni/com.example.hellojni.HelloJni

20140903181858

 

然后开启IDA远程调试搞上,  IDA pro attach 要调试的进程, 然后Debugger Options 设置新线程,加载so时断点,然后F9运行程序

20140903182648

这时候程序还是处于Waiting For Debugger状态.  我们开启Android Eclipse

20140903185805

 

在Devices窗口看到我们的hellojni的端口是8700. 其实一般都是8700了, 开不开Android Eclipse都可以. 然后使用这条命令, 端口就是上面的8700.

jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700

20140903185805

 

这时候ida里面就有反应了. 加载libhello-jin.so这时候我们切换到so文件. 在Java_com_example_hellojni_HelloJni_stringFromJNI上下断点, 然后ida F9. 成功断下. 终于能够调试了, 舒服多了.

20140903185805