全局构造函数调用不在.init_array部分 [英] Global constructor call not in .init_array section

查看:2133
本文介绍了全局构造函数调用不在.init_array部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在嵌入式目标(ARM Cortex-M3)上添加全局构造函数支持。
假设我有以下代码:

I'm trying to add global constructor support on an embedded target (ARM Cortex-M3). Lets say I've the following code:

class foobar
{
    int i;

public:
    foobar()
    {
        i = 100;
    }

    void inc()
    {
        i++;
    }
};

foobar foo;

int main()
{
    foo.inc();
    for (;;);
}

我这样编译:

arm-none-eabi-g++ -O0 -gdwarf-2 -mcpu=cortex-m3 -mthumb -c foo.cpp -o foo.o

当我使用objdump查看.init_array节时,它显示.init_section的大小为零。

When I look at the .init_array section with objdump it shows the .init_section has a zero size.

我得到一个名为 _Z41__static_initialization_and_destruction_0ii 的符号。
当我反汇编对象文件时,我看到全局构造是在static_initialization_and_destruction符号中完成的。

I do get an symbol named _Z41__static_initialization_and_destruction_0ii. When I disassemble the object file I see that the global construction is done in the static_initialization_and_destruction symbol.

为什么在.init_section?

Why isn't a pointer added to this symbol in the .init_section?

推荐答案

我知道这个问题几乎已经两年了, GCC自己的裸机C ++初始化的机制,所以我想我会在这里分享细节。结果是在网络上有很多过时的或混乱的信息。例如,由于其任意段支持支持下面描述的方法,所以 collect2 包装器似乎不用于ARM ELF目标。

I know it has been almost two years since this question was asked, but I just had to figure out the mechanics of bare-metal C++ initialization with GCC myself, so I thought I'd share the details here. There turns out to be a lot of out-of-date or confusing information on the web. For example, the oft-mentioned collect2 wrapper does not appear to be used for ARM ELF targets, since its arbitrary section support enables the approach described below.

首先,当我使用Sourcery CodeBench Lite 2012.09-63编译上面的代码时,我会看到正确的 .init_array 区段大小4:

First, when I compile the code above with the given command line using Sourcery CodeBench Lite 2012.09-63, I do see the correct .init_array section size of 4:

$ arm-none-eabi-objdump -h foo.o

foo.o:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
...
 13 .init_array   00000004  00000000  00000000  0000010c  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, DATA
...

当我看看节内容,它只包含0:

When I look at the section contents, it just contains 0:

$ arm-none-eabi-objdump -j .init_array -s foo.o
Contents of section .init_array:
 0000 00000000                             ....

但是,还有一个重定位部分可以正确设置为 _GLOBAL__sub_I_foo

However, there is also a relocation section that sets it correctly to _GLOBAL__sub_I_foo:

$ arm-none-eabi-objdump -x foo.o
...
RELOCATION RECORDS FOR [.init_array]:
OFFSET   TYPE              VALUE
00000000 R_ARM_TARGET1     _GLOBAL__sub_I_foo

一般来说, .init_array 指向所有 _GLOBAL__sub_I_XXX 初始化器存根,每个都调用自己的 _Z41__static_initialization_and_destruction_0ii 副本(是的,它是乘法

In general, .init_array points to all of your _GLOBAL__sub_I_XXX initializer stubs, each of which calls its own copy of _Z41__static_initialization_and_destruction_0ii (yes, it is multiply-defined), which calls the constructor with the appropriate arguments.

因为我在我使用 -nostdlib build,我不能使用CodeSourcery的 __ libc_init_array 为我执行 .init_array ,所以我需要调用static initializers myself:

Because I'm using -nostdlib in my build, I can't use CodeSourcery's __libc_init_array to execute the .init_array for me, so I need to call the static initializers myself:

extern "C"
{
    extern void (**__init_array_start)();
    extern void (**__init_array_end)();

    inline void static_init()
    {
        for (void (**p)() = __init_array_start; p < __init_array_end; ++p)
            (*p)();
    }
}

__ init_array_start __ init_array_end 由链接描述文件定义:

__init_array_start and __init_array_end are defined by the linker script:

. = ALIGN(4);
.init_array :
{
__init_array_start = .;
KEEP (*(.init_array*))
__init_array_end = .;
}

这种方法似乎适用于CodeSourcery交叉编译器和本机ARM GCC ,例如在Ubuntu 12.10 for ARM。支持两个编译器是使用 -nostdlib 而不依赖于CodeSourcery CS3裸机支持的一个原因。

This approach seems to work with both the CodeSourcery cross-compiler and native ARM GCC, e.g. in Ubuntu 12.10 for ARM. Supporting both compilers is one reason for using -nostdlib and not relying on the CodeSourcery CS3 bare-metal support.

这篇关于全局构造函数调用不在.init_array部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