summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2016-04-29 04:31:54 -0700
committerH.J. Lu <hjl.tools@gmail.com>2016-04-29 04:31:54 -0700
commitc337a1627c7e0edf6d46e66dee513c56975d0625 (patch)
treeb8d42703d3ad38ea188b57e82d0f8925f8d7bc9a
parentafd9acee15d55fccf2a25b72c99303f7cbaaa1c2 (diff)
downloadbinutils-gdb-c337a1627c7e0edf6d46e66dee513c56975d0625.tar.gz
i386: Don't relocate section when check_relocs failed
No need to relocate section when check_relocs failed. * elf32-i386.c (check_relocs_failed): New. (elf_i386_check_relocs): Set check_relocs_failed on error. (elf_i386_relocate_section): Skip if check_relocs failed.
-rw-r--r--bfd/ChangeLog6
-rw-r--r--bfd/elf32-i386.c44
2 files changed, 34 insertions, 16 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 23d7f68264c..f422b888916 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,11 @@
2016-04-29 H.J. Lu <hongjiu.lu@intel.com>
+ * elf32-i386.c (check_relocs_failed): New.
+ (elf_i386_check_relocs): Set check_relocs_failed on error.
+ (elf_i386_relocate_section): Skip if check_relocs failed.
+
+2016-04-29 H.J. Lu <hongjiu.lu@intel.com>
+
* elf64-x86-64.c (elf_x86_64_check_relocs): Set
check_relocs_failed on error.
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 4de8a2df8df..ec09c93c9c4 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1506,7 +1506,8 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
/* Rename some of the generic section flags to better document how they
are used here. */
-#define need_convert_load sec_flg0
+#define need_convert_load sec_flg0
+#define check_relocs_failed sec_flg1
/* Look through the relocs for a section during the first phase, and
calculate needed space in the global offset table, procedure linkage
@@ -1533,7 +1534,10 @@ elf_i386_check_relocs (bfd *abfd,
htab = elf_i386_hash_table (info);
if (htab == NULL)
- return FALSE;
+ {
+ sec->check_relocs_failed = 1;
+ return FALSE;
+ }
use_plt_got = (!get_elf_i386_backend_data (abfd)->is_vxworks
&& (get_elf_i386_backend_data (abfd)
@@ -1563,7 +1567,7 @@ elf_i386_check_relocs (bfd *abfd,
(*_bfd_error_handler) (_("%B: bad symbol index: %d"),
abfd,
r_symndx);
- return FALSE;
+ goto error_return;
}
if (r_symndx < symtab_hdr->sh_info)
@@ -1572,14 +1576,14 @@ elf_i386_check_relocs (bfd *abfd,
isym = bfd_sym_from_r_symndx (&htab->sym_cache,
abfd, r_symndx);
if (isym == NULL)
- return FALSE;
+ goto error_return;
/* Check relocation against local STT_GNU_IFUNC symbol. */
if (ELF32_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
{
h = elf_i386_get_local_sym_hash (htab, abfd, rel, TRUE);
if (h == NULL)
- return FALSE;
+ goto error_return;
/* Fake a STT_GNU_IFUNC symbol. */
h->type = STT_GNU_IFUNC;
@@ -1621,7 +1625,7 @@ elf_i386_check_relocs (bfd *abfd,
if (h->type == STT_GNU_IFUNC
&& !_bfd_elf_create_ifunc_sections (htab->elf.dynobj,
info))
- return FALSE;
+ goto error_return;
break;
}
@@ -1638,7 +1642,7 @@ elf_i386_check_relocs (bfd *abfd,
symtab_hdr, sym_hashes,
&r_type, GOT_UNKNOWN,
rel, rel_end, h, r_symndx))
- return FALSE;
+ goto error_return;
switch (r_type)
{
@@ -1729,7 +1733,7 @@ elf_i386_check_relocs (bfd *abfd,
local_got_refcounts = (bfd_signed_vma *)
bfd_zalloc (abfd, size);
if (local_got_refcounts == NULL)
- return FALSE;
+ goto error_return;
elf_local_got_refcounts (abfd) = local_got_refcounts;
elf_i386_local_tlsdesc_gotent (abfd)
= (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
@@ -1765,7 +1769,7 @@ elf_i386_check_relocs (bfd *abfd,
"thread local symbol"),
abfd, name);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ goto error_return;
}
}
@@ -1787,7 +1791,7 @@ elf_i386_check_relocs (bfd *abfd,
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
- return FALSE;
+ goto error_return;
}
if (r_type != R_386_TLS_IE)
{
@@ -1903,7 +1907,7 @@ do_size:
(sec, htab->elf.dynobj, 2, abfd, /*rela?*/ FALSE);
if (sreloc == NULL)
- return FALSE;
+ goto error_return;
}
/* If this is a global symbol, we count the number of
@@ -1923,7 +1927,7 @@ do_size:
isym = bfd_sym_from_r_symndx (&htab->sym_cache,
abfd, r_symndx);
if (isym == NULL)
- return FALSE;
+ goto error_return;
s = bfd_section_from_elf_index (abfd, isym->st_shndx);
if (s == NULL)
@@ -1940,7 +1944,7 @@ do_size:
p = (struct elf_dyn_relocs *) bfd_alloc (htab->elf.dynobj,
amt);
if (p == NULL)
- return FALSE;
+ goto error_return;
p->next = *head;
*head = p;
p->sec = sec;
@@ -1959,7 +1963,7 @@ do_size:
Reconstruct it for later use during GC. */
case R_386_GNU_VTINHERIT:
if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
- return FALSE;
+ goto error_return;
break;
/* This relocation describes which C++ vtable entries are actually
@@ -1968,7 +1972,7 @@ do_size:
BFD_ASSERT (h != NULL);
if (h != NULL
&& !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
- return FALSE;
+ goto error_return;
break;
default:
@@ -2006,7 +2010,7 @@ do_size:
|| !bfd_set_section_alignment (htab->elf.dynobj,
htab->plt_got,
plt_got_align))
- return FALSE;
+ goto error_return;
}
if ((r_type == R_386_GOT32 || r_type == R_386_GOT32X)
@@ -2015,6 +2019,10 @@ do_size:
}
return TRUE;
+
+error_return:
+ sec->check_relocs_failed = 1;
+ return FALSE;
}
/* Return the section that should be marked against GC for a given
@@ -3581,6 +3589,10 @@ elf_i386_relocate_section (bfd *output_bfd,
BFD_ASSERT (is_i386_elf (input_bfd));
+ /* Skip if check_relocs failed. */
+ if (input_section->check_relocs_failed)
+ return FALSE;
+
htab = elf_i386_hash_table (info);
if (htab == NULL)
return FALSE;