I am developing firmware for an embedded application on ARM Cortex-M in C++ with GCC 7.3.1 in C++14 mode. There's only 64k of flash available, and my binary wouldn't fit. Looking at the map file I see that there's a function called __gcclibcxx_demangle_callback in the binary that takes up 27k flash space. I understand that this is related to C++ name demangling. The linker doesn't discard this symbol although I'm definitely not doing any name demangling in my code. I'm using STL here and there though. How can I eliminate this function to gain some flash space?

I've tried passing -ffreestanding -fno-exceptions -nostartfiles -fno-rtti to the compiler and the linker. Passing -nostdlib causes the linking to fail even if I pass -lc -lg -lgcc -lstdc++.

2 Answers

Community On Best Solutions

@Russ Schultz's comment got me thinking. Very probably it really was some STL code that used name demangling, and it would have been surprising if there was no other libstdc++ that was more suitable for embedded systems. Apparently, the GNU Arm Embedded Toolchain provides alternate versions of libstdc++. One is the "nano" version which can be easily used by passing -specs=nano.specs to the linker. This reduces the size of the resulting binary drastically (115k to 45k), and roughly looking at the contents, it really includes only necessary symbols. Almost no code bloat apart from some C++ vtables which are tiny anyway.

l.k On

More options:

-Os -flto  -fno-fat-lto-objects -fuse-ld=gold -fuse-linker-plugin \
-Wl,--icf=all -Wl,--icf-iterations=4 -Wl,--gc-sections -Wl,--as-needed \
-Wl,--strip-all -Wl,-O3 -Wl,--orphan-handling=discard -Wl,--no-eh-frame-hdr \
-Wl,--no-ld-generated-unwind-info -fno-unwind-tables

error corrected
(--icf is specific to "gold")

I'm just learning how myself, but if that doesn't do it you can start modifying the linker script... you can add an "implicit" linker script to the standing defaults by passing it on the link line (ld tries to read anything that doesn't look like object code as a script). My best guess is you'll want to assign the problem library to its own section, then discard it: >

The linker will ignore address assignments (*note Output Section Address::) on discarded output sections, except when the linker script defines symbols in the output section. In that case the linker will obey the address assignments, possibly advancing dot even though the section is discarded.

The special output section name '/DISCARD/' may be used to discard input sections. Any input sections which are assigned to an output section named '/DISCARD/' are not included in the output file.

I feel like this really shouldn't be it, but there's also --no-demangle...

edit: if you're trying to compile with -nostdlib you might need some combination of -lgcc_s -lsupc++ -lm, -B `your/compiler/dir`, etc