执行库(.so)时如何打印版本字符串/运行一些代码?

问题描述 投票:1回答:1

我已经看到了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()

我想在自己的库中执行此操作,以打印有关它的编译方式,支持的内容等有用的信息。我对此的搜索没有取得成果,但是也许我搜索的是错误的东西。我该怎么办?

executable shared-libraries version
1个回答
2
投票

位置独立可执行文件(PIE)现在是Linux和OpenBSD [1]等系统上的默认设置。因此,您可以像常规可执行文件一样构建共享库,然后将可执行文件作为对象参数提供给ccLD_PRELOADdlopen()作为共享库。

唯一需要确保的是,所有需要的符号都是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可执行文件,但不必链接一个。

© www.soinside.com 2019 - 2024. All rights reserved.