[PATCH] D67206: [ELF][MC] Fix IFunc alias resolving issue

Sr.Zhang via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 4 18:29:19 PDT 2019


zsrkmyn created this revision.
zsrkmyn added reviewers: grosbach, craig.topper, annita.zhang, LuoYuanke, MaskRay.
Herald added subscribers: llvm-commits, hiraditya, arichardson, emaste.
Herald added a reviewer: espindola.
Herald added a project: LLVM.

If we use '.set' directive to set a symbol as an alias of an IFunc, then the
symbol should also be IFunc. But it's evaluated to be the IFunc resolver at
this time. This patch tries to fix it.


Repository:
  rL LLVM

https://reviews.llvm.org/D67206

Files:
  llvm/lib/MC/ELFObjectWriter.cpp
  llvm/test/MC/ELF/ifunc-alias.s


Index: llvm/test/MC/ELF/ifunc-alias.s
===================================================================
--- /dev/null
+++ llvm/test/MC/ELF/ifunc-alias.s
@@ -0,0 +1,58 @@
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readobj --symbols | FileCheck %s
+.text
+
+.globl foo_impl
+.type  foo_impl, at function
+foo_impl:
+  ret
+
+.globl foo_resolver
+.type  foo_resolver, at function
+foo_resolver:
+  mov $foo_impl, %rax
+  ret
+
+.globl foo
+.type  foo, at gnu_indirect_function
+.set   foo,foo_resolver
+
+// 'foo2' should be an IFunc identical to 'foo'
+.globl foo2
+.set   foo2,foo
+
+// CHECK:        Symbol {
+// CHECK:         Name: foo (25)
+// CHECK-NEXT:    Value: 0x1
+// CHECK-NEXT:    Size: 0
+// CHECK-NEXT:    Binding: Global (0x1)
+// CHECK-NEXT:    Type: GNU_IFunc (0xA)
+// CHECK-NEXT:    Other: 0
+// CHECK-NEXT:    Section: .text (0x2)
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Symbol {
+// CHECK-NEXT:    Name: foo2 (54)
+// CHECK-NEXT:    Value: 0x1
+// CHECK-NEXT:    Size: 0
+// CHECK-NEXT:    Binding: Global (0x1)
+// CHECK-NEXT:    Type: GNU_IFunc (0xA)
+// CHECK-NEXT:    Other: 0
+// CHECK-NEXT:    Section: .text (0x2)
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Symbol {
+// CHECK-NEXT:    Name: foo_impl (29)
+// CHECK-NEXT:    Value: 0x0
+// CHECK-NEXT:    Size: 0
+// CHECK-NEXT:    Binding: Global (0x1)
+// CHECK-NEXT:    Type: Function (0x2)
+// CHECK-NEXT:    Other: 0
+// CHECK-NEXT:    Section: .text (0x2)
+// CHECK-NEXT:  }
+// CHECK-NEXT:  Symbol {
+// CHECK-NEXT:    Name: foo_resolver (12)
+// CHECK-NEXT:    Value: 0x1
+// CHECK-NEXT:    Size: 0
+// CHECK-NEXT:    Binding: Global (0x1)
+// CHECK-NEXT:    Type: Function (0x2)
+// CHECK-NEXT:    Other: 0
+// CHECK-NEXT:    Section: .text (0x2)
+// CHECK-NEXT:  }
Index: llvm/lib/MC/ELFObjectWriter.cpp
===================================================================
--- llvm/lib/MC/ELFObjectWriter.cpp
+++ llvm/lib/MC/ELFObjectWriter.cpp
@@ -511,6 +511,18 @@
   return Type;
 }
 
+static bool isIFunc(const MCSymbolELF &Symbol) {
+  if (Symbol.getType() == ELF::STT_GNU_IFUNC)
+    return true;
+
+  const MCSymbolRefExpr *Value;
+  if (!Symbol.isVariable() ||
+      !(Value = dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue())) ||
+      Value->getKind() != MCSymbolRefExpr::VK_None)
+    return false;
+  return isIFunc(cast<MCSymbolELF>(Value->getSymbol()));
+}
+
 void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
                             ELFSymbolData &MSD, const MCAsmLayout &Layout) {
   const auto &Symbol = cast<MCSymbolELF>(*MSD.Symbol);
@@ -524,6 +536,8 @@
   // Binding and Type share the same byte as upper and lower nibbles
   uint8_t Binding = Symbol.getBinding();
   uint8_t Type = Symbol.getType();
+  if (Type == ELF::STT_NOTYPE && isIFunc(Symbol))
+    Type = ELF::STT_GNU_IFUNC;
   if (Base) {
     Type = mergeTypeForSet(Type, Base->getType());
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D67206.218822.patch
Type: text/x-patch
Size: 2910 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190905/48dce291/attachment-0001.bin>


More information about the llvm-commits mailing list