了解地图文件,优化尺寸

时间:2016-04-16 18:23:03

标签: c gcc compilation makefile linker

最近我意识到我的可执行文件的大小非常大。我正在使用Eclipse和GCC为Cortex-M微控制器开发软件。

为了解决这个问题,我使用了一个我在互联网上找到的示例项目,通过直接操作寄存器来简单地闪烁LED,这是基于makefile的。

我使用我的库,启动代码,链接器脚本等使用Eclipse的托管makefile创建了一个非常相似的项目。

第一个项目编译成功,并生成了一个app的二进制文件。 6KB。第二个项目产生了一个app.48kB的二进制文件!对于基本相同的结果来说,这显然是一个很大的差异,而后者肯定是一个巨大的文件,只是闪烁LED。在这两种情况下,优化都已关闭。

在我自己的库中,有一些易失性缓冲区,可能是大型BSS或数据部分的借口,所以我决定首先专注于文本部分(仍然是5kB到27kB的5倍)

我看了一下map文件,看看究竟是什么链接到了二进制文件。相同或类似的功能也具有相似的尺寸。

有一件事对我来说似乎非常奇怪。在整个项目中只有一次定义的函数,但似乎已经多次链接,每次都来自不同的目标文件,每次都占用文本部分的空间。看一下示例来运行.text.port_lock

这是正常的吗?如何减少最终文件大小,如何告诉工具链只链接每个函数?

The map file

修改 正如评论中所述,两个程序没有区别,只需稍加修改(例如启动代码和访问GPIO寄存器的功能)即可。我没有测试GCC优化代码的能力,因此我使用了-O0。我试着理解地图文件,以及为什么我多次看到一些函数。

1 个答案:

答案 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

读取链接器映射文件通常是调查符号和部分的笨重方式 在你的二进制文件中。首选objdumpreadelfnm