Skip to content

Docker container that can build gcc-arm-none-eabi with an additional nano_eh library that supports exception-handling.

Notifications You must be signed in to change notification settings

tgree/docker-gcc-arm-none-eabi-nano_eh-build

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 

Repository files navigation

gcc-arm-none-eabi-nano-eh

This Docker image allows you to build the standard gcc-arm-none-eabi compiler
and infrastructure with an additional set of "nano_eh" libraries that can be
used in place of the normal "nano" libraries.  The nano_eh libraries have
exception-handling enabled so that C++ exceptions can be used in your
firmware.  The support code required for C++ exceptions can add around 8-9K in
size to your binary, and you will also have variable-length exception tables
included depending on how large your firmware is, so this could considerably
increase the size of your firmware image on small systems.

The tools built with this Docker image will behave exactly the same as their
official counterparts when working with non-nano_eh libraries.  The MD5 sum of
the generated executable in such cases will be identical to the MD5 sum of the
executable generated by the official compiler.  This means that the generated
code, data layout and other sections in the built executable match what the
official compiler builds, so you can be confident that the compiler is stable.

To achieve this reproducibility, the ARM build scripts have been extended to
allow specifying the "release date" of the compiler.  Normally, today's date
would be used when doing a new compiler build, however that generates a string
that is embedded in the compiler and later embedded in .comment sections of the
generated executable.  If that string doesn't match the string used by the
original, official compiler build then the MD5 sum of generated binaries will
no longer match those of binaries generated by the original compiler, even if
everything else in the binary is identical.  To achieve reproducibility, when
building the compiler the new --release_date option should be specified with a
YYYYMMDD value that matches the build date of the original compiler.

To build the nano_eh library versions, a new clause has been added to the
build-toolchain.sh file.  This one is similar to the clause that builds the
regular "nano" libraries, however it omits the "--fno-exceptions" target flag.
This has the effect of including exception tables in the target libraries
which are required for exception-handling to work.  The regular nano libraries
include all of the code required to perform exception-handling, however the
ommission of the exception tables means that all exceptions are destined to
fail immediately because the first function that must be unwound when throwing
an exception is in the libsupc++ library - which was just built without
exception tables.

If exception tables are the only difference, then one would ask why they
aren't just turned on by default and then everyone could just link against an
official nano_eh version.  Well, there are some other minor differences in the
built libraries.  There are some "noexcept" functions defined in the standard
libraries which trigger __gxx_personality routines to be pulled in when built
with exeptions enabled - these handle the case where an exception would escape
a noexcept function.  This, in turn, pulls in that extra 8-9K of exception-
handling code that you wouldn't typically want in a small binary.  Finally,
there are some conditionally-compiled _try and _catch macros in libsupc++ that
behave differently if exceptions are enabled or disabled.

With that all said and done, all you need to do to build all of this is build
the docker container and then run it:

cd docker
docker build -t gcc-arm-none-eabi-9-2020-q2-update-nano_eh-build .
docker run -ti gcc-arm-none-eabi-9-2020-q2-update-nano_eh-build
./build-gcc-arm-none-eabi-nano-eh.sh

This will build everything and you can find the result in the newly-created
~/pkg/ directory inside the docker container.  You can scp it to your desired
destination once it is built.

Now that you've built it all, how do you use it?  First you must install it,
in exactly the same way that you would install the officially-distributed
version.  A typical install may be done with the following command:

sudo tar x -C /usr --strip 1 \
    -f gcc-arm-none-eabi-9-2020-q2-update-nano-eh-x86_64-linux.tar.bz2

In your code, everywhere you were specifying some nano library (say,
libsupc++_nano.a) just replace it with the nano_eh equivalent (i.e.
libsupc++_nano_eh.a).  Typically this will be in your build scripts wherever
you invoke the linker; if you were using a nano.specs command instead then
there is a new nano_eh.specs file that should have equivalent functionality,
although this is untested since my projects link directly against specific
libraries using gnu ld (which doesn't support .spec files) rather than gcc.

Finally, if you are using a custom link script you must include the exception
tables.  Something like this works (replacing >FLASH with something suitable):

    .ARM.extab : ALIGN(0x10)
    {
        *(.ARM.extab* .gnu.linkonce.armextab.*)
    } >FLASH AT>FLASH

    .ARM.exidx : ALIGN(0x10)
    {
        __exidx_start = .;
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
        __exidx_end = .;
    } >FLASH AT>FLASH

If linking directly with gcc then these sections are likely included
automatically by default.

About

Docker container that can build gcc-arm-none-eabi with an additional nano_eh library that supports exception-handling.

Resources

Stars

Watchers

Forks

Packages

No packages published