[rtems-users] C++ Virtual Functions
Joel Sherrill <joel@OARcorp.com>
joel.sherrill at OARcorp.com
Thu Feb 3 20:49:33 UTC 2005
Thanks Till. I forgot that I had started a Wiki Page on this.
Feel free to add info to it:
http://www.rtems.com/phpwiki/index.php/Using%20C%2B%2B
Till Straumann wrote:
> Here's my recollection of things [powerpc] -- sorry for the lengthy
> explanation...
>
> 1) BSP should call [gcc provided] '_eabi()' very early to set up a
> SYSV/EABI compliant environment [load r2/r13, stack align etc.].
> If you don't do this, e.g., SYSV/EABI short data areas won't work
> (see gcc -msdata -meabi options) !!
>
> 2) RTEMS calls '_init()' which among other things works through the
> C++ static constructor list -- provided that your linker stript
> and bsp_specs files are correct. (See Appendix on how it works.)
>
> HOWEVER: There is a problem here, in that '_eabi()' ends up calling
> '_init()' [actually, '__init()' -- we renamed to fix the problem
> described here] when it is still too early to initialize the
> C++ environment.
>
> Note that both details are of the 'seems to work' type. You
> won't notice anything if you don't call _eabi() until you try
> to use an essential SYSV/EABI feature.
> Likewise, calling '_init()' too early might not cause problems
> in many cases until one of your constructors uses an yet unavailable
> feature [such as e.g., 'malloc()'].
>
> ==> a typical chicken + egg. problem
>
> 1) we want to call _eabi() early [libbsp/powerpc/shared/start/start.S]
> 2) we want to prevent __init() from being called too early (by _eabi())
> 3) we want to call __init() at the apropriate time.
> 4) we dont want to hack gcc.
>
> Here's the solution [uses '.init' magic as described in the appendix]:
>
> an additional startup file 'rtems_crti.S' "terminates" __init()
> so it becomes a no-op and introduces a new '_init()' entry point
> to be used by rtems (ThreadHandler).
>
> Hence here's what you need:
>
> o BSP's 'start.S' file must call '_eabi()'
>
> o BSP's bsp_specs:
> *startfile: must contain [order is crucial]
>
> ecrti%O%s /* prologue of __init() */
> rtems_crti%0%s /* epilogue of __init(), prologue of
> _init() */
> /* now _init() does everything __init()
> usually
> * does
> */
> crtbegin.o%s /* crucial stuff, e.g. C++ exceptions,
> dtors */
>
> *endfile: must contain [order is essential]
>
> crtend.o%s /* crucial stuff, e.g., C++ exceptions,
> ctors */
> ecrtn.o%s /* _init() epilogue() */
>
> Here's what happens (properly linked executable):
>
> - BSP start.s calls _eabi(); SYSVI/EABI environment setup
> - _eabi() calls __init()
> - __init() returns immediately
> - BSP initializes
> - RTEMS starts up; initializes newlibc
> - ThreadHandler calls _init() [points to what __init() was intended
> to do]
> - _init() walks through code snippets provided by various '.init'
> sections
> - _init() encounters _do_global_ctors_aux() [provided by crtend.o]
> - _do_global_ctors_aux() initializes C++ environment [exceptions, ctors]
> - ...
>
> HTH
>
> -- Till
>
>
> APPENDIX on '.init' linker magic
> --------------------------------
>
> Note that '_init()' is not an ordinary function but 'compiler/linker
> magic' which uses the special '.init' section. An object file's
> '.init' section must be composed of small snippets of code like
>
> do_something();
> do_something_else();
>
> that should eventually go into the '_init()' routine. Any object
> may contain such code.
> The linker finally gathers all these snippets (in the order the objects
> are linked together) and that's where the 'ecrti.o/ecrtn.o' files
> come into play. These two files bracket the '.init' snippets with
> a proper function prologue (from ecrti.o) and epilogue (ecrtn.o),
> i.e., if you link (ecrti/ecrtn implicitely provided by gcc specs)
>
> ecrti.o my_object.o ecrtn.o
>
> you end up with something like ('translated into C'):
>
> _init ()
> { /* from ecrti.o */
>
> do_something();
> do_something_else(); /* from my_object.o */
>
> } /* from ecrtn.o */
>
> Hence, the rtems_crti.S file does the following:
>
> /* from ecrti.o: */
> __init()
> {
> /* from rtems_crti.o */
> }
>
> _init()
> {
> /* '.init' sections from other objects */
>
> /* from crtend.o: */
> __do_global_ctors_aux();
>
> /* from ecrtn.o: */
> }
>
>
> GCC uses this feature to call C++ static constructors by sticking
> a call to
>
> __do_global_ctors_aux()
>
> into the '.init' section of 'crtend.o' -- hence if you don't link
> against 'crtbegin/crtend' [bsp_specs] your constructors are not
> called.
>
> ==> your gcc configuration, linkcmds and bsp_specs must harmonize!
>
>
> Phil Torre wrote:
>
>> On Thu, Feb 03, 2005 at 09:07:44AM -0500, Smith, Gene wrote:
>>
>>> I went back a read everything I could find on this list regarding this
>>> and several people have reported this problem. The only one who reported
>>> a resolution did like you and wrote their own initializer (Phil Torre).
>>> However there was a lot of discussion about "eabi" that got into the
>>> ctor init and pointed out that it occurs in a call to _init() in
>>> _Thread_Handler when __USE_INIT_FINI__ is defined. The _init() call
>>> occurs on my system as described which in turn calls etext and
>>> eventually __do_global_ctors_aux__ but I never see any constructors
>>> actually called before _init() returns. I assume it is supposed to call
>>> the constructors for any globally or statically defined c++ objects
>>> somewhere inside the _init() call? Also, are these c++ objects supposed
>>> to be in the .bss section?
>>> -gene
>>
>>
>>
>> Someone subsequently pointed out to me that this was the wrong thing
>> to do, so these days I have added crtbegin.o and crtend.o to our
>> bsp_specs file, like so:
>>
>> *startfile:
>> %{!qrtems: %(old_startfile)} %{!nostdlib: %{qrtems: ecrti%O%s
>> crtbegin.o%s \
>> %{!qrtems_debug: start.o%s} \
>> %{qrtems_debug: start_g.o%s}}}
>>
>> *endfile:
>> %{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn%O%s}
>>
>> (I'm guity of cargo-cult programming here, as I don't actually understand
>> why this works. It does the trick, though, and without requiring me to
>> explicitly call my own initializer function.)
>>
>> -Phil
>
>
>
--
Joel Sherrill, Ph.D. Director of Research & Development
joel at OARcorp.com On-Line Applications Research
Ask me about RTEMS: a free RTOS Huntsville AL 35805
Support Available (256) 722-9985
More information about the users
mailing list