build立一个.so这也是一个可执行文件

所以大家可能知道glibc的/lib/libc.so.6可以在shell中像正常的可执行文件那样执行,在这种情况下,它会打印版本信息并退出。 这是通过在.so中定义一个入口点来完成的。 对于某些情况,也可以将其用于其他项目。 不幸的是,你可以通过ld的-e选项设置的低级入口点有点太低级:dynamic加载器不可用,所以你不能调用任何适当的库函数。 glibc出于这个原因在这个入口点通过裸机系统调用来实现write()系统调用。

我现在的问题是,任何人都可以想出一个很好的方法,如何从这个入口引导一个完整的dynamic链接器,以便可以访问其他.so的函数?

-pie选项build立你的共享库似乎给你你想要的一切:

 /* pie.c */ #include <stdio.h> int foo() { printf("in %s %s:%d\n", __func__, __FILE__, __LINE__); return 42; } int main() { printf("in %s %s:%d\n", __func__, __FILE__, __LINE__); return foo(); } /* main.c */ #include <stdio.h> extern int foo(void); int main() { printf("in %s %s:%d\n", __func__, __FILE__, __LINE__); return foo(); } $ gcc -fPIC -pie -o pie.so pie.c -Wl,-E $ gcc main.c ./pie.so $ ./pie.so in main pie.c:9 in foo pie.c:4 $ ./a.out in main main.c:6 in foo pie.c:4 $ 

PS glibc通过系统调用来实现write(3) ,因为它没有其他地方可以调用(它已经是最低级别了)。 这与能够执行libc.so.6无关。

不是一个好的方法,但我会创build一个小的包装可执行文件围绕.so调用我想要运行的入口点函数。

我想你会有你的ld -e指向一个入口点,然后使用dlopen()系列函数来查找和引导dynamic链接器的其余部分。 当然,你必须确保dlopen()本身是静态链接的,或者你可能必须实现足够的链接器存根才能使用(像使用mmap()一样的系统调用接口,就像libc本身正在做的那样。

没有一个对我来说听起来“很好”。 事实上,仅仅是阅读glibc源码(和ld-linux源代码,作为一个例子)的想法,足以评估这个工作的规模,听起来对我来说是相当危险的。 这也可能是一个便携式的噩梦。 Linux实现ld-linux和OpenSolaris,FreeBSD等链接方式之间可能存在很大的差异。 (我不知道)。