I filed this nuts bug report this morning; anyway the real problem has finally been found. The way the ELF loader works, all relocations happen in userspace. The ELF loader itself is just another userspace binary that doesn't have any relocations of its own that loads the main binary, processes its relocations, and jumps to _start. But when you're static linking, _start points to the relocator, and things go from there. I'm not going to say that's what I'm writing because I'm not. Here's the thing: If you remove all constructs like const char *str = "Hello, world"; and similar things like initializing one static variable to the address of another; all remaining constructs in C can be compiled without relocations. When you write something like puts("Hello, world"); it generates call puts@PLT which looks like it needs a relocation but doesn't. The linker converts it to call puts In x86 you wouldn't be able to access string constants; but in x64 it's not a problem. The compiler emits something like mov .LC4(%rip), %rdi which after link time is just mov offset(%rip), %rdi which is fine. So the actual problem: there are some circumstances remaining where gcc will emit code requiring a relocation when it need not do so. In this case it emitted .LC16: .quad .LC7 because it wanted to use an indirect load of an xmm register. Avoiding this *must* be possible because the relocation engine avoids this problem. I'm not certain which world we live in: 1) The relocation engine works reliably but the necessary options aren't documented. 2) The relocation engine works reliably but the necessary options aren't known. (that is; it won't break unless its compilation options are changed but we don't know why) 3) The relocation engine is subject to random breakage in the future due to optimization changes. One of three is not good.