Index: lib/Passes/LayoutPass.cpp =================================================================== --- lib/Passes/LayoutPass.cpp +++ lib/Passes/LayoutPass.cpp @@ -154,11 +154,20 @@ } else { // the atom could be part of chain already // Get to the root of the chain const DefinedAtom *a = _followOnRoots[targetAtom]; + const DefinedAtom *targetPrevAtom = nullptr; + + // If the size of the atom is 0, and the target + // is already part of a chain, lets bring the current + // atom into the chain + size_t currentAtomSize = (*ai).size(); + // Lets add to the chain only if the atoms that // appear before the targetAtom in the chain // are of size 0 bool foundNonZeroSizeAtom = false; while (true) { + targetPrevAtom = a; + // Set all the follow on's for the targetAtom to be // the current root AtomToAtomT::iterator targetFollowOnAtomsIter = @@ -169,12 +178,14 @@ else break; - if (a->size() != 0) { + if ((a->size() != 0) && (currentAtomSize != 0)) { foundNonZeroSizeAtom = true; break; } + if (a == targetAtom) break; + } // while true if (foundNonZeroSizeAtom) { // TODO: print warning that an impossible layout @@ -183,20 +194,30 @@ break; } - _followOnNexts[ai] = _followOnRoots[targetAtom]; - // Set the root of all atoms in the - a = _followOnRoots[targetAtom]; - while (true) { - _followOnRoots[a] = _followOnRoots[ai]; - // Set all the follow on's for the targetAtom to be - // the current root - AtomToAtomT::iterator targetFollowOnAtomsIter = - _followOnNexts.find(a); - if (targetFollowOnAtomsIter != _followOnNexts.end()) - a = targetFollowOnAtomsIter->second; - else - break; - } // while true + // If the atom is a zero sized atom, then make the target + // follow the zero sized atom, as the zero sized atom may be + // a weak symbol + if ((currentAtomSize == 0) && (targetPrevAtom)) { + _followOnNexts[targetPrevAtom] = ai; + _followOnRoots[ai] = _followOnRoots[targetPrevAtom]; + _followOnNexts[ai] = targetAtom; + } + else { + _followOnNexts[ai] = _followOnRoots[targetAtom]; + // Set the root of all atoms in the + a = _followOnRoots[targetAtom]; + while (true) { + _followOnRoots[a] = _followOnRoots[ai]; + // Set all the follow on's for the targetAtom to be + // the current root + AtomToAtomT::iterator targetFollowOnAtomsIter = + _followOnNexts.find(a); + if (targetFollowOnAtomsIter != _followOnNexts.end()) + a = targetFollowOnAtomsIter->second; + else + break; + } // while true + } // end else (currentAtomSize != 0) } // end else } // else } // kindLayoutAfter Index: lib/ReaderWriter/ELF/File.h =================================================================== --- lib/ReaderWriter/ELF/File.h +++ lib/ReaderWriter/ELF/File.h @@ -346,6 +346,11 @@ } ELFDefinedAtom *previous_atom = nullptr; + // Don't allocate content to a weak symbol, as they may be merged away. + // Create an anonymous atom to hold the data. + ELFDefinedAtom *anonAtom = nullptr; + ELFReference *anonPrecededBy = nullptr; + ELFReference *anonFollowedBy = nullptr; // i.first is the section the symbol lives in for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) { @@ -380,9 +385,29 @@ contentSize = isCommon ? 0 : (*(si + 1))->st_value - (*si)->st_value; } + // Check to see if we need to add the FollowOn Reference + // We dont want to do for symbols that are + // a) common symbols + ELFReference *followOn = nullptr; + if (!isCommon && previous_atom) { + // Replace the followon atom with the anonymous + // atom that we created, so that the next symbol + // that we create is a followon from the anonymous + // atom + if (!anonFollowedBy) { + followOn = new (_readerStorage) + ELFReference(lld::Reference::kindLayoutAfter); + previous_atom->addReference(followOn); + } + else + followOn = anonFollowedBy; + } + // Don't allocate content to a weak symbol, as they may be merged away. // Create an anonymous atom to hold the data. - ELFDefinedAtom *anonAtom = nullptr; + anonAtom = nullptr; + anonPrecededBy = nullptr; + anonFollowedBy = nullptr; if ((*si)->getBinding() == llvm::ELF::STB_WEAK && contentSize != 0) { // Create a new non-weak ELF symbol. auto sym = new (_readerStorage) Elf_Sym; @@ -392,26 +417,26 @@ "", sectionName, sym, i.first, ArrayRef((uint8_t *)sectionContents.data() + (*si)->st_value, contentSize)); + + // If this is the last atom, lets not create a followon + // reference + if ((si + 1) != se) + anonFollowedBy = new (_readerStorage) + ELFReference(lld::Reference::kindLayoutAfter); + anonPrecededBy = new (_readerStorage) + ELFReference(lld::Reference::kindLayoutBefore); + // Add the references to the anonymous atom that we created + if (anonFollowedBy) + anonAtom->addReference(anonFollowedBy); + anonAtom->addReference(anonPrecededBy); + if (previous_atom) + anonPrecededBy->setTarget(previous_atom); contentSize = 0; } ArrayRef symbolData = ArrayRef( (uint8_t *)sectionContents.data() + (*si)->st_value, contentSize); - // Check to see if we need to add the FollowOn Reference - // We dont want to do for symbols that are - // a) common symbols - // so, lets add a follow-on reference from the previous atom to the - // current atom as well as lets add a preceded-by reference from the - // current atom to the previous atom, so that the previous atom - // is not removed in any case - ELFReference *followOn = nullptr; - if (!isCommon && previous_atom) { - followOn = new (_readerStorage) - ELFReference(lld::Reference::kindLayoutAfter); - previous_atom->addReference(followOn); - } - // If the linker finds that a section has global atoms that are in a // mergeable section, treat them as defined atoms as they shouldnt be // merged away as well as these symbols have to be part of symbol @@ -434,11 +459,24 @@ auto newAtom = createDefinedAtomAndAssignRelocations( symbolName, sectionName, *si, i.first, symbolData); - // If we are inserting a followOn reference, lets add a precededBy - // reference too + // If the atom was a weak symbol, lets create a followon + // reference to the anonymous atom that we created + if (((*si)->getBinding() == llvm::ELF::STB_WEAK) && (anonAtom)) { + ELFReference *wFollowedBy = new (_readerStorage) + ELFReference(lld::Reference::kindLayoutAfter); + wFollowedBy->setTarget(anonAtom); + newAtom->addReference(wFollowedBy); + } + if (followOn) { ELFReference *precededby = nullptr; - followOn->setTarget(newAtom); + // Set the followon atom to the weak atom + // that we have created, so that they would + // alias when the file gets written + if (anonAtom) + followOn->setTarget(anonAtom); + else + followOn->setTarget(newAtom); // Add a preceded by reference only if the current atom is not a // weak atom if ((*si)->getBinding() != llvm::ELF::STB_WEAK) { @@ -451,7 +489,9 @@ // The previous atom is always the atom created before unless // the atom is a weak atom - if ((*si)->getBinding() != llvm::ELF::STB_WEAK) + if (anonAtom) + previous_atom = anonAtom; + else previous_atom = newAtom; _definedAtoms._atoms.push_back(newAtom); Index: test/elf/X86_64/Inputs/multi-ovrd.c =================================================================== --- test/elf/X86_64/Inputs/multi-ovrd.c +++ test/elf/X86_64/Inputs/multi-ovrd.c @@ -0,0 +1,10 @@ +#include +void f(void) +{ + printf("overridden f!\n"); +} + +void g(void) +{ + printf("overridden g!\n"); +} Index: test/elf/X86_64/Inputs/multi-weak.c =================================================================== --- test/elf/X86_64/Inputs/multi-weak.c +++ test/elf/X86_64/Inputs/multi-weak.c @@ -0,0 +1,20 @@ +int fn() +{ + return 0; +} + +void __attribute__((weak)) f() +{ + printf("original f..\n"); +} + +void __attribute__((weak)) g() +{ + printf("original f..\n"); +} + +int main(void) +{ + f(); + return 0; +} Index: test/elf/X86_64/Inputs/ovrd.c =================================================================== --- test/elf/X86_64/Inputs/ovrd.c +++ test/elf/X86_64/Inputs/ovrd.c @@ -0,0 +1,6 @@ +#include +void f(void) +{ + printf("overridden f!\n"); +} + Index: test/elf/X86_64/Inputs/weak.c =================================================================== --- test/elf/X86_64/Inputs/weak.c +++ test/elf/X86_64/Inputs/weak.c @@ -0,0 +1,14 @@ +int fn() +{ + return 0; +} + +void __attribute__((weak)) f() +{ + printf("original f..\n"); +} +int main(void) +{ + f(); + return 0; +} Index: test/elf/X86_64/multi-weak-override.test =================================================================== --- test/elf/X86_64/multi-weak-override.test +++ test/elf/X86_64/multi-weak-override.test @@ -0,0 +1,15 @@ +# Test for weak symbol getting overridden +RUN: lld-core -reader ELF -writer ELF -arch x86_64 %p/Inputs/multi-weak.o \ +RUN: %p/Inputs/multi-ovrd.o -o %t +RUN: llvm-nm -n %t | FileCheck -check-prefix=WEAKORDER %s +RUN: lld-core -reader ELF -arch x86_64 %p/Inputs/multi-weak.o \ +RUN: %p/Inputs/multi-ovrd.o -layout-pass=true -o %t2 +RUN: FileCheck -check-prefix=WEAKATOMSORDER %s < %t2 + +WEAKORDER: 0040011c T f +WEAKORDER: 0040012c T g + +WEAKATOMSORDER: - ref-name: L002 +WEAKATOMSORDER: - ref-name: L003 +WEAKATOMSORDER: - name: f +WEAKATOMSORDER: - name: g Index: test/elf/X86_64/multi-weak-syms-order.test =================================================================== --- test/elf/X86_64/multi-weak-syms-order.test +++ test/elf/X86_64/multi-weak-syms-order.test @@ -0,0 +1,19 @@ +# Test for weak symbol getting overridden +RUN: lld-core -reader ELF -writer ELF -arch x86_64 %p/Inputs/multi-weak.o \ +RUN: -o %t +RUN: llvm-nm -n %t | FileCheck -check-prefix=WEAKORDER %s +RUN: lld-core -reader ELF -arch x86_64 %p/Inputs/multi-weak.o \ +RUN: -layout-pass=true -o %t2 +RUN: FileCheck -check-prefix=WEAKATOMSORDER %s < %t2 + +WEAKORDER: 004000c0 T fn +WEAKORDER: 004000cb T .text +WEAKORDER: 004000cb T f +WEAKORDER: 004000db T .text +WEAKORDER: 004000db T g +WEAKORDER: 004000eb T main + +WEAKATOMSORDER: - name: f +WEAKATOMSORDER: - ref-name: L004 +WEAKATOMSORDER: - name: g +WEAKATOMSORDER: - ref-name: L005 Index: test/elf/X86_64/weak-override.test =================================================================== --- test/elf/X86_64/weak-override.test +++ test/elf/X86_64/weak-override.test @@ -0,0 +1,56 @@ +# Test for weak symbol getting overridden +RUN: lld-core -reader ELF -writer ELF -arch x86_64 %p/Inputs/weak.o \ +RUN: %p/Inputs/ovrd.o -o %t +RUN: llvm-nm %t | FileCheck -check-prefix=WEAKORDER %s +RUN: lld-core -reader ELF -arch x86_64 %p/Inputs/weak.o \ +RUN: %p/Inputs/ovrd.o -layout-pass=true -o %t2 +RUN: FileCheck -check-prefix=WEAKATOMSORDER %s < %t2 + +WEAKORDER: 004000fc T f + +WEAKATOMSORDER: - name: .text +WEAKATOMSORDER: references: +WEAKATOMSORDER: - kind: layout-after +WEAKATOMSORDER: offset: 0 +WEAKATOMSORDER: target: fn +WEAKATOMSORDER: - name: fn +WEAKATOMSORDER: references: +WEAKATOMSORDER: - kind: layout-after +WEAKATOMSORDER: offset: 0 +WEAKATOMSORDER: target: L001 +WEAKATOMSORDER: - ref-name: L001 +WEAKATOMSORDER: scope: global +WEAKATOMSORDER: content: [ 55, 48, 89, E5, BF, 00, 00, 00, 00, E8, 00, 00, +WEAKATOMSORDER: 00, 00, 5D, C3 ] +WEAKATOMSORDER: references: +WEAKATOMSORDER: - kind: layout-after +WEAKATOMSORDER: offset: 0 +WEAKATOMSORDER: target: main +WEAKATOMSORDER: - kind: layout-before +WEAKATOMSORDER: offset: 0 +WEAKATOMSORDER: target: fn +WEAKATOMSORDER: - name: main +WEAKATOMSORDER: scope: global +WEAKATOMSORDER: content: [ 55, 48, 89, E5, B8, 00, 00, 00, 00, E8, 00, 00, +WEAKATOMSORDER: 00, 00, B8, 00, 00, 00, 00, 5D, C3 ] +WEAKATOMSORDER: references: +WEAKATOMSORDER: - kind: call32 +WEAKATOMSORDER: offset: 10 +WEAKATOMSORDER: target: f +WEAKATOMSORDER: addend: -4 +WEAKATOMSORDER: - kind: layout-before +WEAKATOMSORDER: offset: 0 +WEAKATOMSORDER: target: L001 +WEAKATOMSORDER: - name: .text +WEAKATOMSORDER: section-name: .text +WEAKATOMSORDER: references: +WEAKATOMSORDER: - kind: layout-after +WEAKATOMSORDER: offset: 0 +WEAKATOMSORDER: target: f +WEAKATOMSORDER: - name: f +WEAKATOMSORDER: scope: global +WEAKATOMSORDER: content: [ 55, 48, 89, E5, BF, 00, 00, 00, 00, E8, 00, 00, +WEAKATOMSORDER: 00, 00, 5D, C3 ] +WEAKATOMSORDER: references: +WEAKATOMSORDER: - kind: layout-before +WEAKATOMSORDER: offset: 0 Index: test/elf/X86_64/weak-zero-sized.test =================================================================== --- test/elf/X86_64/weak-zero-sized.test +++ test/elf/X86_64/weak-zero-sized.test @@ -0,0 +1,34 @@ +# Test for zero sized weak atoms, there is only a single weak atom +RUN: lld-core -reader ELF -writer ELF -arch x86_64 %p/Inputs/weak-zero-sized.o \ +RUN: -o %t +RUN: llvm-nm %t | FileCheck -check-prefix=WEAKORDER %s +RUN: lld-core -reader ELF -arch x86_64 %p/Inputs/weak-zero-sized.o \ +RUN: -layout-pass=true -o %t2 +RUN: FileCheck -check-prefix=WEAKATOMSORDER %s < %t2 + +WEAKORDER: 004000b0 T _start + +WEAKATOMSORDER: - name: .text +WEAKATOMSORDER: alignment: 2^2 +WEAKATOMSORDER: section-name: .text +WEAKATOMSORDER: - kind: layout-after +WEAKATOMSORDER: offset: 0 +WEAKATOMSORDER: target: L001 +WEAKATOMSORDER: - name: _start +WEAKATOMSORDER: scope: global +WEAKATOMSORDER: merge: as-weak +WEAKATOMSORDER: alignment: 2^2 +WEAKATOMSORDER: section-name: .text +WEAKATOMSORDER: references: +WEAKATOMSORDER: - kind: layout-after +WEAKATOMSORDER: offset: 0 +WEAKATOMSORDER: target: L001 +WEAKATOMSORDER: - ref-name: L001 +WEAKATOMSORDER: scope: global +WEAKATOMSORDER: content: [ C3 ] +WEAKATOMSORDER: alignment: 2^2 +WEAKATOMSORDER: section-name: .text +WEAKATOMSORDER: references: +WEAKATOMSORDER: - kind: layout-before +WEAKATOMSORDER: offset: 0 +WEAKATOMSORDER: target: .text