Skip to content

Commit

Permalink
Make --undefined=ignore-in-object-files to override -z defs
Browse files Browse the repository at this point in the history
The interaction between these flags are unnecessarily complicated,
but it looks like `--undefined=ignore-in-object-files` needs to
share the same internal flag as `-z defs` so that they override
each other.

Fixes #1270
  • Loading branch information
rui314 committed May 31, 2024
1 parent 01bc0b5 commit 8cd85aa
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 21 deletions.
30 changes: 21 additions & 9 deletions elf/cmdline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,9 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {

bool version_shown = false;
bool warn_shared_textrel = false;
bool error_unresolved_symbols = true;
std::optional<SeparateCodeKind> z_separate_code;
std::optional<bool> report_undefined;
std::optional<bool> z_relro;
std::optional<u64> shuffle_sections_seed;
std::unordered_set<std::string_view> rpaths;
Expand Down Expand Up @@ -781,9 +783,9 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
ctx.arg.unique = std::move(*pat);
} else if (read_arg("unresolved-symbols")) {
if (arg == "report-all" || arg == "ignore-in-shared-libs")
ctx.arg.unresolved_symbols = UNRESOLVED_ERROR;
report_undefined = true;
else if (arg == "ignore-all" || arg == "ignore-in-object-files")
ctx.arg.unresolved_symbols = UNRESOLVED_IGNORE;
report_undefined = false;
else
Fatal(ctx) << "unknown --unresolved-symbols argument: " << arg;
} else if (read_arg("undefined") || read_arg("u")) {
Expand Down Expand Up @@ -963,10 +965,10 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
z_relro = true;
} else if (read_z_flag("norelro")) {
z_relro = false;
} else if (read_z_flag("defs")) {
ctx.arg.z_defs = true;
} else if (read_z_flag("defs") || read_flag("no-undefined")) {
report_undefined = true;
} else if (read_z_flag("undefs")) {
ctx.arg.z_defs = false;
report_undefined = false;
} else if (read_z_flag("nodlopen")) {
ctx.arg.z_dlopen = false;
} else if (read_z_flag("nodelete")) {
Expand Down Expand Up @@ -1018,8 +1020,6 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
ctx.arg.z_rewrite_endbr = true;
} else if (read_z_flag("rodynamic")) {
ctx.arg.z_rodynamic = true;
} else if (read_flag("no-undefined")) {
ctx.arg.z_defs = true;
} else if (read_flag("nmagic")) {
ctx.arg.nmagic = true;
} else if (read_flag("no-nmagic")) {
Expand Down Expand Up @@ -1149,9 +1149,9 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
} else if (read_flag("strip-debug") || read_flag("S")) {
ctx.arg.strip_debug = true;
} else if (read_flag("warn-unresolved-symbols")) {
ctx.arg.unresolved_symbols = UNRESOLVED_WARN;
error_unresolved_symbols = false;
} else if (read_flag("error-unresolved-symbols")) {
ctx.arg.unresolved_symbols = UNRESOLVED_ERROR;
error_unresolved_symbols = true;
} else if (read_arg("rpath")) {
add_rpath(arg);
} else if (read_arg("R")) {
Expand Down Expand Up @@ -1310,6 +1310,18 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
if (ctx.arg.pic)
ctx.arg.image_base = 0;

if (!report_undefined)
report_undefined = !ctx.arg.shared;

if (*report_undefined) {
if (error_unresolved_symbols)
ctx.arg.unresolved_symbols = UNRESOLVED_ERROR;
else
ctx.arg.unresolved_symbols = UNRESOLVED_WARN;
} else {
ctx.arg.unresolved_symbols = UNRESOLVED_IGNORE;
}

if (ctx.arg.retain_symbols_file) {
ctx.arg.strip_all = false;
ctx.arg.discard_all = false;
Expand Down
18 changes: 12 additions & 6 deletions elf/input-sections.cc
Original file line number Diff line number Diff line change
Expand Up @@ -523,16 +523,22 @@ bool InputSection<E>::record_undef_error(Context<E> &ctx, const ElfRel<E> &rel)
acc->second.push_back(ss.str());
};

// A non-weak undefined symbol must be promoted to an imported
// symbol or resolved to an defined symbol. Otherwise, it's an
// undefined symbol error.
// A non-weak undefined symbol must be promoted to an imported symbol
// or resolved to an defined symbol. Otherwise, we need to report an
// error or warn on it.
//
// Every ELF file has an absolute local symbol as its first symbol.
// Referring to that symbol is always valid.
bool is_undef = esym.is_undef() && !esym.is_weak() && sym.sym_idx;
if (!sym.is_imported && is_undef && sym.esym().is_undef()) {
record();
return true;
if (is_undef && sym.esym().is_undef()) {
if (ctx.arg.unresolved_symbols == UNRESOLVED_ERROR && !sym.is_imported) {
record();
return true;
}
if (ctx.arg.unresolved_symbols == UNRESOLVED_WARN) {
record();
return false;
}
}

// If a protected/hidden undefined symbol is resolved to other .so,
Expand Down
3 changes: 1 addition & 2 deletions elf/mold.h
Original file line number Diff line number Diff line change
Expand Up @@ -1690,7 +1690,7 @@ struct Context {
Symbol<E> *entry = nullptr;
Symbol<E> *fini = nullptr;
Symbol<E> *init = nullptr;
UnresolvedKind unresolved_symbols = UNRESOLVED_ERROR;
UnresolvedKind unresolved_symbols = UNRESOLVED_IGNORE;
BsymbolicKind Bsymbolic = BSYMBOLIC_NONE;
bool allow_multiple_definition = false;
bool apply_dynamic_relocs = true;
Expand Down Expand Up @@ -1745,7 +1745,6 @@ struct Context {
bool warn_once = false;
bool warn_textrel = false;
bool z_copyreloc = true;
bool z_defs = false;
bool z_delete = true;
bool z_dlopen = true;
bool z_dump = true;
Expand Down
11 changes: 7 additions & 4 deletions elf/passes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1432,9 +1432,11 @@ void compute_section_sizes(Context<E> &ctx) {
}

// Find all unresolved symbols and attach them to the most appropriate files.
// Note that even a symbol that will be reported as an undefined symbol will
// get an owner file in this function. Such symbol will be reported by
// ObjectFile<E>::scan_relocations().
//
// Note that even a symbol that will be reported as an undefined symbol
// will get an owner file in this function. Such symbol will be reported
// by ObjectFile<E>::scan_relocations(). This is because we want to report
// errors only on symbols that are actually referenced.
template <typename E>
void claim_unresolved_symbols(Context<E> &ctx) {
Timer t(ctx, "claim_unresolved_symbols");
Expand Down Expand Up @@ -1512,7 +1514,8 @@ void 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 && sym.visibility != STV_HIDDEN && !ctx.arg.z_defs) {
if (ctx.arg.shared && sym.visibility != STV_HIDDEN &&
ctx.arg.unresolved_symbols != UNRESOLVED_ERROR) {
claim(true);
continue;
}
Expand Down
Empty file modified test/elf/copyrel-norelro.sh
100644 → 100755
Empty file.
Empty file modified test/elf/linker-script6.sh
100644 → 100755
Empty file.
Empty file modified test/elf/riscv64_global-pointer-dso.sh
100644 → 100755
Empty file.
10 changes: 10 additions & 0 deletions test/elf/unresolved-symbols2.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
. $(dirname $0)/common.inc

cat <<EOF | $CC -c -o $t/a.o -xc -fPIC -
int foo();
int bar() { foo(); }
EOF

$CC -B. -shared -o $t/b.so $t/a.o -Wl,-z,defs -Wl,--unresolved-symbols,ignore-in-object-files
readelf -W --dyn-syms $t/b.so | grep -q ' UND foo$'

1 comment on commit 8cd85aa

@Alcaro
Copy link

@Alcaro Alcaro commented on 8cd85aa May 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

No, github, those aren't empty. I've filed a bug report.

Please sign in to comment.