如何使Linux共享库(库)自己运行?
注意到,gcc -shared
创建一个可执行文件,我刚刚得到了奇怪的想法来检查时,我尝试运行它......好结果是发生了什么 段错误
我自己的库。因此,对此感到好奇,我试图“运行” glibc(/lib/x86_64-linux-
gnu/libc.so.6在我的系统上)。果然,它没有崩溃,但是提供了一些输出:
GNU C Library (Debian GLIBC 2.19-18) stable release version 2.19, by Roland McGrath et al.Copyright (C) 2014 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.8.4.
Compiled on a Linux 3.16.7 system on 2015-04-14.
Available extensions:
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
所以我的问题是:这背后的魔力是什么?我不能只main
在库中定义符号-可以吗?
回答:
我写
了一篇有关该主题的博客文章,在此我进行了更深入的介绍,因为我发现它很有趣。您可以在下面找到我的原始答案。
您可以使用-Wl,-e,entry_point
gcc选项指定链接器的自定义入口点,其中g entry_point
库的“主”函数名称为。
void entry_point(){
printf("Hello, world!\n");
}
链接器不希望与之链接-shared
的文件作为可执行文件运行,并且必须提供一些更多信息才能使程序可运行。如果尝试立即运行该库,则会遇到分段错误。
.interp节是操作系统运行应用程序所需的结果二进制文件的一部分。如果-shared
未使用,它将由链接器自动设置。如果要构建自己执行的共享库,则必须在C代码中手动设置此部分。看到这个问题。
解释器的工作是查找并加载程序所需的共享库,准备要运行的程序,然后运行它。对于Linux上的ELF格式(现代* nix普遍存在),使用该ld-
linux.so程序。有关更多信息,请参见手册页。
下面的行使用GCC属性在.interp节中放置一个字符串。将其放在库的全局范围内,以明确告诉链接器您要在二进制文件中包含动态链接器路径。
const char interp_section[] __attribute__((section(".interp"))) = "/path/to/ld-linux";
查找路径的最简单方法ld-linux.so
是ldd
在任何普通应用程序上运行。我的系统的示例输出:
jacwah@jacob-mint17 ~ $ ldd $(which gcc) linux-vdso.so.1 => (0x00007fff259fe000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007faec5939000)
/lib64/ld-linux-x86-64.so.2 (0x00007faec5d23000)
指定解释器后,您的库应该是可执行的!仅有一个小缺陷:entry_point
返回时将出现段错误。
使用编译程序时main
,它不是执行该程序时要调用的第一个函数。main
实际上是由另一个称为的函数调用的_start
。此功能是负责建立argv
和argc
等初始化。然后它调用main
。当main
返回时,_start
调用exit
与返回值main
。
堆栈中没有返回地址,_start
因为它是第一个要调用的函数。如果尝试返回,则会发生无效读取(最终导致分段错误)。这正是我们的入口函数所发生的。将调用添加exit
为进入函数的最后一行,以正确清理而不崩溃。
#include <stdio.h>#include <stdlib.h>
const char interp_section[] __attribute__((section(".interp"))) = "/path/to/ld-linux";
void entry_point()
{
printf("Hello, world!\n");
exit(0);
}
用编译gcc example.c -shared -fPIC -Wl,-e,entry_point
。
以上是 如何使Linux共享库(库)自己运行? 的全部内容, 来源链接: utcz.com/qa/403015.html