summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2018-12-20 13:05:06 -0800
committerH.J. Lu <hjl.tools@gmail.com>2018-12-20 13:05:06 -0800
commit0125148f8b211154d579beec623d04a225775a3b (patch)
treeb33a74d0532f4238eb2104b6551056506fd60728
parent3705cabd71de7577b7e379a3dd483414f39619f5 (diff)
downloadbinutils-gdb-users/hjl/16bit.tar.gz
Fix R_386_SEG16/R_386_SUB16/R_386_SUB32users/hjl/16bit
-rw-r--r--bfd/elf32-i386.c62
1 files changed, 45 insertions, 17 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index bd4f18e0cae..4be30a51030 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -148,10 +148,10 @@ static reloc_howto_type elf_howto_table[]=
#define R_386_ext2 (R_386_GOT32X + 1 - R_386_tls_offset)
#define R_386_seg16_offset (R_386_SEG16 - R_386_ext2)
- HOWTO(R_386_SEG16, 0, 1, 16, TRUE, 0, complain_overflow_bitfield,
+ HOWTO(R_386_SEG16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_SEG16",
TRUE, 0xffff, 0xffff, FALSE),
- HOWTO(R_386_SUB16, 0, 1, 16, TRUE, 0, complain_overflow_bitfield,
+ HOWTO(R_386_SUB16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_SUB16",
TRUE, 0xffff, 0xffff, FALSE),
HOWTO(R_386_SUB32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
@@ -1947,27 +1947,16 @@ do_size:
case R_386_SUB32:
if (!bfd_link_executable (info))
{
- reloc_howto_type *howto;
- unsigned int indx;
- if ((indx = r_type) >= R_386_standard
- && ((indx = r_type - R_386_ext_offset) - R_386_standard
- >= R_386_ext - R_386_standard)
- && ((indx = r_type - R_386_seg16_offset) - R_386_ext
- >= R_386_ext2 - R_386_ext)
- && ((indx = r_type - R_386_tls_offset) - R_386_ext2
- >= R_386_ext3 - R_386_ext2))
- return _bfd_unrecognized_reloc (abfd, sec, r_type);
- howto = elf_howto_table + indx;
+ reloc_howto_type *howto
+ = elf_i386_rtype_to_howto (abfd, r_type);
if (h)
name = h->root.root.string;
else
- name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
- NULL);
+ name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
info->callbacks->einfo
(_("%F%P: %pB: unsupported relocation %s against symbol "
"`%s' for non-executable\n"),
abfd, howto->name, name);
- bfd_set_error (bfd_error_bad_value);
return FALSE;
}
break;
@@ -2077,6 +2066,7 @@ elf_i386_relocate_section (bfd *output_bfd,
Elf_Internal_Rela *relend;
bfd_boolean is_vxworks_tls;
unsigned plt_entry_size;
+ bfd_vma last_relocation;
/* Skip if check_relocs failed. */
if (input_section->check_relocs_failed)
@@ -2107,6 +2097,8 @@ elf_i386_relocate_section (bfd *output_bfd,
plt_entry_size = htab->plt.plt_entry_size;
+ last_relocation = 0;
+
rel = wrel = relocs;
relend = relocs + input_section->reloc_count;
for (; rel < relend; wrel++, rel++)
@@ -3469,7 +3461,7 @@ disallow_got32:
case R_386_SUB16:
where = contents + rel->r_offset;
addend = bfd_get_16 (input_bfd, where);
- relocation = addend - relocation;
+ relocation = addend - relocation + last_relocation;
bfd_put_16 (input_bfd, 0, where);
break;
@@ -3484,6 +3476,39 @@ disallow_got32:
break;
}
+ /* Handle consecutive relocations of R_386_16 and R_386_SUB16
+ for the same offset. */
+ if ((rel + 1) < relend && rel->r_offset == rel[1].r_offset)
+ {
+ unsigned int r_type2 = ELF32_R_TYPE (rel[1].r_info);
+ reloc_howto_type *howto2
+ = elf_i386_rtype_to_howto (input_bfd, r_type2);
+ if (r_type != R_386_16 && r_type2 != R_386_SUB16)
+ {
+ const char *name;
+ if (h)
+ name = h->root.root.string;
+ else
+ name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
+ NULL);
+ info->callbacks->einfo
+ (_("%F%P: %pB: invalid consecutive relocations %s and "
+ "%s against symbol `%s` at %#x in in section `%pA'\n"),
+ input_bfd, howto->name, howto2->name, name,
+ (uint32_t) rel->r_offset, input_section);
+ return FALSE;
+ }
+
+ /* Record the R_386_16 relocation result. */
+ where = contents + rel->r_offset;
+ addend = bfd_get_16 (input_bfd, where);
+ last_relocation = relocation + addend;
+ bfd_put_16 (input_bfd, 0, where);
+
+ /* Combine R_386_16 relocation with R_386_SUB16. */
+ continue;
+ }
+
/* Dynamic relocs are not propagated for SEC_DEBUGGING sections
because such sections are not SEC_ALLOC and thus ld.so will
not process them. */
@@ -3544,6 +3569,9 @@ check_relocation_error:
if (wrel != rel)
*wrel = *rel;
+
+ /* Clear the previous relocation. */
+ last_relocation = 0;
}
if (wrel != rel)