Skip to content

[lld-link] Crash on LTO pulling in objects with export attributesΒ #158248

@mstorsjo

Description

@mstorsjo

First off - this issue is very similar to #131807. During linking, a late stage ends up pulling in an object file, which contains an -export: attribute.

We handle -export entries here, https://github.com/llvm/llvm-project/blob/llvmorg-21.1.1/lld/COFF/Driver.cpp#L2536-L2558, resolving their symbols and attempting to pull in those symbols. But any late included object file with a new -export: attribute is missed, never executing something like e.sym = symtab.addGCRoot(e.name, !e.data);, which means that at the end, we have e.sym == nullptr.

This case is somewhat different in the mechanisms in how we end up late-including more object files, but the effect is the same - a late included object file with -export is fatal.

To reproduce the issue:

  • entry.c:
double pow(double, double);
double entry(double d) {
    return pow(d, d);
}
  • pow.c:
double __declspec(dllexport) pow(double x, double y) {
    return x;
}
  • _fltused.c:
int _fltused;

Build like this:

clang -target x86_64-windows-msvc -c entry.c -flto=thin -fno-math-errno
clang -target x86_64-windows-msvc -c pow.c
clang -target x86_64-windows-msvc -c _fltused.c
llvm-ar rcs math.lib pow.o _fltused.o
lld-link entry.o -entry:entry -subsystem:console math.lib

The triggering factor here, is that the compiled IR object entry.o doesn't show any traces of the pow function:

$ llvm-nm entry.o
---------------- T entry

This happens as long as building with -fno-math-errno and not using -fno-builtin - the math function is treated as the IR builtin @llvm.pow.f64. After the bitcode is compiled to a regular object file, we get an actual reference to the pow symbol, try to pull it in from math.lib, and find the -export directive.

For LTO, there is logic to try to pull in any potential function that can be referenced by generated code like this, here: https://github.com/llvm/llvm-project/blob/llvmorg-21.1.1/lld/COFF/Driver.cpp#L2561-L2571
This does include the pow function - however, this only pulls in potential bitcode object files. Regular objects are not pulled in here: https://github.com/llvm/llvm-project/blob/llvmorg-21.1.1/lld/COFF/SymbolTable.cpp#L951-L964

This is a reduced form of downstream issue mstorsjo/llvm-mingw#516.

CC @aganea @rnk @cjacek @Andarwinux

What do you think about this case? The previous very similar issue, #131807, was handled by making that mechanism (pulling in a symbol <foo> for an undefined referece to __imp_<foo>) not pull in lazy objects from archives.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions