<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/158248>158248</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[lld-link] Crash on LTO pulling in objects with export attributes
</td>
</tr>
<tr>
<th>Labels</th>
<td>
lld:COFF
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
mstorsjo
</td>
</tr>
</table>
<pre>
First off - this issue is very similar to https://github.com/llvm/llvm-project/issues/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`:
```c
double pow(double, double);
double entry(double d) {
return pow(d, d);
}
```
* `pow.c`:
```c
double __declspec(dllexport) pow(double x, double y) {
return x;
}
```
* `_fltused.c`:
```c
int _fltused;
```
Build like this:
```console
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:
```console
$ 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 https://github.com/mstorsjo/llvm-mingw/issues/516.
CC @aganea @rnk @cjacek @Andarwinux
What do you think about this case? The previous very similar issue, https://github.com/llvm/llvm-project/issues/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.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy8V11v47oR_TX0y0CCPmzZfvCDN6mLCyxwgTRAHwOKHEncUKRAUnbcX18MJdlOit1726JdLCBHGh3OnDnzIe69ag3igW2-sc3zio-hs-7Q-2Cd_2FXtZXXw0k5H8A2DSQQOuVBeT8iKA9ndFfwqleaOwgWuhAGz8ojK06sOLUqdGOdCtuz4qT1ebkkg7M_UARWnCKSZ8UpL_Ndtk3heXTKtKCVeVemZcUTcNA8IPjAWwQ00sM4wDBqTXbKADdga4KDRmmkNy6dEh0IawJXxpMBq7IEPwbrAjlXZcBDcKoeA6YsO7Ls-HeEjhup8dG0ygBNcAo9dOgi9L8dYK1tPd-1rk2KPM3TPN6QrDg9_X4inGenzuhSMQysKL8Xm7JKvhebzY5OdOitPlOsoUPlwF_72mqKSlIU2A8hPrSREyIkdNbjYpfCtzEAN9eJRWWEHiXKR8rgokIHHAxefkEUpbtX3qMkrwye0QF-oBjj8d72GLopc--RREz9tQdWPpMngdcpl_KvTy_WBlbsMDW8j4SyIsdU8sBZsWflN1Zl9wz2yI2H0PEAPFD4lP74mLJ1_nwMnWRGrYfgWJXNaX0ltQruo_fk44XApGoadGjCxBZCj6LjRvne053OXugENJKURrQlE20UXm8dPpLnyZ96nN1rGrqvfPzL8x4hWfT7c-Y_K055aHjgeonAgsPBWTkKjKixYig58TErjpEFE9w1FcTe7UmVTf8Fy47SjrVGGOyFFbvpD_J7-RWZv1lFsJsdSFbsgW3JAByG0ZkFJ0Lc3mbb58dj7_6Rg4O9_LF7b28ShfYDCkLXeial2H9yHD7ursP1wTmAxb-PP_CIVdlbo8PoUf7CK2UCLGYz4Geob6PSchI8tcUZ5QZhjbcaWXYUmpsWksBdiwE-dtVbtU4uykh78UnvzwISAXMKIWl0sKx8pmqCpDE26XnoEnTO2D-LNbH9J40fmMiOsXtxB054oHNTreoIZ-92NtrJhHr07LaFZFJNeYxXSPxY-6sP2LPyODNxA_xXJl87hOBU22Ls_g0Xwbpb01VzEyD5C9sPSqOE316WSrrp31L9SIvesGIbwFMhU-cLjgv0YJuIMKmRTJvRiKCs-WniWLGGyIjpl0BZdky-_IPXuWQ-hxV7T8eHAWkGedDWtHStSTUU5a34vySZuq6RYGyA0ZPhYkNvBmXIIJn6Fg_dLYpIk0MeUNIx9Py3F5jfIQy2ziiYlNLZVGvqknBsArpoW6sgrIyN8sZxsMDBYTvSeP86ZBFIVNwAF2HkGhzGpkptyn4heppF9BZp4zaqYv9tnO3J9CaOaQIQA40yckF66JBSORRBnZfZfbIOvr_-HuFJMhSCtq0S0ZHHA02Uw2ADmqC4vlMX5SW4gRrvcUior9CiQRc5jezci52WAdJnefw_LQVVTkvBNl-kRUJfpspPhA0JDTMa1RM5yoM1-hrZiKPuTsWS_sfRlsLLp9x74A6jLgkAZRyW_1MO_haF88prjQsR-02efN9X64cBr3yUKY1ICY11PZW6tBfjqR76eV39hYfLurt42SvTXh63001ezWJ7egK2znjLDXL65cw7XcQPLjD-OhrJ3UWZ8QPm1TKuHBaudqQUmHfgtY0Lw7ybsPIE1AAHh2dlxy9b9TTv_5PV88tuHYuW-3nPjeLu-fu0WPJw34GAFbvH9Xqu3thByqfGWlb-JYrMOqr-0UhslEE5F85U_zRh31Q_vD2-QrN6UQ9Ba_6P601asQ9wJzp1Rj-TzbLjSh5KuS_3fIWHfLvZVtU2K8tVdxCi2e2FwGxXSr7B7TrbrNflerfbrvcNbpuVOhRZscn2eZHtNllZpjuRr_M9L0S-229l3rB1hj1XOo1d0bp2FRk75Jtdsd6tNK9R-_hhVBSkyvI4qbKgDyV3iGzXY-upryof_B0nqKDjJ9UyJtnmGZ4c9x1YQ73q8ftlISCOg6nL3bduvxqdPvwXqZ9iOR-KfwYAAP__VamFhw">