| Index: bfd/elf32-avr.c
|
| diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c
|
| index 6d20aefdc21904479b9eaddf0a836f41ca9fa915..38e41df48dfd863e3b1317563684e970e49d0669 100644
|
| --- a/bfd/elf32-avr.c
|
| +++ b/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, FALSE);
|
| +
|
| + for (irelend = irel + isec->reloc_count;
|
| irel < irelend;
|
| irel++)
|
| {
|
| @@ -1564,6 +1617,9 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
|
| /* else...Reference symbol is extern. No need for adjusting
|
| the addend. */
|
| }
|
| +
|
| + if (elf_section_data (isec)->relocs == NULL)
|
| + free (irelend - isec->reloc_count);
|
| }
|
| }
|
|
|
| @@ -1649,6 +1705,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 +1871,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 +1954,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);
|
|
|