How to disable all exceptions code when building with g++

Asked by d.ry

I'm using GNU ARM GCC bare bones toolchain, arm-none-eabi., version 5.4.1.
I'm using C++, and want to disable all exceptions from the code, and having some difficulties with it.
I basically just pass one option while building, the -fno-exceptions, and while it looks like does do some changes (i see binary
marginally smaller after enabling this), it does not remove exceptions completely.

One issue I'm having, is very early during runtime initialization. Looking at stack trace, the call to __libc_init_array() calls
 _GLOBAL_sub_|__cxa_allocate_exception() (which calls malloc() at some stage). I don't have sources for the library to see
exactly what it is but looks like some exception data trying to allocate something for self.

So that -fno-exceptions doesn't remove all exception handling code, i also see in the map file bunch of _cxa methods.

What is proper way to disable all exceptions code? I saw a thread here from 2012 someone mentioned that a special library build
is required to cleanly remove all exceptions. Is this available?

Question information

Language:
English Edit question
Status:
Solved
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Solved by:
Andre Vieira
Solved:
Last query:
Last reply:
Revision history for this message
Best Andre Vieira (andre-simoesdiasvieira) said :
#1

Hi d.ry,

Try adding --specs=nano.specs, this will tell the linker to link against our newlib-nano libraries which were built without exception support.

Hope that helps.

Cheers,
Andre

Revision history for this message
d.ry (d.ry) said :
#2

Hi Andre,

Thanks ! That definitely solved the above. It also almost half'ed the size of final binary. (Hope I won't loose some useful functionality :))

I had to however modify my linking command, because I specify every library I'm linking with using --start-group ... --end-group (I don't know why really, because the compiler should find it's libraries. But this is how the linking was setup with a RTOS i'm using)

 So after i replaced the libc, libsupc++ with _nano versions, it worked.

Thanks again

Revision history for this message
d.ry (d.ry) said :
#3

Thanks Andre Vieira, that solved my question.

Revision history for this message
d.ry (d.ry) said :
#4

Got another small related question:

I tried to remove specifying every single library, including c, c++ libraries, to linker with start/stop group, and rather let it pick what's needed, and pass the --specs=nano.specs.
It compiled, but failed at the linking stage, missing functions _kill, _getpid.

I added extra --specs=nosys.specs, and then it linked. The output is about 150 bytes larger.
Is it ok to use both specs at the same time? nosys seems to add extra small library to link against.
I saw that others solved the above linking problem by creating empty
functions _kill, _getpid (and couple of others it's missing) in the code, since they don't mean anything on a bare bones or RTOS based
system.

Revision history for this message
Andre Vieira (andre-simoesdiasvieira) said :
#5

Hi d.ry,

So what does your link command look like? '--specs=nano.specs' will merely tell it to use the nano versions of libc and libstdc++. You still need to link in the startup code and other syscall implementations that are needed. So yes usually --specs=nano.specs is used in combination with --specs=nosys.specs or --specs=rdimon.specs.

I guess in your case I would try to figure out where the dependencies on _kill and _getpid come from. I see rdimon's _exit implementation uses _kill, but since you are not using --specs=rdimon.specs you are probably using a different _exit implementation that probably uses _kill too. And as for _getpid I suspect a syscall you are linking against requires its implementation. The implementation of _getpid provided by '--specs=rdimon.specs' just returns 1.

Cheers,
Andre

Revision history for this message
Freddie Chopin (freddie-chopin) said :
#6

BTW there's always an option for alternate toolchain - I disable C++ exceptions in both "normal" and "nano" variants of the libraries.

https://github.com/FreddieChopin/bleeding-edge-toolchain

Revision history for this message
d.ry (d.ry) said :
#7

Hey,
I think dependencies for _kill and _getpid do not come from my RTOS based code, they must be coming from libc,c++ for gcc libs somehow.
Yes I also specify the no default startup. The RTOS came with a startup file, which does a few small things.
And no, _exit does not use _kill, its just
void _exit(int status)
{// disable all interrupts, run infinite loop
    __asm("cpsid i");
    while(1);
}

In my original linker settings I did not have problem those with _kill or _getpid. I had all libraries explicitly listed with --start/end-group, and options -nostdlib -nodefaultlibs -nostartfiles. The complete start/end libs would look like: (now with _nano)

--start-group ..rtoslib1 ... rtoslib2 ... /devel/gcc-arm-none-eabi-clibs/armv7e-m/fpu/libgcc.a /devel/gcc-arm-none-eabi/arm-none-eabi/lib/armv7e-m/fpu/libc_nano.a /devel/gcc-arm-none-eabi/arm-none-eabi/lib/armv7e-m/fpu/libsupc++_nano.a /devel/gcc-arm-none-eabi/arm-none-eabi/lib/armv7e-m/fpu/libm.a /devel/gcc-arm-none-eabi/arm-none-eabi/lib/armv7e-m/fpu/libnosys.a

So then I thought about your suggestion with flag -specs=nano.specs, i thought why am I specifying all those libs which compiler installation will find anyway. So I dropped them all, left only the rtobslibs, and -spec=nano.specs.

That gave me the missing _kill & _getpid. So they could actually may be come from _nano?. Adding the flag -spec=nosys.specs
solved it.
Thus i'm pretty convinced the _kill & _getpid ain't coming from any local code.