[lld] r362721 - [PPC32] Improve the 32-bit PowerPC port

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 6 10:03:00 PDT 2019


Author: maskray
Date: Thu Jun  6 10:03:00 2019
New Revision: 362721

URL: http://llvm.org/viewvc/llvm-project?rev=362721&view=rev
Log:
[PPC32] Improve the 32-bit PowerPC port

Many -static/-no-pie/-shared/-pie applications linked against glibc or musl
should work with this patch. This also helps FreeBSD PowerPC64 to migrate
their lib32 (PR40888).

* Fix default image base and max page size.
* Support new-style Secure PLT (see below). Old-style BSS PLT is not
  implemented, so it is not suitable for FreeBSD rtld now because it doesn't
  support Secure PLT yet.
* Support more initial relocation types:
  R_PPC_ADDR32, R_PPC_REL16*, R_PPC_LOCAL24PC, R_PPC_PLTREL24, and R_PPC_GOT16.
  The addend of R_PPC_PLTREL24 is special: it decides the call stub PLT type
  but it should be ignored for the computation of target symbol VA.
* Support GNU ifunc
* Support .glink used for lazy PLT resolution in glibc
* Add a new thunk type: PPC32PltCallStub that is similar to PPC64PltCallStub.
  It is used by R_PPC_REL24 and R_PPC_PLTREL24.

A PLT stub used in -fPIE/-fPIC usually loads an address relative to
.got2+0x8000 (-fpie/-fpic code uses _GLOBAL_OFFSET_TABLE_ relative
addresses).
Two .got2 sections in two object files have different addresses, thus a PLT stub
can't be shared by two object files. To handle this incompatibility,
change the parameters of Thunk::isCompatibleWith to
`const InputSection &, const Relocation &`.

PowerPC psABI specified an old-style .plt (BSS PLT) that is both
writable and executable. Linkers don't make separate RW- and RWE segments,
which causes all initially writable memory (think .data) executable.
This is a big security concern so a new PLT scheme (secure PLT) was developed to
address the security issue.

TLS will be implemented in D62940.

glibc older than ~2012 requires .rela.dyn to include .rela.plt, it can
not handle the DT_RELA+DT_RELASZ == DT_JMPREL case correctly. A hack
(not included in this patch) in LinkerScript.cpp addOrphanSections() to
work around the issue:

    if (Config->EMachine == EM_PPC) {
      // Older glibc assumes .rela.dyn includes .rela.plt
      Add(In.RelaDyn);
      if (In.RelaPlt->isLive() && !In.RelaPlt->Parent)
        In.RelaDyn->getParent()->addSection(In.RelaPlt);
    }

Reviewed By: ruiu

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

Added:
    lld/trunk/test/ELF/ppc32-abs-pic.s
    lld/trunk/test/ELF/ppc32-call-stub-nopic.s
    lld/trunk/test/ELF/ppc32-call-stub-pic.s
    lld/trunk/test/ELF/ppc32-gnu-ifunc-nonpreemptable.s
    lld/trunk/test/ELF/ppc32-gnu-ifunc.s
    lld/trunk/test/ELF/ppc32-local-branch.s
    lld/trunk/test/ELF/ppc32-reloc-addr.s
    lld/trunk/test/ELF/ppc32-reloc-got.s
    lld/trunk/test/ELF/ppc32-reloc-rel.s
    lld/trunk/test/ELF/ppc32-weak-undef-call.s
Removed:
    lld/trunk/test/ELF/ppc-relocs.s
Modified:
    lld/trunk/ELF/Arch/PPC.cpp
    lld/trunk/ELF/InputFiles.h
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/Relocations.h
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.h
    lld/trunk/ELF/Target.h
    lld/trunk/ELF/Thunks.cpp
    lld/trunk/ELF/Thunks.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/basic-ppc.s
    lld/trunk/test/ELF/ppc-rela.s
    lld/trunk/test/ELF/silent-ignore.test

Modified: lld/trunk/ELF/Arch/PPC.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC.cpp?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC.cpp (original)
+++ lld/trunk/ELF/Arch/PPC.cpp Thu Jun  6 10:03:00 2019
@@ -6,7 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "OutputSections.h"
 #include "Symbols.h"
+#include "SyntheticSections.h"
 #include "Target.h"
 #include "lld/Common/ErrorHandler.h"
 #include "llvm/Support/Endian.h"
@@ -21,26 +23,165 @@ namespace {
 class PPC final : public TargetInfo {
 public:
   PPC();
-  void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
+  void writeGotHeader(uint8_t *Buf) const override;
+  void writePltHeader(uint8_t *Buf) const override {
+    llvm_unreachable("should call writePPC32GlinkSection() instead");
+  }
+  void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
+    int32_t Index, unsigned RelOff) const override {
+    llvm_unreachable("should call writePPC32GlinkSection() instead");
+  }
+  void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;
+  bool needsThunk(RelExpr Expr, RelType RelocType, const InputFile *File,
+                  uint64_t BranchAddr, const Symbol &S) const override;
+  uint32_t getThunkSectionSpacing() const override;
+  bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override;
   RelExpr getRelExpr(RelType Type, const Symbol &S,
                      const uint8_t *Loc) const override;
+  void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
 };
 } // namespace
 
+static uint16_t lo(uint32_t V) { return V; }
+static uint16_t ha(uint32_t V) { return (V + 0x8000) >> 16; }
+
+void elf::writePPC32GlinkSection(uint8_t *Buf, size_t NumEntries) {
+  // On PPC Secure PLT ABI, bl foo at plt jumps to a call stub, which loads an
+  // absolute address from a specific .plt slot (usually called .got.plt on
+  // other targets) and jumps there.
+  //
+  // a) With immediate binding (BIND_NOW), the .plt entry is resolved at load
+  // time. The .glink section is not used.
+  // b) With lazy binding, the .plt entry points to a `b PLTresolve`
+  // instruction in .glink, filled in by PPC::writeGotPlt().
+
+  // Write N `b PLTresolve` first.
+  for (size_t I = 0; I != NumEntries; ++I)
+    write32(Buf + 4 * I, 0x48000000 | 4 * (NumEntries - I));
+  Buf += 4 * NumEntries;
+
+  // Then write PLTresolve(), which has two forms: PIC and non-PIC. PLTresolve()
+  // computes the PLT index (by computing the distance from the landing b to
+  // itself) and calls _dl_runtime_resolve() (in glibc).
+  uint32_t GOT = In.Got->getVA();
+  uint32_t Glink = In.Plt->getVA(); // VA of .glink
+  const uint8_t *End = Buf + 64;
+  if (Config->Pic) {
+    uint32_t AfterBcl = In.Plt->getSize() - Target->PltHeaderSize + 12;
+    uint32_t GotBcl = GOT + 4 - (Glink + AfterBcl);
+    write32(Buf + 0, 0x3d6b0000 | ha(AfterBcl));  // addis r11,r11,1f-glink at ha
+    write32(Buf + 4, 0x7c0802a6);                 // mflr r0
+    write32(Buf + 8, 0x429f0005);                 // bcl 20,30,.+4
+    write32(Buf + 12, 0x396b0000 | lo(AfterBcl)); // 1: addi r11,r11,1b-.glink at l
+    write32(Buf + 16, 0x7d8802a6);                // mflr r12
+    write32(Buf + 20, 0x7c0803a6);                // mtlr r0
+    write32(Buf + 24, 0x7d6c5850);                // sub r11,r11,r12
+    write32(Buf + 28, 0x3d8c0000 | ha(GotBcl));   // addis 12,12,GOT+4-1b at ha
+    if (ha(GotBcl) == ha(GotBcl + 4)) {
+      write32(Buf + 32, 0x800c0000 | lo(GotBcl)); // lwz r0,r12,GOT+4-1b at l(r12)
+      write32(Buf + 36,
+              0x818c0000 | lo(GotBcl + 4));       // lwz r12,r12,GOT+8-1b at l(r12)
+    } else {
+      write32(Buf + 32, 0x840c0000 | lo(GotBcl)); // lwzu r0,r12,GOT+4-1b at l(r12)
+      write32(Buf + 36, 0x818c0000 | 4);          // lwz r12,r12,4(r12)
+    }
+    write32(Buf + 40, 0x7c0903a6);                // mtctr 0
+    write32(Buf + 44, 0x7c0b5a14);                // add r0,11,11
+    write32(Buf + 48, 0x7d605a14);                // add r11,0,11
+    write32(Buf + 52, 0x4e800420);                // bctr
+    Buf += 56;
+  } else {
+    write32(Buf + 0, 0x3d800000 | ha(GOT + 4));   // lis     r12,GOT+4 at ha
+    write32(Buf + 4, 0x3d6b0000 | ha(-Glink));    // addis   r11,r11,-Glink at ha
+    if (ha(GOT + 4) == ha(GOT + 8))
+      write32(Buf + 8, 0x800c0000 | lo(GOT + 4)); // lwz r0,GOT+4 at l(r12)
+    else
+      write32(Buf + 8, 0x840c0000 | lo(GOT + 4)); // lwzu r0,GOT+4 at l(r12)
+    write32(Buf + 12, 0x396b0000 | lo(-Glink));   // addi    r11,r11,-Glink at l
+    write32(Buf + 16, 0x7c0903a6);                // mtctr   r0
+    write32(Buf + 20, 0x7c0b5a14);                // add     r0,r11,r11
+    if (ha(GOT + 4) == ha(GOT + 8))
+      write32(Buf + 24, 0x818c0000 | lo(GOT + 8)); // lwz r12,GOT+8 at ha(r12)
+    else
+      write32(Buf + 24, 0x818c0000 | 4);          // lwz r12,4(r12)
+    write32(Buf + 28, 0x7d605a14);                // add     r11,r0,r11
+    write32(Buf + 32, 0x4e800420);                // bctr
+    Buf += 36;
+  }
+
+  // Pad with nop. They should not be executed.
+  for (; Buf < End; Buf += 4)
+    write32(Buf, 0x60000000);
+}
+
 PPC::PPC() {
+  GotRel = R_PPC_GLOB_DAT;
   NoneRel = R_PPC_NONE;
+  PltRel = R_PPC_JMP_SLOT;
+  RelativeRel = R_PPC_RELATIVE;
+  IRelativeRel = R_PPC_IRELATIVE;
   GotBaseSymInGotPlt = false;
+  GotHeaderEntriesNum = 3;
+  GotPltHeaderEntriesNum = 0;
+  PltHeaderSize = 64; // size of PLTresolve in .glink
+  PltEntrySize = 4;
+
+  NeedsThunks = true;
+
+  DefaultMaxPageSize = 65536;
+  DefaultImageBase = 0x10000000;
+
+  write32(TrapInstr.data(), 0x7fe00008);
+}
+
+void PPC::writeGotHeader(uint8_t *Buf) const {
+  // _GLOBAL_OFFSET_TABLE_[0] = _DYNAMIC
+  // glibc stores _dl_runtime_resolve in _GLOBAL_OFFSET_TABLE_[1],
+  // link_map in _GLOBAL_OFFSET_TABLE_[2].
+  write32(Buf, In.Dynamic->getVA());
+}
+
+void PPC::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
+  // Address of the symbol resolver stub in .glink .
+  write32(Buf, In.Plt->getVA() + 4 * S.PltIndex);
+}
+
+bool PPC::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,
+                     uint64_t BranchAddr, const Symbol &S) const {
+  if (Type != R_PPC_REL24 && Type != R_PPC_PLTREL24)
+    return false;
+  if (S.isInPlt())
+    return true;
+  if (S.isUndefWeak())
+    return false;
+  return !(Expr == R_PC && PPC::inBranchRange(Type, BranchAddr, S.getVA()));
+}
+
+uint32_t PPC::getThunkSectionSpacing() const { return 0x2000000; }
+
+bool PPC::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const {
+  uint64_t Offset = Dst - Src;
+  if (Type == R_PPC_REL24 || R_PPC_PLTREL24)
+    return isInt<26>(Offset);
+  llvm_unreachable("unsupported relocation type used in branch");
 }
 
 RelExpr PPC::getRelExpr(RelType Type, const Symbol &S,
                         const uint8_t *Loc) const {
   switch (Type) {
   case R_PPC_REL14:
-  case R_PPC_REL24:
   case R_PPC_REL32:
+  case R_PPC_LOCAL24PC:
+  case R_PPC_REL16_LO:
+  case R_PPC_REL16_HI:
+  case R_PPC_REL16_HA:
     return R_PC;
-  case R_PPC_PLTREL24:
+  case R_PPC_GOT16:
+    return R_GOT_OFF;
+  case R_PPC_REL24:
     return R_PLT_PC;
+  case R_PPC_PLTREL24:
+    return R_PPC32_PLTREL;
   default:
     return R_ABS;
   }
@@ -48,26 +189,44 @@ RelExpr PPC::getRelExpr(RelType Type, co
 
 void PPC::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
   switch (Type) {
+  case R_PPC_ADDR16:
+  case R_PPC_GOT16:
+    checkInt(Loc, Val, 16, Type);
+    write16(Loc, Val);
+    break;
   case R_PPC_ADDR16_HA:
-    write16be(Loc, (Val + 0x8000) >> 16);
+  case R_PPC_REL16_HA:
+    write16(Loc, ha(Val));
     break;
   case R_PPC_ADDR16_HI:
-    write16be(Loc, Val >> 16);
+  case R_PPC_REL16_HI:
+    write16(Loc, Val >> 16);
     break;
   case R_PPC_ADDR16_LO:
-    write16be(Loc, Val);
+  case R_PPC_REL16_LO:
+    write16(Loc, Val);
     break;
   case R_PPC_ADDR32:
+  case R_PPC_GLOB_DAT:
   case R_PPC_REL32:
-    write32be(Loc, Val);
+    write32(Loc, Val);
     break;
-  case R_PPC_REL14:
-    write32be(Loc, read32be(Loc) | (Val & 0xFFFC));
+  case R_PPC_REL14: {
+    uint32_t Mask = 0x0000FFFC;
+    checkInt(Loc, Val, 16, Type);
+    checkAlignment(Loc, Val, 4, Type);
+    write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask));
     break;
-  case R_PPC_PLTREL24:
+  }
   case R_PPC_REL24:
-    write32be(Loc, read32be(Loc) | (Val & 0x3FFFFFC));
+  case R_PPC_LOCAL24PC:
+  case R_PPC_PLTREL24: {
+    uint32_t Mask = 0x03FFFFFC;
+    checkInt(Loc, Val, 26, Type);
+    checkAlignment(Loc, Val, 4, Type);
+    write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask));
     break;
