9

我创建了一个小程序作为要在嵌入式平台上实现的系统的概念验证。该程序是用 C++11 编写的,使用 std 并编译为在笔记本电脑上运行。稍后应该实现的最终程序是嵌入式系统。我们无权访问嵌入式平台的编译器。

我想知道当它应该移植到嵌入式平台时,是否有一种方法可以以合理且可比较的方式确定程序的静态内存(编译后的二进制文件的大小)。要求是二进制文件的大小小于 10kb。当使用以下标志编译和剥离时,我们的二进制文件大小为 700Kb:

g++ options:     -Os -s -ffunction-sections -fdata-sections
linker options:  -s -Wl,--gc-sections

strip libmodel.a -s -R .comment -R .gnu.version --strip-unneeded -R .note

在我们使用剥离和优化选项之前,它占用了 4MB。

我还有很长的路要走,它并不是一个真正的大程序。如何以任何方式与嵌入式平台上的等效程序进行比较。

4

2 回答 2

4

请注意,二进制文件的大小可能有点欺骗性,因为未初始化的变量(.bss 部分)不一定会占用二进制文件中的物理空间,因为它们通常只是被标记为存在而实际上没有给它们任何空间...这通常由操作系统加载程序在运行您的程序时发生。

objdump( http://www.gnu.org/software/binutils/ ) 或者elfdumpelf 工具链 ( http://sourceforge.net/apps/trac/elftoolchain/ ) 将帮助您确定各个段的大小,数据和文本,以及单个函数和全局变量的大小等。所有这些程序“查看”您编译的二进制文件并提取大量信息,例如 .text、.data 部分的大小,列出各种符号,它们的位置和大小,甚至可以分解 .text 部分...

在 ELF 图像 test.elf 上使用 elfdump 的示例可能是elfdump -z test.elf > output.txt. 这将转储包括文本部分反汇编在内的所有内容。例如,从elfdump我的系统上我看到

Section #6: .text, type=NOBITS, addr=0x500, off=0x5f168
             size=149404(0x2479c), link=0, info=0, align=16, entsize=1
             flags=<WRITE,ALLOC,EXECINSTR>
Section #7: .text, type=NOBITS, addr=0x24c9c, off=0x5f168
             size=362822(0x58946), link=0, info=0, align=4, entsize=1
             flags=<WRITE,ALLOC,EXECINSTR,INCLUDE>
....
Section #9: .rodata, type=NOBITS, addr=0x7d5e4, off=0x5f168
             size=7670(0x1df6), link=0, info=0, align=4, entsize=1
         flags=<WRITE,ALLOC>

所以我可以看到我的代码占用了多少(.text 部分)和我的只读数据。稍后在文件中,我看到...

Symbol table ".symtab"
         Value    Size     Bind Type Section                  Name
         -----    ----     ---- ---- -------                  ----
218      0x7c090  130      LOC  FUNC .text               IRemovedThisName

所以我可以看到我的函数IRemovedThisName占用了 130 个字节。一个快速脚本将允许您列出按大小排序的函数和按大小排序的变量。这可以为您指出要优化的地方...

有关objdump尝试http://www.thegeekstuff.com/2012/09/objdump-examples/的一个很好的示例,特别是第 3 节,它向您展示了如何使用该-h选项获取节标题的内容。

至于程序如何在两个不同的平台上进行比较,我认为您只需要在两个平台上编译并比较您obj/elfdump在每个系统上获得的结果 - 结果将取决于系统指令集,每个编译器可以优化的程度,一般硬件架构差异等。

如果您无法访问嵌入式系统,您可以尝试在笔记本电脑上使用为最终目标配置的交叉编译器。这将为您提供适合嵌入式平台的二进制文件和分析文件的工具(即 的跨平台版本objdump)。这将为您提供一些关于程序在最终嵌入式系统上的外观的大致数字。

希望这可以帮助。

编辑:这也将有助于如何从 C 程序内部或使用内联汇编获取 C 函数的大小?

于 2013-05-29T17:12:28.003 回答
1

似乎包含的库占用了巨大的空间(正如评论中指出的那样),通过删除这些库,可以结合以下标志将大小减少到几乎没有:

set(CMAKE_CXX_FLAGS "-Os -s  -ffunction-sections -fdata-sections -DNO_STD -fno-rtti -fno-exceptions")
set(CMAKE_EXE_LINKER_FLAGS "-s -Wl,--gc-sections")  

并使用以下方法删除任何不必要的代码:

strip libmodel.a -s -R .comment -R .gnu.version --strip-unneeded -R .note

4MB 可以减少到 9.4kb,低于我们的限制。

总之,std占用了大量的空间。

于 2013-05-29T20:29:54.170 回答