diff options
| author | Rui Ueyama <ruiu@google.com> | 2014-05-14 17:29:27 +0000 |
|---|---|---|
| committer | Rui Ueyama <ruiu@google.com> | 2014-05-14 17:29:27 +0000 |
| commit | 2a522511535cade4e6470666e0ac1f4e33a903d3 (patch) | |
| tree | e540e40b7da2a010006475be54b5ac9ef13a6c80 | |
| parent | 24feaf70aaeee0325d8008f7cb22d58c5282e46e (diff) | |
| download | bcm5719-llvm-2a522511535cade4e6470666e0ac1f4e33a903d3.tar.gz bcm5719-llvm-2a522511535cade4e6470666e0ac1f4e33a903d3.zip | |
Fix regression introduced in r205566.
In r205566, I made a change to Resolver so that Resolver revisit
only archive files in --start-group and --end-group pair. That's
not correct, as it also has to revisit DSO files.
This patch is to fix the issue.
Added a test to demonstrate the fix. I confirmed that it succeeded
before r205566, failed after r205566, and is ok with this patch.
Differential Revision: http://reviews.llvm.org/D3734
llvm-svn: 208797
| -rw-r--r-- | lld/include/lld/Core/Resolver.h | 2 | ||||
| -rw-r--r-- | lld/include/lld/Core/SymbolTable.h | 12 | ||||
| -rw-r--r-- | lld/include/lld/Driver/GnuLdInputGraph.h | 5 | ||||
| -rw-r--r-- | lld/lib/Core/Resolver.cpp | 21 | ||||
| -rw-r--r-- | lld/lib/Core/SymbolTable.cpp | 28 | ||||
| -rw-r--r-- | lld/test/elf/X86_64/Inputs/group/group.sh | 1 | ||||
| -rwxr-xr-x | lld/test/elf/X86_64/Inputs/group/libfn2.so | bin | 0 -> 9624 bytes | |||
| -rw-r--r-- | lld/test/elf/X86_64/startGroupEndGroup.test | 5 |
8 files changed, 44 insertions, 30 deletions
diff --git a/lld/include/lld/Core/Resolver.h b/lld/include/lld/Core/Resolver.h index 621e8d1b206..22af4e21437 100644 --- a/lld/include/lld/Core/Resolver.h +++ b/lld/include/lld/Core/Resolver.h @@ -33,7 +33,7 @@ public: // InputFiles::Handler methods void doDefinedAtom(const DefinedAtom&); - void doUndefinedAtom(const UndefinedAtom&); + bool doUndefinedAtom(const UndefinedAtom &); void doSharedLibraryAtom(const SharedLibraryAtom &); void doAbsoluteAtom(const AbsoluteAtom &); diff --git a/lld/include/lld/Core/SymbolTable.h b/lld/include/lld/Core/SymbolTable.h index 26bdf820104..73317070cfc 100644 --- a/lld/include/lld/Core/SymbolTable.h +++ b/lld/include/lld/Core/SymbolTable.h @@ -39,16 +39,16 @@ public: explicit SymbolTable(const LinkingContext &); /// @brief add atom to symbol table - void add(const DefinedAtom &); + bool add(const DefinedAtom &); /// @brief add atom to symbol table - void add(const UndefinedAtom &); + bool add(const UndefinedAtom &); /// @brief add atom to symbol table - void add(const SharedLibraryAtom &); + bool add(const SharedLibraryAtom &); /// @brief add atom to symbol table - void add(const AbsoluteAtom &); + bool add(const AbsoluteAtom &); /// @brief checks if name is in symbol table and if so atom is not /// UndefinedAtom @@ -102,8 +102,8 @@ private: }; typedef llvm::DenseSet<const DefinedAtom*, AtomMappingInfo> AtomContentSet; - void addByName(const Atom &); - void addByContent(const DefinedAtom &); + bool addByName(const Atom &); + bool addByContent(const DefinedAtom &); const LinkingContext &_context; AtomToAtom _replacedAtoms; diff --git a/lld/include/lld/Driver/GnuLdInputGraph.h b/lld/include/lld/Driver/GnuLdInputGraph.h index b14017f36a7..5389248b410 100644 --- a/lld/include/lld/Driver/GnuLdInputGraph.h +++ b/lld/include/lld/Driver/GnuLdInputGraph.h @@ -80,8 +80,9 @@ public: /// to start processing files as part of the input element from beginning. /// Reset the next file index to 0 only if the node is an archive library. void resetNextIndex() override { - if (_files[0]->kind() == File::kindArchiveLibrary && - !_attributes._isWholeArchive) { + auto kind = _files[0]->kind(); + if (kind == File::kindSharedLibrary || + (kind == File::kindArchiveLibrary && !_attributes._isWholeArchive)) { _nextFileIndex = 0; } } diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp index d139f8a4625..6ed35598d60 100644 --- a/lld/lib/Core/Resolver.cpp +++ b/lld/lib/Core/Resolver.cpp @@ -48,15 +48,12 @@ private: } // namespace void Resolver::handleFile(const File &file) { - bool isEmpty = file.defined().empty() && file.undefined().empty() && - file.sharedLibrary().empty() && file.absolute().empty(); - if (isEmpty) - return; - + bool undefAdded = false; for (const DefinedAtom *atom : file.defined()) doDefinedAtom(*atom); for (const UndefinedAtom *atom : file.undefined()) - doUndefinedAtom(*atom); + if (doUndefinedAtom(*atom)) + undefAdded = true; for (const SharedLibraryAtom *atom : file.sharedLibrary()) doSharedLibraryAtom(*atom); for (const AbsoluteAtom *atom : file.absolute()) @@ -65,7 +62,9 @@ void Resolver::handleFile(const File &file) { // Notify the input file manager of the fact that we have made some progress // on linking using the current input file. It may want to know the fact for // --start-group/--end-group. - _context.getInputGraph().notifyProgress(); + if (undefAdded) { + _context.getInputGraph().notifyProgress(); + } } void Resolver::forEachUndefines(bool searchForOverrides, @@ -124,7 +123,7 @@ void Resolver::handleSharedLibrary(const File &file) { }); } -void Resolver::doUndefinedAtom(const UndefinedAtom &atom) { +bool Resolver::doUndefinedAtom(const UndefinedAtom &atom) { DEBUG_WITH_TYPE("resolver", llvm::dbgs() << " UndefinedAtom: " << llvm::format("0x%09lX", &atom) @@ -134,7 +133,7 @@ void Resolver::doUndefinedAtom(const UndefinedAtom &atom) { _atoms.push_back(&atom); // tell symbol table - _symbolTable.add(atom); + bool newUndefAdded = _symbolTable.add(atom); // If the undefined symbol has an alternative name, try to resolve the // symbol with the name to give it a second chance. This feature is used @@ -145,6 +144,7 @@ void Resolver::doUndefinedAtom(const UndefinedAtom &atom) { _symbolTable.addReplacement(&atom, fallbackAtom); } } + return newUndefAdded; } /// \brief Add the section group and the group-child reference members. @@ -178,7 +178,8 @@ bool Resolver::maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom) { return true; } -// called on each atom when a file is added +// Called on each atom when a file is added. Returns true if a given +// atom is added to the symbol table. void Resolver::doDefinedAtom(const DefinedAtom &atom) { DEBUG_WITH_TYPE("resolver", llvm::dbgs() << " DefinedAtom: " diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp index a6620753424..81ed9bb0b5e 100644 --- a/lld/lib/Core/SymbolTable.cpp +++ b/lld/lib/Core/SymbolTable.cpp @@ -32,26 +32,26 @@ namespace lld { SymbolTable::SymbolTable(const LinkingContext &context) : _context(context) {} -void SymbolTable::add(const UndefinedAtom &atom) { addByName(atom); } +bool SymbolTable::add(const UndefinedAtom &atom) { return addByName(atom); } -void SymbolTable::add(const SharedLibraryAtom &atom) { addByName(atom); } +bool SymbolTable::add(const SharedLibraryAtom &atom) { return addByName(atom); } -void SymbolTable::add(const AbsoluteAtom &atom) { addByName(atom); } +bool SymbolTable::add(const AbsoluteAtom &atom) { return addByName(atom); } -void SymbolTable::add(const DefinedAtom &atom) { +bool SymbolTable::add(const DefinedAtom &atom) { if (!atom.name().empty() && atom.scope() != DefinedAtom::scopeTranslationUnit) { // Named atoms cannot be merged by content. assert(atom.merge() != DefinedAtom::mergeByContent); // Track named atoms that are not scoped to file (static). - addByName(atom); - return; + return addByName(atom); } if (atom.merge() == DefinedAtom::mergeByContent) { // Named atoms cannot be merged by content. assert(atom.name().empty()); - addByContent(atom); + return addByContent(atom); } + return false; } const Atom *SymbolTable::findGroup(StringRef sym) { @@ -162,16 +162,20 @@ static uint64_t sectionSize(const DefinedAtom *atom) { + getSizeFollowReferences(atom, lld::Reference::kindLayoutAfter); } -void SymbolTable::addByName(const Atom &newAtom) { +bool SymbolTable::addByName(const Atom &newAtom) { StringRef name = newAtom.name(); assert(!name.empty()); const Atom *existing = findByName(name); if (existing == nullptr) { // Name is not in symbol table yet, add it associate with this atom. _nameTable[name] = &newAtom; - return; + return true; } + // Do nothing if the same object is added more than once. + if (existing == &newAtom) + return false; + // Name is already in symbol table and associated with another atom. bool useNew = true; switch (collide(existing->definition(), newAtom.definition())) { @@ -301,6 +305,7 @@ void SymbolTable::addByName(const Atom &newAtom) { // New atom is not being used. Add it to replacement table. _replacedAtoms[&newAtom] = existing; } + return false; } unsigned SymbolTable::AtomMappingInfo::getHashValue(const DefinedAtom *atom) { @@ -332,17 +337,18 @@ bool SymbolTable::AtomMappingInfo::isEqual(const DefinedAtom * const l, return memcmp(lc.data(), rc.data(), lc.size()) == 0; } -void SymbolTable::addByContent(const DefinedAtom & newAtom) { +bool SymbolTable::addByContent(const DefinedAtom &newAtom) { // Currently only read-only constants can be merged. assert(newAtom.permissions() == DefinedAtom::permR__); AtomContentSet::iterator pos = _contentTable.find(&newAtom); if (pos == _contentTable.end()) { _contentTable.insert(&newAtom); - return; + return true; } const Atom* existing = *pos; // New atom is not being used. Add it to replacement table. _replacedAtoms[&newAtom] = existing; + return false; } const Atom *SymbolTable::findByName(StringRef sym) { diff --git a/lld/test/elf/X86_64/Inputs/group/group.sh b/lld/test/elf/X86_64/Inputs/group/group.sh index 336226abd9b..2eba1030160 100644 --- a/lld/test/elf/X86_64/Inputs/group/group.sh +++ b/lld/test/elf/X86_64/Inputs/group/group.sh @@ -31,6 +31,7 @@ fn2(); gcc -c 1.c fn.c fn2.c fn1.c ar cr libfn.a fn.o fn2.o ar cr libfn1.a fn1.o +lld -flavor gnu -target x86_64 -shared -o libfn2.so fn2.o lld -flavor gnu -target x86_64 1.o libfn.a libfn1.a -o x lld -flavor gnu -target x86_64 1.o --start-group libfn.a libfn1.a --end-group -o x lld -flavor gnu -target x86_64 1.o --start-group fn.o fn2.o fn1.o --end-group -o x diff --git a/lld/test/elf/X86_64/Inputs/group/libfn2.so b/lld/test/elf/X86_64/Inputs/group/libfn2.so Binary files differnew file mode 100755 index 00000000000..7ce86737391 --- /dev/null +++ b/lld/test/elf/X86_64/Inputs/group/libfn2.so diff --git a/lld/test/elf/X86_64/startGroupEndGroup.test b/lld/test/elf/X86_64/startGroupEndGroup.test index add3c41deae..ce1897683b3 100644 --- a/lld/test/elf/X86_64/startGroupEndGroup.test +++ b/lld/test/elf/X86_64/startGroupEndGroup.test @@ -18,6 +18,11 @@ RUN: lld -flavor gnu -target x86_64 %p/Inputs/group/1.o --start-group \ RUN: --whole-archive %p/Inputs/group/libfn.a --no-whole-archive \ RUN: %p/Inputs/group/libfn1.a --end-group -o %t3 +# Defined symbols in a shared library. +RUN: lld -flavor gnu -target x86_64 %p/Inputs/group/1.o --start-group \ +RUN: %p/Inputs/group/libfn2.so %p/Inputs/group/fn1.o %p/Inputs/group/fn.o \ +RUN: --end-group -o %t4 + # Test alias options too, as they are more widely used # Test group RUN: lld -flavor gnu -target x86_64 %p/Inputs/group/1.o '-(' \ |

