Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>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 <code>collect2</code> wrapper does not appear to be used for ARM ELF targets, since its arbitrary section support enables the approach described below.</p> <p>First, when I compile the code above with the given command line using Sourcery CodeBench Lite 2012.09-63, I do see the correct <code>.init_array</code> section size of 4:</p> <pre><code>$ 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 ... </code></pre> <p>When I look at the section contents, it just contains 0:</p> <pre><code>$ arm-none-eabi-objdump -j .init_array -s foo.o Contents of section .init_array: 0000 00000000 .... </code></pre> <p>However, there is also a relocation section that sets it correctly to <code>_GLOBAL__sub_I_foo</code>:</p> <pre><code>$ arm-none-eabi-objdump -x foo.o ... RELOCATION RECORDS FOR [.init_array]: OFFSET TYPE VALUE 00000000 R_ARM_TARGET1 _GLOBAL__sub_I_foo </code></pre> <p>In general, <code>.init_array</code> points to all of your <code>_GLOBAL__sub_I_XXX</code> initializer stubs, each of which calls its own copy of <code>_Z41__static_initialization_and_destruction_0ii</code> (yes, it is multiply-defined), which calls the constructor with the appropriate arguments.</p> <p>Because I'm using <code>-nostdlib</code> in my build, I can't use CodeSourcery's <code>__libc_init_array</code> to execute the <code>.init_array</code> for me, so I need to call the static initializers myself:</p> <pre><code>extern "C" { extern void (**__init_array_start)(); extern void (**__init_array_end)(); inline void static_init() { for (void (**p)() = __init_array_start; p &lt; __init_array_end; ++p) (*p)(); } } </code></pre> <p><code>__init_array_start</code> and <code>__init_array_end</code> are defined by the linker script:</p> <pre><code>. = ALIGN(4); .init_array : { __init_array_start = .; KEEP (*(.init_array*)) __init_array_end = .; } </code></pre> <p>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 <code>-nostdlib</code> and not relying on the CodeSourcery CS3 bare-metal support.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload