隐藏动态库so中的符号(函数名)
正常的lib库生成
1.c
int func1()
{
return 1;
}
2.c
extern int func1(void);
int func2()
{
return func1();
}
编译成动态库 libfunc.so
:
gcc -shared -fPIC -o libfunc.so 1.c 2.c
查看符号:
$nm libfunc.so | grep func
00000000000006c8 T func1
00000000000006d4 T func2
因为我们的 func1 和 func2都没有定义成static,所以都是global类型的函数。
隐藏函数
通过1.c
和2.c
我们可以看到,func1()
的函数的存在,实际是为了被func2()
调用,但是由于可能是两个模块,所以被分在了2个文件编译。该so作为开源的库,func1()
的实现不适合迭代更新,不能让用户使用func1()
,我们如何隐藏func1()
呢?
方法1
使用 __attribute__((visibility ("hidden")))
__attribute__((visibility ("hidden"))) int func1()
{
return 1;
}
然后重新编译成动态库
$nm libfunc.so | grep func 0000000000000678 t func1 0000000000000684 T func2
发现符号还在,但是通过readelf
发现 是 LOCAL
类型的函数
$readelf -s libfunc.so | grep fun
39: 0000000000000678 11 FUNC LOCAL DEFAULT 11 func1
48: 0000000000000684 11 FUNC GLOBAL DEFAULT 11 func2
这意味着, func1 不能被 引用 libfunc.so
的程序调用。
方法2
使用--version-script=
func.map:
{
local:
func1;
};
编译动态库:
gcc -shared -fPIC -o libfunc.so 1.c 2.c -Wl,--version-script=./func.map
此时,我们使用readelf查看:
func1
也是 LOCAL
类型的,和 func.map
设置的一致。
$readelf -s ./libfunc.so | grep func
39: 0000000000000678 11 FUNC LOCAL DEFAULT 11 func1
48: 0000000000000684 11 FUNC GLOBAL DEFAULT 11 func2
当然,可以通过通配符来描述 map 文件:
{
global: func2;
local: *;
};
通配符的配置必须在最后。