我怎样才能 运行 共享库作为终端的可执行文件?

How am I able to run a shared library as an executable from the terminal?

来自 musl libc FAQ

Q: Where is ldd?

musl’s dynamic linker comes with ldd functionality built in. Just create a symlink from ld-musl-$ARCH.so to /bin/ldd. If the dynamic linker was started as “ldd”, it will detect that and print the appropriate DSO information.

检查 ld-musl-$ARCH.so 我发现它是 musl /usr/local/musl/lib/libc.so

的符号链接

那绝对是一个共享库

$ file /usr/local/musl/lib/libc.so
/usr/local/musl/lib/libc.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=068deca2fec0ea2c50ec1e11166d25b3bb057431, not stripped

而且它确实有效,真是太棒了哈哈。我真的可以做到这一点:

$ /usr/local/musl/lib/libc.so ./a.out

它会起作用的。但是我怎么可能从终端调用共享库呢?

好的,我想我明白了。

所以基本上共享库实际上是一个可执行文件。因为 musl 是一个 libc 实现,它定义了 _start() 函数,这是程序真正的 entry-point 。 _start() 函数将调用主函数。

musl 的开发者做到了,如果您将他们的 libc.so 作为 ldldd 调用,他们会检测到并采取相应的行动。

他们可以检测到,因为 _start() 确实需要 argcargv(然后将传递给 main()),所以他们可以查看是否 argv[0] 是 "ld" 或 "ldd".

感谢@that other guy 和@David C. Rankin 链接 this。那里的答案说你甚至可以有一个定义 main().

的共享库

所以我自己尝试了。

这是_start.c

void
_start()
{
    asm("mov ,%rax; mov [=10=],%rdi; syscall");
}

我在 x86_64 ubuntu linux 机器上用 gcc 7.4.0 编译了它,如下所示:

$ gcc -shared -nostdlib _start.c -o libwow.so

然后我称它为:

$ ./libwow.so
$

它当然什么也没做,但是它做了 运行。

我们生活在一个疯狂的世界 :D

编辑:

更疯狂的是。可以使用 dlopen(3). Look at this answer 将可执行文件加载为动态库以了解更多信息。

结论:

共享库和可执行文件几乎是一回事(ELF 个二进制文件)。

除了共享库没有固定的 entry-point 地址而可执行文件有。

默认情况下,共享库 PIE 而二进制文件不是。

而且我想还有一些其他的细微差别 :p

我们中间存在一些可执行文件(叛徒 :p),它们一直都是真正共享的库,我们不知道 gawkntfsck

查看此 Question/Answers 了解更多信息。