当然,最原始的方法是把你的程序编成静态的,即编译时加参数-static即可。但这不符合我们一般的习惯,也是我无法容忍的。
方法还是有的:
1、compile
arm-unknown-linux-gnueabi-gcc -o hello hello.c -Wl,-dynamic-linker=/data/app/ld-linux.so.3
这样,编出来的hello就会使用/data/app/ld-linux.so.3当作动态库加载器
qj@king:~/test$ readelf -a hello|grep ld-linux
[Requesting program interpreter: /data/app/ld-linux.so.3]
2、run, 由于Android上并没有所以需要我们自己拷贝ld-linux.so.3上去。
copy ld-linux.so.3 to /data/app
copy libc.so.6 to /data/app
修改LD_LIBRARY_PATH以把我们的程序所依赖的其它动态库加入搜索路径,在adb shell下执行:
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/app
注意,在android下只有data目录是可写的,其它目录都是只读的,所以只能用data目录了。
more info:
-Wl,option
Pass option as an option to the linker. If option contains commas, it is split into
multiple options at the commas. You can use this syntax to pass an argument
to the option. For example, ‘-Wl,-Map,output.map’ passes ‘-Map output.map’
to the linker. When using the GNU linker, you can also get the same effect
with ‘-Wl,-Map=output.map’.
即-dynamic-linker 传递给了linker。注意,上面介绍的两种写法,一种是等号传递;另一种是逗号传递。效果是一样的。
下面是对连接器ld中参数--dynamic-linker的解释:
#ld --help
-I PROGRAM, --dynamic-linker PROGRAM
Set PROGRAM as the dynamic linker to use
ld-linux.so.3、libc.so.6等是从toolchains下面拷来的。
实际上ld-linux.so.3是指向ld-2.9.so的链接,所以实际上需要把ld-2.9.so拷贝到/data/app目录下,然后做一个链接:
ln -s ld-2.9.so ld-linux.so.3
虽然ld-2.9.so看上去是个动态库,但实际上它是可执行的。加载它会被执行,所以需要给它增加可执行权限,否则执行时会提示说not found 之类的,总之android shell下的这个提示很难让人理解:
chmod 777 ld-2.9.so
chmod 777 ld-linux.so.3
如果你的代码是C++写的,编译需要使用arm-...linux...-g++,而且运行时还需要把libstdc++.so.6拷贝到/data/app目录下去。
另外,还有一个关键点:
一定要把/data/app加入到LD_LIBRARY_PATH环境变量中。
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/app
以上步骤完成后,基本可以保证能成功运行,已经经过了我的多次验证。
参考资料:https://groups.google.com/forum/?fromgroups=#!topic/android-internals/fHKKNkdPvAU