[llvm] r371312 - [ELF][MC] Set types of aliases of IFunc to STT_GNU_IFUNC
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 7 07:58:47 PDT 2019
Author: maskray
Date: Sat Sep 7 07:58:47 2019
New Revision: 371312
URL: http://llvm.org/viewvc/llvm-project?rev=371312&view=rev
Log:
[ELF][MC] Set types of aliases of IFunc to STT_GNU_IFUNC
```
.type foo, at gnu_indirect_function
.set foo,foo_resolver
.set foo2,foo
.set foo3,foo2
```
The types of foo2 and foo3 should be STT_GNU_IFUNC, but we currently
resolve them to the type of foo_resolver. This patch fixes it.
Differential Revision: https://reviews.llvm.org/D67206
Patch by Senran Zhang
Added:
llvm/trunk/test/MC/ELF/ifunc-alias.s
Modified:
llvm/trunk/lib/MC/ELFObjectWriter.cpp
Modified: llvm/trunk/lib/MC/ELFObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/ELFObjectWriter.cpp?rev=371312&r1=371311&r2=371312&view=diff
==============================================================================
--- llvm/trunk/lib/MC/ELFObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/ELFObjectWriter.cpp Sat Sep 7 07:58:47 2019
@@ -511,6 +511,19 @@ static uint8_t mergeTypeForSet(uint8_t o
return Type;
}
+static bool isIFunc(const MCSymbolELF *Symbol) {
+ while (Symbol->getType() != ELF::STT_GNU_IFUNC) {
+ const MCSymbolRefExpr *Value;
+ if (!Symbol->isVariable() ||
+ !(Value = dyn_cast<MCSymbolRefExpr>(Symbol->getVariableValue())) ||
+ Value->getKind() != MCSymbolRefExpr::VK_None ||
+ mergeTypeForSet(Symbol->getType(), ELF::STT_GNU_IFUNC) != ELF::STT_GNU_IFUNC)
+ return false;
+ Symbol = &cast<MCSymbolELF>(Value->getSymbol());
+ }
+ return true;
+}
+
void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
ELFSymbolData &MSD, const MCAsmLayout &Layout) {
const auto &Symbol = cast<MCSymbolELF>(*MSD.Symbol);
@@ -524,6 +537,8 @@ void ELFWriter::writeSymbol(SymbolTableW
// Binding and Type share the same byte as upper and lower nibbles
uint8_t Binding = Symbol.getBinding();
uint8_t Type = Symbol.getType();
+ if (isIFunc(&Symbol))
+ Type = ELF::STT_GNU_IFUNC;
if (Base) {
Type = mergeTypeForSet(Type, Base->getType());
}
Added: llvm/trunk/test/MC/ELF/ifunc-alias.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/ifunc-alias.s?rev=371312&view=auto
==============================================================================
--- llvm/trunk/test/MC/ELF/ifunc-alias.s (added)
+++ llvm/trunk/test/MC/ELF/ifunc-alias.s Sat Sep 7 07:58:47 2019
@@ -0,0 +1,32 @@
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readelf -s | FileCheck %s
+.text
+
+.type foo_impl, at function
+foo_impl:
+ ret
+
+.type foo_resolver, at function
+foo_resolver:
+ mov $foo_impl, %rax
+ ret
+
+.type foo, at gnu_indirect_function
+.set foo,foo_resolver
+
+// All things below should be IFunc identical to 'foo'
+.set foo2,foo
+.set foo3,foo2
+.type foo4, at function
+.set foo4,foo3
+
+// But tls_object should not be IFunc
+.set tls,foo
+.type tls, at tls_object
+
+// CHECK: IFUNC LOCAL DEFAULT 2 foo
+// CHECK: IFUNC LOCAL DEFAULT 2 foo2
+// CHECK: IFUNC LOCAL DEFAULT 2 foo3
+// CHECK: IFUNC LOCAL DEFAULT 2 foo4
+// CHECK: FUNC LOCAL DEFAULT 2 foo_impl
+// CHECK: FUNC LOCAL DEFAULT 2 foo_resolver
+// CHECK: TLS LOCAL DEFAULT 2 tls
More information about the llvm-commits
mailing list