我正在生成一个在ARM处理器上运行的hex文件,我想保持在32K以下.它目前比这大得多,我想知道是否有人可能会对减肥的最佳方法有什么建议?
这是我到目前为止所做的
所以我在它上面运行'size'来确定hex文件有多大.
然后'size'再次查看每个目标文件有多大,该链接用于创建十六进制文件.似乎大多数大小来自外部库.
然后我使用'readelf'来查看哪些函数占用了大部分内存.
我搜索了代码,看看是否可以消除对这些函数的调用.
这是我卡住的地方,有一些我不直接调用的函数(例如_vfprintf),我找不到调用它的所以我可以删除调用(因为我认为我不需要它).
那么接下来的步骤是什么?
回答答案:
正如我所看到的,有些函数被调用占用大量内存.然而,我无法找到所谓的内容.
我想省略那些功能(如果可能的话),但我找不到它们的名字!我想可以从任意数量的库函数调用.
链接器正在按需工作,我认为它只包含相关的库文件.您如何知道是否仅包含相关功能?你可以为此设置旗帜吗?
我正在使用GCC
Andrew Edgec.. 14
一般清单:
确保禁用了编译器和链接器调试选项
编译并链接打开的所有大小选项(gcc中的-Os)
运行strip
可执行文件
生成地图文件并检查您的功能大小.您可以让您的链接器生成您的映射文件(-M
使用ld时),或者您可以在最终的可执行文件上使用objdump(请注意,这只适用于未提取的可执行文件!)这实际上不会解决问题,但它会让你知道最严重的罪犯.
使用nm
调查从每个对象文件中的所谓的符号.这应该有助于找到你不想调用的函数.
原始问题是关于仅包括相关功能的子问题.gcc
将包括所使用的每个目标文件中的所有函数.换句话说,如果你有一个包含10个函数的目标文件,即使实际调用了1个函数,所有10个函数都包含在你的可执行文件中.
标准库(例如libc)将函数拆分为许多单独的目标文件,然后存档.然后将可执行文件链接到存档.通过拆分成许多目标文件,链接器只能包含实际调用的函数.(这假设你是静态链接)
你没有理由不能做同样的伎俩.当然,您可以争辩说,如果没有调用函数,您可以自己删除它们.
如果您静态链接到其他库,您也可以运行上面列出的工具,以确保它们遵循类似的规则.
一般清单:
确保禁用了编译器和链接器调试选项
编译并链接打开的所有大小选项(gcc中的-Os)
运行strip
可执行文件
生成地图文件并检查您的功能大小.您可以让您的链接器生成您的映射文件(-M
使用ld时),或者您可以在最终的可执行文件上使用objdump(请注意,这只适用于未提取的可执行文件!)这实际上不会解决问题,但它会让你知道最严重的罪犯.
使用nm
调查从每个对象文件中的所谓的符号.这应该有助于找到你不想调用的函数.
原始问题是关于仅包括相关功能的子问题.gcc
将包括所使用的每个目标文件中的所有函数.换句话说,如果你有一个包含10个函数的目标文件,即使实际调用了1个函数,所有10个函数都包含在你的可执行文件中.
标准库(例如libc)将函数拆分为许多单独的目标文件,然后存档.然后将可执行文件链接到存档.通过拆分成许多目标文件,链接器只能包含实际调用的函数.(这假设你是静态链接)
你没有理由不能做同样的伎俩.当然,您可以争辩说,如果没有调用函数,您可以自己删除它们.
如果您静态链接到其他库,您也可以运行上面列出的工具,以确保它们遵循类似的规则.
假设您正在使用GCC,另一个可能为您节省工作的优化是-ffunction-sections,-Wl,-gc-sections.不过,一个好的工具链不需要被告知.
说明:GNU ld链接部分,GCC每个翻译单元发出一个部分,除非你另有说明.但在C++中,依赖图中的节点是对象和函数.