C++ static constructor problem

Till Straumann strauman at SLAC.Stanford.EDU
Tue Nov 26 04:44:31 UTC 2002

Hi all.

Hadn't come across this since I only had dynamically loaded C++
modules recently.

I can reproduce Kate's problem. A simple test example (see below)
works fine when built with gcc-2.95.3 but fails when built with gcc3.2 
(OAR RPM for linux, vers. gcc3.2newlib1.10.0-2).

2 hours of research revealed some sort of mess between how different
versions of gcc and rtems and CPUs perform constructor calls:

NOTE: I am NOT a gcc internals expert

  1) older gcc versions (2.95.3) uses two flavors:
      i) systems who support '.init'/'.fini' sections are expected
         to use 'crtbegin/crtend'; crtbegin/crtend embed
         __do_global_ctors() into the '.init' section
      ii) for other systems, __do_global_ctors is built into __main()

    Although powerpc-eabi falls under i), it is treated as ii) with
    __main() redefined to __eabi(); __eabi() calls
    __do_global_ctors() (also defined by eabi code).

  2) newer gcc versions (3.2) behaves different:
     a) powerpc-eabi defines __main() to __eabi() which is still
        called by main().
     b) __eabi() does NOT define nor call __do_global_ctors()
        but calls __init() instead.
     c) __init() executes the list of function pointers embedded
        into the '.init' section.
     d) Correct behavior could probably be obtained by using
        'crtbegin/crtend' (spec file mod.) - this would result in
        constructor calls ending up in '.init', hence they would
        be executed under c) -- see B however.

  1) rtems may call __main or __init on its own (__USE_MAIN__,
     __USE_INIT_FINI__, respectively). Most BSPs have __USE_INIT_FINI__
     defined, i.e. the list in '.init' is actually executed TWICE :-O
     Once by main()-->__eabi()-->__init() and one more time by
     RTEMS (score/src/threadhandler.c)

Summary GCC 3.2/RTEMS behavior (built with __USE_INIT_FINI__):
   x) app defines main(), crtbegin/crtend _not_ used:
      C++ constructors are _not_ executed (but other stuff in
      '.init' is executed twice.
   y) app defines main(), crtbegin/crtend _are_ used:
      C++ constructors are executed twice.
   z) app does not define main(), crtbegin/crtend _are_ used:
      C++ constructors are executed once

  1) Solution z) might be OK, including eh frame registration
  2) ctors/dtors are not the only C++ issue. If those are called
     by any other means but __init(), eh frame registration must
     also be taken care of.
  3) Cexp, when used on a system with statically linked C++ code,
     might be unable to collapse '.gnu.linkonce.xxx' sections into
     the statically linked part
     because these sections are flattened out into the .text/.data
     sections by the static link (unless preserved by the linker script).

Sorry for the long message - as I said, I'm not GCC expert and
the analysis might miss some details.

As can be seen one more time: C++ is the DEVIL lurking in the details.

-- Till

APPENDIX: test example code


    /* configuration macros/includes go here */

    main(int argc, char **argv){ return 0;}

    Init(void *unused) { main(0,0); }

    #include <stdio.h>
    int i=printf("hello\n");)

Kate Feng wrote:
> Hi  Joel,
> I tried to post the following message to the rtems-users mailing list
> last week.  However, it did not  succeed.  Why does this happen ?
> Could you please help me to post it ?
> The platform :
> gcc-3.2 cross compiler,
> RTEMS version : rtems-ss-20021007
> taget BSP : MVME2307
> Problem :
> In my application, there are some C++ static constructors which are
> supposed to run on application startup.  However, it did not happen at
> all. It seems that  __do_global_ctors was not  in the gcc library.
> My question is that is the C++ static constructors implemented
> in the gcc-3.2 cross compiler  for powerpc or maybe it is just my local
> building error ?
> I thought the C++ static constructor was built in the gcc-3.2 crosss
> compiler.
> However,  the __do_global_ctors is missing.
> I  thought maybe I can start to  modify the  gcc-3.2/gcc/libgcc2.c
> file or the crtstuff.c file.  However,   everything else in my current
> platform
> works  fine.  I do not want to make it worse  if it was already
> supported.
> Any pointer would be highly appreciated.
> Thanks in advance,
> Kate
> S. Kate Feng
> Brookhaven National Lab.
> National Synchrotron Light Source
> Bldg. 725D
> Upton, New York  11973-5000
> Email: feng1 at bnl.gov

More information about the users mailing list