我已经看到了libc.so的某些版本,当从命令行执行该版本时,将打印一个版本字符串,如下所示:
$ /lib/libc.so.6
GNU C Library (Buildrood) stable release version 2.30.
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTIBILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 7.4.0.
libc ABIs: UNIQUE IFUNC ABSOLUTE
For bug reporting instructions, please see:
<https://www.gnu.org/software/libc/bugs.html>.
显然,此库中有某种入口点,同时仍为用户程序保留main()
。
我想在自己的库中执行此操作,以打印有关它的编译方式,支持的内容等有用的信息。我对此的搜索没有取得成果,但是也许我搜索的是错误的东西。我该怎么办?
位置独立可执行文件(PIE)现在是Linux和OpenBSD [1]等系统上的默认设置。因此,您可以像常规可执行文件一样构建共享库,然后将可执行文件作为对象参数提供给cc
,LD_PRELOAD
或dlopen()
作为共享库。
唯一需要确保的是,所有需要的符号都是exported,这不是默认值。因此,您应该使用-Wl,-E
(这将导致它导出所有符号),或者通过-Wl,--dynamic-list=filename
为其提供已导出符号的列表。
$ cc -Wl,--dynamic-list=<(echo '{func;};') -include stdio.h -o shared.so -xc - <<'EOT' int main(){ printf("Shared library!\n"); } void func(){ printf("Exported function!\n"); } EOT $ cc -include stdio.h -xc - -x none ./shared.so -o main <<'EOT' int main(){ extern void func(void); func(); } EOT $ ./shared.so Shared library! $ ./main Exported function!
-Wl,-E
的问题在于,它还将从crt*.o
启动文件中导出符号,这可能会导致“ main”可执行文件引用它们,而不是提取其自己的启动代码副本。这似乎不是一个好主意。
一种可以让您仍然使用-Wl,-E
-Wl,--version-script=file
与版本脚本一起使用,该脚本本地化main
,__libc_csu*
, _start
和动物园的其余部分:cc -Wl,-E -Wl,--version-script=<(echo '{local:_*;data_start;main;};') -include stdio.h -o shared.so -xc - <<'EOT' int main(){ printf("Shared library!\n"); } void func(){ printf("Exported function!\n"); } EOT $ ./main Exported function!
[1]在某些系统上,例如FreeBSD或NetBSD,您仍然必须使用
-pie -fPIE
来构建PIE可执行文件,但不必链接一个。