【问题标题】:Segmentation fault using .init_array section使用 .init_array 部分的分段错误
【发布时间】:2019-07-11 04:42:18
【问题描述】:

我正在学习 ELF,遇到了一个奇怪的 seg fault

代码:

#include <stdio.h>
#include <stdint.h>

__attribute__((constructor(102))) static void init1() {
    printf("%s\n", __FUNCTION__);
}

__attribute__((constructor(101))) static void init2() {
    printf("%s\n", __FUNCTION__);
}

void another_init1() {
    printf("%s\n", __FUNCTION__);
}

void another_init2() {
    printf("%s\n", __FUNCTION__);
}

typedef void (*init)();
__attribute__((section(".init_array"))) init init_arr[2] = {another_init1, another_init2};

static void my_function_1() {}

int main() {
    printf("hello world\n");
    return 0;
}

用gcc -o hello hello.c 编译它并运行./hello 我明白了

[root@20f890034489 ch5]# ./hello 
init2
init1
Segmentation fault

这来自 .init_arr。如果我让这个数组包含一个函数 ptr,一切都会按预期工作,但是其中有 2 个 ptr,它会出现段错误。

有什么建议吗?只是觉得这很奇怪

VK

【问题讨论】:

  • 这是故意的。如果数组有多个元素,gcc 在连接部分时插入 NULL,请参阅this source。这使得 __libc_csu_init 跳转到 NULL。
  • 关于 NULL 很清楚,但您不要将其插入 .init/fini\_array。关于对齐的答案是 100% 正确的。

标签: c elf


【解决方案1】:

init_array 应该与指针的大小对齐;如果您将其更改为:

__attribute__((section(".init_array"), aligned(sizeof (void*)))) init init_arr[2] = {another_init1, another_init2};

它会起作用的。

如果不是(至少在 x86-64 上)gcc 会将您的数组对齐到 16 字节边界,在 .init_array 部分中已经存在的 3 个函数指针之间创建一个 8 字节间隙(frame_dummy + 您的init1 和 init2) 以及 2 个新函数,它们将在动态链接器中显示为 NULL 指针。

【讨论】:

  • 哦,哇,it works。使用当前的 C,您宁愿 aligned(_Alignof(void*))。
猜你喜欢
  • 2016-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-15
  • 2015-02-28
  • 2015-11-16
  • 2012-01-06
  • 1970-01-01
相关资源
最近更新 更多