[llvm] r270906 - coff: fix weak alias to local.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Thu May 26 13:31:00 PDT 2016


Author: rafael
Date: Thu May 26 15:31:00 2016
New Revision: 270906

URL: http://llvm.org/viewvc/llvm-project?rev=270906&view=rev
Log:
coff: fix weak alias to local.

We were creating a weak external that tried to reference a static symbol. That
would always fail to link with link.exe.

We now create an external symbol in the same position as the local and refer
to that. This works with link.exe and matches what gas does.

Added:
    llvm/trunk/test/MC/COFF/weak-alias-local.s
Modified:
    llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp
    llvm/trunk/test/MC/COFF/weak.s

Modified: llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp?rev=270906&r1=270905&r2=270906&view=diff
==============================================================================
--- llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp Thu May 26 15:31:00 2016
@@ -155,6 +155,8 @@ public:
   object_t *createCOFFEntity(StringRef Name, list_t &List);
 
   void defineSection(MCSectionCOFF const &Sec);
+
+  COFFSymbol *getLinkedSymbol(const MCSymbol &Symbol);
   void DefineSymbol(const MCSymbol &Symbol, MCAssembler &Assembler,
                     const MCAsmLayout &Layout);
 
@@ -353,6 +355,21 @@ static uint64_t getSymbolValue(const MCS
   return Res;
 }
 
+COFFSymbol *WinCOFFObjectWriter::getLinkedSymbol(const MCSymbol &Symbol) {
+  if (!Symbol.isVariable())
+    return nullptr;
+
+  const MCSymbolRefExpr *SymRef =
+      dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue());
+  if (!SymRef)
+    return nullptr;
+
+  const MCSymbol &Aliasee = SymRef->getSymbol();
+  if (!Aliasee.isUndefined())
+    return nullptr;
+  return GetOrCreateCOFFSymbol(&Aliasee);
+}
+
 /// This function takes a symbol data object from the assembler
 /// and creates the associated COFF symbol staging object.
 void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol,
@@ -367,32 +384,23 @@ void WinCOFFObjectWriter::DefineSymbol(c
       report_fatal_error("conflicting sections for symbol");
   }
 
+  COFFSymbol *Local = nullptr;
   if (cast<MCSymbolCOFF>(Symbol).isWeakExternal()) {
     coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
 
-    if (Symbol.isVariable()) {
-      const MCSymbolRefExpr *SymRef =
-          dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue());
-
-      if (!SymRef)
-        report_fatal_error("Weak externals may only alias symbols");
-
-      coff_symbol->Other = GetOrCreateCOFFSymbol(&SymRef->getSymbol());
-    } else {
+    COFFSymbol *WeakDefault = getLinkedSymbol(Symbol);
+    if (!WeakDefault) {
       std::string WeakName = (".weak." + Symbol.getName() + ".default").str();
-      COFFSymbol *WeakDefault = createSymbol(WeakName);
-
+      WeakDefault = createSymbol(WeakName);
       if (!Sec)
         WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
       else
         WeakDefault->Section = Sec;
-
-      WeakDefault->Data.StorageClass = COFF::IMAGE_SYM_CLASS_EXTERNAL;
-      WeakDefault->Data.Type = 0;
-      WeakDefault->Data.Value = getSymbolValue(Symbol, Layout);
-      coff_symbol->Other = WeakDefault;
+      Local = WeakDefault;
     }
 
+    coff_symbol->Other = WeakDefault;
+
     // Setup the Weak External auxiliary symbol.
     coff_symbol->Aux.resize(1);
     memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0]));
@@ -400,32 +408,32 @@ void WinCOFFObjectWriter::DefineSymbol(c
     coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0;
     coff_symbol->Aux[0].Aux.WeakExternal.Characteristics =
         COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY;
-
-    coff_symbol->MC = &Symbol;
   } else {
-    coff_symbol->Data.Value = getSymbolValue(Symbol, Layout);
+    if (!Base)
+      coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
+    else
+      coff_symbol->Section = Sec;
+    Local = coff_symbol;
+  }
+
+  if (Local) {
+    Local->Data.Value = getSymbolValue(Symbol, Layout);
 
     const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(Symbol);
-    coff_symbol->Data.Type = SymbolCOFF.getType();
-    coff_symbol->Data.StorageClass = SymbolCOFF.getClass();
+    Local->Data.Type = SymbolCOFF.getType();
+    Local->Data.StorageClass = SymbolCOFF.getClass();
 
     // If no storage class was specified in the streamer, define it here.
-    if (coff_symbol->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) {
+    if (Local->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) {
       bool IsExternal = Symbol.isExternal() ||
                         (!Symbol.getFragment() && !Symbol.isVariable());
 
-      coff_symbol->Data.StorageClass = IsExternal
-                                           ? COFF::IMAGE_SYM_CLASS_EXTERNAL
-                                           : COFF::IMAGE_SYM_CLASS_STATIC;
+      Local->Data.StorageClass = IsExternal ? COFF::IMAGE_SYM_CLASS_EXTERNAL
+                                            : COFF::IMAGE_SYM_CLASS_STATIC;
     }
-
-    if (!Base)
-      coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
-    else
-      coff_symbol->Section = Sec;
-
-    coff_symbol->MC = &Symbol;
   }
+
+  coff_symbol->MC = &Symbol;
 }
 
 // Maximum offsets for different string table entry encodings.

