diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2014-07-16 08:16:24 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2014-07-16 10:57:49 -0700 |
commit | 144bed8d4d8a1bdc0067f55f2ee71c07e5594677 (patch) | |
tree | d4f7b7298150ad44133ef5b04eaa363f045225d3 /bfd/elf32-i386.c | |
parent | 4d974e8854dbc506f154efca8879da3f310bb2b9 (diff) | |
download | gdb-144bed8d4d8a1bdc0067f55f2ee71c07e5594677.zip gdb-144bed8d4d8a1bdc0067f55f2ee71c07e5594677.tar.gz gdb-144bed8d4d8a1bdc0067f55f2ee71c07e5594677.tar.bz2 |
Properly match PLT entry against .got.plt relocation
Relocations against .got.plt section may not be in the same order as
entries in PLT section. It is incorrect to assume that the Ith reloction
index against .got.plt section always maps to the (I + 1)th entry in PLT
section. This patch matches the .got.plt relocation offset/index in PLT
entry against the index in .got.plt relocation table. It only checks
R_*_JUMP_SLOT and R_*_IRELATIVE relocations. It ignores R_*_TLS_DESC
and R_*_TLSDESC relocations since they have different PLT entries.
bfd/
PR binutils/17154
* elf32-i386.c (elf_i386_plt_sym_val): Only match R_*_JUMP_SLOT
and R_*_IRELATIVE relocation offset with PLT entry.
* elf64-x86-64.c (elf_x86_64_plt_sym_val): Likewise.
(elf_x86_64_plt_sym_val_offset_plt_bnd): New.
(elf_x86_64_get_synthetic_symtab): Use it.
ld/testsuite/
PR binutils/17154
* ld-ifunc/pr17154-i386.d: New file.
* ld-ifunc/pr17154-x86-64.d: Likewise.
* ld-ifunc/pr17154-x86.s: Likewise.
* ld-x86-64/bnd-ifunc-2.d: Likewise.
* ld-x86-64/bnd-ifunc-2.s: Likewise.
* ld-x86-64/mpx.exp: Run bnd-ifunc-2.
* ld-x86-64/tlsdesc-nacl.pd: Updated.
* ld-x86-64/tlsdesc.pd: Likewise.
Diffstat (limited to 'bfd/elf32-i386.c')
-rw-r--r-- | bfd/elf32-i386.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 2244c6c..aa01a7a 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -4976,14 +4976,42 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, return TRUE; } -/* Return address for Ith PLT stub in section PLT, for relocation REL - or (bfd_vma) -1 if it should not be included. */ +/* Return address in section PLT for the Ith GOTPLT relocation, for + relocation REL or (bfd_vma) -1 if it should not be included. */ static bfd_vma -elf_i386_plt_sym_val (bfd_vma i, const asection *plt, - const arelent *rel ATTRIBUTE_UNUSED) +elf_i386_plt_sym_val (bfd_vma i, const asection *plt, const arelent *rel) { - return plt->vma + (i + 1) * GET_PLT_ENTRY_SIZE (plt->owner); + bfd *abfd; + const struct elf_i386_backend_data *bed; + bfd_vma plt_offset; + + /* Only match R_386_JUMP_SLOT and R_386_IRELATIVE. */ + if (rel->howto->type != R_386_JUMP_SLOT + && rel->howto->type != R_386_IRELATIVE) + return (bfd_vma) -1; + + abfd = plt->owner; + bed = get_elf_i386_backend_data (abfd); + plt_offset = bed->plt->plt_entry_size; + while (plt_offset < plt->size) + { + bfd_vma reloc_offset; + bfd_byte reloc_offset_raw[4]; + + if (!bfd_get_section_contents (abfd, (asection *) plt, + reloc_offset_raw, + plt_offset + bed->plt->plt_reloc_offset, + sizeof (reloc_offset_raw))) + return (bfd_vma) -1; + + reloc_offset = H_GET_32 (abfd, reloc_offset_raw); + if (reloc_offset == i * sizeof (Elf32_External_Rel)) + return plt->vma + plt_offset; + plt_offset += bed->plt->plt_entry_size; + } + + abort (); } /* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */ |