[lld] r211106 - [PECOFF] Support COMDAT associative sections.

Rui Ueyama ruiu at google.com
Tue Jun 17 09:19:33 PDT 2014


Author: ruiu
Date: Tue Jun 17 11:19:33 2014
New Revision: 211106

URL: http://llvm.org/viewvc/llvm-project?rev=211106&view=rev
Log:
[PECOFF] Support COMDAT associative sections.

COFF supports a feature similar to ELF's section groups. This
patch implements it.

In ELF, section groups are identified by their names, and they are
treated somewhat differently from regular symbols. In COFF, the
feature is realized in a more straightforward way. A section can
have an annotation saying "if Nth section is linked, link this
section too."

I added a new reference type, kindAssociate. If a target atom is
coalesced away, the referring atom is removed by Resolver, so that
they are treated as a group.

Differential Revision: http://reviews.llvm.org/D4028

Added:
    lld/trunk/test/core/associates.objtxt
    lld/trunk/test/pecoff/Inputs/associative1.obj.yaml
    lld/trunk/test/pecoff/Inputs/associative3.obj.yaml
    lld/trunk/test/pecoff/associative.test
Modified:
    lld/trunk/include/lld/Core/Reference.h
    lld/trunk/include/lld/Core/Resolver.h
    lld/trunk/lib/Core/Resolver.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h
    lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
    lld/trunk/lib/ReaderWriter/Reader.cpp

Modified: lld/trunk/include/lld/Core/Reference.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Reference.h?rev=211106&r1=211105&r2=211106&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Reference.h (original)
+++ lld/trunk/include/lld/Core/Reference.h Tue Jun 17 11:19:33 2014
@@ -91,6 +91,7 @@ public:
     kindLayoutBefore = 3,
     // kindGroupChild is treated as a bidirected edge too.
     kindGroupChild = 4,
+    kindAssociate = 5,
   };
 
   // A value to be added to the value of a target

Modified: lld/trunk/include/lld/Core/Resolver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=211106&r1=211105&r2=211106&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Resolver.h (original)
+++ lld/trunk/include/lld/Core/Resolver.h Tue Jun 17 11:19:33 2014
@@ -105,6 +105,7 @@ private:
   std::vector<const Atom *>     _atoms;
   std::set<const Atom *>        _deadStripRoots;
   llvm::DenseSet<const Atom *>  _liveAtoms;
+  llvm::DenseSet<const Atom *>  _deadAtoms;
   std::unique_ptr<MergedFile>   _result;
   llvm::DenseMap<const Atom *, llvm::DenseSet<const Atom *>> _reverseRef;
 };

Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=211106&r1=211105&r2=211106&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Tue Jun 17 11:19:33 2014
@@ -277,6 +277,16 @@ void Resolver::updateReferences() {
   for (const Atom *atom : _atoms) {
     if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom)) {
       for (const Reference *ref : *defAtom) {
+        // A reference of type kindAssociate should't be updated.
+        // Instead, an atom having such reference will be removed
+        // if the target atom is coalesced away, so that they will
+        // go away as a group.
+        if (ref->kindNamespace() == lld::Reference::KindNamespace::all &&
+            ref->kindValue() == lld::Reference::kindAssociate) {
+          if (_symbolTable.isCoalescedAway(atom))
+            _deadAtoms.insert(ref->target());
+          continue;
+        }
         const Atom *newTarget = _symbolTable.replacement(ref->target());
         const_cast<Reference *>(ref)->setTarget(newTarget);
       }
@@ -399,7 +409,7 @@ bool Resolver::checkUndefines() {
 void Resolver::removeCoalescedAwayAtoms() {
   ScopedTask task(getDefaultDomain(), "removeCoalescedAwayAtoms");
   _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), [&](const Atom *a) {
-                 return _symbolTable.isCoalescedAway(a);
+                 return _symbolTable.isCoalescedAway(a) || _deadAtoms.count(a);
                }),
                _atoms.end());
 }

Modified: lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h?rev=211106&r1=211105&r2=211106&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h Tue Jun 17 11:19:33 2014
@@ -158,7 +158,6 @@ public:
   }
 
   void setAlignment(Alignment val) { _alignment = val; }
