我如何用gcc工具链强制二进制函数的顺序? [英] How can I force the order of functions in a binary with the gcc toolchain?

查看:186
本文介绍了我如何用gcc工具链强制二进制函数的顺序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



背景是,我有外部代码链接到这个二进制的偏移量。现在如果我改变了源代码,所有的偏移量都会改变,因为gcc可能会决定以不同的顺序排列函数,所以我想把所引用的函数以固定的顺序放在开始位置,这样它们的偏移量就不会改变......



我查看了ld的文档,但找不到任何有关函数顺序的内容。



我发现的唯一情况是-fno-toplevel - 对我来说并没有真正的帮助。

解决方案

真的没有干净而可靠的方法强制某个函数地址(除了入口函数)或者甚至强制具有特定顺序的函数(并且如果您可以执行命令,这仍然不意味着当源改变时地址保持不变!)。



我看到的最大问题是,即使可能将某个函数修复为某个地址,也是不可能的将它们全部修复到al准备好现有的外部程序(假设你不能修改这个程序)。如果这真的起作用了,那完全是巧合和纯粹的运气。

在其他程序期望的地址提供蹦床几乎是最容易的,函数(无论它们可能是什么)指向这些。这需要你的代码使用不同的基地址,所以实际的程序代码不会与蹦床相撞。



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


  1. 可以将每个不允许移动的函数放在适当的部分, code> __ attribute__((section(some name)))。不幸的是, .text 总是显示为第一部分,因此如果 .text 中的任何内容发生更改, 512字节的边界,你的偏移量将会改变。默认情况下(但请参阅下文),您不能在 .text 之前开始部分。

  2. -falign-functions = n 命令行选项可让您将函数与边界对齐。通常这是约16个字节的东西。现在,你可以选择一个很大的值,比如1024.这会浪费大量的空间,但它也会确保只要函数只是适度地改变,以下函数的地址将保持不变。显然,它仍然不会阻止编译器/链接器在感觉到它时重新排序整个块(尽管 -fno-toplevel-reorder 至少会部分阻止这个)。 li>
  3. 如果您愿意编写自定义链接器脚本,您可以为每个部分分配一个起始地址。这些是虚拟内存地址,而不是可执行文件中的位置,但我认为硬链接也适用于VMA(基于默认图像库)。所以这可能是 工作,虽然有很多麻烦,而不是一个漂亮的方式。

    当编写自己的链接脚本时,你也可以考虑把不能移动的函数分成两部分,在可执行文件的开头( .text )前面移动这些部分,所以 .text 不会移动您的功能。

更新:
gcc标签表明您可能瞄准* NIX,所以这可能不会对您有所帮助,但是...如果您可以选择使用COFF,则美元符号部分可能有效(信息在任何情况下,其他人都可能会感兴趣。)

我今天偶然发现了这个(我的重点):

< blockquote>

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

如果文档不是谎言(如果我没有看错),这意味着您应该能够将您想要位于前面的所有功能打包成一个部分 .text $ A ,以及其他所有内容放入 .text $ B 中,它应该做到这一点。 p>

I'm building a static binary out of several source files and libraries, and I want to control the order in which the functions are put into the resulting binary.

The background is, I have external code which is linked against offsets in this binary. Now if I change the source, all the offsets change because gcc may decide to order the functions differently, so I want to put the referenced functions at the beginning in a fixed order so thier offsets stay unchanged...

I looked through ld's documentation but couldn't find anything about order of functions.

The only thing i found was -fno-toplevel-reorder which doesn't really help me.

解决方案

There is really no clean and reliable way of forcing a function to a particular address (except for the entry function) or even forcing functions having a particular order (and if you could enforce the order that would still not mean that the addresses stay the same when the source is changed!).

The biggest problem that I see is that even if it may be possible to fix a function to some address, it will be sheer impossible to fix all of them to exactly the addresses that the already existing external program expects (assuming you cannot modify this program). If that actually worked, it would be total coincidence and sheer luck.

It might be almost easiest to provide trampolines at the addresses that the other program expects, and having the real functions (whereever they may be) pointed to by these. That would require your code to use a different base address, so the actual program code doesn't collide with the trampolines.

There are three things that almost work for giving functions fixed addresses:

  1. You can place each function that isn't allowed to move in its proper section using __attribute__ ((section ("some name"))). Unluckily, .text always appears as the first section, so if anything in .text changes so the size is bumped over the 512 byte boundary, your offsets will change. By default (but see below) you can't get a section to start before .text.
  2. The -falign-functions=n commandline option lets you align functions to a boundary. Normally this is something around 16 bytes. Now, you could choose a large value like for example 1024. That will waste an immense amount of space, but it will also make sure that as long as functions only change moderately, the addresses of the following functions will remain the same. Obviously it still does not prevent the compiler/linker from reordering entire blocks when it feels like it (though -fno-toplevel-reorder will prevent this at least partially).
  3. If you are willing to write a custom linker script, you can assign a start address for each section. These are virtual memory addresses, not positions in the executable, but I assume the hard linking works with VMAs (based on the default image base) too. So that could kind of work, although with much trouble and not in a pretty way.
    When writing your own linker script, you could also consider putting the functions that must not move into their own sections and moving these sections at the beginning of the executable (in front of .text), so changes in .text won't move your functions around.

Update: The "gcc" tag suggests that you probably target *NIX, so again this is probably not going to help you, but... if you have the option to use COFF, dollar-sign sections might work (the info might be interesting for others, in any case).

I just stumbled across this today (emphasis mine):

The "$" character (dollar sign) has a special interpretation in section names in object files. When determining the image section that will contain the contents of an object section, the linker discards the "$" and all characters that follow it. Thus, an object section named .text$X actually contributes to the .text section in the image. However, the characters following the "$" determine the ordering of the contributions to the image section. All contributions with the same object-section name are allocated contiguously in the image, and the blocks of contributions are sorted in lexical order by object-section name. Therefore, everything in object files with section name .text$X ends up together, after the .text$W contributions and before the .text$Y contributions.

If the documentation does not lie (and if I'm not reading wrong), this means you should be able to pack all the functions that you want located in the front into one section .text$A, and everything else into .text$B, and it should do just that.

这篇关于我如何用gcc工具链强制二进制函数的顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