Link_section not adding section in release

Hi everyone.

I would like to play around with adding a function to a specific, custom ELF section, but, for some reason, the section does not exist on the release binary. The debug binary has it though.

I have this code:

#[link_section = ".custom_section"]
fn test() -> u32 {
    32
}

fn main() {
    test();
}

If I do cargo build, it generates a debug binary that has the section:

$ readelf -S target/debug/helloworld | grep custom
  [15] .custom_section   PROGBITS         0000000000032b90  00032b90

When I do cargo build --release, the new binary does not have the section.

I have seen other threads, but they refer to more complex topics of code injection, etc. (one of them with a very similar title: Link_section not appearing in release)

I am afraid that I may be missing something and this might have a simple solution.

Thank you.

For static variables there's #[used] to prevent them from being optimized out. I don't know if there's a solution for functions. Does making them pub or #[no_mangle] help?

Hey!

Making the function pub or even #[no_mangle] does not help, the section is still missing, unfortunately.

#[used] doesn't work for executables. Executables don't export any symbols other than libc specific stuff and main. As test is neither exported nor used, the linker concludes that the section is unused and because of --gc-sections skips it entirely.

Thanks for your response.

It seems that I have to use a Rust flag, -C link-dead-code for it to maintain the section in release, in other words, to not execute --gc-sections. Is this a valid solution or are there any other preferrable solutions?

What is the purpose of the custom section? -Clink-dead-code increases the binary size. You could try a volatile load of for example the first byte of the test function. You can also use a custom linker script that explicitly includes the custom section.

The purpose is to have a function in that section that might me referenced later by another executable (by reading the ELF file). I do see that -Clink-dead-code does increase the binary beyond a reasonable size. I guess the only way is through the custom linker script, as you suggested.

Making the section name start with .note. in combination with #[no_mangle] (or #[used] for statics) seems to work too. Note sections are never allocated though, so you need to make sure that the symbol is not referenced at runtime. You can only read it directly from the linked executable file.

2 Likes

Thanks for the help, I guess I have enough to do what I want to do. :slight_smile: