From 605d18d4351b43e619928770c2912d07175cb1e4 Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Tue, 15 Jul 2008 18:48:07 +0000 Subject: [PATCH] * elf-m10300.c (mn10300_elf_final_link_relocate): Correct overflow checks for PCREL8, PCREL16, GOTPC16, GOTOFF16, PLT16, and GOT16 relocs. (mn10300_elf_relax_section): Correct jump offset check when target is in a different section. --- bfd/ChangeLog | 8 ++++++++ bfd/elf-m10300.c | 26 +++++++++++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 769dd8bf11..443786bc31 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2008-07-14 DJ Delorie + + * elf-m10300.c (mn10300_elf_final_link_relocate): Correct overflow + checks for PCREL8, PCREL16, GOTPC16, GOTOFF16, PLT16, and GOT16 + relocs. + (mn10300_elf_relax_section): Correct jump offset check when target + is in a different section. + 2008-07-15 Jie Zhang * elf32-bfin.c (elf32_bfin_special_sections[]): New. diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c index 61ce3e167f..37c4f3b575 100644 --- a/bfd/elf-m10300.c +++ b/bfd/elf-m10300.c @@ -1212,7 +1212,7 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto, value -= offset; value += addend; - if ((long) value > 0xff || (long) value < -0x100) + if ((long) value > 0x7f || (long) value < -0x80) return bfd_reloc_overflow; bfd_put_8 (input_bfd, value, hit_data); @@ -1224,7 +1224,7 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto, value -= offset; value += addend; - if ((long) value > 0xffff || (long) value < -0x10000) + if ((long) value > 0x7fff || (long) value < -0x8000) return bfd_reloc_overflow; bfd_put_16 (input_bfd, value, hit_data); @@ -1264,7 +1264,7 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto, value -= offset; value += addend; - if ((long) value > 0xffff || (long) value < -0x10000) + if ((long) value > 0x7fff || (long) value < -0x8000) return bfd_reloc_overflow; bfd_put_16 (input_bfd, value, hit_data); @@ -1296,7 +1296,7 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto, ".got")->output_section->vma; value += addend; - if ((long) value > 0xffff || (long) value < -0x10000) + if ((long) value > 0x7fff || (long) value < -0x8000) return bfd_reloc_overflow; bfd_put_16 (input_bfd, value, hit_data); @@ -1345,7 +1345,7 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto, value -= offset; value += addend; - if ((long) value > 0xffff || (long) value < -0x10000) + if ((long) value > 0x7fff || (long) value < -0x8000) return bfd_reloc_overflow; bfd_put_16 (input_bfd, value, hit_data); @@ -1433,7 +1433,7 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto, } else if (r_type == R_MN10300_GOT16) { - if ((long) value > 0xffff || (long) value < -0x10000) + if ((long) value > 0x7fff || (long) value < -0x8000) return bfd_reloc_overflow; bfd_put_16 (input_bfd, value, hit_data); @@ -2751,6 +2751,8 @@ mn10300_elf_relax_section (bfd *abfd, for (irel = internal_relocs; irel < irelend; irel++) { bfd_vma symval; + bfd_signed_vma jump_offset; + asection *sym_sec = NULL; struct elf32_mn10300_link_hash_entry *h = NULL; /* If this isn't something that can be relaxed, then ignore @@ -2790,7 +2792,6 @@ mn10300_elf_relax_section (bfd *abfd, if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) { Elf_Internal_Sym *isym; - asection *sym_sec = NULL; const char *sym_name; char *new_name; @@ -2857,6 +2858,8 @@ mn10300_elf_relax_section (bfd *abfd, if (h->root.root.u.def.section->output_section == NULL) continue; + sym_sec = h->root.root.u.def.section->output_section; + symval = (h->root.root.u.def.value + h->root.root.u.def.section->output_section->vma + h->root.root.u.def.section->output_offset); @@ -2959,10 +2962,15 @@ mn10300_elf_relax_section (bfd *abfd, /* See if the value will fit in 16 bits, note the high value is 0x7fff + 2 as the target will be two bytes closer if we are - able to relax. */ + able to relax, if it's in the same section. */ + if (sec->output_section == sym_sec->output_section) + jump_offset = 0x8001; + else + jump_offset = 0x7fff; + /* Account for jumps across alignment boundaries using align_gap_adjustment. */ - if ((bfd_signed_vma) value < 0x8001 - (bfd_signed_vma) align_gap_adjustment + if ((bfd_signed_vma) value < jump_offset - (bfd_signed_vma) align_gap_adjustment && ((bfd_signed_vma) value > -0x8000 + (bfd_signed_vma) align_gap_adjustment)) { unsigned char code;