开发者

How can I force the order of functions in a binary with the gcc toolchain?

开发者 https://www.devze.com 2023-03-18 05:53 出处:网络
I\'m building a static binary out of several source files and libraries, and I want to control开发者_Go百科 the order in which the functions are put into the resulting binary.

I'm building a static binary out of several source files and libraries, and I want to control开发者_Go百科 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 their 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.


Build your code with -ffunction-sections -- this will place each function into its own section.

If you are using GNU-ld, the linker script gives you absolute control, but is a very platform-specific and somewhat painful solution.

A better solution might be to use the recent work on gold, which allows exactly the function ordering you are seeking.


A lot of it comes from the order the functions are in the file and the order the files are on the command line when you link.

Embed something in the code that your external code can find, a const structure with some ascii code and the address to functions perhaps, then no matter where the compiler puts the functions you can find them.

that or use the normal .dll or .so mechanisms, and not have to mess with it.


In my experience, gcc -O0 will fix the binary order of functions to match the order in the source code.

However as others have mentioned, even if the order is fixed, the offsets can change as you modify the source code or upgrade your toolchain.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号