It is not clearly defined when undefined weak symbols are resolved.
It looks like there are two possible approaches:
1. Promote all weak undefined symbols to dynamic ones so that they'll
have another chance to be resolved at load-time, or
2. Promote weak undefined symbols to dynamic ones only when there are
definitions in other DSOs at link-time.
(1) provides the maximum flexibility. For example, consider a main program
that has a weak undefined symbol `foo` and there's no DSO that defines it
at link-time. In (1), `foo` gets promoted to a dynamic symbol, so that one
of its depending DSO is upgraded to define `foo`, the main executable's
`foo` is resolved to that symbol at load-time. On the other hand, in (2),
`foo` would have already been converted to an absolute symbol at address
zero at link-time, so you need to rebuild the main executable to use the
new definition of `foo` in the shared library.
However, (1) is not compatible with copy relocations. This is because we
need to know the size of the symbol when creating a copy relocation, but
that information is not available unless we have a definition. It's also
not compatible with canonical PLTs because canonical PLTs have non-zero
addresses and therefore weak undefined symbols would always be resolved to
non-zero addresses.
As a workaround, GNU ld promotes weak undefs to dynamic symbols only when
they don't need copy relocations or canonical PLTs. In other words, weak
undef's behavior is different between -fPIC and -fno-PIC. In the former
case, they become dynamic symbols, and vice versa.
I don't think that workaround is a good one. So, mold took the second
approach.
There is, however, another thing to consider. What if we can find a
defined symbol in a DSO that is specified as `-as-needed`? Previously,
mold did not mark the library as "needed" and converted the weak undef
into an absolute symbol.
However, libstdc++ assumes that if weak undef symbol
`__pthread_key_create` is not resolved, it assumes that multi-threading is
not used in the executable, which resulted in a mis-detection with mold.
Therefore, this patch changes the mold's behavior so that it makes weak
undefs to keep DSOs "needed".
Fixes https://github.com/rui314/mold/issues/1286
Use $CXX instead of $CC to detect whether C++ programs could be built
statically. Add function test_cxxflags for convenience.
Fix test error in an environment where C++ programs cannot be built
statically, with error like:
mold: fatal: library not found: c++
Signed-off-by: Yao Zi <ziyao@disroot.org>