Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strip unused runtime functions which bloat executable (GCC)

I have build the GCC4.7.1 cross-toolchain for ARM (cortex-m3). Now I'm linking an executable from C/C++ code that surely doesn't use some certain STL classes (e.g. std::string). Furthermore exceptions and RTTI are turned off.

Though when I'm looking to the target ELF (e.g. using nm), there's a lot of symbols (apparantly from the libstdc++) linked in I wouldn't expect to find there (e.g. std::exception, std::ios_base, etc.).

Why is this there, and how can I get rid of this stuff to reduce the .text section size of my target?

A coworker gave me a tip to override some GCC specific stub function:

namespace __gnu_cxx
{
    void __verbose_terminate_handler()
    {
        for (;;)
            ;
    }
}

This alone reduced the code size about 20KB.
Are there more such stubs I can override?


UPDATE:
OK, I found one really stupid error that removed most of the stuff I was wondering about, when fixing it:
There was an #include <iostream> statement left (though nothing called from there) in one of the source files. This will of course link in the static std::cin, std::cout and std::cerr instances and all the stuff that comes along with these.
Removing the #include <iostream> statement reduced the .text segment about another > 100KB portion.


Nevertheless:
There's still the std::exception and std::basic_string stuff I'm wondering about:

Namespace summaries:
==============================================================================
Type         Size Namespace 
T             774 'std'
W             184 'std::string::_Rep'
W             268 'std'
W             472 'std::string'
Class summaries:
==============================================================================
Type         Size Class 
T              50 'std::error_category'
T              52 'std::type_info'
T              54 'std::bad_exception'
T              54 'std::exception'
T              68 'std::bad_alloc'
T              98 'std::length_error'
T             214 'std::logic_error'
W             268 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >'

There isn't really much code size used, just about several 100 bytes, so I could live with neglecting it, but would appreciate, if I can get rid of this also.

Since I'm explicitly using no exceptions I wonder why these are still instantiated when linking. Usage of exceptions or not can't be really determined at runtime?!?
The only remaining thing from the __gnu_cxx namespace I have left now is

Type         Size Class 
T              58 '__gnu_cxx::recursive_init_error'

It's another exception class.


FINALLY:
I used some additional flags to configure the GCC4.7 cross build:

--enable-gold=yes 
--enable-lto 
--enable-cxx-flags='-fno-exceptions -ffunction-sections -fno-omit-frame-pointer'

The latter flags are used to compile the libstdc++ and are essentially the same as used for building the target code (which is a reasonable action anyway). Exception references where gone afterwards (including the __gnu_cxx::recursive_init_error).

Last thing was, I found an unexpected use of std::string in our codebase. After fixing that, the reference to std::basic_string<char, std::char_traits<char>, std::allocator<char> > also disappeared.

So I'm happy with the result now, no more unnecessary, unexpected overhead from libstdc++, no reason not to use C++ in preference over C.

like image 275
πάντα ῥεῖ Avatar asked Sep 13 '13 16:09

πάντα ῥεῖ


1 Answers

You can never know what using one of library functions will pull in. Well, actually you probably can by creating call graph with one of the tools. So what part of c++ std library are you using?

Other than that, I have had success in removing unneeded function from executable by using two methods (none of this on ARM, but methods are not ARM specific):

  1. Compile with -ffunction-sections switch, then link with -gc-sections. This puts each function into it's own section and then tells linker to remove unused sections.
  2. Use link time optimization (-flto, see gcc manual for details). This lets compiler see "whole" program as if it was single source and will probably let it remove unused functions.

You are already using -Os, right?

like image 189
dbrank0 Avatar answered Oct 01 '22 18:10

dbrank0