[lld] r176583 - [ELF] Order weak symbols properly

Shankar Easwaran shankare at codeaurora.org
Wed Mar 6 13:59:28 PST 2013


Author: shankare
Date: Wed Mar  6 15:59:27 2013
New Revision: 176583

URL: http://llvm.org/viewvc/llvm-project?rev=176583&view=rev
Log:
[ELF] Order weak symbols properly

Added:
    lld/trunk/test/elf/X86_64/
    lld/trunk/test/elf/X86_64/Inputs/
    lld/trunk/test/elf/X86_64/Inputs/multi-ovrd.c
    lld/trunk/test/elf/X86_64/Inputs/multi-ovrd.o   (with props)
    lld/trunk/test/elf/X86_64/Inputs/multi-weak.c
    lld/trunk/test/elf/X86_64/Inputs/multi-weak.o   (with props)
    lld/trunk/test/elf/X86_64/Inputs/ovrd.c
    lld/trunk/test/elf/X86_64/Inputs/ovrd.o   (with props)
    lld/trunk/test/elf/X86_64/Inputs/weak-zero-sized.o   (with props)
    lld/trunk/test/elf/X86_64/Inputs/weak.c
    lld/trunk/test/elf/X86_64/Inputs/weak.o   (with props)
    lld/trunk/test/elf/X86_64/multi-weak-override.test
    lld/trunk/test/elf/X86_64/multi-weak-syms-order.test
    lld/trunk/test/elf/X86_64/weak-override.test
    lld/trunk/test/elf/X86_64/weak-zero-sized.test
Modified:
    lld/trunk/lib/Passes/LayoutPass.cpp
    lld/trunk/lib/ReaderWriter/ELF/File.h

Modified: lld/trunk/lib/Passes/LayoutPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Passes/LayoutPass.cpp?rev=176583&r1=176582&r2=176583&view=diff
==============================================================================
--- lld/trunk/lib/Passes/LayoutPass.cpp (original)
+++ lld/trunk/lib/Passes/LayoutPass.cpp Wed Mar  6 15:59:27 2013
@@ -154,11 +154,20 @@ void LayoutPass::buildFollowOnTable(Muta
           } 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 @@ void LayoutPass::buildFollowOnTable(Muta
               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,29 @@ void LayoutPass::buildFollowOnTable(Muta
               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

Modified: lld/trunk/lib/ReaderWriter/ELF/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/File.h?rev=176583&r1=176582&r2=176583&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/File.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/File.h Wed Mar  6 15:59:27 2013
@@ -346,6 +346,11 @@ public:
       }
 
       ELFDefinedAtom<ELFT> *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<ELFT> *anonAtom = nullptr;
+      ELFReference<ELFT> *anonPrecededBy = nullptr;
+      ELFReference<ELFT> *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 @@ public:
           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<ELFT> *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<ELFT>(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<ELFT> *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 @@ public:
               "", sectionName, sym, i.first,
               ArrayRef<uint8_t>((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<ELFT>(lld::Reference::kindLayoutAfter);
+          anonPrecededBy = new (_readerStorage)
+              ELFReference<ELFT>(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<uint8_t> symbolData = ArrayRef<uint8_t>(
             (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<ELFT> *followOn = nullptr;
-        if (!isCommon && previous_atom) {
-          followOn = new (_readerStorage)
-              ELFReference<ELFT>(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 @@ public:
         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<ELFT> *wFollowedBy = new (_readerStorage)
+              ELFReference<ELFT>(lld::Reference::kindLayoutAfter);
+          wFollowedBy->setTarget(anonAtom);
+          newAtom->addReference(wFollowedBy);
+        }
+
         if (followOn) {
           ELFReference<ELFT> *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 @@ public:
 
         // 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);

Added: lld/trunk/test/elf/X86_64/Inputs/multi-ovrd.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/multi-ovrd.c?rev=176583&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/Inputs/multi-ovrd.c (added)
+++ lld/trunk/test/elf/X86_64/Inputs/multi-ovrd.c Wed Mar  6 15:59:27 2013
@@ -0,0 +1,10 @@
+#include <stdio.h>
+void f(void)
+{
+        printf("overridden f!\n");
+}
+
+void g(void)
+{
+        printf("overridden g!\n");
+}

Added: lld/trunk/test/elf/X86_64/Inputs/multi-ovrd.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/multi-ovrd.o?rev=176583&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lld/trunk/test/elf/X86_64/Inputs/multi-ovrd.o
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: lld/trunk/test/elf/X86_64/Inputs/multi-weak.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/multi-weak.c?rev=176583&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/Inputs/multi-weak.c (added)
+++ lld/trunk/test/elf/X86_64/Inputs/multi-weak.c Wed Mar  6 15:59:27 2013
@@ -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;
+}

Added: lld/trunk/test/elf/X86_64/Inputs/multi-weak.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/multi-weak.o?rev=176583&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lld/trunk/test/elf/X86_64/Inputs/multi-weak.o
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: lld/trunk/test/elf/X86_64/Inputs/ovrd.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/ovrd.c?rev=176583&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/Inputs/ovrd.c (added)
+++ lld/trunk/test/elf/X86_64/Inputs/ovrd.c Wed Mar  6 15:59:27 2013
@@ -0,0 +1,6 @@
+#include <stdio.h>
+void f(void)
+{
+        printf("overridden f!\n");
+}
+

Added: lld/trunk/test/elf/X86_64/Inputs/ovrd.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/ovrd.o?rev=176583&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lld/trunk/test/elf/X86_64/Inputs/ovrd.o
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: lld/trunk/test/elf/X86_64/Inputs/weak-zero-sized.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/weak-zero-sized.o?rev=176583&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lld/trunk/test/elf/X86_64/Inputs/weak-zero-sized.o
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: lld/trunk/test/elf/X86_64/Inputs/weak.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/weak.c?rev=176583&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/Inputs/weak.c (added)
+++ lld/trunk/test/elf/X86_64/Inputs/weak.c Wed Mar  6 15:59:27 2013
@@ -0,0 +1,14 @@
+int fn()
+{
+  return 0;
+}
+
+void __attribute__((weak)) f()
+{
+        printf("original f..\n");
+}
+int main(void)
+{
+        f();
+        return 0;
+}

Added: lld/trunk/test/elf/X86_64/Inputs/weak.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/weak.o?rev=176583&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lld/trunk/test/elf/X86_64/Inputs/weak.o
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: lld/trunk/test/elf/X86_64/multi-weak-override.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/multi-weak-override.test?rev=176583&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/multi-weak-override.test (added)
+++ lld/trunk/test/elf/X86_64/multi-weak-override.test Wed Mar  6 15:59:27 2013
@@ -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

Added: lld/trunk/test/elf/X86_64/multi-weak-syms-order.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/multi-weak-syms-order.test?rev=176583&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/multi-weak-syms-order.test (added)
+++ lld/trunk/test/elf/X86_64/multi-weak-syms-order.test Wed Mar  6 15:59:27 2013
@@ -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

Added: lld/trunk/test/elf/X86_64/weak-override.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/weak-override.test?rev=176583&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/weak-override.test (added)
+++ lld/trunk/test/elf/X86_64/weak-override.test Wed Mar  6 15:59:27 2013
@@ -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

Added: lld/trunk/test/elf/X86_64/weak-zero-sized.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/weak-zero-sized.test?rev=176583&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/weak-zero-sized.test (added)
+++ lld/trunk/test/elf/X86_64/weak-zero-sized.test Wed Mar  6 15:59:27 2013
@@ -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





More information about the llvm-commits mailing list