【问题标题】:Understanding the map file, optimizing for size了解地图文件,优化大小
【发布时间】:2016-04-16 18:23:02
【问题描述】:

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

为了检查这一点,我使用了我在互联网上找到的一个示例项目,它只是通过直接操作寄存器来使 LED 闪烁,并且是基于 makefile 的。

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

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

在我自己的库中,有一些不稳定的缓冲区,这可能是大 BSS 或数据部分的借口,所以我决定从专注于文本部分开始(它仍然是 5kB 到 27kB 的 5 倍) .

我查看了映射文件以了解真正链接到二进制文件的内容。相同或相似的功能也有相似的大小。

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

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

The map file

编辑: 正如 cmets 中所述,这两个程序没有什么不同,它们是相同的,只是稍作修改(例如启动代码和访问 GPIO 寄存器的函数)。我没有测试 GCC 优化代码的能力,因此我使用了 -O0。我试图理解地图文件,以及为什么我多次看到某些功能。

【问题讨论】:

  • 所以要清楚,您是说您正在比较两个完全独立且执行相同(简单)功能的程序的编译大小?
  • GCC 有一个选项,-Os,可以针对较小的可执行文件进行优化。你可以考虑打开它。甚至-O1 在尺寸方面可能比根本没有优化做得更好。至于可执行映像中同一函数的多个副本——如果这确实是你所看到的——你并没有给我们太多继续。你能提供一个 minimal reproducible example 来展示这个问题吗?
  • 故意关闭优化。我不是在测试编译器优化代码的能力。我正在研究如何优化代码。这两个程序,没有什么不同。它们是相同的,只是有一些非常小的修改。问题是关于理解地图文件,以及我多次看到相同功能的方式。

标签: c gcc compilation makefile linker


【解决方案1】:

您误读了地图文件。没有出现.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

这是来自/home/fotis/Documents/Resources/Chibios/Chibios/Debug/libChibios.a(chcoreasm_v7m.o) 的输入.text 部分。

映射文件不包含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

【讨论】:

  • 这很清楚。看来我必须找到另一种方法来调查我是如何浪费空间的......
猜你喜欢
  • 1970-01-01
  • 2020-03-20
  • 2010-10-11
  • 2010-10-23
  • 2022-01-14
  • 1970-01-01
  • 2015-05-09
  • 2015-05-31
  • 2014-03-03
相关资源
最近更新 更多