Can GOT table be optimized for static Rust binaries?

For a simple Rust program

fn main() {
    println!("Hello, world!");
}

with Cargo.toml as:

[package]
name = "got-test"
version = "0.1.0"
edition = "2021"

[dependencies]

[profile.release]
lto = true
codegen-units = 1

And we compile it as

cargo build --release --target x86_64-unknown-linux-musl

with rustc version 1.84.0 on Ubuntu 22.04.

We can see many libc functions are called via static GOT table in the generated binary:

These GOT entries lead to many indirect calls across the whole binary, which may potentially decrease the performance (one more memory access and less opportunity for inline optimization).

I know little about LTO, while I guess it may be LTO's job to do those things? Why LTO has no effect on those static GOT entries? Since they are only read but never written across the whole binary, can these entries be eliminated?

P.S. Found this SO question which may be relevant, which I don't know if the bug described in it has been fixed or not.

1 Like

All GOT entries I see are references to libc. Libc doesn't participate in LTO and bitcode for the standard library is generated when rustc itself got compiled and thus has to take into account that you may want to dynamically link libc and there is nothing that can at LTO time tell LLVM that you won't do dynamic linking. As such LLVM doesn't know that it can use direct calls without GOT indirection when emitting the object files, even with LTO.

1 Like