diff options
Diffstat (limited to 'binutils-2.22/bfd/elf32-avr.c')
-rw-r--r-- | binutils-2.22/bfd/elf32-avr.c | 97 |
1 files changed, 82 insertions, 15 deletions
diff --git a/binutils-2.22/bfd/elf32-avr.c b/binutils-2.22/bfd/elf32-avr.c index 6d20aef..857a4b7 100644 --- a/binutils-2.22/bfd/elf32-avr.c +++ b/binutils-2.22/bfd/elf32-avr.c @@ -1,6 +1,7 @@ /* AVR-specific support for 32-bit ELF Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, - 2010, 2011 Free Software Foundation, Inc. + 2010, 2011, 2012 + Free Software Foundation, Inc. Contributed by Denis Chertykov <denisc@overta.ru> This file is part of BFD, the Binary File Descriptor library. @@ -516,6 +517,48 @@ static reloc_howto_type elf_avr_howto_table[] = 0x000000ff, /* src_mask */ 0x000000ff, /* dst_mask */ FALSE), /* pcrel_offset */ + /* lo8-part to use in .byte lo8(sym). */ + HOWTO (R_AVR_8_LO8, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_AVR_8_LO8", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* hi8-part to use in .byte hi8(sym). */ + HOWTO (R_AVR_8_HI8, /* type */ + 8, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_AVR_8_HI8", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* hlo8-part to use in .byte hlo8(sym). */ + HOWTO (R_AVR_8_HLO8, /* type */ + 16, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_AVR_8_HLO8", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ }; /* Map BFD reloc types to AVR ELF reloc types. */ @@ -554,7 +597,10 @@ static const struct avr_reloc_map avr_reloc_map[] = { BFD_RELOC_AVR_LDI, R_AVR_LDI }, { BFD_RELOC_AVR_6, R_AVR_6 }, { BFD_RELOC_AVR_6_ADIW, R_AVR_6_ADIW }, - { BFD_RELOC_8, R_AVR_8 } + { BFD_RELOC_8, R_AVR_8 }, + { BFD_RELOC_AVR_8_LO, R_AVR_8_LO8 }, + { BFD_RELOC_AVR_8_HI, R_AVR_8_HI8 }, + { BFD_RELOC_AVR_8_HLO, R_AVR_8_HLO8 } }; /* Meant to be filled one day with the wrap around address for the @@ -1189,9 +1235,9 @@ elf32_avr_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, name = h->root.root.string; } - if (sec != NULL && elf_discarded_section (sec)) + if (sec != NULL && discarded_section (sec)) RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, - rel, relend, howto, contents); + rel, 1, relend, howto, 0, contents); if (info->relocatable) continue; @@ -1503,11 +1549,18 @@ elf32_avr_relax_delete_bytes (bfd *abfd, bfd_vma symval; bfd_vma shrinked_insn_address; + if (isec->reloc_count == 0) + continue; + shrinked_insn_address = (sec->output_section->vma + sec->output_offset + addr - count); - irelend = elf_section_data (isec)->relocs + isec->reloc_count; - for (irel = elf_section_data (isec)->relocs; + irel = elf_section_data (isec)->relocs; + /* PR 12161: Read in the relocs for this section if necessary. */ + if (irel == NULL) + irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE); + + for (irelend = irel + isec->reloc_count; irel < irelend; irel++) { @@ -1649,6 +1702,16 @@ elf32_avr_relax_section (bfd *abfd, Elf_Internal_Sym *isymbuf = NULL; struct elf32_avr_link_hash_table *htab; + /* If 'shrinkable' is FALSE, do not shrink by deleting bytes while + relaxing. Such shrinking can cause issues for the sections such + as .vectors and .jumptables. Instead the unused bytes should be + filled with nop instructions. */ + bfd_boolean shrinkable = TRUE; + + if (!strcmp (sec->name,".vectors") + || !strcmp (sec->name,".jumptables")) + shrinkable = FALSE; + if (link_info->relocatable) (*link_info->callbacks->einfo) (_("%P%F: --relax and -r may not be used together\n")); @@ -1805,10 +1868,16 @@ elf32_avr_relax_section (bfd *abfd, /* Compute the distance from this insn to the branch target. */ gap = value - dot; - /* If the distance is within -4094..+4098 inclusive, then we can - relax this jump/call. +4098 because the call/jump target - will be closer after the relaxation. */ - if ((int) gap >= -4094 && (int) gap <= 4098) + /* Check if the gap falls in the range that can be accommodated + in 13bits signed (It is 12bits when encoded, as we deal with + word addressing). */ + if (!shrinkable && ((int) gap >= -4096 && (int) gap <= 4095)) + distance_short_enough = 1; + /* If shrinkable, then we can check for a range of distance which + is two bytes farther on both the directions because the call + or jump target will be closer by two bytes after the + relaxation. */ + else if (shrinkable && ((int) gap >= -4094 && (int) gap <= 4097)) distance_short_enough = 1; /* Here we handle the wrap-around case. E.g. for a 16k device @@ -1882,11 +1951,9 @@ elf32_avr_relax_section (bfd *abfd, irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_AVR_13_PCREL); - /* Check for the vector section. There we don't want to - modify the ordering! */ - - if (!strcmp (sec->name,".vectors") - || !strcmp (sec->name,".jumptables")) + /* We should not modify the ordering if 'shrinkable' is + FALSE. */ + if (!shrinkable) { /* Let's insert a nop. */ bfd_put_8 (abfd, 0x00, contents + irel->r_offset + 2); |