方案是我尝试通过/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)
我的问题是:
为什么程序在执行时会崩溃?如果有人能解释?
答案 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。