Added: llvm/trunk/test/MC/COFF/weak-alias-local.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/weak-alias-local.s?rev=270906&view=auto
==============================================================================
--- llvm/trunk/test/MC/COFF/weak-alias-local.s (added)
+++ llvm/trunk/test/MC/COFF/weak-alias-local.s Thu May 26 15:31:00 2016
@@ -0,0 +1,43 @@
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s -o %t.o
+// RUN: llvm-readobj -t %t.o | FileCheck %s
+
+// test that we create an external symbol for a to point to.
+
+        .data
+        .long 123
+b:
+        .long   42
+        .weak   a
+a=b
+
+// CHECK:      Symbol {
+// CHECK:        Name: b
+// CHECK-NEXT:   Value: 4
+// CHECK-NEXT:   Section: .data (2)
+// CHECK-NEXT:   BaseType: Null (0x0)
+// CHECK-NEXT:   ComplexType: Null (0x0)
+// CHECK-NEXT:   StorageClass: Static (0x3)
+// CHECK-NEXT:   AuxSymbolCount: 0
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT:   Name: a
+// CHECK-NEXT:   Value: 0
+// CHECK-NEXT:   Section: IMAGE_SYM_UNDEFINED (0)
+// CHECK-NEXT:   BaseType: Null (0x0)
+// CHECK-NEXT:   ComplexType: Null (0x0)
+// CHECK-NEXT:   StorageClass: WeakExternal (0x69)
+// CHECK-NEXT:   AuxSymbolCount: 1
+// CHECK-NEXT:   AuxWeakExternal {
+// CHECK-NEXT:     Linked: .weak.a.default (9)
+// CHECK-NEXT:     Search: Library (0x2)
+// CHECK-NEXT:   }
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT:   Name: .weak.a.default
+// CHECK-NEXT:   Value: 4
+// CHECK-NEXT:   Section: .data (2)
+// CHECK-NEXT:   BaseType: Null (0x0)
+// CHECK-NEXT:   ComplexType: Null (0x0)
+// CHECK-NEXT:   StorageClass: External (0x2)
+// CHECK-NEXT:   AuxSymbolCount: 0
+// CHECK-NEXT: }

Modified: llvm/trunk/test/MC/COFF/weak.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/weak.s?rev=270906&r1=270905&r2=270906&view=diff
==============================================================================
--- llvm/trunk/test/MC/COFF/weak.s (original)
+++ llvm/trunk/test/MC/COFF/weak.s Thu May 26 15:31:00 2016
@@ -35,6 +35,16 @@ LBB0_2:
 // CHECK: Symbols [
 
 // CHECK:      Symbol {
+// CHECK:        Name: _main
+// CHECK-NEXT:   Value: 0
+// CHECK-NEXT:   Section: .text
+// CHECK-NEXT:   BaseType: Null
+// CHECK-NEXT:   ComplexType: Function
+// CHECK-NEXT:   StorageClass: External
+// CHECK-NEXT:   AuxSymbolCount: 0
+// CHECK-NEXT: }
+
+// CHECK:      Symbol {
 // CHECK:        Name:           _test_weak
 // CHECK-NEXT:   Value:          0
 // CHECK-NEXT:   Section:        IMAGE_SYM_UNDEFINED (0)
@@ -67,7 +77,17 @@ LBB0_2:
 // CHECK-NEXT:   StorageClass:   WeakExternal
 // CHECK-NEXT:   AuxSymbolCount: 1
 // CHECK-NEXT:   AuxWeakExternal {
-// CHECK-NEXT:     Linked: _main
+// CHECK-NEXT:     Linked: .weak._test_weak_alias.default
 // CHECK-NEXT:      Search: Library
 // CHECK-NEXT:   }
 // CHECK-NEXT: }
+
+// CHECK:      Symbol {
+// CHECK:        Name: .weak._test_weak_alias.default
+// CHECK-NEXT:   Value: 0
+// CHECK-NEXT:   Section: .text
+// CHECK-NEXT:   BaseType: Null
+// CHECK-NEXT:   ComplexType: Null
+// CHECK-NEXT:   StorageClass: External
+// CHECK-NEXT:   AuxSymbolCount: 0
+// CHECK-NEXT: }




More information about the llvm-commits mailing list