链接到目录后执行程序时崩溃

时间:2016-07-17 06:36:03

标签: c linux gcc x86 dynamic-linking

方案是我尝试通过/proc将程序重新链接到目录,其中这些目录为elf可执行文件。

首先,我创建一个名为test

的目录
$ mkdir test

链接到hello二进制文件

# ln /bin/ping test
# exit

打开目标二进制文件的文件描述符

$ exec 3< test

您知道,现在可以通过/proc

访问此描述符
$ ls -l /proc/$$/fd/3
lr-x------ 1 febri febri 64 Jul 17 11:09 /proc/2930/fd/3 -> /home/febri/test

删除先前创建的目录

$ rm -rf test

/proc链接应该仍然存在,但现在将被标记为已删除。

$ ls -l /proc/$$/fd/3 
lr-x------ 1 febri febri 64 Jul 17 11:09 /proc/2930/fd/3 -> /home/febri/test (deleted)

使用示例有效负载替换目录,如:

$ cat hello.c
#include <stdio.h>

int main(int argc, char ** argv) {
printf("hello!\n");
return 0;
}
$ gcc -w -fPIC -shared -o test hello.c
$ ls -l test
-rwxrwxr-x 1 febri febri 6894 Jul 17 11:20 test
$ file test 
test: ELF 32-bit LSB  shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=361c522d3d9db35ad24de9f3162f80f8a26c9c5b, not stripped

所以,我运行链接的程序,输出是:

$ ./test
Segmentation fault (core dumped)

我的问题是:

为什么程序在执行时会崩溃?如果有人能解释?

1 个答案:

答案 0 :(得分:1)

事实上,你搞砸的目录和/或符号链接与你所面临的分段错误完全无关。让我们看看您用来编译hello.c的命令行选项:

  • -w:取消所有警告。这是不好的做法,迟早会成为你每一个错误的根源。我还没有找到一个很好的理由来压制任何警告。无论如何,这对于这种情况并不重要,因为编译一个hello world程序不会产生任何警告。

  • -fPIC:生成与位置无关的代码](https://en.wikipedia.org/wiki/Position-independent_code)。

  • -shared:生成shared library而不是可执行文件。

所以,你正在尝试执行一个不打算执行的共享库!但是,GCC使用可执行位标记输出文件。这完全没有意义......直到您遇到HP-UX的mmap()实现。

看起来,由于one of HP-UX's features咳嗽设计缺陷咳嗽),整个Unix(类似)系列继承了这种共享库的约定被标记作为可执行文件,即使你真正尝试执行它们,它们中的大多数都会SIGSEGV

从操作系统的角度来看,分段错误的实际原因是Executable and Linkable Format在1980年代后期设计的方式的工件。

奇怪的是,共享库确实可以在执行时避免SEGV。但是,为了这样做,应执行黑色伏都教,例如the GNU C Library's。执行这种仪式的后果令人痛苦。例如,您无法初始化C运行时,因此您必须使用直接read()write()而不是{{1 }}。其他运行时支持的子系统,例如stdio和朋友,也是不可能的。此外,(由于没有运行时支持),没有malloc()。您必须改为定义自己的入口点,并明确调用main()

tl; dr :目录和符号链接与此问题无关。您尝试执行共享库,并且由于这不是预期的行为,您_exit(0)&#39; d。