剥离未使用的运行时功能,其可膨胀可执行(GCC) [英] Strip unused runtime functions which bloat executable (GCC)
问题描述
std :: string
)。此外,例外和RTTI关闭。 虽然我正在寻找目标ELF(例如使用nm),但是有很多符号(来自libstdc ++)链接在我不会期望找到那里(例如 std :: exception
, std :: ios_base
等)
为什么会这样,如何摆脱这些东西来减少 .text
我的目标的部分大小?
一个同事给了我一个提示来覆盖一些GCC特定的存根功能:
命名空间__gnu_cxx
{
void __verbose_terminate_handler()
{
for(;;)
;
}
}
这个单独减少了大约20KB的代码大小。 >
我可以覆盖更多这样的存根吗?
更新:
好的,我发现一个非常愚蠢的错误,删除了我想知道的大部分东西,当修复它:
有一个<$ c $其中一个源文件中的c> #include< iostream> 语句(尽管没有从中调用)。这当然会链接到静态的 std :: cin
, std :: cout
和 std :: cerr
实例以及与这些相关的所有内容。
删除 #include< iostream>
然而:
还有 std :: exception
和 std :: basic_string
我想知道的东西:
命名空间摘要:
======= ================================================== =====================
类型大小命名空间
T 774'std'
W 184'std :: string :: _Rep'
W 268'std'
W 472'std :: string'
类摘要:
============== ================================================== ============
类型大小类
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> ; >'
使用的代码大小没有太多,只有几百个字节,所以我可能会忽略它,但会感激,如果我也可以摆脱这一点。
由于我明确使用没有例外,我想知道为什么这些仍然被实例化链接。在运行时无法真正确定使用异常?!?
现在剩下的 __ gnu_cxx
命名空间中唯一剩下的是
类型大小类
/ pre>
T 58'__gnu_cxx :: recursive_init_error'
这是另一个例外类。
FINALLY:
我使用了一些额外的标志来配置GCC4.7交叉版本:- enable-gold = yes
--enable-lto
--enable-cxx-flags =' - fno-exceptions -function-sections -fno-omit-frame-pointer'
后一个标志用于编译libstdc ++,并且与用于构建目标代码基本相同是合理的行动)最后的事情是,我发现一个意想不到的例外情况(包括
__ gnu_cxx :: recursive_init_error
)
<在我们的代码库中使用std :: string
。修正后,引用std :: basic_string< char,std :: char_traits< char>,std :: allocator< char> < / code>也消失了。
所以我很高兴现在的结果,没有更多的不必要的,意外的开销从libstdc ++,没有理由不使用C ++优先于C。
解决方案
为什么会这样,我摆脱这个东西来减少我的目标的
.text
部分大小?
从
libstdc ++
链接的东西可能有(静态)引用,这将被实例化,无论它们是否在实际中被调用或引用执行的codepathes。
仔细搜索包含这种引用声明的#include
语句的使用(例如#include< iostream> $>
当使用不同的C ++编译标志安装GCC时,
libstdc ++
正在构建如用于最终目标的目标,可能有不想要的东西链接或被实例化(例如__ gnu_cxx :: recursive_init_error
异常类,尽管使用了-fno-exceptions
标志)。在构建工具链时,使用- enable-cxx-flags
配置选项与预期的目标编译标志同步。
还要仔细查看代码库中某些STL类的不必要/意外使用(例如
std :: string
),尽管它们可能会编译并链接而不会出现错误或警告,尽管某些功能(例如new()
)在您的裸机平台上并不真正支持。
是否有更多这样的存根可以覆盖?
根据'newlib'构建工具链(请参阅
- en / disable-newlib-provided-syscalls
配置选项),可能需要覆盖此处提供的某些或所有存根。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 staticstd::cin
,std::cout
andstd::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 thestd::exception
andstd::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 isType 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 tostd::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.
解决方案Why is this there, and how can I get rid of this stuff to reduce the
.text
section size of my target?There might be (static) references for stuff linked in from the
libstdc++
, that will be instantiated no matter if they are called or referenced in the actually executed codepathes.
Carefully search for usage of#include
statements that contain such reference declarations (e.g.#include <iostream>
).When
libstdc++
is build during installation of GCC with different C++ compile flags as used for the finally intended target, there might be unwanted stuff linked in or being instantiated (e.g. the__gnu_cxx::recursive_init_error
exception class despite usage of the-fno-exceptions
flag). Use the--enable-cxx-flags
configuration option to synchronize with the intended target compile flags when building the toolchain.Also look carefully for unwanted/unexpected usage of certain STL classes in your codebase (e.g.
std::string
), they might compile and being linked without errors or warnings, despite certain features (e.g.new()
) aren't really supported on your bare metal platform.Are there more such stubs I can override?
Depending on how 'newlib' was build for the toolchain (see
--en/disable-newlib-supplied-syscalls
configuration option), it might be necessary to override certain or all stubs provided there.这篇关于剥离未使用的运行时功能,其可膨胀可执行(GCC)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!