Version Script
Table of Contents
1. Version Script
1.1. 声明 global, local 符号
与 gcc 的 visibility attribute 功能类似
$> cat v.map
{
global:
foo;
local:
*;
};
$> cat test.c
void foo() {}
void bar() {}
$> gcc -shared test.c -Wl,--version-script,vb.map
$> readelf -a ./a.out
Symbol table '.dynsym' contains 6 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
...
5: 000000000000050a 7 FUNC GLOBAL DEFAULT 11 foo
1.2. 定义符号的 version
$> cat v.map
LIBTEST_V1.0 {
global:
foo;
local:
*;
};
LIBTEST_V1.1 {
global:
bar;
local:
*;
};
$> cat test.c
void foo() {
printf("foo from LIBTEST_V1.0\n");
}
void bar() {
printf("bar from libTEST_V1.1\n");
}
$> cat main.c
extern void foo();
extern void bar();
int main(int argc, char *argv[]) {
foo();
bar();
}
$> gcc -shared test.c -Wl,--version-script,v.map -o libtest.so
$> gcc main.c ./libtest.so
$> readelf -a ./a.out
Symbol table '.dynsym' contains 9 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
...
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND bar@LIBTEST_V1.1 (2)
...
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND foo@LIBTEST_V1.0 (4)
...
1.3. .symver directive
除了使用 version script, gcc 允许使用 .symver directive 在代码中指定 version
$> cat v.map
LIBTEST_V1.0 {
};
LIBTEST_V1.1 {
};
$> cat test.c
__asm__ (".symver foo, foo@LIBTEST_V1.0");
void foo() {
printf("foo from LIBTEST_V1.0\n");
}
__asm__ (".symver bar, bar@LIBTEST_V1.1");
void bar() {
printf("bar from libTEST_V1.1\n");
}
$> cat main.c
__asm__(".symver foo, foo@LIBTEST_V1.0");
__asm__(".symver bar, bar@LIBTEST_V1.1");
extern void foo();
extern void bar();
int main(int argc, char *argv[]) {
foo();
bar();
}
$> gcc -shared test.c -o libtest.so
$> gcc main.c ./libtest.so
$> readelf -a ./a.out
Symbol table '.dynsym' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
...
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND bar@LIBTEST_V1.1 (3)
...
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND foo@LIBTEST_V1.0 (4)
...
1.3.1. 使用 .symver directive 实现同一个函数的多个版本
$> cat v.map
LIBTEST_V1.0 {
};
LIBTEST_V1.1 {
};
$> cat test.c
__asm__ (".symver foo1, foo@LIBTEST_V1.0");
void foo1() {
printf("foo from LIBTEST_V1.0\n");
}
__asm__ (".symver foo2, foo@LIBTEST_V1.1");
void foo2() {
printf("foo from libTEST_V1.1\n");
}
$> cat main.c
__asm__(".symver foo, foo@LIBTEST_V1.0");
extern void foo();
int main(int argc, char *argv[]) {
foo();
}
$> ./a.out
foo from LIBTEST_V1.0
$> cat main.c
__asm__(".symver foo, foo@LIBTEST_V1.1");
extern void foo();
int main(int argc, char *argv[]) {
foo();
}
$> ./a.out
foo from libTEST_V1.1
$> readelf -a libtest.so
Symbol table '.dynsym' contains 17 entries:
Num: Value Size Type Bind Vis Ndx Name
...
6: 000000000000073d 19 FUNC GLOBAL DEFAULT 13 foo@LIBTEST_V1.1
...
9: 000000000000072a 19 FUNC GLOBAL DEFAULT 13 foo@LIBTEST_V1.0
...
Backlinks
GCC Attribute (GCC Attribute > visibility): 通过 Version Script, 也可以控制符号的 visibility. 另外, linkage 也会影响符号的 visibility, 例如 inline, static 等关键字
