Skip to content

Commit

Permalink
[ELF] Do not create .plt.got for ppc64/ppc64le
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Oct 14, 2022
1 parent 2dbbc54 commit 30dd63c
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 29 deletions.
10 changes: 3 additions & 7 deletions elf/arch-ppc64v1.cc
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,10 @@ void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
*(ub32 *)(buf + 4) = 0x4b00'0000 | (offset & 0x00ff'ffff); // b plt0
}

// .plt.got is not necessary on PPC64 because range extension thunks
// directly read GOT entries and jump there.
template <>
void write_pltgot_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
// No one uses .got.plt at runtime because all calls to .got.plt are
// made via range extension thunks. Range extension thunks directly
// calls the final destination by reading a .got entry. Here, we just
// set a dummy instruction.
*(ub32 *)buf = 0x6000'0000; // nop
}
void write_pltgot_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {}

template <>
void EhFrameSection<E>::apply_reloc(Context<E> &ctx, const ElfRel<E> &rel,
Expand Down
13 changes: 3 additions & 10 deletions elf/arch-ppc64v2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -121,17 +121,10 @@ void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
*(ul32 *)buf |= (ctx.plt->shdr.sh_addr - sym.get_plt_addr(ctx)) & 0x00ff'ffff;
}

// .plt.got is not necessary on PPC64 because range extension thunks
// directly read GOT entries and jump there.
template <>
void write_pltgot_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
// No one uses .got.plt at runtime because all calls to .got.plt are
// made via range extension thunks. Range extension thunks directly
// calls the final destination by reading a .got entry. Here, we just
// set a dummy instruction.
//
// I believe we can completely elimnate .got.plt, but saving 4 bytes
// for each GOTPLT entry doesn't seem to be worth its complexity.
*(ul32 *)buf = 0x6000'0000; // nop
}
void write_pltgot_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {}

template <>
void EhFrameSection<E>::apply_reloc(Context<E> &ctx, const ElfRel<E> &rel,
Expand Down
28 changes: 20 additions & 8 deletions elf/arch-s390x.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,26 @@
// aligned to 2 bytes boundaries. Despite unfamiliarty, I found that it
// just feels like a 64-bit i386 in a parallel universe.
//
// Its psABI reserves %r0 and %r1 as scratch registers so we can use them
// in our PLT. %r2-%r6 are used for parameter passing. %r2 is also used to
// return a value. In position independent code, %r12 usually contains the
// address of GOT. %r14 usually contains a return address. %r15 is a stack
// pointer. Access registers %a0 and %a1 contain the upper 32 bits and
// the lower 32 bits of the thread pointer, respectively.
// Here is the register usage in this ABI:
//
// https://uclibc.org/docs/psABI-s390x.pdf
// r0-r1: reserved as scratch registers so we can use them in our PLT
// r2: parameter passing and return values
// r3-r6: parameter passing
// r12: address of GOT if position-independent code
// r14: return address
// r15: stack pointer
// a1: upper 32 bits of TP (thread pointer)
// a2: lower 32 bits of TP (thread pointer)
//
// TLS is supported on s390x in the same way as it is on other targets
// with one exeption. On other targets, __tls_get_addr is used to get an
// address of a thread-local variable. On s390x, __tls_get_offset is used
// instead. The difference is __tls_get_offset returns an address of a
// thread-local variable as an offset from TP. So we need to add TP to a
// return value before use. I don't know why it is different, but that is
// the way it is.
//
// https://github.com/IBM/s390x-abi/releases/download/v1.6/lzsabi_s390x.pdf

#include "mold.h"

Expand All @@ -33,7 +45,7 @@ template <>
void write_plt_header(Context<E> &ctx, u8 *buf) {
static u8 insn[] = {
0xe3, 0x00, 0xf0, 0x38, 0x00, 0x24, // stg %r0, 56(%r15)
0xc0, 0x10, 0, 0, 0, 0, // larl %r1, GOT_OFFSET
0xc0, 0x10, 0, 0, 0, 0, // larl %r1, GOTPLT_OFFSET
0xd2, 0x07, 0xf0, 0x30, 0x10, 0x08, // mvc 48(8, %r15), 8(%r1)
0xe3, 0x10, 0x10, 0x10, 0x00, 0x04, // lg %r1, 16(%r1)
0x07, 0xf1, // br %r1
Expand Down
4 changes: 2 additions & 2 deletions elf/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -2669,7 +2669,7 @@ struct PPC64V1 {
static constexpr u32 e_machine = EM_PPC64;
static constexpr u32 plt_hdr_size = 52;
static constexpr u32 plt_size = 8;
static constexpr u32 pltgot_size = 4;
static constexpr u32 pltgot_size = 0;
static constexpr u32 tls_dtv_offset = 0x8000;
static constexpr u32 thunk_hdr_size = 0;
static constexpr u32 thunk_size = 28;
Expand Down Expand Up @@ -2706,7 +2706,7 @@ struct PPC64V2 {
static constexpr u32 e_machine = EM_PPC64;
static constexpr u32 plt_hdr_size = 60;
static constexpr u32 plt_size = 4;
static constexpr u32 pltgot_size = 4;
static constexpr u32 pltgot_size = 0;
static constexpr u32 tls_dtv_offset = 0x8000;
static constexpr u32 thunk_hdr_size = 0;
static constexpr u32 thunk_size = 20;
Expand Down
4 changes: 2 additions & 2 deletions elf/output-chunks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1496,9 +1496,9 @@ void PltGotSection<E>::add_symbol(Context<E> &ctx, Symbol<E> *sym) {
assert(!sym->has_plt(ctx));
assert(sym->has_got(ctx));

sym->set_pltgot_idx(ctx, this->shdr.sh_size / E::pltgot_size);
this->shdr.sh_size += E::pltgot_size;
sym->set_pltgot_idx(ctx, symbols.size());
symbols.push_back(sym);
this->shdr.sh_size = symbols.size() * E::pltgot_size;
}

template <typename E>
Expand Down

0 comments on commit 30dd63c

Please sign in to comment.