如何使共享库成为可执行文件
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;
,因为它只从堆栈中获取 argc
和 argv
,而不是 envp
.
无论如何,当 运行 作为可执行文件时,它具有成为有效 dynamically-linked 可执行文件所需的一切:一个 entry-point 运行 一些代码并退出,一个解释器,以及对 libc 的依赖。 (ELF 共享库可以依赖(即 link 反对)其他 ELF 共享库,就像可执行文件一样)。
当用作库时,它只是作为包含一些函数定义的普通库。 None 甚至查看了让它作为可执行文件(入口点和解释器)工作的东西。
我不确定为什么 main
的多个定义没有出现错误,因为它没有声明为 "weak" symbol。我猜 shared-lib 定义仅在引用未定义的符号时才会被查找。所以使用 call.c
中的 main()
而不是 libtest.so
中的 main()
因为 main
在 linker 查看 [=24 之前已经有了定义=].
我正在搜索已提出的问题。我看到这个 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;
,因为它只从堆栈中获取 argc
和 argv
,而不是 envp
.
无论如何,当 运行 作为可执行文件时,它具有成为有效 dynamically-linked 可执行文件所需的一切:一个 entry-point 运行 一些代码并退出,一个解释器,以及对 libc 的依赖。 (ELF 共享库可以依赖(即 link 反对)其他 ELF 共享库,就像可执行文件一样)。
当用作库时,它只是作为包含一些函数定义的普通库。 None 甚至查看了让它作为可执行文件(入口点和解释器)工作的东西。
我不确定为什么 main
的多个定义没有出现错误,因为它没有声明为 "weak" symbol。我猜 shared-lib 定义仅在引用未定义的符号时才会被查找。所以使用 call.c
中的 main()
而不是 libtest.so
中的 main()
因为 main
在 linker 查看 [=24 之前已经有了定义=].