大多数情况下,当你编译一个共享库时,执行它是没有意义的,这样做没有任何用处:
$ ./libfoobarbaz.so
Segmentation fault
然而,当执行glibc时,GNU的人们能够坚持一些输出:
$ /lib/libc.so.6
GNU C Library (Debian EGLIBC 2.11.2-10) stable release version 2.11.2, by Roland McGrath et al.
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.4.5.
Compiled on a Linux 2.6.32 system on 2011-01-23.
Available extensions:
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
虽然这个特殊的用法对我来说似乎很普通,但他们是如何实现创建一个同时充当可执行文件的共享库的呢?
答案 0 :(得分:2)
这里的技巧是,可执行文件和共享对象库与 crt0中的代码协作使用与 libc.so 相同的格式ELF 和。 .o (on * nixes),编译器的一部分,实际上负责设置运行时环境,然后调用正确的int main(...)
函数。如果不链接 libc.so 和 crt0.o ,则只会执行int main(...)
的程序。从技术上讲,可以将 main 函数设置为可执行入口点,但是启动就像程序不会接收命令行参数,没有环境等,这些都是标准的责任运行时库 libc.so
所以 libc.so ,也负责准备int main(...)
函数的调用,可以很容易地确定它是否被其他程序链接,或者它是否“独立” 。如果进程通过 libc.so 入口点开始,则会显示此消息,然后退出。只有当进程通过可执行文件二进制入口点启动时,二进制文件才能通过该魔法 crt0.o 接收,该进程将照常运行。
答案 1 :(得分:0)
答案在于“可执行文件和链接格式”。相同的文件格式用于可执行文件和库。
答案 2 :(得分:0)
有关此主题here的方法。原理是在库中定义一个入口点,并用解释程序的路径名(例如/lib/ld-linux.so.2)填充ELF文件的interp部分。