[lld] r246405 - Keep the largest common symbol.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 30 18:16:20 PDT 2015


Author: rafael
Date: Sun Aug 30 20:16:19 2015
New Revision: 246405

URL: http://llvm.org/viewvc/llvm-project?rev=246405&view=rev
Log:
Keep the largest common symbol.

This requires templating some functions over ELFT, but that opens other cleanup
opportunities for future patches.

Added:
    lld/trunk/test/elf2/Inputs/common.s
    lld/trunk/test/elf2/common.s
Modified:
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/SymbolTable.h
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Symbols.h

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=246405&r1=246404&r2=246405&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Sun Aug 30 20:16:19 2015
@@ -12,12 +12,12 @@
 #include "Symbols.h"
 
 using namespace llvm;
+using namespace llvm::object;
 
 using namespace lld;
 using namespace lld::elf2;
 
 SymbolTable::SymbolTable() {
-  resolve(new (Alloc) SyntheticUndefined("_start"));
 }
 
 void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
@@ -32,11 +32,41 @@ void SymbolTable::addObject(ObjectFileBa
     ObjectFileBase &Old = *ObjectFiles[0];
     if (!Old.isCompatibleWith(*File))
       error(Twine(Old.getName() + " is incompatible with " + File->getName()));
+  } else {
+    auto *Start = new (Alloc) SyntheticUndefined("_start");
+    switch (File->kind()) {
+    case InputFile::Object32LEKind:
+      resolve<ELF32LE>(Start);
+      break;
+    case InputFile::Object32BEKind:
+      resolve<ELF32BE>(Start);
+      break;
+    case InputFile::Object64LEKind:
+      resolve<ELF64LE>(Start);
+      break;
+    case InputFile::Object64BEKind:
+      resolve<ELF64BE>(Start);
+      break;
+    }
   }
 
   ObjectFiles.emplace_back(File);
-  for (SymbolBody *Body : File->getSymbols())
-    resolve(Body);
+  for (SymbolBody *Body : File->getSymbols()) {
+    switch (File->kind()) {
+    case InputFile::Object32LEKind:
+      resolve<ELF32LE>(Body);
+      break;
+    case InputFile::Object32BEKind:
+      resolve<ELF32BE>(Body);
+      break;
+    case InputFile::Object64LEKind:
+      resolve<ELF64LE>(Body);
+      break;
+    case InputFile::Object64BEKind:
+      resolve<ELF64BE>(Body);
+      break;
+    }
+  }
 }
 
 void SymbolTable::reportRemainingUndefines() {
@@ -49,7 +79,7 @@ void SymbolTable::reportRemainingUndefin
 
 // This function resolves conflicts if there's an existing symbol with
 // the same name. Decisions are made based on symbol type.
-void SymbolTable::resolve(SymbolBody *New) {
+template <class ELFT> void SymbolTable::resolve(SymbolBody *New) {
   // Find an existing Symbol or create and insert a new one.
   StringRef Name = New->getName();
   Builder.add(Name);
@@ -64,7 +94,7 @@ void SymbolTable::resolve(SymbolBody *Ne
   // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
   // equivalent (conflicting), or more preferable, respectively.
   SymbolBody *Existing = Sym->Body;
-  int comp = Existing->compare(New);
+  int comp = Existing->compare<ELFT>(New);
   if (comp < 0)
     Sym->Body = New;
   if (comp == 0)

Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=246405&r1=246404&r2=246405&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Sun Aug 30 20:16:19 2015
@@ -51,7 +51,7 @@ public:
 private:
   void addObject(ObjectFileBase *File);
 
-  void resolve(SymbolBody *Body);
+  template <class ELFT> void resolve(SymbolBody *Body);
 
   llvm::DenseMap<StringRef, Symbol *> Symtab;
   llvm::BumpPtrAllocator Alloc;

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=246405&r1=246404&r2=246405&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Sun Aug 30 20:16:19 2015
@@ -19,25 +19,36 @@ using namespace lld::elf2;
 
 // Returns 1, 0 or -1 if this symbol should take precedence
 // over the Other, tie or lose, respectively.
-int SymbolBody::compare(SymbolBody *Other) {
+template <class ELFT> int SymbolBody::compare(SymbolBody *Other) {
   std::pair<bool, bool> L(isDefined(), !isWeak());
   std::pair<bool, bool> R(Other->isDefined(), !Other->isWeak());
 
   // Normalize
   if (L > R)
-    return -Other->compare(this);
+    return -Other->compare<ELFT>(this);
 
   if (L != R)
     return -1;
 
   if (L.first && L.second) {
-    // FIXME: In the case where both are common we need to pick the largest
-    // and remember the alignment restriction.
-    if (isCommon())
+    if (isCommon()) {
+      if (Other->isCommon()) {
+        // FIXME: We also need to remember the alignment restriction.
+        if (cast<DefinedCommon<ELFT>>(this)->Sym.st_size >=
+            cast<DefinedCommon<ELFT>>(Other)->Sym.st_size)
+          return 1;
+        return -1;
+      }
       return -1;
+    }
     if (Other->isCommon())
       return 1;
     return 0;
   }
   return 1;
 }
+
+template int SymbolBody::compare<ELF32LE>(SymbolBody *Other);
+template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
+template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
+template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=246405&r1=246404&r2=246405&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Sun Aug 30 20:16:19 2015
@@ -71,7 +71,7 @@ public:
   // Decides which symbol should "win" in the symbol table, this or
   // the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if
   // they are duplicate (conflicting) symbols.
-  int compare(SymbolBody *Other);
+  template <class ELFT> int compare(SymbolBody *Other);
 
 protected:
   SymbolBody(Kind K, StringRef Name, bool IsWeak)

Added: lld/trunk/test/elf2/Inputs/common.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/common.s?rev=246405&view=auto
==============================================================================
--- lld/trunk/test/elf2/Inputs/common.s (added)
+++ lld/trunk/test/elf2/Inputs/common.s Sun Aug 30 20:16:19 2015
@@ -0,0 +1,2 @@
+.comm sym1,8,4
+.comm sym2,4,4

Added: lld/trunk/test/elf2/common.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/common.s?rev=246405&view=auto
==============================================================================
--- lld/trunk/test/elf2/common.s (added)
+++ lld/trunk/test/elf2/common.s Sun Aug 30 20:16:19 2015
@@ -0,0 +1,28 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/common.s -o %t2
+// RUN: lld -flavor gnu2 %t %t2 -o %t3
+// RUN: llvm-readobj -t %t3 | FileCheck %s
+// REQUIRES: x86
+
+// CHECK:      Name: sym2
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+
+// CHECK:      Name: sym1
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+
+
+.globl _start
+_start:
+
+.comm sym1,4,4
+.comm sym2,8,4




More information about the llvm-commits mailing list