berber 2011-02-18
Android Source中默认的Dalvik编译目标是ARM平台,只能在模拟机或者真机上运行,不过如果想研究它我觉得还是在x86下方便点.
1、如果使用Ubunut的话,把gcc版本换成4.3的。
gcc -v可以查看当前版本。
sudo apt-get install gcc-4.3 g++-4.3
sudo ln -s /usr/bin/gcc-4.3 /usr/bin/gcc
sudo ln -s /usr/bin/g++-4.3 /usr/bin/g++
默认的4.4 compile时要求更严格,会出现error: invalid conversion from
‘const char*’ to ‘char*’的提示。
2、在源代码跟目录下,运行:
. build/envsetup.sh
lunch 2
这主要设置编译的目标平台。
注:
默认的平台信息如下:
PLATFORM_VERSION_CODENAME=AOSP
PLATFORM_VERSION=AOSP
TARGET_PRODUCT=generic
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=OPENMASTER
选用上述平台后的信息如下:
PLATFORM_VERSION_CODENAME=AOSP
PLATFORM_VERSION=AOSP
TARGET_PRODUCT=sim
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=true
TARGET_BUILD_TYPE=debug
TARGET_BUILD_APPS=
TARGET_ARCH=x86
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=OPENMASTER
具体需要什么平台可以根据envsetup.sh文件内容进行选择。我这边是x86.
3、编译相对应的模块:
make dalvikvm core ext dexopt framework android.policy services
dalvikvm后面的几个模块是VM本身需要的一些library,比如ext.jar。如果make所有模块也可以,不过耗时就长多了,而且出现编译错误的可能性就大多了。如果只是为了研究dalvik的移植或者调试,上述模块基本够了。需要注意的是,在我参考的一篇文章中没有dexopt项,在运行时会出现该错误“E/dalvikvm(1540):execv 'mnt/hd/Android/out/debug/host/linux-x86/pr/sim/system/bin/dexopt' failed: No such file or directory”,dexopt是对dex文件进行优化的一个模块,一定需要生成。
生成的文件在源码目录下的out文件夹内。可用find . -name dalvikvm查找dalvikvm文件
4、测试hello程序:
hello.java代码:
public class hello{
public static void main(String args[])
{
System.out.println("hello world");
}
}
注意:我是将hello.java和makefile文件放在了Android源码的根目录下,且我的源码是挂载在第二硬盘的下/mnt/hd/Android,因此得
到:ANDROID_SRC_DIR := /mnt/hd/Android,只需对文件目录相应改变即可。又因为Android目录下已有一个Makefile,因此避免冲突
将hello程序的makefile命名为HelloMakefile。
HelloMakefile:
ANDROID_SRC_DIR := /mnt/hd/Android
android_dir_dx = $(ANDROID_SRC_DIR)/out/host/linux-x86/bin/dx
all:
javac hello.java
$(android_dir_dx) --dex --output=hello.jar hello.class
clean:
@rm *.jar *.class
完成上述步骤后,会生成hello.jar、hello.class
Android目录下所有文件如下图所示:
5、如果直接运行/mnt/hd/Android/out/debug/host/linux-x86/pr/sim/system/bin/dalvikvm -cp hello.jar hello则会出现以下错误:
E/dalvikvm( 4668): ERROR: must specify non-'.' bootclasspath
W/dalvikvm( 4668): JNI_CreateJavaVM failed
Dalvik VM init failed (check log file)
原因是虚拟机运行的一些相关文件没有加载。因此需要一个脚本文件,命名为
rund.sh:
#!/bin/sh
base=`pwd`
# configure root dir of interesting stuff
root=$base/out/debug/host/linux-x86/pr/sim/system
export ANDROID_ROOT=$root
# configure bootclasspath
bootpath=$root/framework
export BOOTCLASSPATH=$bootpath/core.jar:$bootpath/ext.jar:$bootpath/framework.jar:$bootpath/android.policy.jar:$bootpath/services.jar
# this is where we create the dalvik-cache directory; make sure it exists
export ANDROID_DATA=/tmp/dalvik_$USER
mkdir -p $ANDROID_DATA/dalvik-cache
exec gdb $root/bin/dalvikvm
而后输入以下命令即可运行gdb程序,调试dalvik的运行了:
./rund.sh
然后在gdb调试下输入运行参数:
set args -cp hello.jar hello
设置断点
b main
以下就可以单步调试dalvik了。
以下是我的运行结果:
zhutou@zhutou-desktop:/mnt/hd/Android$ ./rund.sh
GNU gdb (GDB) 7.1-Ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /mnt/hd/Android/out/debug/host/linux-x86/pr/sim/system/bin/dalvikvm...done.
(gdb) set args -cp hello.jar hello
(gdb) b main
Breakpoint 1 at 0x8048822: file dalvik/dalvikvm/Main.c, line 142.
(gdb) r
Starting program: /mnt/hd/Android/out/debug/host/linux-x86/pr/sim/system/bin/dalvikvm -cp hello.jar hello
[Thread debugging using libthread_db enabled]
Breakpoint 1, main (argc=4, argv=0xbfffebd4) at dalvik/dalvikvm/Main.c:142
142 {
(gdb) c
Continuing.
[New Thread 0x1439b70 (LWP 4698)]
[New Thread 0x1c3ab70 (LWP 4699)]
Hello World!
[Thread 0x1439b70 (LWP 4698) exited]
[Thread 0x1c3ab70 (LWP 4699) exited]
Program exited normally.