如何使共享库成为可执行文件

how to make shared library an executable

我正在搜索已提出的问题。我看到这个 link https://hev.cc/2512.html 正在做我想要的完全相同的事情。但是没有解释发生了什么。我也很困惑是否可以使带有 main() 的共享库可执行,如果是的话如何?我猜我必须给出 global main() 但不知道细节。非常感谢任何进一步的简单参考和指导

我正在使用内核 3.13

开发 x86-64 64 位 Ubuntu

这从根本上讲是不明智的。

共享库通常不执行任何可以使用的任务,因为它等同于 main() 函数。主要目标是允许单独管理和实现公共代码操作,并在以这种方式运行的系统上允许加载和共享单个代码文件,从而减少使用它的应用程序代码的内存开销。

可执行文件被设计为具有单一入口点,从该入口点执行与完成明确定义的任务相关的所有操作。不同的 OSes 对该入口点有不同的要求。共享库通常没有类似的底层功能。

因此,为了(有效地)将共享库转换为可执行文件,您还必须定义(并为其生成代码)可以从单个入口点启动的任务。

您链接到的代码从库的源代码开始,并明确编码了它通过入口点函数调用的 main()。如果你没有库的源代码,理论上你可以从共享库中破解一个新文件(在任何给定的 OS 中都没有安全功能来防止这种情况发生),但这将是一个奇怪的事情。

但实际上您不会以这种方式部署代码。相反,您会将共享库编码为共享库。如果您想执行某些任务,您将编写一个链接到该库和代码的单独的可执行文件。试图将两者结合在一起会破坏编写库的目的,并扭曲该库和应用程序的结构、实现和维护。将应用程序和库分开。

  • 使用示例创建共享动态库。

Suppose with there are three files are : sum.o mul.o and print.o

Shared library name " libmno.so "

cc -shared -o libmno.so sum.o mul.o print.o

and compile with

cc main.c ./libmno.so

我看不出这有什么用。您始终可以通过在针对该库的 link 的单独二进制文件中使用 main 来实现相同的功能。制作一个兼具两者功能的文件完全属于 "silly computer tricks" 的领域。我认为将 main 嵌入到库中没有任何好处,即使它是测试工具或其他东西。

可能有一些性能原因,比如没有函数调用通过 PLT 的间接寻址。


在那个例子中,共享库也是一个有效的 ELF 可执行文件,因为它有一个 quick-and-dirty entry-point 从 the ABI 获取 main 的参数说他们走了(即将他们从堆栈复制到寄存器)。它还安排正确设置 ELF 解释器。它只能在 x86-64 上工作,因为没有为其他平台提供 init_args 的定义。

我很惊讶它真的有效;我认为通常的 CRT(启动)代码所做的所有废话实际上是 stdio 正常工作所必需的。看起来它没有初始化 extern char **environ;,因为它只从堆栈中获取 argcargv,而不是 envp.

无论如何,当 运行 作为可执行文件时,它具有成为有效 dynamically-linked 可执行文件所需的一切:一个 entry-point 运行 一些代码并退出,一个解释器,以及对 libc 的依赖。 (ELF 共享库可以依赖(即 link 反对)其他 ELF 共享库,就像可执行文件一样)。


当用作库时,它只是作为包含一些函数定义的普通库。 None 甚至查看了让它作为可执行文件(入口点和解释器)工作的东西。

我不确定为什么 main 的多个定义没有出现错误,因为它没有声明为 "weak" symbol。我猜 shared-lib 定义仅在引用未定义的符号时才会被查找。所以使用 call.c 中的 main() 而不是 libtest.so 中的 main() 因为 main 在 linker 查看 [=24 之前已经有了定义=].