gcc - 为什么独立的 C hello 程序在用作动态链接器时会崩溃

标签 gcc glibc elf dynamic-linking

以下程序:

#include <stdio.h>

int main(int argc, char *argv[])
{
  for (int j = 0; j < argc; j++)
    printf("%d: %s\n", j, argv[j]);
  return 0;
}

内置于静态链接的 PIE 中:
gcc -g -fpie main.c -static-pie -o ld.so

工作正常:
$ ./ld.so foo bar
0: ./ld.so
1: foo
2: bar

但是当我将该程序用作另一个程序的 ELF 解释器时:
$ gcc -g main.c -Wl,-I./ld.so -o a.out

它像这样崩溃:
gdb -q ./a.out
(gdb) run
Starting program: /tmp/a.out 

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7da84e2 in __ctype_init () at ctype-info.c:31
31    *bp = (const uint16_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS) + 128;
(gdb) bt
#0  0x00007ffff7da84e2 in __ctype_init () at ctype-info.c:31
#1  0x00007ffff7d9e3bf in __libc_init_first (argc=argc@entry=1, argv=argv@entry=0x7fffffffd728, envp=0x7fffffffd738) at ../csu/init-first.c:84
#2  0x00007ffff7d575cd in __libc_start_main (main=0x7ffff7d56e29 <main>, argc=1, argv=0x7fffffffd728, init=0x7ffff7d57ce0 <__libc_csu_init>, fini=0x7ffff7d57d70 <__libc_csu_fini>, rtld_fini=0x0, 
    stack_end=0x7fffffffd718) at ../csu/libc-start.c:244
#3  0x00007ffff7d56d6a in _start () at ../sysdeps/x86_64/start.S:120

这是为什么?

以上地址均在./ld.so内本身,所以它在自己的初始化过程中崩溃。事实上,控制永远不会到达a.outld.so退出。

最佳答案

调试时间比我预期的要长一些。

崩溃是在:

Dump of assembler code for function __ctype_init:
   0x00007ffff7da84d0 <+0>:     mov    $0xffffffffffffffa0,%rax
   0x00007ffff7da84d7 <+7>:     mov    $0xfffffffffffffff0,%rcx
   0x00007ffff7da84de <+14>:    mov    %fs:(%rax),%rax
=> 0x00007ffff7da84e2 <+18>:    mov    (%rax),%rax
   0x00007ffff7da84e5 <+21>:    mov    0x40(%rax),%rsi

$rax == 0 .当ld.so本身通过这个代码,$rax明显非NULL。显然在TLS期间出了点问题设置,但什么?

事实证明,GLIBC 初始化了它的 _dl_phdr来自 AT_PHDR在辅助向量中,然后遍历所有 Phdr s 找一个 PT_TLS类型。

如果没有,则 GLIBC 假定没有 TLS设置是必要的。

ld.so直接运行,内核提供的辅助向量指向Phdr s 为 ld.so , PT_TLS存在,一切正常。

但是当 ld.so作为 a.out 的解释器间接运行,辅助向量指向 Phdr s 为 a.out (而不是 ld.so——这是设计好的)。自 a.out没有任何线程局部变量,它没有 PT_TLS段。

结论:目前无法构建 ELF翻译与-static-pie和 GLIBC,除非非常小心地避免线程本地存储。避免线程本地存储目前似乎也不是一个选项:一个微不足道的 int main() { return 0; }还有一个TLS尽管根本没有使用 GLIBC 中的任何东西。

关于gcc - 为什么独立的 C hello 程序在用作动态链接器时会崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55679589/

相关文章:

gcc - 哪个选项启用对象大小跟踪和 __builtin_object_size?

linux - 由于 glibc 版本,基于 Qt 的应用程序二进制兼容性问题

ubuntu - 构建 glibc 时未定义对 _dl_cet_check 的引用

c - 需要 __alignof__ 的调试符号

linux - objdump 输出中第一列数字是什么意思?

gcc - 需要gcc44-c++支持

gcc - Linux 是否有与 Windows "resource files"等效的代码?

c++ - 为什么我的 Curiously Recurring Template Pattern (CRTP) 不能引用派生类的 typedef?

c - Elf Symtab 解析空指针

elf - 在 ELF 文件中,_start 的地址是如何确定的?