[rtems-users] C++ Virtual Functions

Smith, Gene gene.smith at siemens.com
Thu Feb 3 17:06:55 UTC 2005


Sergei Organov wrote, On 2/3/2005 9:45 AM:

> "Smith, Gene" <gene.smith at siemens.com> writes:
> 
> 
>>Sergei Organov wrote, On 2/3/2005 8:38 AM:
>>
>>
>>>"Smith, Gene" <gene.smith at siemens.com> writes:
>>>
>>>
>>>>Sergei Organov wrote, On 2/2/2005 12:10 PM:
>>>>
>>>>
>>>>
>>>>>"Smith, Gene" <Gene.Smith at siemens.com> writes:
>>>>>
>>>>
>>>>>>I am having some problems running code containing C++ virtual
>>>>>>functions in rtems. When the code tries to branch to a virtual
>>>>>>function address using "bctrl" instruction, the address (in ctr) is
>>>>>>way out of range and results in a machine check exception.
>>>>>>
>>>>>>Is there anything I need to do special in rtems for virtual functions to
>>>>>>work? Is anyone using virtual functions, pure or impure, in rtems? I am
>>>>>>still using rtems 4.6.1 and my ppc40x-derived bsp.
>>>>>
>>>>>Besides what others have already suggested to check for, it could be the
>>>>
>>>>>case that you call a virtual member function of a static or global
>>>>>object for which constructor hasn't been invoked (yet). In this case
>>>>>virtual table pointer in the object isn't initialized. Global
>>>>>constructors are invoked by special startup code so you need to check if
>>>>>this code is linked in and executed. Check for .ctors section in the
>>>>>executable as well.
>>>>
>>>>Yes, that is what I just concluded in my previous post to this thread.
>>>>I could see *no* .ctors or .dtors sections in my original output file.
>>>>The .ctors and .dtors sections were supposedly placed into the .text
>>>>section (see the attached linkcmds on previous msg). I then moved them
>>>>out of .text into their own sections following .got2 (as shown in
>>>>referenced example linkcmds, psim and motorola) and now I do see the
>>>>sections .c(d)tors in the output following .got2. However, I still
>>>>don't seem to see any initialization (construction) of the global
>>>>object in question (its constructor is never hit when a breakpoint is
>>>>put on it).
>>>
>>>The code that calls constructors doesn't in fact use .ctors section in
>>
>>>any way, it uses __CTOR_LIST__  and probably __CTOR_END__ symbols that
>>>seem to be correctly defined by your linker script, so moving all that
>>>from .text to separate .ctors won't help.
>>>Most probably you don't link in correct C++ startup code or somehow it's
>>
>>>not called. There are guys on the list that know much better than me how
>>>C++ startup code is linked in and invoked in RTEMS. I can't tell out of
>>>my head as for historical reasons I do it manually in my projects, not
>>>using RTEMS standard ways. I.e., I have my own routine that calls all
>>>the functions put into the table referenced to by __CTOR_LIST__ and call
>>>it before main().
>>
>>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? 
> 
> 
> Well, all that is in fact some g++ magic that I still don't quite
> understand, but the essence is that the routines which addresses are
> given in the ctor table should be called in turn at startup. Here is how
> I do it. Please note that my ctor table is built somewhat different,
> i.e., in the linker script:
> 
>   /* Table of global constructors (to be called on startup). */
>   .ctors : {
>     __CTOR_LIST__ = .;
>     KEEP(*(SORT(.ctors.*)))
>     KEEP(*(.ctors))
>     __CTOR_END__ = .;
>   } > ROM
> 
> so that there is no "number of pointers" field in the beginning of the
> table. Please also note that my code calls them top-to-bottom, and AFAIK
> g++'s way is to call bottom-to-top.
> 
> Here is the code:
> 
> /* Single entry in the CTOR table.  */
> typedef void (*Ctor) (void);
> 
> /* Begin and end markers of CTORS table. */
> extern Ctor const __CTOR_LIST__[];
> extern Ctor const __CTOR_END__[];
> 
> /* Call global constructors according to CTOR table */
> static void ctors(void)
> {
>   Ctor const* ptr = __CTOR_LIST__;
>   Ctor const* end = __CTOR_END__;
>   for ( ; ptr != end; ptr++)
>     if (*ptr)
>       (*ptr)();
> }
> 
> 
>>Also, are these c++ objects supposed to be in the .bss section?
> 
> 
> I don't believe it's essential, what's essential is that the section
> must be read-write, i.e., you can't put C++ objects but PODs into ROM.

PODs?

Anyhow, thanks for the code. I put it in my init.c and I now see some 
constructors being called by it.  However, for some reason, I don't see 
the constructor for the class with the virtual function that I am 
wanting to be called. The class variable is declared static and it's 
constructor is in the the same cpp file. When I dump the object for the 
cpp file I see a .ctor section of size 4 and the constructor of interest 
is in a ".gnu.linkonce.t..." type of section. But the address of the 
constructor never seems to make it to the final .ctor table since when 
it goes through your code it never calls the constructor of interest.

I also changed my linkcmds file (in the libbsp area) as you show. All I 
did was re-install rtems and it put linkcmds to the right place in the 
install area, /opt/rtems-4.6. Then I forced a relink of my app. That 
seem like enough but maybe I need to make clean all, make install rtems 
and rebuild clean my app. Takes a while but I will do it now.

Tks,
-gene






More information about the users mailing list