mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-25 13:27:26 +08:00
Correct R_SH_IND12W handling
Using bfd_vma for insn is to avoid having to worry about sign propagation in expressions involving insn and sym_value when bfd_vma is not the same as unsigned long. * elf32-sh.c (sh_reloc): Use a bfd_vma insn. (sh_reloc <R_SH_IND12W>): Divide calculated relocation value by two before applying to insn. Correct overflow test. * coff-sh.c (sh_reloc): Likewise.
This commit is contained in:
@ -1,3 +1,10 @@
|
|||||||
|
2019-11-27 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* elf32-sh.c (sh_reloc): Use a bfd_vma insn.
|
||||||
|
(sh_reloc <R_SH_IND12W>): Divide calculated relocation value
|
||||||
|
by two before applying to insn. Correct overflow test.
|
||||||
|
* coff-sh.c (sh_reloc): Likewise.
|
||||||
|
|
||||||
2019-11-26 Nick Clifton <nickc@redhat.com>
|
2019-11-26 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
* elf32-sh.c (sh_elf_reloc): Use a signed_vma when checking for a
|
* elf32-sh.c (sh_elf_reloc): Use a signed_vma when checking for a
|
||||||
|
@ -567,7 +567,7 @@ sh_reloc (bfd * abfd,
|
|||||||
bfd * output_bfd,
|
bfd * output_bfd,
|
||||||
char ** error_message ATTRIBUTE_UNUSED)
|
char ** error_message ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
unsigned long insn;
|
bfd_vma insn;
|
||||||
bfd_vma sym_value;
|
bfd_vma sym_value;
|
||||||
unsigned short r_type;
|
unsigned short r_type;
|
||||||
bfd_vma addr = reloc_entry->address;
|
bfd_vma addr = reloc_entry->address;
|
||||||
@ -610,14 +610,14 @@ sh_reloc (bfd * abfd,
|
|||||||
#endif
|
#endif
|
||||||
insn = bfd_get_32 (abfd, hit_data);
|
insn = bfd_get_32 (abfd, hit_data);
|
||||||
insn += sym_value + reloc_entry->addend;
|
insn += sym_value + reloc_entry->addend;
|
||||||
bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
|
bfd_put_32 (abfd, insn, hit_data);
|
||||||
break;
|
break;
|
||||||
#ifdef COFF_WITH_PE
|
#ifdef COFF_WITH_PE
|
||||||
case R_SH_IMAGEBASE:
|
case R_SH_IMAGEBASE:
|
||||||
insn = bfd_get_32 (abfd, hit_data);
|
insn = bfd_get_32 (abfd, hit_data);
|
||||||
insn += sym_value + reloc_entry->addend;
|
insn += sym_value + reloc_entry->addend;
|
||||||
insn -= pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
|
insn -= pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
|
||||||
bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
|
bfd_put_32 (abfd, insn, hit_data);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case R_SH_PCDISP:
|
case R_SH_PCDISP:
|
||||||
@ -627,12 +627,10 @@ sh_reloc (bfd * abfd,
|
|||||||
+ input_section->output_offset
|
+ input_section->output_offset
|
||||||
+ addr
|
+ addr
|
||||||
+ 4);
|
+ 4);
|
||||||
sym_value += (insn & 0xfff) << 1;
|
sym_value += (((insn & 0xfff) ^ 0x800) - 0x800) << 1;
|
||||||
if (insn & 0x800)
|
insn = (insn & 0xf000) | ((sym_value >> 1) & 0xfff);
|
||||||
sym_value -= 0x1000;
|
bfd_put_16 (abfd, insn, hit_data);
|
||||||
insn = (insn & 0xf000) | (sym_value & 0xfff);
|
if (sym_value + 0x1000 >= 0x2000 || (sym_value & 1) != 0)
|
||||||
bfd_put_16 (abfd, (bfd_vma) insn, hit_data);
|
|
||||||
if ((bfd_signed_vma) sym_value < -0x1000 || sym_value >= 0x1000)
|
|
||||||
return bfd_reloc_overflow;
|
return bfd_reloc_overflow;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -232,7 +232,7 @@ sh_elf_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol_in,
|
|||||||
void *data, asection *input_section, bfd *output_bfd,
|
void *data, asection *input_section, bfd *output_bfd,
|
||||||
char **error_message ATTRIBUTE_UNUSED)
|
char **error_message ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
unsigned long insn;
|
bfd_vma insn;
|
||||||
bfd_vma sym_value;
|
bfd_vma sym_value;
|
||||||
enum elf_sh_reloc_type r_type;
|
enum elf_sh_reloc_type r_type;
|
||||||
bfd_vma addr = reloc_entry->address;
|
bfd_vma addr = reloc_entry->address;
|
||||||
@ -274,7 +274,7 @@ sh_elf_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol_in,
|
|||||||
case R_SH_DIR32:
|
case R_SH_DIR32:
|
||||||
insn = bfd_get_32 (abfd, hit_data);
|
insn = bfd_get_32 (abfd, hit_data);
|
||||||
insn += sym_value + reloc_entry->addend;
|
insn += sym_value + reloc_entry->addend;
|
||||||
bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
|
bfd_put_32 (abfd, insn, hit_data);
|
||||||
break;
|
break;
|
||||||
case R_SH_IND12W:
|
case R_SH_IND12W:
|
||||||
insn = bfd_get_16 (abfd, hit_data);
|
insn = bfd_get_16 (abfd, hit_data);
|
||||||
@ -283,12 +283,10 @@ sh_elf_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol_in,
|
|||||||
+ input_section->output_offset
|
+ input_section->output_offset
|
||||||
+ addr
|
+ addr
|
||||||
+ 4);
|
+ 4);
|
||||||
sym_value += (insn & 0xfff) << 1;
|
sym_value += (((insn & 0xfff) ^ 0x800) - 0x800) << 1;
|
||||||
if (insn & 0x800)
|
insn = (insn & 0xf000) | ((sym_value >> 1) & 0xfff);
|
||||||
sym_value -= 0x1000;
|
bfd_put_16 (abfd, insn, hit_data);
|
||||||
insn = (insn & 0xf000) | (sym_value & 0xfff);
|
if (sym_value + 0x1000 >= 0x2000 || (sym_value & 1) != 0)
|
||||||
bfd_put_16 (abfd, (bfd_vma) insn, hit_data);
|
|
||||||
if ((bfd_signed_vma) sym_value < -0x1000 || sym_value >= 0x1000)
|
|
||||||
return bfd_reloc_overflow;
|
return bfd_reloc_overflow;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
Reference in New Issue
Block a user