| /* AVR-specific support for 32-bit ELF | 
 |    Copyright (C) 1999-2021 Free Software Foundation, Inc. | 
 |    Contributed by Denis Chertykov <denisc@overta.ru> | 
 |  | 
 |    This file is part of BFD, the Binary File Descriptor library. | 
 |  | 
 |    This program is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3 of the License, or | 
 |    (at your option) any later version. | 
 |  | 
 |    This program is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |    GNU General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program; if not, write to the Free Software | 
 |    Foundation, Inc., 51 Franklin Street - Fifth Floor, | 
 |    Boston, MA 02110-1301, USA.  */ | 
 |  | 
 | #include "sysdep.h" | 
 | #include "bfd.h" | 
 | #include "libbfd.h" | 
 | #include "elf-bfd.h" | 
 | #include "elf/avr.h" | 
 | #include "elf32-avr.h" | 
 |  | 
 | /* Enable debugging printout at stdout with this variable.  */ | 
 | static bool debug_relax = false; | 
 |  | 
 | /* Enable debugging printout at stdout with this variable.  */ | 
 | static bool debug_stubs = false; | 
 |  | 
 | static bfd_reloc_status_type | 
 | bfd_elf_avr_diff_reloc (bfd *, arelent *, asymbol *, void *, | 
 | 			asection *, bfd *, char **); | 
 |  | 
 | /* Hash table initialization and handling.  Code is taken from the hppa port | 
 |    and adapted to the needs of AVR.  */ | 
 |  | 
 | /* We use two hash tables to hold information for linking avr objects. | 
 |  | 
 |    The first is the elf32_avr_link_hash_table which is derived from the | 
 |    stanard ELF linker hash table.  We use this as a place to attach the other | 
 |    hash table and some static information. | 
 |  | 
 |    The second is the stub hash table which is derived from the base BFD | 
 |    hash table.  The stub hash table holds the information on the linker | 
 |    stubs.  */ | 
 |  | 
 | struct elf32_avr_stub_hash_entry | 
 | { | 
 |   /* Base hash table entry structure.  */ | 
 |   struct bfd_hash_entry bh_root; | 
 |  | 
 |   /* Offset within stub_sec of the beginning of this stub.  */ | 
 |   bfd_vma stub_offset; | 
 |  | 
 |   /* Given the symbol's value and its section we can determine its final | 
 |      value when building the stubs (so the stub knows where to jump).  */ | 
 |   bfd_vma target_value; | 
 |  | 
 |   /* This way we could mark stubs to be no longer necessary.  */ | 
 |   bool is_actually_needed; | 
 | }; | 
 |  | 
 | struct elf32_avr_link_hash_table | 
 | { | 
 |   /* The main hash table.  */ | 
 |   struct elf_link_hash_table etab; | 
 |  | 
 |   /* The stub hash table.  */ | 
 |   struct bfd_hash_table bstab; | 
 |  | 
 |   bool no_stubs; | 
 |  | 
 |   /* Linker stub bfd.  */ | 
 |   bfd *stub_bfd; | 
 |  | 
 |   /* The stub section.  */ | 
 |   asection *stub_sec; | 
 |  | 
 |   /* Usually 0, unless we are generating code for a bootloader.  Will | 
 |      be initialized by elf32_avr_size_stubs to the vma offset of the | 
 |      output section associated with the stub section.  */ | 
 |   bfd_vma vector_base; | 
 |  | 
 |   /* Assorted information used by elf32_avr_size_stubs.  */ | 
 |   unsigned int	      bfd_count; | 
 |   unsigned int	      top_index; | 
 |   asection **	      input_list; | 
 |   Elf_Internal_Sym ** all_local_syms; | 
 |  | 
 |   /* Tables for mapping vma beyond the 128k boundary to the address of the | 
 |      corresponding stub.  (AMT) | 
 |      "amt_max_entry_cnt" reflects the number of entries that memory is allocated | 
 |      for in the "amt_stub_offsets" and "amt_destination_addr" arrays. | 
 |      "amt_entry_cnt" informs how many of these entries actually contain | 
 |      useful data.  */ | 
 |   unsigned int amt_entry_cnt; | 
 |   unsigned int amt_max_entry_cnt; | 
 |   bfd_vma *    amt_stub_offsets; | 
 |   bfd_vma *    amt_destination_addr; | 
 | }; | 
 |  | 
 | /* Various hash macros and functions.  */ | 
 | #define avr_link_hash_table(p) \ | 
 |   ((is_elf_hash_table ((p)->hash)					\ | 
 |     && elf_hash_table_id (elf_hash_table (p)) == AVR_ELF_DATA)		\ | 
 |    ? (struct elf32_avr_link_hash_table *) (p)->hash : NULL) | 
 |  | 
 | #define avr_stub_hash_entry(ent) \ | 
 |   ((struct elf32_avr_stub_hash_entry *)(ent)) | 
 |  | 
 | #define avr_stub_hash_lookup(table, string, create, copy) \ | 
 |   ((struct elf32_avr_stub_hash_entry *) \ | 
 |    bfd_hash_lookup ((table), (string), (create), (copy))) | 
 |  | 
 | static reloc_howto_type elf_avr_howto_table[] = | 
 | { | 
 |   HOWTO (R_AVR_NONE,		/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 3,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 0,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_dont, /* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc,	/* special_function */ | 
 | 	 "R_AVR_NONE",		/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0,			/* src_mask */ | 
 | 	 0,			/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |  | 
 |   HOWTO (R_AVR_32,		/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 2,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 32,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_bitfield, /* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc,	/* special_function */ | 
 | 	 "R_AVR_32",		/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffffffff,		/* src_mask */ | 
 | 	 0xffffffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |  | 
 |   /* A 7 bit PC relative relocation.  */ | 
 |   HOWTO (R_AVR_7_PCREL,		/* type */ | 
 | 	 1,			/* rightshift */ | 
 | 	 1,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 7,			/* bitsize */ | 
 | 	 true,			/* pc_relative */ | 
 | 	 3,			/* bitpos */ | 
 | 	 complain_overflow_bitfield, /* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc, /* special_function */ | 
 | 	 "R_AVR_7_PCREL",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 true),			/* pcrel_offset */ | 
 |  | 
 |   /* A 13 bit PC relative relocation.  */ | 
 |   HOWTO (R_AVR_13_PCREL,	/* type */ | 
 | 	 1,			/* rightshift */ | 
 | 	 1,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 13,			/* bitsize */ | 
 | 	 true,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_bitfield, /* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc, /* special_function */ | 
 | 	 "R_AVR_13_PCREL",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xfff,			/* src_mask */ | 
 | 	 0xfff,			/* dst_mask */ | 
 | 	 true),			/* pcrel_offset */ | 
 |  | 
 |   /* A 16 bit absolute relocation.  */ | 
 |   HOWTO (R_AVR_16,		/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 1,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 16,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_dont, /* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc,	/* special_function */ | 
 | 	 "R_AVR_16",		/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |  | 
 |   /* A 16 bit absolute relocation for command address | 
 |      Will be changed when linker stubs are needed.  */ | 
 |   HOWTO (R_AVR_16_PM,		/* type */ | 
 | 	 1,			/* rightshift */ | 
 | 	 1,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 16,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_bitfield, /* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc,	/* special_function */ | 
 | 	 "R_AVR_16_PM",		/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A low 8 bit absolute relocation of 16 bit address. | 
 |      For LDI command.  */ | 
 |   HOWTO (R_AVR_LO8_LDI,		/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 1,			/* 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_LO8_LDI",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A high 8 bit absolute relocation of 16 bit address. | 
 |      For LDI command.  */ | 
 |   HOWTO (R_AVR_HI8_LDI,		/* type */ | 
 | 	 8,			/* rightshift */ | 
 | 	 1,			/* 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_HI8_LDI",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A high 6 bit absolute relocation of 22 bit address. | 
 |      For LDI command.  As well second most significant 8 bit value of | 
 |      a 32 bit link-time constant.  */ | 
 |   HOWTO (R_AVR_HH8_LDI,		/* type */ | 
 | 	 16,			/* rightshift */ | 
 | 	 1,			/* 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_HH8_LDI",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A negative low 8 bit absolute relocation of 16 bit address. | 
 |      For LDI command.  */ | 
 |   HOWTO (R_AVR_LO8_LDI_NEG,	/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 1,			/* 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_LO8_LDI_NEG",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A negative high 8 bit absolute relocation of 16 bit address. | 
 |      For LDI command.  */ | 
 |   HOWTO (R_AVR_HI8_LDI_NEG,	/* type */ | 
 | 	 8,			/* rightshift */ | 
 | 	 1,			/* 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_HI8_LDI_NEG",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A negative high 6 bit absolute relocation of 22 bit address. | 
 |      For LDI command.  */ | 
 |   HOWTO (R_AVR_HH8_LDI_NEG,	/* type */ | 
 | 	 16,			/* rightshift */ | 
 | 	 1,			/* 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_HH8_LDI_NEG",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A low 8 bit absolute relocation of 24 bit program memory address. | 
 |      For LDI command.  Will not be changed when linker stubs are needed. */ | 
 |   HOWTO (R_AVR_LO8_LDI_PM,	/* type */ | 
 | 	 1,			/* rightshift */ | 
 | 	 1,			/* 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_LO8_LDI_PM",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A low 8 bit absolute relocation of 24 bit program memory address. | 
 |      For LDI command.  Will not be changed when linker stubs are needed. */ | 
 |   HOWTO (R_AVR_HI8_LDI_PM,	/* type */ | 
 | 	 9,			/* rightshift */ | 
 | 	 1,			/* 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_HI8_LDI_PM",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A low 8 bit absolute relocation of 24 bit program memory address. | 
 |      For LDI command.  Will not be changed when linker stubs are needed. */ | 
 |   HOWTO (R_AVR_HH8_LDI_PM,	/* type */ | 
 | 	 17,			/* rightshift */ | 
 | 	 1,			/* 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_HH8_LDI_PM",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A low 8 bit absolute relocation of 24 bit program memory address. | 
 |      For LDI command.  Will not be changed when linker stubs are needed. */ | 
 |   HOWTO (R_AVR_LO8_LDI_PM_NEG,	/* type */ | 
 | 	 1,			/* rightshift */ | 
 | 	 1,			/* 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_LO8_LDI_PM_NEG", /* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A low 8 bit absolute relocation of 24 bit program memory address. | 
 |      For LDI command.  Will not be changed when linker stubs are needed. */ | 
 |   HOWTO (R_AVR_HI8_LDI_PM_NEG,	/* type */ | 
 | 	 9,			/* rightshift */ | 
 | 	 1,			/* 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_HI8_LDI_PM_NEG", /* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A low 8 bit absolute relocation of 24 bit program memory address. | 
 |      For LDI command.  Will not be changed when linker stubs are needed. */ | 
 |   HOWTO (R_AVR_HH8_LDI_PM_NEG,	/* type */ | 
 | 	 17,			/* rightshift */ | 
 | 	 1,			/* 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_HH8_LDI_PM_NEG", /* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* Relocation for CALL command in ATmega.  */ | 
 |   HOWTO (R_AVR_CALL,		/* type */ | 
 | 	 1,			/* rightshift */ | 
 | 	 2,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 23,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_dont,/* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc,	/* special_function */ | 
 | 	 "R_AVR_CALL",		/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffffffff,		/* src_mask */ | 
 | 	 0xffffffff,		/* dst_mask */ | 
 | 	 false),			/* pcrel_offset */ | 
 |   /* A 16 bit absolute relocation of 16 bit address. | 
 |      For LDI command.  */ | 
 |   HOWTO (R_AVR_LDI,		/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 1,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 16,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_dont,/* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc,	/* special_function */ | 
 | 	 "R_AVR_LDI",		/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A 6 bit absolute relocation of 6 bit offset. | 
 |      For ldd/sdd command.  */ | 
 |   HOWTO (R_AVR_6,		/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 0,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 6,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_dont,/* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc,	/* special_function */ | 
 | 	 "R_AVR_6",		/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A 6 bit absolute relocation of 6 bit offset. | 
 |      For sbiw/adiw command.  */ | 
 |   HOWTO (R_AVR_6_ADIW,		/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 0,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 6,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_dont,/* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc,	/* special_function */ | 
 | 	 "R_AVR_6_ADIW",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* Most significant 8 bit value of a 32 bit link-time constant.  */ | 
 |   HOWTO (R_AVR_MS8_LDI,		/* type */ | 
 | 	 24,			/* rightshift */ | 
 | 	 1,			/* 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_MS8_LDI",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* Negative most significant 8 bit value of a 32 bit link-time constant.  */ | 
 |   HOWTO (R_AVR_MS8_LDI_NEG,	/* type */ | 
 | 	 24,			/* rightshift */ | 
 | 	 1,			/* 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_MS8_LDI_NEG",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A low 8 bit absolute relocation of 24 bit program memory address. | 
 |      For LDI command.  Will be changed when linker stubs are needed.  */ | 
 |   HOWTO (R_AVR_LO8_LDI_GS,	/* type */ | 
 | 	 1,			/* rightshift */ | 
 | 	 1,			/* 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_LO8_LDI_GS",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* A low 8 bit absolute relocation of 24 bit program memory address. | 
 |      For LDI command.  Will be changed when linker stubs are needed.  */ | 
 |   HOWTO (R_AVR_HI8_LDI_GS,	/* type */ | 
 | 	 9,			/* rightshift */ | 
 | 	 1,			/* 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_HI8_LDI_GS",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* 8 bit offset.  */ | 
 |   HOWTO (R_AVR_8,		/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 0,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 8,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_bitfield,/* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc,	/* special_function */ | 
 | 	 "R_AVR_8",		/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 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 */ | 
 |   HOWTO (R_AVR_DIFF8,		/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 0,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 8,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_bitfield, /* complain_on_overflow */ | 
 | 	 bfd_elf_avr_diff_reloc, /* special_function */ | 
 | 	 "R_AVR_DIFF8",		/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0,			/* src_mask */ | 
 | 	 0xff,			/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   HOWTO (R_AVR_DIFF16,		/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 1,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 16,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_bitfield, /* complain_on_overflow */ | 
 | 	 bfd_elf_avr_diff_reloc,/* special_function */ | 
 | 	 "R_AVR_DIFF16",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0,			/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   HOWTO (R_AVR_DIFF32,		/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 2,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 32,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_bitfield, /* complain_on_overflow */ | 
 | 	 bfd_elf_avr_diff_reloc,/* special_function */ | 
 | 	 "R_AVR_DIFF32",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0,			/* src_mask */ | 
 | 	 0xffffffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   /* 7 bit immediate for LDS/STS in Tiny core.  */ | 
 |   HOWTO (R_AVR_LDS_STS_16,  /* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 1,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 7,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_dont,/* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc, /* special_function */ | 
 | 	 "R_AVR_LDS_STS_16",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffff,		/* src_mask */ | 
 | 	 0xffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |  | 
 |   HOWTO (R_AVR_PORT6,		/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 0,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 6,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_dont,/* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc,	/* special_function */ | 
 | 	 "R_AVR_PORT6",		/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffffff,		/* src_mask */ | 
 | 	 0xffffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |   HOWTO (R_AVR_PORT5,		/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 0,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 5,			/* bitsize */ | 
 | 	 false,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_dont,/* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc,	/* special_function */ | 
 | 	 "R_AVR_PORT5",		/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffffff,		/* src_mask */ | 
 | 	 0xffffff,		/* dst_mask */ | 
 | 	 false),		/* pcrel_offset */ | 
 |  | 
 |   /* A 32 bit PC relative relocation.  */ | 
 |   HOWTO (R_AVR_32_PCREL,	/* type */ | 
 | 	 0,			/* rightshift */ | 
 | 	 2,			/* size (0 = byte, 1 = short, 2 = long) */ | 
 | 	 32,			/* bitsize */ | 
 | 	 true,			/* pc_relative */ | 
 | 	 0,			/* bitpos */ | 
 | 	 complain_overflow_bitfield, /* complain_on_overflow */ | 
 | 	 bfd_elf_generic_reloc, /* special_function */ | 
 | 	 "R_AVR_32_PCREL",	/* name */ | 
 | 	 false,			/* partial_inplace */ | 
 | 	 0xffffffff,		/* src_mask */ | 
 | 	 0xffffffff,		/* dst_mask */ | 
 | 	 true),			/* pcrel_offset */ | 
 | }; | 
 |  | 
 | /* Map BFD reloc types to AVR ELF reloc types.  */ | 
 |  | 
 | struct avr_reloc_map | 
 | { | 
 |   bfd_reloc_code_real_type bfd_reloc_val; | 
 |   unsigned int elf_reloc_val; | 
 | }; | 
 |  | 
 | static const struct avr_reloc_map avr_reloc_map[] = | 
 | { | 
 |   { BFD_RELOC_NONE,		    R_AVR_NONE }, | 
 |   { BFD_RELOC_32,		    R_AVR_32 }, | 
 |   { BFD_RELOC_AVR_7_PCREL,	    R_AVR_7_PCREL }, | 
 |   { BFD_RELOC_AVR_13_PCREL,	    R_AVR_13_PCREL }, | 
 |   { BFD_RELOC_16,		    R_AVR_16 }, | 
 |   { BFD_RELOC_AVR_16_PM,	    R_AVR_16_PM }, | 
 |   { BFD_RELOC_AVR_LO8_LDI,	    R_AVR_LO8_LDI}, | 
 |   { BFD_RELOC_AVR_HI8_LDI,	    R_AVR_HI8_LDI }, | 
 |   { BFD_RELOC_AVR_HH8_LDI,	    R_AVR_HH8_LDI }, | 
 |   { BFD_RELOC_AVR_MS8_LDI,	    R_AVR_MS8_LDI }, | 
 |   { BFD_RELOC_AVR_LO8_LDI_NEG,	    R_AVR_LO8_LDI_NEG }, | 
 |   { BFD_RELOC_AVR_HI8_LDI_NEG,	    R_AVR_HI8_LDI_NEG }, | 
 |   { BFD_RELOC_AVR_HH8_LDI_NEG,	    R_AVR_HH8_LDI_NEG }, | 
 |   { BFD_RELOC_AVR_MS8_LDI_NEG,	    R_AVR_MS8_LDI_NEG }, | 
 |   { BFD_RELOC_AVR_LO8_LDI_PM,	    R_AVR_LO8_LDI_PM }, | 
 |   { BFD_RELOC_AVR_LO8_LDI_GS,	    R_AVR_LO8_LDI_GS }, | 
 |   { BFD_RELOC_AVR_HI8_LDI_PM,	    R_AVR_HI8_LDI_PM }, | 
 |   { BFD_RELOC_AVR_HI8_LDI_GS,	    R_AVR_HI8_LDI_GS }, | 
 |   { BFD_RELOC_AVR_HH8_LDI_PM,	    R_AVR_HH8_LDI_PM }, | 
 |   { BFD_RELOC_AVR_LO8_LDI_PM_NEG,   R_AVR_LO8_LDI_PM_NEG }, | 
 |   { BFD_RELOC_AVR_HI8_LDI_PM_NEG,   R_AVR_HI8_LDI_PM_NEG }, | 
 |   { BFD_RELOC_AVR_HH8_LDI_PM_NEG,   R_AVR_HH8_LDI_PM_NEG }, | 
 |   { BFD_RELOC_AVR_CALL,		    R_AVR_CALL }, | 
 |   { 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_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 }, | 
 |   { BFD_RELOC_AVR_DIFF8,	    R_AVR_DIFF8 }, | 
 |   { BFD_RELOC_AVR_DIFF16,	    R_AVR_DIFF16 }, | 
 |   { BFD_RELOC_AVR_DIFF32,	    R_AVR_DIFF32 }, | 
 |   { BFD_RELOC_AVR_LDS_STS_16,	    R_AVR_LDS_STS_16}, | 
 |   { BFD_RELOC_AVR_PORT6,	    R_AVR_PORT6}, | 
 |   { BFD_RELOC_AVR_PORT5,	    R_AVR_PORT5}, | 
 |   { BFD_RELOC_32_PCREL,		    R_AVR_32_PCREL} | 
 | }; | 
 |  | 
 | static const struct bfd_elf_special_section elf_avr_special_sections[] = | 
 | { | 
 |   { STRING_COMMA_LEN (".noinit"), 0, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE }, | 
 |   { NULL, 0,			  0, 0,		   0 } | 
 | }; | 
 |  | 
 | /* Meant to be filled one day with the wrap around address for the | 
 |    specific device.  I.e. should get the value 0x4000 for 16k devices, | 
 |    0x8000 for 32k devices and so on. | 
 |  | 
 |    We initialize it here with a value of 0x1000000 resulting in | 
 |    that we will never suggest a wrap-around jump during relaxation. | 
 |    The logic of the source code later on assumes that in | 
 |    avr_pc_wrap_around one single bit is set.  */ | 
 | static bfd_vma avr_pc_wrap_around = 0x10000000; | 
 |  | 
 | /* If this variable holds a value different from zero, the linker relaxation | 
 |    machine will try to optimize call/ret sequences by a single jump | 
 |    instruction. This option could be switched off by a linker switch.  */ | 
 | static int avr_replace_call_ret_sequences = 1; | 
 |  | 
 |  | 
 | /* Per-section relaxation related information for avr.  */ | 
 |  | 
 | struct avr_relax_info | 
 | { | 
 |   /* Track the avr property records that apply to this section.  */ | 
 |  | 
 |   struct | 
 |   { | 
 |     /* Number of records in the list.  */ | 
 |     unsigned count; | 
 |  | 
 |     /* How many records worth of space have we allocated.  */ | 
 |     unsigned allocated; | 
 |  | 
 |     /* The records, only COUNT records are initialised.  */ | 
 |     struct avr_property_record *items; | 
 |   } records; | 
 | }; | 
 |  | 
 | /* Per section data, specialised for avr.  */ | 
 |  | 
 | struct elf_avr_section_data | 
 | { | 
 |   /* The standard data must appear first.  */ | 
 |   struct bfd_elf_section_data elf; | 
 |  | 
 |   /* Relaxation related information.  */ | 
 |   struct avr_relax_info relax_info; | 
 | }; | 
 |  | 
 | /* Possibly initialise avr specific data for new section SEC from ABFD.  */ | 
 |  | 
 | static bool | 
 | elf_avr_new_section_hook (bfd *abfd, asection *sec) | 
 | { | 
 |   if (!sec->used_by_bfd) | 
 |     { | 
 |       struct elf_avr_section_data *sdata; | 
 |       size_t amt = sizeof (*sdata); | 
 |  | 
 |       sdata = bfd_zalloc (abfd, amt); | 
 |       if (sdata == NULL) | 
 | 	return false; | 
 |       sec->used_by_bfd = sdata; | 
 |     } | 
 |  | 
 |   return _bfd_elf_new_section_hook (abfd, sec); | 
 | } | 
 |  | 
 | /* Return a pointer to the relaxation information for SEC.  */ | 
 |  | 
 | static struct avr_relax_info * | 
 | get_avr_relax_info (asection *sec) | 
 | { | 
 |   struct elf_avr_section_data *section_data; | 
 |  | 
 |   /* No info available if no section or if it is an output section.  */ | 
 |   if (!sec || sec == sec->output_section) | 
 |     return NULL; | 
 |  | 
 |   section_data = (struct elf_avr_section_data *) elf_section_data (sec); | 
 |   return §ion_data->relax_info; | 
 | } | 
 |  | 
 | /* Initialise the per section relaxation information for SEC.  */ | 
 |  | 
 | static void | 
 | init_avr_relax_info (asection *sec) | 
 | { | 
 |   struct avr_relax_info *relax_info = get_avr_relax_info (sec); | 
 |  | 
 |   relax_info->records.count = 0; | 
 |   relax_info->records.allocated = 0; | 
 |   relax_info->records.items = NULL; | 
 | } | 
 |  | 
 | /* Initialize an entry in the stub hash table.  */ | 
 |  | 
 | static struct bfd_hash_entry * | 
 | stub_hash_newfunc (struct bfd_hash_entry *entry, | 
 | 		   struct bfd_hash_table *table, | 
 | 		   const char *string) | 
 | { | 
 |   /* Allocate the structure if it has not already been allocated by a | 
 |      subclass.  */ | 
 |   if (entry == NULL) | 
 |     { | 
 |       entry = bfd_hash_allocate (table, | 
 | 				 sizeof (struct elf32_avr_stub_hash_entry)); | 
 |       if (entry == NULL) | 
 | 	return entry; | 
 |     } | 
 |  | 
 |   /* Call the allocation method of the superclass.  */ | 
 |   entry = bfd_hash_newfunc (entry, table, string); | 
 |   if (entry != NULL) | 
 |     { | 
 |       struct elf32_avr_stub_hash_entry *hsh; | 
 |  | 
 |       /* Initialize the local fields.  */ | 
 |       hsh = avr_stub_hash_entry (entry); | 
 |       hsh->stub_offset = 0; | 
 |       hsh->target_value = 0; | 
 |     } | 
 |  | 
 |   return entry; | 
 | } | 
 |  | 
 | /* This function is just a straight passthrough to the real | 
 |    function in linker.c.  Its prupose is so that its address | 
 |    can be compared inside the avr_link_hash_table macro.  */ | 
 |  | 
 | static struct bfd_hash_entry * | 
 | elf32_avr_link_hash_newfunc (struct bfd_hash_entry * entry, | 
 | 			     struct bfd_hash_table * table, | 
 | 			     const char * string) | 
 | { | 
 |   return _bfd_elf_link_hash_newfunc (entry, table, string); | 
 | } | 
 |  | 
 | /* Free the derived linker hash table.  */ | 
 |  | 
 | static void | 
 | elf32_avr_link_hash_table_free (bfd *obfd) | 
 | { | 
 |   struct elf32_avr_link_hash_table *htab | 
 |     = (struct elf32_avr_link_hash_table *) obfd->link.hash; | 
 |  | 
 |   /* Free the address mapping table.  */ | 
 |   free (htab->amt_stub_offsets); | 
 |   free (htab->amt_destination_addr); | 
 |  | 
 |   bfd_hash_table_free (&htab->bstab); | 
 |   _bfd_elf_link_hash_table_free (obfd); | 
 | } | 
 |  | 
 | /* Create the derived linker hash table.  The AVR ELF port uses the derived | 
 |    hash table to keep information specific to the AVR ELF linker (without | 
 |    using static variables).  */ | 
 |  | 
 | static struct bfd_link_hash_table * | 
 | elf32_avr_link_hash_table_create (bfd *abfd) | 
 | { | 
 |   struct elf32_avr_link_hash_table *htab; | 
 |   size_t amt = sizeof (*htab); | 
 |  | 
 |   htab = bfd_zmalloc (amt); | 
 |   if (htab == NULL) | 
 |     return NULL; | 
 |  | 
 |   if (!_bfd_elf_link_hash_table_init (&htab->etab, abfd, | 
 | 				      elf32_avr_link_hash_newfunc, | 
 | 				      sizeof (struct elf_link_hash_entry), | 
 | 				      AVR_ELF_DATA)) | 
 |     { | 
 |       free (htab); | 
 |       return NULL; | 
 |     } | 
 |  | 
 |   /* Init the stub hash table too.  */ | 
 |   if (!bfd_hash_table_init (&htab->bstab, stub_hash_newfunc, | 
 | 			    sizeof (struct elf32_avr_stub_hash_entry))) | 
 |     { | 
 |       _bfd_elf_link_hash_table_free (abfd); | 
 |       return NULL; | 
 |     } | 
 |   htab->etab.root.hash_table_free = elf32_avr_link_hash_table_free; | 
 |  | 
 |   return &htab->etab.root; | 
 | } | 
 |  | 
 | /* Calculates the effective distance of a pc relative jump/call.  */ | 
 |  | 
 | static int | 
 | avr_relative_distance_considering_wrap_around (unsigned int distance) | 
 | { | 
 |   unsigned int wrap_around_mask = avr_pc_wrap_around - 1; | 
 |   int dist_with_wrap_around = distance & wrap_around_mask; | 
 |  | 
 |   if (dist_with_wrap_around >= ((int) (avr_pc_wrap_around >> 1))) | 
 |     dist_with_wrap_around -= avr_pc_wrap_around; | 
 |  | 
 |   return dist_with_wrap_around; | 
 | } | 
 |  | 
 |  | 
 | static reloc_howto_type * | 
 | bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, | 
 | 				 bfd_reloc_code_real_type code) | 
 | { | 
 |   unsigned int i; | 
 |  | 
 |   for (i = 0; | 
 |        i < sizeof (avr_reloc_map) / sizeof (struct avr_reloc_map); | 
 |        i++) | 
 |     if (avr_reloc_map[i].bfd_reloc_val == code) | 
 |       return &elf_avr_howto_table[avr_reloc_map[i].elf_reloc_val]; | 
 |  | 
 |   return NULL; | 
 | } | 
 |  | 
 | static reloc_howto_type * | 
 | bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, | 
 | 				 const char *r_name) | 
 | { | 
 |   unsigned int i; | 
 |  | 
 |   for (i = 0; | 
 |        i < sizeof (elf_avr_howto_table) / sizeof (elf_avr_howto_table[0]); | 
 |        i++) | 
 |     if (elf_avr_howto_table[i].name != NULL | 
 | 	&& strcasecmp (elf_avr_howto_table[i].name, r_name) == 0) | 
 |       return &elf_avr_howto_table[i]; | 
 |  | 
 |   return NULL; | 
 | } | 
 |  | 
 | /* Set the howto pointer for an AVR ELF reloc.  */ | 
 |  | 
 | static bool | 
 | avr_info_to_howto_rela (bfd *abfd, | 
 | 			arelent *cache_ptr, | 
 | 			Elf_Internal_Rela *dst) | 
 | { | 
 |   unsigned int r_type; | 
 |  | 
 |   r_type = ELF32_R_TYPE (dst->r_info); | 
 |   if (r_type >= (unsigned int) R_AVR_max) | 
 |     { | 
 |       /* xgettext:c-format */ | 
 |       _bfd_error_handler (_("%pB: unsupported relocation type %#x"), | 
 | 			  abfd, r_type); | 
 |       bfd_set_error (bfd_error_bad_value); | 
 |       return false; | 
 |     } | 
 |   cache_ptr->howto = &elf_avr_howto_table[r_type]; | 
 |   return true; | 
 | } | 
 |  | 
 | static bool | 
 | avr_stub_is_required_for_16_bit_reloc (bfd_vma relocation) | 
 | { | 
 |   return (relocation >= 0x020000); | 
 | } | 
 |  | 
 | /* Returns the address of the corresponding stub if there is one. | 
 |    Returns otherwise an address above 0x020000.  This function | 
 |    could also be used, if there is no knowledge on the section where | 
 |    the destination is found.  */ | 
 |  | 
 | static bfd_vma | 
 | avr_get_stub_addr (bfd_vma srel, | 
 | 		   struct elf32_avr_link_hash_table *htab) | 
 | { | 
 |   unsigned int sindex; | 
 |   bfd_vma stub_sec_addr = | 
 | 	      (htab->stub_sec->output_section->vma + | 
 | 	       htab->stub_sec->output_offset); | 
 |  | 
 |   for (sindex = 0; sindex < htab->amt_max_entry_cnt; sindex ++) | 
 |     if (htab->amt_destination_addr[sindex] == srel) | 
 |       return htab->amt_stub_offsets[sindex] + stub_sec_addr; | 
 |  | 
 |   /* Return an address that could not be reached by 16 bit relocs.  */ | 
 |   return 0x020000; | 
 | } | 
 |  | 
 | /* Perform a diff relocation. Nothing to do, as the difference value is already | 
 |    written into the section's contents. */ | 
 |  | 
 | static bfd_reloc_status_type | 
 | bfd_elf_avr_diff_reloc (bfd *abfd ATTRIBUTE_UNUSED, | 
 | 		      arelent *reloc_entry ATTRIBUTE_UNUSED, | 
 | 	      asymbol *symbol ATTRIBUTE_UNUSED, | 
 | 	      void *data ATTRIBUTE_UNUSED, | 
 | 	      asection *input_section ATTRIBUTE_UNUSED, | 
 | 	      bfd *output_bfd ATTRIBUTE_UNUSED, | 
 | 	      char **error_message ATTRIBUTE_UNUSED) | 
 | { | 
 |   return bfd_reloc_ok; | 
 | } | 
 |  | 
 |  | 
 | /* Perform a single relocation.  By default we use the standard BFD | 
 |    routines, but a few relocs, we have to do them ourselves.  */ | 
 |  | 
 | static bfd_reloc_status_type | 
 | avr_final_link_relocate (reloc_howto_type *		    howto, | 
 | 			 bfd *				    input_bfd, | 
 | 			 asection *			    input_section, | 
 | 			 bfd_byte *			    contents, | 
 | 			 Elf_Internal_Rela *		    rel, | 
 | 			 bfd_vma			    relocation, | 
 | 			 struct elf32_avr_link_hash_table * htab) | 
 | { | 
 |   bfd_reloc_status_type r = bfd_reloc_ok; | 
 |   bfd_vma x; | 
 |   bfd_signed_vma srel; | 
 |   bfd_signed_vma reloc_addr; | 
 |   bool use_stubs = false; | 
 |   /* Usually is 0, unless we are generating code for a bootloader.  */ | 
 |   bfd_signed_vma base_addr = htab->vector_base; | 
 |  | 
 |   /* Absolute addr of the reloc in the final excecutable.  */ | 
 |   reloc_addr = rel->r_offset + input_section->output_section->vma | 
 | 	       + input_section->output_offset; | 
 |  | 
 |   switch (howto->type) | 
 |     { | 
 |     case R_AVR_7_PCREL: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation; | 
 |       srel += rel->r_addend; | 
 |       srel -= rel->r_offset; | 
 |       srel -= 2;	/* Branch instructions add 2 to the PC...  */ | 
 |       srel -= (input_section->output_section->vma + | 
 | 	       input_section->output_offset); | 
 |  | 
 |       if (srel & 1) | 
 | 	return bfd_reloc_outofrange; | 
 |       if (srel > ((1 << 7) - 1) || (srel < - (1 << 7))) | 
 | 	return bfd_reloc_overflow; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xfc07) | (((srel >> 1) * 8) & 0x3f8); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_13_PCREL: | 
 |       contents   += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation; | 
 |       srel += rel->r_addend; | 
 |       srel -= rel->r_offset; | 
 |       srel -= 2;	/* Branch instructions add 2 to the PC...  */ | 
 |       srel -= (input_section->output_section->vma + | 
 | 	       input_section->output_offset); | 
 |  | 
 |       if (srel & 1) | 
 | 	return bfd_reloc_outofrange; | 
 |  | 
 |       srel = avr_relative_distance_considering_wrap_around (srel); | 
 |  | 
 |       /* AVR addresses commands as words.  */ | 
 |       srel >>= 1; | 
 |  | 
 |       /* Check for overflow.  */ | 
 |       if (srel < -2048 || srel > 2047) | 
 | 	{ | 
 | 	  /* Relative distance is too large.  */ | 
 |  | 
 | 	  /* Always apply WRAPAROUND for avr2, avr25, and avr4.  */ | 
 | 	  switch (bfd_get_mach (input_bfd)) | 
 | 	    { | 
 | 	    case bfd_mach_avr2: | 
 | 	    case bfd_mach_avr25: | 
 | 	    case bfd_mach_avr4: | 
 | 	      break; | 
 |  | 
 | 	    default: | 
 | 	      return bfd_reloc_overflow; | 
 | 	    } | 
 | 	} | 
 |  | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf000) | (srel & 0xfff); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_LO8_LDI: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_LDI: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       if (((srel > 0) && (srel & 0xffff) > 255) | 
 | 	  || ((srel < 0) && ((-srel) & 0xffff) > 128)) | 
 | 	/* Remove offset for data/eeprom section.  */ | 
 | 	return bfd_reloc_overflow; | 
 |  | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_6: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       if (((srel & 0xffff) > 63) || (srel < 0)) | 
 | 	/* Remove offset for data/eeprom section.  */ | 
 | 	return bfd_reloc_overflow; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xd3f8) | ((srel & 7) | ((srel & (3 << 3)) << 7) | 
 | 		       | ((srel & (1 << 5)) << 8)); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_6_ADIW: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       if (((srel & 0xffff) > 63) || (srel < 0)) | 
 | 	/* Remove offset for data/eeprom section.  */ | 
 | 	return bfd_reloc_overflow; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xff30) | (srel & 0xf) | ((srel & 0x30) << 2); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_HI8_LDI: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       srel = (srel >> 8) & 0xff; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_HH8_LDI: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       srel = (srel >> 16) & 0xff; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_MS8_LDI: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       srel = (srel >> 24) & 0xff; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_LO8_LDI_NEG: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       srel = -srel; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_HI8_LDI_NEG: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       srel = -srel; | 
 |       srel = (srel >> 8) & 0xff; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_HH8_LDI_NEG: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       srel = -srel; | 
 |       srel = (srel >> 16) & 0xff; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_MS8_LDI_NEG: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       srel = -srel; | 
 |       srel = (srel >> 24) & 0xff; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_LO8_LDI_GS: | 
 |       use_stubs = (!htab->no_stubs); | 
 |       /* Fall through.  */ | 
 |     case R_AVR_LO8_LDI_PM: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |  | 
 |       if (use_stubs | 
 | 	  && avr_stub_is_required_for_16_bit_reloc (srel - base_addr)) | 
 | 	{ | 
 | 	  bfd_vma old_srel = srel; | 
 |  | 
 | 	  /* We need to use the address of the stub instead.  */ | 
 | 	  srel = avr_get_stub_addr (srel, htab); | 
 | 	  if (debug_stubs) | 
 | 	    printf ("LD: Using jump stub (at 0x%x) with destination 0x%x for " | 
 | 		    "reloc at address 0x%x.\n", | 
 | 		    (unsigned int) srel, | 
 | 		    (unsigned int) old_srel, | 
 | 		    (unsigned int) reloc_addr); | 
 |  | 
 | 	  if (avr_stub_is_required_for_16_bit_reloc (srel - base_addr)) | 
 | 	    return bfd_reloc_outofrange; | 
 | 	} | 
 |  | 
 |       if (srel & 1) | 
 | 	return bfd_reloc_outofrange; | 
 |       srel = srel >> 1; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_HI8_LDI_GS: | 
 |       use_stubs = (!htab->no_stubs); | 
 |       /* Fall through.  */ | 
 |     case R_AVR_HI8_LDI_PM: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |  | 
 |       if (use_stubs | 
 | 	  && avr_stub_is_required_for_16_bit_reloc (srel - base_addr)) | 
 | 	{ | 
 | 	  bfd_vma old_srel = srel; | 
 |  | 
 | 	  /* We need to use the address of the stub instead.  */ | 
 | 	  srel = avr_get_stub_addr (srel, htab); | 
 | 	  if (debug_stubs) | 
 | 	    printf ("LD: Using jump stub (at 0x%x) with destination 0x%x for " | 
 | 		    "reloc at address 0x%x.\n", | 
 | 		    (unsigned int) srel, | 
 | 		    (unsigned int) old_srel, | 
 | 		    (unsigned int) reloc_addr); | 
 |  | 
 | 	  if (avr_stub_is_required_for_16_bit_reloc (srel - base_addr)) | 
 | 	    return bfd_reloc_outofrange; | 
 | 	} | 
 |  | 
 |       if (srel & 1) | 
 | 	return bfd_reloc_outofrange; | 
 |       srel = srel >> 1; | 
 |       srel = (srel >> 8) & 0xff; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_HH8_LDI_PM: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       if (srel & 1) | 
 | 	return bfd_reloc_outofrange; | 
 |       srel = srel >> 1; | 
 |       srel = (srel >> 16) & 0xff; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_LO8_LDI_PM_NEG: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       srel = -srel; | 
 |       if (srel & 1) | 
 | 	return bfd_reloc_outofrange; | 
 |       srel = srel >> 1; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_HI8_LDI_PM_NEG: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       srel = -srel; | 
 |       if (srel & 1) | 
 | 	return bfd_reloc_outofrange; | 
 |       srel = srel >> 1; | 
 |       srel = (srel >> 8) & 0xff; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_HH8_LDI_PM_NEG: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       srel = -srel; | 
 |       if (srel & 1) | 
 | 	return bfd_reloc_outofrange; | 
 |       srel = srel >> 1; | 
 |       srel = (srel >> 16) & 0xff; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_CALL: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       if (srel & 1) | 
 | 	return bfd_reloc_outofrange; | 
 |       srel = srel >> 1; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x |= ((srel & 0x10000) | ((srel << 3) & 0x1f00000)) >> 16; | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       bfd_put_16 (input_bfd, (bfd_vma) srel & 0xffff, contents+2); | 
 |       break; | 
 |  | 
 |     case R_AVR_16_PM: | 
 |       use_stubs = (!htab->no_stubs); | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |  | 
 |       if (use_stubs | 
 | 	  && avr_stub_is_required_for_16_bit_reloc (srel - base_addr)) | 
 | 	{ | 
 | 	  bfd_vma old_srel = srel; | 
 |  | 
 | 	  /* We need to use the address of the stub instead.  */ | 
 | 	  srel = avr_get_stub_addr (srel,htab); | 
 | 	  if (debug_stubs) | 
 | 	    printf ("LD: Using jump stub (at 0x%x) with destination 0x%x for " | 
 | 		    "reloc at address 0x%x.\n", | 
 | 		    (unsigned int) srel, | 
 | 		    (unsigned int) old_srel, | 
 | 		    (unsigned int) reloc_addr); | 
 |  | 
 | 	  if (avr_stub_is_required_for_16_bit_reloc (srel - base_addr)) | 
 | 	    return bfd_reloc_outofrange; | 
 | 	} | 
 |  | 
 |       if (srel & 1) | 
 | 	return bfd_reloc_outofrange; | 
 |       srel = srel >> 1; | 
 |       bfd_put_16 (input_bfd, (bfd_vma) srel &0x00ffff, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_DIFF8: | 
 |     case R_AVR_DIFF16: | 
 |     case R_AVR_DIFF32: | 
 |       /* Nothing to do here, as contents already contains the diff value. */ | 
 |       r = bfd_reloc_ok; | 
 |       break; | 
 |  | 
 |    case R_AVR_LDS_STS_16: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       if ((srel & 0xFFFF) < 0x40 || (srel & 0xFFFF) > 0xbf) | 
 | 	return bfd_reloc_outofrange; | 
 |       srel = srel & 0x7f; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x |= (srel & 0x0f) | ((srel & 0x30) << 5) | ((srel & 0x40) << 2); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_PORT6: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       if ((srel & 0xffff) > 0x3f) | 
 | 	return bfd_reloc_outofrange; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xf9f0) | ((srel & 0x30) << 5) | (srel & 0x0f); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     case R_AVR_PORT5: | 
 |       contents += rel->r_offset; | 
 |       srel = (bfd_signed_vma) relocation + rel->r_addend; | 
 |       if ((srel & 0xffff) > 0x1f) | 
 | 	return bfd_reloc_outofrange; | 
 |       x = bfd_get_16 (input_bfd, contents); | 
 |       x = (x & 0xff07) | ((srel & 0x1f) << 3); | 
 |       bfd_put_16 (input_bfd, x, contents); | 
 |       break; | 
 |  | 
 |     default: | 
 |       r = _bfd_final_link_relocate (howto, input_bfd, input_section, | 
 | 				    contents, rel->r_offset, | 
 | 				    relocation, rel->r_addend); | 
 |     } | 
 |  | 
 |   return r; | 
 | } | 
 |  | 
 | /* Relocate an AVR ELF section.  */ | 
 |  | 
 | static int | 
 | elf32_avr_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, | 
 | 			    struct bfd_link_info *info, | 
 | 			    bfd *input_bfd, | 
 | 			    asection *input_section, | 
 | 			    bfd_byte *contents, | 
 | 			    Elf_Internal_Rela *relocs, | 
 | 			    Elf_Internal_Sym *local_syms, | 
 | 			    asection **local_sections) | 
 | { | 
 |   Elf_Internal_Shdr *		symtab_hdr; | 
 |   struct elf_link_hash_entry ** sym_hashes; | 
 |   Elf_Internal_Rela *		rel; | 
 |   Elf_Internal_Rela *		relend; | 
 |   struct elf32_avr_link_hash_table * htab = avr_link_hash_table (info); | 
 |  | 
 |   if (htab == NULL) | 
 |     return false; | 
 |  | 
 |   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; | 
 |   sym_hashes = elf_sym_hashes (input_bfd); | 
 |   relend     = relocs + input_section->reloc_count; | 
 |  | 
 |   for (rel = relocs; rel < relend; rel ++) | 
 |     { | 
 |       reloc_howto_type *	   howto; | 
 |       unsigned long		   r_symndx; | 
 |       Elf_Internal_Sym *	   sym; | 
 |       asection *		   sec; | 
 |       struct elf_link_hash_entry * h; | 
 |       bfd_vma			   relocation; | 
 |       bfd_reloc_status_type	   r; | 
 |       const char *		   name; | 
 |       int			   r_type; | 
 |  | 
 |       r_type = ELF32_R_TYPE (rel->r_info); | 
 |       r_symndx = ELF32_R_SYM (rel->r_info); | 
 |       howto  = elf_avr_howto_table + r_type; | 
 |       h      = NULL; | 
 |       sym    = NULL; | 
 |       sec    = NULL; | 
 |  | 
 |       if (r_symndx < symtab_hdr->sh_info) | 
 | 	{ | 
 | 	  sym = local_syms + r_symndx; | 
 | 	  sec = local_sections [r_symndx]; | 
 | 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); | 
 |  | 
 | 	  name = bfd_elf_string_from_elf_section | 
 | 	    (input_bfd, symtab_hdr->sh_link, sym->st_name); | 
 | 	  name = name == NULL ? bfd_section_name (sec) : name; | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  bool unresolved_reloc, warned, ignored; | 
 |  | 
 | 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, | 
 | 				   r_symndx, symtab_hdr, sym_hashes, | 
 | 				   h, sec, relocation, | 
 | 				   unresolved_reloc, warned, ignored); | 
 |  | 
 | 	  name = h->root.root.string; | 
 | 	} | 
 |  | 
 |       if (sec != NULL && discarded_section (sec)) | 
 | 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, | 
 | 					 rel, 1, relend, howto, 0, contents); | 
 |  | 
 |       if (bfd_link_relocatable (info)) | 
 | 	continue; | 
 |  | 
 |       r = avr_final_link_relocate (howto, input_bfd, input_section, | 
 | 				   contents, rel, relocation, htab); | 
 |  | 
 |       if (r != bfd_reloc_ok) | 
 | 	{ | 
 | 	  const char * msg = (const char *) NULL; | 
 |  | 
 | 	  switch (r) | 
 | 	    { | 
 | 	    case bfd_reloc_overflow: | 
 | 	      (*info->callbacks->reloc_overflow) | 
 | 		(info, (h ? &h->root : NULL), name, howto->name, | 
 | 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset); | 
 | 	      break; | 
 |  | 
 | 	    case bfd_reloc_undefined: | 
 | 	      (*info->callbacks->undefined_symbol) | 
 | 		(info, name, input_bfd, input_section, rel->r_offset, true); | 
 | 	      break; | 
 |  | 
 | 	    case bfd_reloc_outofrange: | 
 | 	      msg = _("internal error: out of range error"); | 
 | 	      break; | 
 |  | 
 | 	    case bfd_reloc_notsupported: | 
 | 	      msg = _("internal error: unsupported relocation error"); | 
 | 	      break; | 
 |  | 
 | 	    case bfd_reloc_dangerous: | 
 | 	      msg = _("internal error: dangerous relocation"); | 
 | 	      break; | 
 |  | 
 | 	    default: | 
 | 	      msg = _("internal error: unknown error"); | 
 | 	      break; | 
 | 	    } | 
 |  | 
 | 	  if (msg) | 
 | 	    (*info->callbacks->warning) (info, msg, name, input_bfd, | 
 | 					 input_section, rel->r_offset); | 
 | 	} | 
 |     } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | /* The final processing done just before writing out a AVR ELF object | 
 |    file.  This gets the AVR architecture right based on the machine | 
 |    number.  */ | 
 |  | 
 | static bool | 
 | bfd_elf_avr_final_write_processing (bfd *abfd) | 
 | { | 
 |   unsigned long val; | 
 |  | 
 |   switch (bfd_get_mach (abfd)) | 
 |     { | 
 |     default: | 
 |     case bfd_mach_avr2: | 
 |       val = E_AVR_MACH_AVR2; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avr1: | 
 |       val = E_AVR_MACH_AVR1; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avr25: | 
 |       val = E_AVR_MACH_AVR25; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avr3: | 
 |       val = E_AVR_MACH_AVR3; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avr31: | 
 |       val = E_AVR_MACH_AVR31; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avr35: | 
 |       val = E_AVR_MACH_AVR35; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avr4: | 
 |       val = E_AVR_MACH_AVR4; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avr5: | 
 |       val = E_AVR_MACH_AVR5; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avr51: | 
 |       val = E_AVR_MACH_AVR51; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avr6: | 
 |       val = E_AVR_MACH_AVR6; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avrxmega1: | 
 |       val = E_AVR_MACH_XMEGA1; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avrxmega2: | 
 |       val = E_AVR_MACH_XMEGA2; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avrxmega3: | 
 |       val = E_AVR_MACH_XMEGA3; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avrxmega4: | 
 |       val = E_AVR_MACH_XMEGA4; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avrxmega5: | 
 |       val = E_AVR_MACH_XMEGA5; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avrxmega6: | 
 |       val = E_AVR_MACH_XMEGA6; | 
 |       break; | 
 |  | 
 |     case bfd_mach_avrxmega7: | 
 |       val = E_AVR_MACH_XMEGA7; | 
 |       break; | 
 |  | 
 |    case bfd_mach_avrtiny: | 
 |       val = E_AVR_MACH_AVRTINY; | 
 |       break; | 
 |     } | 
 |  | 
 |   elf_elfheader (abfd)->e_machine = EM_AVR; | 
 |   elf_elfheader (abfd)->e_flags &= ~ EF_AVR_MACH; | 
 |   elf_elfheader (abfd)->e_flags |= val; | 
 |   return _bfd_elf_final_write_processing (abfd); | 
 | } | 
 |  | 
 | /* Set the right machine number.  */ | 
 |  | 
 | static bool | 
 | elf32_avr_object_p (bfd *abfd) | 
 | { | 
 |   unsigned int e_set = bfd_mach_avr2; | 
 |  | 
 |   if (elf_elfheader (abfd)->e_machine == EM_AVR | 
 |       || elf_elfheader (abfd)->e_machine == EM_AVR_OLD) | 
 |     { | 
 |       int e_mach = elf_elfheader (abfd)->e_flags & EF_AVR_MACH; | 
 |  | 
 |       switch (e_mach) | 
 | 	{ | 
 | 	default: | 
 | 	case E_AVR_MACH_AVR2: | 
 | 	  e_set = bfd_mach_avr2; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_AVR1: | 
 | 	  e_set = bfd_mach_avr1; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_AVR25: | 
 | 	  e_set = bfd_mach_avr25; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_AVR3: | 
 | 	  e_set = bfd_mach_avr3; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_AVR31: | 
 | 	  e_set = bfd_mach_avr31; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_AVR35: | 
 | 	  e_set = bfd_mach_avr35; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_AVR4: | 
 | 	  e_set = bfd_mach_avr4; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_AVR5: | 
 | 	  e_set = bfd_mach_avr5; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_AVR51: | 
 | 	  e_set = bfd_mach_avr51; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_AVR6: | 
 | 	  e_set = bfd_mach_avr6; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_XMEGA1: | 
 | 	  e_set = bfd_mach_avrxmega1; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_XMEGA2: | 
 | 	  e_set = bfd_mach_avrxmega2; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_XMEGA3: | 
 | 	  e_set = bfd_mach_avrxmega3; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_XMEGA4: | 
 | 	  e_set = bfd_mach_avrxmega4; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_XMEGA5: | 
 | 	  e_set = bfd_mach_avrxmega5; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_XMEGA6: | 
 | 	  e_set = bfd_mach_avrxmega6; | 
 | 	  break; | 
 |  | 
 | 	case E_AVR_MACH_XMEGA7: | 
 | 	  e_set = bfd_mach_avrxmega7; | 
 | 	  break; | 
 |  | 
 |     case E_AVR_MACH_AVRTINY: | 
 |       e_set = bfd_mach_avrtiny; | 
 |       break; | 
 | 	} | 
 |     } | 
 |   return bfd_default_set_arch_mach (abfd, bfd_arch_avr, | 
 | 				    e_set); | 
 | } | 
 |  | 
 | /* Returns whether the relocation type passed is a diff reloc. */ | 
 |  | 
 | static bool | 
 | elf32_avr_is_diff_reloc (Elf_Internal_Rela *irel) | 
 | { | 
 |   return (ELF32_R_TYPE (irel->r_info) == R_AVR_DIFF8 | 
 | 	  ||ELF32_R_TYPE (irel->r_info) == R_AVR_DIFF16 | 
 | 	  || ELF32_R_TYPE (irel->r_info) == R_AVR_DIFF32); | 
 | } | 
 |  | 
 | /* Reduce the diff value written in the section by count if the shrinked | 
 |    insn address happens to fall between the two symbols for which this | 
 |    diff reloc was emitted.  */ | 
 |  | 
 | static void | 
 | elf32_avr_adjust_diff_reloc_value (bfd *abfd, | 
 | 				   struct bfd_section *isec, | 
 | 				   Elf_Internal_Rela *irel, | 
 | 				   bfd_vma symval, | 
 | 				   bfd_vma shrinked_insn_address, | 
 | 				   int count) | 
 | { | 
 |   unsigned char *reloc_contents = NULL; | 
 |   unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents; | 
 |   if (isec_contents == NULL) | 
 |   { | 
 |     if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents)) | 
 |       return; | 
 |  | 
 |     elf_section_data (isec)->this_hdr.contents = isec_contents; | 
 |   } | 
 |  | 
 |   reloc_contents = isec_contents + irel->r_offset; | 
 |  | 
 |   /* Read value written in object file. */ | 
 |   bfd_signed_vma x = 0; | 
 |   switch (ELF32_R_TYPE (irel->r_info)) | 
 |   { | 
 |   case R_AVR_DIFF8: | 
 |     { | 
 |       x = bfd_get_signed_8 (abfd, reloc_contents); | 
 |       break; | 
 |     } | 
 |   case R_AVR_DIFF16: | 
 |     { | 
 |       x = bfd_get_signed_16 (abfd, reloc_contents); | 
 |       break; | 
 |     } | 
 |   case R_AVR_DIFF32: | 
 |     { | 
 |       x = bfd_get_signed_32 (abfd, reloc_contents); | 
 |       break; | 
 |     } | 
 |   default: | 
 |     { | 
 |       BFD_FAIL(); | 
 |     } | 
 |   } | 
 |  | 
 |   /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written | 
 |      into the object file at the reloc offset. sym2's logical value is | 
 |      symval (<start_of_section>) + reloc addend. Compute the start and end | 
 |      addresses and check if the shrinked insn falls between sym1 and sym2. */ | 
 |  | 
 |   bfd_vma sym2_address = symval + irel->r_addend; | 
 |   bfd_vma sym1_address = sym2_address - x; | 
 |  | 
 |   /* Don't assume sym2 is bigger than sym1 - the difference | 
 |      could be negative. Compute start and end addresses, and | 
 |      use those to see if they span shrinked_insn_address. */ | 
 |  | 
 |   bfd_vma start_address = sym1_address < sym2_address | 
 |     ? sym1_address : sym2_address; | 
 |   bfd_vma end_address = sym1_address > sym2_address | 
 |     ? sym1_address : sym2_address; | 
 |  | 
 |  | 
 |   if (shrinked_insn_address >= start_address | 
 |       && shrinked_insn_address < end_address) | 
 |   { | 
 |     /* Reduce the diff value by count bytes and write it back into section | 
 |        contents. */ | 
 |     bfd_signed_vma new_diff = x < 0 ? x + count : x - count; | 
 |  | 
 |     if (sym2_address > shrinked_insn_address) | 
 |       irel->r_addend -= count; | 
 |  | 
 |     switch (ELF32_R_TYPE (irel->r_info)) | 
 |     { | 
 |     case R_AVR_DIFF8: | 
 |       { | 
 | 	bfd_put_signed_8 (abfd, new_diff, reloc_contents); | 
 | 	break; | 
 |       } | 
 |     case R_AVR_DIFF16: | 
 |       { | 
 | 	bfd_put_signed_16 (abfd, new_diff & 0xFFFF, reloc_contents); | 
 | 	break; | 
 |       } | 
 |     case R_AVR_DIFF32: | 
 |       { | 
 | 	bfd_put_signed_32 (abfd, new_diff & 0xFFFFFFFF, reloc_contents); | 
 | 	break; | 
 |       } | 
 |     default: | 
 |       { | 
 | 	BFD_FAIL(); | 
 |       } | 
 |     } | 
 |  | 
 |   } | 
 | } | 
 |  | 
 | static void | 
 | elf32_avr_adjust_reloc_if_spans_insn (bfd *abfd, | 
 | 				      asection *isec, | 
 | 				      Elf_Internal_Rela *irel,  bfd_vma symval, | 
 | 				      bfd_vma shrinked_insn_address, | 
 | 				      bfd_vma shrink_boundary, | 
 | 				      int count) | 
 | { | 
 |  | 
 |   if (elf32_avr_is_diff_reloc (irel)) | 
 |     { | 
 |       elf32_avr_adjust_diff_reloc_value (abfd, isec, irel, | 
 | 					 symval, | 
 | 					 shrinked_insn_address, | 
 | 					 count); | 
 |     } | 
 |   else | 
 |     { | 
 |       bfd_vma reloc_value = symval + irel->r_addend; | 
 |       bool addend_within_shrink_boundary = reloc_value <= shrink_boundary; | 
 |  | 
 |       bool reloc_spans_insn = | 
 | 	(symval <= shrinked_insn_address | 
 | 	 && reloc_value > shrinked_insn_address | 
 | 	 && addend_within_shrink_boundary); | 
 |  | 
 |       if (! reloc_spans_insn) | 
 | 	return; | 
 |  | 
 |       irel->r_addend -= count; | 
 |  | 
 |       if (debug_relax) | 
 | 	printf ("Relocation's addend needed to be fixed \n"); | 
 |     } | 
 | } | 
 |  | 
 | static bool | 
 | avr_should_move_sym (symvalue symval, | 
 | 		     bfd_vma start, | 
 | 		     bfd_vma end, | 
 | 		     bool did_pad) | 
 | { | 
 |   bool sym_within_boundary = did_pad ? symval < end : symval <= end; | 
 |   return (symval > start && sym_within_boundary); | 
 | } | 
 |  | 
 | static bool | 
 | avr_should_reduce_sym_size (symvalue symval, | 
 | 			    symvalue symend, | 
 | 			    bfd_vma start, | 
 | 			    bfd_vma end, | 
 | 			    bool did_pad) | 
 | { | 
 |   bool sym_end_within_boundary = did_pad ? symend < end : symend <= end; | 
 |   return (symval <= start && symend > start && sym_end_within_boundary); | 
 | } | 
 |  | 
 | static bool | 
 | avr_should_increase_sym_size (symvalue symval, | 
 | 			      symvalue symend, | 
 | 			      bfd_vma start, | 
 | 			      bfd_vma end, | 
 | 			      bool did_pad) | 
 | { | 
 |   return (avr_should_move_sym (symval, start, end, did_pad) | 
 | 	  && symend >= end && did_pad); | 
 | } | 
 |  | 
 | /* Delete some bytes from a section while changing the size of an instruction. | 
 |    The parameter "addr" denotes the section-relative offset pointing just | 
 |    behind the shrinked instruction. "addr+count" point at the first | 
 |    byte just behind the original unshrinked instruction. If delete_shrinks_insn | 
 |    is FALSE, we are deleting redundant padding bytes from relax_info prop | 
 |    record handling. In that case, addr is section-relative offset of start | 
 |    of padding, and count is the number of padding bytes to delete. */ | 
 |  | 
 | static bool | 
 | elf32_avr_relax_delete_bytes (bfd *abfd, | 
 | 			      asection *sec, | 
 | 			      bfd_vma addr, | 
 | 			      int count, | 
 | 			      bool delete_shrinks_insn) | 
 | { | 
 |   Elf_Internal_Shdr *symtab_hdr; | 
 |   unsigned int sec_shndx; | 
 |   bfd_byte *contents; | 
 |   Elf_Internal_Rela *irel, *irelend; | 
 |   Elf_Internal_Sym *isym; | 
 |   Elf_Internal_Sym *isymbuf = NULL; | 
 |   bfd_vma toaddr; | 
 |   struct elf_link_hash_entry **sym_hashes; | 
 |   struct elf_link_hash_entry **end_hashes; | 
 |   unsigned int symcount; | 
 |   struct avr_relax_info *relax_info; | 
 |   struct avr_property_record *prop_record = NULL; | 
 |   bool did_shrink = false; | 
 |   bool did_pad = false; | 
 |  | 
 |   symtab_hdr = &elf_tdata (abfd)->symtab_hdr; | 
 |   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); | 
 |   contents = elf_section_data (sec)->this_hdr.contents; | 
 |   relax_info = get_avr_relax_info (sec); | 
 |  | 
 |   toaddr = sec->size; | 
 |  | 
 |   if (relax_info->records.count > 0) | 
 |     { | 
 |       /* There should be no property record within the range of deleted | 
 | 	 bytes, however, there might be a property record for ADDR, this is | 
 | 	 how we handle alignment directives. | 
 | 	 Find the next (if any) property record after the deleted bytes.  */ | 
 |       unsigned int i; | 
 |  | 
 |       for (i = 0; i < relax_info->records.count; ++i) | 
 | 	{ | 
 | 	  bfd_vma offset = relax_info->records.items [i].offset; | 
 |  | 
 | 	  BFD_ASSERT (offset <= addr || offset >= (addr + count)); | 
 | 	  if (offset >= (addr + count)) | 
 | 	    { | 
 | 	      prop_record = &relax_info->records.items [i]; | 
 | 	      toaddr = offset; | 
 | 	      break; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   irel = elf_section_data (sec)->relocs; | 
 |   irelend = irel + sec->reloc_count; | 
 |  | 
 |   /* Actually delete the bytes.  */ | 
 |   if (toaddr - addr - count > 0) | 
 |     { | 
 |       memmove (contents + addr, contents + addr + count, | 
 | 	       (size_t) (toaddr - addr - count)); | 
 |       did_shrink = true; | 
 |     } | 
 |   if (prop_record == NULL) | 
 |     { | 
 |       sec->size -= count; | 
 |       did_shrink = true; | 
 |     } | 
 |   else | 
 |     { | 
 |       /* Use the property record to fill in the bytes we've opened up.  */ | 
 |       int fill = 0; | 
 |       switch (prop_record->type) | 
 | 	{ | 
 | 	case RECORD_ORG_AND_FILL: | 
 | 	  fill = prop_record->data.org.fill; | 
 | 	  /* Fall through.  */ | 
 | 	case RECORD_ORG: | 
 | 	  break; | 
 | 	case RECORD_ALIGN_AND_FILL: | 
 | 	  fill = prop_record->data.align.fill; | 
 | 	  /* Fall through.  */ | 
 | 	case RECORD_ALIGN: | 
 | 	  prop_record->data.align.preceding_deleted += count; | 
 | 	  break; | 
 | 	}; | 
 |       /* If toaddr == (addr + count), then we didn't delete anything, yet | 
 | 	 we fill count bytes backwards from toaddr. This is still ok - we | 
 | 	 end up overwriting the bytes we would have deleted. We just need | 
 | 	 to remember we didn't delete anything i.e. don't set did_shrink, | 
 | 	 so that we don't corrupt reloc offsets or symbol values.*/ | 
 |       memset (contents + toaddr - count, fill, count); | 
 |       did_pad = true; | 
 |     } | 
 |  | 
 |   if (!did_shrink) | 
 |     return true; | 
 |  | 
 |   /* Adjust all the reloc addresses.  */ | 
 |   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) | 
 |     { | 
 |       bfd_vma old_reloc_address; | 
 |  | 
 |       old_reloc_address = (sec->output_section->vma | 
 | 			   + sec->output_offset + irel->r_offset); | 
 |  | 
 |       /* Get the new reloc address.  */ | 
 |       if ((irel->r_offset > addr | 
 | 	   && irel->r_offset < toaddr)) | 
 | 	{ | 
 | 	  if (debug_relax) | 
 | 	    printf ("Relocation at address 0x%x needs to be moved.\n" | 
 | 		    "Old section offset: 0x%x, New section offset: 0x%x \n", | 
 | 		    (unsigned int) old_reloc_address, | 
 | 		    (unsigned int) irel->r_offset, | 
 | 		    (unsigned int) ((irel->r_offset) - count)); | 
 |  | 
 | 	  irel->r_offset -= count; | 
 | 	} | 
 |  | 
 |     } | 
 |  | 
 |    /* The reloc's own addresses are now ok. However, we need to readjust | 
 |       the reloc's addend, i.e. the reloc's value if two conditions are met: | 
 |       1.) the reloc is relative to a symbol in this section that | 
 | 	  is located in front of the shrinked instruction | 
 |       2.) symbol plus addend end up behind the shrinked instruction. | 
 |  | 
 |       The most common case where this happens are relocs relative to | 
 |       the section-start symbol. | 
 |  | 
 |       This step needs to be done for all of the sections of the bfd.  */ | 
 |  | 
 |   { | 
 |     struct bfd_section *isec; | 
 |  | 
 |     for (isec = abfd->sections; isec; isec = isec->next) | 
 |      { | 
 |        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); | 
 |        if (delete_shrinks_insn) | 
 | 	 shrinked_insn_address -= count; | 
 |  | 
 |        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++) | 
 | 	 { | 
 | 	   /* Read this BFD's local symbols if we haven't done | 
 | 	      so already.  */ | 
 | 	   if (isymbuf == NULL && symtab_hdr->sh_info != 0) | 
 | 	     { | 
 | 	       isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; | 
 | 	       if (isymbuf == NULL) | 
 | 		 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, | 
 | 						 symtab_hdr->sh_info, 0, | 
 | 						 NULL, NULL, NULL); | 
 | 	       if (isymbuf == NULL) | 
 | 		 return false; | 
 | 	     } | 
 |  | 
 | 	   /* Get the value of the symbol referred to by the reloc.  */ | 
 | 	   if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) | 
 | 	     { | 
 | 	       /* A local symbol.  */ | 
 | 	       asection *sym_sec; | 
 |  | 
 | 	       isym = isymbuf + ELF32_R_SYM (irel->r_info); | 
 | 	       sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); | 
 | 	       symval = isym->st_value; | 
 | 	       /* If the reloc is absolute, it will not have | 
 | 		  a symbol or section associated with it.  */ | 
 | 	       if (sym_sec == sec) | 
 | 		 { | 
 | 		   /* If there is an alignment boundary, we only need to | 
 | 		      adjust addends that end up below the boundary. */ | 
 | 		   bfd_vma shrink_boundary = (toaddr | 
 | 					      + sec->output_section->vma | 
 | 					      + sec->output_offset); | 
 |  | 
 | 		   symval += sym_sec->output_section->vma | 
 | 			     + sym_sec->output_offset; | 
 |  | 
 | 		   if (debug_relax) | 
 | 		     printf ("Checking if the relocation's " | 
 | 			     "addend needs corrections.\n" | 
 | 			     "Address of anchor symbol: 0x%x \n" | 
 | 			     "Address of relocation target: 0x%x \n" | 
 | 			     "Address of relaxed insn: 0x%x \n", | 
 | 			     (unsigned int) symval, | 
 | 			     (unsigned int) (symval + irel->r_addend), | 
 | 			     (unsigned int) shrinked_insn_address); | 
 |  | 
 | 		   elf32_avr_adjust_reloc_if_spans_insn (abfd, isec, irel, | 
 | 							 symval, | 
 | 							 shrinked_insn_address, | 
 | 							 shrink_boundary, | 
 | 							 count); | 
 | 		 } | 
 | 	       /* else...Reference symbol is absolute.  No adjustment needed.  */ | 
 | 	     } | 
 | 	   /* else...Reference symbol is extern.  No need for adjusting | 
 | 	      the addend.  */ | 
 | 	 } | 
 |      } | 
 |   } | 
 |  | 
 |   /* Adjust the local symbols defined in this section.  */ | 
 |   isym = (Elf_Internal_Sym *) symtab_hdr->contents; | 
 |   /* Fix PR 9841, there may be no local symbols.  */ | 
 |   if (isym != NULL) | 
 |     { | 
 |       Elf_Internal_Sym *isymend; | 
 |  | 
 |       isymend = isym + symtab_hdr->sh_info; | 
 |       for (; isym < isymend; isym++) | 
 | 	{ | 
 | 	  if (isym->st_shndx == sec_shndx) | 
 | 	    { | 
 | 	      symvalue symval = isym->st_value; | 
 | 	      symvalue symend = symval + isym->st_size; | 
 | 	      if (avr_should_reduce_sym_size (symval, symend, | 
 | 				      addr, toaddr, did_pad)) | 
 | 		{ | 
 | 		  /* If this assert fires then we have a symbol that ends | 
 | 		     part way through an instruction.  Does that make | 
 | 		     sense?  */ | 
 | 		  BFD_ASSERT (isym->st_value + isym->st_size >= addr + count); | 
 | 		  isym->st_size -= count; | 
 | 		} | 
 | 	      else if (avr_should_increase_sym_size (symval, symend, | 
 | 				      addr, toaddr, did_pad)) | 
 | 		isym->st_size += count; | 
 |  | 
 | 	      if (avr_should_move_sym (symval, addr, toaddr, did_pad)) | 
 | 		isym->st_value -= count; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   /* Now adjust the global symbols defined in this section.  */ | 
 |   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) | 
 | 	      - symtab_hdr->sh_info); | 
 |   sym_hashes = elf_sym_hashes (abfd); | 
 |   end_hashes = sym_hashes + symcount; | 
 |   for (; sym_hashes < end_hashes; sym_hashes++) | 
 |     { | 
 |       struct elf_link_hash_entry *sym_hash = *sym_hashes; | 
 |       if ((sym_hash->root.type == bfd_link_hash_defined | 
 | 	   || sym_hash->root.type == bfd_link_hash_defweak) | 
 | 	  && sym_hash->root.u.def.section == sec) | 
 | 	{ | 
 | 	  symvalue symval = sym_hash->root.u.def.value; | 
 | 	  symvalue symend = symval + sym_hash->size; | 
 |  | 
 | 	  if (avr_should_reduce_sym_size (symval, symend, | 
 | 				  addr, toaddr, did_pad)) | 
 | 	    { | 
 | 	      /* If this assert fires then we have a symbol that ends | 
 | 		 part way through an instruction.  Does that make | 
 | 		 sense?  */ | 
 | 	      BFD_ASSERT (symend >= addr + count); | 
 | 	      sym_hash->size -= count; | 
 | 	    } | 
 | 	  else if (avr_should_increase_sym_size (symval, symend, | 
 | 				  addr, toaddr, did_pad)) | 
 | 	      sym_hash->size += count; | 
 |  | 
 | 	  if (avr_should_move_sym (symval, addr, toaddr, did_pad)) | 
 | 	    sym_hash->root.u.def.value -= count; | 
 | 	} | 
 |     } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static Elf_Internal_Sym * | 
 | retrieve_local_syms (bfd *input_bfd) | 
 | { | 
 |   Elf_Internal_Shdr *symtab_hdr; | 
 |   Elf_Internal_Sym *isymbuf; | 
 |   size_t locsymcount; | 
 |  | 
 |   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; | 
 |   locsymcount = symtab_hdr->sh_info; | 
 |  | 
 |   isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; | 
 |   if (isymbuf == NULL && locsymcount != 0) | 
 |     isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0, | 
 | 				    NULL, NULL, NULL); | 
 |  | 
 |   /* Save the symbols for this input file so they won't be read again.  */ | 
 |   if (isymbuf && isymbuf != (Elf_Internal_Sym *) symtab_hdr->contents) | 
 |     symtab_hdr->contents = (unsigned char *) isymbuf; | 
 |  | 
 |   return isymbuf; | 
 | } | 
 |  | 
 | /* Get the input section for a given symbol index. | 
 |    If the symbol is: | 
 |    . a section symbol, return the section; | 
 |    . a common symbol, return the common section; | 
 |    . an undefined symbol, return the undefined section; | 
 |    . an indirect symbol, follow the links; | 
 |    . an absolute value, return the absolute section.  */ | 
 |  | 
 | static asection * | 
 | get_elf_r_symndx_section (bfd *abfd, unsigned long r_symndx) | 
 | { | 
 |   Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr; | 
 |   asection *target_sec = NULL; | 
 |   if (r_symndx < symtab_hdr->sh_info) | 
 |     { | 
 |       Elf_Internal_Sym *isymbuf; | 
 |       unsigned int section_index; | 
 |  | 
 |       isymbuf = retrieve_local_syms (abfd); | 
 |       section_index = isymbuf[r_symndx].st_shndx; | 
 |  | 
 |       if (section_index == SHN_UNDEF) | 
 | 	target_sec = bfd_und_section_ptr; | 
 |       else if (section_index == SHN_ABS) | 
 | 	target_sec = bfd_abs_section_ptr; | 
 |       else if (section_index == SHN_COMMON) | 
 | 	target_sec = bfd_com_section_ptr; | 
 |       else | 
 | 	target_sec = bfd_section_from_elf_index (abfd, section_index); | 
 |     } | 
 |   else | 
 |     { | 
 |       unsigned long indx = r_symndx - symtab_hdr->sh_info; | 
 |       struct elf_link_hash_entry *h = elf_sym_hashes (abfd)[indx]; | 
 |  | 
 |       while (h->root.type == bfd_link_hash_indirect | 
 | 	     || h->root.type == bfd_link_hash_warning) | 
 | 	h = (struct elf_link_hash_entry *) h->root.u.i.link; | 
 |  | 
 |       switch (h->root.type) | 
 | 	{ | 
 | 	case bfd_link_hash_defined: | 
 | 	case  bfd_link_hash_defweak: | 
 | 	  target_sec = h->root.u.def.section; | 
 | 	  break; | 
 | 	case bfd_link_hash_common: | 
 | 	  target_sec = bfd_com_section_ptr; | 
 | 	  break; | 
 | 	case bfd_link_hash_undefined: | 
 | 	case bfd_link_hash_undefweak: | 
 | 	  target_sec = bfd_und_section_ptr; | 
 | 	  break; | 
 | 	default: /* New indirect warning.  */ | 
 | 	  target_sec = bfd_und_section_ptr; | 
 | 	  break; | 
 | 	} | 
 |     } | 
 |   return target_sec; | 
 | } | 
 |  | 
 | /* Get the section-relative offset for a symbol number.  */ | 
 |  | 
 | static bfd_vma | 
 | get_elf_r_symndx_offset (bfd *abfd, unsigned long r_symndx) | 
 | { | 
 |   Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr; | 
 |   bfd_vma offset = 0; | 
 |  | 
 |   if (r_symndx < symtab_hdr->sh_info) | 
 |     { | 
 |       Elf_Internal_Sym *isymbuf; | 
 |       isymbuf = retrieve_local_syms (abfd); | 
 |       offset = isymbuf[r_symndx].st_value; | 
 |     } | 
 |   else | 
 |     { | 
 |       unsigned long indx = r_symndx - symtab_hdr->sh_info; | 
 |       struct elf_link_hash_entry *h = | 
 | 	elf_sym_hashes (abfd)[indx]; | 
 |  | 
 |       while (h->root.type == bfd_link_hash_indirect | 
 | 	     || h->root.type == bfd_link_hash_warning) | 
 | 	h = (struct elf_link_hash_entry *) h->root.u.i.link; | 
 |       if (h->root.type == bfd_link_hash_defined | 
 | 	  || h->root.type == bfd_link_hash_defweak) | 
 | 	offset = h->root.u.def.value; | 
 |     } | 
 |   return offset; | 
 | } | 
 |  | 
 | /* Iterate over the property records in R_LIST, and copy each record into | 
 |    the list of records within the relaxation information for the section to | 
 |    which the record applies.  */ | 
 |  | 
 | static void | 
 | avr_elf32_assign_records_to_sections (struct avr_property_record_list *r_list) | 
 | { | 
 |   unsigned int i; | 
 |  | 
 |   for (i = 0; i < r_list->record_count; ++i) | 
 |     { | 
 |       struct avr_relax_info *relax_info; | 
 |  | 
 |       relax_info = get_avr_relax_info (r_list->records [i].section); | 
 |       BFD_ASSERT (relax_info != NULL); | 
 |  | 
 |       if (relax_info->records.count | 
 | 	  == relax_info->records.allocated) | 
 | 	{ | 
 | 	  /* Allocate more space.  */ | 
 | 	  bfd_size_type size; | 
 |  | 
 | 	  relax_info->records.allocated += 10; | 
 | 	  size = (sizeof (struct avr_property_record) | 
 | 		  * relax_info->records.allocated); | 
 | 	  relax_info->records.items | 
 | 	    = bfd_realloc (relax_info->records.items, size); | 
 | 	} | 
 |  | 
 |       memcpy (&relax_info->records.items [relax_info->records.count], | 
 | 	      &r_list->records [i], | 
 | 	      sizeof (struct avr_property_record)); | 
 |       relax_info->records.count++; | 
 |     } | 
 | } | 
 |  | 
 | /* Compare two STRUCT AVR_PROPERTY_RECORD in AP and BP, used as the | 
 |    ordering callback from QSORT.  */ | 
 |  | 
 | static int | 
 | avr_property_record_compare (const void *ap, const void *bp) | 
 | { | 
 |   const struct avr_property_record *a | 
 |     = (struct avr_property_record *) ap; | 
 |   const struct avr_property_record *b | 
 |     = (struct avr_property_record *) bp; | 
 |  | 
 |   if (a->offset != b->offset) | 
 |     return (a->offset - b->offset); | 
 |  | 
 |   if (a->section != b->section) | 
 |     return bfd_section_vma (a->section) - bfd_section_vma (b->section); | 
 |  | 
 |   return (a->type - b->type); | 
 | } | 
 |  | 
 | /* Load all of the avr property sections from all of the bfd objects | 
 |    referenced from LINK_INFO.  All of the records within each property | 
 |    section are assigned to the STRUCT AVR_RELAX_INFO within the section | 
 |    specific data of the appropriate section.  */ | 
 |  | 
 | static void | 
 | avr_load_all_property_sections (struct bfd_link_info *link_info) | 
 | { | 
 |   bfd *abfd; | 
 |   asection *sec; | 
 |  | 
 |   /* Initialize the per-section relaxation info.  */ | 
 |   for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link.next) | 
 |     for (sec = abfd->sections; sec != NULL; sec = sec->next) | 
 |       { | 
 | 	init_avr_relax_info (sec); | 
 |       } | 
 |  | 
 |   /* Load the descriptor tables from .avr.prop sections.  */ | 
 |   for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link.next) | 
 |     { | 
 |       struct avr_property_record_list *r_list; | 
 |  | 
 |       r_list = avr_elf32_load_property_records (abfd); | 
 |       if (r_list != NULL) | 
 | 	avr_elf32_assign_records_to_sections (r_list); | 
 |  | 
 |       free (r_list); | 
 |     } | 
 |  | 
 |   /* Now, for every section, ensure that the descriptor list in the | 
 |      relaxation data is sorted by ascending offset within the section.  */ | 
 |   for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link.next) | 
 |     for (sec = abfd->sections; sec != NULL; sec = sec->next) | 
 |       { | 
 | 	struct avr_relax_info *relax_info = get_avr_relax_info (sec); | 
 | 	if (relax_info && relax_info->records.count > 0) | 
 | 	  { | 
 | 	    unsigned int i; | 
 |  | 
 | 	    qsort (relax_info->records.items, | 
 | 		   relax_info->records.count, | 
 | 		   sizeof (struct avr_property_record), | 
 | 		   avr_property_record_compare); | 
 |  | 
 | 	    /* For debug purposes, list all the descriptors.  */ | 
 | 	    for (i = 0; i < relax_info->records.count; ++i) | 
 | 	      { | 
 | 		switch (relax_info->records.items [i].type) | 
 | 		  { | 
 | 		  case RECORD_ORG: | 
 | 		    break; | 
 | 		  case RECORD_ORG_AND_FILL: | 
 | 		    break; | 
 | 		  case RECORD_ALIGN: | 
 | 		    break; | 
 | 		  case RECORD_ALIGN_AND_FILL: | 
 | 		    break; | 
 | 		  }; | 
 | 	      } | 
 | 	  } | 
 |       } | 
 | } | 
 |  | 
 | /* This function handles relaxing for the avr. | 
 |    Many important relaxing opportunities within functions are already | 
 |    realized by the compiler itself. | 
 |    Here we try to replace  call (4 bytes) ->  rcall (2 bytes) | 
 |    and jump -> rjmp (safes also 2 bytes). | 
 |    As well we now optimize seqences of | 
 |      - call/rcall function | 
 |      - ret | 
 |    to yield | 
 |      - jmp/rjmp function | 
 |      - ret | 
 |    . In case that within a sequence | 
 |      - jmp/rjmp label | 
 |      - ret | 
 |    the ret could no longer be reached it is optimized away. In order | 
 |    to check if the ret is no longer needed, it is checked that the ret's address | 
 |    is not the target of a branch or jump within the same section, it is checked | 
 |    that there is no skip instruction before the jmp/rjmp and that there | 
 |    is no local or global label place at the address of the ret. | 
 |  | 
 |    We refrain from relaxing within sections ".vectors" and | 
 |    ".jumptables" in order to maintain the position of the instructions. | 
 |    There, however, we substitute jmp/call by a sequence rjmp,nop/rcall,nop | 
 |    if possible. (In future one could possibly use the space of the nop | 
 |    for the first instruction of the irq service function. | 
 |  | 
 |    The .jumptables sections is meant to be used for a future tablejump variant | 
 |    for the devices with 3-byte program counter where the table itself | 
 |    contains 4-byte jump instructions whose relative offset must not | 
 |    be changed.  */ | 
 |  | 
 | static bool | 
 | elf32_avr_relax_section (bfd *abfd, | 
 | 			 asection *sec, | 
 | 			 struct bfd_link_info *link_info, | 
 | 			 bool *again) | 
 | { | 
 |   Elf_Internal_Shdr *symtab_hdr; | 
 |   Elf_Internal_Rela *internal_relocs; | 
 |   Elf_Internal_Rela *irel, *irelend; | 
 |   bfd_byte *contents = NULL; | 
 |   Elf_Internal_Sym *isymbuf = NULL; | 
 |   struct elf32_avr_link_hash_table *htab; | 
 |   static bool relaxation_initialised = false; | 
 |  | 
 |   if (!relaxation_initialised) | 
 |     { | 
 |       relaxation_initialised = true; | 
 |  | 
 |       /* Load entries from the .avr.prop sections.  */ | 
 |       avr_load_all_property_sections (link_info); | 
 |     } | 
 |  | 
 |   /* 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. */ | 
 |   bool shrinkable = true; | 
 |  | 
 |   if (!strcmp (sec->name,".vectors") | 
 |       || !strcmp (sec->name,".jumptables")) | 
 |     shrinkable = false; | 
 |  | 
 |   if (bfd_link_relocatable (link_info)) | 
 |     (*link_info->callbacks->einfo) | 
 |       (_("%P%F: --relax and -r may not be used together\n")); | 
 |  | 
 |   htab = avr_link_hash_table (link_info); | 
 |   if (htab == NULL) | 
 |     return false; | 
 |  | 
 |   /* Assume nothing changes.  */ | 
 |   *again = false; | 
 |  | 
 |   if ((!htab->no_stubs) && (sec == htab->stub_sec)) | 
 |     { | 
 |       /* We are just relaxing the stub section. | 
 | 	 Let's calculate the size needed again.  */ | 
 |       bfd_size_type last_estimated_stub_section_size = htab->stub_sec->size; | 
 |  | 
 |       if (debug_relax) | 
 | 	printf ("Relaxing the stub section. Size prior to this pass: %i\n", | 
 | 		(int) last_estimated_stub_section_size); | 
 |  | 
 |       elf32_avr_size_stubs (htab->stub_sec->output_section->owner, | 
 | 			    link_info, false); | 
 |  | 
 |       /* Check if the number of trampolines changed.  */ | 
 |       if (last_estimated_stub_section_size != htab->stub_sec->size) | 
 | 	*again = true; | 
 |  | 
 |       if (debug_relax) | 
 | 	printf ("Size of stub section after this pass: %i\n", | 
 | 		(int) htab->stub_sec->size); | 
 |  | 
 |       return true; | 
 |     } | 
 |  | 
 |   /* We don't have to do anything for a relocatable link, if | 
 |      this section does not have relocs, or if this is not a | 
 |      code section.  */ | 
 |   if (bfd_link_relocatable (link_info) | 
 |       || (sec->flags & SEC_RELOC) == 0 | 
 |       || sec->reloc_count == 0 | 
 |       || (sec->flags & SEC_CODE) == 0) | 
 |     return true; | 
 |  | 
 |   /* Check if the object file to relax uses internal symbols so that we | 
 |      could fix up the relocations.  */ | 
 |   if (!(elf_elfheader (abfd)->e_flags & EF_AVR_LINKRELAX_PREPARED)) | 
 |     return true; | 
 |  | 
 |   symtab_hdr = &elf_tdata (abfd)->symtab_hdr; | 
 |  | 
 |   /* Get a copy of the native relocations.  */ | 
 |   internal_relocs = (_bfd_elf_link_read_relocs | 
 | 		     (abfd, sec, NULL, NULL, link_info->keep_memory)); | 
 |   if (internal_relocs == NULL) | 
 |     goto error_return; | 
 |  | 
 |   /* Walk through the relocs looking for relaxing opportunities.  */ | 
 |   irelend = internal_relocs + sec->reloc_count; | 
 |   for (irel = internal_relocs; irel < irelend; irel++) | 
 |     { | 
 |       bfd_vma symval; | 
 |  | 
 |       if (   ELF32_R_TYPE (irel->r_info) != R_AVR_13_PCREL | 
 | 	  && ELF32_R_TYPE (irel->r_info) != R_AVR_7_PCREL | 
 | 	  && ELF32_R_TYPE (irel->r_info) != R_AVR_CALL) | 
 | 	continue; | 
 |  | 
 |       /* Get the section contents if we haven't done so already.  */ | 
 |       if (contents == NULL) | 
 | 	{ | 
 | 	  /* Get cached copy if it exists.  */ | 
 | 	  if (elf_section_data (sec)->this_hdr.contents != NULL) | 
 | 	    contents = elf_section_data (sec)->this_hdr.contents; | 
 | 	  else | 
 | 	    { | 
 | 	      /* Go get them off disk.  */ | 
 | 	      if (! bfd_malloc_and_get_section (abfd, sec, &contents)) | 
 | 		goto error_return; | 
 | 	    } | 
 | 	} | 
 |  | 
 |       /* Read this BFD's local symbols if we haven't done so already.  */ | 
 |       if (isymbuf == NULL && symtab_hdr->sh_info != 0) | 
 | 	{ | 
 | 	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; | 
 | 	  if (isymbuf == NULL) | 
 | 	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, | 
 | 					    symtab_hdr->sh_info, 0, | 
 | 					    NULL, NULL, NULL); | 
 | 	  if (isymbuf == NULL) | 
 | 	    goto error_return; | 
 | 	} | 
 |  | 
 |  | 
 |       /* Get the value of the symbol referred to by the reloc.  */ | 
 |       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) | 
 | 	{ | 
 | 	  /* A local symbol.  */ | 
 | 	  Elf_Internal_Sym *isym; | 
 | 	  asection *sym_sec; | 
 |  | 
 | 	  isym = isymbuf + ELF32_R_SYM (irel->r_info); | 
 | 	  sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); | 
 | 	  symval = isym->st_value; | 
 | 	  /* If the reloc is absolute, it will not have | 
 | 	     a symbol or section associated with it.  */ | 
 | 	  if (sym_sec) | 
 | 	    symval += sym_sec->output_section->vma | 
 | 	      + sym_sec->output_offset; | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  unsigned long indx; | 
 | 	  struct elf_link_hash_entry *h; | 
 |  | 
 | 	  /* An external symbol.  */ | 
 | 	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; | 
 | 	  h = elf_sym_hashes (abfd)[indx]; | 
 | 	  BFD_ASSERT (h != NULL); | 
 | 	  if (h->root.type != bfd_link_hash_defined | 
 | 	      && h->root.type != bfd_link_hash_defweak) | 
 | 	    /* This appears to be a reference to an undefined | 
 | 	       symbol.  Just ignore it--it will be caught by the | 
 | 	       regular reloc processing.  */ | 
 | 	    continue; | 
 |  | 
 | 	  symval = (h->root.u.def.value | 
 | 		    + h->root.u.def.section->output_section->vma | 
 | 		    + h->root.u.def.section->output_offset); | 
 | 	} | 
 |  | 
 |       /* For simplicity of coding, we are going to modify the section | 
 | 	 contents, the section relocs, and the BFD symbol table.  We | 
 | 	 must tell the rest of the code not to free up this | 
 | 	 information.  It would be possible to instead create a table | 
 | 	 of changes which have to be made, as is done in coff-mips.c; | 
 | 	 that would be more work, but would require less memory when | 
 | 	 the linker is run.  */ | 
 |       switch (ELF32_R_TYPE (irel->r_info)) | 
 | 	{ | 
 | 	  /* Try to turn a 22-bit absolute call/jump into an 13-bit | 
 | 	     pc-relative rcall/rjmp.  */ | 
 | 	case R_AVR_CALL: | 
 | 	  { | 
 | 	    bfd_vma value = symval + irel->r_addend; | 
 | 	    bfd_vma dot, gap; | 
 | 	    int distance_short_enough = 0; | 
 |  | 
 | 	    /* Get the address of this instruction.  */ | 
 | 	    dot = (sec->output_section->vma | 
 | 		   + sec->output_offset + irel->r_offset); | 
 |  | 
 | 	    /* Compute the distance from this insn to the branch target.  */ | 
 | 	    gap = value - dot; | 
 |  | 
 | 	    /* The ISA manual states that addressable range is PC - 2k + 1 to | 
 | 	       PC + 2k. In bytes, that would be -4094 <= PC <= 4096. The range | 
 | 	       is shifted one word to the right, because pc-relative instructions | 
 | 	       implicitly add one word i.e. rjmp 0 jumps to next insn, not the | 
 | 	       current one. | 
 | 	       Therefore, for the !shrinkable case, the range is as above. | 
 | 	       If shrinkable, then the current code only deletes bytes 3 and | 
 | 	       4 of the absolute call/jmp, so the forward jump range increases | 
 | 	       by 2 bytes, but the backward (negative) jump range remains | 
 | 	       the same. */ | 
 |  | 
 |  | 
 | 	    /* 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 >= -4094 && (int) gap <= 4096)) | 
 | 	      distance_short_enough = 1; | 
 | 	    /* If shrinkable, then we can check for a range of distance which | 
 | 	       is two bytes farther on the positive direction because the call | 
 | 	       or jump target will be closer by two bytes after the | 
 | 	       relaxation. */ | 
 | 	    else if (shrinkable && ((int) gap >= -4094 && (int) gap <= 4098)) | 
 | 	      distance_short_enough = 1; | 
 |  | 
 | 	    /* Here we handle the wrap-around case.  E.g. for a 16k device | 
 | 	       we could use a rjmp to jump from address 0x100 to 0x3d00! | 
 | 	       In order to make this work properly, we need to fill the | 
 | 	       vaiable avr_pc_wrap_around with the appropriate value. | 
 | 	       I.e. 0x4000 for a 16k device.  */ | 
 | 	    { | 
 | 	      /* Shrinking the code size makes the gaps larger in the | 
 | 		 case of wrap-arounds.  So we use a heuristical safety | 
 | 		 margin to avoid that during relax the distance gets | 
 | 		 again too large for the short jumps.  Let's assume | 
 | 		 a typical code-size reduction due to relax for a | 
 | 		 16k device of 600 bytes.  So let's use twice the | 
 | 		 typical value as safety margin.  */ | 
 | 	      int rgap; | 
 | 	      int safety_margin; | 
 |  | 
 | 	      int assumed_shrink = 600; | 
 | 	      if (avr_pc_wrap_around > 0x4000) | 
 | 		assumed_shrink = 900; | 
 |  | 
 | 	      safety_margin = 2 * assumed_shrink; | 
 |  | 
 | 	      rgap = avr_relative_distance_considering_wrap_around (gap); | 
 |  | 
 | 	      if (rgap >= (-4092 + safety_margin) | 
 | 		  && rgap <= (4094 - safety_margin)) | 
 | 		distance_short_enough = 1; | 
 | 	    } | 
 |  | 
 | 	    if (distance_short_enough) | 
 | 	      { | 
 | 		unsigned char code_msb; | 
 | 		unsigned char code_lsb; | 
 |  | 
 | 		if (debug_relax) | 
 | 		  printf ("shrinking jump/call instruction at address 0x%x" | 
 | 			  " in section %s\n\n", | 
 | 			  (int) dot, sec->name); | 
 |  | 
 | 		/* 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; | 
 |  | 
 | 		/* Get the instruction code for relaxing.  */ | 
 | 		code_lsb = bfd_get_8 (abfd, contents + irel->r_offset); | 
 | 		code_msb = bfd_get_8 (abfd, contents + irel->r_offset + 1); | 
 |  | 
 | 		/* Mask out the relocation bits.  */ | 
 | 		code_msb &= 0x94; | 
 | 		code_lsb &= 0x0E; | 
 | 		if (code_msb == 0x94 && code_lsb == 0x0E) | 
 | 		  { | 
 | 		    /* we are changing call -> rcall .  */ | 
 | 		    bfd_put_8 (abfd, 0x00, contents + irel->r_offset); | 
 | 		    bfd_put_8 (abfd, 0xD0, contents + irel->r_offset + 1); | 
 | 		  } | 
 | 		else if (code_msb == 0x94 && code_lsb == 0x0C) | 
 | 		  { | 
 | 		    /* we are changeing jump -> rjmp.  */ | 
 | 		    bfd_put_8 (abfd, 0x00, contents + irel->r_offset); | 
 | 		    bfd_put_8 (abfd, 0xC0, contents + irel->r_offset + 1); | 
 | 		  } | 
 | 		else | 
 | 		  abort (); | 
 |  | 
 | 		/* Fix the relocation's type.  */ | 
 | 		irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), | 
 | 					     R_AVR_13_PCREL); | 
 |  | 
 | 		/* 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); | 
 | 		    bfd_put_8 (abfd, 0x00, contents + irel->r_offset + 3); | 
 | 		  } | 
 | 		else | 
 | 		  { | 
 | 		    /* Delete two bytes of data.  */ | 
 | 		    if (!elf32_avr_relax_delete_bytes (abfd, sec, | 
 | 						       irel->r_offset + 2, 2, | 
 | 						       true)) | 
 | 		      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; | 
 | 		  } | 
 | 	      } | 
 | 	  } | 
 | 	  /* Fall through.  */ | 
 |  | 
 | 	default: | 
 | 	  { | 
 | 	    unsigned char code_msb; | 
 | 	    unsigned char code_lsb; | 
 | 	    bfd_vma dot; | 
 |  | 
 | 	    code_msb = bfd_get_8 (abfd, contents + irel->r_offset + 1); | 
 | 	    code_lsb = bfd_get_8 (abfd, contents + irel->r_offset + 0); | 
 |  | 
 | 	    /* Get the address of this instruction.  */ | 
 | 	    dot = (sec->output_section->vma | 
 | 		   + sec->output_offset + irel->r_offset); | 
 |  | 
 | 	    /* Here we look for rcall/ret or call/ret sequences that could be | 
 | 	       safely replaced by rjmp/ret or jmp/ret.  */ | 
 | 	    if (((code_msb & 0xf0) == 0xd0) | 
 | 		&& avr_replace_call_ret_sequences) | 
 | 	      { | 
 | 		/* This insn is a rcall.  */ | 
 | 		unsigned char next_insn_msb = 0; | 
 | 		unsigned char next_insn_lsb = 0; | 
 |  | 
 | 		if (irel->r_offset + 3 < sec->size) | 
 | 		  { | 
 | 		    next_insn_msb = | 
 | 		      bfd_get_8 (abfd, contents + irel->r_offset + 3); | 
 | 		    next_insn_lsb = | 
 | 		      bfd_get_8 (abfd, contents + irel->r_offset + 2); | 
 | 		  } | 
 |  | 
 | 		if ((0x95 == next_insn_msb) && (0x08 == next_insn_lsb)) | 
 | 		  { | 
 | 		    /* The next insn is a ret. We now convert the rcall insn | 
 | 		       into a rjmp instruction.  */ | 
 | 		    code_msb &= 0xef; | 
 | 		    bfd_put_8 (abfd, code_msb, contents + irel->r_offset + 1); | 
 | 		    if (debug_relax) | 
 | 		      printf ("converted rcall/ret sequence at address 0x%x" | 
 | 			      " into rjmp/ret sequence. Section is %s\n\n", | 
 | 			      (int) dot, sec->name); | 
 | 		    *again = true; | 
 | 		    break; | 
 | 		  } | 
 | 	      } | 
 | 	    else if ((0x94 == (code_msb & 0xfe)) | 
 | 		     && (0x0e == (code_lsb & 0x0e)) | 
 | 		     && avr_replace_call_ret_sequences) | 
 | 	      { | 
 | 		/* This insn is a call.  */ | 
 | 		unsigned char next_insn_msb = 0; | 
 | 		unsigned char next_insn_lsb = 0; | 
 |  | 
 | 		if (irel->r_offset + 5 < sec->size) | 
 | 		  { | 
 | 		    next_insn_msb = | 
 | 		      bfd_get_8 (abfd, contents + irel->r_offset + 5); | 
 | 		    next_insn_lsb = | 
 | 		      bfd_get_8 (abfd, contents + irel->r_offset + 4); | 
 | 		  } | 
 |  | 
 | 		if ((0x95 == next_insn_msb) && (0x08 == next_insn_lsb)) | 
 | 		  { | 
 | 		    /* The next insn is a ret. We now convert the call insn | 
 | 		       into a jmp instruction.  */ | 
 |  | 
 | 		    code_lsb &= 0xfd; | 
 | 		    bfd_put_8 (abfd, code_lsb, contents + irel->r_offset); | 
 | 		    if (debug_relax) | 
 | 		      printf ("converted call/ret sequence at address 0x%x" | 
 | 			      " into jmp/ret sequence. Section is %s\n\n", | 
 | 			      (int) dot, sec->name); | 
 | 		    *again = true; | 
 | 		    break; | 
 | 		  } | 
 | 	      } | 
 | 	    else if ((0xc0 == (code_msb & 0xf0)) | 
 | 		     || ((0x94 == (code_msb & 0xfe)) | 
 | 			 && (0x0c == (code_lsb & 0x0e)))) | 
 | 	      { | 
 | 		/* This insn is a rjmp or a jmp.  */ | 
 | 		unsigned char next_insn_msb = 0; | 
 | 		unsigned char next_insn_lsb = 0; | 
 | 		int insn_size; | 
 |  | 
 | 		if (0xc0 == (code_msb & 0xf0)) | 
 | 		  insn_size = 2; /* rjmp insn */ | 
 | 		else | 
 | 		  insn_size = 4; /* jmp insn */ | 
 |  | 
 | 		if (irel->r_offset + insn_size + 1 < sec->size) | 
 | 		  { | 
 | 		    next_insn_msb = | 
 | 		      bfd_get_8 (abfd, contents + irel->r_offset | 
 | 				 + insn_size + 1); | 
 | 		    next_insn_lsb = | 
 | 		      bfd_get_8 (abfd, contents + irel->r_offset | 
 | 				 + insn_size); | 
 | 		  } | 
 |  | 
 | 		if ((0x95 == next_insn_msb) && (0x08 == next_insn_lsb)) | 
 | 		  { | 
 | 		    /* The next insn is a ret. We possibly could delete | 
 | 		       this ret. First we need to check for preceding | 
 | 		       sbis/sbic/sbrs or cpse "skip" instructions.  */ | 
 |  | 
 | 		    int there_is_preceding_non_skip_insn = 1; | 
 | 		    bfd_vma address_of_ret; | 
 |  | 
 | 		    address_of_ret = dot + insn_size; | 
 |  | 
 | 		    if (debug_relax && (insn_size == 2)) | 
 | 		      printf ("found rjmp / ret sequence at address 0x%x\n", | 
 | 			      (int) dot); | 
 | 		    if (debug_relax && (insn_size == 4)) | 
 | 		      printf ("found jmp / ret sequence at address 0x%x\n", | 
 | 			      (int) dot); | 
 |  | 
 | 		    /* We have to make sure that there is a preceding insn.  */ | 
 | 		    if (irel->r_offset >= 2) | 
 | 		      { | 
 | 			unsigned char preceding_msb; | 
 | 			unsigned char preceding_lsb; | 
 |  | 
 | 			preceding_msb = | 
 | 			  bfd_get_8 (abfd, contents + irel->r_offset - 1); | 
 | 			preceding_lsb = | 
 | 			  bfd_get_8 (abfd, contents + irel->r_offset - 2); | 
 |  | 
 | 			/* sbic.  */ | 
 | 			if (0x99 == preceding_msb) | 
 | 			  there_is_preceding_non_skip_insn = 0; | 
 |  | 
 | 			/* sbis.  */ | 
 | 			if (0x9b == preceding_msb) | 
 | 			  there_is_preceding_non_skip_insn = 0; | 
 |  | 
 | 			/* sbrc */ | 
 | 			if ((0xfc == (preceding_msb & 0xfe) | 
 | 			     && (0x00 == (preceding_lsb & 0x08)))) | 
 | 			  there_is_preceding_non_skip_insn = 0; | 
 |  | 
 | 			/* sbrs */ | 
 | 			if ((0xfe == (preceding_msb & 0xfe) | 
 | 			     && (0x00 == (preceding_lsb & 0x08)))) | 
 | 			  there_is_preceding_non_skip_insn = 0; | 
 |  | 
 | 			/* cpse */ | 
 | 			if (0x10 == (preceding_msb & 0xfc)) | 
 | 			  there_is_preceding_non_skip_insn = 0; | 
 |  | 
 | 			if (there_is_preceding_non_skip_insn == 0) | 
 | 			  if (debug_relax) | 
 | 			    printf ("preceding skip insn prevents deletion of" | 
 | 				    " ret insn at Addy 0x%x in section %s\n", | 
 | 				    (int) dot + 2, sec->name); | 
 | 		      } | 
 | 		    else | 
 | 		      { | 
 | 			/* There is no previous instruction.  */ | 
 | 			there_is_preceding_non_skip_insn = 0; | 
 | 		      } | 
 |  | 
 | 		    if (there_is_preceding_non_skip_insn) | 
 | 		      { | 
 | 			/* We now only have to make sure that there is no | 
 | 			   local label defined at the address of the ret | 
 | 			   instruction and that there is no local relocation | 
 | 			   in this section pointing to the ret.  */ | 
 |  | 
 | 			int deleting_ret_is_safe = 1; | 
 | 			unsigned int section_offset_of_ret_insn = | 
 | 			  irel->r_offset + insn_size; | 
 | 			Elf_Internal_Sym *isym, *isymend; | 
 | 			unsigned int sec_shndx; | 
 | 			struct bfd_section *isec; | 
 |  | 
 | 			sec_shndx = | 
 | 			  _bfd_elf_section_from_bfd_section (abfd, sec); | 
 |  | 
 | 			/* Check for local symbols.  */ | 
 | 			isym = (Elf_Internal_Sym *) symtab_hdr->contents; | 
 | 			isymend = isym + symtab_hdr->sh_info; | 
 | 			/* PR 6019: There may not be any local symbols.  */ | 
 | 			for (; isym != NULL && isym < isymend; isym++) | 
 | 			  { | 
 | 			    if (isym->st_value == section_offset_of_ret_insn | 
 | 				&& isym->st_shndx == sec_shndx) | 
 | 			      { | 
 | 				deleting_ret_is_safe = 0; | 
 | 				if (debug_relax) | 
 | 				  printf ("local label prevents deletion of ret " | 
 | 					  "insn at address 0x%x\n", | 
 | 					  (int) dot + insn_size); | 
 | 			      } | 
 | 			  } | 
 |  | 
 | 			/* Now check for global symbols.  */ | 
 | 			{ | 
 | 			  int symcount; | 
 | 			  struct elf_link_hash_entry **sym_hashes; | 
 | 			  struct elf_link_hash_entry **end_hashes; | 
 |  | 
 | 			  symcount = (symtab_hdr->sh_size | 
 | 				      / sizeof (Elf32_External_Sym) | 
 | 				      - symtab_hdr->sh_info); | 
 | 			  sym_hashes = elf_sym_hashes (abfd); | 
 | 			  end_hashes = sym_hashes + symcount; | 
 | 			  for (; sym_hashes < end_hashes; sym_hashes++) | 
 | 			    { | 
 | 			      struct elf_link_hash_entry *sym_hash = | 
 | 				*sym_hashes; | 
 | 			      if ((sym_hash->root.type == bfd_link_hash_defined | 
 | 				   || sym_hash->root.type == | 
 | 				   bfd_link_hash_defweak) | 
 | 				  && sym_hash->root.u.def.section == sec | 
 | 				  && sym_hash->root.u.def.value == section_offset_of_ret_insn) | 
 | 				{ | 
 | 				  deleting_ret_is_safe = 0; | 
 | 				  if (debug_relax) | 
 | 				    printf ("global label prevents deletion of " | 
 | 					    "ret insn at address 0x%x\n", | 
 | 					    (int) dot + insn_size); | 
 | 				} | 
 | 			    } | 
 | 			} | 
 |  | 
 | 			/* Now we check for relocations pointing to ret.  */ | 
 | 			for (isec = abfd->sections; isec && deleting_ret_is_safe; isec = isec->next) | 
 | 			  { | 
 | 			    Elf_Internal_Rela *rel; | 
 | 			    Elf_Internal_Rela *relend; | 
 |  | 
 | 			    rel = elf_section_data (isec)->relocs; | 
 | 			    if (rel == NULL) | 
 | 			      rel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, true); | 
 |  | 
 | 			    relend = rel + isec->reloc_count; | 
 |  | 
 | 			    for (; rel && rel < relend; rel++) | 
 | 			      { | 
 | 				bfd_vma reloc_target = 0; | 
 |  | 
 | 				/* Read this BFD's local symbols if we haven't | 
 | 				   done so already.  */ | 
 | 				if (isymbuf == NULL && symtab_hdr->sh_info != 0) | 
 | 				  { | 
 | 				    isymbuf = (Elf_Internal_Sym *) | 
 | 				      symtab_hdr->contents; | 
 | 				    if (isymbuf == NULL) | 
 | 				      isymbuf = bfd_elf_get_elf_syms | 
 | 					(abfd, | 
 | 					 symtab_hdr, | 
 | 					 symtab_hdr->sh_info, 0, | 
 | 					 NULL, NULL, NULL); | 
 | 				    if (isymbuf == NULL) | 
 | 				      break; | 
 | 				  } | 
 |  | 
 | 				/* Get the value of the symbol referred to | 
 | 				   by the reloc.  */ | 
 | 				if (ELF32_R_SYM (rel->r_info) | 
 | 				    < symtab_hdr->sh_info) | 
 | 				  { | 
 | 				    /* A local symbol.  */ | 
 | 				    asection *sym_sec; | 
 |  | 
 | 				    isym = isymbuf | 
 | 				      + ELF32_R_SYM (rel->r_info); | 
 | 				    sym_sec = bfd_section_from_elf_index | 
 | 				      (abfd, isym->st_shndx); | 
 | 				    symval = isym->st_value; | 
 |  | 
 | 				    /* If the reloc is absolute, it will not | 
 | 				       have a symbol or section associated | 
 | 				       with it.  */ | 
 |  | 
 | 				    if (sym_sec) | 
 | 				      { | 
 | 					symval += | 
 | 					  sym_sec->output_section->vma | 
 | 					  + sym_sec->output_offset; | 
 | 					reloc_target = symval + rel->r_addend; | 
 | 				      } | 
 | 				    else | 
 | 				      { | 
 | 					reloc_target = symval + rel->r_addend; | 
 | 					/* Reference symbol is absolute.  */ | 
 | 				      } | 
 | 				  } | 
 | 				/* else ... reference symbol is extern.  */ | 
 |  | 
 | 				if (address_of_ret == reloc_target) | 
 | 				  { | 
 | 				    deleting_ret_is_safe = 0; | 
 | 				    if (debug_relax) | 
 | 				      printf ("ret from " | 
 | 					      "rjmp/jmp ret sequence at address" | 
 | 					      " 0x%x could not be deleted. ret" | 
 | 					      " is target of a relocation.\n", | 
 | 					      (int) address_of_ret); | 
 | 				    break; | 
 | 				  } | 
 | 			      } | 
 | 			  } | 
 |  | 
 | 			if (deleting_ret_is_safe) | 
 | 			  { | 
 | 			    if (debug_relax) | 
 | 			      printf ("unreachable ret instruction " | 
 | 				      "at address 0x%x deleted.\n", | 
 | 				      (int) dot + insn_size); | 
 |  | 
 | 			    /* Delete two bytes of data.  */ | 
 | 			    if (!elf32_avr_relax_delete_bytes (abfd, sec, | 
 | 							       irel->r_offset + insn_size, 2, | 
 | 							       true)) | 
 | 			      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; | 
 | 			    break; | 
 | 			  } | 
 | 		      } | 
 | 		  } | 
 | 	      } | 
 | 	    break; | 
 | 	  } | 
 | 	} | 
 |     } | 
 |  | 
 |   if (!*again) | 
 |     { | 
 |       /* Look through all the property records in this section to see if | 
 | 	 there's any alignment records that can be moved.  */ | 
 |       struct avr_relax_info *relax_info; | 
 |  | 
 |       relax_info = get_avr_relax_info (sec); | 
 |       if (relax_info->records.count > 0) | 
 | 	{ | 
 | 	  unsigned int i; | 
 |  | 
 | 	  for (i = 0; i < relax_info->records.count; ++i) | 
 | 	    { | 
 | 	      switch (relax_info->records.items [i].type) | 
 | 		{ | 
 | 		case RECORD_ORG: | 
 | 		case RECORD_ORG_AND_FILL: | 
 | 		  break; | 
 | 		case RECORD_ALIGN: | 
 | 		case RECORD_ALIGN_AND_FILL: | 
 | 		  { | 
 | 		    struct avr_property_record *record; | 
 | 		    unsigned long bytes_to_align; | 
 | 		    int count = 0; | 
 |  | 
 | 		    /* Look for alignment directives that have had enough | 
 | 		       bytes deleted before them, such that the directive | 
 | 		       can be moved backwards and still maintain the | 
 | 		       required alignment.  */ | 
 | 		    record = &relax_info->records.items [i]; | 
 | 		    bytes_to_align | 
 | 		      = (unsigned long) (1 << record->data.align.bytes); | 
 | 		    while (record->data.align.preceding_deleted >= | 
 | 			   bytes_to_align) | 
 | 		      { | 
 | 			record->data.align.preceding_deleted | 
 | 			  -= bytes_to_align; | 
 | 			count += bytes_to_align; | 
 | 		      } | 
 |  | 
 | 		    if (count > 0) | 
 | 		      { | 
 | 			bfd_vma addr = record->offset; | 
 |  | 
 | 			/* We can delete COUNT bytes and this alignment | 
 | 			   directive will still be correctly aligned. | 
 | 			   First move the alignment directive, then delete | 
 | 			   the bytes.  */ | 
 | 			record->offset -= count; | 
 | 			elf32_avr_relax_delete_bytes (abfd, sec, | 
 | 						      addr - count, | 
 | 						      count, false); | 
 | 			*again = true; | 
 | 		      } | 
 | 		  } | 
 | 		  break; | 
 | 		} | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   if (contents != NULL | 
 |       && elf_section_data (sec)->this_hdr.contents != contents) | 
 |     { | 
 |       if (! link_info->keep_memory) | 
 | 	free (contents); | 
 |       else | 
 | 	{ | 
 | 	  /* Cache the section contents for elf_link_input_bfd.  */ | 
 | 	  elf_section_data (sec)->this_hdr.contents = contents; | 
 | 	} | 
 |     } | 
 |  | 
 |   if (elf_section_data (sec)->relocs != internal_relocs) | 
 |     free (internal_relocs); | 
 |  | 
 |   return true; | 
 |  | 
 |  error_return: | 
 |   if (symtab_hdr->contents != (unsigned char *) isymbuf) | 
 |     free (isymbuf); | 
 |   if (elf_section_data (sec)->this_hdr.contents != contents) | 
 |     free (contents); | 
 |   if (elf_section_data (sec)->relocs != internal_relocs) | 
 |     free (internal_relocs); | 
 |  | 
 |   return false; | 
 | } | 
 |  | 
 | /* This is a version of bfd_generic_get_relocated_section_contents | 
 |    which uses elf32_avr_relocate_section. | 
 |  | 
 |    For avr it's essentially a cut and paste taken from the H8300 port. | 
 |    The author of the relaxation support patch for avr had absolutely no | 
 |    clue what is happening here but found out that this part of the code | 
 |    seems to be important.  */ | 
 |  | 
 | static bfd_byte * | 
 | elf32_avr_get_relocated_section_contents (bfd *output_bfd, | 
 | 					  struct bfd_link_info *link_info, | 
 | 					  struct bfd_link_order *link_order, | 
 | 					  bfd_byte *data, | 
 | 					  bool relocatable, | 
 | 					  asymbol **symbols) | 
 | { | 
 |   Elf_Internal_Shdr *symtab_hdr; | 
 |   asection *input_section = link_order->u.indirect.section; | 
 |   bfd *input_bfd = input_section->owner; | 
 |   asection **sections = NULL; | 
 |   Elf_Internal_Rela *internal_relocs = NULL; | 
 |   Elf_Internal_Sym *isymbuf = NULL; | 
 |  | 
 |   /* We only need to handle the case of relaxing, or of having a | 
 |      particular set of section contents, specially.  */ | 
 |   if (relocatable | 
 |       || elf_section_data (input_section)->this_hdr.contents == NULL) | 
 |     return bfd_generic_get_relocated_section_contents (output_bfd, link_info, | 
 | 						       link_order, data, | 
 | 						       relocatable, | 
 | 						       symbols); | 
 |   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; | 
 |  | 
 |   memcpy (data, elf_section_data (input_section)->this_hdr.contents, | 
 | 	  (size_t) input_section->size); | 
 |  | 
 |   if ((input_section->flags & SEC_RELOC) != 0 | 
 |       && input_section->reloc_count > 0) | 
 |     { | 
 |       asection **secpp; | 
 |       Elf_Internal_Sym *isym, *isymend; | 
 |       bfd_size_type amt; | 
 |  | 
 |       internal_relocs = (_bfd_elf_link_read_relocs | 
 | 			 (input_bfd, input_section, NULL, NULL, false)); | 
 |       if (internal_relocs == NULL) | 
 | 	goto error_return; | 
 |  | 
 |       if (symtab_hdr->sh_info != 0) | 
 | 	{ | 
 | 	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; | 
 | 	  if (isymbuf == NULL) | 
 | 	    isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, | 
 | 					    symtab_hdr->sh_info, 0, | 
 | 					    NULL, NULL, NULL); | 
 | 	  if (isymbuf == NULL) | 
 | 	    goto error_return; | 
 | 	} | 
 |  | 
 |       amt = symtab_hdr->sh_info; | 
 |       amt *= sizeof (asection *); | 
 |       sections = bfd_malloc (amt); | 
 |       if (sections == NULL && amt != 0) | 
 | 	goto error_return; | 
 |  | 
 |       isymend = isymbuf + symtab_hdr->sh_info; | 
 |       for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp) | 
 | 	{ | 
 | 	  asection *isec; | 
 |  | 
 | 	  if (isym->st_shndx == SHN_UNDEF) | 
 | 	    isec = bfd_und_section_ptr; | 
 | 	  else if (isym->st_shndx == SHN_ABS) | 
 | 	    isec = bfd_abs_section_ptr; | 
 | 	  else if (isym->st_shndx == SHN_COMMON) | 
 | 	    isec = bfd_com_section_ptr; | 
 | 	  else | 
 | 	    isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx); | 
 |  | 
 | 	  *secpp = isec; | 
 | 	} | 
 |  | 
 |       if (! elf32_avr_relocate_section (output_bfd, link_info, input_bfd, | 
 | 					input_section, data, internal_relocs, | 
 | 					isymbuf, sections)) | 
 | 	goto error_return; | 
 |  | 
 |       free (sections); | 
 |       if (symtab_hdr->contents != (unsigned char *) isymbuf) | 
 | 	free (isymbuf); | 
 |       if (elf_section_data (input_section)->relocs != internal_relocs) | 
 | 	free (internal_relocs); | 
 |     } | 
 |  | 
 |   return data; | 
 |  | 
 |  error_return: | 
 |   free (sections); | 
 |   if (symtab_hdr->contents != (unsigned char *) isymbuf) | 
 |     free (isymbuf); | 
 |   if (elf_section_data (input_section)->relocs != internal_relocs) | 
 |     free (internal_relocs); | 
 |   return NULL; | 
 | } | 
 |  | 
 |  | 
 | /* Determines the hash entry name for a particular reloc. It consists of | 
 |    the identifier of the symbol section and the added reloc addend and | 
 |    symbol offset relative to the section the symbol is attached to.  */ | 
 |  | 
 | static char * | 
 | avr_stub_name (const asection *symbol_section, | 
 | 	       const bfd_vma symbol_offset, | 
 | 	       const Elf_Internal_Rela *rela) | 
 | { | 
 |   char *stub_name; | 
 |   bfd_size_type len; | 
 |  | 
 |   len = 8 + 1 + 8 + 1 + 1; | 
 |   stub_name = bfd_malloc (len); | 
 |   if (stub_name != NULL) | 
 |     sprintf (stub_name, "%08x+%08x", | 
 | 	     symbol_section->id & 0xffffffff, | 
 | 	     (unsigned int) ((rela->r_addend & 0xffffffff) + symbol_offset)); | 
 |  | 
 |   return stub_name; | 
 | } | 
 |  | 
 |  | 
 | /* Add a new stub entry to the stub hash.  Not all fields of the new | 
 |    stub entry are initialised.  */ | 
 |  | 
 | static struct elf32_avr_stub_hash_entry * | 
 | avr_add_stub (const char *stub_name, | 
 | 	      struct elf32_avr_link_hash_table *htab) | 
 | { | 
 |   struct elf32_avr_stub_hash_entry *hsh; | 
 |  | 
 |   /* Enter this entry into the linker stub hash table.  */ | 
 |   hsh = avr_stub_hash_lookup (&htab->bstab, stub_name, true, false); | 
 |  | 
 |   if (hsh == NULL) | 
 |     { | 
 |       /* xgettext:c-format */ | 
 |       _bfd_error_handler (_("cannot create stub entry %s"), stub_name); | 
 |       return NULL; | 
 |     } | 
 |  | 
 |   hsh->stub_offset = 0; | 
 |   return hsh; | 
 | } | 
 |  | 
 | /* We assume that there is already space allocated for the stub section | 
 |    contents and that before building the stubs the section size is | 
 |    initialized to 0.  We assume that within the stub hash table entry, | 
 |    the absolute position of the jmp target has been written in the | 
 |    target_value field.  We write here the offset of the generated jmp insn | 
 |    relative to the trampoline section start to the stub_offset entry in | 
 |    the stub hash table entry.  */ | 
 |  | 
 | static  bool | 
 | avr_build_one_stub (struct bfd_hash_entry *bh, void *in_arg) | 
 | { | 
 |   struct elf32_avr_stub_hash_entry *hsh; | 
 |   struct bfd_link_info *info; | 
 |   struct elf32_avr_link_hash_table *htab; | 
 |   bfd *stub_bfd; | 
 |   bfd_byte *loc; | 
 |   bfd_vma target; | 
 |   bfd_vma starget; | 
 |  | 
 |   /* Basic opcode */ | 
 |   bfd_vma jmp_insn = 0x0000940c; | 
 |  | 
 |   /* Massage our args to the form they really have.  */ | 
 |   hsh = avr_stub_hash_entry (bh); | 
 |  | 
 |   if (!hsh->is_actually_needed) | 
 |     return true; | 
 |  | 
 |   info = (struct bfd_link_info *) in_arg; | 
 |  | 
 |   htab = avr_link_hash_table (info); | 
 |   if (htab == NULL) | 
 |     return false; | 
 |  | 
 |   target = hsh->target_value; | 
 |  | 
 |   /* Make a note of the offset within the stubs for this entry.  */ | 
 |   hsh->stub_offset = htab->stub_sec->size; | 
 |   loc = htab->stub_sec->contents + hsh->stub_offset; | 
 |  | 
 |   stub_bfd = htab->stub_sec->owner; | 
 |  | 
 |   if (debug_stubs) | 
 |     printf ("Building one Stub. Address: 0x%x, Offset: 0x%x\n", | 
 | 	     (unsigned int) target, | 
 | 	     (unsigned int) hsh->stub_offset); | 
 |  | 
 |   /* We now have to add the information on the jump target to the bare | 
 |      opcode bits already set in jmp_insn.  */ | 
 |  | 
 |   /* Check for the alignment of the address.  */ | 
 |   if (target & 1) | 
 |      return false; | 
 |  | 
 |   starget = target >> 1; | 
 |   jmp_insn |= ((starget & 0x10000) | ((starget << 3) & 0x1f00000)) >> 16; | 
 |   bfd_put_16 (stub_bfd, jmp_insn, loc); | 
 |   bfd_put_16 (stub_bfd, (bfd_vma) starget & 0xffff, loc + 2); | 
 |  | 
 |   htab->stub_sec->size += 4; | 
 |  | 
 |   /* Now add the entries in the address mapping table if there is still | 
 |      space left.  */ | 
 |   { | 
 |     unsigned int nr; | 
 |  | 
 |     nr = htab->amt_entry_cnt + 1; | 
 |     if (nr <= htab->amt_max_entry_cnt) | 
 |       { | 
 | 	htab->amt_entry_cnt = nr; | 
 |  | 
 | 	htab->amt_stub_offsets[nr - 1] = hsh->stub_offset; | 
 | 	htab->amt_destination_addr[nr - 1] = target; | 
 |       } | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool | 
 | avr_mark_stub_not_to_be_necessary (struct bfd_hash_entry *bh, | 
 | 				   void *in_arg ATTRIBUTE_UNUSED) | 
 | { | 
 |   struct elf32_avr_stub_hash_entry *hsh; | 
 |  | 
 |   hsh = avr_stub_hash_entry (bh); | 
 |   hsh->is_actually_needed = false; | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool | 
 | avr_size_one_stub (struct bfd_hash_entry *bh, void *in_arg) | 
 | { | 
 |   struct elf32_avr_stub_hash_entry *hsh; | 
 |   struct elf32_avr_link_hash_table *htab; | 
 |   int size; | 
 |  | 
 |   /* Massage our args to the form they really have.  */ | 
 |   hsh = avr_stub_hash_entry (bh); | 
 |   htab = in_arg; | 
 |  | 
 |   if (hsh->is_actually_needed) | 
 |     size = 4; | 
 |   else | 
 |     size = 0; | 
 |  | 
 |   htab->stub_sec->size += size; | 
 |   return true; | 
 | } | 
 |  | 
 | void | 
 | elf32_avr_setup_params (struct bfd_link_info *info, | 
 | 			bfd *avr_stub_bfd, | 
 | 			asection *avr_stub_section, | 
 | 			bool no_stubs, | 
 | 			bool deb_stubs, | 
 | 			bool deb_relax, | 
 | 			bfd_vma pc_wrap_around, | 
 | 			bool call_ret_replacement) | 
 | { | 
 |   struct elf32_avr_link_hash_table *htab = avr_link_hash_table (info); | 
 |  | 
 |   if (htab == NULL) | 
 |     return; | 
 |   htab->stub_sec = avr_stub_section; | 
 |   htab->stub_bfd = avr_stub_bfd; | 
 |   htab->no_stubs = no_stubs; | 
 |  | 
 |   debug_relax = deb_relax; | 
 |   debug_stubs = deb_stubs; | 
 |   avr_pc_wrap_around = pc_wrap_around; | 
 |   avr_replace_call_ret_sequences = call_ret_replacement; | 
 | } | 
 |  | 
 |  | 
 | /* Set up various things so that we can make a list of input sections | 
 |    for each output section included in the link.  Returns -1 on error, | 
 |    0 when no stubs will be needed, and 1 on success.  It also sets | 
 |    information on the stubs bfd and the stub section in the info | 
 |    struct.  */ | 
 |  | 
 | int | 
 | elf32_avr_setup_section_lists (bfd *output_bfd, | 
 | 			       struct bfd_link_info *info) | 
 | { | 
 |   bfd *input_bfd; | 
 |   unsigned int bfd_count; | 
 |   unsigned int top_id, top_index; | 
 |   asection *section; | 
 |   asection **input_list, **list; | 
 |   size_t amt; | 
 |   struct elf32_avr_link_hash_table *htab = avr_link_hash_table (info); | 
 |  | 
 |   if (htab == NULL || htab->no_stubs) | 
 |     return 0; | 
 |  | 
 |   /* Count the number of input BFDs and find the top input section id.  */ | 
 |   for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0; | 
 |        input_bfd != NULL; | 
 |        input_bfd = input_bfd->link.next) | 
 |     { | 
 |       bfd_count += 1; | 
 |       for (section = input_bfd->sections; | 
 | 	   section != NULL; | 
 | 	   section = section->next) | 
 | 	if (top_id < section->id) | 
 | 	  top_id = section->id; | 
 |     } | 
 |  | 
 |   htab->bfd_count = bfd_count; | 
 |  | 
 |   /* We can't use output_bfd->section_count here to find the top output | 
 |      section index as some sections may have been removed, and | 
 |      strip_excluded_output_sections doesn't renumber the indices.  */ | 
 |   for (section = output_bfd->sections, top_index = 0; | 
 |        section != NULL; | 
 |        section = section->next) | 
 |     if (top_index < section->index) | 
 |       top_index = section->index; | 
 |  | 
 |   htab->top_index = top_index; | 
 |   amt = sizeof (asection *) * (top_index + 1); | 
 |   input_list = bfd_malloc (amt); | 
 |   htab->input_list = input_list; | 
 |   if (input_list == NULL) | 
 |     return -1; | 
 |  | 
 |   /* For sections we aren't interested in, mark their entries with a | 
 |      value we can check later.  */ | 
 |   list = input_list + top_index; | 
 |   do | 
 |     *list = bfd_abs_section_ptr; | 
 |   while (list-- != input_list); | 
 |  | 
 |   for (section = output_bfd->sections; | 
 |        section != NULL; | 
 |        section = section->next) | 
 |     if ((section->flags & SEC_CODE) != 0) | 
 |       input_list[section->index] = NULL; | 
 |  | 
 |   return 1; | 
 | } | 
 |  | 
 |  | 
 | /* Read in all local syms for all input bfds, and create hash entries | 
 |    for export stubs if we are building a multi-subspace shared lib. | 
 |    Returns -1 on error, 0 otherwise.  */ | 
 |  | 
 | static int | 
 | get_local_syms (bfd *input_bfd, struct bfd_link_info *info) | 
 | { | 
 |   unsigned int bfd_indx; | 
 |   Elf_Internal_Sym *local_syms, **all_local_syms; | 
 |   struct elf32_avr_link_hash_table *htab = avr_link_hash_table (info); | 
 |   size_t amt; | 
 |  | 
 |   if (htab == NULL) | 
 |     return -1; | 
 |  | 
 |   /* We want to read in symbol extension records only once.  To do this | 
 |      we need to read in the local symbols in parallel and save them for | 
 |      later use; so hold pointers to the local symbols in an array.  */ | 
 |   amt = sizeof (Elf_Internal_Sym *) * htab->bfd_count; | 
 |   all_local_syms = bfd_zmalloc (amt); | 
 |   htab->all_local_syms = all_local_syms; | 
 |   if (all_local_syms == NULL) | 
 |     return -1; | 
 |  | 
 |   /* Walk over all the input BFDs, swapping in local symbols. | 
 |      If we are creating a shared library, create hash entries for the | 
 |      export stubs.  */ | 
 |   for (bfd_indx = 0; | 
 |        input_bfd != NULL; | 
 |        input_bfd = input_bfd->link.next, bfd_indx++) | 
 |     { | 
 |       Elf_Internal_Shdr *symtab_hdr; | 
 |  | 
 |       /* We'll need the symbol table in a second.  */ | 
 |       symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; | 
 |       if (symtab_hdr->sh_info == 0) | 
 | 	continue; | 
 |  | 
 |       /* We need an array of the local symbols attached to the input bfd.  */ | 
 |       local_syms = (Elf_Internal_Sym *) symtab_hdr->contents; | 
 |       if (local_syms == NULL) | 
 | 	{ | 
 | 	  local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, | 
 | 					     symtab_hdr->sh_info, 0, | 
 | 					     NULL, NULL, NULL); | 
 | 	  /* Cache them for elf_link_input_bfd.  */ | 
 | 	  symtab_hdr->contents = (unsigned char *) local_syms; | 
 | 	} | 
 |       if (local_syms == NULL) | 
 | 	return -1; | 
 |  | 
 |       all_local_syms[bfd_indx] = local_syms; | 
 |     } | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | #define ADD_DUMMY_STUBS_FOR_DEBUGGING 0 | 
 |  | 
 | bool | 
 | elf32_avr_size_stubs (bfd *output_bfd, | 
 | 		      struct bfd_link_info *info, | 
 | 		      bool is_prealloc_run) | 
 | { | 
 |   struct elf32_avr_link_hash_table *htab; | 
 |   int stub_changed = 0; | 
 |  | 
 |   htab = avr_link_hash_table (info); | 
 |   if (htab == NULL) | 
 |     return false; | 
 |  | 
 |   /* At this point we initialize htab->vector_base | 
 |      To the start of the text output section.  */ | 
 |   htab->vector_base = htab->stub_sec->output_section->vma; | 
 |  | 
 |   if (get_local_syms (info->input_bfds, info)) | 
 |     { | 
 |       if (htab->all_local_syms) | 
 | 	goto error_ret_free_local; | 
 |       return false; | 
 |     } | 
 |  | 
 |   if (ADD_DUMMY_STUBS_FOR_DEBUGGING) | 
 |     { | 
 |       struct elf32_avr_stub_hash_entry *test; | 
 |  | 
 |       test = avr_add_stub ("Hugo",htab); | 
 |       test->target_value = 0x123456; | 
 |       test->stub_offset = 13; | 
 |  | 
 |       test = avr_add_stub ("Hugo2",htab); | 
 |       test->target_value = 0x84210; | 
 |       test->stub_offset = 14; | 
 |     } | 
 |  | 
 |   while (1) | 
 |     { | 
 |       bfd *input_bfd; | 
 |       unsigned int bfd_indx; | 
 |  | 
 |       /* We will have to re-generate the stub hash table each time anything | 
 | 	 in memory has changed.  */ | 
 |  | 
 |       bfd_hash_traverse (&htab->bstab, avr_mark_stub_not_to_be_necessary, htab); | 
 |       for (input_bfd = info->input_bfds, bfd_indx = 0; | 
 | 	   input_bfd != NULL; | 
 | 	   input_bfd = input_bfd->link.next, bfd_indx++) | 
 | 	{ | 
 | 	  Elf_Internal_Shdr *symtab_hdr; | 
 | 	  asection *section; | 
 | 	  Elf_Internal_Sym *local_syms; | 
 |  | 
 | 	  /* We'll need the symbol table in a second.  */ | 
 | 	  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; | 
 | 	  if (symtab_hdr->sh_info == 0) | 
 | 	    continue; | 
 |  | 
 | 	  local_syms = htab->all_local_syms[bfd_indx]; | 
 |  | 
 | 	  /* Walk over each section attached to the input bfd.  */ | 
 | 	  for (section = input_bfd->sections; | 
 | 	       section != NULL; | 
 | 	       section = section->next) | 
 | 	    { | 
 | 	      Elf_Internal_Rela *internal_relocs, *irelaend, *irela; | 
 |  | 
 | 	      /* If there aren't any relocs, then there's nothing more | 
 | 		 to do.  */ | 
 | 	      if ((section->flags & SEC_RELOC) == 0 | 
 | 		  || section->reloc_count == 0) | 
 | 		continue; | 
 |  | 
 | 	      /* If this section is a link-once section that will be | 
 | 		 discarded, then don't create any stubs.  */ | 
 | 	      if (section->output_section == NULL | 
 | 		  || section->output_section->owner != output_bfd) | 
 | 		continue; | 
 |  | 
 | 	      /* Get the relocs.  */ | 
 | 	      internal_relocs | 
 | 		= _bfd_elf_link_read_relocs (input_bfd, section, NULL, NULL, | 
 | 					     info->keep_memory); | 
 | 	      if (internal_relocs == NULL) | 
 | 		goto error_ret_free_local; | 
 |  | 
 | 	      /* Now examine each relocation.  */ | 
 | 	      irela = internal_relocs; | 
 | 	      irelaend = irela + section->reloc_count; | 
 | 	      for (; irela < irelaend; irela++) | 
 | 		{ | 
 | 		  unsigned int r_type, r_indx; | 
 | 		  struct elf32_avr_stub_hash_entry *hsh; | 
 | 		  asection *sym_sec; | 
 | 		  bfd_vma sym_value; | 
 | 		  bfd_vma destination; | 
 | 		  struct elf_link_hash_entry *hh; | 
 | 		  char *stub_name; | 
 |  | 
 | 		  r_type = ELF32_R_TYPE (irela->r_info); | 
 | 		  r_indx = ELF32_R_SYM (irela->r_info); | 
 |  | 
 | 		  /* Only look for 16 bit GS relocs. No other reloc will need a | 
 | 		     stub.  */ | 
 | 		  if (!((r_type == R_AVR_16_PM) | 
 | 			|| (r_type == R_AVR_LO8_LDI_GS) | 
 | 			|| (r_type == R_AVR_HI8_LDI_GS))) | 
 | 		    continue; | 
 |  | 
 | 		  /* Now determine the call target, its name, value, | 
 | 		     section.  */ | 
 | 		  sym_sec = NULL; | 
 | 		  sym_value = 0; | 
 | 		  destination = 0; | 
 | 		  hh = NULL; | 
 | 		  if (r_indx < symtab_hdr->sh_info) | 
 | 		    { | 
 | 		      /* It's a local symbol.  */ | 
 | 		      Elf_Internal_Sym *sym; | 
 | 		      Elf_Internal_Shdr *hdr; | 
 | 		      unsigned int shndx; | 
 |  | 
 | 		      sym = local_syms + r_indx; | 
 | 		      if (ELF_ST_TYPE (sym->st_info) != STT_SECTION) | 
 | 			sym_value = sym->st_value; | 
 | 		      shndx = sym->st_shndx; | 
 | 		      if (shndx < elf_numsections (input_bfd)) | 
 | 			{ | 
 | 			  hdr = elf_elfsections (input_bfd)[shndx]; | 
 | 			  sym_sec = hdr->bfd_section; | 
 | 			  destination = (sym_value + irela->r_addend | 
 | 					 + sym_sec->output_offset | 
 | 					 + sym_sec->output_section->vma); | 
 | 			} | 
 | 		    } | 
 | 		  else | 
 | 		    { | 
 | 		      /* It's an external symbol.  */ | 
 | 		      int e_indx; | 
 |  | 
 | 		      e_indx = r_indx - symtab_hdr->sh_info; | 
 | 		      hh = elf_sym_hashes (input_bfd)[e_indx]; | 
 |  | 
 | 		      while (hh->root.type == bfd_link_hash_indirect | 
 | 			     || hh->root.type == bfd_link_hash_warning) | 
 | 			hh = (struct elf_link_hash_entry *) | 
 | 			      (hh->root.u.i.link); | 
 |  | 
 | 		      if (hh->root.type == bfd_link_hash_defined | 
 | 			  || hh->root.type == bfd_link_hash_defweak) | 
 | 			{ | 
 | 			  sym_sec = hh->root.u.def.section; | 
 | 			  sym_value = hh->root.u.def.value; | 
 | 			  if (sym_sec->output_section != NULL) | 
 | 			  destination = (sym_value + irela->r_addend | 
 | 					 + sym_sec->output_offset | 
 | 					 + sym_sec->output_section->vma); | 
 | 			} | 
 | 		      else if (hh->root.type == bfd_link_hash_undefweak) | 
 | 			{ | 
 | 			  if (! bfd_link_pic (info)) | 
 | 			    continue; | 
 | 			} | 
 | 		      else if (hh->root.type == bfd_link_hash_undefined) | 
 | 			{ | 
 | 			  if (! (info->unresolved_syms_in_objects == RM_IGNORE | 
 | 				 && (ELF_ST_VISIBILITY (hh->other) | 
 | 				     == STV_DEFAULT))) | 
 | 			     continue; | 
 | 			} | 
 | 		      else | 
 | 			{ | 
 | 			  bfd_set_error (bfd_error_bad_value); | 
 |  | 
 | 			  error_ret_free_internal: | 
 | 			  if (elf_section_data (section)->relocs == NULL) | 
 | 			    free (internal_relocs); | 
 | 			  goto error_ret_free_local; | 
 | 			} | 
 | 		    } | 
 |  | 
 | 		  if (! avr_stub_is_required_for_16_bit_reloc | 
 | 		      (destination - htab->vector_base)) | 
 | 		    { | 
 | 		      if (!is_prealloc_run) | 
 | 			/* We are having a reloc that does't need a stub.  */ | 
 | 			continue; | 
 |  | 
 | 		      /* We don't right now know if a stub will be needed. | 
 | 			 Let's rather be on the safe side.  */ | 
 | 		    } | 
 |  | 
 | 		  /* Get the name of this stub.  */ | 
 | 		  stub_name = avr_stub_name (sym_sec, sym_value, irela); | 
 |  | 
 | 		  if (!stub_name) | 
 | 		    goto error_ret_free_internal; | 
 |  | 
 |  | 
 | 		  hsh = avr_stub_hash_lookup (&htab->bstab, | 
 | 					      stub_name, | 
 | 					      false, false); | 
 | 		  if (hsh != NULL) | 
 | 		    { | 
 | 		      /* The proper stub has already been created.  Mark it | 
 | 			 to be used and write the possibly changed destination | 
 | 			 value.  */ | 
 | 		      hsh->is_actually_needed = true; | 
 | 		      hsh->target_value = destination; | 
 | 		      free (stub_name); | 
 | 		      continue; | 
 | 		    } | 
 |  | 
 | 		  hsh = avr_add_stub (stub_name, htab); | 
 | 		  if (hsh == NULL) | 
 | 		    { | 
 | 		      free (stub_name); | 
 | 		      goto error_ret_free_internal; | 
 | 		    } | 
 |  | 
 | 		  hsh->is_actually_needed = true; | 
 | 		  hsh->target_value = destination; | 
 |  | 
 | 		  if (debug_stubs) | 
 | 		    printf ("Adding stub with destination 0x%x to the" | 
 | 			    " hash table.\n", (unsigned int) destination); | 
 | 		  if (debug_stubs) | 
 | 		    printf ("(Pre-Alloc run: %i)\n", is_prealloc_run); | 
 |  | 
 | 		  stub_changed = true; | 
 | 		} | 
 |  | 
 | 	      /* We're done with the internal relocs, free them.  */ | 
 | 	      if (elf_section_data (section)->relocs == NULL) | 
 | 		free (internal_relocs); | 
 | 	    } | 
 | 	} | 
 |  | 
 |       /* Re-Calculate the number of needed stubs.  */ | 
 |       htab->stub_sec->size = 0; | 
 |       bfd_hash_traverse (&htab->bstab, avr_size_one_stub, htab); | 
 |  | 
 |       if (!stub_changed) | 
 | 	break; | 
 |  | 
 |       stub_changed = false; | 
 |     } | 
 |  | 
 |   free (htab->all_local_syms); | 
 |   return true; | 
 |  | 
 |  error_ret_free_local: | 
 |   free (htab->all_local_syms); | 
 |   return false; | 
 | } | 
 |  | 
 |  | 
 | /* Build all the stubs associated with the current output file.  The | 
 |    stubs are kept in a hash table attached to the main linker hash | 
 |    table.  We also set up the .plt entries for statically linked PIC | 
 |    functions here.  This function is called via hppaelf_finish in the | 
 |    linker.  */ | 
 |  | 
 | bool | 
 | elf32_avr_build_stubs (struct bfd_link_info *info) | 
 | { | 
 |   asection *stub_sec; | 
 |   struct bfd_hash_table *table; | 
 |   struct elf32_avr_link_hash_table *htab; | 
 |   bfd_size_type total_size = 0; | 
 |  | 
 |   htab = avr_link_hash_table (info); | 
 |   if (htab == NULL) | 
 |     return false; | 
 |  | 
 |   /* In case that there were several stub sections:  */ | 
 |   for (stub_sec = htab->stub_bfd->sections; | 
 |        stub_sec != NULL; | 
 |        stub_sec = stub_sec->next) | 
 |     { | 
 |       bfd_size_type size; | 
 |  | 
 |       /* Allocate memory to hold the linker stubs.  */ | 
 |       size = stub_sec->size; | 
 |       total_size += size; | 
 |  | 
 |       stub_sec->contents = bfd_zalloc (htab->stub_bfd, size); | 
 |       if (stub_sec->contents == NULL && size != 0) | 
 | 	return false; | 
 |       stub_sec->size = 0; | 
 |     } | 
 |  | 
 |   /* Allocate memory for the adress mapping table.  */ | 
 |   htab->amt_entry_cnt = 0; | 
 |   htab->amt_max_entry_cnt = total_size / 4; | 
 |   htab->amt_stub_offsets = bfd_malloc (sizeof (bfd_vma) | 
 | 				       * htab->amt_max_entry_cnt); | 
 |   htab->amt_destination_addr = bfd_malloc (sizeof (bfd_vma) | 
 | 					   * htab->amt_max_entry_cnt ); | 
 |  | 
 |   if (debug_stubs) | 
 |     printf ("Allocating %i entries in the AMT\n", htab->amt_max_entry_cnt); | 
 |  | 
 |   /* Build the stubs as directed by the stub hash table.  */ | 
 |   table = &htab->bstab; | 
 |   bfd_hash_traverse (table, avr_build_one_stub, info); | 
 |  | 
 |   if (debug_stubs) | 
 |     printf ("Final Stub section Size: %i\n", (int) htab->stub_sec->size); | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | /* Callback used by QSORT to order relocations AP and BP.  */ | 
 |  | 
 | static int | 
 | internal_reloc_compare (const void *ap, const void *bp) | 
 | { | 
 |   const Elf_Internal_Rela *a = (const Elf_Internal_Rela *) ap; | 
 |   const Elf_Internal_Rela *b = (const Elf_Internal_Rela *) bp; | 
 |  | 
 |   if (a->r_offset != b->r_offset) | 
 |     return (a->r_offset - b->r_offset); | 
 |  | 
 |   /* We don't need to sort on these criteria for correctness, | 
 |      but enforcing a more strict ordering prevents unstable qsort | 
 |      from behaving differently with different implementations. | 
 |      Without the code below we get correct but different results | 
 |      on Solaris 2.7 and 2.8.  We would like to always produce the | 
 |      same results no matter the host.  */ | 
 |  | 
 |   if (a->r_info != b->r_info) | 
 |     return (a->r_info - b->r_info); | 
 |  | 
 |   return (a->r_addend - b->r_addend); | 
 | } | 
 |  | 
 | /* Return true if ADDRESS is within the vma range of SECTION from ABFD.  */ | 
 |  | 
 | static bool | 
 | avr_is_section_for_address (asection *section, bfd_vma address) | 
 | { | 
 |   bfd_vma vma; | 
 |   bfd_size_type size; | 
 |  | 
 |   vma = bfd_section_vma (section); | 
 |   if (address < vma) | 
 |     return false; | 
 |  | 
 |   size = section->size; | 
 |   if (address >= vma + size) | 
 |     return false; | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | /* Data structure used by AVR_FIND_SECTION_FOR_ADDRESS.  */ | 
 |  | 
 | struct avr_find_section_data | 
 | { | 
 |   /* The address we're looking for.  */ | 
 |   bfd_vma address; | 
 |  | 
 |   /* The section we've found.  */ | 
 |   asection *section; | 
 | }; | 
 |  | 
 | /* Helper function to locate the section holding a certain virtual memory | 
 |    address.  This is called via bfd_map_over_sections.  The DATA is an | 
 |    instance of STRUCT AVR_FIND_SECTION_DATA, the address field of which | 
 |    has been set to the address to search for, and the section field has | 
 |    been set to NULL.  If SECTION from ABFD contains ADDRESS then the | 
 |    section field in DATA will be set to SECTION.  As an optimisation, if | 
 |    the section field is already non-null then this function does not | 
 |    perform any checks, and just returns.  */ | 
 |  | 
 | static void | 
 | avr_find_section_for_address (bfd *abfd ATTRIBUTE_UNUSED, | 
 | 			      asection *section, void *data) | 
 | { | 
 |   struct avr_find_section_data *fs_data | 
 |     = (struct avr_find_section_data *) data; | 
 |  | 
 |   /* Return if already found.  */ | 
 |   if (fs_data->section != NULL) | 
 |     return; | 
 |  | 
 |   /* If this section isn't part of the addressable code content, skip it.  */ | 
 |   if ((bfd_section_flags (section) & SEC_ALLOC) == 0 | 
 |       && (bfd_section_flags (section) & SEC_CODE) == 0) | 
 |     return; | 
 |  | 
 |   if (avr_is_section_for_address (section, fs_data->address)) | 
 |     fs_data->section = section; | 
 | } | 
 |  | 
 | /* Load all of the property records from SEC, a section from ABFD.  Return | 
 |    a STRUCT AVR_PROPERTY_RECORD_LIST containing all the records.  The | 
 |    memory for the returned structure, and all of the records pointed too by | 
 |    the structure are allocated with a single call to malloc, so, only the | 
 |    pointer returned needs to be free'd.  */ | 
 |  | 
 | static struct avr_property_record_list * | 
 | avr_elf32_load_records_from_section (bfd *abfd, asection *sec) | 
 | { | 
 |   bfd_byte *contents, *ptr; | 
 |   bfd_size_type size, mem_size; | 
 |   bfd_byte version, flags; | 
 |   uint16_t record_count, i; | 
 |   struct avr_property_record_list *r_list = NULL; | 
 |   Elf_Internal_Rela *internal_relocs = NULL, *rel, *rel_end; | 
 |   struct avr_find_section_data fs_data; | 
 |  | 
 |   fs_data.section = NULL; | 
 |  | 
 |   if (!bfd_malloc_and_get_section (abfd, sec, &contents)) | 
 |     goto load_failed; | 
 |   ptr = contents; | 
 |  | 
 |   /* Load the relocations for the '.avr.prop' section if there are any, and | 
 |      sort them.  */ | 
 |   internal_relocs = (_bfd_elf_link_read_relocs | 
 | 		     (abfd, sec, NULL, NULL, false)); | 
 |   if (internal_relocs) | 
 |     qsort (internal_relocs, sec->reloc_count, | 
 | 	   sizeof (Elf_Internal_Rela), internal_reloc_compare); | 
 |  | 
 |   /* There is a header at the start of the property record section SEC, the | 
 |      format of this header is: | 
 |        uint8_t  : version number | 
 |        uint8_t  : flags | 
 |        uint16_t : record counter | 
 |   */ | 
 |  | 
 |   /* Check we have at least got a headers worth of bytes.  */ | 
 |   size = bfd_section_size (sec); | 
 |   if (size < AVR_PROPERTY_SECTION_HEADER_SIZE) | 
 |     goto load_failed; | 
 |  | 
 |   version = *ptr; | 
 |   ptr++; | 
 |   flags = *ptr; | 
 |   ptr++; | 
 |   record_count = bfd_get_16 (abfd, ptr); | 
 |   ptr += 2; | 
 |   BFD_ASSERT (ptr - contents == AVR_PROPERTY_SECTION_HEADER_SIZE); | 
 |  | 
 |   /* Now allocate space for the list structure, and all of the list | 
 |      elements in a single block.  */ | 
 |   mem_size = sizeof (struct avr_property_record_list) | 
 |     + sizeof (struct avr_property_record) * record_count; | 
 |   r_list = bfd_malloc (mem_size); | 
 |   if (r_list == NULL) | 
 |     goto load_failed; | 
 |  | 
 |   r_list->version = version; | 
 |   r_list->flags = flags; | 
 |   r_list->section = sec; | 
 |   r_list->record_count = record_count; | 
 |   r_list->records = (struct avr_property_record *) (&r_list [1]); | 
 |   size -= AVR_PROPERTY_SECTION_HEADER_SIZE; | 
 |  | 
 |   /* Check that we understand the version number.  There is only one | 
 |      version number right now, anything else is an error.  */ | 
 |   if (r_list->version != AVR_PROPERTY_RECORDS_VERSION) | 
 |     goto load_failed; | 
 |  | 
 |   rel = internal_relocs; | 
 |   rel_end = rel + sec->reloc_count; | 
 |   for (i = 0; i < record_count; ++i) | 
 |     { | 
 |       bfd_vma address; | 
 |  | 
 |       /* Each entry is a 32-bit address, followed by a single byte type. | 
 | 	 After that is the type specific data.  We must take care to | 
 | 	 ensure that we don't read beyond the end of the section data.  */ | 
 |       if (size < 5) | 
 | 	goto load_failed; | 
 |  | 
 |       r_list->records [i].section = NULL; | 
 |       r_list->records [i].offset = 0; | 
 |  | 
 |       if (rel) | 
 | 	{ | 
 | 	  /* The offset of the address within the .avr.prop section.  */ | 
 | 	  size_t offset = ptr - contents; | 
 |  | 
 | 	  while (rel < rel_end && rel->r_offset < offset) | 
 | 	    ++rel; | 
 |  | 
 | 	  if (rel == rel_end) | 
 | 	    rel = NULL; | 
 | 	  else if (rel->r_offset == offset) | 
 | 	    { | 
 | 	      /* Find section and section offset.  */ | 
 | 	      unsigned long r_symndx; | 
 |  | 
 | 	      asection * rel_sec; | 
 | 	      bfd_vma sec_offset; | 
 |  | 
 | 	      r_symndx = ELF32_R_SYM (rel->r_info); | 
 | 	      rel_sec = get_elf_r_symndx_section (abfd, r_symndx); | 
 | 	      sec_offset = get_elf_r_symndx_offset (abfd, r_symndx) | 
 | 		+ rel->r_addend; | 
 |  | 
 | 	      r_list->records [i].section = rel_sec; | 
 | 	      r_list->records [i].offset = sec_offset; | 
 | 	    } | 
 | 	} | 
 |  | 
 |       address = bfd_get_32 (abfd, ptr); | 
 |       ptr += 4; | 
 |       size -= 4; | 
 |  | 
 |       if (r_list->records [i].section == NULL) | 
 | 	{ | 
 | 	  /* Try to find section and offset from address.  */ | 
 | 	  if (fs_data.section != NULL | 
 | 	      && !avr_is_section_for_address (fs_data.section, address)) | 
 | 	    fs_data.section = NULL; | 
 |  | 
 | 	  if (fs_data.section == NULL) | 
 | 	    { | 
 | 	      fs_data.address = address; | 
 | 	      bfd_map_over_sections (abfd, avr_find_section_for_address, | 
 | 				     &fs_data); | 
 | 	    } | 
 |  | 
 | 	  if (fs_data.section == NULL) | 
 | 	    { | 
 | 	      fprintf (stderr, "Failed to find matching section.\n"); | 
 | 	      goto load_failed; | 
 | 	    } | 
 |  | 
 | 	  r_list->records [i].section = fs_data.section; | 
 | 	  r_list->records [i].offset | 
 | 	    = address - bfd_section_vma (fs_data.section); | 
 | 	} | 
 |  | 
 |       r_list->records [i].type = *ptr; | 
 |       ptr += 1; | 
 |       size -= 1; | 
 |  | 
 |       switch (r_list->records [i].type) | 
 | 	{ | 
 | 	case RECORD_ORG: | 
 | 	  /* Nothing else to load.  */ | 
 | 	  break; | 
 | 	case RECORD_ORG_AND_FILL: | 
 | 	  /* Just a 4-byte fill to load.  */ | 
 | 	  if (size < 4) | 
 | 	    goto load_failed; | 
 | 	  r_list->records [i].data.org.fill = bfd_get_32 (abfd, ptr); | 
 | 	  ptr += 4; | 
 | 	  size -= 4; | 
 | 	  break; | 
 | 	case RECORD_ALIGN: | 
 | 	  /* Just a 4-byte alignment to load.  */ | 
 | 	  if (size < 4) | 
 | 	    goto load_failed; | 
 | 	  r_list->records [i].data.align.bytes = bfd_get_32 (abfd, ptr); | 
 | 	  ptr += 4; | 
 | 	  size -= 4; | 
 | 	  /* Just initialise PRECEDING_DELETED field, this field is | 
 | 	     used during linker relaxation.  */ | 
 | 	  r_list->records [i].data.align.preceding_deleted = 0; | 
 | 	  break; | 
 | 	case RECORD_ALIGN_AND_FILL: | 
 | 	  /* A 4-byte alignment, and a 4-byte fill to load.  */ | 
 | 	  if (size < 8) | 
 | 	    goto load_failed; | 
 | 	  r_list->records [i].data.align.bytes = bfd_get_32 (abfd, ptr); | 
 | 	  ptr += 4; | 
 | 	  r_list->records [i].data.align.fill = bfd_get_32 (abfd, ptr); | 
 | 	  ptr += 4; | 
 | 	  size -= 8; | 
 | 	  /* Just initialise PRECEDING_DELETED field, this field is | 
 | 	     used during linker relaxation.  */ | 
 | 	  r_list->records [i].data.align.preceding_deleted = 0; | 
 | 	  break; | 
 | 	default: | 
 | 	  goto load_failed; | 
 | 	} | 
 |     } | 
 |  | 
 |   free (contents); | 
 |   if (elf_section_data (sec)->relocs != internal_relocs) | 
 |     free (internal_relocs); | 
 |   return r_list; | 
 |  | 
 |  load_failed: | 
 |   if (elf_section_data (sec)->relocs != internal_relocs) | 
 |     free (internal_relocs); | 
 |   free (contents); | 
 |   free (r_list); | 
 |   return NULL; | 
 | } | 
 |  | 
 | /* Load all of the property records from ABFD.  See | 
 |    AVR_ELF32_LOAD_RECORDS_FROM_SECTION for details of the return value.  */ | 
 |  | 
 | struct avr_property_record_list * | 
 | avr_elf32_load_property_records (bfd *abfd) | 
 | { | 
 |   asection *sec; | 
 |  | 
 |   /* Find the '.avr.prop' section and load the contents into memory.  */ | 
 |   sec = bfd_get_section_by_name (abfd, AVR_PROPERTY_RECORD_SECTION_NAME); | 
 |   if (sec == NULL) | 
 |     return NULL; | 
 |   return avr_elf32_load_records_from_section (abfd, sec); | 
 | } | 
 |  | 
 | const char * | 
 | avr_elf32_property_record_name (struct avr_property_record *rec) | 
 | { | 
 |   const char *str; | 
 |  | 
 |   switch (rec->type) | 
 |     { | 
 |     case RECORD_ORG: | 
 |       str = "ORG"; | 
 |       break; | 
 |     case RECORD_ORG_AND_FILL: | 
 |       str = "ORG+FILL"; | 
 |       break; | 
 |     case RECORD_ALIGN: | 
 |       str = "ALIGN"; | 
 |       break; | 
 |     case RECORD_ALIGN_AND_FILL: | 
 |       str = "ALIGN+FILL"; | 
 |       break; | 
 |     default: | 
 |       str = "unknown"; | 
 |     } | 
 |  | 
 |   return str; | 
 | } | 
 |  | 
 |  | 
 | #define ELF_ARCH		bfd_arch_avr | 
 | #define ELF_TARGET_ID		AVR_ELF_DATA | 
 | #define ELF_MACHINE_CODE	EM_AVR | 
 | #define ELF_MACHINE_ALT1	EM_AVR_OLD | 
 | #define ELF_MAXPAGESIZE		1 | 
 |  | 
 | #define TARGET_LITTLE_SYM	avr_elf32_vec | 
 | #define TARGET_LITTLE_NAME	"elf32-avr" | 
 |  | 
 | #define bfd_elf32_bfd_link_hash_table_create elf32_avr_link_hash_table_create | 
 |  | 
 | #define elf_info_to_howto		     avr_info_to_howto_rela | 
 | #define elf_info_to_howto_rel		     NULL | 
 | #define elf_backend_relocate_section	     elf32_avr_relocate_section | 
 | #define elf_backend_can_gc_sections	     1 | 
 | #define elf_backend_rela_normal		     1 | 
 | #define elf_backend_final_write_processing \ | 
 | 					bfd_elf_avr_final_write_processing | 
 | #define elf_backend_object_p		elf32_avr_object_p | 
 |  | 
 | #define bfd_elf32_bfd_relax_section elf32_avr_relax_section | 
 | #define bfd_elf32_bfd_get_relocated_section_contents \ | 
 | 					elf32_avr_get_relocated_section_contents | 
 | #define bfd_elf32_new_section_hook	elf_avr_new_section_hook | 
 | #define elf_backend_special_sections	elf_avr_special_sections | 
 |  | 
 | #include "elf32-target.h" |