Skip to content

Commit

Permalink
[ELF] Set the .dynamic address to the first entry of .got
Browse files Browse the repository at this point in the history
glibc for ARM64 prior to August 2021 arguably wrongly assumes that
the GOT first entry contains the address of the .dynamic section.
That's been removed in the following commit, but without satisfying
that assumption, mold can't create working static position-independent
execuables for ARM64.

https://sourceware.org/git/?p=glibc.git;h=43d06ed218fc8be58987bdfd00e21e5720f0b862
  • Loading branch information
rui314 committed Oct 8, 2022
1 parent 8bedc4d commit fc66759
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 11 deletions.
2 changes: 1 addition & 1 deletion elf/mold.h
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ class GotSection : public Chunk<E> {
this->shdr.sh_type = SHT_PROGBITS;
this->shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
this->shdr.sh_addralign = sizeof(Word<E>);
this->shdr.sh_size = sizeof(Word<E>);
}

void add_got_symbol(Context<E> &ctx, Symbol<E> *sym);
Expand All @@ -495,7 +496,6 @@ class GotSection : public Chunk<E> {
u64 get_tlsld_addr(Context<E> &ctx) const;
bool has_tlsld(Context<E> &ctx) const { return tlsld_idx != -1; }
i64 get_reldyn_size(Context<E> &ctx) const;
void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;

void compute_symtab_size(Context<E> &ctx) override;
Expand Down
17 changes: 9 additions & 8 deletions elf/output-chunks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1259,20 +1259,21 @@ std::vector<GotEntry<E>> GotSection<E>::get_entries(Context<E> &ctx) const {
return entries;
}

template <typename E>
void GotSection<E>::update_shdr(Context<E> &ctx) {
// We always create a .got so that _GLOBAL_OFFSET_TABLE_ refers
// a GOT section.
if (this->shdr.sh_size == 0)
this->shdr.sh_size = sizeof(Word<E>);
}

// Fill .got and .rel.dyn.
template <typename E>
void GotSection<E>::copy_buf(Context<E> &ctx) {
Word<E> *buf = (Word<E> *)(ctx.buf + this->shdr.sh_offset);
memset(buf, 0, this->shdr.sh_size);

// glibc before 2021-08 assumes GOT[0] refers _DYNAMIC. We need to
// satisfy the assumption until older glibc completely retires.
// Since it is only required for static PIE on ARM64, we do this only
// for that case, so that no new code would accidentally depend on it.
//
// https://sourceware.org/git/?p=glibc.git;h=43d06ed218fc8be58987bdfd00e21e5720f0b862
if (std::is_same_v<E, ARM64> && ctx.arg.is_static && ctx.arg.pie && ctx.dynamic)
buf[0] = ctx.dynamic->shdr.sh_addr;

ElfRel<E> *rel = (ElfRel<E> *)(ctx.buf + ctx.reldyn->shdr.sh_offset);

for (GotEntry<E> &ent : get_entries(ctx)) {
Expand Down
1 change: 0 additions & 1 deletion test/elf/ifunc-static-pie.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

test_cflags -static-pie || skip
supports_ifunc || skip
[ $MACHINE = aarch64 ] && skip

cat <<EOF | $CC -o $t/a.o -c -xc - -fPIC
#include <stdio.h>
Expand Down
1 change: 0 additions & 1 deletion test/elf/static-pie.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
. $(dirname $0)/common.inc

test_cflags -static-pie || skip
[ $MACHINE = aarch64 ] && skip

cat <<EOF | $CC -o $t/a.o -c -xc - -fPIE
#include <stdio.h>
Expand Down

0 comments on commit fc66759

Please sign in to comment.