我正在使用几个源文件和库构建一个静态二进制文件,我想控制函数放入生成的二进制文件的顺序。
背景是,我有外部代码与这个二进制文件中的偏移量相关联。现在,如果我更改源,所有偏移都会改变,因为gcc可能决定以不同的方式对函数进行排序,所以我想以固定的顺序将引用的函数放在开头,这样它们的偏移量保持不变......
我查看了ld的文档,但找不到任何关于函数顺序的信息。
我发现的唯一的东西是-fno-toplevel-reorder,这对我没有帮助。
答案 0 :(得分:10)
实际上没有干净可靠的方法将函数强制转换为特定地址(入口函数除外),甚至强制执行具有特定顺序的函数(如果可以强制执行 order 那么当源被改变时,仍然不意味着地址保持不变!)。
我看到的最大问题是,即使可以将某个功能修复到某些地址,也几乎不可能将所有这些功能完全修复为已存在的地址外部程序期望(假设您无法修改此程序)。如果这确实有效,那将是完全巧合和纯粹的运气。
在其他程序所期望的地址上提供蹦床可能几乎是最容易的,并且具有真实的功能(无论它们可能是什么)。这将要求您的代码使用不同的基址,因此实际的程序代码不会与蹦床发生碰撞。
几乎有三件事可以为函数提供固定地址:
__attribute__ ((section ("some name")))
将每个不允许移动的功能放在适当的部分中。不幸的是,.text
始终显示为第一部分,因此,如果.text
中的任何内容发生更改,因此大小会超过512字节边界,则您的偏移量将会发生变化。默认情况下(但请参阅下文),您无法在.text
之前启动某个部分。-falign-functions=n
命令行选项可让您将功能与边界对齐。通常这大约是16个字节。现在,您可以选择一个较大的值,例如1024.这将浪费大量的空间,但它也将确保只要函数仅适度改变,以下函数的地址将保持不变。显然它仍然不会阻止编译器/链接器在感觉到它时重新排序整个块(尽管-fno-toplevel-reorder
将至少部分阻止它)。.text
前面)移动这些部分,因此.text
中的更改不会影响您的功能。<强>更新强> “gcc”标签表明您可能会定位* NIX,所以这可能不会对您有所帮助,但是......如果您可以选择使用COFF,则美元符号部分可能会起作用(信息可能会有用)其他人,无论如何)。
我今天偶然发现了这个(强调我的):
“$”字符(美元符号)在目标文件的节名中有特殊解释。在确定将包含对象部分内容的图像部分时,链接器会丢弃“$”及其后面的所有字符。因此,名为.text $ X的对象部分实际上对图像中的.text部分有贡献。但是,“$”后面的字符决定了对图像部分的贡献的排序。具有相同对象部分名称的所有贡献在图像中连续分配,并且贡献块按字节顺序按对象部分名称排序。 因此,在.text $ W贡献之后和.text $ Y贡献之前,部分名称.text $ X的目标文件中的所有内容都会一起结束。
如果文档不存在(如果我没有读错),这意味着您应该能够将前面所需的所有功能打包到一个部分.text$A
,以及其他所有内容进入.text$B
,就应该这样做。
答案 1 :(得分:6)
使用-ffunction-sections
构建代码 - 这会将每个函数放入其自己的部分。
如果您使用的是GNU-ld,链接描述文件将为您提供绝对控制,但这是一个非常特定于平台且有点痛苦的解决方案。
更好的解决方案可能是在gold
上使用recent work,这样可以完全按照您要求的功能排序。
答案 2 :(得分:0)
很多来自文件中函数的顺序以及链接时文件在命令行上的顺序。
在外部代码可以找到的代码中嵌入一些东西,一个带有一些ascii代码的const结构和函数的地址,然后无论编译器放置哪些函数你都可以找到它们。
那或使用正常的.dll或.so机制,而不必乱用它。
答案 3 :(得分:0)
根据我的经验,gcc -O0 将修复函数的二进制顺序以匹配源代码中的顺序。
然而,正如其他人所提到的,即使顺序是固定的,偏移量也会随着您修改源代码或升级工具链而发生变化。