So rustc emits indirect call through GOT at 0x7c3e even if foo_add is linked against statically. Is this behavior intentional? Why don't rustc just emit a plain function call in such a case, as a C/C++ compiler would do?
When compiling the function it is not yet known that the callee would be statically linked. Note that C++ probably makes it a relative rather than a GOT call due to RELRO being disabled by default for C++ while rustc emables it by default. This means that C++ can emit a PLT call which the linker can relax to a relative call while rustc emits a GOT call as the lazy symbol resolving the PLT allows isn't possible with full RELRO anyway due to the GOT being made read-only after relocating.
Are you sure? I haven't heard of relro causing a performance hit besides the actual effort of doing the relocations at startup, which isn't applicable here. And isn't relro only specified at link time anyway?