[转载] Glibc移植到android调查小结
(2012-05-18 18:53:32)
标签:
杂谈 |
分类: android |
目的:调查Glibc如何最小修改使其可以在Android平台上使用。
应用场景:
Linux的现有应用程序或库需要移植到Android上,一般来说都要修改源码使其适合Android自己重新实现的C库Bionic。Bionic相对于Glib更简略,更高效,但是有些Glibc中有的库函数或者包装的syscall在bionic中没有实现,如果Linux原来的应用程序或者库使用到了这些bionic没有实现函数,那就要做相应修改才能让程序编译运行。
能想到的修改方法有三种:
1、
修改程序源程序,实现相应功能的函数或者寻找替代函数。
2、
修改bionic库添加相应函数或syscall。
3、
移植glibc到android上面,作为一个普通的动态链接库让程序调用,这也是本次调查的主题。
目前试验过的移植方法:
1、编译时候使用glibc静态库链接,静态链接可以直接跑起来。但是把所有的库或程序都静态链接不合适,可执行文件太大了。
2、将glibc单独函数包装成动态库,实验情况如下:
单独将printf(在glibc和bionic中都实现)包裹一层做成一个so,可以正常调用。
相关输出信息:
DEBUG: 252 Processing
'libhello.so' relocation at index 0
252 SEARCH printf in
libhello.so@0x80000000 077905a6 2
252 SEARCH printf in
libdl.so@0x00000000 077905a6 0
252 SEARCH printf in
./dlopentest-new@0x00000000 077905a6 2
252 SEARCH printf in
libc.so@0xafe00000 077905a6 152
252 FOUND printf in libc.so
(00014359) 44
<---在android自己的C库中找到了函数定义
252 printf
s->st_value = 0x00014359, si->base =
0xafe00000
252 RELO JMP_SLOT 80008360
<- afe14359 printf
DEBUG: [ 252 finished linking
libhello.so ]
252 SEARCH hello in
libhello.so@0x80000000 006ec32f 1
252 FOUND hello in libhello.so
(00000280) 60
单独将getline(在glibc实现了,bionic中没有实现)包裹一层做成一个so,调用错误。
相关输出信息:
DEBUG: 258 Processing
'libgetline.so' relocation at index 0
258 SEARCH getline in
libgetline.so@0x80000000 0dcb3025 1
258 SEARCH getline in
libdl.so@0x00000000 0dcb3025 0
258 SEARCH getline in
./getlinetest@0x00000000 0dcb3025 12
258 SEARCH getline in
libc.so@0xafe00000 0dcb3025 650
258 SEARCH getline in
libstdc++.so@0xafd00000 0dcb3025 0
258 SEARCH getline in
libm.so@0xafc00000 0dcb3025 101
/android_source/google_android_dount/bionic/linker/linker.c:1172| ERROR: 258 cannot locate
'getline'...
/android_source/google_android_dount/bionic/linker/linker.c:1698| ERROR: failed to link libgetline.so
在Android的C库中找不到这个函数的实现。
3、编译时使用glibc动态库,使用glibc库自己的dynamic loader---ld-linux.so
参见:http://groups.google.com/group/android-internals/browse_thread/thread/7c728a36474fbc05
方法就是在编译时指定dynamic loader为ld-linux.so,例如:
arm-none-linux-gnueabi-gcc -o hello.out hello.c -Wl,-dynamic-linker=/ system/lib/ld-linux.so.6
我试了一下,hello world可以跑,大型复杂程序不知道会如何,需要考虑效率,IPC方式等很多问题。
4、
编译时使用glibc动态库,使用bionic库自己的dynamic loader---linker
实验情况如下:
相关输出信息:
DEBUG: 256 Processing
'libc.so.6' relocation at index 1185
/android_source/google_android_dount/bionic/linker/linker.c:1288| ERROR: 256 unknown reloc type
19
@ 0x80014ee0 (1185)
/android_source/google_android_dount/bionic/linker/linker.c:1698| ERROR: failed to link libc.so.6
在进行Link的relocation时候发生错误,链接过程还没结束就出错,根本没有查找有没有printf这个函数可用。
查了一下reloc type 19的定义是:R_ARM_TLS_TPOFF32,是和线程本地存储相关的一个relocation。
从代码和网络查了一下,android目前对TLS支持十分有限,而且目前的实现也有问题。
参见:
http://groups.google.com/group/android-ndk/browse_thread/thread/4f60d0201464b7f4/8821e4d791e5be35?lnk=raot
http://groups.google.com.tw/group/0xlab-devel/browse_thread/thread/69239c9b773d3c59
http://elinux.org/Android_on_OMAP#TLS_issue
而且Linker(1.6的代码)中没有关于TLS的代码。
我想到的另外一个原因是linker/README.txt里写的:
线程本地数据相关的数据要链接到执行程序映像,会有分配内存的动作。
THE DYNAMIC LINKER CANNOT USE malloc()/free() !That's why it is linked to a special version of the C library that will abort when any of these functions (or calloc()/realloc()) is called.
所以单纯把libc.so.6和其相关的so拿到android上使用android自己的linker肯定是有问题的。
而且这还没有考虑到bionic中还有没有实现的linux syscall接口和即使TLS问题解决,还会有其他的底层问题出现。
试图重新编译Glibc去掉TLS特性,在glibc上的官方文档上的编译选项中有—without-tls,但是具体到ARM交叉编译的时候发现arm的ports库里面tls.h有如下语句:
#ifndef HAVE_TLS_SUPPORT
# error "TLS support is required."
#endif
导致编译错误。
目前调查如何修改bionic的linker使其适应libc.so。
应用场景:
Linux的现有应用程序或库需要移植到Android上,一般来说都要修改源码使其适合Android自己重新实现的C库Bionic。Bionic相对于Glib更简略,更高效,但是有些Glibc中有的库函数或者包装的syscall在bionic中没有实现,如果Linux原来的应用程序或者库使用到了这些bionic没有实现函数,那就要做相应修改才能让程序编译运行。
能想到的修改方法有三种:
1、
2、
3、
目前试验过的移植方法:
1、编译时候使用glibc静态库链接,静态链接可以直接跑起来。但是把所有的库或程序都静态链接不合适,可执行文件太大了。
2、将glibc单独函数包装成动态库,实验情况如下:
单独将printf(在glibc和bionic中都实现)包裹一层做成一个so,可以正常调用。
相关输出信息:
DEBUG:
DEBUG: [
单独将getline(在glibc实现了,bionic中没有实现)包裹一层做成一个so,调用错误。
相关输出信息:
DEBUG:
/android_source/google_android_dount/bionic/linker/linker.c:1172| ERROR:
/android_source/google_android_dount/bionic/linker/linker.c:1698| ERROR: failed to link libgetline.so
在Android的C库中找不到这个函数的实现。
3、编译时使用glibc动态库,使用glibc库自己的dynamic loader---ld-linux.so
参见:http://groups.google.com/group/android-internals/browse_thread/thread/7c728a36474fbc05
方法就是在编译时指定dynamic loader为ld-linux.so,例如:
arm-none-linux-gnueabi-gcc -o hello.out hello.c -Wl,-dynamic-linker=/ system/lib/ld-linux.so.6
我试了一下,hello world可以跑,大型复杂程序不知道会如何,需要考虑效率,IPC方式等很多问题。
4、
实验情况如下:
相关输出信息:
DEBUG:
/android_source/google_android_dount/bionic/linker/linker.c:1288| ERROR:
@ 0x80014ee0 (1185)
/android_source/google_android_dount/bionic/linker/linker.c:1698| ERROR: failed to link libc.so.6
在进行Link的relocation时候发生错误,链接过程还没结束就出错,根本没有查找有没有printf这个函数可用。
查了一下reloc type 19的定义是:R_ARM_TLS_TPOFF32,是和线程本地存储相关的一个relocation。
从代码和网络查了一下,android目前对TLS支持十分有限,而且目前的实现也有问题。
参见:
http://groups.google.com/group/android-ndk/browse_thread/thread/4f60d0201464b7f4/8821e4d791e5be35?lnk=raot
http://groups.google.com.tw/group/0xlab-devel/browse_thread/thread/69239c9b773d3c59
http://elinux.org/Android_on_OMAP#TLS_issue
而且Linker(1.6的代码)中没有关于TLS的代码。
我想到的另外一个原因是linker/README.txt里写的:
线程本地数据相关的数据要链接到执行程序映像,会有分配内存的动作。
THE DYNAMIC LINKER CANNOT USE malloc()/free() !That's why it is linked to a special version of the C library that will abort when any of these functions (or calloc()/realloc()) is called.
所以单纯把libc.so.6和其相关的so拿到android上使用android自己的linker肯定是有问题的。
而且这还没有考虑到bionic中还有没有实现的linux syscall接口和即使TLS问题解决,还会有其他的底层问题出现。
试图重新编译Glibc去掉TLS特性,在glibc上的官方文档上的编译选项中有—without-tls,但是具体到ARM交叉编译的时候发现arm的ports库里面tls.h有如下语句:
#ifndef HAVE_TLS_SUPPORT
# error "TLS support is required."
#endif
导致编译错误。
目前调查如何修改bionic的linker使其适应libc.so。
后一篇:android 交叉编译器