我怎样才能 运行 共享库作为终端的可执行文件?
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
作为 ld
或 ldd
调用,他们会检测到并采取相应的行动。
他们可以检测到,因为 _start()
确实需要 argc
和 argv
(然后将传递给 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),它们一直都是真正共享的库,我们不知道 gawk
和 ntfsck
。
查看此 Question/Answers 了解更多信息。
来自 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
作为 ld
或 ldd
调用,他们会检测到并采取相应的行动。
他们可以检测到,因为 _start()
确实需要 argc
和 argv
(然后将传递给 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),它们一直都是真正共享的库,我们不知道 gawk
和 ntfsck
。
查看此 Question/Answers 了解更多信息。