# DP: Fix PR ld/13302, taken from the trunk bfd/ 2012-03-06 Jakub Jelinek * elf64-x86-64.c (elf_x86_64_relocate_section): For R_X86_64_RELATIVE set relocate to TRUE. 2011-10-21 H.J. Lu PR ld/13302 * elf32-i386.c (elf_i386_relocate_section): Replace R_386_IRELATIVE with R_386_RELATIVE. * elf64-x86-64.c (elf_x86_64_relocate_section): Replace R_X86_64_IRELATIVE with R_X86_64_RELATIVE. 2011-10-21 H.J. Lu . * elf32-i386.c (elf_i386_relocate_section): Fix a typo in comments. * elf64-x86-64.c (elf_x86_64_relocate_section): Likewise. 2011-10-21 H.J. Lu PR ld/13302 * elf32-i386.c (elf_i386_link_hash_table): Add next_jump_slot_index and next_irelative_index. (elf_i386_link_hash_table_create): Initialize next_jump_slot_index and next_irelative_index. (elf_i386_allocate_dynrelocs): Increment reloc_count instead of next_tls_desc_index. (elf_i386_size_dynamic_sections): Set next_tls_desc_index and next_irelative_index from reloc_count. (elf_i386_finish_dynamic_symbol): Put R_386_IRELATIVE after R_386_JUMP_SLOT. * elf64-x86-64.c (elf_x86_64_link_hash_table): Add next_jump_slot_index and next_irelative_index. (elf_x86_64_link_hash_table_create): Initialize next_jump_slot_index and next_irelative_index. (elf_x86_64_size_dynamic_sections): Set next_irelative_index from reloc_count. (elf_x86_64_finish_dynamic_symbol): Put R_X86_64_IRELATIVE after R_X86_64_JUMP_SLOT. ld/testsuite 2011-10-21 H.J. Lu PR ld/13302 * ld-i386/i386.exp: Run pr13302. * ld-i386/pr13302.d: New. * ld-i386/pr13302.s: Likewise. * ld-x86-64/pr13082-5b.d: Updated. * ld-x86-64/pr13082-6a.d: Likewise. * ld-x86-64/pr13082-6b.d: Likewise. 2011-10-21 H.J. Lu PR ld/13302 * ld-ifunc/ifunc-16-i386.d: New. * ld-ifunc/ifunc-16-x86-64.d: Likewise. * ld-ifunc/ifunc-16-x86.s: Likewise. diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 7ef1fc1..d187305 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -806,6 +806,12 @@ struct elf_i386_link_hash_table /* The index of the next unused R_386_TLS_DESC slot in .rel.plt. */ bfd_vma next_tls_desc_index; + + /* The index of the next unused R_386_JUMP_SLOT slot in .rel.plt. */ + bfd_vma next_jump_slot_index; + + /* The index of the next unused R_386_IRELATIVE slot in .rel.plt. */ + bfd_vma next_irelative_index; }; /* Get the i386 ELF linker hash table from a link_info structure. */ @@ -946,6 +952,8 @@ elf_i386_link_hash_table_create (bfd *abfd) ret->sym_cache.abfd = NULL; ret->srelplt2 = NULL; ret->tls_module_base = NULL; + ret->next_jump_slot_index = 0; + ret->next_irelative_index = 0; ret->loc_hash_table = htab_try_create (1024, elf_i386_local_htab_hash, @@ -2275,7 +2283,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* We also need to make an entry in the .rel.plt section. */ htab->elf.srelplt->size += sizeof (Elf32_External_Rel); - htab->next_tls_desc_index++; + htab->elf.srelplt->reloc_count++; if (get_elf_i386_backend_data (info->output_bfd)->is_vxworks && !info->shared) @@ -2700,9 +2708,19 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) incremented. However, when we reserve space for TLS descriptors, it's not incremented, so in order to compute the space reserved for them, it suffices to multiply the reloc count by the jump - slot size. */ + slot size. + + PR ld/13302: We start next_irelative_index at the end of .rela.plt + so that R_386_IRELATIVE entries come last. */ if (htab->elf.srelplt) - htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4; + { + htab->next_tls_desc_index = htab->elf.srelplt->reloc_count; + htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4; + htab->next_irelative_index = htab->elf.srelplt->reloc_count - 1; + } + else if (htab->elf.irelplt) + htab->next_irelative_index = htab->elf.irelplt->reloc_count - 1; + if (htab->elf.sgotplt) { @@ -3232,13 +3250,14 @@ elf_i386_relocate_section (bfd *output_bfd, case R_386_32: /* Generate dynamic relcoation only when there is a - non-GOF reference in a shared object. */ + non-GOT reference in a shared object. */ if (info->shared && h->non_got_ref) { Elf_Internal_Rela outrel; bfd_byte *loc; asection *sreloc; bfd_vma offset; + bfd_boolean relocate; /* Need a dynamic relocation to get the real function adddress. */ @@ -3259,15 +3278,14 @@ elf_i386_relocate_section (bfd *output_bfd, || info->executable) { /* This symbol is resolved locally. */ - outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE); - bfd_put_32 (output_bfd, - (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset), - contents + offset); + outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); + relocate = TRUE; } else - outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); + { + outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); + relocate = FALSE; + } sreloc = htab->elf.irelifunc; loc = sreloc->contents; @@ -3280,7 +3298,8 @@ elf_i386_relocate_section (bfd *output_bfd, we need to include the symbol value so that it becomes an addend for the dynamic reloc. For an internal symbol, we have updated addend. */ - continue; + if (! relocate) + continue; } /* FALLTHROUGH */ case R_386_PC32: @@ -4364,13 +4383,13 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, if (plt == htab->elf.splt) { - plt_index = h->plt.offset / plt_entry_size - 1; - got_offset = (plt_index + 3) * 4; + got_offset = h->plt.offset / plt_entry_size - 1; + got_offset = (got_offset + 3) * 4; } else { - plt_index = h->plt.offset / plt_entry_size; - got_offset = plt_index * 4; + got_offset = h->plt.offset / plt_entry_size; + got_offset = got_offset * 4; } /* Fill in the entry in the procedure linkage table. */ @@ -4431,18 +4450,6 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, + abed->plt->plt_got_offset); } - /* Don't fill PLT entry for static executables. */ - if (plt == htab->elf.splt) - { - bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel), - plt->contents + h->plt.offset - + abed->plt->plt_reloc_offset); - bfd_put_32 (output_bfd, - (h->plt.offset - + abed->plt->plt_plt_offset + 4), - plt->contents + h->plt.offset - + abed->plt->plt_plt_offset); - } - /* Fill in the entry in the global offset table. */ bfd_put_32 (output_bfd, (plt->output_section->vma @@ -4470,12 +4477,29 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, + h->root.u.def.section->output_offset), gotplt->contents + got_offset); rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE); + /* R_386_IRELATIVE comes last. */ + plt_index = htab->next_irelative_index--; } else - rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT); + { + rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT); + plt_index = htab->next_jump_slot_index++; + } loc = relplt->contents + plt_index * sizeof (Elf32_External_Rel); bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); + /* Don't fill PLT entry for static executables. */ + if (plt == htab->elf.splt) + { + bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel), + plt->contents + h->plt.offset + + abed->plt->plt_reloc_offset); + bfd_put_32 (output_bfd, - (h->plt.offset + + abed->plt->plt_plt_offset + 4), + plt->contents + h->plt.offset + + abed->plt->plt_plt_offset); + } + if (!h->def_regular) { /* Mark the symbol as undefined, rather than as defined in diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index e4c3946..2206dd4 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -698,6 +698,11 @@ struct elf_x86_64_link_hash_table /* The offset into sgot of the GOT entry used by the PLT entry above. */ bfd_vma tlsdesc_got; + + /* The index of the next R_X86_64_JUMP_SLOT entry in .rela.plt. */ + bfd_vma next_jump_slot_index; + /* The index of the next R_X86_64_IRELATIVE entry in .rela.plt. */ + bfd_vma next_irelative_index; }; /* Get the x86-64 ELF linker hash table from a link_info structure. */ @@ -839,6 +844,8 @@ elf_x86_64_link_hash_table_create (bfd *abfd) ret->tls_ld_got.refcount = 0; ret->sgotplt_jump_table_size = 0; ret->tls_module_base = NULL; + ret->next_jump_slot_index = 0; + ret->next_irelative_index = 0; if (ABI_64_P (abfd)) { @@ -2667,10 +2674,18 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, incremented. However, when we reserve space for TLS descriptors, it's not incremented, so in order to compute the space reserved for them, it suffices to multiply the reloc count by the jump - slot size. */ + slot size. + + PR ld/13302: We start next_irelative_index at the end of .rela.plt + so that R_X86_64_IRELATIVE entries come last. */ if (htab->elf.srelplt) - htab->sgotplt_jump_table_size - = elf_x86_64_compute_jump_table_size (htab); + { + htab->sgotplt_jump_table_size + = elf_x86_64_compute_jump_table_size (htab); + htab->next_irelative_index = htab->elf.srelplt->reloc_count - 1; + } + else if (htab->elf.irelplt) + htab->next_irelative_index = htab->elf.irelplt->reloc_count - 1; if (htab->tlsdesc_plt) { @@ -3141,11 +3156,12 @@ elf_x86_64_relocate_section (bfd *output_bfd, } /* Generate dynamic relcoation only when there is a - non-GOF reference in a shared object. */ + non-GOT reference in a shared object. */ if (info->shared && h->non_got_ref) { Elf_Internal_Rela outrel; asection *sreloc; + bfd_boolean relocate; /* Need a dynamic relocation to get the real function address. */ @@ -3165,15 +3181,15 @@ elf_x86_64_relocate_section (bfd *output_bfd, || info->executable) { /* This symbol is resolved locally. */ - outrel.r_info = htab->r_info (0, R_X86_64_IRELATIVE); - outrel.r_addend = (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset); + outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE); + outrel.r_addend = relocation; + relocate = TRUE; } else { outrel.r_info = htab->r_info (h->dynindx, r_type); outrel.r_addend = 0; + relocate = FALSE; } sreloc = htab->elf.irelifunc; @@ -3184,7 +3200,8 @@ elf_x86_64_relocate_section (bfd *output_bfd, we need to include the symbol value so that it becomes an addend for the dynamic reloc. For an internal symbol, we have updated addend. */ - continue; + if (! relocate) + continue; } /* FALLTHROUGH */ case R_X86_64_PC32: @@ -4205,13 +4222,13 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, if (plt == htab->elf.splt) { - plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; - got_offset = (plt_index + 3) * GOT_ENTRY_SIZE; + got_offset = h->plt.offset / PLT_ENTRY_SIZE - 1; + got_offset = (got_offset + 3) * GOT_ENTRY_SIZE; } else { - plt_index = h->plt.offset / PLT_ENTRY_SIZE; - got_offset = plt_index * GOT_ENTRY_SIZE; + got_offset = h->plt.offset / PLT_ENTRY_SIZE; + got_offset = got_offset * GOT_ENTRY_SIZE; } /* Fill in the entry in the procedure linkage table. */ @@ -4233,17 +4250,6 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, - 6), plt->contents + h->plt.offset + 2); - /* Don't fill PLT entry for static executables. */ - if (plt == htab->elf.splt) - { - /* Put relocation index. */ - bfd_put_32 (output_bfd, plt_index, - plt->contents + h->plt.offset + 7); - /* Put offset for jmp .PLT0. */ - bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE), - plt->contents + h->plt.offset + 12); - } - /* Fill in the entry in the global offset table, initially this points to the pushq instruction in the PLT which is at offset 6. */ bfd_put_64 (output_bfd, (plt->output_section->vma @@ -4267,11 +4273,25 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, rela.r_addend = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); + /* R_X86_64_IRELATIVE comes last. */ + plt_index = htab->next_irelative_index--; } else { rela.r_info = htab->r_info (h->dynindx, R_X86_64_JUMP_SLOT); rela.r_addend = 0; + plt_index = htab->next_jump_slot_index++; + } + + /* Don't fill PLT entry for static executables. */ + if (plt == htab->elf.splt) + { + /* Put relocation index. */ + bfd_put_32 (output_bfd, plt_index, + plt->contents + h->plt.offset + 7); + /* Put offset for jmp .PLT0. */ + bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE), + plt->contents + h->plt.offset + 12); } bed = get_elf_backend_data (output_bfd); diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp index 68b71fb..1727922 100644 --- a/ld/testsuite/ld-i386/i386.exp +++ b/ld/testsuite/ld-i386/i386.exp @@ -210,3 +210,4 @@ if { !([istarget "i?86-*-linux*"] run_dump_test "compressed1" run_dump_test "pr12627" +run_dump_test "pr13302" diff --git a/ld/testsuite/ld-i386/pr13302.d b/ld/testsuite/ld-i386/pr13302.d new file mode 100644 index 0000000..3d85d08 --- /dev/null +++ b/ld/testsuite/ld-i386/pr13302.d @@ -0,0 +1,12 @@ +#name: PR ld/13302 +#as: --32 +#ld: -pie -melf_i386 +#readelf: -r --wide + +Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 1 entries: + Offset Info Type Sym. Value Symbol's Name +[0-9a-f]+ +[0-9a-f]+ +R_386_RELATIVE + + +Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 1 entries: + Offset Info Type Sym. Value Symbol's Name +[0-9a-f]+ +[0-9a-f]+ +R_386_IRELATIVE + diff --git a/ld/testsuite/ld-i386/pr13302.s b/ld/testsuite/ld-i386/pr13302.s new file mode 100644 index 0000000..cfd2717 --- /dev/null +++ b/ld/testsuite/ld-i386/pr13302.s @@ -0,0 +1,11 @@ + .text + .globl _start + .type ifunc, @gnu_indirect_function +_start: + lea .Ljmp@GOTOFF(%ebx), %eax +ifunc: + jmp *(%eax) + .section .data.rel.ro.local,"aw",@progbits + .align 4 +.Ljmp: + .long ifunc diff --git a/ld/testsuite/ld-ifunc/ifunc-16-i386.d b/ld/testsuite/ld-ifunc/ifunc-16-i386.d new file mode 100644 index 0000000..8ae3d0a --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-16-i386.d @@ -0,0 +1,10 @@ +#source: ifunc-16-x86.s +#ld: -shared -m elf_i386 +#as: --32 +#readelf: -r --wide +#target: x86_64-*-* i?86-*-* + +Relocation section '.rel.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_JUMP_SLOT[ ]+0+[ ]+ifunc +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]* diff --git a/ld/testsuite/ld-ifunc/ifunc-16-x86-64.d b/ld/testsuite/ld-ifunc/ifunc-16-x86-64.d new file mode 100644 index 0000000..d69626d --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-16-x86-64.d @@ -0,0 +1,10 @@ +#source: ifunc-16-x86.s +#as: --64 +#ld: -shared -melf_x86_64 +#readelf: -r --wide +#target: x86_64-*-* + +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_JUMP_SLOT[ ]+0+[ ]+ifunc \+ 0 +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-ifunc/ifunc-16-x86.s b/ld/testsuite/ld-ifunc/ifunc-16-x86.s new file mode 100644 index 0000000..fb38253 --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-16-x86.s @@ -0,0 +1,17 @@ + .text + .globl fct + .type fct, @gnu_indirect_function + .set fct,resolve + .hidden int_fct + .globl int_fct + .set int_fct,fct + .p2align 4,,15 + .type resolve, @function +resolve: + call ifunc@PLT + .size resolve, .-resolve + .globl g + .type g, @function +g: + jmp int_fct@PLT + .size g, .-g diff --git a/ld/testsuite/ld-x86-64/pr13082-5b.d b/ld/testsuite/ld-x86-64/pr13082-5b.d index 1c5a5e7..48e37c3 100644 --- a/ld/testsuite/ld-x86-64/pr13082-5b.d +++ b/ld/testsuite/ld-x86-64/pr13082-5b.d @@ -6,7 +6,7 @@ Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries: Offset Info Type Sym. Value Symbol's Name \+ Addend -[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +R_X86_64_RELATIVE +[0-9a-f]+ Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries: Offset Info Type Sym. Value Symbol's Name \+ Addend diff --git a/ld/testsuite/ld-x86-64/pr13082-6a.d b/ld/testsuite/ld-x86-64/pr13082-6a.d index 9a1a655..de90bb8 100644 --- a/ld/testsuite/ld-x86-64/pr13082-6a.d +++ b/ld/testsuite/ld-x86-64/pr13082-6a.d @@ -6,7 +6,7 @@ Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries: Offset Info Type Sym. Value Symbol's Name \+ Addend -[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +R_X86_64_RELATIVE +[0-9a-f]+ Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries: Offset Info Type Sym. Value Symbol's Name \+ Addend diff --git a/ld/testsuite/ld-x86-64/pr13082-6b.d b/ld/testsuite/ld-x86-64/pr13082-6b.d index 792c348..66ff59b 100644 --- a/ld/testsuite/ld-x86-64/pr13082-6b.d +++ b/ld/testsuite/ld-x86-64/pr13082-6b.d @@ -6,7 +6,7 @@ Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 1 entries: Offset Info Type Sym. Value Symbol's Name \+ Addend -[0-9a-f]+ +[0-9a-f]+ +R_X86_64_IRELATIVE +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +R_X86_64_RELATIVE +[0-9a-f]+ Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries: Offset Info Type Sym. Value Symbol's Name \+ Addend