剥去膨胀可执行文件(GCC)的未使用的运行时函数

πάν*_*ῥεῖ 7 c++ embedded gcc cross-compiling

我为ARM(cortex-m3)构建了GCC4.7.1交叉工具链.现在,我正在链接C/C++代码中的可执行文件,肯定不会使用某些某些STL类(例如std::string).此外,例外和RTTI被关闭.

当我寻找到目标ELF(使用纳米如)虽然,有挂在我不希望找到有(如大量的符号(apparantly从的libstdc ++) std::exception,std::ios_base等等).

为什么会出现这种情况,如何摆脱这些东西以减少.text目标的截面尺寸?

一位同事给了我一个提示,以覆盖一些GCC特定的存根函数:

namespace __gnu_cxx
{
    void __verbose_terminate_handler()
    {
        for (;;)
            ;
    }
}
Run Code Online (Sandbox Code Playgroud)

仅此一项就将代码大小减少了大约20KB.
我可以覆盖更多这样的存根吗?


更新:
好的,我发现了一个非常愚蠢的错误,删除了我想知道的大部分内容,修复它时:在其中一个源文件中
有一条#include <iostream>语句(尽管没有任何调用).在静态课程链接的这种意志std::cin,std::cout以及std::cerr实例和所有的东西,这些走来.
删除该#include <iostream>语句会使该.text段减少大约100KB的部分.


然而:
目前仍然在std::exceptionstd::basic_string我想知道有关的东西:

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> >'
Run Code Online (Sandbox Code Playgroud)

使用的代码大小并不多,只有大约100个字节,所以我可以忽视它,但是如果我能摆脱它,我会很感激.

由于我明确地使用了没有例外,我想知道为什么这些在链接时仍然被实例化.是否在运行时确定是否使用异常?!?我现在留下
__gnu_cxx命名空间中唯一剩下的就是

Type         Size Class 
T              58 '__gnu_cxx::recursive_init_error'
Run Code Online (Sandbox Code Playgroud)

这是另一个例外类.


最后:
我使用了一些额外的标志来配置GCC4.7交叉构建:

--enable-gold=yes 
--enable-lto 
--enable-cxx-flags='-fno-exceptions -ffunction-sections -fno-omit-frame-pointer'
Run Code Online (Sandbox Code Playgroud)

后面的标志用于编译libstdc ++,基本上与用于构建目标代码的标志相同(无论如何这是一个合理的操作).之后消失的异常引用(包括__gnu_cxx::recursive_init_error).

最后一件事是,我std::string在代码库中发现了意外的使用.修好之后,参考std::basic_string<char, std::char_traits<char>, std::allocator<char> >也消失了.

所以我现在对结果感到满意,没有更多不必要的,来自libstdc ++的意外开销,没有理由不优先使用C++而不是C.

πάν*_*ῥεῖ 2

为什么会出现这个,我怎样才能摆脱这些东西以减少.text目标的部分大小?

可能存在从 链接的内容的(静态)引用libstdc++,无论它们是否在实际执行的代码路径中被调用或引用,这些引用都会被实例化。
仔细搜索包含#include此类引用声明的语句的用法(例如#include <iostream>)。

当在libstdc++安装 GCC 期间使用用于最终预期目标的不同 C++ 编译标志进行构建时,可能会链接或实例化不需要的内容(例如,__gnu_cxx::recursive_init_error尽管使用了该标志,但仍存在异常类-fno-exceptions)。构建工具链时,使用--enable-cxx-flags配置选项与预期目标编译标志同步。

还要仔细检查代码库中某些 STL 类的不需要/意​​外的使用(例如std::string),它们可能会编译并链接而不会出现错误或警告,尽管某些功能(例如new())在您的裸机平台上并不真正受支持。

还有更多这样的存根我可以覆盖吗?

根据工具链的“newlib”构建方式(请参阅--en/disable-newlib-supplied-syscalls配置选项),可能需要覆盖其中提供的某些或所有存根。