如何使用gcc工具链强制二进制函数的顺序?

Sec*_*Sec 7 linker gcc gnu

我正在从几个源文件和库中构建一个静态二进制文件,我想控制函数放入生成的二进制文件的顺序.

背景是,我有外部代码链接到这个二进制文件中的偏移量.现在,如果我更改源,所有偏移都会改变,因为gcc可能决定以不同的方式对函数进行排序,所以我想以固定的顺序将引用的函数放在开头,这样它们的偏移量保持不变......

我查看了ld的文档,但找不到任何关于函数顺序的信息.

我发现的唯一的东西是-fno-toplevel-reorder,这对我没有帮助.

Dam*_*mon 10

实际上没有干净可靠的方法将函数强制转换为特定地址(入口函数除外),甚至强制执行具有特定订单的函数(如果您可以强制执行仍然不意味着地址保持不变的顺序)当源被改变!).

我看到的最大问题是,即使可能将函数修复到某个地址,也几乎不可能将所有这些函数修复为已存在的外部程序所期望的地址(假设您无法修改此程序) ).如果这确实有效,那将是完全巧合和纯粹的运气.

在其他程序所期望的地址上提供蹦床可能几乎是最容易的,并且具有真实的功能(无论它们可能是什么).这将要求您的代码使用不同的基址,因此实际的程序代码不会与蹦床发生冲突.

有三件事几乎可以为函数提供固定地址:

  1. 您可以使用允许放置不允许在其正确部分中移动的每个函数__attribute__ ((section ("some name"))).不幸的是,.text总是显示为第一部分,因此如果有任何.text变化,因此大小超过512字节边界,您的偏移量将会改变.默认情况下(但请参阅下文),您无法在之前启动某个部分.text.
  2. -falign-functions=n命令行选项,您可以对齐功能的边界.通常这大约是16个字节.现在,您可以选择一个较大的值,例如1024.这将浪费大量的空间,但它也将确保只要函数仅适度改变,以下函数的地址将保持不变.显然它仍然不会阻止编译器/链接器在感觉到它时重新排序整个块(尽管-fno-toplevel-reorder会至少部分地阻止它).
  3. 如果您愿意编写自定义链接描述文件,则可以为每个部分分配起始地址.这些是虚拟内存地址,而不是可执行文件中的位置,但我认为硬链接也适用于VMA(基于默认图像库).所以这可能有点工作,虽然有很多麻烦而且不是很漂亮.
    当写你自己的链接脚本,你也可以考虑把那个不能移动的功能集成到自己的部分,并在可执行文件(在前面的开始移动这些部分.text),所以改变.text不会四处移动你的功能.

更新: "gcc"标签表明您可能会定位*NIX,所以这可能不会对您有所帮助,但是......如果您可以选择使用COFF,则美元符号部分可能会起作用(信息可能是对任何人都很有意思,无论如何).

我今天偶然发现了这个(强调我的):

"$"字符(美元符号)在目标文件的节名中有特殊解释.在确定将包含对象部分内容的图像部分时,链接器会丢弃"$"及其后面的所有字符.因此,名为.text $ X的对象部分实际上对图像中的.text部分有贡献.但是,"$"后面的字符决定了对图像部分的贡献顺序.具有相同对象部分名称的所有贡献在图像中连续分配,并且贡献块按字节顺序按对象部分名称排序.因此,在.text $ W贡献之后和.text $ Y贡献之前,部分名称.text $ X的目标文件中的所有内容都会一起结束.

如果文档没有说谎(如果我没有读错),这意味着你应该能够将你想要的所有功能打包到一个部分.text$A,以及其他所有内容.text$B,它应该只是.


Emp*_*ian 6

使用-ffunction-sections- 构建代码- 这会将每个函数放入其自己的部分.

如果您使用的是GNU-ld,链接描述文件将为您提供绝对控制,但这是一个非常特定于平台且有点痛苦的解决方案.

一个更好的解决方案可能是使用最近的工作gold,这使得完全功能命令你正在寻找.