A vast majority of that 415 KB is due to the backtrace support, which is amazingly complicated. (See my other comment for specifics.) It will depend on some more machinaries from std, and a "simple" hello world can always panic if stdout is closed or so, therefore that part of std cannot be easily removed unless you are fine with useless backtraces.
Also, Rust has no direct platform support unlike C. So everything has to be statically linked to be portable. A statically linked glibc is indeed much larger than that (~800 KB in my machine). Conversely, you can sacrifice portability and link to `libstd*.so` dynamically to get a very small binary (~17 KB in my machine, both for C and Rust).
For a statically linked libc I would expect that only the stdlib code that's actually used is included in the program (even without LTO).
For instance a statically linked C hello world for Linux via MUSL (cross-compiled with `zig cc -Os -target x86_64-linux-musl hello.c -o hello` because I'm currently on a Mac) is just 5 KBytes.
Musl doesn't have anything like Rust backtraces so it's not a fair comparison. By the way, glibc does have one [1], and I would be surprised if adding a backtrace printer doesn't significantly increase the binary size.
Also, Rust has no direct platform support unlike C. So everything has to be statically linked to be portable. A statically linked glibc is indeed much larger than that (~800 KB in my machine). Conversely, you can sacrifice portability and link to `libstd*.so` dynamically to get a very small binary (~17 KB in my machine, both for C and Rust).