参考代码:(文件内容见最下面)
~/mydroid/android-1.6_r2/development/self/HelloWorld/Android.mk
~/mydroid/android-1.6_r2/development/self/HelloWorld/HelloWorld.c
~/mydroid/android-1.6_r2/development/self/libtest/Android.mk
~/mydroid/android-1.6_r2/development/self/libtest/libtest.h
~/mydroid/android-1.6_r2/development/self/libtest/libtest.c
使用的平台:
系统平台:ubuntu10.4 LTS
源代码版本:Android 1.6r2
Emulator平台:Android 1.6(SDK是Android2.2,这个版本没大关系了)
注:编译Android略过,编译目标是默认的generic release版,若需要调试dalvikvm等系统自带程序,最好编译debug版本。
(以下默认shell都已执行过 $ source build/envsetup.sh)
更改debug版的命令是:
(选择device debug generic eng)
(小提示:执行“lunch 2”命令,可以将Android编译目标更改为编译主机程序,编译的dalvikvm可以直接在ubuntu下运行,某种情况下还是很有用的)
0. 准备工作
启动模拟器
在Android源代码根目录执行
1. 使用没有被strip版本的执行文件HelloWorld和libtest.so
在Android源代码根目录下依次执行
$ make HelloWorld
没有被strip的版本所在位置是
~/mydroid/android-1.6_r2/out/target/product/generic/symbols/system/bin/HelloWorld
~/mydroid/android-1.6_r2/out/target/product/generic/symbols/system/lib/libtest.so
将HelloWorld push到/data/bin/目录下,将libtest.so push到/system/lib/目录下
$ adb remount
$ adb push ~/ mydroid/ android-1.6 _r2/ out/ target/ product/ generic/ symbols/ system/ lib/ libtest.so / system/ lib/
2. 启动gdbserver
Android1.6模拟器中自带gdbserver程序,在Android模拟器中执行如下命令:
正常的话结果应该是:(不正常的话就自己查吧)
Listening on port 1234
不要忘记上面的pid,忘记了就ps呗
3. 启动arm-eabi-gdb进行调试连接
3.1 首先设置模拟器端口转发:
3.2 启动arm-eabi-gdb: (android源代码prebuild目录下有相应文件,有多个版本,没查有什么区别,我用的是4.4)
(2010/08/05+: 用arm-eabi-gdbtui调试也可,只是上下左右方向键是用来控制源代码显示的。另外, 有些程序不需要第5步就可以调试动态链接库,目前不知道为什么,但要在gdb中调用set solib相关的两个命令(参照3.3节),并且是绝对路经,其实之前用相对路径没有效果。进入动态链接库调试时可以使用n,尽管显示代码位置会到处乱跳,但在关键函数处倒也正确。)
$ ~/ mydroid/ android-1.6 _r2/ prebuilt/ linux-x86/ toolchain/ arm-eabi-4.4.0/ bin/ arm-eabi-gdb ~/ mydroid/ android-1.6 _r2/ out/ target/ product/ generic/ symbols/ system/ bin/ HelloWorld
启动后会显示:
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-elf-linux"...
3.3 首先执行set solib-×××的两个命令: (可选,只调试HelloWorld及其动态库的话不执行也无碍,最好是绝对路径,用自动扩展的写法可能不行)
( gdb ) set solib-search-path / home/ j/ mydroid/ android-1.6 _r2/ out/ target/ product/ generic/ symbols/ system/ lib/
3.4 连接gdbserver调试:
成功的话会显示:
35 mov r0, sp
Current language: auto; currently asm
如果没执行set solib-×××的两个命令会显示如下信息,但没关系
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
0xb0000100 in ?? ()
4. 进行gdb调试
首先执行两个命令:
( gdb ) c
这是调试会停在HelloWorld.c的main函数处,提示信息如下:
Error while mapping shared library sections:
libc.so: No such file or directory.
Error while mapping shared library sections:
libstdc++.so: No such file or directory.
Error while mapping shared library sections:
libm.so: No such file or directory.
Error while mapping shared library sections:
libtest.so: No such file or directory.
Breakpoint 1, main ()
at /home/j/mydroid/android-1.6_r2/development/self/HelloWorld/HelloWorld.c:6
6 printf("main 1");
Current language: auto; currently c
最后几行表示调试正常,如果你编的debug版的Android,前几行会显示加载动态库成功,但也不能直接进入动态链接库进行调试的:)至少我这里不能。
(2010/08/05+:这个时候可以通过info share来判断。执行info share命令会显示当前动态链接库加载的内存地址,若显示的地址与第5节获得的地址相同,则说明可以调试动态链接库,并且应该可以用n命令,若不同,则请尝试第5节的办法。)
这时你可以通过基本的gdb调试命令进行调试:
( gdb ) b 10 (在第10 行设断点)
( gdb ) list (显示源代码信息)
( gdb ) c (继续至下一断点或结束)
(注:其实我不了解gdb调试,还是google一下比较好)
若你在func()处执行s命令进入func()函数体,就会提示错误,也无法进行正常调试了,如何调,请继续下一节—
5. 加载动态库so文件进行调试
这部分的工作参考 gdbserver调试共享库 这篇文章就可以了,不过我还是重复一下Android平台的步骤:
5.1 查看动态链接库加载的内存地址
结果中会有如下几行:
40000000-40008000 r-xs 00000000 00:07 186 /dev/ashmem/system_properties (deleted)
80000000-80001000 r-xp 00000000 1f:00 713 /system/lib/libtest.so
80001000-80002000 rwxp 00001000 1f:00 713 /system/lib/libtest.so
afc00000-afc21000 r-xp 00000000 1f:00 478 /system/lib/libm.so
记录下80000000这个地址。
5.2 查看动态链接库libtest.so中text段的偏移地 址
$ ./ prebuilt/ linux-x86/ toolchain/ arm-eabi-4.4.0/ bin/ arm-eabi-objdump -h ~/ mydroid/ android-1.6 _r2/ out/ target/ product/ generic/ symbols/ system/ lib/ libtest.so | grep .text