我正在使用GCC arm-none-eabi-g++
(4.8.3)编译ARM Cortex-M0 mcu的代码。
一切都很好,但我注意到当我包含并使用cstdlib
中的任何函数时,也会包含该文件中的所有函数。如何摆脱它们?
我仅呼叫malloc()
和free()
,但生成的ELF也有system()
和isatty()
个机器码。
mcu只有32kB的闪光灯,所以~0.7kB的镇流器非常重要,特别是如果这种情况一直发生在其他接头上。
现在我使用-ffunction-sections -fdata-sections
进行编译,并在链接时使用-Wl,--gc-sections -Wl,--static
,如下所示:
arm-none-eabi-g++ -c --std=c++11 -Os -I. -Ilpc1xxx -Idrivers -Wall -mthumb \
-ffunction-sections -fdata-sections -fmessage-length=0 -mcpu=cortex-m0 \
-DTARGET=LPC11xx -fno-builtin -flto -fno-exceptions -o main.o main.cpp
arm-none-eabi-gcc -c --std=c11 -Os -I. -Ilpc1xxx -Idrivers -Wall -mthumb \
-ffunction-sections -fdata-sections -fmessage-length=0 -mcpu=cortex-m0 \
-DTARGET=LPC11xx -fno-builtin -flto -o core_cm0.o lpc1xxx/nxp/core_cm0.c
arm-none-eabi-gcc -nostartfiles -mcpu=cortex-m0 -mthumb -Wl,--gc-sections -flto \
-Os -Wl,--static -T lpc1xxx/memory.ld -o firmware.elf main.o core_cm0.o \
libaeabi-cortexm0/libaeabi-cortexm0.a LPC11xx_handlers.o LPC1xxx_startup.o
编辑:警告:我的示例中的-flto
标志是错误的 - 它以某种方式丢弃了中断例程。
结果是,当我arm-none-eabi-objdump -t firmware.elf
时,我会得到其他人:
00000fbc g F .text 0000002c _isatty
00001798 g F .text 00000018 fclose
00000e4c g F .text 00000030 _kill
00000e7c g F .text 00000018 _exit
00000fe8 g F .text 00000050 _system
这些函数显然是多余的(在mcu上完全没用),但是GCC将它们保存在可执行文件中。没有调用它们,这些符号在任何地方都没有引用。它实际上是死代码。
如何摆脱它们?一些额外的编译器/链接器标志?
修改
重现我的问题的最小代码:
#include <cstdlib>
int main(){
[[gnu::unused]] volatile void * x = malloc(1);
return 0;
}
用于编译的命令:
arm-none-eabi-g++ --std=c++11 -Os -Wall -mthumb -ffunction-sections
-fdata-sections -fmessage-length=0 -mcpu=cortex-m0 -fno-builtin -flto
-fno-exceptions -Wl,--static -Wl,--gc-sections -o main.elf main.cpp
main.elf
文件仍然存在所有stdlib膨胀。
答案 0 :(得分:2)
在这里使用-ffunction-sections
是正确的,但问题是提供malloc
和free
的对象文件是在没有它的情况下构建的(LPC11xx_handlers.o
,{{ 1}}或LPC1xxx_startup.o
中的一些目标文件。在这种情况下,链接器只能包含整个目标文件(或libaeabi-cortexm0.a
,整个部分),其中包含您需要的功能。
目标文件和部分中的函数布局是唯一真正重要的事情,而不是在与另一个函数相同的头文件中定义哪个函数。
因此,要解决您的问题,请使用-Wl,--gc-sections
重建标准库文件。