+  }
   default:
     error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type));
   }

Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Thu Jun  6 10:03:00 2019
@@ -117,6 +117,10 @@ public:
   // True if this is an argument for --just-symbols. Usually false.
   bool JustSymbols = false;
 
+  // OutSecOff of .got2 in the current file. This is used by PPC32 -fPIC/-fPIE
+  // to compute offsets in PLT call stubs.
+  uint32_t PPC32Got2OutSecOff = 0;
+
   // On PPC64 we need to keep track of which files contain small code model
   // relocations that access the .toc section. To minimize the chance of a
   // relocation overflow, files that do contain said relocations should have

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Thu Jun  6 10:03:00 2019
@@ -718,6 +718,8 @@ static uint64_t getRelocTargetVA(const I
         Dest = getARMUndefinedRelativeWeakVA(Type, A, P);
       else if (Config->EMachine == EM_AARCH64)
         Dest = getAArch64UndefinedRelativeWeakVA(Type, A, P);
+      else if (Config->EMachine == EM_PPC)
+        Dest = P;
       else
         Dest = Sym.getVA(A);
     } else {
@@ -730,6 +732,11 @@ static uint64_t getRelocTargetVA(const I
   case R_PLT_PC:
   case R_PPC64_CALL_PLT:
     return Sym.getPltVA() + A - P;
+  case R_PPC32_PLTREL:
+    // R_PPC_PLTREL24 uses the addend (usually 0 or 0x8000) to indicate r30
+    // stores _GLOBAL_OFFSET_TABLE_ or .got2+0x8000. The addend is ignored for
+    // target VA compuation.
+    return Sym.getPltVA() - P;
   case R_PPC64_CALL: {
     uint64_t SymVA = Sym.getVA(A);
     // If we have an undefined weak symbol, we might get here with a symbol

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Thu Jun  6 10:03:00 2019
@@ -537,6 +537,7 @@ def: F<"no-warn-mismatch">;
 def: Flag<["-"], "p">;
 def: Separate<["--", "-"], "rpath-link">;
 def: J<"rpath-link=">;
+def: F<"secure-plt">;
 def: F<"sort-common">;
 def: F<"stats">;
 def: F<"warn-execstack">;

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Thu Jun  6 10:03:00 2019
@@ -363,7 +363,7 @@ static bool isAbsoluteValue(const Symbol
 
 // Returns true if Expr refers a PLT entry.
 static bool needsPlt(RelExpr Expr) {
-  return oneof<R_PLT_PC, R_PPC64_CALL_PLT, R_PLT>(Expr);
+  return oneof<R_PLT_PC, R_PPC32_PLTREL, R_PPC64_CALL_PLT, R_PLT>(Expr);
 }
 
 // Returns true if Expr refers a GOT entry. Note that this function
@@ -399,8 +399,8 @@ static bool isStaticLinkTimeConstant(Rel
             R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOTREL, R_MIPS_GOT_OFF,
             R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, R_MIPS_TLSGD,
             R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, R_GOTPLTONLY_PC,
-            R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC, R_PPC64_CALL_PLT,
-            R_PPC64_RELAX_TOC, R_TLSDESC_CALL, R_TLSDESC_PC,
+            R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC, R_PPC32_PLTREL,
+            R_PPC64_CALL_PLT, R_PPC64_RELAX_TOC, R_TLSDESC_CALL, R_TLSDESC_PC,
             R_AARCH64_TLSDESC_PAGE, R_HINT, R_TLSLD_HINT, R_TLSIE_HINT>(E))
     return true;
 
@@ -469,6 +469,7 @@ static RelExpr fromPlt(RelExpr Expr) {
   // reference to the symbol itself.
   switch (Expr) {
   case R_PLT_PC:
+  case R_PPC32_PLTREL:
     return R_PC;
   case R_PPC64_CALL_PLT:
     return R_PPC64_CALL;
@@ -1105,6 +1106,9 @@ static void scanReloc(InputSectionBase &
          getLocation(Sec, Sym, Offset));
   }
 
+  // Read an addend.
+  int64_t Addend = computeAddend<ELFT>(Rel, End, Sec, Expr, Sym.isLocal());
+
   // Relax relocations.
   //
   // If we know that a PLT entry will be resolved within the same ELF module, we
@@ -1114,10 +1118,15 @@ static void scanReloc(InputSectionBase &
   // runtime, because the main exectuable is always at the beginning of a search
   // list. We can leverage that fact.
   if (!Sym.IsPreemptible && (!Sym.isGnuIFunc() || Config->ZIfuncNoplt)) {
-    if (Expr == R_GOT_PC && !isAbsoluteValue(Sym))
+    if (Expr == R_GOT_PC && !isAbsoluteValue(Sym)) {
       Expr = Target->adjustRelaxExpr(Type, RelocatedAddr, Expr);
-    else
+    } else {
+      // Addend of R_PPC_PLTREL24 is used to choose call stub type. It should be
+      // ignored if optimized to R_PC.
+      if (Config->EMachine == EM_PPC && Expr == R_PPC32_PLTREL)
+        Addend = 0;
       Expr = fromPlt(Expr);
+    }
   }
 
   // If the relocation does not emit a GOT or GOTPLT entry but its computation
@@ -1131,9 +1140,6 @@ static void scanReloc(InputSectionBase &
     In.Got->HasGotOffRel = true;
   }
 
-  // Read an addend.
-  int64_t Addend = computeAddend<ELFT>(Rel, End, Sec, Expr, Sym.isLocal());
-
   // Process some TLS relocations, including relaxing TLS relocations.
   // Note that this function does not handle all TLS relocations.
   if (unsigned Processed =
@@ -1618,27 +1624,27 @@ static bool isThunkSectionCompatible(Inp
   return true;
 }
 
-std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *IS, Symbol &Sym,
-                                                RelType Type, uint64_t Src) {
+std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *IS,
+                                                Relocation &Rel, uint64_t Src) {
   std::vector<Thunk *> *ThunkVec = nullptr;
 
   // We use (section, offset) pair to find the thunk position if possible so
   // that we create only one thunk for aliased symbols or ICFed sections.
-  if (auto *D = dyn_cast<Defined>(&Sym))
+  if (auto *D = dyn_cast<Defined>(Rel.Sym))
     if (!D->isInPlt() && D->Section)
       ThunkVec = &ThunkedSymbolsBySection[{D->Section->Repl, D->Value}];
   if (!ThunkVec)
-    ThunkVec = &ThunkedSymbols[&Sym];
+    ThunkVec = &ThunkedSymbols[Rel.Sym];
 
   // Check existing Thunks for Sym to see if they can be reused
   for (Thunk *T : *ThunkVec)
     if (isThunkSectionCompatible(IS, T->getThunkTargetSym()->Section) &&
-        T->isCompatibleWith(Type) &&
-        Target->inBranchRange(Type, Src, T->getThunkTargetSym()->getVA()))
+        T->isCompatibleWith(*IS, Rel) &&
+        Target->inBranchRange(Rel.Type, Src, T->getThunkTargetSym()->getVA()))
       return std::make_pair(T, false);
 
   // No existing compatible Thunk in range, create a new one
-  Thunk *T = addThunk(Type, Sym);
+  Thunk *T = addThunk(*IS, Rel);
   ThunkVec->push_back(T);
   return std::make_pair(T, true);
 }
@@ -1717,7 +1723,7 @@ bool ThunkCreator::createThunks(ArrayRef
 
             Thunk *T;
             bool IsNew;
-            std::tie(T, IsNew) = getThunk(IS, *Rel.Sym, Rel.Type, Src);
+            std::tie(T, IsNew) = getThunk(IS, Rel, Src);
 
             if (IsNew) {
               // Find or create a ThunkSection for the new Thunk
@@ -1733,6 +1739,10 @@ bool ThunkCreator::createThunks(ArrayRef
             // Redirect relocation to Thunk, we never go via the PLT to a Thunk
             Rel.Sym = T->getThunkTargetSym();
             Rel.Expr = fromPlt(Rel.Expr);
+
+            // Addend of R_PPC_PLTREL24 should be ignored after changing to R_PC.
+            if (Config->EMachine == EM_PPC && Rel.Type == R_PPC_PLTREL24)
+              Rel.Addend = 0;
           }
 
         for (auto &P : ISD->ThunkSections)

Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Thu Jun  6 10:03:00 2019
@@ -91,6 +91,7 @@ enum RelExpr {
   R_MIPS_GOT_OFF32,
   R_MIPS_TLSGD,
   R_MIPS_TLSLD,
+  R_PPC32_PLTREL,
   R_PPC64_CALL,
   R_PPC64_CALL_PLT,
   R_PPC64_RELAX_TOC,
@@ -136,7 +137,7 @@ private:
 
   void createInitialThunkSections(ArrayRef<OutputSection *> OutputSections);
 
-  std::pair<Thunk *, bool> getThunk(InputSection *IS, Symbol &Sym, RelType Type,
+  std::pair<Thunk *, bool> getThunk(InputSection *IS, Relocation &Rel,
                                     uint64_t Src);
 
   ThunkSection *addThunkSection(OutputSection *OS, InputSectionDescription *,

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Thu Jun  6 10:03:00 2019
@@ -1057,10 +1057,15 @@ void MipsGotSection::writeTo(uint8_t *Bu
 // section. I don't know why we have a BSS style type for the section but it is
 // consitent across both 64-bit PowerPC ABIs as well as the 32-bit PowerPC ABI.
 GotPltSection::GotPltSection()
-    : SyntheticSection(SHF_ALLOC | SHF_WRITE,
-                       Config->EMachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS,
-                       Config->Wordsize,
-                       Config->EMachine == EM_PPC64 ? ".plt" : ".got.plt") {}
+    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize,
+                       ".got.plt") {
+  if (Config->EMachine == EM_PPC) {
+    Name = ".plt";
+  } else if (Config->EMachine == EM_PPC64) {
+    Type = SHT_NOBITS;
+    Name = ".plt";
+  }
+}
 
 void GotPltSection::addEntry(Symbol &Sym) {
   assert(Sym.PltIndex == Entries.size());
@@ -1404,6 +1409,11 @@ template <class ELFT> void DynamicSectio
     }
   }
 
+  // DT_PPC_GOT indicates to glibc Secure PLT is used. If DT_PPC_GOT is absent,
+  // glibc assumes the old-style BSS PLT layout which we don't support.
+  if (Config->EMachine == EM_PPC)
+    add(DT_PPC_GOT, [] { return In.Got->getVA(); });
+
   // Glink dynamic tag is required by the V2 abi if the plt section isn't empty.
   if (Config->EMachine == EM_PPC64 && In.Plt->isNeeded()) {
     // The Glink tag points to 32 bytes before the first lazy symbol resolution
@@ -2279,8 +2289,11 @@ void HashTableSection::writeTo(uint8_t *
 // On PowerPC64 the lazy symbol resolvers go into the `global linkage table`
 // in the .glink section, rather then the typical .plt section.
 PltSection::PltSection(bool IsIplt)
-    : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16,
-                       Config->EMachine == EM_PPC64 ? ".glink" : ".plt"),
+    : SyntheticSection(
+          SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16,
+          (Config->EMachine == EM_PPC || Config->EMachine == EM_PPC64)
+              ? ".glink"
+              : ".plt"),
       HeaderSize(!IsIplt || Config->ZRetpolineplt ? Target->PltHeaderSize : 0),
       IsIplt(IsIplt) {
   // The PLT needs to be writable on SPARC as the dynamic linker will
@@ -2290,6 +2303,11 @@ PltSection::PltSection(bool IsIplt)
 }
 
 void PltSection::writeTo(uint8_t *Buf) {
+  if (Config->EMachine == EM_PPC) {
+    writePPC32GlinkSection(Buf, Entries.size());
+    return;
+  }
+
   // At beginning of PLT or retpoline IPLT, we have code to call the dynamic
   // linker to resolve dynsyms at runtime. Write such code.
   if (HeaderSize)
@@ -3236,6 +3254,37 @@ bool ThunkSection::assignOffsets() {
   return Changed;
 }
 
+PPC32Got2Section::PPC32Got2Section()
+    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, 4, ".got2") {}
+
+bool PPC32Got2Section::isNeeded() const {
+  // See the comment below. This is not needed if there is no other
+  // InputSection.
+  for (BaseCommand *Base : getParent()->SectionCommands)
+    if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
+      for (InputSection *IS : ISD->Sections)
+        if (IS != this)
+          return true;
+  return false;
+}
+
+void PPC32Got2Section::finalizeContents() {
+  // PPC32 may create multiple GOT sections for -fPIC/-fPIE, one per file in
+  // .got2 . This function computes OutSecOff of each .got2 to be used in
+  // PPC32PltCallStub::writeTo(). The purpose of this empty synthetic section is
+  // to collect input sections named ".got2".
+  uint32_t Offset = 0;
+  for (BaseCommand *Base : getParent()->SectionCommands)
+    if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) {
+      for (InputSection *IS : ISD->Sections) {
+        if (IS == this)
+          continue;
+        IS->File->PPC32Got2OutSecOff = Offset;
+        Offset += (uint32_t)IS->getSize();
+      }
+    }
+}
+
 // If linking position-dependent code then the table will store the addresses
 // directly in the binary so the section has type SHT_PROGBITS. If linking
 // position-independent code the section has type SHT_NOBITS since it will be

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Thu Jun  6 10:03:00 2019
@@ -1041,6 +1041,17 @@ private:
   size_t Size = 0;
 };
 
+// Used to compute OutSecOff of .got2 in each object file. This is needed to
+// synthesize PLT entries for PPC32 Secure PLT ABI.
+class PPC32Got2Section final : public SyntheticSection {
+public:
+  PPC32Got2Section();
+  size_t getSize() const override { return 0; }
+  bool isNeeded() const override;
+  void finalizeContents() override;
+  void writeTo(uint8_t *Buf) override {}
+};
+
 // This section is used to store the addresses of functions that are called
 // in range-extending thunks on PowerPC64. When producing position dependant
 // code the addresses are link-time constants and the table is written out to
@@ -1100,6 +1111,7 @@ struct InStruct {
   MipsRldMapSection *MipsRldMap;
   PltSection *Plt;
   PltSection *Iplt;
+  PPC32Got2Section *PPC32Got2;
   RelocationBaseSection *RelaDyn;
   RelrBaseSection *RelrDyn;
   RelocationBaseSection *RelaPlt;

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Thu Jun  6 10:03:00 2019
@@ -162,6 +162,8 @@ static inline std::string getErrorLocati
   return getErrorPlace(Loc).Loc;
 }
 
+void writePPC32GlinkSection(uint8_t *Buf, size_t NumEntries);
+
 bool tryRelaxPPC64TocIndirection(RelType Type, const Relocation &Rel,
                                  uint8_t *BufLoc);
 

Modified: lld/trunk/ELF/Thunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.cpp?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/ELF/Thunks.cpp (original)
+++ lld/trunk/ELF/Thunks.cpp Thu Jun  6 10:03:00 2019
@@ -78,7 +78,8 @@ public:
   bool mayUseShortThunk();
   uint32_t size() override { return mayUseShortThunk() ? 4 : sizeLong(); }
   void writeTo(uint8_t *Buf) override;
-  bool isCompatibleWith(RelType Type) const override;
+  bool isCompatibleWith(const InputSection &IS,
+                        const Relocation &Rel) const override;
 
   // Returns the size of a long thunk.
   virtual uint32_t sizeLong() = 0;
@@ -107,7 +108,8 @@ public:
   bool mayUseShortThunk();
   uint32_t size() override { return mayUseShortThunk() ? 4 : sizeLong(); }
   void writeTo(uint8_t *Buf) override;
-  bool isCompatibleWith(RelType Type) const override;
+  bool isCompatibleWith(const InputSection &IS,
+                        const Relocation &Rel) const override;
 
   // Returns the size of a long thunk.
   virtual uint32_t sizeLong() = 0;
@@ -170,7 +172,8 @@ public:
   uint32_t sizeLong() override { return 8; }
   void writeLong(uint8_t *Buf) override;
   void addSymbols(ThunkSection &IS) override;
-  bool isCompatibleWith(uint32_t RelocType) const override;
+  bool isCompatibleWith(const InputSection &IS,
+                        const Relocation &Rel) const override;
 };
 
 class ARMV5PILongThunk final : public ARMThunk {
@@ -180,7 +183,8 @@ public:
   uint32_t sizeLong() override { return 16; }
   void writeLong(uint8_t *Buf) override;
   void addSymbols(ThunkSection &IS) override;
-  bool isCompatibleWith(uint32_t RelocType) const override;
+  bool isCompatibleWith(const InputSection &IS,
+                        const Relocation &Rel) const override;
 };
 
 // Implementations of Thunks for Arm v6-M. Only Thumb instructions are permitted
@@ -235,6 +239,24 @@ public:
   InputSection *getTargetInputSection() const override;
 };
 
+class PPC32PltCallStub final : public Thunk {
+public:
+  PPC32PltCallStub(const InputSection &IS, const Relocation &Rel, Symbol &Dest)
+      : Thunk(Dest), Addend(Rel.Type == R_PPC_PLTREL24 ? Rel.Addend : 0),
+        File(IS.File) {}
+  uint32_t size() override { return 16; }
+  void writeTo(uint8_t *Buf) override;
+  void addSymbols(ThunkSection &IS) override;
+  bool isCompatibleWith(const InputSection &IS, const Relocation &Rel) const override;
+
+private:
+  // For R_PPC_PLTREL24, this records the addend, which will be used to decide
+  // the offsets in the call stub.
+  uint32_t Addend;
+
+  // Records the call site of the call stub.
+  const InputFile *File;
+};
 
 // PPC64 Plt call stubs.
 // Any call site that needs to call through a plt entry needs a call stub in
@@ -396,9 +418,10 @@ void ARMThunk::writeTo(uint8_t *Buf) {
   Target->relocateOne(Buf, R_ARM_JUMP24, Offset);
 }
 
-bool ARMThunk::isCompatibleWith(RelType Type) const {
+bool ARMThunk::isCompatibleWith(const InputSection &IS,
+                                const Relocation &Rel) const {
   // Thumb branch relocations can't use BLX
-  return Type != R_ARM_THM_JUMP19 && Type != R_ARM_THM_JUMP24;
+  return Rel.Type != R_ARM_THM_JUMP19 && Rel.Type != R_ARM_THM_JUMP24;
 }
 
 // This function returns true if the target is Thumb and is within 2^25, and
@@ -433,9 +456,10 @@ void ThumbThunk::writeTo(uint8_t *Buf) {
   Target->relocateOne(Buf, R_ARM_THM_JUMP24, Offset);
 }
 
-bool ThumbThunk::isCompatibleWith(RelType Type) const {
+bool ThumbThunk::isCompatibleWith(const InputSection &IS,
+                                  const Relocation &Rel) const {
   // ARM branch relocations can't use BLX
-  return Type != R_ARM_JUMP24 && Type != R_ARM_PC24 && Type != R_ARM_PLT32;
+  return Rel.Type != R_ARM_JUMP24 && Rel.Type != R_ARM_PC24 && Rel.Type != R_ARM_PLT32;
 }
 
 void ARMV7ABSLongThunk::writeLong(uint8_t *Buf) {
@@ -532,9 +556,10 @@ void ARMV5ABSLongThunk::addSymbols(Thunk
   addSymbol("$d", STT_NOTYPE, 4, IS);
 }
 
-bool ARMV5ABSLongThunk::isCompatibleWith(uint32_t RelocType) const {
+bool ARMV5ABSLongThunk::isCompatibleWith(const InputSection &IS,
+                                         const Relocation &Rel) const {
   // Thumb branch relocations can't use BLX
-  return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24;
+  return Rel.Type != R_ARM_THM_JUMP19 && Rel.Type != R_ARM_THM_JUMP24;
 }
 
 void ARMV5PILongThunk::writeLong(uint8_t *Buf) {
@@ -557,9 +582,10 @@ void ARMV5PILongThunk::addSymbols(ThunkS
   addSymbol("$d", STT_NOTYPE, 12, IS);
 }
 
-bool ARMV5PILongThunk::isCompatibleWith(uint32_t RelocType) const {
+bool ARMV5PILongThunk::isCompatibleWith(const InputSection &IS,
+                                        const Relocation &Rel) const {
   // Thumb branch relocations can't use BLX
-  return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24;
+  return Rel.Type != R_ARM_THM_JUMP19 && Rel.Type != R_ARM_THM_JUMP24;
 }
 
 void ThumbV6MABSLongThunk::writeLong(uint8_t *Buf) {
@@ -681,6 +707,60 @@ InputSection *MicroMipsR6Thunk::getTarge
   return dyn_cast<InputSection>(DR.Section);
 }
 
+void PPC32PltCallStub::writeTo(uint8_t *Buf) {
+  if (!Config->Pic) {
+    uint64_t VA = Destination.getGotPltVA();
+    write32(Buf + 0, 0x3d600000 | (VA + 0x8000) >> 16); // lis r11,ha
+    write32(Buf + 4, 0x816b0000 | (uint16_t)VA);        // lwz r11,l(r11)
+    write32(Buf + 8, 0x7d6903a6);                       // mtctr r11
+    write32(Buf + 12, 0x4e800420);                      // bctr
+    return;
+  }
+  uint32_t Offset;
+  if (Addend >= 0x8000) {
+    // The stub loads an address relative to r30 (.got2+Addend). Addend is
+    // almost always 0x8000. The address of .got2 is different in another object
+    // file, so a stub cannot be shared.
+    Offset = Destination.getGotPltVA() - (In.PPC32Got2->getParent()->getVA() +
+                                          File->PPC32Got2OutSecOff + Addend);
+  } else {
+    // The stub loads an address relative to _GLOBAL_OFFSET_TABLE_ (which is
+    // currently the address of .got).
+    Offset = Destination.getGotPltVA() - In.Got->getVA();
+  }
+  uint16_t HA = (Offset + 0x8000) >> 16, L = (uint16_t)Offset;
+  if (HA == 0) {
+    write32(Buf + 0, 0x817e0000 | L); // lwz r11,l(r30)
+    write32(Buf + 4, 0x7d6903a6);     // mtctr r11
+    write32(Buf + 8, 0x4e800420);     // bctr
+    write32(Buf + 12, 0x60000000);    // nop
+  } else {
+    write32(Buf + 0, 0x3d7e0000 | HA); // addis r11,r30,ha
+    write32(Buf + 4, 0x816b0000 | L);  // lwz r11,l(r11)
+    write32(Buf + 8, 0x7d6903a6);      // mtctr r11
+    write32(Buf + 12, 0x4e800420);     // bctr
+  }
+}
+
+void PPC32PltCallStub::addSymbols(ThunkSection &IS) {
+  std::string Buf;
+  raw_string_ostream OS(Buf);
+  OS << format_hex_no_prefix(Addend, 8);
+  if (!Config->Pic)
+    OS << ".plt_call32.";
+  else if (Addend >= 0x8000)
+    OS << ".got2.plt_pic32.";
+  else
+    OS << ".plt_pic32.";
+  OS << Destination.getName();
+  addSymbol(Saver.save(OS.str()), STT_FUNC, 0, IS);
+}
+
+bool PPC32PltCallStub::isCompatibleWith(const InputSection &IS,
+                                        const Relocation &Rel) const {
+  return !Config->Pic || (IS.File == File && Rel.Addend == Addend);
+}
+
 static void writePPCLoadAndBranch(uint8_t *Buf, int64_t Offset) {
   uint16_t OffHa = (Offset + 0x8000) >> 16;
   uint16_t OffLo = Offset & 0xffff;
@@ -814,6 +894,12 @@ static Thunk *addThunkMips(RelType Type,
   return make<MipsThunk>(S);
 }
 
+static Thunk *addThunkPPC32(const InputSection &IS, const Relocation &Rel, Symbol &S) {
+  assert((Rel.Type == R_PPC_REL24 || Rel.Type == R_PPC_PLTREL24) &&
+         "unexpected relocation type for thunk");
+  return make<PPC32PltCallStub>(IS, Rel, S);
+}
+
 static Thunk *addThunkPPC64(RelType Type, Symbol &S) {
   assert(Type == R_PPC64_REL24 && "unexpected relocation type for thunk");
   if (S.isInPlt())
@@ -825,18 +911,23 @@ static Thunk *addThunkPPC64(RelType Type
   return make<PPC64PDLongBranchThunk>(S);
 }
 
-Thunk *addThunk(RelType Type, Symbol &S) {
+Thunk *addThunk(const InputSection &IS, Relocation &Rel) {
+  Symbol &S = *Rel.Sym;
+
   if (Config->EMachine == EM_AARCH64)
-    return addThunkAArch64(Type, S);
+    return addThunkAArch64(Rel.Type, S);
 
   if (Config->EMachine == EM_ARM)
-    return addThunkArm(Type, S);
+    return addThunkArm(Rel.Type, S);
 
   if (Config->EMachine == EM_MIPS)
-    return addThunkMips(Type, S);
+    return addThunkMips(Rel.Type, S);
+
+  if (Config->EMachine == EM_PPC)
+    return addThunkPPC32(IS, Rel, S);
 
   if (Config->EMachine == EM_PPC64)
-    return addThunkPPC64(Type, S);
+    return addThunkPPC64(Rel.Type, S);
 
   llvm_unreachable("add Thunk only supported for ARM, Mips and PowerPC");
 }

Modified: lld/trunk/ELF/Thunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.h?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/ELF/Thunks.h (original)
+++ lld/trunk/ELF/Thunks.h Thu Jun  6 10:03:00 2019
@@ -46,9 +46,12 @@ public:
   // a branch and fall through to the first Symbol in the Target.
   virtual InputSection *getTargetInputSection() const { return nullptr; }
 
-  // To reuse a Thunk the caller as identified by the Type must be
-  // compatible with it.
-  virtual bool isCompatibleWith(RelType Type) const { return true; }
+  // To reuse a Thunk the InputSection and the relocation must be compatible
+  // with it.
+  virtual bool isCompatibleWith(const InputSection &,
+                                const Relocation &) const {
+    return true;
+  }
 
   Defined *getThunkTargetSym() const { return Syms[0]; }
 
@@ -61,8 +64,8 @@ public:
 };
 
 // For a Relocation to symbol S create a Thunk to be added to a synthetic
-// ThunkSection. At present there are implementations for ARM and Mips Thunks.
-Thunk *addThunk(RelType Type, Symbol &S);
+// ThunkSection.
+Thunk *addThunk(const InputSection &IS, Relocation &Rel);
 
 } // namespace elf
 } // namespace lld

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Jun  6 10:03:00 2019
@@ -212,6 +212,10 @@ void elf::addReservedSymbols() {
     // https://sourceware.org/ml/binutils/2004-12/msg00094.html
     if (Symtab->find("__gnu_local_gp"))
       ElfSym::MipsLocalGp = addAbsolute("__gnu_local_gp");
+  } else if (Config->EMachine == EM_PPC) {
+    // glibc *crt1.o has a undefined reference to _SDA_BASE_. Since we don't
+    // support Small Data Area, define it arbitrarily as 0.
+    addOptionalRegular("_SDA_BASE_", nullptr, 0, STV_HIDDEN);
   }
 
   // The Power Architecture 64-bit v2 ABI defines a TableOfContents (TOC) which
@@ -233,7 +237,7 @@ void elf::addReservedSymbols() {
     }
 
     uint64_t GotOff = 0;
-    if (Config->EMachine == EM_PPC || Config->EMachine == EM_PPC64)
+    if (Config->EMachine == EM_PPC64)
       GotOff = 0x8000;
 
     S->resolve(Defined{/*File=*/nullptr, GotSymName, STB_GLOBAL, STV_HIDDEN,
@@ -387,6 +391,11 @@ template <class ELFT> static void create
     Add(In.Got);
   }
 
+  if (Config->EMachine == EM_PPC) {
+    In.PPC32Got2 = make<PPC32Got2Section>();
+    Add(In.PPC32Got2);
+  }
+
   if (Config->EMachine == EM_PPC64) {
     In.PPC64LongBranchTarget = make<PPC64LongBranchTargetSection>();
     Add(In.PPC64LongBranchTarget);
@@ -1773,6 +1782,7 @@ template <class ELFT> void Writer<ELFT>:
   finalizeSynthetic(In.RelaPlt);
   finalizeSynthetic(In.Plt);
   finalizeSynthetic(In.Iplt);
+  finalizeSynthetic(In.PPC32Got2);
   finalizeSynthetic(In.EhFrameHdr);
   finalizeSynthetic(In.VerSym);
   finalizeSynthetic(In.VerNeed);

Modified: lld/trunk/test/ELF/basic-ppc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/basic-ppc.s?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/test/ELF/basic-ppc.s (original)
+++ lld/trunk/test/ELF/basic-ppc.s Thu Jun  6 10:03:00 2019
@@ -1,7 +1,7 @@
 # REQUIRES: ppc
-# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-freebsd %s -o %t
-# RUN: ld.lld --hash-style=sysv -discard-all -shared %t -o %t2
-# RUN: llvm-readobj --file-headers --sections --section-data -l %t2 | FileCheck %s
+# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-freebsd %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-readobj --file-headers --sections --section-data -l %t | FileCheck %s
 
 # exits with return code 42 on FreeBSD
 .text
@@ -23,20 +23,20 @@
 // CHECK-NEXT:     ABIVersion: 0
 // CHECK-NEXT:     Unused: (00 00 00 00 00 00 00)
 // CHECK-NEXT:   }
-// CHECK-NEXT:   Type: SharedObject (0x3)
+// CHECK-NEXT:   Type: Executable (0x2)
 // CHECK-NEXT:   Machine: EM_PPC (0x14)
 // CHECK-NEXT:   Version: 1
-// CHECK-NEXT:   Entry: 0x1000
+// CHECK-NEXT:   Entry: 0x10010000
 // CHECK-NEXT:   ProgramHeaderOffset: 0x34
-// CHECK-NEXT:   SectionHeaderOffset: 0x20AC
+// CHECK-NEXT:   SectionHeaderOffset: 0x11044
 // CHECK-NEXT:   Flags [ (0x0)
 // CHECK-NEXT:   ]
 // CHECK-NEXT:   HeaderSize: 52
 // CHECK-NEXT:   ProgramHeaderEntrySize: 32
-// CHECK-NEXT:   ProgramHeaderCount: 7
+// CHECK-NEXT:   ProgramHeaderCount: 4
 // CHECK-NEXT:   SectionHeaderEntrySize: 40
-// CHECK-NEXT:   SectionHeaderCount: 10
-// CHECK-NEXT:   StringTableSectionIndex: 8
+// CHECK-NEXT:   SectionHeaderCount: 6
+// CHECK-NEXT:   StringTableSectionIndex: 4
 // CHECK-NEXT: }
 // CHECK-NEXT: Sections [
 // CHECK-NEXT:   Section {
@@ -57,68 +57,14 @@
 // CHECK-NEXT:   }
 // CHECK-NEXT:   Section {
 // CHECK-NEXT:     Index: 1
-// CHECK-NEXT:     Name: .dynsym
-// CHECK-NEXT:     Type: SHT_DYNSYM (0xB)
-// CHECK-NEXT:     Flags [ (0x2)
-// CHECK-NEXT:       SHF_ALLOC (0x2)
-// CHECK-NEXT:     ]
-// CHECK-NEXT:     Address: 0x114
-// CHECK-NEXT:     Offset: 0x114
-// CHECK-NEXT:     Size: 16
-// CHECK-NEXT:     Link: 3
-// CHECK-NEXT:     Info: 1
-// CHECK-NEXT:     AddressAlignment: 4
-// CHECK-NEXT:     EntrySize: 16
-// CHECK-NEXT:     SectionData (
-// CHECK-NEXT:       0000: 00000000 00000000 00000000 00000000  |................|
-// CHECK-NEXT:     )
-// CHECK-NEXT:   }
-// CHECK-NEXT:   Section {
-// CHECK-NEXT:     Index: 2
-// CHECK-NEXT:     Name: .hash
-// CHECK-NEXT:     Type: SHT_HASH (0x5)
-// CHECK-NEXT:     Flags [ (0x2)
-// CHECK-NEXT:       SHF_ALLOC (0x2)
-// CHECK-NEXT:     ]
-// CHECK-NEXT:     Address: 0x124
-// CHECK-NEXT:     Offset: 0x124
-// CHECK-NEXT:     Size: 16
-// CHECK-NEXT:     Link: 1
-// CHECK-NEXT:     Info: 0
-// CHECK-NEXT:     AddressAlignment: 4
-// CHECK-NEXT:     EntrySize: 4
-// CHECK-NEXT:     SectionData (
-// CHECK-NEXT:       0000: 00000001 00000001 00000000 00000000  |................|
-// CHECK-NEXT:     )
-// CHECK-NEXT:   }
-// CHECK-NEXT:   Section {
-// CHECK-NEXT:     Index: 3
-// CHECK-NEXT:     Name: .dynstr
-// CHECK-NEXT:     Type: SHT_STRTAB (0x3)
-// CHECK-NEXT:     Flags [ (0x2)
-// CHECK-NEXT:       SHF_ALLOC (0x2)
-// CHECK-NEXT:     ]
-// CHECK-NEXT:     Address: 0x134
-// CHECK-NEXT:     Offset: 0x134
-// CHECK-NEXT:     Size: 1
-// CHECK-NEXT:     Link: 0
-// CHECK-NEXT:     Info: 0
-// CHECK-NEXT:     AddressAlignment: 1
-// CHECK-NEXT:     EntrySize: 0
-// CHECK-NEXT:     SectionData (
-// CHECK-NEXT:       0000: 00                                   |.|
-// CHECK-NEXT:     )
-// CHECK-NEXT:   }
-// CHECK-NEXT:   Section {
-// CHECK-NEXT:     Index: 4
 // CHECK-NEXT:     Name: .text
 // CHECK-NEXT:     Type: SHT_PROGBITS (0x1)
 // CHECK-NEXT:     Flags [ (0x6)
 // CHECK-NEXT:       SHF_ALLOC (0x2)
 // CHECK-NEXT:       SHF_EXECINSTR (0x4)
 // CHECK-NEXT:     ]
-// CHECK-NEXT:     Address: 0x1000
-// CHECK-NEXT:     Offset: 0x1000
+// CHECK-NEXT:     Address: 0x10010000
+// CHECK-NEXT:     Offset: 0x10000
 // CHECK-NEXT:     Size: 12
 // CHECK-NEXT:     Link: 0
 // CHECK-NEXT:     Info: 0
@@ -129,28 +75,7 @@
 // CHECK-NEXT:     )
 // CHECK-NEXT:   }
 // CHECK-NEXT:   Section {
-// CHECK-NEXT:     Index: 5
-// CHECK-NEXT:     Name: .dynamic
-// CHECK-NEXT:     Type: SHT_DYNAMIC (0x6)
-// CHECK-NEXT:     Flags [ (0x3)
-// CHECK-NEXT:       SHF_ALLOC (0x2)
-// CHECK-NEXT:       SHF_WRITE (0x1)
-// CHECK-NEXT:     ]
-// CHECK-NEXT:     Address: 0x2000
-// CHECK-NEXT:     Offset: 0x2000
-// CHECK-NEXT:     Size: 48
-// CHECK-NEXT:     Link: 3
-// CHECK-NEXT:     Info: 0
-// CHECK-NEXT:     AddressAlignment: 4
-// CHECK-NEXT:     EntrySize: 8
-// CHECK-NEXT:     SectionData (
-// CHECK-NEXT:       0000: 00000006 00000114 0000000B 00000010
-// CHECK-NEXT:       0010: 00000005 00000134 0000000A 00000001
-// CHECK-NEXT:       0020: 00000004 00000124 00000000 00000000
-// CHECK-NEXT:     )
-// CHECK-NEXT:   }
-// CHECK-NEXT:   Section {
-// CHECK-NEXT:     Index: 6
+// CHECK-NEXT:     Index: 2
 // CHECK-NEXT:     Name: .comment
 // CHECK-NEXT:     Type: SHT_PROGBITS (0x1)
 // CHECK-NEXT:     Flags [ (0x30)
@@ -158,70 +83,59 @@
 // CHECK-NEXT:       SHF_STRINGS (0x20)
 // CHECK-NEXT:     ]
 // CHECK-NEXT:     Address: 0x0
-// CHECK-NEXT:     Offset: 0x2030
+// CHECK-NEXT:     Offset: 0x11000
 // CHECK-NEXT:     Size: 8
 // CHECK-NEXT:     Link: 0
 // CHECK-NEXT:     Info: 0
 // CHECK-NEXT:     AddressAlignment: 1
 // CHECK-NEXT:     EntrySize: 1
-// CHECK-NEXT:     SectionData (
-// CHECK-NEXT:       0000: 4C4C4420 312E3000                    |LLD 1.0.|
-// CHECK-NEXT:     )
-// CHECK-NEXT:   }
+// CHECK:        }
 // CHECK-NEXT:   Section {
-// CHECK-NEXT:     Index: 7
+// CHECK-NEXT:     Index: 3
 // CHECK-NEXT:     Name: .symtab
 // CHECK-NEXT:     Type: SHT_SYMTAB (0x2)
 // CHECK-NEXT:     Flags [ (0x0)
 // CHECK-NEXT:     ]
 // CHECK-NEXT:     Address: 0x0
-// CHECK-NEXT:     Offset: 0x2038
-// CHECK-NEXT:     Size: 32
-// CHECK-NEXT:     Link: 9
-// CHECK-NEXT:     Info: 2
+// CHECK-NEXT:     Offset: 0x11008
+// CHECK-NEXT:     Size: 16
+// CHECK-NEXT:     Link: 5
+// CHECK-NEXT:     Info: 1
 // CHECK-NEXT:     AddressAlignment: 4
 // CHECK-NEXT:     EntrySize: 16
 // CHECK-NEXT:     SectionData (
 // CHECK-NEXT:       0000: 00000000 00000000 00000000 00000000  |................|
-// CHECK-NEXT:       0010: 00000001 00002000 00000000 00020005  |...... .........|
 // CHECK-NEXT:     )
 // CHECK-NEXT:   }
 // CHECK-NEXT:   Section {
-// CHECK-NEXT:     Index: 8
+// CHECK-NEXT:     Index: 4
 // CHECK-NEXT:     Name: .shstrtab
 // CHECK-NEXT:     Type: SHT_STRTAB (0x3)
 // CHECK-NEXT:     Flags [ (0x0)
 // CHECK-NEXT:     ]
 // CHECK-NEXT:     Address: 0x0
-// CHECK-NEXT:     Offset: 0x2058
-// CHECK-NEXT:     Size: 73
+// CHECK-NEXT:     Offset: 0x11018
+// CHECK-NEXT:     Size: 42
 // CHECK-NEXT:     Link: 0
 // CHECK-NEXT:     Info: 0
 // CHECK-NEXT:     AddressAlignment: 1
 // CHECK-NEXT:     EntrySize: 0
-// CHECK-NEXT:     SectionData (
-// CHECK-NEXT:       0000: 002E6479 6E73796D 002E6861 7368002E  |..dynsym..hash..|
-// CHECK-NEXT:       0010: 64796E73 7472002E 74657874 002E6479  |dynstr..text..dy|
-// CHECK-NEXT:       0020: 6E616D69 63002E63 6F6D6D65 6E74002E  |namic..comment..|
-// CHECK-NEXT:       0030: 73796D74 6162002E 73687374 72746162  |symtab..shstrtab|
-// CHECK-NEXT:       0040: 002E7374 72746162 00                 |..strtab.|
-// CHECK-NEXT:     )
-// CHECK-NEXT:   }
+// CHECK:        }
 // CHECK-NEXT:   Section {
-// CHECK-NEXT:     Index: 9
+// CHECK-NEXT:     Index: 5
 // CHECK-NEXT:     Name: .strtab
 // CHECK-NEXT:     Type: SHT_STRTAB (0x3)
 // CHECK-NEXT:     Flags [ (0x0)
 // CHECK-NEXT:     ]
 // CHECK-NEXT:     Address: 0x0
-// CHECK-NEXT:     Offset: 0x20A1
-// CHECK-NEXT:     Size: 10
+// CHECK-NEXT:     Offset: 0x11042
+// CHECK-NEXT:     Size: 1
 // CHECK-NEXT:     Link: 0
 // CHECK-NEXT:     Info: 0
 // CHECK-NEXT:     AddressAlignment: 1
 // CHECK-NEXT:     EntrySize: 0
 // CHECK-NEXT:     SectionData (
-// CHECK-NEXT:       0000: 005F4459 4E414D49 4300               |._DYNAMIC.|
+// CHECK-NEXT:       0000: 00
 // CHECK-NEXT:     )
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
@@ -229,10 +143,10 @@
 // CHECK-NEXT:   ProgramHeader {
 // CHECK-NEXT:     Type: PT_PHDR (0x6)
 // CHECK-NEXT:     Offset: 0x34
-// CHECK-NEXT:     VirtualAddress: 0x34
-// CHECK-NEXT:     PhysicalAddress: 0x34
-// CHECK-NEXT:     FileSize: 224
-// CHECK-NEXT:     MemSize: 224
+// CHECK-NEXT:     VirtualAddress: 0x10000034
+// CHECK-NEXT:     PhysicalAddress: 0x10000034
+// CHECK-NEXT:     FileSize: 128
+// CHECK-NEXT:     MemSize: 128
 // CHECK-NEXT:     Flags [ (0x4)
 // CHECK-NEXT:       PF_R (0x4)
 // CHECK-NEXT:     ]
@@ -241,65 +155,27 @@
 // CHECK-NEXT:   ProgramHeader {
 // CHECK-NEXT:     Type: PT_LOAD (0x1)
 // CHECK-NEXT:     Offset: 0x0
-// CHECK-NEXT:     VirtualAddress: 0x0
-// CHECK-NEXT:     PhysicalAddress: 0x0
-// CHECK-NEXT:     FileSize: 309
-// CHECK-NEXT:     MemSize: 309
+// CHECK-NEXT:     VirtualAddress: 0x10000000
+// CHECK-NEXT:     PhysicalAddress: 0x10000000
+// CHECK-NEXT:     FileSize: 180
+// CHECK-NEXT:     MemSize: 180
 // CHECK-NEXT:     Flags [ (0x4)
 // CHECK-NEXT:       PF_R (0x4)
 // CHECK-NEXT:     ]
-// CHECK-NEXT:     Alignment: 4096
+// CHECK-NEXT:     Alignment: 65536
 // CHECK-NEXT:   }
 // CHECK-NEXT:   ProgramHeader {
 // CHECK-NEXT:     Type: PT_LOAD (0x1)
 // CHECK-NEXT:     Offset: 0x1000
-// CHECK-NEXT:     VirtualAddress: 0x1000
-// CHECK-NEXT:     PhysicalAddress: 0x1000
-// CHECK-NEXT:     FileSize: 12
-// CHECK-NEXT:     MemSize: 12
+// CHECK-NEXT:     VirtualAddress: 0x10010000
+// CHECK-NEXT:     PhysicalAddress: 0x10010000
+// CHECK-NEXT:     FileSize: 4096
+// CHECK-NEXT:     MemSize: 4096
 // CHECK-NEXT:     Flags [ (0x5)
 // CHECK-NEXT:       PF_R (0x4)
 // CHECK-NEXT:       PF_X (0x1)
 // CHECK-NEXT:     ]
-// CHECK-NEXT:     Alignment: 4096
-// CHECK-NEXT:   }
-// CHECK-NEXT:   ProgramHeader {
-// CHECK-NEXT:     Type: PT_LOAD (0x1)
-// CHECK-NEXT:     Offset: 0x2000
-// CHECK-NEXT:     VirtualAddress: 0x2000
-// CHECK-NEXT:     PhysicalAddress: 0x2000
-// CHECK-NEXT:     FileSize: 48
-// CHECK-NEXT:     MemSize: 48
-// CHECK-NEXT:     Flags [ (0x6)
-// CHECK-NEXT:       PF_R (0x4)
-// CHECK-NEXT:       PF_W (0x2)
-// CHECK-NEXT:     ]
-// CHECK-NEXT:     Alignment: 4096
-// CHECK-NEXT:   }
-// CHECK-NEXT:   ProgramHeader {
-// CHECK-NEXT:     Type: PT_DYNAMIC (0x2)
-// CHECK-NEXT:     Offset: 0x2000
-// CHECK-NEXT:     VirtualAddress: 0x2000
-// CHECK-NEXT:     PhysicalAddress: 0x2000
-// CHECK-NEXT:     FileSize: 48
-// CHECK-NEXT:     MemSize: 48
-// CHECK-NEXT:     Flags [ (0x6)
-// CHECK-NEXT:       PF_R (0x4)
-// CHECK-NEXT:       PF_W (0x2)
-// CHECK-NEXT:     ]
-// CHECK-NEXT:     Alignment: 4
-// CHECK-NEXT:   }
-// CHECK-NEXT:   ProgramHeader {
-// CHECK-NEXT:     Type: PT_GNU_RELRO (0x6474E552)
-// CHECK-NEXT:     Offset: 0x2000
-// CHECK-NEXT:     VirtualAddress: 0x2000
-// CHECK-NEXT:     PhysicalAddress: 0x2000
-// CHECK-NEXT:     FileSize: 48
-// CHECK-NEXT:     MemSize: 4096
-// CHECK-NEXT:     Flags [ (0x4)
-// CHECK-NEXT:       PF_R (0x4)
-// CHECK-NEXT:     ]
-// CHECK-NEXT:     Alignment: 1
+// CHECK-NEXT:     Alignment: 65536
 // CHECK-NEXT:   }
 // CHECK-NEXT:   ProgramHeader {
 // CHECK-NEXT:     Type: PT_GNU_STACK (0x6474E551)

Modified: lld/trunk/test/ELF/ppc-rela.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc-rela.s?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/test/ELF/ppc-rela.s (original)
+++ lld/trunk/test/ELF/ppc-rela.s Thu Jun  6 10:03:00 2019
@@ -7,5 +7,5 @@
   .long foo
 
 // CHECK:      Section ({{.*}}) .rela.dyn {
-// CHECK-NEXT:   0x2000 R_PPC_ADDR32 foo 0x0
+// CHECK-NEXT:   0x20000 R_PPC_ADDR32 foo 0x0
 // CHECK-NEXT: }

Removed: lld/trunk/test/ELF/ppc-relocs.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc-relocs.s?rev=362720&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc-relocs.s (original)
+++ lld/trunk/test/ELF/ppc-relocs.s (removed)
@@ -1,106 +0,0 @@
-# REQUIRES: ppc
-# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-freebsd %s -o %t.o
-# RUN: ld.lld %t.o -o %t
-# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
-# RUN: llvm-objdump -s --no-show-raw-insn %t | FileCheck --check-prefix=HEX %s
-
-.section .R_PPC_ADDR16_HA,"ax", at progbits
-.globl _start
-_start:
-  lis 4, msg at ha
-msg:
-  .string "foo"
-  len = . - msg
-
-# CHECK: Disassembly of section .R_PPC_ADDR16_HA:
-# CHECK-EMPTY:
-# CHECK: _start:
-# CHECK:    11000:       lis 4, 1
-# CHECK: msg:
-# CHECK:    11004:       oris 15, 19, 28416
-
-.section .R_PPC_ADDR16_HI,"ax", at progbits
-.globl _starti
-_starti:
-  lis 4,msgi at h
-msgi:
-  .string "foo"
-  leni = . - msgi
-
-# CHECK: Disassembly of section .R_PPC_ADDR16_HI:
-# CHECK-EMPTY:
-# CHECK: _starti:
-# CHECK:    11008:       lis 4, 1
-# CHECK: msgi:
-# CHECK:    1100c:       oris 15, 19, 28416
-
-.section .R_PPC_ADDR16_LO,"ax", at progbits
-  addi 4, 4, msg at l
-mystr:
-  .asciz "blah"
-  len = . - mystr
-
-# CHECK: Disassembly of section .R_PPC_ADDR16_LO:
-# CHECK-EMPTY:
-# CHECK: .R_PPC_ADDR16_LO:
-# CHECK:    11010:       addi 4, 4, 4100
-# CHECK: mystr:
-# CHECK:    11014:       ori 12, 19, 24936
-
-.align  2
-.section .R_PPC_REL24,"ax", at progbits
-.globl .FR_PPC_REL24
-.FR_PPC_REL24:
-  b .Lfoox
-.section .R_PPC_REL24_2,"ax", at progbits
-.Lfoox:
-
-# CHECK: Disassembly of section .R_PPC_REL24:
-# CHECK-EMPTY:
-# CHECK: .FR_PPC_REL24:
-# CHECK:    1101c:       b .+4
-
-.section .R_PPC_REL14,"ax", at progbits
-.globl .FR_PPC_REL14
-.FR_PPC_REL14:
-  beq .Lfooy
-.section .R_PPC_REL14_2,"ax", at progbits
-.Lfooy:
-
-# CHECK: Disassembly of section .R_PPC_REL14:
-# CHECK-EMPTY:
-# CHECK: .FR_PPC_REL14:
-# CHECK:    11020:       bt 2, .+4
-
-.section .R_PPC_REL32,"ax", at progbits
-.globl .FR_PPC_REL32
-.FR_PPC_REL32:
-  .long .Lfoox3 - .
-.section .R_PPC_REL32_2,"ax", at progbits
-.Lfoox3:
-
-# HEX:     .R_PPC_REL32:
-# HEX-NEXT: 11024 00000004
-
-.section .R_PPC_ADDR32,"ax", at progbits
-.globl .FR_PPC_ADDR32
-.FR_PPC_ADDR32:
-  .long .Lfoox2
-.section .R_PPC_ADDR32_2,"ax", at progbits
-.Lfoox2:
-
-# HEX:     .R_PPC_ADDR32:
-# HEX-NEXT: 11028 0001102c
-
-.align  2
-.section .R_PPC_PLTREL24,"ax", at progbits
-.globl .R_PPC_PLTREL24
-.FR_PPC_PLTREL24:
-  b .Lfoox4 at PLT
-.section .R_PPC_PLTREL24_2,"ax", at progbits
-.Lfoox4:
-
-# CHECK: Disassembly of section .R_PPC_PLTREL24:
-# CHECK-EMPTY:
-# CHECK: .R_PPC_PLTREL24:
-# CHECK:    1102c:       b .+4

Added: lld/trunk/test/ELF/ppc32-abs-pic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc32-abs-pic.s?rev=362721&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc32-abs-pic.s (added)
+++ lld/trunk/test/ELF/ppc32-abs-pic.s Thu Jun  6 10:03:00 2019
@@ -0,0 +1,23 @@
+# REQUIRES: ppc
+# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
+# RUN: ld.lld -shared %t.o -o %t.so
+# RUN: llvm-nm %t.so | FileCheck --check-prefix=NM %s
+# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=RELOC %s
+
+## R_PPC_ADDR32 is an absolute relocation type.
+## In PIC mode, it creates a relative relocation if the symbol is non-preemptable.
+
+# NM: 00020004 d b
+
+# RELOC:      .rela.dyn {
+# RELOC-NEXT:   0x20004 R_PPC_RELATIVE - 0x20004
+# RELOC-NEXT:   0x20000 R_PPC_ADDR32 a 0
+# RELOC-NEXT: }
+
+.globl a, b
+.hidden b
+
+.data
+.long a
+b:
+.long b

Added: lld/trunk/test/ELF/ppc32-call-stub-nopic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc32-call-stub-nopic.s?rev=362721&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc32-call-stub-nopic.s (added)
+++ lld/trunk/test/ELF/ppc32-call-stub-nopic.s Thu Jun  6 10:03:00 2019
@@ -0,0 +1,81 @@
+# REQUIRES: ppc
+# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
+# RUN: echo '.globl f, g, h; f: g: h:' | llvm-mc -filetype=obj -triple=powerpc - -o %t1.o
+# RUN: ld.lld -shared %t1.o -soname t1.so -o %t1.so
+
+## Check we can create PLT entries for -fno-PIE executable.
+# RUN: ld.lld %t.o %t1.so -o %t
+# RUN: llvm-readobj -r -d %t | FileCheck --check-prefix=RELOC %s
+# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SEC %s
+# RUN: llvm-readelf -x .plt %t | FileCheck --check-prefix=HEX %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
+
+# RELOC:      .rela.plt {
+# RELOC-NEXT:   0x10030000 R_PPC_JMP_SLOT f 0x0
+# RELOC-NEXT:   0x10030004 R_PPC_JMP_SLOT g 0x0
+# RELOC-NEXT: }
+
+# SEC:   .got PROGBITS 10020070
+# RELOC: PPC_GOT 0x10020070
+
+## .got2+0x8000-0x10004 = 0x30000+0x8000-0x10004 = 65536*2+32764
+# CHECK-LABEL: _start:
+# CHECK-NEXT:    bl .+16
+# CHECK-NEXT:    bl .+12
+# CHECK-NEXT:    bl .+24
+# CHECK-NEXT:    bl .+20
+# CHECK-EMPTY:
+
+## -fno-PIC call stubs of f and g.
+## .plt[0] = 0x10030000 = 65536*4099+0
+## .plt[1] = 0x10030004 = 65536*4099+4
+# CHECK-NEXT:  00000000.plt_call32.f:
+# CHECK-NEXT:    lis 11, 4099
+# CHECK-NEXT:    lwz 11, 0(11)
+# CHECK-NEXT:    mtctr 11
+# CHECK-NEXT:    bctr
+# CHECK-EMPTY:
+# CHECK-NEXT:  00000000.plt_call32.g:
+# CHECK-NEXT:    lis 11, 4099
+# CHECK-NEXT:    lwz 11, 4(11)
+# CHECK-NEXT:    mtctr 11
+# CHECK-NEXT:    bctr
+# CHECK-EMPTY:
+
+## In Secure PLT ABI, .plt stores function pointers to first instructions of .glink
+# HEX: 0x10030000 10010040 10010044
+
+## These instructions are referenced by .plt entries.
+# CHECK: 0000000010010040 .glink:
+# CHECK-NEXT: b .+8
+# CHECK-NEXT: b .+4
+
+## PLTresolve
+## Operands of lis & lwz: .got+4 = 0x10020070+4 = 65536*4098+116
+## Operands of addis & addi: -.glink = -0x10010040 = 65536*-4097-48
+# CHECK-NEXT: lis 12, 4098
+# CHECK-NEXT: addis 11, 11, -4097
+# CHECK-NEXT: lwz 0, 116(12)
+# CHECK-NEXT: addi 11, 11, -64
+
+# CHECK-NEXT: mtctr 0
+# CHECK-NEXT: add 0, 11, 11
+# CHECK-NEXT: lwz 12, 120(12)
+# CHECK-NEXT: add 11, 0, 11
+# CHECK-NEXT: bctr
+
+## glibc crti.o references _GLOBAL_OFFSET_TABLE_.
+.section .init
+  bcl 20, 31, .+4
+.L:
+  mflr 30
+  addis 30, 30, _GLOBAL_OFFSET_TABLE_-.L at ha
+  addi 30, 30, _GLOBAL_OFFSET_TABLE_-.L at l
+
+.text
+.globl _start
+_start:
+  bl f
+  bl f
+  bl g
+  bl g

Added: lld/trunk/test/ELF/ppc32-call-stub-pic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc32-call-stub-pic.s?rev=362721&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc32-call-stub-pic.s (added)
+++ lld/trunk/test/ELF/ppc32-call-stub-pic.s Thu Jun  6 10:03:00 2019
@@ -0,0 +1,151 @@
+# REQUIRES: ppc
+# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
+# RUN: echo '.globl f, g, h; f: g: h:' | llvm-mc -filetype=obj -triple=powerpc - -o %t1.o
+# RUN: ld.lld -shared %t1.o -soname t1.so -o %t1.so
+# RUN: echo 'bl f+0x8000 at plt' | llvm-mc -filetype=obj -triple=powerpc - -o %t2.o
+
+## Check we can create PLT entries for -fPIE or -fpie executable.
+# RUN: ld.lld -pie %t.o %t1.so %t2.o -o %t
+# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
+# RUN: llvm-readobj -d %t | FileCheck --check-prefix=DYN %s
+# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SEC %s
+# RUN: llvm-readelf -x .plt %t | FileCheck --check-prefix=HEX %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=CHECK,PIE %s
+
+## Check we can create PLT entries for -fPIC or -fpic DSO.
+# RUN: ld.lld -shared %t.o %t1.so %t2.o -o %t
+# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=CHECK,SHARED %s
+
+# RELOC:      .rela.dyn {
+# RELOC-NEXT:   R_PPC_ADDR32 f 0x0
+# RELOC-NEXT:   R_PPC_ADDR32 g 0x0
+# RELOC-NEXT:   R_PPC_ADDR32 h 0x0
+# RELOC-NEXT: }
+# RELOC-NEXT: .rela.plt {
+# RELOC-NEXT:   R_PPC_JMP_SLOT f 0x0
+# RELOC-NEXT:   R_PPC_JMP_SLOT g 0x0
+# RELOC-NEXT:   R_PPC_JMP_SLOT h 0x0
+# RELOC-NEXT: }
+
+# SEC: .got PROGBITS 00020088
+# DYN: PPC_GOT 0x20088
+
+## .got2+0x8000-0x10004 = 0x30000+0x8000-0x10004 = 65536*2+32764
+# CHECK-LABEL: _start:
+# CHECK-NEXT:    bcl 20, 31, .+4
+# CHECK-NEXT:  10004: mflr 30
+# CHECK-NEXT:    addis 30, 30, 2
+# CHECK-NEXT:    addi 30, 30, 32764
+
+## Two bl 00008000.got2.plt_pic32.f
+# CHECK-NEXT:    bl .+40
+# CHECK-NEXT:    bl .+36
+## Two bl 00008000.got2.plt_pic32.g
+# CHECK-NEXT:    bl .+48
+# CHECK-NEXT:    bl .+44
+## Two bl 00008000.got2.plt_pic32.h
+# CHECK-NEXT:    bl .+56
+# CHECK-NEXT:    bl .+52
+# CHECK-NEXT:    addis 30, 30, {{.*}}
+# CHECK-NEXT:    addi 30, 30, {{.*}}
+## bl 00008000.plt_pic32.f
+# CHECK-NEXT:    bl .+56
+## bl 00008000.plt_pic32.f
+# CHECK-NEXT:    bl .+68
+# CHECK-EMPTY:
+
+## -fPIC call stubs of f and g.
+# CHECK-NEXT:  00008000.got2.plt_pic32.f:
+# CHECK-NEXT:    lwz 11, 32760(30)
+# CHECK-NEXT:    mtctr 11
+# CHECK-NEXT:    bctr
+# CHECK-NEXT:    nop
+# CHECK-EMPTY:
+# CHECK-NEXT:  00008000.got2.plt_pic32.g:
+# CHECK-NEXT:    lwz 11, 32764(30)
+# CHECK-NEXT:    mtctr 11
+# CHECK-NEXT:    bctr
+# CHECK-NEXT:    nop
+# CHECK-EMPTY:
+
+## The -fPIC call stub of h needs two instructions addis+lwz to represent the offset 65536*1-32768.
+# CHECK-NEXT:  00008000.got2.plt_pic32.h:
+# CHECK-NEXT:    addis 11, 30, 1
+# CHECK-NEXT:    lwz 11, -32768(11)
+# CHECK-NEXT:    mtctr 11
+# CHECK-NEXT:    bctr
+# CHECK-EMPTY:
+
+## -fpic call stub of f.
+# CHECK-NEXT:  00000000.plt_pic32.f:
+# CHECK-NEXT:    addis 11, 30, 2
+# PIE-NEXT:      lwz 11, -144(11)
+# SHARED-NEXT:   lwz 11, -136(11)
+# CHECK-NEXT:    mtctr 11
+# CHECK-NEXT:    bctr
+# CHECK-EMPTY:
+
+## Another -fPIC call stub of f from another object file %t2.o
+## .got2 may have different addresses in different object files,
+## so the call stub cannot be shared.
+# CHECK-NEXT:  00008000.got2.plt_pic32.f:
+
+## In Secure PLT ABI, .plt stores function pointers to first instructions of .glink
+# HEX: 0x0003fff8 00010090 00010094 00010098
+
+## These instructions are referenced by .plt entries.
+# CHECK: 0000000000010090 .glink:
+# CHECK-NEXT: b .+12
+# CHECK-NEXT: b .+8
+# CHECK-NEXT: b .+4
+
+## PLTresolve
+## Operand of addi: 0x100a8-.glink = 24
+# CHECK-NEXT: addis 11, 11, 0
+# CHECK-NEXT: mflr 0
+# CHECK-NEXT: bcl 20, 31, .+4
+# CHECK-NEXT: 100a8: addi 11, 11, 24
+
+# CHECK-NEXT: mflr 12
+# CHECK-NEXT: mtlr 0
+# CHECK-NEXT: subf 11, 12, 11
+
+## Operand of lwz in -pie mode: &.got[1] - 0x100a8 = 0x20088+4 - 0x100a8 = 65536*1-28
+# CHECK-NEXT: addis 12, 12, 1
+# PIE-NEXT:   lwz 0, -28(12)
+# SHARED-NEXT: lwz 0, -36(12)
+
+# PIE-NEXT:   lwz 12, -24(12)
+# SHARED-NEXT: lwz 12, -32(12)
+# CHECK-NEXT: mtctr 0
+# CHECK-NEXT: add 0, 11, 11
+# CHECK-NEXT: add 11, 0, 11
+# CHECK-NEXT: bctr
+
+.section .got2,"aw"
+.space 65516
+.long f
+.long g
+.long h
+
+.text
+.globl _start
+_start:
+  bcl 20,31,.L
+.L:
+  mflr 30
+  addis 30, 30, .got2+0x8000-.L at ha
+  addi 30, 30, .got2+0x8000-.L at l
+  bl f+0x8000 at plt
+  bl f+0x8000 at plt
+  bl g+0x8000 at plt
+  bl g+0x8000 at plt
+  bl h+0x8000 at plt
+  bl h+0x8000 at plt
+
+## An addend of 0 indicates r30 is stored in _GLOBAL_OFFSET_TABLE_.
+## The existing thunk is incompatible, thus it cannot be reused.
+  addis 30, 30, _GLOBAL_OFFSET_TABLE_-.L at ha
+  addi 30, 30, _GLOBAL_OFFSET_TABLE_-.L at l
+  bl f at plt

Added: lld/trunk/test/ELF/ppc32-gnu-ifunc-nonpreemptable.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc32-gnu-ifunc-nonpreemptable.s?rev=362721&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc32-gnu-ifunc-nonpreemptable.s (added)
+++ lld/trunk/test/ELF/ppc32-gnu-ifunc-nonpreemptable.s Thu Jun  6 10:03:00 2019
@@ -0,0 +1,45 @@
+# REQUIRES: ppc
+# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
+# RUN: llvm-readelf -s %t | FileCheck --check-prefix=SYM %s
+# RUN: llvm-readelf -x .got2 %t | FileCheck --check-prefix=HEX %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
+
+# RELOC:      .rela.plt {
+# RELOC-NEXT:   0x10020004 R_PPC_IRELATIVE - 0x10010000
+# RELOC-NEXT: }
+
+# SYM: 10010020 0 FUNC GLOBAL DEFAULT {{.*}} func
+# HEX: 0x10020000 10010020
+
+.section .got2,"aw"
+.long func
+
+# CHECK:      func_resolver:
+# CHECK-NEXT: 10010000: blr
+# CHECK:      _start:
+# CHECK-NEXT:   bl .+12
+# CHECK-NEXT:   lis 9, 4097
+# CHECK-NEXT:   addi 9, 9, 32
+# CHECK-EMPTY:
+# CHECK-NEXT: 00000000.plt_call32.func:
+## 10020004 = 65536*4098+4
+# CHECK-NEXT:   lis 11, 4098
+# CHECK-NEXT:   lwz 11, 4(11)
+
+.text
+.globl func
+.type func, @gnu_indirect_function
+func:
+.globl func_resolver
+.type func_resolver, @function
+func_resolver:
+  blr
+
+.globl _start
+_start:
+  bl func
+
+  lis 9, func at ha
+  la 9, func at l(9)

Added: lld/trunk/test/ELF/ppc32-gnu-ifunc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc32-gnu-ifunc.s?rev=362721&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc32-gnu-ifunc.s (added)
+++ lld/trunk/test/ELF/ppc32-gnu-ifunc.s Thu Jun  6 10:03:00 2019
@@ -0,0 +1,41 @@
+# REQUIRES: ppc
+# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
+# RUN: llvm-readelf -S -s %t | FileCheck --check-prefixes=SEC,SYM %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
+
+# RELOC:      .rela.plt {
+# RELOC-NEXT:   0x10020000 R_PPC_IRELATIVE - 0x10010000
+# RELOC-NEXT: }
+
+# SEC: .rela.plt RELA 100000d4 0000d4 00000c
+# SYM: 10010000 0 FUNC GLOBAL DEFAULT {{.*}} func
+
+# CHECK:      func_resolver:
+# CHECK-NEXT:   10010000:
+# CHECK:      _start:
+# CHECK-NEXT:   bl .+20
+## .rela.plt = 0x100000d4 = 65536*4096+212
+## end(.rela.plt) = 0x100000d4+0xc = 65536*4096+224
+# CHECK-NEXT:   lis 9, 4096
+# CHECK-NEXT:   lis 8, 4096
+# CHECK-NEXT:   addi 9, 9, 212
+# CHECK-NEXT:   addi 8, 8, 224
+
+.globl func
+.type func, @gnu_indirect_function
+func:
+.globl func_resolver
+.type func_resolver, @function
+func_resolver:
+  blr
+
+.globl _start
+_start:
+  bl func
+
+  lis 9, __rela_iplt_start at ha
+  lis 8, __rela_iplt_end at ha
+  la 9, __rela_iplt_start at l(9)
+  la 8, __rela_iplt_end at l(8)

Added: lld/trunk/test/ELF/ppc32-local-branch.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc32-local-branch.s?rev=362721&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc32-local-branch.s (added)
+++ lld/trunk/test/ELF/ppc32-local-branch.s Thu Jun  6 10:03:00 2019
@@ -0,0 +1,21 @@
+# REQUIRES: ppc
+# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
+# RUN: echo '.globl foo; foo: blr' | llvm-mc -filetype=obj -triple=powerpc - -o %t1.o
+# RUN: ld.lld %t.o %t1.o -o %t
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
+
+## R_PPC_REL24 and R_PPC_PLTREL24 are converted to PC relative relocations if the
+## symbol is non-preemptable. The addend of R_PPC_PLTREL24 should be ignored.
+
+# CHECK:      _start:
+# CHECK-NEXT:   b .+12
+# CHECK-NEXT:   b .+8
+# CHECK-NEXT:   b .+4
+# CHECK-EMPTY:
+# CHECK-NEXT: foo:
+
+.globl _start
+_start:
+  b foo  # R_PPC_REL24
+  b foo at plt  # R_PPC_PLTREL24
+  b foo+32768 at plt  #_PPC_PLTREL24 with addend

Added: lld/trunk/test/ELF/ppc32-reloc-addr.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc32-reloc-addr.s?rev=362721&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc32-reloc-addr.s (added)
+++ lld/trunk/test/ELF/ppc32-reloc-addr.s Thu Jun  6 10:03:00 2019
@@ -0,0 +1,34 @@
+# REQUIRES: ppc
+# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
+# RUN: ld.lld --noinhibit-exec %t.o --defsym=a=0x1234 --defsym=b=0xbcdef -o %t 2>&1 | \
+# RUN:   FileCheck --check-prefix=WARN %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
+# RUN: llvm-objdump -s --no-show-raw-insn %t | FileCheck --check-prefix=HEX %s
+
+.section .R_PPC_ADDR16,"ax", at progbits
+  lis 4, a
+  lis 4, b
+# CHECK-LABEL: section .R_PPC_ADDR16:
+# CHECK: lis 4, 4660
+# WARN: warning: {{.*}}.o:(.R_PPC_ADDR16+0x6): relocation R_PPC_ADDR16 out of range: 773615 is not in [-32768, 32767]
+
+.section .R_PPC_ADDR16_HA,"ax", at progbits
+  lis 4, a at ha
+# CHECK-LABEL: section .R_PPC_ADDR16_HA:
+# CHECK: lis 4, 0
+
+.section .R_PPC_ADDR16_HI,"ax", at progbits
+  lis 4, a at h
+# CHECK-LABEL: section .R_PPC_ADDR16_HI:
+# CHECK: lis 4, 0
+
+.section .R_PPC_ADDR16_LO,"ax", at progbits
+  addi 4, 4, a at l
+# CHECK-LABEL: section .R_PPC_ADDR16_LO:
+# CHECK: addi 4, 4, 4660
+
+.section .R_PPC_ADDR32,"a", at progbits
+  .long a
+  .long b
+# HEX-LABEL: section .R_PPC_ADDR32:
+# HEX-NEXT: 100000b4 00001234 000bcdef

Added: lld/trunk/test/ELF/ppc32-reloc-got.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc32-reloc-got.s?rev=362721&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc32-reloc-got.s (added)
+++ lld/trunk/test/ELF/ppc32-reloc-got.s Thu Jun  6 10:03:00 2019
@@ -0,0 +1,36 @@
+# REQUIRES: ppc
+# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
+# RUN: echo '.globl b; b:' | llvm-mc -filetype=obj -triple=powerpc - -o %t1.o
+# RUN: ld.lld -shared %t1.o -o %t1.so
+
+# RUN: ld.lld %t.o %t1.so -o %t
+# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
+# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
+# RUN: llvm-readobj -x .got %t | FileCheck --check-prefix=HEX %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
+
+## Check we can handle R_PPC_GOT16, which may be generated by -fpic code.
+
+# SEC: .got PROGBITS 00020068 020068 000014
+
+# RELOC:      .rela.dyn {
+# RELOC-NEXT:   0x10020078 R_PPC_GLOB_DAT b 0x0
+# RELOC-NEXT: }
+
+# NM: 10030000 d a
+
+## The GOT slot of a can be filled at link time.
+# HEX: section '.got':
+# HEX: 0x10020068 {{[0-9a-f]+}} 00000000 00000000 10030000
+
+## a: &.got[3] - _GLOBAL_OFFSET_TABLE_ = 12
+## b: &.got[4] - _GLOBAL_OFFSET_TABLE_ = 16
+# CHECK: lwz 3, 12(30)
+# CHECK: lwz 4, 16(30)
+
+lwz 3,a at got(30)
+lwz 4,b at got(30)
+
+.data
+a:
+.long _GLOBAL_OFFSET_TABLE_

Added: lld/trunk/test/ELF/ppc32-reloc-rel.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc32-reloc-rel.s?rev=362721&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc32-reloc-rel.s (added)
+++ lld/trunk/test/ELF/ppc32-reloc-rel.s Thu Jun  6 10:03:00 2019
@@ -0,0 +1,34 @@
+# REQUIRES: ppc
+# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
+
+.section .R_PPC_REL14,"ax", at progbits
+  beq 1f
+1:
+# CHECK-LABEL: section .R_PPC_REL14:
+# CHECK: bt 2, .+4
+
+.section .R_PPC_REL24,"ax", at progbits
+  b 1f
+1:
+# CHECK-LABEL: section .R_PPC_REL24:
+# CHECK: b .+4
+
+.section .R_PPC_REL32,"ax", at progbits
+  .long 1f - .
+1:
+# HEX-LABEL: section .R_PPC_REL32:
+# HEX-NEXT: 10010008 00000004
+
+.section .R_PPC_PLTREL24,"ax", at progbits
+  b 1f at PLT+32768
+1:
+# CHECK-LABEL: section .R_PPC_PLTREL24:
+# CHECK: b .+4
+
+.section .R_PPC_LOCAL24PC,"ax", at progbits
+  b 1f at local
+1:
+# CHECK-LABEL: section .R_PPC_LOCAL24PC:
+# CHECK: b .+4

Added: lld/trunk/test/ELF/ppc32-weak-undef-call.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc32-weak-undef-call.s?rev=362721&view=auto
==============================================================================
--- lld/trunk/test/ELF/ppc32-weak-undef-call.s (added)
+++ lld/trunk/test/ELF/ppc32-weak-undef-call.s Thu Jun  6 10:03:00 2019
@@ -0,0 +1,19 @@
+# REQUIRES: ppc
+# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=EXE %s
+# RUN: ld.lld -pie %t.o -o %t
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=EXE %s
+# RUN: ld.lld -shared %t.o -o %t
+# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=SHARED %s
+
+## It does not really matter how we fixup it, but we cannot overflow and
+## should not generate a call stub (this would waste space).
+# EXE: bl .+0
+
+## With -shared, create a call stub. ld.bfd produces bl .+0
+# SHARED: bl .+4
+# SHARED: 00000000.plt_pic32.foo:
+
+.weak foo
+bl foo

Modified: lld/trunk/test/ELF/silent-ignore.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/silent-ignore.test?rev=362721&r1=362720&r2=362721&view=diff
==============================================================================
--- lld/trunk/test/ELF/silent-ignore.test (original)
+++ lld/trunk/test/ELF/silent-ignore.test Thu Jun  6 10:03:00 2019
@@ -10,6 +10,7 @@ RUN:   -no-pipeline-knowledge \
 RUN:   -no-warn-common \
 RUN:   -no-warn-mismatch \
 RUN:   -p \
+RUN:   -secure-plt \
 RUN:   -sort-common \
 RUN:   -stats \
 RUN:   -warn-execstack \




More information about the llvm-commits mailing list