mirror of
https://github.com/rui314/mold.git
synced 2024-11-10 19:26:38 +03:00
[ELF] Export undef symbols if both -z defs
and -warn-undefined-symbols
are given
When we are creating a DSO, unresolved undefined symbols are promoted to dynamic symbols by default so that they will get another chance to be resolved at runtime. You can suppress this behavior by passing `-z defs`. If that option is given, remaining undefs are reported as errors instead of being silently promoted. It looks like `-warn-undefined-symbols` negates the effect of `-z defs`. So, if both options are given, remaining undefs are promoted to dynamic symbols. mold previously silently make such symbols absolute symbols with value 0. Fixed https://github.com/rui314/mold/issues/152
This commit is contained in:
parent
5601cf4236
commit
04ccd4dbdd
@ -992,6 +992,22 @@ void ObjectFile<E>::claim_unresolved_symbols(Context<E> &ctx) {
|
||||
|
||||
std::lock_guard lock(sym.mu);
|
||||
|
||||
if (sym.file &&
|
||||
(!sym.esym().is_undef() || sym.file->priority <= this->priority))
|
||||
continue;
|
||||
|
||||
// If a symbol name is in the form of "foo@version", search for
|
||||
// symbol "foo" and check if the symbol has version "version".
|
||||
std::string_view key = symbol_strtab.data() + esym.st_name;
|
||||
if (i64 pos = key.find('@'); pos != key.npos) {
|
||||
Symbol<E> *sym2 = intern(ctx, key.substr(0, pos));
|
||||
if (sym2->file && sym2->file->is_dso &&
|
||||
sym2->get_version() == key.substr(pos + 1)) {
|
||||
this->symbols[i] = sym2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto claim = [&]() {
|
||||
sym.file = this;
|
||||
sym.input_section = nullptr;
|
||||
@ -1002,23 +1018,11 @@ void ObjectFile<E>::claim_unresolved_symbols(Context<E> &ctx) {
|
||||
sym.is_exported = false;
|
||||
};
|
||||
|
||||
if (!sym.file ||
|
||||
(sym.esym().is_undef() && this->priority < sym.file->priority)) {
|
||||
std::string_view key = symbol_strtab.data() + esym.st_name;
|
||||
|
||||
// If a symbol name is in the form of "foo@version", search for
|
||||
// symbol "foo" and check if the symbol has version "version".
|
||||
if (i64 pos = key.find('@'); pos != key.npos) {
|
||||
Symbol<E> *sym2 = intern(ctx, key.substr(0, pos));
|
||||
if (sym2->file && sym2->file->is_dso &&
|
||||
sym2->get_version() == key.substr(pos + 1)) {
|
||||
this->symbols[i] = sym2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (ctx.arg.unresolved_symbols == UnresolvedKind::WARN)
|
||||
Warn(ctx) << "undefined symbol: " << *this << ": " << sym;
|
||||
|
||||
// Convert remaining undefined symbols to dynamic symbols.
|
||||
//
|
||||
if (ctx.arg.shared) {
|
||||
// Traditionally, remaining undefined symbols cause a link failure
|
||||
// only when we are creating an executable. Undefined symbols in
|
||||
// shared objects are promoted to dynamic symbols, so that they'll
|
||||
@ -1029,10 +1033,11 @@ void ObjectFile<E>::claim_unresolved_symbols(Context<E> &ctx) {
|
||||
// promoted to dynamic symbols for compatibility with other linkers.
|
||||
// Some major programs, notably Firefox, depend on the behavior
|
||||
// (they use this loophole to export symbols from libxul.so).
|
||||
if (ctx.arg.shared && (!ctx.arg.z_defs || esym.is_undef_weak())) {
|
||||
if (!ctx.arg.z_defs || esym.is_undef_weak() ||
|
||||
ctx.arg.unresolved_symbols != UnresolvedKind::ERROR) {
|
||||
claim();
|
||||
sym.ver_idx = 0;
|
||||
sym.is_imported = !ctx.arg.is_static;
|
||||
sym.is_imported = true;
|
||||
|
||||
if (sym.traced)
|
||||
SyncOut(ctx) << "trace-symbol: " << *this << ": unresolved"
|
||||
@ -1040,6 +1045,7 @@ void ObjectFile<E>::claim_unresolved_symbols(Context<E> &ctx) {
|
||||
<< " symbol " << sym;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert remaining undefined symbols to absolute symbols with value 0.
|
||||
if (ctx.arg.unresolved_symbols != UnresolvedKind::ERROR ||
|
||||
@ -1047,10 +1053,6 @@ void ObjectFile<E>::claim_unresolved_symbols(Context<E> &ctx) {
|
||||
claim();
|
||||
sym.ver_idx = ctx.arg.default_version;
|
||||
sym.is_imported = false;
|
||||
|
||||
if (ctx.arg.unresolved_symbols == UnresolvedKind::WARN)
|
||||
Warn(ctx) << "undefined symbol: " << *this << ": " << sym;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,17 @@ EOF
|
||||
clang -fuse-ld=$mold -shared -o $t/b.so $t/a.o
|
||||
clang -fuse-ld=$mold -shared -o $t/b.so $t/a.o -Wl,-z,nodefs
|
||||
|
||||
! clang -fuse-ld=$mold -shared -o $t/b.so $t/a.o -Wl,-z,defs 2> $t/log || false
|
||||
! clang -fuse-ld=$mold -shared -o $t/b.so $t/a.o -Wl,-z,defs \
|
||||
2> $t/log || false
|
||||
grep -q 'undefined symbol:.* foo' $t/log
|
||||
|
||||
! clang -fuse-ld=$mold -shared -o $t/b.so $t/a.o -Wl,-no-undefined 2> $t/log || false
|
||||
! clang -fuse-ld=$mold -shared -o $t/b.so $t/a.o -Wl,-no-undefined \
|
||||
2> $t/log || false
|
||||
grep -q 'undefined symbol:.* foo' $t/log
|
||||
|
||||
clang -fuse-ld=$mold -shared -o $t/c.so $t/a.o -Wl,-z,defs \
|
||||
-Wl,--warn-unresolved-symbols 2> $t/log
|
||||
grep -q 'undefined symbol: .* foo$' $t/log
|
||||
readelf --dyn-syms $t/c.so | grep -q ' foo$'
|
||||
|
||||
echo OK
|
Loading…
Reference in New Issue
Block a user