| 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); | 
|  |