Skip to content

Commit

Permalink
[ELF] - Do not use HeaderSize for conditions in PltSection.
Browse files Browse the repository at this point in the history
Previously we checked (HeaderSize == 0) to find out if
PltSection section is IPLT or PLT. Some targets does not set
HeaderSize though. For example PPC64 has no lazy binding implemented
and does not set PltHeaderSize constant.

Because of that using of both IPLT and PLT relocations worked
incorrectly there (testcase is provided).

Patch fixes the issue.

Differential revision: https://reviews.llvm.org/D41613

llvm-svn: 322362
  • Loading branch information
George Rimar committed Jan 12, 2018
1 parent 5627c21 commit 9fc2c64
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 11 deletions.
12 changes: 6 additions & 6 deletions lld/ELF/SyntheticSections.cpp
Expand Up @@ -1858,9 +1858,9 @@ void HashTableSection::writeTo(uint8_t *Buf) {
}
}

PltSection::PltSection(size_t S)
PltSection::PltSection(size_t HeaderSize, bool IsIplt)
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".plt"),
HeaderSize(S) {
HeaderSize(HeaderSize), IsIplt(IsIplt) {
// The PLT needs to be writable on SPARC as the dynamic linker will
// modify the instructions in the PLT entries.
if (Config->EMachine == EM_SPARCV9)
Expand All @@ -1870,7 +1870,7 @@ PltSection::PltSection(size_t S)
void PltSection::writeTo(uint8_t *Buf) {
// At beginning of PLT but not the IPLT, we have code to call the dynamic
// linker to resolve dynsyms at runtime. Write such code.
if (HeaderSize != 0)
if (!IsIplt)
Target->writePltHeader(Buf);
size_t Off = HeaderSize;
// The IPlt is immediately after the Plt, account for this in RelOff
Expand All @@ -1889,7 +1889,7 @@ void PltSection::writeTo(uint8_t *Buf) {
template <class ELFT> void PltSection::addEntry(Symbol &Sym) {
Sym.PltIndex = Entries.size();
RelocationBaseSection *PltRelocSection = InX::RelaPlt;
if (HeaderSize == 0) {
if (IsIplt) {
PltRelocSection = InX::RelaIplt;
Sym.IsInIplt = true;
}
Expand All @@ -1906,7 +1906,7 @@ size_t PltSection::getSize() const {
// example ARM uses mapping symbols to aid disassembly
void PltSection::addSymbols() {
// The PLT may have symbols defined for the Header, the IPLT has no header
if (HeaderSize != 0)
if (!IsIplt)
Target->addPltHeaderSymbols(*this);
size_t Off = HeaderSize;
for (size_t I = 0; I < Entries.size(); ++I) {
Expand All @@ -1916,7 +1916,7 @@ void PltSection::addSymbols() {
}

unsigned PltSection::getPltRelocOff() const {
return (HeaderSize == 0) ? InX::Plt->getSize() : 0;
return IsIplt ? InX::Plt->getSize() : 0;
}

// The string hash function for .gdb_index.
Expand Down
6 changes: 3 additions & 3 deletions lld/ELF/SyntheticSections.h
Expand Up @@ -487,13 +487,13 @@ class HashTableSection final : public SyntheticSection {
size_t Size = 0;
};

// The PltSection is used for both the Plt and Iplt. The former always has a
// The PltSection is used for both the Plt and Iplt. The former usually has a
// header as its first entry that is used at run-time to resolve lazy binding.
// The latter is used for GNU Ifunc symbols, that will be subject to a
// Target->IRelativeRel.
class PltSection : public SyntheticSection {
public:
PltSection(size_t HeaderSize);
PltSection(size_t HeaderSize, bool IsIplt);
void writeTo(uint8_t *Buf) override;
size_t getSize() const override;
bool empty() const override { return Entries.empty(); }
Expand All @@ -504,8 +504,8 @@ class PltSection : public SyntheticSection {
private:
unsigned getPltRelocOff() const;
std::vector<std::pair<const Symbol *, unsigned>> Entries;
// Iplt always has HeaderSize of 0, the Plt HeaderSize is always non-zero
size_t HeaderSize;
bool IsIplt;
};

// GdbIndexChunk is created for each .debug_info section and contains
Expand Down
4 changes: 2 additions & 2 deletions lld/ELF/Writer.cpp
Expand Up @@ -369,9 +369,9 @@ template <class ELFT> static void createSyntheticSections() {
false /*Sort*/);
Add(InX::RelaIplt);

InX::Plt = make<PltSection>(Target->PltHeaderSize);
InX::Plt = make<PltSection>(Target->PltHeaderSize, false /*IsIplt*/);
Add(InX::Plt);
InX::Iplt = make<PltSection>(0);
InX::Iplt = make<PltSection>(0 /*HeaderSize*/, true /*IsIplt*/);
Add(InX::Iplt);

if (!Config->Relocatable) {
Expand Down
41 changes: 41 additions & 0 deletions lld/test/ELF/ppc64-ifunc.s
@@ -0,0 +1,41 @@
# REQUIRES: ppc
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o
# RUN: ld.lld -shared %t2.o -o %t2.so
# RUN: ld.lld %t.o %t2.so -o %t
# RUN: llvm-objdump -d %t | FileCheck %s

# CHECK: _start:
# CHECK-NEXT: 10010004: {{.*}} bl .+12
# CHECK-NEXT: 10010008: {{.*}} bl .+40

# 0x10010004 + 12 = 0x10010010 (PLT entry 0)
# 0x10010008 + 40 = 0x10010030 (PLT entry 1)

# CHECK: Disassembly of section .plt:
# CHECK: 10010010: {{.*}} std 2, 40(1)
# CHECK-NEXT: 10010014: {{.*}} addis 11, 2, 4098
# CHECK-NEXT: 10010018: {{.*}} ld 12, -32744(11)
# CHECK-NEXT: 1001001c: {{.*}} ld 11, 0(12)
# CHECK-NEXT: 10010020: {{.*}} mtctr 11
# CHECK-NEXT: 10010024: {{.*}} ld 2, 8(12)
# CHECK-NEXT: 10010028: {{.*}} ld 11, 16(12)
# CHECK-NEXT: 1001002c: {{.*}} bctr
# CHECK-NEXT: 10010030: {{.*}} std 2, 40(1)
# CHECK-NEXT: 10010034: {{.*}} addis 11, 2, 4098
# CHECK-NEXT: 10010038: {{.*}} ld 12, -32736(11)
# CHECK-NEXT: 1001003c: {{.*}} ld 11, 0(12)
# CHECK-NEXT: 10010040: {{.*}} mtctr 11
# CHECK-NEXT: 10010044: {{.*}} ld 2, 8(12)
# CHECK-NEXT: 10010048: {{.*}} ld 11, 16(12)
# CHECK-NEXT: 1001004c: {{.*}} bctr

.type ifunc STT_GNU_IFUNC
.globl ifunc
ifunc:
nop

.global _start
_start:
bl bar
bl ifunc

0 comments on commit 9fc2c64

Please sign in to comment.