[lld] 00925aa - [ELF][PPC32] Fix canonical PLTs when the order does not match the PLT order

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 28 22:25:00 PST 2020


Author: Fangrui Song
Date: 2020-02-28T22:23:14-08:00
New Revision: 00925aadb3f26ed41d4f1d35c1328adad1a3eeb1

URL: https://github.com/llvm/llvm-project/commit/00925aadb3f26ed41d4f1d35c1328adad1a3eeb1
DIFF: https://github.com/llvm/llvm-project/commit/00925aadb3f26ed41d4f1d35c1328adad1a3eeb1.diff

LOG: [ELF][PPC32] Fix canonical PLTs when the order does not match the PLT order

Reviewed By: Bdragon28

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

Added: 
    

Modified: 
    lld/ELF/Arch/PPC.cpp
    lld/ELF/Relocations.cpp
    lld/ELF/SyntheticSections.cpp
    lld/ELF/SyntheticSections.h
    lld/ELF/Writer.cpp
    lld/test/ELF/Inputs/canonical-plt-pcrel.s
    lld/test/ELF/ppc32-canonical-plt.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp
index 032674e98739..a1e81d0c34c0 100644
--- a/lld/ELF/Arch/PPC.cpp
+++ b/lld/ELF/Arch/PPC.cpp
@@ -76,12 +76,11 @@ void writePPC32GlinkSection(uint8_t *buf, size_t numEntries) {
   // non-GOT-non-PLT relocations referencing external functions for -fpie/-fPIE.
   uint32_t glink = in.plt->getVA(); // VA of .glink
   if (!config->isPic) {
-    for (const Symbol *sym : in.plt->entries)
-      if (sym->needsPltAddr) {
-        writePPC32PltCallStub(buf, sym->getGotPltVA(), nullptr, 0);
-        buf += 16;
-        glink += 16;
-      }
+    for (const Symbol *sym : cast<PPC32GlinkSection>(in.plt)->canonical_plts) {
+      writePPC32PltCallStub(buf, sym->getGotPltVA(), nullptr, 0);
+      buf += 16;
+      glink += 16;
+    }
   }
 
   // On PPC Secure PLT ABI, bl foo at plt jumps to a call stub, which loads an

diff  --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 8fa183297743..60972e839ca3 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1226,6 +1226,7 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
           // PPC32 canonical PLT entries are at the beginning of .glink
           cast<Defined>(sym).value = in.plt->headerSize;
           in.plt->headerSize += 16;
+          cast<PPC32GlinkSection>(in.plt)->canonical_plts.push_back(&sym);
         }
       }
       sym.needsPltAddr = true;

