[lld] r204172 - [PECOFF] Support yet another new type of weak symbol.

Rui Ueyama ruiu at google.com
Tue Mar 18 12:37:51 PDT 2014


Author: ruiu
Date: Tue Mar 18 14:37:50 2014
New Revision: 204172

URL: http://llvm.org/viewvc/llvm-project?rev=204172&view=rev
Log:
[PECOFF] Support yet another new type of weak symbol.

COMDAT_SELECT_LARGEST is a COMDAT type that make linker to choose the largest
definition from among all of the definition of a symbol. If the size is the
same, the choice is arbitrary.

Differential Revision: http://llvm-reviews.chandlerc.com/D3011

Added:
    lld/trunk/test/pecoff/Inputs/merge-largest1.obj.yaml
    lld/trunk/test/pecoff/Inputs/merge-largest2.obj.yaml
    lld/trunk/test/pecoff/merge-largest.test
Modified:
    lld/trunk/include/lld/Core/DefinedAtom.h
    lld/trunk/lib/Core/SymbolTable.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
    lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp

Modified: lld/trunk/include/lld/Core/DefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=204172&r1=204171&r2=204172&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/DefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/DefinedAtom.h Tue Mar 18 14:37:50 2014
@@ -99,6 +99,7 @@ public:
     mergeAsWeakAndAddressUsed, // Is C++ definition inline definition whose
                                // address was taken.
     mergeSameNameAndSize,   // Another atom with different size is error
+    mergeByLargestSection,  // Choose an atom whose section is the largest.
     mergeByContent,         // Merge with other constants with same content.
   };
 

Modified: lld/trunk/lib/Core/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/SymbolTable.cpp?rev=204172&r1=204171&r2=204172&view=diff
==============================================================================
--- lld/trunk/lib/Core/SymbolTable.cpp (original)
+++ lld/trunk/lib/Core/SymbolTable.cpp Tue Mar 18 14:37:50 2014
@@ -102,13 +102,14 @@ enum MergeResolution {
   MCR_Error
 };
 
