[llvm] [BOLT][AArch64] Handle gold-style IFUNCs (PR #70974)
Vladislav Khmelevsky via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 1 12:18:06 PDT 2023
https://github.com/yota9 created https://github.com/llvm/llvm-project/pull/70974
Gold linker doesn't produce symbol for IFUNC trampoline, so currently it
is handled wrong by BOLT. Since IRELATIVE relocation doesn't have symbol
use addend to find resolver/ifunc (they're using the same address) and
use it for PLT function naming.
>From 8f2c4293355dc8ff09d9d53d4748840adbc4454b Mon Sep 17 00:00:00 2001
From: Vladislav Khmelevsky <och95 at yandex.ru>
Date: Wed, 1 Nov 2023 22:48:31 +0400
Subject: [PATCH] [BOLT][AArch64] Handle gold-style IFUNCs
Gold linker doesn't produce symbol for IFUNC trampoline, so currently it
is handled wrong by BOLT. Since IRELATIVE relocation doesn't have symbol
use addend to find resolver/ifunc (they're using the same address) and
use it for PLT function naming.
---
bolt/include/bolt/Core/Relocation.h | 4 +
bolt/lib/Rewrite/RewriteInstance.cpp | 29 +++-
bolt/test/AArch64/Inputs/ifunc-gold.yaml | 188 +++++++++++++++++++++++
bolt/test/AArch64/ifunc-gold.test | 10 ++
bolt/test/runtime/iplt.c | 8 +-
5 files changed, 232 insertions(+), 7 deletions(-)
create mode 100644 bolt/test/AArch64/Inputs/ifunc-gold.yaml
create mode 100644 bolt/test/AArch64/ifunc-gold.test
diff --git a/bolt/include/bolt/Core/Relocation.h b/bolt/include/bolt/Core/Relocation.h
index bc16d952e7a291e..36bf12fddd514e7 100644
--- a/bolt/include/bolt/Core/Relocation.h
+++ b/bolt/include/bolt/Core/Relocation.h
@@ -124,6 +124,10 @@ struct Relocation {
/// otherwise.
bool isRelative() const { return isRelative(Type); }
+ /// Return true if this relocation is R_*_IRELATIVE type. Return false
+ /// otherwise.
+ bool isIRelative() const { return isIRelative(Type); }
+
/// Emit relocation at a current \p Streamer' position. The caller is
/// responsible for setting the position correctly.
size_t emit(MCStreamer *Streamer) const;
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 0d78c9b75e03d32..0bb47220b37561e 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -1344,24 +1344,41 @@ void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress,
BinaryFunction *BF = BC->getBinaryFunctionAtAddress(EntryAddress);
if (BF && BC->isAArch64()) {
- // Handle IFUNC trampoline
+ // Handle IFUNC trampoline with symbol
setPLTSymbol(BF, BF->getOneName());
return;
}
const Relocation *Rel = BC->getDynamicRelocationAt(TargetAddress);
- if (!Rel || !Rel->Symbol)
+ if (!Rel)
return;
+ MCSymbol *Symbol = Rel->Symbol;
+ if (!Symbol) {
+ if (!BC->isAArch64() || !Rel->Addend || !Rel->isIRelative())
+ return;
+
+ // IFUNC trampiline without symbol
+ BinaryFunction *TargetBF = BC->getBinaryFunctionAtAddress(Rel->Addend);
+ if (!TargetBF) {
+ errs()
+ << "BOLT-WARNING: Expected BF to be presented as IFUNC resolver at "
+ << Twine::utohexstr(Rel->Addend) << ", skipping\n";
+ return;
+ }
+
+ Symbol = TargetBF->getSymbol();
+ }
+
ErrorOr<BinarySection &> Section = BC->getSectionForAddress(EntryAddress);
assert(Section && "cannot get section for address");
if (!BF)
- BF = BC->createBinaryFunction(Rel->Symbol->getName().str() + "@PLT",
- *Section, EntryAddress, 0, EntrySize,
+ BF = BC->createBinaryFunction(Symbol->getName().str() + "@PLT", *Section,
+ EntryAddress, 0, EntrySize,
Section->getAlignment());
else
- BF->addAlternativeName(Rel->Symbol->getName().str() + "@PLT");
- setPLTSymbol(BF, Rel->Symbol->getName());
+ BF->addAlternativeName(Symbol->getName().str() + "@PLT");
+ setPLTSymbol(BF, Symbol->getName());
}
void RewriteInstance::disassemblePLTSectionAArch64(BinarySection &Section) {
diff --git a/bolt/test/AArch64/Inputs/ifunc-gold.yaml b/bolt/test/AArch64/Inputs/ifunc-gold.yaml
new file mode 100644
index 000000000000000..4c21f1cfd5dce18
--- /dev/null
+++ b/bolt/test/AArch64/Inputs/ifunc-gold.yaml
@@ -0,0 +1,188 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_GNU
+ Type: ET_EXEC
+ Machine: EM_AARCH64
+ Entry: 0x400500
+ProgramHeaders:
+ - Type: PT_PHDR
+ Flags: [ PF_R ]
+ VAddr: 0x400040
+ Align: 0x8
+ Offset: 0x40
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_R ]
+ FirstSec: .dynsym
+ LastSec: .text
+ VAddr: 0x400278
+ Align: 0x4
+ Offset: 0x0
+ - Type: PT_LOAD
+ Flags: [ PF_W, PF_R ]
+ FirstSec: .dynamic
+ LastSec: .got.plt
+ VAddr: 0x41FE08
+ Align: 0x10000
+ Offset: 0x478
+ - Type: PT_DYNAMIC
+ Flags: [ PF_W, PF_R ]
+ FirstSec: .dynamic
+ LastSec: .dynamic
+ VAddr: 0x41FE08
+ Align: 0x8
+ Offset: 0x478
+Sections:
+ - Name: .dynsym
+ Type: SHT_DYNSYM
+ Flags: [ SHF_ALLOC ]
+ Address: 0x400278
+ Link: .dynstr
+ AddressAlign: 0x8
+ - Name: .dynstr
+ Type: SHT_STRTAB
+ Flags: [ SHF_ALLOC ]
+ Address: 0x400320
+ AddressAlign: 0x1
+ - Name: .rela.dyn
+ Type: SHT_RELA
+ Flags: [ SHF_ALLOC ]
+ Address: 0x4003E8
+ Link: .dynsym
+ AddressAlign: 0x8
+ Relocations:
+ - Offset: 0x41FFE0
+ Symbol: __gmon_start__
+ Type: R_AARCH64_GLOB_DAT
+ - Name: .rela.plt
+ Type: SHT_RELA
+ Flags: [ SHF_ALLOC, SHF_INFO_LINK ]
+ Address: 0x400400
+ Link: .dynsym
+ AddressAlign: 0x8
+ Info: .plt
+ Relocations:
+ - Offset: 0x420000
+ Symbol: __libc_start_main
+ Type: R_AARCH64_JUMP_SLOT
+ - Offset: 0x420008
+ Symbol: abort
+ Type: R_AARCH64_JUMP_SLOT
+ - Offset: 0x420010
+ Symbol: __gmon_start__
+ Type: R_AARCH64_JUMP_SLOT
+ - Offset: 0x420018
+ Symbol: puts
+ Type: R_AARCH64_JUMP_SLOT
+ - Offset: 0x420020
+ Type: R_AARCH64_IRELATIVE
+ Addend: 4195828
+ - Name: .plt
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x400490
+ AddressAlign: 0x8
+ EntSize: 0x10
+ Content: F07BBFA9F00000F011FE47F910E23F9120021FD61F2003D51F2003D51F2003D510010090110240F91002009120021FD610010090110640F91022009120021FD610010090110A40F91042009120021FD610010090110E40F91062009120021FD610010090111240F91082009120021FD6
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x400500
+ AddressAlign: 0x8
+ Content: 1D0080D21E0080D2E50300AAE10340F9E2230091E60300910000009000E014910300009063A018910400009084A01A91E0FFFF97E3FFFF9732000014E00000F000F047F9400000B4E2FFFF17C0035FD60001009000E000910101009021E000913F0000EBC000005401000090216443F9610000B4F00301AA00021FD6C0035FD60001009000E000910101009021E00091210000CB22FC7FD3410C818BFF0781EB21FC4193C000005402000090426843F9620000B4F00302AA00021FD6C0035FD6FD7BBEA9FD030091F30B00F91301009060E2403980000035DEFFFF972000805260E20039F30B40F9FD7BC2A8C0035FD6E4FFFF170000009000601891C0035FD6FD7BBFA9FD030091BAFFFF97E0031F2AFD7BC1A8C0035FD60000009000601B91B0FFFF1700000000FD7BBCA9FD030091F35301A9F40000F094223891F55B02A9F50000F0B5023891940215CBF603002AF76303A9F70301AAF80302AA87FFFF97FF0F94EB6001005494FE4393130080D2A37A73F8E20318AA73060091E10317AAE003162A60003FD69F0213EB21FFFF54F35341A9F55B42A9F76343A9FD7BC4A8C0035FD61F2003D5C0035FD6
+ - Name: .dynamic
+ Type: SHT_DYNAMIC
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x41FE08
+ Link: .dynstr
+ AddressAlign: 0x8
+ Entries:
+ - Tag: DT_PLTGOT
+ Value: 0x41FFE8
+ - Tag: DT_PLTRELSZ
+ Value: 0x78
+ - Tag: DT_JMPREL
+ Value: 0x400400
+ - Tag: DT_PLTREL
+ Value: 0x7
+ - Tag: DT_RELA
+ Value: 0x4003E8
+ - Tag: DT_RELASZ
+ Value: 0x18
+ - Tag: DT_RELAENT
+ Value: 0x18
+ - Tag: DT_SYMENT
+ Value: 0x18
+ - Tag: DT_STRTAB
+ Value: 0x400320
+ - Tag: DT_STRSZ
+ Value: 0x78
+ - Tag: DT_NULL
+ Value: 0x0
+ - Name: .got
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x41FFD8
+ AddressAlign: 0x8
+ Content: 08FE4100000000000000000000000000
+ - Name: .got.plt
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x41FFE8
+ AddressAlign: 0x8
+ Content: '00000000000000000000000000000000000000000000000090044000000000009004400000000000900440000000000090044000000000009004400000000000'
+ - Name: .rela.text
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Link: .symtab
+ AddressAlign: 0x8
+ Info: .text
+ Relocations:
+ - Offset: 0x400530
+ Symbol: __libc_start_main
+ Type: R_AARCH64_CALL26
+Symbols:
+ - Name: resolver_foo
+ Type: STT_FUNC
+ Section: .text
+ Value: 0x4005F4
+ Size: 0xC
+ - Name: foo
+ Type: STT_FUNC
+ Section: .text
+ Value: 0x400618
+ Size: 0xC
+ - Name: __libc_start_main
+ Type: STT_FUNC
+ Binding: STB_GLOBAL
+ - Name: ifoo
+ Type: STT_GNU_IFUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x4005F4
+ Size: 0xC
+ - Name: main
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x400600
+ Size: 0x18
+ - Name: _start
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x400500
+DynamicSymbols:
+ - Name: __libc_start_main
+ Type: STT_FUNC
+ Binding: STB_GLOBAL
+ - Name: abort
+ Type: STT_FUNC
+ Binding: STB_GLOBAL
+ - Name: puts
+ Type: STT_FUNC
+ Binding: STB_GLOBAL
+ - Name: __gmon_start__
+ Binding: STB_WEAK
+...
diff --git a/bolt/test/AArch64/ifunc-gold.test b/bolt/test/AArch64/ifunc-gold.test
new file mode 100644
index 000000000000000..d267769db7589bc
--- /dev/null
+++ b/bolt/test/AArch64/ifunc-gold.test
@@ -0,0 +1,10 @@
+// This test checks that IFUNC-related PLT entries references are correctly
+// recognised and handled by BOLT.
+// The IFUNC uses the same address for ifunc symbol and resolver, so check
+// for common name (foo).
+
+// RUN: yaml2obj %p/Inputs/ifunc-gold.yaml &> %t.exe
+// RUN: llvm-bolt %t.exe -o %t.bolt --print-disasm --print-only=main | \
+// RUN: FileCheck %s
+
+CHECK: {{.*}} bl {{.*}}foo{{.*}}@PLT
diff --git a/bolt/test/runtime/iplt.c b/bolt/test/runtime/iplt.c
index b0e2e6d250700c9..d5b56d901e6227d 100644
--- a/bolt/test/runtime/iplt.c
+++ b/bolt/test/runtime/iplt.c
@@ -1,10 +1,16 @@
// This test checks that the ifuncs works after bolt.
+// Compiling with 00 results in IFUNC indirect calling.
-// RUN: %clang %cflags -no-pie %s -fuse-ld=lld \
+// RUN: %clang %cflags -O0 -no-pie %s -fuse-ld=lld \
// RUN: -o %t.exe -Wl,-q
// RUN: llvm-bolt %t.exe -o %t.bolt.exe --use-old-text=0 --lite=0
// RUN: %t.bolt.exe | FileCheck %s
+// RUN: %clang %cflags -O3 -no-pie %s -fuse-ld=lld \
+// RUN: -o %t.O3.exe -Wl,-q
+// RUN: llvm-bolt %t.O3.exe -o %t.O3.bolt.exe --use-old-text=0 --lite=0
+// RUN: %t.O3.bolt.exe | FileCheck %s
+
// CHECK: foo
#include <stdio.h>
More information about the llvm-commits
mailing list