diff --git a/elf/arch-aarch64.cc b/elf/arch-aarch64.cc index f82888f773..0dc1d9ba70 100644 --- a/elf/arch-aarch64.cc +++ b/elf/arch-aarch64.cc @@ -398,7 +398,7 @@ void InputSection::scan_relocations(Context &ctx) { // Absolute Local Imported data Imported code { NONE, BASEREL, DYNREL, DYNREL }, // DSO { NONE, BASEREL, DYNREL, DYNREL }, // PIE - { NONE, NONE, DYNREL, DYNREL }, // PDE + { NONE, NONE, COPYREL, PLT }, // PDE }; dispatch(ctx, table, i); break; diff --git a/elf/arch-i386.cc b/elf/arch-i386.cc index 9fcab29ccb..79019ad695 100644 --- a/elf/arch-i386.cc +++ b/elf/arch-i386.cc @@ -404,7 +404,7 @@ void InputSection::scan_relocations(Context &ctx) { // Absolute Local Imported data Imported code { NONE, BASEREL, DYNREL, DYNREL }, // DSO { NONE, BASEREL, DYNREL, DYNREL }, // PIE - { NONE, NONE, DYNREL, DYNREL }, // PDE + { NONE, NONE, COPYREL, PLT }, // PDE }; dispatch(ctx, table, i); break; diff --git a/elf/arch-x86-64.cc b/elf/arch-x86-64.cc index 1126057a89..3ea3316f4c 100644 --- a/elf/arch-x86-64.cc +++ b/elf/arch-x86-64.cc @@ -556,7 +556,7 @@ void InputSection::scan_relocations(Context &ctx) { // Absolute Local Imported data Imported code { NONE, BASEREL, DYNREL, DYNREL }, // DSO { NONE, BASEREL, DYNREL, DYNREL }, // PIE - { NONE, NONE, DYNREL, DYNREL }, // PDE + { NONE, NONE, COPYREL, PLT }, // PDE }; dispatch(ctx, table, i); break; diff --git a/elf/output-chunks.cc b/elf/output-chunks.cc index 9d85c779b9..e65655abed 100644 --- a/elf/output-chunks.cc +++ b/elf/output-chunks.cc @@ -861,7 +861,6 @@ void GotSection::copy_buf(Context &ctx) { template void PltSection::add_symbol(Context &ctx, Symbol *sym) { ASSERT(!sym->has_plt(ctx)); - ASSERT(!sym->has_got(ctx)); if (this->shdr.sh_size == 0) { this->shdr.sh_size = E::plt_hdr_size; @@ -1005,7 +1004,7 @@ void DynsymSection::copy_buf(Context &ctx) { } else if (sym.file->is_dso || sym.esym().is_undef()) { esym.st_shndx = SHN_UNDEF; esym.st_size = 0; - if (!ctx.arg.pic && sym.has_plt(ctx) && !sym.has_got(ctx)) { + if (sym.has_plt(ctx) && !ctx.arg.pic) { // Emit an address for a canonical PLT esym.st_value = sym.get_plt_addr(ctx); } diff --git a/elf/passes.cc b/elf/passes.cc index ed6ad9550e..d0c059aad9 100644 --- a/elf/passes.cc +++ b/elf/passes.cc @@ -531,7 +531,10 @@ void scan_rels(Context &ctx) { ctx.got->add_got_symbol(ctx, sym); if (sym->flags & NEEDS_PLT) { - if (sym->flags & NEEDS_GOT) + // If we need to create a canonical PLT (i.e. ctx.arg.pic is false), + // we can't use .plt.got because otherwise .plt.got and .plt would + // refer each other, resulting in an infinite loop at runtime. + if ((sym->flags & NEEDS_GOT) && !ctx.arg.pic) ctx.pltgot->add_symbol(ctx, sym); else ctx.plt->add_symbol(ctx, sym); diff --git a/test/func-addr.sh b/test/func-addr.sh index faed234a4c..dcff5ce453 100755 --- a/test/func-addr.sh +++ b/test/func-addr.sh @@ -10,11 +10,13 @@ cat < +typedef void Func(); + void fn(); -void (*ptr)() = fn; +Func *const ptr = fn; int main() { printf("%d\n", fn == ptr);