/* MSP430-specific support for 32-bit ELF
- Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ Copyright (C) 2002-2015 Free Software Foundation, Inc.
Contributed by Dmitry Diky <diwil@mail.ru>
This file is part of BFD, the Binary File Descriptor library.
static inline bfd_boolean
uses_msp430x_relocs (bfd * abfd)
{
- extern const bfd_target bfd_elf32_msp430_ti_vec;
+ extern const bfd_target msp430_elf32_ti_vec;
return bfd_get_mach (abfd) == bfd_mach_msp430x
- || abfd->xvec == & bfd_elf32_msp430_ti_vec;
+ || abfd->xvec == & msp430_elf32_ti_vec;
}
static reloc_howto_type *
if (uses_msp430x_relocs (abfd))
{
- BFD_ASSERT (r_type < (unsigned int) R_MSP430x_max);
+ if (r_type >= (unsigned int) R_MSP430x_max)
+ {
+ _bfd_error_handler (_("%A: invalid MSP430X reloc number: %d"), abfd, r_type);
+ r_type = 0;
+ }
cache_ptr->howto = elf_msp430x_howto_table + r_type;
return;
}
- BFD_ASSERT (r_type < (unsigned int) R_MSP430_max);
+ if (r_type >= (unsigned int) R_MSP430_max)
+ {
+ _bfd_error_handler (_("%A: invalid MSP430 reloc number: %d"), abfd, r_type);
+ r_type = 0;
+ }
cache_ptr->howto = &elf_msp430_howto_table[r_type];
}
irelend = irel + sec->reloc_count;
symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
isym = (Elf_Internal_Sym *) symtab_hdr->contents;
-
+
for (;irel < irelend; irel++)
{
- int sidx = ELF32_R_SYM(irel->r_info);
+ unsigned int sidx = ELF32_R_SYM(irel->r_info);
Elf_Internal_Sym *lsym = isym + sidx;
-
+
/* Adjust symbols referenced by .sec+0xXX */
- if (irel->r_addend > addr && irel->r_addend < toaddr
+ if (irel->r_addend > addr && irel->r_addend < toaddr
+ && sidx < symtab_hdr->sh_info
&& lsym->st_shndx == sec_shndx)
irel->r_addend -= count;
}
bfd_byte * contents = NULL;
Elf_Internal_Sym * isymbuf = NULL;
-
/* Assume nothing changes. */
*again = FALSE;
*again = TRUE;
}
- if (! uses_msp430x_relocs (abfd))
- /* Now perform the relocations that shrink the code size.
- We only do this for non msp430x as gas only generates the RL
- reloc for the msp430. */
for (irel = internal_relocs; irel < irelend; irel++)
{
bfd_vma symval;
/* Try to turn a 16bit pc-relative branch into a 10bit pc-relative
branch. */
/* Paranoia? paranoia... */
- if (ELF32_R_TYPE (irel->r_info) == (int) R_MSP430_RL_PCREL)
+ if (! uses_msp430x_relocs (abfd)
+ && ELF32_R_TYPE (irel->r_info) == (int) R_MSP430_RL_PCREL)
{
bfd_vma value = symval;
*again = TRUE;
}
}
+
+ /* Try to turn a 16-bit absolute branch into a 10-bit pc-relative
+ branch. */
+ if (uses_msp430x_relocs (abfd)
+ && ELF32_R_TYPE (irel->r_info) == R_MSP430X_ABS16)
+ {
+ bfd_vma value = symval;
+
+ value -= irel->r_offset;
+ value += irel->r_addend;
+
+ /* See if the value will fit in 10 bits, note the high value is
+ 1016 as the target will be two bytes closer if we are
+ able to relax. */
+ if ((long) value < 1016 && (long) value > -1016)
+ {
+ int code2;
+
+ /* Get the opcode. */
+ code2 = bfd_get_16 (abfd, contents + irel->r_offset - 2);
+ if (code2 != 0x4030)
+ continue;
+ /* FIXME: check r4 and r3 ? */
+ /* FIXME: Handle 0x4010 as well ? */
+
+ /* Note that we've changed the relocs, section contents, etc. */
+ elf_section_data (sec)->relocs = internal_relocs;
+ elf_section_data (sec)->this_hdr.contents = contents;
+ symtab_hdr->contents = (unsigned char *) isymbuf;
+
+ /* Fix the relocation's type. */
+ if (uses_msp430x_relocs (abfd))
+ {
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+ R_MSP430X_10_PCREL);
+ }
+ else
+ {
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+ R_MSP430_10_PCREL);
+ }
+
+ /* Fix the opcode right way. */
+ bfd_put_16 (abfd, 0x3c00, contents + irel->r_offset - 2);
+ irel->r_offset -= 2;
+
+ /* Delete bytes. */
+ if (!msp430_elf_relax_delete_bytes (abfd, sec,
+ irel->r_offset + 2, 2))
+ goto error_return;
+
+ /* That will change things, so, we should relax again.
+ Note that this is not required, and it may be slow. */
+ *again = TRUE;
+ }
+ }
}
if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
#define ELF_MAXPAGESIZE 4
#define ELF_OSABI ELFOSABI_STANDALONE
-#define TARGET_LITTLE_SYM bfd_elf32_msp430_vec
+#define TARGET_LITTLE_SYM msp430_elf32_vec
#define TARGET_LITTLE_NAME "elf32-msp430"
#define elf_info_to_howto msp430_info_to_howto_rela
#define elf_backend_can_gc_sections 1
#define elf_backend_final_write_processing bfd_elf_msp430_final_write_processing
#define elf_backend_object_p elf32_msp430_object_p
-#define elf_backend_post_process_headers _bfd_elf_set_osabi
#define bfd_elf32_bfd_relax_section msp430_elf_relax_section
#define bfd_elf32_bfd_is_target_special_symbol msp430_elf_is_target_special_symbol
/* The TI compiler sets the OSABI field to ELFOSABI_NONE. */
#undef TARGET_LITTLE_SYM
-#define TARGET_LITTLE_SYM bfd_elf32_msp430_ti_vec
+#define TARGET_LITTLE_SYM msp430_elf32_ti_vec
#undef elf32_bed
#define elf32_bed elf32_msp430_ti_bed