This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

How to enable C++ exception support for an embedded newlib PowerPC target


Hi all:

I am building a GCC 4.5.3 cross-compiler for an embedded PowerPC target, together with binutils-2.21 and newlib 1.19.0, and I have found it difficult to collect all the necessary information on how to enable C++ exception support.

I am writing this message as I wanted to share that information with other embedded GCC users.

These instructions are for GCC 4.5.3, your mileage with other versions may vary.

There are 2 ways to manually enable C++ exception support for an embedded target:

a) The old way (thanks to Oman for this information):

1) Add to your linker script file the following:

    .eh_frame ALIGN(0x4):
    { 
      PROVIDE (__eh_frame_start = .);
      KEEP(*(.eh_frame))
      LONG (0);
    } > ram

    .gcc_except_table : { *(.gcc_except_table) *(.gcc_except_table.*) } >ram

2) Add to your main() routine the following:

     extern char __eh_frame_start[];  // Defined in our linker script file, see above.

     extern "C" void __register_frame ( void * );  // Copied from GCC 4.5.3, it's not exported in any header file and therefore could change unnoticed!

     extern "C" int main ( void or whatever... )
     {
       // Note that GCC generates a hidden call to __eabi() at this point for PowerPC EABI targets.

       __register_frame( &__eh_frame_start );

      ...
     }
    
Actually, you should call __register_frame() before any C++ constructors get called, which may happen before main() if you declare global static objects. The right to do that is to call __register_frame() from your crt0 assembly code before calling main().

The code above works for me because I've always avoided declaring global static C++ objects, not just because __register_frame() gets called a little too late, but because it's hard to guarantee the order in which those static objects will be initialised. I tend to declare pointers to those objects instead and then allocate/initialise them inside main(). That way, you get to see in the source code the explicit initialisation sequence.

Despite that precaution, note that this isn't a water-tight solution, as the C++ run-time library itself, or some other C++ library you might be using, might be triggering C++ constructor calls for static objects they might define.

3) Be aware of the following pitfalls:

- __register_frame() does a malloc() and does not check whether there was enough memory (!), at least in GCC 4.5.3.
Therefore, support for malloc() has to be active before calling __register_frame().

- The exception tables are sorted the first time an exception is thrown. That means that the first C++ exception thrown will take much longer to process.

- The exception table sorting is not thread safe, unless you have managed to configure GCC with some thread model that ends up using your embedded target's thread locking support.

b) The new way. This involves using linker switch --eh-frame-hdr , but I haven't managed to get it to work yet for an embedded newlib target.

Regards,
  R. Diez


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]