-static MergeResolution mergeCases[][5] = {
-  // no          tentative      weak          weakAddress   sameNameAndSize
-  {MCR_Error,    MCR_First,     MCR_First,    MCR_First,    MCR_SameSize}, // no
-  {MCR_Second,   MCR_Largest,   MCR_Second,   MCR_Second,   MCR_SameSize}, // tentative
-  {MCR_Second,   MCR_First,     MCR_First,    MCR_Second,   MCR_SameSize}, // weak
-  {MCR_Second,   MCR_First,     MCR_First,    MCR_First,    MCR_SameSize}, // weakAddress
-  {MCR_SameSize, MCR_SameSize,  MCR_SameSize, MCR_SameSize, MCR_SameSize}, // sameSize
+static MergeResolution mergeCases[][6] = {
+  // no          tentative      weak          weakAddress   sameNameAndSize largest
+  {MCR_Error,    MCR_First,     MCR_First,    MCR_First,    MCR_SameSize,   MCR_Largest},  // no
+  {MCR_Second,   MCR_Largest,   MCR_Second,   MCR_Second,   MCR_SameSize,   MCR_Largest},  // tentative
+  {MCR_Second,   MCR_First,     MCR_First,    MCR_Second,   MCR_SameSize,   MCR_Largest},  // weak
+  {MCR_Second,   MCR_First,     MCR_First,    MCR_First,    MCR_SameSize,   MCR_Largest},  // weakAddress
+  {MCR_SameSize, MCR_SameSize,  MCR_SameSize, MCR_SameSize, MCR_SameSize,   MCR_SameSize}, // sameSize
+  {MCR_Largest,  MCR_Largest,   MCR_Largest,  MCR_Largest,  MCR_SameSize,   MCR_Largest},  // largest
 };
 
 static MergeResolution mergeSelect(DefinedAtom::Merge first,
@@ -118,6 +119,33 @@ static MergeResolution mergeSelect(Defin
   return mergeCases[first][second];
 }
 
+static uint64_t getSizeFollowReferences(const DefinedAtom *atom, uint32_t kind) {
+  uint64_t size = 0;
+redo:
+  while (atom) {
+    for (const Reference *r : *atom) {
+      if (r->kindNamespace() == Reference::KindNamespace::all &&
+          r->kindArch() == Reference::KindArch::all &&
+          r->kindValue() == kind) {
+        atom = cast<DefinedAtom>(r->target());
+        size += atom->size();
+        goto redo;
+      }
+    }
+    break;
+  }
+  return size;
+}
+
+// Returns the size of the section containing the given atom. Atoms in the same
+// section are connected by layout-before and layout-after edges, so this
+// function traverses them to get the total size of atoms in the same section.
+static uint64_t sectionSize(const DefinedAtom *atom) {
+  return atom->size()
+      + getSizeFollowReferences(atom, lld::Reference::kindLayoutBefore)
+      + getSizeFollowReferences(atom, lld::Reference::kindLayoutAfter);
+}
+
 void SymbolTable::addByName(const Atom &newAtom) {
   StringRef name = newAtom.name();
   assert(!name.empty());
@@ -148,19 +176,22 @@ void SymbolTable::addByName(const Atom &
     case MCR_Second:
       useNew = true;
       break;
-    case MCR_Largest:
-      useNew = true;
+    case MCR_Largest: {
+      uint64_t existingSize = sectionSize((DefinedAtom*)existing);
+      uint64_t newSize = sectionSize((DefinedAtom*)&newAtom);
+      useNew = (newSize >= existingSize);
       break;
+    }
     case MCR_SameSize: {
-      uint64_t sa = ((DefinedAtom*)existing)->size();
-      uint64_t sb = ((DefinedAtom*)&newAtom)->size();
-      if (sa == sb) {
+      uint64_t existingSize = sectionSize((DefinedAtom*)existing);
+      uint64_t newSize = sectionSize((DefinedAtom*)&newAtom);
+      if (existingSize == newSize) {
         useNew = true;
         break;
       }
       llvm::errs() << "Size mismatch: "
-                   << existing->name() << " (" << sa << ") "
-                   << newAtom.name() << " (" << sb << ")\n";
+                   << existing->name() << " (" << existingSize << ") "
+                   << newAtom.name() << " (" << newSize << ")\n";
       // fallthrough
     }
     case MCR_Error:

Modified: lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp?rev=204172&r1=204171&r2=204172&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp Tue Mar 18 14:37:50 2014
@@ -250,11 +250,13 @@ DefinedAtom::Merge getMerge(const coff_a
   case llvm::COFF::IMAGE_COMDAT_SELECT_ANY:
     return DefinedAtom::mergeAsWeakAndAddressUsed;
   case llvm::COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH:
+    // TODO: This mapping is wrong. Fix it.
     return DefinedAtom::mergeByContent;
   case llvm::COFF::IMAGE_COMDAT_SELECT_SAME_SIZE:
     return DefinedAtom::mergeSameNameAndSize;
-  case llvm::COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE:
   case llvm::COFF::IMAGE_COMDAT_SELECT_LARGEST:
+    return DefinedAtom::mergeByLargestSection;
+  case llvm::COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE:
   case llvm::COFF::IMAGE_COMDAT_SELECT_NEWEST:
     // FIXME: These attributes has more complicated semantics than the regular
     // weak symbol. These are mapped to mergeAsWeakAndAddressUsed for now

Modified: lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp?rev=204172&r1=204171&r2=204172&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp (original)
+++ lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp Tue Mar 18 14:37:50 2014
@@ -340,6 +340,7 @@ template <> struct ScalarEnumerationTrai
     io.enumCase(value, "by-content",   lld::DefinedAtom::mergeByContent);
     io.enumCase(value, "same-name-and-size",
                 lld::DefinedAtom::mergeSameNameAndSize);
+    io.enumCase(value, "largest", lld::DefinedAtom::mergeByLargestSection);
   }
 };
 

Added: lld/trunk/test/pecoff/Inputs/merge-largest1.obj.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/merge-largest1.obj.yaml?rev=204172&view=auto
==============================================================================
--- lld/trunk/test/pecoff/Inputs/merge-largest1.obj.yaml (added)
+++ lld/trunk/test/pecoff/Inputs/merge-largest1.obj.yaml Tue Mar 18 14:37:50 2014
@@ -0,0 +1,25 @@
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_I386
+  Characteristics: [  ]
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       16
+    SectionData:     00112233
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    NumberOfAuxSymbols: 1
+    AuxiliaryData:   0700000000000000C979F796000006000000
+  - Name:            "_foo"
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...

Added: lld/trunk/test/pecoff/Inputs/merge-largest2.obj.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/merge-largest2.obj.yaml?rev=204172&view=auto
==============================================================================
--- lld/trunk/test/pecoff/Inputs/merge-largest2.obj.yaml (added)
+++ lld/trunk/test/pecoff/Inputs/merge-largest2.obj.yaml Tue Mar 18 14:37:50 2014
@@ -0,0 +1,25 @@
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_I386
+  Characteristics: [  ]
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       16
+    SectionData:     0011223344556677
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    NumberOfAuxSymbols: 1
+    AuxiliaryData:   0700000000000000C979F796000006000000
+  - Name:            "_foo"
+    Value:           6
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...

Added: lld/trunk/test/pecoff/merge-largest.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/merge-largest.test?rev=204172&view=auto
==============================================================================
--- lld/trunk/test/pecoff/merge-largest.test (added)
+++ lld/trunk/test/pecoff/merge-largest.test Tue Mar 18 14:37:50 2014
@@ -0,0 +1,24 @@
+# RUN: yaml2obj %p/Inputs/merge-largest1.obj.yaml > %t1.obj
+# RUN: yaml2obj %p/Inputs/merge-largest2.obj.yaml > %t2.obj
+#
+# RUN: lld -flavor link /out:%t.exe /subsystem:console /opt:noref /force \
+# RUN:   -- %t1.obj %t2.obj 2>&1 > %t.log
+#
+# FileCheck complains if the input files is empty, so add a dummy line.
+# RUN: echo foo >> %t.log
+# RUN: FileCheck -check-prefix=STDERR %s < %t.log
+#
+# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=READOBJ %s
+
+STDERR-NOT: duplicate symbol error
+
+READOBJ:      Format: COFF-i386
+READOBJ-NEXT: Arch: i386
+READOBJ-NEXT: AddressSize: 32bit
+READOBJ-NEXT: Sections [
+READOBJ-NEXT:   Section {
+READOBJ-NEXT:     Number: 1
+READOBJ-NEXT:     Name: .text (2E 74 65 78 74 00 00 00)
+READOBJ-NEXT:     VirtualSize: 0x8
+READOBJ-NEXT:     VirtualAddress: 0x1000
+READOBJ-NEXT:     RawDataSize: 8





More information about the llvm-commits mailing list