【发布时间】:2021-05-17 12:06:10
【问题描述】:
【问题讨论】:
-
为什么要关心二进制文件中函数的顺序?这应该在你的问题中解释
-
@BasileStarynkevitch 教育目的,更好地了解内部原理
-
您应该联系法国的 Albert Cohen。给我发邮件,我知道他的。他的研究与你的非常接近。见this。艾伯特真的是一个非常好的人!
【问题讨论】:
GCC 可以更改函数的顺序,因为 C 标准(例如 n1570 或更新的)允许这样做。
GCC 没有义务将 C 函数编译为 ELF 格式意义上的单个函数。在 Linux 上查看 elf(5)
在实践中(启用优化:尝试使用gcc -Wall -fverbose-asm -O3 foo.c 编译foo.c,然后查看发出的foo.s 汇编程序文件),GCC 编译器正在构建像GIMPLE 这样的中间表示。大量优化正在将 GIMPLE 转变为更好的 GIMPLE。
一旦 GIMPLE 表示“足够好”,编译器会将其转换为 RTL
在 Linux 系统上,您可以使用 dladdr(3) 来查找离给定地址最近的 ELF 函数。您还可以使用backtrace(3) 在运行时检查您的call stack。
GCC 甚至可以完全删除函数,尤其是调用将被内联扩展的 static 函数(即使 没有任何 inline 关键字)。
我倾向于相信,如果你编译和链接你的整个程序与 gcc -O3 -flto -fwhole-program 一些非静态但未使用的函数也可以删除......
您可以随时编写自己的GCC plugin 来更改函数的顺序。
如果你想猜测 GCC 是如何工作的:下载并研究它的源代码(因为它是免费软件)并在你的机器上编译它,invoke 它与 GCC developer options,在GCC mailing lists 上提问。 .
另请参阅bismon 静态源代码分析器(一些正在进行的工作可能会让您感兴趣)和DECODER 项目。您可以通过电子邮件与我联系。您还可以为RefPerSys 做出贡献并使用它来生成 GCC 插件(C++ 形式)。
【讨论】:
从中可以得到什么?
优化。如果编译器认为某些代码会被大量使用,它可能会将该代码放在与预期不会经常执行的代码不同的区域(或者是错误路径,其中性能不那么重要)。并且可能在其他代码之后或临时附近执行的代码应该放在附近,因此在需要时更有可能在缓存中。
__attribute__((hot)) and __attribute__((cold)) 的存在出于某些相同的原因。
为什么toplevel-reorder默认值为true?
因为 99% 的开发人员都不会被这个默认设置所困扰,而且它可以让程序运行得更快。需要关心排序的 1% 的开发者使用属性、配置文件引导优化或其他可能与 no-toplevel-reorder 无论如何冲突的功能。
【讨论】:
foo 的一些“热”代码被移到它自己的部分,并且foo 出现在之前 bar 在源文件中,那么“hot-foo”部分可以在之后 bar