diff  --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 5de3df867c9f..d15226949e96 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2447,12 +2447,9 @@ PltSection::PltSection()
     : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".plt"),
       headerSize(target->pltHeaderSize) {
   // On PowerPC, this section contains lazy symbol resolvers.
-  if (config->emachine == EM_PPC || config->emachine == EM_PPC64) {
+  if (config->emachine == EM_PPC64) {
     name = ".glink";
     alignment = 4;
-    // PLTresolve is at the end.
-    if (config->emachine == EM_PPC)
-      footerSize = 64;
   }
 
   // On x86 when IBT is enabled, this section contains the second PLT (lazy
@@ -2468,11 +2465,6 @@ PltSection::PltSection()
 }
 
 void PltSection::writeTo(uint8_t *buf) {
-  if (config->emachine == EM_PPC) {
-    writePPC32GlinkSection(buf, entries.size());
-    return;
-  }
-
   // At beginning of PLT, we have code to call the dynamic
   // linker to resolve dynsyms at runtime. Write such code.
   target->writePltHeader(buf);
@@ -2490,7 +2482,7 @@ void PltSection::addEntry(Symbol &sym) {
 }
 
 size_t PltSection::getSize() const {
-  return headerSize + entries.size() * target->pltEntrySize + footerSize;
+  return headerSize + entries.size() * target->pltEntrySize;
 }
 
 bool PltSection::isNeeded() const {
@@ -2544,6 +2536,19 @@ void IpltSection::addSymbols() {
   }
 }
 
+PPC32GlinkSection::PPC32GlinkSection() {
+  name = ".glink";
+  alignment = 4;
+}
+
+void PPC32GlinkSection::writeTo(uint8_t *buf) {
+  writePPC32GlinkSection(buf, entries.size());
+}
+
+size_t PPC32GlinkSection::getSize() const {
+  return headerSize + entries.size() * target->pltEntrySize + footerSize;
+}
+
 // This is an x86-only extra PLT section and used only when a security
 // enhancement feature called CET is enabled. In this comment, I'll explain what
 // the feature is and why we have two PLT sections if CET is enabled.

diff  --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 5f59178fb541..190a4fd3ac9e 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -684,7 +684,6 @@ class PltSection : public SyntheticSection {
   size_t getNumEntries() const { return entries.size(); }
 
   size_t headerSize;
-  size_t footerSize = 0;
 
   std::vector<const Symbol *> entries;
 };
@@ -705,6 +704,16 @@ class IpltSection final : public SyntheticSection {
   void addEntry(Symbol &sym);
 };
 
+class PPC32GlinkSection : public PltSection {
+public:
+  PPC32GlinkSection();
+  void writeTo(uint8_t *buf) override;
+  size_t getSize() const override;
+
+  std::vector<const Symbol *> canonical_plts;
+  static constexpr size_t footerSize = 64;
+};
+
 // This is x86-only.
 class IBTPltSection : public SyntheticSection {
 public:

diff  --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 013f7d066703..b41aceb8634b 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -525,7 +525,8 @@ template <class ELFT> void createSyntheticSections() {
     add(in.ibtPlt);
   }
 
-  in.plt = make<PltSection>();
+  in.plt = config->emachine == EM_PPC ? make<PPC32GlinkSection>()
+                                      : make<PltSection>();
   add(in.plt);
   in.iplt = make<IpltSection>();
   add(in.iplt);

diff  --git a/lld/test/ELF/Inputs/canonical-plt-pcrel.s b/lld/test/ELF/Inputs/canonical-plt-pcrel.s
index 966f26a1e643..1547d848b65b 100644
--- a/lld/test/ELF/Inputs/canonical-plt-pcrel.s
+++ b/lld/test/ELF/Inputs/canonical-plt-pcrel.s
@@ -1,5 +1,7 @@
-.globl func, ifunc
+.globl func, func2, ifunc
 .type func, @function
+.type func2, @function
 .type ifunc, @gnu_indirect_function
 func:
+func2:
 ifunc:

diff  --git a/lld/test/ELF/ppc32-canonical-plt.s b/lld/test/ELF/ppc32-canonical-plt.s
index 371aa7325b2d..148e65283a94 100644
--- a/lld/test/ELF/ppc32-canonical-plt.s
+++ b/lld/test/ELF/ppc32-canonical-plt.s
@@ -14,49 +14,59 @@
 
 # REL:      Relocations [
 # REL-NEXT:   .rela.plt {
-# REL-NEXT:     R_PPC_JMP_SLOT func 0x0
-# REL-NEXT:     R_PPC_JMP_SLOT ifunc 0x0
+# REL-NEXT:     0x10030318 R_PPC_JMP_SLOT func 0x0
+# REL-NEXT:     0x1003031C R_PPC_JMP_SLOT func2 0x0
+# REL-NEXT:     0x10030320 R_PPC_JMP_SLOT ifunc 0x0
 # REL-NEXT:   }
 # REL-NEXT: ]
 
-# SYM: .glink PROGBITS 100101dc
+# SYM: .glink PROGBITS 1001022c
 
 ## st_value points to the canonical PLT entry in .glink
 # SYM: Symbol table '.dynsym'
-# SYM: 100101dc 0 FUNC GLOBAL DEFAULT UND func
-# SYM: 100101ec 0 FUNC GLOBAL DEFAULT UND ifunc
+# SYM: 1001023c 0 FUNC GLOBAL DEFAULT UND func
+# SYM: 1001022c 0 FUNC GLOBAL DEFAULT UND func2
+# SYM: 1001024c 0 FUNC GLOBAL DEFAULT UND ifunc
 # SYM: Symbol table '.symtab'
-# SYM: 100101dc 0 FUNC GLOBAL DEFAULT UND func
-# SYM: 100101ec 0 FUNC GLOBAL DEFAULT UND ifunc
+# SYM: 1001023c 0 FUNC GLOBAL DEFAULT UND func
+# SYM: 1001022c 0 FUNC GLOBAL DEFAULT UND func2
+# SYM: 1001024c 0 FUNC GLOBAL DEFAULT UND ifunc
 
-# HEX: 0x100302b4 100101fc 10010200
+# HEX: 0x10030318 1001025c 10010260 10010264
 
-## Canonical PLT entry of func.
-## 0x100101dc + 4*2 + 64 = 0x10010224
-## 0x1001021c = 65536*4099+692
-# CHECK:      100101dc .glink:
+## Canonical PLT entry of func2.
+## 0x1003031C = 65536*4099+796
+# CHECK:      1001022c .glink:
 # CHECK-NEXT:           lis 11, 4099
-# CHECK-NEXT:           lwz 11, 692(11)
+# CHECK-NEXT:           lwz 11, 796(11)
+# CHECK-NEXT:           mtctr 11
+# CHECK-NEXT:           bctr
+
+## Canonical PLT entry of func.
+## 0x10030318 = 65536*4099+792
+# CHECK-NEXT: 1001023c: lis 11, 4099
+# CHECK-NEXT:           lwz 11, 792(11)
 # CHECK-NEXT:           mtctr 11
 # CHECK-NEXT:           bctr
 
 ## Canonical PLT entry of ifunc.
-## 0x10010220 = 65536*4099+696
-# CHECK-NEXT: 100101ec: lis 11, 4099
-# CHECK-NEXT:           lwz 11, 696(11)
+## 0x10030320 = 65536*4099+800
+# CHECK-NEXT: 1001024c: lis 11, 4099
+# CHECK-NEXT:           lwz 11, 800(11)
 # CHECK-NEXT:           mtctr 11
 # CHECK-NEXT:           bctr
 
-## The 2 b instructions are referenced by .plt entries.
-# CHECK-NEXT: 100101fc: b .+8
+## The 3 b instructions are referenced by .plt entries.
+# CHECK-NEXT: 1001025c: b .+12
+# CHECK-NEXT:           b .+8
 # CHECK-NEXT:           b .+4
 
 ## PLTresolve of 64 bytes is at the end.
-## Operands of addis & addi: -0x100101fc = 65536*-4097-508
+## Operands of addis & addi: -0x1001025c = 65536*-4097-604
 # CHECK-NEXT:           lis 12, 0
 # CHECK-NEXT:           addis 11, 11, -4097
 # CHECK-NEXT:           lwz 0, 4(12)
-# CHECK-NEXT:           addi 11, 11, -508
+# CHECK-NEXT:           addi 11, 11, -604
 # CHECK-NEXT:           mtctr 0
 # CHECK-NEXT:           add 0, 11, 11
 # CHECK-NEXT:           lwz 12, 8(12)
@@ -66,6 +76,9 @@
 
 .globl _start
 _start:
+  b func
+  lis 3, func2 at ha
+  la 3, func2 at l(3)
   lis 3, func at ha
   la 3, func at l(3)
   lis 4, ifunc at ha


        


More information about the llvm-commits mailing list