Bar*_*der 5 c symbols binutils .a .so
我正在构建一个共享 (.so) 库,该库由多个 .a 文件和调用它们的瘦 API 层组成。我只希望我的 API 和外部依赖项可见,因此我使用 GCC 提供的“隐藏”可见性构建代码 ( -fvisibility=hidden)。
然而,其中一个库是专有的第三方 .a 文件(我们已付费使用),我只能访问其二进制文件。当我将其静态链接到我的 .so 文件中时,它的符号在我的 .so 的动态符号表中可见。我猜测这是因为该库不是使用隐藏的可见性选项构建的。我宁愿将这些功能隐藏起来,因为它们管理我们软件的敏感部分,并且我不希望第三方链接到这些符号。
有什么方法可以在事后将这些符号标记为“隐藏”,以便它们不会出现在我的 .so 文件的符号列表中?我已经看过了objdump,objcopy但我很难理解这些术语。
我尝试过的其他事情:
Mik*_*han 10
这是如何解决您的问题的一个有效示例。
这是您无法重新编译的专有静态库的源代码:
$ cat tpa.c
int tpa(void)
{
return 2;
}
$ cat tpb.c
int tpb(void)
{
return 3;
}
Run Code Online (Sandbox Code Playgroud)
库libtp.a基本上必须是这样构建的1:
$ gcc -fPIC -c -O1 tpa.c tpb.c
$ ar rcs libtp.a tpa.o tpb.o
Run Code Online (Sandbox Code Playgroud)
tpa.o和的符号表tpb.o是:-
$ readelf -s libtp.a
File: libtp.a(tpa.o)
Symbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS tpa.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 2
4: 0000000000000000 0 SECTION LOCAL DEFAULT 3
5: 0000000000000000 0 SECTION LOCAL DEFAULT 5
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 7
8: 0000000000000000 0 SECTION LOCAL DEFAULT 4
9: 0000000000000000 10 FUNC GLOBAL DEFAULT 1 tpa
File: libtp.a(tpb.o)
Symbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS tpb.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 2
4: 0000000000000000 0 SECTION LOCAL DEFAULT 3
5: 0000000000000000 0 SECTION LOCAL DEFAULT 5
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 7
8: 0000000000000000 0 SECTION LOCAL DEFAULT 4
9: 0000000000000000 10 FUNC GLOBAL DEFAULT 1 tpb
Run Code Online (Sandbox Code Playgroud)
您可以看到两个功能符号tpa和tpb都是GLOBAL
( = 可用于链接)并且具有DEFAULT动态可见性,而不是HIDDEN。
现在这是您自己的静态库的源代码,libus.a
$ cat usa.c
int usa(void)
{
return 5;
}
$ cat usb.c
int usb(void)
{
return 7;
}
Run Code Online (Sandbox Code Playgroud)
你像这样构建:
$ gcc -fPIC -c -O1 -fvisibility=hidden usa.c usb.c
$ ar rcs libus.a usa.o usb.o
Run Code Online (Sandbox Code Playgroud)
中的功能符号libus.a也是,GLOBAL但它们的动态可见性是HIDDEN:-
$ readelf -s libus.a
File: libus.a(usa.o)
Symbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS usa.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 2
4: 0000000000000000 0 SECTION LOCAL DEFAULT 3
5: 0000000000000000 0 SECTION LOCAL DEFAULT 5
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 7
8: 0000000000000000 0 SECTION LOCAL DEFAULT 4
9: 0000000000000000 10 FUNC GLOBAL HIDDEN 1 usa
File: libus.a(usb.o)
Symbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS usb.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 2
4: 0000000000000000 0 SECTION LOCAL DEFAULT 3
5: 0000000000000000 0 SECTION LOCAL DEFAULT 5
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 7
8: 0000000000000000 0 SECTION LOCAL DEFAULT 4
9: 0000000000000000 10 FUNC GLOBAL HIDDEN 1 usb
Run Code Online (Sandbox Code Playgroud)
这是共享库的源代码:
$ cat usc.c
extern int tpa(void);
extern int tpb(void);
extern int usa(void);
extern int usb(void);
int usc(void)
{
return tpa() * tpb() * usa() * usb();
}
Run Code Online (Sandbox Code Playgroud)
你编译的:-
$ gcc -fPIC -c -O1 usc.c
Run Code Online (Sandbox Code Playgroud)
现在您要链接usc.o,libtp.a并libus.a在您的共享库中libsus.so。如果您按照普通方式进行操作:
$ gcc -shared -o libsus.so usc.o -L. -ltp -lus
Run Code Online (Sandbox Code Playgroud)
然后你会发现:
$ readelf --dyn-syms libsus.so
Symbol table '.dynsym' contains 8 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __cxa_finalize
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
5: 0000000000001139 38 FUNC GLOBAL DEFAULT 12 usc
6: 000000000000115f 10 FUNC GLOBAL DEFAULT 12 tpa
7: 0000000000001169 10 FUNC GLOBAL DEFAULT 12 tpb
Run Code Online (Sandbox Code Playgroud)
动态符号表中不存在来自的可见性符号,但包含HIDDEN来自的可见性符号,这是您不想要的。libus.aDEFAULTlibtp.a
要排除后者,请按如下方式链接您的共享库:
$ gcc -shared -o libsus.so usc.o -L. -ltp -lus -Wl,--exclude-libs=libtp.a
Run Code Online (Sandbox Code Playgroud)
那么动态符号表就变成:
$ readelf --dyn-syms libsus.so
Symbol table '.dynsym' contains 6 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __cxa_finalize
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
5: 00000000000010f9 38 FUNC GLOBAL DEFAULT 10 usc
Run Code Online (Sandbox Code Playgroud)
如你所愿。
链接器选项--exclude-libs已记录:
--排除库 lib,lib,...
指定不应自动导出符号的存档库列表。库名称可以用逗号或冒号分隔。指定 --exclude-libs ALL 会从自动导出中排除所有存档库中的符号。...对于 ELF 目标端口,受此选项影响的符号将被视为隐藏。
为了确保符号tp*定义已链接,您仍然可以在共享库的完整符号表中看到它们:
$ readelf -s libsus.so | egrep 'FUNC.*(us|tp)(a|b|c)'
5: 00000000000010f9 38 FUNC GLOBAL DEFAULT 10 usc
41: 0000000000001133 10 FUNC LOCAL DEFAULT 10 usa
44: 000000000000111f 10 FUNC LOCAL DEFAULT 10 tpa
46: 000000000000113d 10 FUNC LOCAL DEFAULT 10 usb
48: 0000000000001129 10 FUNC LOCAL DEFAULT 10 tpb
50: 00000000000010f9 38 FUNC GLOBAL DEFAULT 10 usc
Run Code Online (Sandbox Code Playgroud)
就像显式隐藏的us*符号一样,它们变成LOCAL,不可用于进一步链接。(您会usc在 中看到两次,grep因为它同时被列为全局符号和动态符号)。
正如您可以从中推断出的那样,只要我们将其存档以进行进一步的链接,我们就不必费力地使用 编译我们自己的us*代码。我们可以像这样链接共享库:-fvisibility=hiddenlibus.a
$ gcc -shared -o libsus.so usc.o -L. -ltp -lus -Wl,--exclude-libs=libtp.a,libus.a
Run Code Online (Sandbox Code Playgroud)
具有相同的效果。
-fPIC明确指定以确保生成可以在 DSO 中链接的与位置无关的目标代码,但这一直是自 GCC 6 以来的 GCC 默认值。
| 归档时间: |
|
| 查看次数: |
2150 次 |
| 最近记录: |