转:
-fvisibility=default|internal|hidden|protected
-fvisibility=[default|internal|hidden|protected]
Set the default ELF image symbol visibility to the specified option---all symbols are marked with this unless overridden within the code. Using this
feature can very substantially improve linking and load times of shared object libraries, produce more optimized code, provide near-perfect API export
and prevent symbol clashes. It is strongly recommended that you use this in any shared objects you distribute.
Despite the nomenclature, default always means public; i.e., available to be linked against from outside the shared object. protected and internal are
pretty useless in real-world usage so the only other commonly used option is hidden. The default if -fvisibility isn't specified is default, i.e., make
every symbol public.
A good explanation of the benefits offered by ensuring ELF symbols have the correct visibility is given by "How To Write Shared Libraries" by Ulrich
Drepper (which can be found at <http://www.akkadia.org/drepper/>)---however a superior solution made possible by this option to marking things hidden
when the default is public is to make the default hidden and mark things public.
gcc的visibility是说,如果编译的时候用了这个属性,那么动态库的符号都是visibility指定的属性,除非强制声明。
1.创建一个c源文件,内容简单
#include<stdio.h>
#include<stdlib.h>
__attribute ((visibility("default"))) void not_hidden ()
{
printf("exported symbol\n");
}
void is_hidden ()
{
printf("hidden one\n");
}
想要做的是,第一个函数符号可以被导出,第二个被隐藏。
先编译成一个动态库,使用到属性-fvisibility
gcc -shared -o libvis.so -fvisibility=hidden vis.c
现在查看
# readelf -s libvis.so |grep hidden
48: 00000420 20 FUNC LOCAL HIDDEN 11 is_hidden
51: 0000040c 20 FUNC GLOBAL DEFAULT 11 not_hidden
可以看到,属性确实有作用了。
现在试图link
vi main.c
int main()
{
not_hidden();
is_hidden();
return 0;
}
试图编译成一个可执行文件,链接到刚才生成的动态库,
gcc -o exe main.c -L ./ -lvis
结果提示:
/tmp/cckYTHcl.o: In function `main':
main.c:(.text+0x17): undefined reference to `is_hidden'
说明了hidden确实起到作用了。
自己实测参数情况
//__attribute__ ((visibility ("internal"))) 调用地方会被优化成内嵌汇编,没有函数
//__attribute__ ((visibility ("hidden"))) 调用地方会被优化成内嵌汇编,没有函数
//__attribute__ ((visibility ("protected"))) 调用地方会被优化成内嵌汇编,有函数,使用dlsym可以找到
//14: 00005491 36 FUNC GLOBAL PROTECTED 12 add
//__attribute__ ((visibility ("default"))) 调用地方会被优化成内嵌汇编,有函数,使用dlsym可以找到
// 14: 00005461 36 FUNC GLOBAL DEFAULT 12 add
void JNICALL analyzor(void)
{
CLog::setHookedProcessName("HookModule");
add(3);
}
void add(int a)
{
CLog::logInfo("add");
a = a+ 1;
CLog::logInfo("add %d",a);
}