-
   SectionChoice sectionChoice() const override { return sectionCustomRequired; }
   StringRef customSectionName() const override { return _sectionName; }
   Scope scope() const override { return _scope; }
@@ -167,6 +166,13 @@ public:
   uint64_t ordinal() const override { return _ordinal; }
   Alignment alignment() const override { return _alignment; }
 
+  void addAssociate(const DefinedAtom *other) {
+    auto *ref = new COFFReference(other, 0, lld::Reference::kindAssociate,
+                                  Reference::KindNamespace::all,
+                                  Reference::KindArch::all);
+    addReference(std::unique_ptr<COFFReference>(ref));
+  }
+
 private:
   StringRef _sectionName;
   Scope _scope;

Modified: lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp?rev=211106&r1=211105&r2=211106&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp Tue Jun 17 11:19:33 2014
@@ -174,6 +174,9 @@ private:
   // A map to get whether the section allows its contents to be merged or not.
   std::map<const coff_section *, DefinedAtom::Merge> _merge;
 
+  // COMDAT associative sections
+  std::map<const coff_section *, std::set<const coff_section *>> _association;
+
   // A sorted map to find an atom from a section and an offset within
   // the section.
   std::map<const coff_section *,
@@ -544,6 +547,7 @@ std::error_code FileCOFF::cacheSectionAt
   // section. It feels to me that it's unnecessarily complicated, but this is
   // how COFF works.
   for (auto i : _auxSymbol) {
+    // Read a section from the file
     const coff_symbol *sym = i.first;
     if (sym->SectionNumber == llvm::COFF::IMAGE_SYM_ABSOLUTE ||
         sym->SectionNumber == llvm::COFF::IMAGE_SYM_UNDEFINED)
@@ -552,19 +556,22 @@ std::error_code FileCOFF::cacheSectionAt
     const coff_section *sec;
     if (std::error_code ec = _obj->getSection(sym->SectionNumber, sec))
       return ec;
-
-    if (_merge.count(sec))
-      continue;
-    if (!(sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_COMDAT))
-      continue;
-
-    _comdatSections.insert(sec);
-
-    if (sym->NumberOfAuxSymbols == 0)
-      return llvm::object::object_error::parse_failed;
     const coff_aux_section_definition *aux =
         reinterpret_cast<const coff_aux_section_definition *>(i.second);
-    _merge[sec] = getMerge(aux);
+
+    if (sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_COMDAT) {
+      // Read aux symbol data.
+      _comdatSections.insert(sec);
+      _merge[sec] = getMerge(aux);
+    }
+
+    // Handle associative sections.
+    if (aux->Selection == llvm::COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
+      const coff_section *parent;
+      if (std::error_code ec = _obj->getSection(aux->Number, parent))
+        return ec;
+      _association[parent].insert(sec);
+    }
   }
 
   // The sections that does not have auxiliary symbol are regular sections, in
@@ -699,6 +706,29 @@ std::error_code FileCOFF::AtomizeDefined
       definedAtoms.push_back(atom);
     }
   }
+
+  // A COMDAT section with SELECT_ASSOCIATIVE attribute refer to other
+  // section. If the referred section is linked to a binary, the
+  // referring section needs to be linked too. A typical use case of
+  // this attribute is a static initializer; a parent is a comdat BSS
+  // section, and a child is a static initializer code for the data.
+  //
+  // We add referring section contents to the referred section's
+  // associate list, so that Resolver takes care of them.
+  for (auto i : _association) {
+    const coff_section *parent = i.first;
+    const std::set<const coff_section *> &childSections = i.second;
+    assert(_sectionAtoms[parent].size() > 0);
+
+    COFFDefinedFileAtom *p = _sectionAtoms[parent][0];
+    for (const coff_section *sec : childSections) {
+      if (_sectionAtoms.count(sec)) {
+        assert(_sectionAtoms[sec].size() > 0);
+        p->addAssociate(_sectionAtoms[sec][0]);
+      }
+    }
+  }
+
   return std::error_code();
 }
 

