<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/107365>107365</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[lld][coff] undefined symbols from lazy-loaded archives
</td>
</tr>
<tr>
<th>Labels</th>
<td>
lld
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
glandium
</td>
</tr>
</table>
<pre>
STR:
- Download https://drive.google.com/file/d/1HhG-LO4MU1GGOLstHlFBi7rOrwKfNDbZ/view?usp=sharing
- Unpack the archive and enter the `repro` directory.
- Run `lld-link @response.txt`
Expected result:
- Linkage fails because of a missing file (`-reproduce` didn't store the manifest file, you may want to edit the response file to remove the manifest-related flags, in which case the expected result is a successful link)
Actual result:
```
lld-link: error: undefined symbol: __declspec(dllimport) _wassert
>>> referenced by /tmp/g/third_party/rust/whatsys/c/windows.c:38
>>> libwhatsys-f4cc7b72e53ee839.rlib(db3b6bfb95261072-windows.o):(get_os_release)
lld-link: error: undefined symbol: __declspec(dllimport) wcscpy
>>> referenced by /tmp/g/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c:4238
>>> liblmdb_sys-564cd906496499b4.rlib(7b4e66c3aa61e8a8-mdb.o):(mdb_fopen)
lld-link: error: undefined symbol: __declspec(dllimport) _aligned_malloc
>>> referenced by /tmp/g/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c:9324
>>> liblmdb_sys-564cd906496499b4.rlib(7b4e66c3aa61e8a8-mdb.o):(mdb_env_copyfd1)
lld-link: error: undefined symbol: __declspec(dllimport) _aligned_free
>>> referenced by /tmp/g/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c:9425
>>> liblmdb_sys-564cd906496499b4.rlib(7b4e66c3aa61e8a8-mdb.o):(mdb_env_copyfd1)
```
What happens is that the symbols, by the time `resolveRemainingUndefines` is called, are still undefined, but `isLazy()` is true for them, and `resolveRemainingUndefines` doesn't handle that case.
A crude retry, like the following, works around the issue:
```
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 3ef9fa3f65c6..46307a386328 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2595,6 +2595,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
// Resolve remaining undefined symbols and warn about imported locals.
ctx.symtab.resolveRemainingUndefines();
+ run();
+ ctx.symtab.resolveRemainingUndefines();
if (errorCount())
return;
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index bb7583bb9a7d..5301a7af9c92 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -501,6 +501,10 @@ void SymbolTable::resolveRemainingUndefines() {
// This odd rule is for compatibility with MSVC linker.
if (name.starts_with("__imp_")) {
Symbol *imp = find(name.substr(strlen("__imp_")));
+ if (imp && imp->isLazy()) {
+ forceLazy(imp);
+ continue;
+ }
if (imp && isa<Defined>(imp)) {
auto *d = cast<Defined>(imp);
replaceSymbol<DefinedLocalImport>(sym, ctx, name, d);
```
But somehow, there is some non-determinism, as when running the command repeatedly, sometimes, it fails with `strdup` marked as undefined symbol.
Cc: @mstorsjo
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzEV01v4zgS_TXMpSBDpj5sHXxI4nbPYru3gf7YBfZiUGTJ4oQiBZKy4_n1i5KUTpx2T4DdmR3AsCSyWCw-PtZjiRD0wSJuWHHHiu2NGGLr_OZghFV66G5qp86bL18_s-yWpVuW3iawdSdrnFDQxtgH6uA7xnfK6yMuDs4dDC6k6xjfNdog9TC-W_7Svk8-fMo_flu-f__pQ4i_mN2dXvlP_vT35h_b-t-M744aTyzbDaFn2Ta0wmt7eJr0m-2FfIDYIggvW31EEFYB2oh-bGVl6rH3jpUpKO1RRufPi6fhnwdLFsaoxGj7ACxPPYbe2YCL-BhZmU6W0_-7xx5lRAUew2Dii7V_0PZBHBAaoU2AGqUYAoJrQECnQ9D2ALRoYHzNyjQZI1KDxCkqZRlfRQjReRyD7oTVDYYIE1L3cHYDdOIMJ2EjRAeodBwtn6Kd3EcHHjt3vPSSeDSCwm6MOARypy2cWi1bkCJMtni5NNABBIRBSgyhGQwQOoxXL9G4lXEQ5jUWBNn0Gz-fkGXZLaD3ztPLYBU22qKCcO5qZ6htv1coTehRMr5Wxuiudz4yXsH-JEJAH2f_2bvpBx4b9GglKqjPwPgudj3juwO9tdqrfS98PDO-80OIjO9OrYjhHBjfSfrSVrlTWEiW3Wbr176NrmfzpMmlXNUrjkWGuM6qhTe6phjrrC7rpq4KXi7TFU-ePDrCidi_PmDcu7D3aFAEfAXfH4DMSQbZn_9XXEyn6sQ_HJMJHPqkh6698BrD9D63dqoeEcv5VczIak-gFWUuVZWWeVXmVVXnT6Ct6hzLUmZClEtci3VCDp8Bo-GN69H-8VjthaGEpvadMMbJvwK0KuP5nwQa2uNeuv7cqOWfCF3jEf8S4HJe_D-Bu0xh0_-_WhGhFX2PNlB2jPRNmXNCcEyr9XlsibqbdSc4c8TP2AlttT18m1EPlPV1ACmMQUUDhUcIURvzvDOjvyGSHx0-iN_OJB28modGPyA0bpS4bvRg1ZtTKodhUppWWEVyQWsgCVhc5HWQflAkLdGfybfRD5NINM4YdyL15fdwcv4hgPBusGrs1SEM-DMdULppIEkOOoKgPTYk_vefdnRD2NINwS9k30P9877Jj7YKHyHDpmpE1pSFLBeLvMzSlcjWZcbXsEzTMp-PWZIkvzfbHCi_m35vT87ylOUpJLyoCsbvS2D8bn5fw9x5dFqN1wH003BCJLs1Y8tHoS3j61vvxfkzNiy7l86GCLIVHhgneoPwh3DrPR08trqbJob5ATDdqeDztM-k9tNG_3Ckw0iJk_AWRO2GCNN5RgXGSWHCvOUg4-MinLso6sXPyTNRL7v7jhiAH-yV5v_CGwDohi5GY3a6d4ONs8XTeSQmDt4-j3ibUl9GDL6Kmu6c13j1yuAluep6Vayzuq7ESi0WRZYuxUo0laz42-S66vZ3GHbdfqZZkS6fWDa9LtMLlr0YPJHsDchf8AmeqfS11QGcUuAHQ4d4TCvSdb2IutZGxzOcdGzh45d_3sNE48ULL9PeWdHhIkThY9iT9Tgh3-911-8Z59Nuvpof5gUQ8XXXA8u20Girvrsb6hA94-sQvUF71eUPtHwOaXTJS8ZLon7CsncXefRlON9HAi1e4mymScmu-AeQzkZtKdu97mOr7cUSf4wlCJbdb-ckn717nucKQABiiI4AUiM8UoT4k9HfD4fH3giJX2ZhfzL-QKf-b5Omj-PCeRQOGR_pQYjTU12s-JoQ3g0RguuwdScaEFv0I22oDayzicKIvtNWh0mZApxatJQwxkRFUiFd11F68tgjVSZm1BnyQNo5lShxLqZG8rEyDdGroScd64R_QEWOXye9Cx27p6sDHZiOCqvwq4MbtclUlVXiBjfLFS8Knq-W1U27UbJQq6xZrtdVltdNmol8KZdqtcaiELVc3-gNT3meVmmRrnmxrBZLkYo8U6ullMUyL1csT-nUmYUxx27h_OFmlMPNMl1lZXFjRI0mjMU052MG4FRV-w2ZJ_VwCCxPjQ4xPDuIOpqx_ib7YsuKO-mahhXbK7m-8a4DI347J1SBEzhTMRxuBm82lwX5Qcd2qOdSnGabH0nv3a8o6ZI2xk53sTn844b_JwAA__-kr-3g">