Skip to content

Commit

Permalink
[ELF][MC] Set types of aliases of IFunc to STT_GNU_IFUNC
Browse files Browse the repository at this point in the history
```
.type  foo,@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

llvm-svn: 371312
  • Loading branch information
MaskRay committed Sep 7, 2019
1 parent 4e76f88 commit 72e99e6
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
15 changes: 15 additions & 0 deletions llvm/lib/MC/ELFObjectWriter.cpp
Expand Up @@ -511,6 +511,19 @@ static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) {
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);
Expand All @@ -524,6 +537,8 @@ void ELFWriter::writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex,
// 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());
}
Expand Down
32 changes: 32 additions & 0 deletions llvm/test/MC/ELF/ifunc-alias.s
@@ -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,@function
foo_impl:
ret

.type foo_resolver,@function
foo_resolver:
mov $foo_impl, %rax
ret

.type foo,@gnu_indirect_function
.set foo,foo_resolver

// All things below should be IFunc identical to 'foo'
.set foo2,foo
.set foo3,foo2
.type foo4,@function
.set foo4,foo3

// But tls_object should not be IFunc
.set tls,foo
.type tls,@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

0 comments on commit 72e99e6

Please sign in to comment.