aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2014-07-16 08:16:24 -0700
committerH.J. Lu <hjl.tools@gmail.com>2014-07-16 10:57:49 -0700
commit144bed8d4d8a1bdc0067f55f2ee71c07e5594677 (patch)
treed4f7b7298150ad44133ef5b04eaa363f045225d3 /bfd
parent4d974e8854dbc506f154efca8879da3f310bb2b9 (diff)
downloadgdb-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')
-rw-r--r--bfd/ChangeLog9
-rw-r--r--bfd/elf32-i386.c38
-rw-r--r--bfd/elf64-x86-64.c89
3 files changed, 122 insertions, 14 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1ecacdd..5e9ce0f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,12 @@
+2014-07-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ 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.
+
2014-07-15 H.J. Lu <hongjiu.lu@intel.com>
PR ld/17057
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. */
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 894ab98..5eea810 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -5292,14 +5292,77 @@ elf_x86_64_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_x86_64_plt_sym_val (bfd_vma i, const asection *plt,
- const arelent *rel ATTRIBUTE_UNUSED)
+ const arelent *rel)
{
- return plt->vma + (i + 1) * GET_PLT_ENTRY_SIZE (plt->owner);
+ bfd *abfd;
+ const struct elf_x86_64_backend_data *bed;
+ bfd_vma plt_offset;
+
+ /* Only match R_X86_64_JUMP_SLOT and R_X86_64_IRELATIVE. */
+ if (rel->howto->type != R_X86_64_JUMP_SLOT
+ && rel->howto->type != R_X86_64_IRELATIVE)
+ return (bfd_vma) -1;
+
+ abfd = plt->owner;
+ bed = get_elf_x86_64_backend_data (abfd);
+ plt_offset = bed->plt_entry_size;
+ while (plt_offset < plt->size)
+ {
+ bfd_vma reloc_index;
+ bfd_byte reloc_index_raw[4];
+
+ if (!bfd_get_section_contents (abfd, (asection *) plt,
+ reloc_index_raw,
+ plt_offset + bed->plt_reloc_offset,
+ sizeof (reloc_index_raw)))
+ return (bfd_vma) -1;
+
+ reloc_index = H_GET_32 (abfd, reloc_index_raw);
+ if (reloc_index == i)
+ return plt->vma + plt_offset;
+ plt_offset += bed->plt_entry_size;
+ }
+
+ abort ();
+}
+
+/* Return offset in .plt.bnd section for the Ith GOTPLT relocation with
+ PLT section, or (bfd_vma) -1 if it should not be included. */
+
+static bfd_vma
+elf_x86_64_plt_sym_val_offset_plt_bnd (bfd_vma i, const asection *plt)
+{
+ const struct elf_x86_64_backend_data *bed = &elf_x86_64_bnd_arch_bed;
+ bfd *abfd = plt->owner;
+ bfd_vma plt_offset = bed->plt_entry_size;
+ while (plt_offset < plt->size)
+ {
+ bfd_vma reloc_index;
+ bfd_byte reloc_index_raw[4];
+
+ if (!bfd_get_section_contents (abfd, (asection *) plt,
+ reloc_index_raw,
+ plt_offset + bed->plt_reloc_offset,
+ sizeof (reloc_index_raw)))
+ return (bfd_vma) -1;
+
+ reloc_index = H_GET_32 (abfd, reloc_index_raw);
+ if (reloc_index == i)
+ {
+ /* This is the index in .plt section. */
+ long plt_index = plt_offset / bed->plt_entry_size;
+ /* Return the offset in .plt.bnd section. */
+ return (plt_index - 1) * sizeof (elf_x86_64_legacy_plt2_entry);
+ }
+ plt_offset += bed->plt_entry_size;
+ }
+
+ abort ();
}
/* Similar to _bfd_elf_get_synthetic_symtab, with .plt.bnd section
@@ -5322,8 +5385,11 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
size_t size;
Elf_Internal_Shdr *hdr;
char *names;
- asection *plt;
- bfd_vma addr;
+ asection *plt, *plt_push;
+
+ plt_push = bfd_get_section_by_name (abfd, ".plt");
+ if (plt_push == NULL)
+ return 0;
plt = bfd_get_section_by_name (abfd, ".plt.bnd");
/* Use the generic ELF version if there is no .plt.bnd section. */
@@ -5369,11 +5435,17 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
names = (char *) (s + count);
p = relplt->relocation;
n = 0;
- addr = 0;
for (i = 0; i < count; i++, p++)
{
+ bfd_vma offset;
size_t len;
+ if (p->howto->type != R_X86_64_JUMP_SLOT
+ && p->howto->type != R_X86_64_IRELATIVE)
+ continue;
+
+ offset = elf_x86_64_plt_sym_val_offset_plt_bnd (i, plt_push);
+
*s = **p->sym_ptr_ptr;
/* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL set. Since
we are defining a symbol, ensure one of them is set. */
@@ -5381,7 +5453,7 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
s->flags |= BSF_GLOBAL;
s->flags |= BSF_SYNTHETIC;
s->section = plt;
- s->value = addr;
+ s->value = offset;
s->name = names;
s->udata.p = NULL;
len = strlen ((*p->sym_ptr_ptr)->name);
@@ -5403,7 +5475,6 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
memcpy (names, "@plt", sizeof ("@plt"));
names += sizeof ("@plt");
++s, ++n;
- addr += sizeof (elf_x86_64_legacy_plt2_entry);
}
return n;