加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

[转载] 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。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有