Skip to content

Symbol Lookup error despite --no-allow-shlib-undefined option and false positive when using lto #1551

@EliasSC30

Description

@EliasSC30

There are two cases where I think the --no-allow-shlib-undefined option does not behave as intended.
I suspect the visibility of symbols from object files not to be considered properly.

The attached .sh shows the two cases, one where the option leads to an error where I think it shouldn't
and one where I think it should've raised an error but it doesn't.
Unpacking the most recent mold-2.40.4-x86_64-linux next to that script should make it runnable and it prints
my suspicions to the console.
build.sh

Hopefully my initial investigation can be helpful:

1. Symbol Resolution (src/input-files.cc, line 985)

void ObjectFile<E>::resolve_symbols(Context<E> &ctx) {
  for (i64 i = this->first_global; i < this->elf_syms.size(); i++) {
    // ...
    if (get_rank(this, esym, !this->is_reachable) < get_rank(sym)) {
      sym.file = this;  // ← Sets sym.file WITHOUT checking visibility
      // ...
    }
  }
}

Key Point: sym.file is set based purely on symbol priority/rank. Visibility is NOT checked.

2. The Check (src/passes.cc, line 1162)

void check_shlib_undefined(Context<E> &ctx) {
  // ...
  tbb::parallel_for_each(ctx.dsos, [&](SharedFile<E> *file) {
    for (i64 i = 0; i < file->elf_syms.size(); i++) {
      const ElfSym<E> &esym = file->elf_syms[i];
      Symbol<E> &sym = *file->symbols[i];
      if (esym.is_undef() && !esym.is_weak() && !sym.file &&  // ← Checks existence of resolved-to file
          !is_sparc_register(esym))
        Error(ctx) << *file << ": --no-allow-shlib-undefined: undefined symbol: " << sym;
    }
  });
}

3. DSO Hidden Symbol Handling (src/passes.cc, line 306)

template <typename E>
void resolve_symbols(Context<E> &ctx) {
// ...
// Special handling exists for hidden symbols from DSOs
tbb::parallel_for_each(ctx.dsos, [&](SharedFile<E> *file) {
  if (file->is_reachable) {
    for (Symbol<E> *sym : file->symbols) {
      if (sym->file == file && sym->visibility == STV_HIDDEN) {
        sym->skip_dso = true;  // ← Only for DSO hidden symbols
        redo = true;
      }
    }
  }
});

Key Point: This special handling applies only to DSOs, not object files.

I'm not 100% sure but this looks like hidden symbols from object files are never filtered because:

  1. Symbol resolution sets sym.file without checking visibility
  2. The undefined check only verifies sym.file exists
  3. Special visibility handling exists only for DSO symbols

Result: Runtime undefined symbol error when the shared library tries to resolve references that were satisfied by
hidden object file symbols during linking.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions