如何防止 C++ 名称分解函数包含在二进制文件中

问题描述 投票:0回答:3

我正在使用 C++ 和 GCC 7.3.1 在 C++14 模式下为 ARM Cortex-M 上的嵌入式应用程序开发固件。只有 64k 可用闪存,我的二进制文件不适合。查看映射文件,我发现二进制文件中有一个名为

__gcclibcxx_demangle_callback
的函数,占用了 27k 闪存空间。据我了解,这与 C++ 名称解析有关。尽管我绝对没有在代码中进行任何名称解析,但链接器不会丢弃此符号。不过我到处都在使用STL。如何消除此功能以获得一些闪存空间?

我尝试将

-ffreestanding -fno-exceptions -nostartfiles -fno-rtti
传递给编译器和链接器。即使我通过了
-nostdlib
,通过
-lc -lg -lgcc -lstdc++
也会导致链接失败。

c++ gcc g++ embedded
3个回答
1
投票

更多选项:

-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

已更正错误

--icf
特指“黄金”)

我只是在学习自己的方法,但如果这不起作用,您可以开始修改链接描述文件...您可以通过在链接行上传递它来将“隐式”链接描述文件添加到常规默认值中(ld尝试读取任何看起来不像目标代码的脚本)。 我最好的猜测是您需要将问题库分配到其自己的部分,然后丢弃它: >

链接器将忽略地址分配(*注意输出部分 地址::) 位于丢弃的输出节上,链接描述文件除外 定义输出部分中的符号。 在这种情况下,链接器将 遵守地址分配,即使在 部分被丢弃。

特殊输出节名称“/DISCARD/”可用于丢弃 输入部分。 分配给输出的任何输入部分 名为“/DISCARD/”的部分不包含在输出文件中。

我觉得确实不应该是这样,但也有

--no-demangle
...

编辑:如果您尝试使用

-nostdlib
进行编译,您可能需要
-lgcc_s -lsupc++ -lm
-B `your/compiler/dir`
等的某种组合


0
投票

@Russ Schultz 的评论让我思考。很可能确实是一些使用名称重组的 STL 代码,如果没有其他更适合嵌入式系统的 libstdc++,那将是令人惊讶的。显然,GNU Arm 嵌入式工具链提供了 libstdc++ 的替代版本。一种是“nano”版本,可以通过将

-specs=nano.specs
传递给链接器来轻松使用。这极大地减少了生成的二进制文件的大小(115k 到 45k),并且粗略地查看内容,它实际上只包含必要的符号。除了一些很小的 C++ vtable 之外,几乎没有代码膨胀。


0
投票

如果您无法切换到其他 C++ 库,您可以重建工具链以使用

--disable-libstdcxx-verbose
配置 libstdc++。 根据 libstdc++ 手册 :

默认情况下,库被配置为将描述性消息写入标准错误[...]这些消息导致库依赖于demangler和标准I/O设施,这在低内存环境或当标准错误不可用时。此选项会禁用这些消息。

使用此选项可以让我节省 60kB 的固件大小

© www.soinside.com 2019 - 2024. All rights reserved.