Modified: lld/trunk/lib/ReaderWriter/Reader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/Reader.cpp?rev=211106&r1=211105&r2=211106&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/Reader.cpp (original)
+++ lld/trunk/lib/ReaderWriter/Reader.cpp Tue Jun 17 11:19:33 2014
@@ -51,6 +51,7 @@ static const Registry::KindStrings kindS
     {Reference::kindLayoutAfter, "layout-after"},
     {Reference::kindLayoutBefore, "layout-before"},
     {Reference::kindGroupChild, "group-child"},
+    {Reference::kindAssociate, "associate"},
     LLD_KIND_STRING_END};
 
 Registry::Registry() {

Added: lld/trunk/test/core/associates.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/core/associates.objtxt?rev=211106&view=auto
==============================================================================
--- lld/trunk/test/core/associates.objtxt (added)
+++ lld/trunk/test/core/associates.objtxt Tue Jun 17 11:19:33 2014
@@ -0,0 +1,30 @@
+# RUN: lld -core %s | FileCheck %s
+
+---
+defined-atoms:
+  - name:  f1
+    merge: as-weak
+    scope: global
+    references:
+      - kind:            associate
+        target:          f2
+  - name:  f2
+---
+defined-atoms:
+  - name:  f1
+    merge: as-weak
+    scope: global
+    references:
+      - kind:            associate
+        target:          f2
+  - name:  f2
+...
+
+# CHECK: defined-atoms:
+# CHECK:   - name:  f1
+# CHECK:     scope: global
+# CHECK:     references:
+# CHECK:       - kind:            associate
+# CHECK:         target:          f2
+# CHECK:   - name:  f2
+# CHECK-NOT: - name:  f2

Added: lld/trunk/test/pecoff/Inputs/associative1.obj.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/associative1.obj.yaml?rev=211106&view=auto
==============================================================================
--- lld/trunk/test/pecoff/Inputs/associative1.obj.yaml (added)
+++ lld/trunk/test/pecoff/Inputs/associative1.obj.yaml Tue Jun 17 11:19:33 2014
@@ -0,0 +1,53 @@
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_I386
+  Characteristics: []
+sections:
+  - Name:            .data
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+    Alignment:       4
+    SectionData:     00000000
+  - Name:            '.CRT$XCU'
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     77777777
+symbols:
+  - Name:            .data
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          4
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          0
+      Selection:       IMAGE_COMDAT_SELECT_ANY
+  - Name:            _var
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            '.CRT$XCU'
+    Value:           0
+    SectionNumber:   2
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          4
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          1
+      Selection:       IMAGE_COMDAT_SELECT_ASSOCIATIVE
+  - Name:            _init
+    Value:           0
+    SectionNumber:   2
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...

Added: lld/trunk/test/pecoff/Inputs/associative3.obj.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/associative3.obj.yaml?rev=211106&view=auto
==============================================================================
--- lld/trunk/test/pecoff/Inputs/associative3.obj.yaml (added)
+++ lld/trunk/test/pecoff/Inputs/associative3.obj.yaml Tue Jun 17 11:19:33 2014
@@ -0,0 +1,33 @@
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_I386
+  Characteristics: []
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     0000000000000000
+    Relocations:
+      - VirtualAddress:  4
+        SymbolName:      _var
+        Type:            IMAGE_REL_I386_DIR32
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+  - Name:            _main
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            _var
+    Value:           0
+    SectionNumber:   0
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...

Added: lld/trunk/test/pecoff/associative.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/associative.test?rev=211106&view=auto
==============================================================================
--- lld/trunk/test/pecoff/associative.test (added)
+++ lld/trunk/test/pecoff/associative.test Tue Jun 17 11:19:33 2014
@@ -0,0 +1,10 @@
+# RUN: yaml2obj %p/Inputs/associative1.obj.yaml > %t1.obj
+# RUN: yaml2obj %p/Inputs/associative1.obj.yaml > %t2.obj
+# RUN: yaml2obj %p/Inputs/associative3.obj.yaml > %t3.obj
+#
+# RUN: lld -flavor link /machine:x86 /subsystem:console /entry:main \
+# RUN:   /out:%t.exe -- %t1.obj %t2.obj %t3.obj
+# RUN: obj2yaml %t.exe | FileCheck %s
+
+CHECK: - Name: .CRT
+CHECK:   SectionData: '77777777'





More information about the llvm-commits mailing list