Correctly handle weak undefined symbols. Before we would get a invalid binding
authorRafael Espindola <rafael.espindola@gmail.com>
Thu, 23 Sep 2010 19:55:14 +0000 (19:55 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Thu, 23 Sep 2010 19:55:14 +0000 (19:55 +0000)
(2 == STB_WEAK | STB_GLOBAL).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114690 91177308-0d34-0410-b5e6-96231b3b80d8

lib/MC/ELFObjectWriter.cpp
test/MC/ELF/weak.s [new file with mode: 0644]

index 587489c26be0d1b1658021b795656ce7e3068bb9..9eb9bcac46aa20986ccfbfc5d98e7ebc9fb340b9 100644 (file)
@@ -43,6 +43,20 @@ static unsigned GetType(const MCSymbolData &SD) {
   return Type;
 }
 
+static unsigned GetBinding(const MCSymbolData &SD) {
+  uint32_t Binding = (SD.getFlags() & (0xf << ELF_STB_Shift)) >> ELF_STB_Shift;
+  assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL ||
+         Binding == ELF::STB_WEAK);
+  return Binding;
+}
+
+static void SetBinding(MCSymbolData &SD, unsigned Binding) {
+  assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL ||
+         Binding == ELF::STB_WEAK);
+  uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STB_Shift);
+  SD.setFlags(OtherFlags | (Binding << ELF_STB_Shift));
+}
+
 namespace {
 
   class ELFObjectWriterImpl {
@@ -460,16 +474,15 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
     assert((Data.getFlags() & ELF_STB_Global) &&
            "External symbol requires STB_GLOBAL flag");
     WriteSymbol(F, MSD, Layout);
-    if ((Data.getFlags() & (0xf << ELF_STB_Shift)) == ELF_STB_Local)
+    if (GetBinding(Data) == ELF::STB_LOCAL)
       LastLocalSymbolIndex++;
   }
 
   for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) {
     ELFSymbolData &MSD = UndefinedSymbolData[i];
     MCSymbolData &Data = *MSD.SymbolData;
-    Data.setFlags(Data.getFlags() | ELF_STB_Global);
     WriteSymbol(F, MSD, Layout);
-    if ((Data.getFlags() & (0xf << ELF_STB_Shift)) == ELF_STB_Local)
+    if (GetBinding(Data) == ELF::STB_LOCAL)
       LastLocalSymbolIndex++;
   }
 }
@@ -682,8 +695,10 @@ void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) {
       ExternalSymbolData.push_back(MSD);
     } else if (Symbol.isUndefined()) {
       MSD.SectionIndex = ELF::SHN_UNDEF;
-      // XXX: for some reason we dont Emit* this
-      it->setFlags(it->getFlags() | ELF_STB_Global);
+      // FIXME: Undefined symbols are global, but this is the first place we
+      // are able to set it.
+      if (GetBinding(*it) == ELF::STB_LOCAL)
+        SetBinding(*it, ELF::STB_GLOBAL);
       UndefinedSymbolData.push_back(MSD);
     } else if (Symbol.isAbsolute()) {
       MSD.SectionIndex = ELF::SHN_ABS;
diff --git a/test/MC/ELF/weak.s b/test/MC/ELF/weak.s
new file mode 100644 (file)
index 0000000..ef8e000
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump  | FileCheck %s
+
+// Test that this produces a weak undefined symbol.
+
+       .weak   foo
+        .long   foo
+
+//CHECK:       (('st_name', 1) # 'foo'
+//CHECK-NEXT:   ('st_bind', 2)
+//CHECK-NEXT:   ('st_type', 0)
+//CHECK-NEXT:   ('st_other', 0)
+//CHECK-NEXT:   ('st_shndx', 0)
+//CHECK-NEXT:   ('st_value', 0)
+//CHECK-NEXT:   ('st_size', 0)