最近我意识到我的可执行文件的大小非常大。我正在使用Eclipse和GCC为Cortex-M微控制器开发软件。
为了解决这个问题,我使用了一个我在互联网上找到的示例项目,通过直接操作寄存器来简单地闪烁LED,这是基于makefile的。
我使用我的库,启动代码,链接器脚本等使用Eclipse的托管makefile创建了一个非常相似的项目。
第一个项目编译成功,并生成了一个app的二进制文件。 6KB。第二个项目产生了一个app.48kB的二进制文件!对于基本相同的结果来说,这显然是一个很大的差异,而后者肯定是一个巨大的文件,只是闪烁LED。在这两种情况下,优化都已关闭。
在我自己的库中,有一些易失性缓冲区,可能是大型BSS或数据部分的借口,所以我决定首先专注于文本部分(仍然是5kB到27kB的5倍)
我看了一下map文件,看看究竟是什么链接到了二进制文件。相同或类似的功能也具有相似的尺寸。
有一件事对我来说似乎非常奇怪。在整个项目中只有一次定义的函数,但似乎已经多次链接,每次都来自不同的目标文件,每次都占用文本部分的空间。看一下示例来运行.text.port_lock
。
这是正常的吗?如何减少最终文件大小,如何告诉工具链只链接每个函数?
修改 正如评论中所述,两个程序没有区别,只需稍加修改(例如启动代码和访问GPIO寄存器的功能)即可。我没有测试GCC优化代码的能力,因此我使用了-O0。我试着理解地图文件,以及为什么我多次看到一些函数。
答案 0 :(得分:2)
您误读了地图文件。没有出现.text.port_lock
,
例如,表示ChibiOS函数void port_lock(void)
的定义。
.text.port_lock
的所有出现都是指输入链接器部分。
前4次出现,位于标题为的地图文件部分内
Discarded input sections
,请参阅链接器的输入链接器部分
丢弃。例如:
.text.port_lock
0x00000000 0x1c /home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chmempools.o)
表示链接器找到大小为28字节的段.text.port_lock
在输入文件/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chmempools.o)
中
扔掉了。
接下来的6次出现,位于标题为的地图文件部分内
Linker script and memory map
都指的是输入链接器部分
映射到输出.text
部分。例如第一个:
.text.port_lock
0x000012a8 0x1c /tmp/ccaossic.ltrans0.ltrans.o
表示链接器找到大小为28字节的段.text.port_lock
在输入文件/tmp/ccaossic.ltrans0.ltrans.o
中
并将其映射到输出.text
部分的地址0x000012a8。同样地
第二次出现:
.text.port_lock
0x00001f70 0x1c /home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chsys.o)
表示在输入中也找到了相同名称和大小的输入节
档案/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chsys.o)
并映射到输出.text
部分的地址0x00001f70。
总共有.text.port_lock
个输入节,全部为28个字节,
从这些输入文件映射到输出.text
部分:
/tmp/ccaossic.ltrans0.ltrans.o
/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chsys.o)
/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chthreads.o)
/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chcore_v7m.o)
/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chmemcore.o)
/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chschd.o)
在所有这6种情况中,输入部分不包含符号,特别是 没有功能。相比之下,以下是 包含符号的输入部分的示例:
.text 0x000002f0 0x28 /home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chcoreasm_v7m.o)
0x000002f0 _port_switch
0x00000300 _port_thread_start
0x00000310 _port_switch_from_isr
0x00000314 _port_exit_from_isr
这是.text
的输入/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chcoreasm_v7m.o)
部分。
地图文件不包含port_lock
功能多次链接的指示。它包含没有
表明该功能完全相关。如果它被多次链接那么
将是一个多重定义链接错误(除非它有
被注释为weak symbol)。
为什么这六个不包含符号的28字节输入节都是链接的,或者它们是否相同
需要的是,我没有足够的证据或ChibiOS专业知识。我注意到
除了这些输入部分所来自的目标文件之外的所有文件都是
归档libChibios
的成员。在那种情况下,值得记住,如果你的联系
由于任何原因需要存档成员,然后默认情况下您将链接整个
存档成员,即使它包含的内容超出了您的需求。另一方面,事实
一些port_lock
输入部分被丢弃,一些被保留表明存在
需要保留那些保留的。如果出于我自己的狡猾原因,我会写一个源文件
基本上就像:
static int __attribute__((section(".text.foo"))) __attribute__((used))
boo(int i)
{
return i * 2;
}
int bar(int i)
{
return boo(i);
}
然后在我的地图文件中,您将看到一个名为.text.foo
的空输入部分。这个
没有告诉你关于我链接的符号的任何信息。
如何告诉工具链只链接每个函数?
链接器不会多次链接任何符号定义,特殊情况除外 弱符号的情况。您的地图文件不包含任何多次链接功能的证据。
如何减少最终文件大小?
当然,为您的版本编译-Os
。并尽量减少链接冗余,
见this question。