Android ELF文件编译之符号隐藏

编译系统是一套非常强大的系统,有众多的编译参数,但是大部分人只听过很少几个,希望以后能有时间好好看一下相关的资料研究清楚。

今天来介绍Android下面NDK编译so时,怎样实现符号隐藏,gcc默认的情况下是将所有符号都导出的,为了安全启见可以将符号隐藏,可以给破解带来很大的麻烦,另外还可以有效减小so文件的大小,还有一个好处是可以加快程序的运行速度。

隐藏符号基本有几种方式:一种是在函数定义时添加visibility属性(__attribute__((visibility("hidden");一种是在Android.mk中添加-fvisibility=hidden编译选项;另外一种是添加--version-script选项,并编译version script脚本。

前两种就不说了,添加以后编译用readelf查看就可以发现符号表里已经没有你定义的函数了。


咱们主要说第三种--version-script选项,version script是用户编写的可以直接被编译到ld链接脚本中的脚本文件,看着有点绕,说白了就是链接器在链接的时候会把你编写的version script脚本加入到链接脚本中,链接器就会执行version script中的命令,来实现一些功能。

链接器最主要的功能就是实现符号到地址的链接,在这个过程中链接器会定义一个树状结构,其中每个节点(version node)根据version script中定义的符号的名字和相互依赖来组成,version script可以指定某个符号被绑定到某个节点(version node)上,这样的话就可以把一些符号设定为local区域,那么这些符号就可以对so外部隐藏。

version script的格式如下:

VER1 {
	 global:
		 foo1;
	 local:
		 old*; 
		 original*; 
		 new*; 
};
其中VER1是脚本中类似函数的东西,也可以叫做标签,可以定义多个标签类似VER2、VER3等等,编译后的so中它们用来区分不同的符号,即把某些符号绑定到这个标签上。

global定义的是对外可见的符号。

local是仅对内可见的符号。

*和?是通配符分别表示匹配多个和一个字符。

这样就可以通过version script脚本来定义符号的可见性,还没有了解透彻,先写这么多吧。


参考链接:

1.http://man7.org/conf/lca2006/shared_libraries/slide18c.html

2.http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_25.html

3.http://www.gnu.org/software/gnulib/manual/html_node/LD-Version-Scripts.html

发布了60 篇原创文章 · 获赞 44 · 访问量 34万+

猜你喜欢

转载自blog.csdn.net/beyond702/article/details/56281068