剥离未使用的运行时功能,其可膨胀可执行(GCC) [英] Strip unused runtime functions which bloat executable (GCC)

查看:202
本文介绍了剥离未使用的运行时功能,其可膨胀可执行(GCC)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经为ARM(cortex-m3)构建了GCC4.7.1交叉工具链。现在我链接一个C / C ++代码的可执行文件,肯定不会使用某些STL类(例如 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 命名空间中唯一剩下的是

 类型大小类
T 58'__gnu_cxx :: recursive_init_error'
/ pre>

这是另一个例外类。






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 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.

解决方案

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