[lld] r347404 - [ELF] Write IPLT header in -static -z retpolineplt mode

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 21 10:10:00 PST 2018


Author: maskray
Date: Wed Nov 21 10:10:00 2018
New Revision: 347404

URL: http://llvm.org/viewvc/llvm-project?rev=347404&view=rev
Log:
[ELF] Write IPLT header in -static -z retpolineplt mode

Summary:
This fixes PR39711: -static -z retpolineplt does not produce retpoline PLT header.
-z now is not relevant.

Statically linked executable does not have PLT, but may have IPLT with no header. When -z retpolineplt is specified, however, the repoline PLT header should still be emitted.

I've checked that this fixes the FreeBSD reproduce in PR39711 and a Linux program statically linked against glibc. The programm print "Hi" rather than SIGILL/SIGSEGV.

getPltEntryOffset may look dirty after this patch, but it can be cleaned up later.

Another possible improvement is that when there are non-preemptible IFUNC symbols (rare case, e.g. -Bsymbolic), both In.Plt and In.Iplt can be non-empty and we'll emit the retpoline PLT header twice.

Reviewers: espindola, emaste, chandlerc, ruiu

Reviewed By: emaste

Subscribers: emaste, arichardson, krytarowski, llvm-commits

Differential Revision: https://reviews.llvm.org/D54782

Added:
    lld/trunk/test/ELF/x86-64-retpoline-znow-static-iplt.s
Modified:
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/SyntheticSections.cpp

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=347404&r1=347403&r2=347404&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Wed Nov 21 10:10:00 2018
@@ -144,8 +144,11 @@ uint64_t Symbol::getPPC64LongBranchOffse
 }
 
 uint64_t Symbol::getPltVA() const {
-  if (this->IsInIplt)
+  if (this->IsInIplt) {
+    if (Config->ZRetpolineplt)
+      return In.Iplt->getVA() + Target->getPltEntryOffset(PltIndex);
     return In.Iplt->getVA() + PltIndex * Target->PltEntrySize;
+  }
   return In.Plt->getVA() + Target->getPltEntryOffset(PltIndex);
 }
 

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=347404&r1=347403&r2=347404&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Wed Nov 21 10:10:00 2018
@@ -2280,7 +2280,8 @@ void HashTableSection::writeTo(uint8_t *
 PltSection::PltSection(bool IsIplt)
     : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16,
                        Config->EMachine == EM_PPC64 ? ".glink" : ".plt"),
-      HeaderSize(IsIplt ? 0 : Target->PltHeaderSize), IsIplt(IsIplt) {
+      HeaderSize(!IsIplt || Config->ZRetpolineplt ? Target->PltHeaderSize : 0),
+      IsIplt(IsIplt) {
   // The PLT needs to be writable on SPARC as the dynamic linker will
   // modify the instructions in the PLT entries.
   if (Config->EMachine == EM_SPARCV9)
@@ -2288,9 +2289,9 @@ PltSection::PltSection(bool IsIplt)
 }
 
 void PltSection::writeTo(uint8_t *Buf) {
-  // At beginning of PLT but not the IPLT, we have code to call the dynamic
+  // At beginning of PLT or retpoline IPLT, we have code to call the dynamic
   // linker to resolve dynsyms at runtime. Write such code.
-  if (!IsIplt)
+  if (HeaderSize > 0)
     Target->writePltHeader(Buf);
   size_t Off = HeaderSize;
   // The IPlt is immediately after the Plt, account for this in RelOff

Added: lld/trunk/test/ELF/x86-64-retpoline-znow-static-iplt.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/x86-64-retpoline-znow-static-iplt.s?rev=347404&view=auto
==============================================================================
--- lld/trunk/test/ELF/x86-64-retpoline-znow-static-iplt.s (added)
+++ lld/trunk/test/ELF/x86-64-retpoline-znow-static-iplt.s Wed Nov 21 10:10:00 2018
@@ -0,0 +1,26 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld -z retpolineplt -z now %t.o -o %t
+# RUN: llvm-objdump -d -no-show-raw-insn %t | FileCheck %s
+
+#0x201001+5 + 42 = 0x201030 (foo at plt)
+# CHECK:      _start:
+# CHECK-NEXT:  201001:       callq   42
+
+#Static IPLT header due to -z retpolineplt
+# CHECK:      {{^}}.plt:
+# CHECK-NEXT:  201010:       callq   11 <.plt+0x10>
+# CHECK-NEXT:  201015:       pause
+# CHECK-NEXT:  201017:       lfence
+#foo at plt
+# CHECK:       201030:       movq    4041(%rip), %r11
+# CHECK-NEXT:  201037:       jmp     -44 <.plt>
+
+.type foo STT_GNU_IFUNC
+.globl foo
+foo:
+  ret
+
+.globl _start
+_start:
+  call foo




More information about the llvm-commits mailing list