[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