AnSwErYWJ's Blog

屏蔽静态库接口

字数统计: 350阅读时长: 8 min
2019/04/13

分享屏蔽静态库接口的一种方法.

准备

hello.c:

1
2
3
4
5
#include <stdio.h>

__attribute__ ((visibility ("default"))) void hello() {
printf("Hello World!\n");
}

hello.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef __HELLO__H
#define __HELLO__H

#ifdef __cplusplus
extern "C" {
#endif

void hello();

#ifdef __cplusplus
}
#endif

#endif

bye.c:

1
2
3
4
5
#include <stdio.h>

void bye() {
printf("Bye Bye!\n");
}

bye.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef __BYE__H
#define __BYE__H

#ifdef __cplusplus
extern "C" {
#endif

void bye();

#ifdef __cplusplus
}
#endif

#endif

编译

编译时使用-fvisibility=hidden,可以默认将符号隐藏;需要对外的符号使用__attribute__ ((visibility ("default")))修饰即可:

1
2
$ gcc -fvisibility=hidden -I. -c hello.c -o hello.o
$ gcc -fvisibility=hidden -I. -c bye.c -o bye.o

其中hello()未被隐藏,bye()是被隐藏的.

链接

将生成的两个.o文件重定位到libt.o中:

1
$ ld -r hello.o bye.o -o libt.o

去除无用的符号

1
$ strip --strip-unneeded libt.o

隐藏的符号本地化(我也不知道中文怎么翻译了)

1
$ objcopy --localize-hidden libt.o libt_hidden.o

打包成静态库

1
$ ar crv libt.a libt_hidden.o

验证

调用未被隐藏的hello()

test1.c:

1
2
3
4
5
6
#include "hello.h"

int main(void) {
hello();
return 0;
}

编译并运行

1
2
3
$ gcc -I. test1.c -L. -lt -o test
$ ./test
Hello World!

调用隐藏的bye()

test2.c

1
2
3
4
5
6
#include "bye.h"

int main(void) {
bye();
return 0;
}

编译并运行

1
2
3
4
5
$ gcc -I. test2.c -L. -lt -o test
$ ./test
/tmp/ccdaJT7s.o: In function `main':
test2.c:(.text+0xa): undefined reference to `bye'
collect2: error: ld returned 1 exit status

原文作者:AnSwErYWJ

原文链接:https://answerywj.com/2019/04/13/hide-symbol-of-static-library/

发表日期:2019/04/13 14:04

版权声明:本文采用Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License进行许可.
Creative Commons License

CATALOG
  1. 1. 准备
  2. 2. 编译
  3. 3. 链接
  4. 4. 去除无用的符号
  5. 5. 隐藏的符号本地化(我也不知道中文怎么翻译了)
  6. 6. 打包成静态库
  7. 7. 验证
    1. 7.1. 调用未被隐藏的hello()
    2. 7.2. 调用隐藏的bye()