Generating a `cdylib` crate without an `.init`

If you build this minimal no_std cdylib crate in release mode on x86_64 and take a look at the resulting .so file you find that there's an _init function inserted into the .init text section that appears to do profiler initialization:

0000000000001000 <_init>:
    1000:       f3 0f 1e fa             endbr64
    1004:       48 83 ec 08             sub    $0x8,%rsp
    1008:       48 8b 05 e9 2f 00 00    mov    0x2fe9(%rip),%rax        # 3ff8 <__gmon_start__>
    100f:       48 85 c0                test   %rax,%rax
    1012:       74 02                   je     1016 <_init+0x16>
    1014:       ff d0                   call   *%rax
    1016:       48 83 c4 08             add    $0x8,%rsp
    101a:       c3                      ret

Is there any way to suppress the generation of _init and _fini, or really anything at all in the .init or .fini section? I looked in rust-lang/rust and couldn't even find where this is being generated as part of output. I suspect this is actually coming from LLVM, as I do see tests inside of the src/llvm-project checking for the presence of __gmon_start__ and __cxa_finalize, but I haven't found the smoking gun in there around what generates it.

I know I can post-process the binary and use objcopy --remove-section to get rid of these sections, but I'm a bit worried that I'll cause something to get added to them that's actually needed and then not notice that I've obliterated it later. I'm not sure if rust even generates init-/ctor-time code though beyond what I'm seeing here.

I think the actual question here might be "how do I disable profiling support in generated binaries?"

This might seem like a strange thing to try to do, but I'm working with a dynamic loader that doesn't support .init/.fini.

Looking at src/llvm-project/compiler-rt/lib/crt/crtbegin.c it really does seem like this is where this call would be injected, but I don't see direct references to __gmon_start__ there.

I figured this out: in your .cargo/config, for whatever [target.<your-target>] you're using, add:

[target.<target>]
rustflags = [
    "-C", "link-args=-nostdlib",
]
1 Like