Embedded 减小可执行文件大小的过程
我正在生成一个在ARM处理器上运行的十六进制文件,我希望它保持在32K以下。它现在比这个大很多,我想知道是否有人会对瘦身的最佳方法有一些建议 这是我到目前为止所做的Embedded 减小可执行文件大小的过程,embedded,arm,Embedded,Arm,我正在生成一个在ARM处理器上运行的十六进制文件,我希望它保持在32K以下。它现在比这个大很多,我想知道是否有人会对瘦身的最佳方法有一些建议 这是我到目前为止所做的 所以我对它运行了“size”来确定十六进制文件有多大 然后再次“调整大小”,查看链接到创建十六进制文件的每个对象文件有多大。似乎大部分的大小来自外部库 然后我使用readelf来查看哪些函数占用的内存最多 我搜索了代码,看看是否可以消除对这些函数的调用 这就是我遇到的问题,有些函数我不直接调用(例如,_vfprintf),我找不到调
- 正如我所看到的,调用的函数占用了大量内存。然而,我找不到什么叫它李>
- 我想省略这些函数(如果可能的话),但我找不到调用它们的内容!可以从任意数量的库函数调用
- 链接器按预期工作,我认为,它只包括相关的库文件。您如何知道是否只包含相关功能?你能为那件事插个旗子什么的吗
- 我正在使用GCC
一个好的链接器应该只具有所需的功能。但是,您可能需要编译器和链接设置来打包单个链接的函数。好的,所以最后我只是将项目简化为最简单的形式,然后慢慢地逐个添加文件,直到要删除的函数出现在“readelf”文件中。然后,当我有了这个文件后,我把所有的东西都注释掉,然后慢慢地把东西添加回去,直到函数再次弹出。所以最后我找到了它的名字并删除了所有的电话…现在它可以正常工作了…太棒了 但必须是一种更好的方法。常规列表:
- 确保已禁用编译器和链接器调试选项
- 在所有大小选项都打开的情况下编译和链接(-gcc中的Os)
- 在可执行文件上运行
strip
- 生成映射文件并检查函数大小。您可以让链接器生成映射文件(
当使用ld时),也可以在最终的可执行文件上使用objdump(注意,这只适用于未压缩的可执行文件!)这实际上不会解决问题,但会让您知道最坏的违规者-M
- 使用
调查从每个对象文件调用的符号。这将有助于找到谁在调用您不希望调用的函数nm
如果您是针对其他库进行静态链接,您也可以在这些库上运行上面列出的工具,以确保它们遵循类似的规则。另一个可能节省您工作的优化是-ffunction节,-Wl,-gc节,假设您使用的是GCC。不过,一个好的工具链不需要被告知这一点
说明:GNULD链接节,GCC每个翻译单元发送一节,除非您另有说明。但是在C++中,DENDEXY图中的节点是对象和函数。在深入嵌入的项目中,< P>总是试图避免使用任何标准库函数。即使像“strtol()”这样的简单函数也会放大二进制大小。如果可能的话,尽量避免打那些电话 在大多数深度嵌入的项目中,您不需要多功能的“printf()”或动态内存分配(许多控制器的RAM不超过32kb)
我使用了一个非常简单的自定义“printf()”,而不是仅仅使用“printf()”,这个函数只能打印十六进制或十进制格式的数字,不能打印更多。大多数数据结构都是在编译时预先分配的。Andrew EdgeCombe有一个很好的列表,但是如果您真的想刮除最后的每个字节,它是一个很好的工具,但是列表中缺少了这个工具,并且可以节省更多的kB 例如,在
strip
本身上运行时
来自旧自述文件(请参阅间接源文件顶部的注释):
sstrip是一个小型实用程序,它可以删除文件末尾的内容
不是程序内存映像一部分的ELF文件
大多数ELF可执行文件都是使用程序头表和
节标题表。然而,只有前者才是必要的
让操作系统加载、链接和执行程序。sstrip试图
提取ELF头、程序头表及其内容,
把其他的东西都放在桶里。它只能移除零件
在要保存的零件之后的末尾出现的文件。然而,
这几乎总是包括节标题表