某些共享库在从命令行调用时提供输出,就好像它们是可执行文件一样。例如:
$ /lib/libc.so.6
GNU C Library stable release version 2.13, by Roland McGrath et al.
Copyright (C) 2011 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.5.2.
Compiled on a Linux 2.6.37 system on 2011-01-18.
[...]
在我自己用 C 编写的共享库中,如何提供此输出?我现在已经执行了一个刚刚创建的库,并且得到了一个segment fault
.
答案1
尝试定义 avoid __libc_main()
或void _init()
。
答案2
我刚刚基本上回答了同样的问题堆栈溢出。我解决这个问题的动机是为了实现支持libcap
和pam_cap.so
。
答案的关键成分是:.interp
ELF 部分内容,其中包括对动态库加载器的引用;运行时入口点的规范。
步骤(缩写为堆栈溢出答案)你这样做:
- 找出您的系统上使用的动态加载程序:
$ ldd $(which awk)|grep ld-linux|awk '{print $1}'
/lib64/ld-linux-x86-64.so.2
- 构建共享库源代码以包含对该二进制文件的引用,并进行一些强制堆栈对齐以避免 SSE 相关的段错误(称为
foo.c
):
#include <stdio.h>
#include <stdlib.h>
void multi(const char *caller) {
printf("called from %s\n", caller);
}
__attribute__((force_align_arg_pointer))
void multi_main(void) {
multi(__FILE__);
exit(42);
}
const char dl_loader[] __attribute__((section(".interp"))) =
"/lib64/ld-linux-x86-64.so.2";
- 编译/链接库及其可运行定义的入口点:
$ gcc -fPIC -shared -o foo.so foo.c --entry=multi_main
$ ldd foo.so
linux-vdso.so.1 (0x00007fff345d7000)
libc.so.6 => /lib64/libc.so.6 (0x00007f5bd69f6000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5bd6be9000)
$ file foo.so
foo.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=94ffcc60e66b21021ad564882c8e39ebeccd477e, not stripped
$ ./foo.so
called from foo.c
这是一个相当小的例子。您可以在我之前的回答或链接的提交中找到更多详细信息libcap
。