diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -1082,6 +1082,7 @@ if (symIndex >= syms.size()) fatal(toString(obj) + ": invalid symbol index in addrsig section"); markAddrsig(syms[symIndex]); + syms[symIndex]->isAddrsig = true; cur += size; } } else { @@ -2099,6 +2100,11 @@ run(); } + // Find symbols in .addrsig table before resolving symbols in case of any of + // those symbols is undefined. + if (config->doICF != ICFLevel::None) + findKeepUniqueSections(); + // At this point, we should not have any symbols that cannot be resolved. // If we are going to do codegen for link-time optimization, check for // unresolvable symbols first, so we don't spend time generating code that @@ -2224,10 +2230,8 @@ convertResources(); // Identify identical COMDAT sections to merge them. - if (config->doICF != ICFLevel::None) { - findKeepUniqueSections(); + if (config->doICF != ICFLevel::None) doICF(symtab->getChunks(), config->doICF); - } // Write the result. writeResult(); diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -357,6 +357,8 @@ ++symIndex; if (!sym) continue; + if (sym->isAddrsig) + continue; if (undefs.count(sym)) { auto it = firstDiag.find(sym); if (it == firstDiag.end()) { diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h --- a/lld/COFF/Symbols.h +++ b/lld/COFF/Symbols.h @@ -104,7 +104,8 @@ : symbolKind(k), isExternal(true), isCOMDAT(false), writtenToSymtab(false), pendingArchiveLoad(false), isGCRoot(false), isRuntimePseudoReloc(false), deferUndefined(false), canInline(true), - nameSize(n.size()), nameData(n.empty() ? nullptr : n.data()) {} + isAddrsig(false), nameSize(n.size()), + nameData(n.empty() ? nullptr : n.data()) {} const unsigned symbolKind : 8; unsigned isExternal : 1; @@ -140,6 +141,10 @@ // doesn't know the final contents of the symbol. unsigned canInline : 1; + // True if the symbol is in .addrsig table. So we don't report it as undefined + // when resolving symbols. + unsigned isAddrsig : 1; + protected: // Symbol name length. Assume symbol lengths fit in a 32-bit integer. uint32_t nameSize; diff --git a/lld/test/COFF/undefined-symbol-addrsig.s b/lld/test/COFF/undefined-symbol-addrsig.s new file mode 100644 --- /dev/null +++ b/lld/test/COFF/undefined-symbol-addrsig.s @@ -0,0 +1,13 @@ +# REQUIRES: x86 +# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s +# RUN: lld-link /entry:_start /subsystem:console %t.obj + +.text +.globl _start +_start: + ret + +.global bar + +.addrsig +.addrsig_sym bar