diff --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h --- a/llvm/include/llvm/Object/Archive.h +++ b/llvm/include/llvm/Object/Archive.h @@ -256,6 +256,8 @@ bool isEmpty() const; bool hasSymbolTable() const; + // Checks that iterating over the symbol table won't result in any errors. + bool isSymbolTableValid() const; StringRef getSymbolTable() const { return SymbolTable; } StringRef getStringTable() const { return StringTable; } uint32_t getNumberOfSymbols() const; diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp --- a/llvm/lib/Object/Archive.cpp +++ b/llvm/lib/Object/Archive.cpp @@ -993,3 +993,14 @@ bool Archive::isEmpty() const { return Data.getBufferSize() == 8; } bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); } + +bool Archive::isSymbolTableValid() const { + for (const Archive::Symbol &Sym : symbols()) { + Expected C = Sym.getMember(); + if (!C) { + consumeError(C.takeError()); + return false; + } + } + return true; +} diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp --- a/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/llvm/tools/llvm-ar/llvm-ar.cpp @@ -840,10 +840,10 @@ // When an archive is created or modified, if the s option is given, the // resulting archive will have a current symbol table. If the S option // is given, it will have no symbol table. - // In summary, we only need to update the symbol table if we have none. - // This is actually very common because of broken build systems that think - // they have to run ranlib. - if (OldArchive->hasSymbolTable()) + // In summary, we only need to update the symbol table if we have none, or if + // the current one is invalid. This is actually very common because of broken + // build systems that think they have to run ranlib. + if (OldArchive->hasSymbolTable() && OldArchive->isSymbolTableValid()) return; performWriteOperation(CreateSymTab, OldArchive, nullptr, nullptr);