g++arm none eabi从4.9升级到gcc 8.2.生成的二进制文件不再适合闪存



我最近将我的Linux笔记本电脑从Ubuntu 16.04更新到了18.04。

我有一个基于STM32(Cortex-M4)Makefile的项目,它使用Ubuntu提供的arm-none eabi g++版本正确编译。生成的文件在.text部分需要47620个字节。

随着Ubuntu的升级,我还安装了最新版本的gcc(来自ARM网站)。版本为8.2.1。

当我编译同一个项目(makeclean&&make)时,生成的二进制文件不适合flash(需要97424字节,超过两倍!)。该项目完全相同(源代码、链接脚本、启动文件、Makefile)。

编译器选项为:-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -DSTM32F303x8 -DARMCM4 -O0 -g -Wall -fexceptions -Wno-deprecated

链接器选项为-mthumb -mcpu=cortex-m4 -Tstm32f303K8.ld -mfloat-abi=hard -mfpu=fpv4-sp-d16 --specs=nosys.specs -lm -Wl,--start-group -lm -Wl,--end-group -Wl,--gc-sections -Lsys -Xlinker -Map=test.elf.map

当我查看.Map生成的文件时,所有用户函数的大小大致相同(新版本节省了8个字节!)。但之后,它包括C++特定的部分,其中一部分超过26Kb(来自地图文件): .text 0x00000000080079e8 0x683c /usr/local/gcc-arm-none-eabi-8-2018-q4-major/bin/../lib/gcc/arm-none-eabi/8.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libstdc++.a(cp-demangle.o) 0x000000000800e13c __cxa_demangle

注意:只使用C的项目没有问题,只使用C++。包含的库相同(gcc 4.9.3->armv7e-m/fpu和gcc 8.2.1->thumb/v7e-m+fp/hard): libm.a libstdc++.a libc.a libnosys.a libgcc.a

有没有一种方法可以摆脱这种情况,这样我就可以编译并闪存我的(没有那么旧的)项目?

问候,

我发现了一个使用libstdc++_nano(而不是隐式libstc++)的解决方案。这样,代码大小从84kb减少到26kb!

LDFLAGS += -lstdc++_nano

它只是起作用。感谢@Henrik、@Matthieu和@EOF的支持!

它可能与异常处理有关,因为用于异常的std::terminate()可能会调用解映射例程。如果您不需要异常,请尝试使用-fno-exceptions禁用它们,如下所述。

另一个解决方案可能是查看GCC标题:

降级例程。ABI在C++运行库中强制要求的用于解映射的入口点。[…]返回一个指针,指向NUL终止的解映射的开始name,如果解映射失败则为NULL。呼叫者是负责使用free释放此内存

原型是:

char*
__cxa_demangle(const char* __mangled_name, char* __output_buffer,
size_t* __length, int* __status);
因此,您可能只需要提供返回NULL的伪函数(假设所有库函数都是弱函数,并且可以被重写)。不过,我建议您先查看已分解的代码,并首先了解它是如何被调用的以及为什么被调用的,因为它可能会改变行为,只丢弃功能)。

他们也在这个论坛的帖子中给出了其他建议,这可能对你也有用:

  • 使用-Os而不是-O0优化大小(可能会添加-Og选项,如果您喜欢易于调试的代码,它通常比-O0更小更快)
  • 编译和链接时使用-flto在链接时进行优化
  • 如果不使用,可能会禁用RTTI

最新更新