diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp --- a/lld/ELF/Arch/X86_64.cpp +++ b/lld/ELF/Arch/X86_64.cpp @@ -85,6 +85,8 @@ tlsGotRel = R_X86_64_TPOFF64; tlsModuleIndexRel = R_X86_64_DTPMOD64; tlsOffsetRel = R_X86_64_DTPOFF64; + gotEntrySize = 8; + gotPltEntrySize = 8; pltHeaderSize = 16; pltEntrySize = 16; ipltEntrySize = 16; diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -160,7 +160,9 @@ return in.got->getVA() + getGotOffset(); } -uint64_t Symbol::getGotOffset() const { return gotIndex * config->wordsize; } +uint64_t Symbol::getGotOffset() const { + return gotIndex * target->gotEntrySize; +} uint64_t Symbol::getGotPltVA() const { if (isInIplt) @@ -170,8 +172,8 @@ uint64_t Symbol::getGotPltOffset() const { if (isInIplt) - return pltIndex * config->wordsize; - return (pltIndex + target->gotPltHeaderEntriesNum) * config->wordsize; + return pltIndex * target->gotPltEntrySize; + return (pltIndex + target->gotPltHeaderEntriesNum) * target->gotPltEntrySize; } uint64_t Symbol::getPltVA() const { diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -644,8 +644,8 @@ } GotSection::GotSection() - : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize, - ".got") { + : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, + target->gotEntrySize, ".got") { numEntries = target->gotHeaderEntriesNum; } @@ -1145,15 +1145,16 @@ } size_t GotPltSection::getSize() const { - return (target->gotPltHeaderEntriesNum + entries.size()) * config->wordsize; + return (target->gotPltHeaderEntriesNum + entries.size()) * + target->gotPltEntrySize; } void GotPltSection::writeTo(uint8_t *buf) { target->writeGotPltHeader(buf); - buf += target->gotPltHeaderEntriesNum * config->wordsize; + buf += target->gotPltHeaderEntriesNum * target->gotPltEntrySize; for (const Symbol *b : entries) { target->writeGotPlt(buf, *b); - buf += config->wordsize; + buf += target->gotPltEntrySize; } } @@ -1181,7 +1182,7 @@ IgotPltSection::IgotPltSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, config->emachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS, - config->wordsize, getIgotPltName()) {} + target->gotPltEntrySize, getIgotPltName()) {} void IgotPltSection::addEntry(Symbol &sym) { assert(sym.pltIndex == entries.size()); @@ -1189,13 +1190,13 @@ } size_t IgotPltSection::getSize() const { - return entries.size() * config->wordsize; + return entries.size() * target->gotPltEntrySize; } void IgotPltSection::writeTo(uint8_t *buf) { for (const Symbol *b : entries) { target->writeIgotPlt(buf, *b); - buf += config->wordsize; + buf += target->gotPltEntrySize; } } diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -122,6 +122,8 @@ RelType tlsGotRel; RelType tlsModuleIndexRel; RelType tlsOffsetRel; + unsigned gotEntrySize = config->wordsize; + unsigned gotPltEntrySize = config->wordsize; unsigned pltEntrySize; unsigned pltHeaderSize; unsigned ipltEntrySize; diff --git a/lld/test/ELF/x86-x32-plt.s b/lld/test/ELF/x86-x32-plt.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/x86-x32-plt.s @@ -0,0 +1,110 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux-gnux32 %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux-gnux32 %p/Inputs/shared.s -o %t2.o +// RUN: ld.lld -shared -soname=so %t2.o -o %t2.so +// RUN: ld.lld -shared %t.o %t2.so -o %t +// RUN: ld.lld %t.o %t2.so -o %t3 +// RUN: llvm-readobj -S -r %t | FileCheck %s +// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=DISASM %s +// RUN: llvm-readobj -S -r %t3 | FileCheck --check-prefix=CHECK2 %s +// RUN: llvm-objdump -d --no-show-raw-insn %t3 | FileCheck --check-prefix=DISASM2 %s + +// CHECK: Name: .plt +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: SHF_EXECINSTR +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x1210 +// CHECK-NEXT: Offset: +// CHECK-NEXT: Size: 64 +// CHECK-NEXT: Link: 0 +// CHECK-NEXT: Info: 0 +// CHECK-NEXT: AddressAlignment: 16 + +// CHECK: Relocations [ +// CHECK-NEXT: Section ({{.*}}) .rela.plt { +// CHECK-NEXT: 0x32C8 R_X86_64_JUMP_SLOT bar 0x0 +// CHECK-NEXT: 0x32D0 R_X86_64_JUMP_SLOT zed 0x0 +// CHECK-NEXT: 0x32D8 R_X86_64_JUMP_SLOT _start 0x0 +// CHECK-NEXT: } +// CHECK-NEXT: ] + +// CHECK2: Name: .plt +// CHECK2-NEXT: Type: SHT_PROGBITS +// CHECK2-NEXT: Flags [ +// CHECK2-NEXT: SHF_ALLOC +// CHECK2-NEXT: SHF_EXECINSTR +// CHECK2-NEXT: ] +// CHECK2-NEXT: Address: 0x2011E0 +// CHECK2-NEXT: Offset: +// CHECK2-NEXT: Size: 48 +// CHECK2-NEXT: Link: 0 +// CHECK2-NEXT: Info: 0 +// CHECK2-NEXT: AddressAlignment: 16 + +// CHECK2: Relocations [ +// CHECK2-NEXT: Section ({{.*}}) .rela.plt { +// CHECK2-NEXT: 0x203290 R_X86_64_JUMP_SLOT bar 0x0 +// CHECK2-NEXT: 0x203298 R_X86_64_JUMP_SLOT zed 0x0 +// CHECK2-NEXT: } +// CHECK2-NEXT: ] + +// DISASM: <_start>: +// DISASM-NEXT: jmp {{.*}} +// DISASM-NEXT: jmp {{.*}} +// DISASM-NEXT: jmp {{.*}} +// DISASM-NEXT: jmp {{.*}} <_start@plt> + +// DISASM: Disassembly of section .plt: +// DISASM-EMPTY: +// DISASM-NEXT: <.plt>: +// DISASM-NEXT: 1210: pushq 8354(%rip) +// DISASM-NEXT: jmpq *8356(%rip) +// DISASM-NEXT: nopl (%rax) +// DISASM-EMPTY: +// DISASM-NEXT: : +// DISASM-NEXT: 1220: jmpq *8354(%rip) +// DISASM-NEXT: pushq $0 +// DISASM-NEXT: jmp 0x1210 <.plt> +// DISASM-EMPTY: +// DISASM-NEXT: : +// DISASM-NEXT: 1230: jmpq *8346(%rip) +// DISASM-NEXT: pushq $1 +// DISASM-NEXT: jmp 0x1210 <.plt> +// DISASM-EMPTY: +// DISASM-NEXT: <_start@plt>: +// DISASM-NEXT: 1240: jmpq *8338(%rip) +// DISASM-NEXT: pushq $2 +// DISASM-NEXT: jmp 0x1210 <.plt> + +// DISASM2: <_start>: +// DISASM2-NEXT: jmp 0x2011f0 +// DISASM2-NEXT: jmp 0x2011f0 +// DISASM2-NEXT: jmp 0x201200 +// DISASM2-NEXT: jmp 0x2011c0 <_start> + +// DISASM2: Disassembly of section .plt: +// DISASM2-EMPTY: +// DISASM2-NEXT: <.plt>: +// DISASM2-NEXT: 2011e0: pushq 8346(%rip) +// DISASM2-NEXT: jmpq *8348(%rip) +// DISASM2-NEXT: nopl (%rax) +// DISASM2-EMPTY: +// DISASM2-NEXT: : +// DISASM2-NEXT: 2011f0: jmpq *8346(%rip) +// DISASM2-NEXT: pushq $0 +// DISASM2-NEXT: jmp 0x2011e0 <.plt> +// DISASM2-EMPTY: +// DISASM2-NEXT: : +// DISASM2-NEXT: 201200: jmpq *8338(%rip) +// DISASM2-NEXT: pushq $1 +// DISASM2-NEXT: jmp 0x2011e0 <.plt> +// DISASM2-NOT: {{.}} + +.global _start +_start: + jmp bar@PLT + jmp bar@PLT + jmp zed@PLT + jmp _start@plt