我正在寻找被问到的问题。我看到这个链接https://hev.cc/2512.html正在做我想要的完全相同的事情。但是没有解释最新情况。我也很困惑,如果是的话,是否可以将带有main()的共享库变为可执行文件?我猜我必须给全局main()但不知道细节。非常感谢任何进一步简单的参考和指导
我正在使用内核3.13的x86-64 64位Ubuntu
答案 0 :(得分:3)
这从根本上说是不明智的。
共享库通常没有执行的任务,因为它等同于main()
函数。主要目标是允许单独管理和实现公共代码操作,以及以这种方式运行以允许加载和共享单个代码文件的系统,从而减少使用它的应用程序代码的内存开销。
可执行文件设计为具有单个入口点,从该入口点执行与完成定义良好的任务相关的所有操作。不同的操作系统对该入口点有不同的要求。共享库通常没有类似的底层函数。
因此,为了(有用地)将共享库转换为可执行文件,您还必须定义(并生成代码)可以从单个入口点启动的任务。
您链接的代码从库的源代码开始,并通过入口点函数显式编码它调用的main()。如果您没有库的源代码,理论上可以从共享库中破解新文件(在没有安全功能的情况下,在任何给定的操作系统中都可以防止这种情况),但这样做会很奇怪
但实际上你不会以这种方式部署代码。相反,您可以将共享库编码为共享库。如果您想执行某项任务,您可以编写链接到该库和代码的单独可执行文件。试图将两者结合在一起会破坏编写库的目的,并扭曲该库和应用程序的结构,实现和维护。保持应用程序和库分开。
答案 1 :(得分:1)
我不知道这对任何事情都有用。您可以始终在单独的二进制文件中使用main
来实现相同的功能,该二进制文件链接到该库。制作一个既可以作为两者的单个文件,也可以在愚蠢的计算机技巧和#34;中实现。我可以看到在库中嵌入main
没有任何好处,即使它是测试工具或其他东西。
可能有一些性能原因,比如没有函数调用通过PLT的间接。
在该示例中,共享库也是一个有效的ELF可执行文件,因为它有一个快速而肮脏的入口点,可以从the ABI所说的main
抓取init_args
的args(即将它们从堆栈复制到寄存器中)。它还安排正确设置ELF解释器。它只适用于x86-64,因为没有为其他平台提供extern char **environ;
的定义。
我很惊讶它确实有效;我认为通常的CRT(启动)代码所做的所有废话实际上都需要stdio才能正常工作。看起来它没有初始化argc
,因为它只从堆栈中获取argv
和envp
,而不是main
。
无论如何,当作为可执行文件运行时,它拥有一切有效的动态链接可执行文件:一个运行一些代码和退出的入口点,一个解释器,以及对libc的依赖。 (ELF共享库可以依赖(即链接)其他ELF共享库,与可执行文件的方式相同)。
当用作库时,它只是作为包含一些函数定义的普通库。甚至没有看到让它作为可执行文件(入口点和解释器)工作的东西。
我不确定为什么你不会因main()
的多个定义而出错,因为它没有被声明为"weak" symbol。我想只有在引用未定义的符号时才会查找shared-lib定义。因此,来自call.c
的{{1}}代替来自main()
的{{1}},因为libtest.so
在链接器查看main
之前已经有了定义。
答案 2 :(得分:0)
使用Example创建共享动态库。
假设有三个文件:sum.o mul.o和print.o
共享库名称" libmno.so"
cc -shared -o libmno.so sum.o mul.o print.o
并使用
进行编译
cc main.c ./libmno.so