143725Syokota/* AVR-specific support for 32-bit ELF
243725Syokota   Copyright 1999, 2000, 2001, 2002, 2003, 2004
343725Syokota   Free Software Foundation, Inc.
443725Syokota   Contributed by Denis Chertykov <denisc@overta.ru>
543725Syokota
643725SyokotaThis file is part of BFD, the Binary File Descriptor library.
743725Syokota
843725SyokotaThis program is free software; you can redistribute it and/or modify
943725Syokotait under the terms of the GNU General Public License as published by
1043725Syokotathe Free Software Foundation; either version 2 of the License, or
1143725Syokota(at your option) any later version.
1243725Syokota
1343725SyokotaThis program is distributed in the hope that it will be useful,
1443725Syokotabut WITHOUT ANY WARRANTY; without even the implied warranty of
1543725SyokotaMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1643725SyokotaGNU General Public License for more details.
1743725Syokota
1843725SyokotaYou should have received a copy of the GNU General Public License
1943725Syokotaalong with this program; if not, write to the Free Software
2043725SyokotaFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2143725Syokota
2243725Syokota#include "bfd.h"
2343725Syokota#include "sysdep.h"
2443725Syokota#include "libbfd.h"
2543725Syokota#include "elf-bfd.h"
2643725Syokota#include "elf/avr.h"
2750476Speter
2843725Syokotastatic reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
29216065Sdougb  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
3053200Sphantomstatic void avr_info_to_howto_rela
3165013Ssheldonh  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
3243725Syokotastatic asection *elf32_avr_gc_mark_hook
3343725Syokota  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
3465013Ssheldonh	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
3543725Syokotastatic bfd_boolean elf32_avr_gc_sweep_hook
3676175Sschweikh  PARAMS ((bfd *, struct bfd_link_info *, asection *,
3743725Syokota	   const Elf_Internal_Rela *));
3843725Syokotastatic bfd_boolean elf32_avr_check_relocs
3943725Syokota  PARAMS ((bfd *, struct bfd_link_info *, asection *,
4076175Sschweikh	   const Elf_Internal_Rela *));
4143725Syokotastatic bfd_reloc_status_type avr_final_link_relocate
4243725Syokota  PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
4343725Syokota	   Elf_Internal_Rela *, bfd_vma));
4465013Ssheldonhstatic bfd_boolean elf32_avr_relocate_section
4562978Sdannyboy  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
4665009Ssheldonh	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
4765009Ssheldonhstatic void bfd_elf_avr_final_write_processing PARAMS ((bfd *, bfd_boolean));
4865009Ssheldonhstatic bfd_boolean elf32_avr_object_p PARAMS ((bfd *));
4965013Ssheldonh
5076175Sschweikhstatic reloc_howto_type elf_avr_howto_table[] =
5165009Ssheldonh{
5265009Ssheldonh  HOWTO (R_AVR_NONE,		/* type */
5365009Ssheldonh	 0,			/* rightshift */
5443725Syokota	 2,			/* size (0 = byte, 1 = short, 2 = long) */
5576175Sschweikh	 32,			/* bitsize */
5643725Syokota	 FALSE,			/* pc_relative */
5743725Syokota	 0,			/* bitpos */
5843725Syokota	 complain_overflow_bitfield, /* complain_on_overflow */
5962978Sdannyboy	 bfd_elf_generic_reloc,	/* special_function */
6057676Ssheldonh	 "R_AVR_NONE",		/* name */
6143844Syokota	 FALSE,			/* partial_inplace */
6243725Syokota	 0,			/* src_mask */
6343844Syokota	 0,			/* dst_mask */
6443844Syokota	 FALSE),		/* pcrel_offset */
6555268Shoek
6643725Syokota  HOWTO (R_AVR_32,		/* type */
6743844Syokota	 0,			/* rightshift */
6843844Syokota	 2,			/* size (0 = byte, 1 = short, 2 = long) */
6943725Syokota	 32,			/* bitsize */
7043844Syokota	 FALSE,			/* pc_relative */
7165009Ssheldonh	 0,			/* bitpos */
7265009Ssheldonh	 complain_overflow_bitfield, /* complain_on_overflow */
7345628Sdes	 bfd_elf_generic_reloc,	/* special_function */
7445628Sdes	 "R_AVR_32",		/* name */
7545628Sdes	 FALSE,			/* partial_inplace */
7645628Sdes	 0xffffffff,		/* src_mask */
77228445Seadler	 0xffffffff,		/* dst_mask */
78228445Seadler	 FALSE),		/* pcrel_offset */
79228445Seadler
80228445Seadler  /* A 7 bit PC relative relocation.  */
81228445Seadler  HOWTO (R_AVR_7_PCREL,		/* type */
82228445Seadler	 1,			/* rightshift */
83228445Seadler	 1,			/* size (0 = byte, 1 = short, 2 = long) */
84228445Seadler	 7,			/* bitsize */
8543725Syokota	 TRUE,			/* pc_relative */
8643725Syokota	 3,			/* bitpos */
8743725Syokota	 complain_overflow_bitfield, /* complain_on_overflow */
8843725Syokota	 bfd_elf_generic_reloc, /* special_function */
8943725Syokota	 "R_AVR_7_PCREL",	/* name */
9043725Syokota	 FALSE,			/* partial_inplace */
9143844Syokota	 0xffff,		/* src_mask */
9243844Syokota	 0xffff,		/* dst_mask */
9343725Syokota	 TRUE),			/* pcrel_offset */
9443725Syokota
9581251Sru  /* A 13 bit PC relative relocation.  */
9681251Sru  HOWTO (R_AVR_13_PCREL,	/* type */
9743844Syokota	 1,			/* rightshift */
9843844Syokota	 1,			/* size (0 = byte, 1 = short, 2 = long) */
9965013Ssheldonh	 13,			/* bitsize */
10081449Sru	 TRUE,			/* pc_relative */
10143844Syokota	 0,			/* bitpos */
10265009Ssheldonh	 complain_overflow_bitfield, /* complain_on_overflow */
10365009Ssheldonh	 bfd_elf_generic_reloc, /* special_function */
10465009Ssheldonh	 "R_AVR_13_PCREL",	/* name */
10565009Ssheldonh	 FALSE,			/* partial_inplace */
10643725Syokota	 0xfff,			/* src_mask */
10743844Syokota	 0xfff,			/* dst_mask */
10843844Syokota	 TRUE),			/* pcrel_offset */
10943725Syokota
110206374Sjkim  /* A 16 bit absolute relocation.  */
111206374Sjkim  HOWTO (R_AVR_16,		/* type */
112206374Sjkim	 0,			/* rightshift */
113206374Sjkim	 1,			/* size (0 = byte, 1 = short, 2 = long) */
11443844Syokota	 16,			/* bitsize */
11581622Sru	 FALSE,			/* pc_relative */
11681622Sru	 0,			/* bitpos */
11781622Sru	 complain_overflow_dont, /* complain_on_overflow */
118206374Sjkim	 bfd_elf_generic_reloc,	/* special_function */
119206374Sjkim	 "R_AVR_16",		/* name */
12043844Syokota	 FALSE,			/* partial_inplace */
12143725Syokota	 0xffff,		/* src_mask */
122154398Sbrueffer	 0xffff,		/* dst_mask */
123154398Sbrueffer	 FALSE),		/* pcrel_offset */
12443844Syokota
125216065Sdougb  /* A 16 bit absolute relocation for command address.  */
126216065Sdougb  HOWTO (R_AVR_16_PM,		/* type */
127216065Sdougb	 1,			/* rightshift */
128216065Sdougb	 1,			/* size (0 = byte, 1 = short, 2 = long) */
12943844Syokota	 16,			/* bitsize */
13081622Sru	 FALSE,			/* pc_relative */
131206374Sjkim	 0,			/* bitpos */
132206374Sjkim	 complain_overflow_bitfield, /* complain_on_overflow */
13343844Syokota	 bfd_elf_generic_reloc,	/* special_function */
13462978Sdannyboy	 "R_AVR_16_PM",		/* name */
13543844Syokota	 FALSE,			/* partial_inplace */
13643725Syokota	 0xffff,		/* src_mask */
13743844Syokota	 0xffff,		/* dst_mask */
13843725Syokota	 FALSE),		/* pcrel_offset */
13943844Syokota  /* A low 8 bit absolute relocation of 16 bit address.
14043725Syokota     For LDI command.  */
14143725Syokota  HOWTO (R_AVR_LO8_LDI,		/* type */
14243725Syokota	 0,			/* rightshift */
14376175Sschweikh	 1,			/* size (0 = byte, 1 = short, 2 = long) */
14449792Schris	 8,			/* bitsize */
14543725Syokota	 FALSE,			/* pc_relative */
14643725Syokota	 0,			/* bitpos */
14743725Syokota	 complain_overflow_dont, /* complain_on_overflow */
14843844Syokota	 bfd_elf_generic_reloc,	/* special_function */
14943725Syokota	 "R_AVR_LO8_LDI",	/* name */
15043844Syokota	 FALSE,			/* partial_inplace */
15143725Syokota	 0xffff,		/* src_mask */
15243725Syokota	 0xffff,		/* dst_mask */
15343725Syokota	 FALSE),		/* pcrel_offset */
15443725Syokota  /* A high 8 bit absolute relocation of 16 bit address.
15543725Syokota     For LDI command.  */
15643725Syokota  HOWTO (R_AVR_HI8_LDI,		/* type */
15743725Syokota	 8,			/* rightshift */
15843725Syokota	 1,			/* size (0 = byte, 1 = short, 2 = long) */
15976175Sschweikh	 8,			/* bitsize */
16043725Syokota	 FALSE,			/* pc_relative */
16143725Syokota	 0,			/* bitpos */
16243725Syokota	 complain_overflow_dont, /* complain_on_overflow */
16343725Syokota	 bfd_elf_generic_reloc,	/* special_function */
16476175Sschweikh	 "R_AVR_HI8_LDI",	/* name */
16543844Syokota	 FALSE,			/* partial_inplace */
16671263Sru	 0xffff,		/* src_mask */
16743844Syokota	 0xffff,		/* dst_mask */
16857676Ssheldonh	 FALSE),		/* pcrel_offset */
16957676Ssheldonh  /* A high 6 bit absolute relocation of 22 bit address.
17043725Syokota     For LDI command.  */
17143844Syokota  HOWTO (R_AVR_HH8_LDI,		/* type */
17281251Sru	 16,			/* rightshift */
17381251Sru	 1,			/* size (0 = byte, 1 = short, 2 = long) */
17481251Sru	 8,			/* bitsize */
17543725Syokota	 FALSE,			/* pc_relative */
17643725Syokota	 0,			/* bitpos */
17743725Syokota	 complain_overflow_dont, /* complain_on_overflow */
17843725Syokota	 bfd_elf_generic_reloc,	/* special_function */
17943844Syokota	 "R_AVR_HH8_LDI",	/* name */
18065013Ssheldonh	 FALSE,			/* partial_inplace */
18176175Sschweikh	 0xffff,		/* src_mask */
18243725Syokota	 0xffff,		/* dst_mask */
18343844Syokota	 FALSE),		/* pcrel_offset */
18465013Ssheldonh  /* A negative low 8 bit absolute relocation of 16 bit address.
18543844Syokota     For LDI command.  */
18643725Syokota  HOWTO (R_AVR_LO8_LDI_NEG,	/* type */
18743725Syokota	 0,			/* rightshift */
18866434Smarko	 1,			/* size (0 = byte, 1 = short, 2 = long) */
18971895Sru	 8,			/* bitsize */
19051866Sdcs	 FALSE,			/* pc_relative */
19171895Sru	 0,			/* bitpos */
19243725Syokota	 complain_overflow_dont, /* complain_on_overflow */
19371895Sru	 bfd_elf_generic_reloc,	/* special_function */
19443725Syokota	 "R_AVR_LO8_LDI_NEG",	/* name */
19571895Sru	 FALSE,			/* partial_inplace */
19643725Syokota	 0xffff,		/* src_mask */
19771895Sru	 0xffff,		/* dst_mask */
19843725Syokota	 FALSE),		/* pcrel_offset */
19943725Syokota  /* A hegative high 8 bit absolute relocation of 16 bit address.
20068854Sru     For LDI command.  */
20176175Sschweikh  HOWTO (R_AVR_HI8_LDI_NEG,	/* type */
20243844Syokota	 8,			/* rightshift */
20343844Syokota	 1,			/* size (0 = byte, 1 = short, 2 = long) */
20476175Sschweikh	 8,			/* bitsize */
20543844Syokota	 FALSE,			/* pc_relative */
20651866Sdcs	 0,			/* bitpos */
20751866Sdcs	 complain_overflow_dont, /* complain_on_overflow */
20881251Sru	 bfd_elf_generic_reloc,	/* special_function */
20981251Sru	 "R_AVR_HI8_LDI_NEG",	/* name */
21051866Sdcs	 FALSE,			/* partial_inplace */
21143725Syokota	 0xffff,		/* src_mask */
21251866Sdcs	 0xffff,		/* dst_mask */
21351866Sdcs	 FALSE),		/* pcrel_offset */
214128035Sschweikh  /* A hegative high 6 bit absolute relocation of 22 bit address.
21543725Syokota     For LDI command.  */
21643725Syokota  HOWTO (R_AVR_HH8_LDI_NEG,	/* type */
21776175Sschweikh	 16,			/* rightshift */
218128035Sschweikh	 1,			/* size (0 = byte, 1 = short, 2 = long) */
21943725Syokota	 8,			/* bitsize */
22043725Syokota	 FALSE,			/* pc_relative */
22143725Syokota	 0,			/* bitpos */
22243844Syokota	 complain_overflow_dont, /* complain_on_overflow */
22343725Syokota	 bfd_elf_generic_reloc,	/* special_function */
22451866Sdcs	 "R_AVR_HH8_LDI_NEG",	/* name */
22551866Sdcs	 FALSE,			/* partial_inplace */
22651866Sdcs	 0xffff,		/* src_mask */
227128035Sschweikh	 0xffff,		/* dst_mask */
22843725Syokota	 FALSE),		/* pcrel_offset */
22943725Syokota  /* A low 8 bit absolute relocation of 24 bit program memory address.
23043725Syokota     For LDI command.  */
23143725Syokota  HOWTO (R_AVR_LO8_LDI_PM,	/* type */
23243725Syokota	 1,			/* rightshift */
23343725Syokota	 1,			/* size (0 = byte, 1 = short, 2 = long) */
234228445Seadler	 8,			/* bitsize */
235228445Seadler	 FALSE,			/* pc_relative */
236228445Seadler	 0,			/* bitpos */
237235317Sgjb	 complain_overflow_dont, /* complain_on_overflow */
238228445Seadler	 bfd_elf_generic_reloc,	/* special_function */
239228445Seadler	 "R_AVR_LO8_LDI_PM",	/* name */
240228445Seadler	 FALSE,			/* partial_inplace */
241228445Seadler	 0xffff,		/* src_mask */
242228445Seadler	 0xffff,		/* dst_mask */
24343725Syokota	 FALSE),		/* pcrel_offset */
24443725Syokota  /* A high 8 bit absolute relocation of 16 bit program memory address.
24543725Syokota     For LDI command.  */
24643844Syokota  HOWTO (R_AVR_HI8_LDI_PM,	/* type */
24743725Syokota	 9,			/* rightshift */
24851866Sdcs	 1,			/* size (0 = byte, 1 = short, 2 = long) */
24943725Syokota	 8,			/* bitsize */
25043725Syokota	 FALSE,			/* pc_relative */
25168753Sben	 0,			/* bitpos */
25243725Syokota	 complain_overflow_dont, /* complain_on_overflow */
25343725Syokota	 bfd_elf_generic_reloc,	/* special_function */
25443725Syokota	 "R_AVR_HI8_LDI_PM",	/* name */
25543725Syokota	 FALSE,			/* partial_inplace */
25643725Syokota	 0xffff,		/* src_mask */
25743725Syokota	 0xffff,		/* dst_mask */
25869027Sru	 FALSE),		/* pcrel_offset */
25943725Syokota  /* A high 8 bit absolute relocation of 24 bit program memory address.
26043725Syokota     For LDI command.  */
26143725Syokota  HOWTO (R_AVR_HH8_LDI_PM,	/* type */
26243725Syokota	 17,			/* rightshift */
26343844Syokota	 1,			/* size (0 = byte, 1 = short, 2 = long) */
26443844Syokota	 8,			/* bitsize */
26543844Syokota	 FALSE,			/* pc_relative */
26643844Syokota	 0,			/* bitpos */
26743844Syokota	 complain_overflow_dont, /* complain_on_overflow */
26843844Syokota	 bfd_elf_generic_reloc,	/* special_function */
26945628Sdes	 "R_AVR_HH8_LDI_PM",	/* name */
27045628Sdes	 FALSE,			/* partial_inplace */
27145628Sdes	 0xffff,		/* src_mask */
27268718Sru	 0xffff,		/* dst_mask */
27345628Sdes	 FALSE),		/* pcrel_offset */
27445628Sdes  /* A low 8 bit absolute relocation of a negative 24 bit
27549792Schris     program memory address.  For LDI command.  */
276228445Seadler  HOWTO (R_AVR_LO8_LDI_PM_NEG,	/* type */
277228445Seadler	 1,			/* rightshift */
278228445Seadler	 1,			/* size (0 = byte, 1 = short, 2 = long) */
279228445Seadler	 8,			/* bitsize */
280228445Seadler	 FALSE,			/* pc_relative */
281228445Seadler	 0,			/* bitpos */
282228445Seadler	 complain_overflow_dont, /* complain_on_overflow */
283228445Seadler	 bfd_elf_generic_reloc,	/* special_function */
284228445Seadler	 "R_AVR_LO8_LDI_PM_NEG", /* name */
285208027Suqs	 FALSE,			/* partial_inplace */
286208027Suqs	 0xffff,		/* src_mask */
287208027Suqs	 0xffff,		/* dst_mask */
288208027Suqs	 FALSE),		/* pcrel_offset */
289140561Sru  /* A high 8 bit absolute relocation of a negative 16 bit
290140561Sru     program memory address.  For LDI command.  */
291140561Sru  HOWTO (R_AVR_HI8_LDI_PM_NEG,	/* type */
292140561Sru	 9,			/* rightshift */
293	 1,			/* size (0 = byte, 1 = short, 2 = long) */
294	 8,			/* bitsize */
295	 FALSE,			/* pc_relative */
296	 0,			/* bitpos */
297	 complain_overflow_dont, /* complain_on_overflow */
298	 bfd_elf_generic_reloc,	/* special_function */
299	 "R_AVR_HI8_LDI_PM_NEG", /* name */
300	 FALSE,			/* partial_inplace */
301	 0xffff,		/* src_mask */
302	 0xffff,		/* dst_mask */
303	 FALSE),		/* pcrel_offset */
304  /* A high 8 bit absolute relocation of a negative 24 bit
305     program memory address.  For LDI command.  */
306  HOWTO (R_AVR_HH8_LDI_PM_NEG,	/* type */
307	 17,			/* rightshift */
308	 1,			/* size (0 = byte, 1 = short, 2 = long) */
309	 8,			/* bitsize */
310	 FALSE,			/* pc_relative */
311	 0,			/* bitpos */
312	 complain_overflow_dont, /* complain_on_overflow */
313	 bfd_elf_generic_reloc,	/* special_function */
314	 "R_AVR_HH8_LDI_PM_NEG", /* name */
315	 FALSE,			/* partial_inplace */
316	 0xffff,		/* src_mask */
317	 0xffff,		/* dst_mask */
318	 FALSE),		/* pcrel_offset */
319  /* Relocation for CALL command in ATmega.  */
320  HOWTO (R_AVR_CALL,		/* type */
321	 1,			/* rightshift */
322	 2,			/* size (0 = byte, 1 = short, 2 = long) */
323	 23,			/* bitsize */
324	 FALSE,			/* pc_relative */
325	 0,			/* bitpos */
326	 complain_overflow_dont, /* complain_on_overflow */
327	 bfd_elf_generic_reloc,	/* special_function */
328	 "R_AVR_CALL",		/* name */
329	 FALSE,			/* partial_inplace */
330	 0xffffffff,		/* src_mask */
331	 0xffffffff,		/* dst_mask */
332	 FALSE)			/* pcrel_offset */
333};
334
335/* Map BFD reloc types to AVR ELF reloc types.  */
336
337struct avr_reloc_map
338{
339  bfd_reloc_code_real_type bfd_reloc_val;
340  unsigned int elf_reloc_val;
341};
342
343 static const struct avr_reloc_map avr_reloc_map[] =
344{
345  { BFD_RELOC_NONE,                 R_AVR_NONE },
346  { BFD_RELOC_32,                   R_AVR_32 },
347  { BFD_RELOC_AVR_7_PCREL,          R_AVR_7_PCREL },
348  { BFD_RELOC_AVR_13_PCREL,         R_AVR_13_PCREL },
349  { BFD_RELOC_16,                   R_AVR_16 },
350  { BFD_RELOC_AVR_16_PM,            R_AVR_16_PM },
351  { BFD_RELOC_AVR_LO8_LDI,          R_AVR_LO8_LDI},
352  { BFD_RELOC_AVR_HI8_LDI,          R_AVR_HI8_LDI },
353  { BFD_RELOC_AVR_HH8_LDI,          R_AVR_HH8_LDI },
354  { BFD_RELOC_AVR_LO8_LDI_NEG,      R_AVR_LO8_LDI_NEG },
355  { BFD_RELOC_AVR_HI8_LDI_NEG,      R_AVR_HI8_LDI_NEG },
356  { BFD_RELOC_AVR_HH8_LDI_NEG,      R_AVR_HH8_LDI_NEG },
357  { BFD_RELOC_AVR_LO8_LDI_PM,       R_AVR_LO8_LDI_PM },
358  { BFD_RELOC_AVR_HI8_LDI_PM,       R_AVR_HI8_LDI_PM },
359  { BFD_RELOC_AVR_HH8_LDI_PM,       R_AVR_HH8_LDI_PM },
360  { BFD_RELOC_AVR_LO8_LDI_PM_NEG,   R_AVR_LO8_LDI_PM_NEG },
361  { BFD_RELOC_AVR_HI8_LDI_PM_NEG,   R_AVR_HI8_LDI_PM_NEG },
362  { BFD_RELOC_AVR_HH8_LDI_PM_NEG,   R_AVR_HH8_LDI_PM_NEG },
363  { BFD_RELOC_AVR_CALL,             R_AVR_CALL }
364};
365
366static reloc_howto_type *
367bfd_elf32_bfd_reloc_type_lookup (abfd, code)
368     bfd *abfd ATTRIBUTE_UNUSED;
369     bfd_reloc_code_real_type code;
370{
371  unsigned int i;
372
373  for (i = 0;
374       i < sizeof (avr_reloc_map) / sizeof (struct avr_reloc_map);
375       i++)
376    {
377      if (avr_reloc_map[i].bfd_reloc_val == code)
378	return &elf_avr_howto_table[avr_reloc_map[i].elf_reloc_val];
379    }
380
381  return NULL;
382}
383
384/* Set the howto pointer for an AVR ELF reloc.  */
385
386static void
387avr_info_to_howto_rela (abfd, cache_ptr, dst)
388     bfd *abfd ATTRIBUTE_UNUSED;
389     arelent *cache_ptr;
390     Elf_Internal_Rela *dst;
391{
392  unsigned int r_type;
393
394  r_type = ELF32_R_TYPE (dst->r_info);
395  BFD_ASSERT (r_type < (unsigned int) R_AVR_max);
396  cache_ptr->howto = &elf_avr_howto_table[r_type];
397}
398
399static asection *
400elf32_avr_gc_mark_hook (sec, info, rel, h, sym)
401     asection *sec;
402     struct bfd_link_info *info ATTRIBUTE_UNUSED;
403     Elf_Internal_Rela *rel;
404     struct elf_link_hash_entry *h;
405     Elf_Internal_Sym *sym;
406{
407  if (h != NULL)
408    {
409      switch (ELF32_R_TYPE (rel->r_info))
410	{
411	default:
412	  switch (h->root.type)
413	    {
414	    case bfd_link_hash_defined:
415	    case bfd_link_hash_defweak:
416	      return h->root.u.def.section;
417
418	    case bfd_link_hash_common:
419	      return h->root.u.c.p->section;
420
421	    default:
422	      break;
423	    }
424	}
425    }
426  else
427    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
428
429  return NULL;
430}
431
432static bfd_boolean
433elf32_avr_gc_sweep_hook (abfd, info, sec, relocs)
434     bfd *abfd ATTRIBUTE_UNUSED;
435     struct bfd_link_info *info ATTRIBUTE_UNUSED;
436     asection *sec ATTRIBUTE_UNUSED;
437     const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
438{
439  /* We don't use got and plt entries for avr.  */
440  return TRUE;
441}
442
443/* Look through the relocs for a section during the first phase.
444   Since we don't do .gots or .plts, we just need to consider the
445   virtual table relocs for gc.  */
446
447static bfd_boolean
448elf32_avr_check_relocs (abfd, info, sec, relocs)
449     bfd *abfd;
450     struct bfd_link_info *info;
451     asection *sec;
452     const Elf_Internal_Rela *relocs;
453{
454  Elf_Internal_Shdr *symtab_hdr;
455  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
456  const Elf_Internal_Rela *rel;
457  const Elf_Internal_Rela *rel_end;
458
459  if (info->relocatable)
460    return TRUE;
461
462  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
463  sym_hashes = elf_sym_hashes (abfd);
464  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
465  if (!elf_bad_symtab (abfd))
466    sym_hashes_end -= symtab_hdr->sh_info;
467
468  rel_end = relocs + sec->reloc_count;
469  for (rel = relocs; rel < rel_end; rel++)
470    {
471      struct elf_link_hash_entry *h;
472      unsigned long r_symndx;
473
474      r_symndx = ELF32_R_SYM (rel->r_info);
475      if (r_symndx < symtab_hdr->sh_info)
476        h = NULL;
477      else
478        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
479    }
480
481  return TRUE;
482}
483
484/* Perform a single relocation.  By default we use the standard BFD
485   routines, but a few relocs, we have to do them ourselves.  */
486
487static bfd_reloc_status_type
488avr_final_link_relocate (howto, input_bfd, input_section,
489			 contents, rel, relocation)
490     reloc_howto_type *  howto;
491     bfd *               input_bfd;
492     asection *          input_section;
493     bfd_byte *          contents;
494     Elf_Internal_Rela * rel;
495     bfd_vma             relocation;
496{
497  bfd_reloc_status_type r = bfd_reloc_ok;
498  bfd_vma               x;
499  bfd_signed_vma	srel;
500
501  switch (howto->type)
502    {
503    case R_AVR_7_PCREL:
504      contents += rel->r_offset;
505      srel = (bfd_signed_vma) relocation;
506      srel += rel->r_addend;
507      srel -= rel->r_offset;
508      srel -= 2;	/* Branch instructions add 2 to the PC...  */
509      srel -= (input_section->output_section->vma +
510	       input_section->output_offset);
511
512      if (srel & 1)
513	return bfd_reloc_outofrange;
514      if (srel > ((1 << 7) - 1) || (srel < - (1 << 7)))
515	return bfd_reloc_overflow;
516      x = bfd_get_16 (input_bfd, contents);
517      x = (x & 0xfc07) | (((srel >> 1) << 3) & 0x3f8);
518      bfd_put_16 (input_bfd, x, contents);
519      break;
520
521    case R_AVR_13_PCREL:
522      contents   += rel->r_offset;
523      srel = (bfd_signed_vma) relocation;
524      srel += rel->r_addend;
525      srel -= rel->r_offset;
526      srel -= 2;	/* Branch instructions add 2 to the PC...  */
527      srel -= (input_section->output_section->vma +
528	       input_section->output_offset);
529
530      if (srel & 1)
531	return bfd_reloc_outofrange;
532
533      /* AVR addresses commands as words.  */
534      srel >>= 1;
535
536      /* Check for overflow.  */
537      if (srel < -2048 || srel > 2047)
538	{
539	  /* Apply WRAPAROUND if possible.  */
540	  switch (bfd_get_mach (input_bfd))
541	    {
542	    case bfd_mach_avr2:
543	    case bfd_mach_avr4:
544	      break;
545
546	    default:
547	      return bfd_reloc_overflow;
548	    }
549	}
550
551      x = bfd_get_16 (input_bfd, contents);
552      x = (x & 0xf000) | (srel & 0xfff);
553      bfd_put_16 (input_bfd, x, contents);
554      break;
555
556    case R_AVR_LO8_LDI:
557      contents += rel->r_offset;
558      srel = (bfd_signed_vma) relocation + rel->r_addend;
559      x = bfd_get_16 (input_bfd, contents);
560      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
561      bfd_put_16 (input_bfd, x, contents);
562      break;
563
564    case R_AVR_HI8_LDI:
565      contents += rel->r_offset;
566      srel = (bfd_signed_vma) relocation + rel->r_addend;
567      srel = (srel >> 8) & 0xff;
568      x = bfd_get_16 (input_bfd, contents);
569      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
570      bfd_put_16 (input_bfd, x, contents);
571      break;
572
573    case R_AVR_HH8_LDI:
574      contents += rel->r_offset;
575      srel = (bfd_signed_vma) relocation + rel->r_addend;
576      srel = (srel >> 16) & 0xff;
577      x = bfd_get_16 (input_bfd, contents);
578      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
579      bfd_put_16 (input_bfd, x, contents);
580      break;
581
582    case R_AVR_LO8_LDI_NEG:
583      contents += rel->r_offset;
584      srel = (bfd_signed_vma) relocation + rel->r_addend;
585      srel = -srel;
586      x = bfd_get_16 (input_bfd, contents);
587      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
588      bfd_put_16 (input_bfd, x, contents);
589      break;
590
591    case R_AVR_HI8_LDI_NEG:
592      contents += rel->r_offset;
593      srel = (bfd_signed_vma) relocation + rel->r_addend;
594      srel = -srel;
595      srel = (srel >> 8) & 0xff;
596      x = bfd_get_16 (input_bfd, contents);
597      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
598      bfd_put_16 (input_bfd, x, contents);
599      break;
600
601    case R_AVR_HH8_LDI_NEG:
602      contents += rel->r_offset;
603      srel = (bfd_signed_vma) relocation + rel->r_addend;
604      srel = -srel;
605      srel = (srel >> 16) & 0xff;
606      x = bfd_get_16 (input_bfd, contents);
607      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
608      bfd_put_16 (input_bfd, x, contents);
609      break;
610
611    case R_AVR_LO8_LDI_PM:
612      contents += rel->r_offset;
613      srel = (bfd_signed_vma) relocation + rel->r_addend;
614      if (srel & 1)
615	return bfd_reloc_outofrange;
616      srel = srel >> 1;
617      x = bfd_get_16 (input_bfd, contents);
618      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
619      bfd_put_16 (input_bfd, x, contents);
620      break;
621
622    case R_AVR_HI8_LDI_PM:
623      contents += rel->r_offset;
624      srel = (bfd_signed_vma) relocation + rel->r_addend;
625      if (srel & 1)
626	return bfd_reloc_outofrange;
627      srel = srel >> 1;
628      srel = (srel >> 8) & 0xff;
629      x = bfd_get_16 (input_bfd, contents);
630      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
631      bfd_put_16 (input_bfd, x, contents);
632      break;
633
634    case R_AVR_HH8_LDI_PM:
635      contents += rel->r_offset;
636      srel = (bfd_signed_vma) relocation + rel->r_addend;
637      if (srel & 1)
638	return bfd_reloc_outofrange;
639      srel = srel >> 1;
640      srel = (srel >> 16) & 0xff;
641      x = bfd_get_16 (input_bfd, contents);
642      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
643      bfd_put_16 (input_bfd, x, contents);
644      break;
645
646    case R_AVR_LO8_LDI_PM_NEG:
647      contents += rel->r_offset;
648      srel = (bfd_signed_vma) relocation + rel->r_addend;
649      srel = -srel;
650      if (srel & 1)
651	return bfd_reloc_outofrange;
652      srel = srel >> 1;
653      x = bfd_get_16 (input_bfd, contents);
654      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
655      bfd_put_16 (input_bfd, x, contents);
656      break;
657
658    case R_AVR_HI8_LDI_PM_NEG:
659      contents += rel->r_offset;
660      srel = (bfd_signed_vma) relocation + rel->r_addend;
661      srel = -srel;
662      if (srel & 1)
663	return bfd_reloc_outofrange;
664      srel = srel >> 1;
665      srel = (srel >> 8) & 0xff;
666      x = bfd_get_16 (input_bfd, contents);
667      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
668      bfd_put_16 (input_bfd, x, contents);
669      break;
670
671    case R_AVR_HH8_LDI_PM_NEG:
672      contents += rel->r_offset;
673      srel = (bfd_signed_vma) relocation + rel->r_addend;
674      srel = -srel;
675      if (srel & 1)
676	return bfd_reloc_outofrange;
677      srel = srel >> 1;
678      srel = (srel >> 16) & 0xff;
679      x = bfd_get_16 (input_bfd, contents);
680      x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
681      bfd_put_16 (input_bfd, x, contents);
682      break;
683
684    case R_AVR_CALL:
685      contents += rel->r_offset;
686      srel = (bfd_signed_vma) relocation + rel->r_addend;
687      if (srel & 1)
688	return bfd_reloc_outofrange;
689      srel = srel >> 1;
690      x = bfd_get_16 (input_bfd, contents);
691      x |= ((srel & 0x10000) | ((srel << 3) & 0x1f00000)) >> 16;
692      bfd_put_16 (input_bfd, x, contents);
693      bfd_put_16 (input_bfd, (bfd_vma) srel & 0xffff, contents+2);
694      break;
695
696    default:
697      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
698				    contents, rel->r_offset,
699				    relocation, rel->r_addend);
700    }
701
702  return r;
703}
704
705/* Relocate an AVR ELF section.  */
706static bfd_boolean
707elf32_avr_relocate_section (output_bfd, info, input_bfd, input_section,
708			    contents, relocs, local_syms, local_sections)
709     bfd *output_bfd ATTRIBUTE_UNUSED;
710     struct bfd_link_info *info;
711     bfd *input_bfd;
712     asection *input_section;
713     bfd_byte *contents;
714     Elf_Internal_Rela *relocs;
715     Elf_Internal_Sym *local_syms;
716     asection **local_sections;
717{
718  Elf_Internal_Shdr *           symtab_hdr;
719  struct elf_link_hash_entry ** sym_hashes;
720  Elf_Internal_Rela *           rel;
721  Elf_Internal_Rela *           relend;
722
723  if (info->relocatable)
724    return TRUE;
725
726  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
727  sym_hashes = elf_sym_hashes (input_bfd);
728  relend     = relocs + input_section->reloc_count;
729
730  for (rel = relocs; rel < relend; rel ++)
731    {
732      reloc_howto_type *           howto;
733      unsigned long                r_symndx;
734      Elf_Internal_Sym *           sym;
735      asection *                   sec;
736      struct elf_link_hash_entry * h;
737      bfd_vma                      relocation;
738      bfd_reloc_status_type        r;
739      const char *                 name = NULL;
740      int                          r_type;
741
742      /* This is a final link.  */
743      r_type = ELF32_R_TYPE (rel->r_info);
744      r_symndx = ELF32_R_SYM (rel->r_info);
745      howto  = elf_avr_howto_table + ELF32_R_TYPE (rel->r_info);
746      h      = NULL;
747      sym    = NULL;
748      sec    = NULL;
749
750      if (r_symndx < symtab_hdr->sh_info)
751	{
752	  sym = local_syms + r_symndx;
753	  sec = local_sections [r_symndx];
754	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
755
756	  name = bfd_elf_string_from_elf_section
757	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
758	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
759	}
760      else
761	{
762	  bfd_boolean unresolved_reloc, warned;
763
764	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
765				   r_symndx, symtab_hdr, sym_hashes,
766				   h, sec, relocation,
767				   unresolved_reloc, warned);
768	}
769
770      r = avr_final_link_relocate (howto, input_bfd, input_section,
771				   contents, rel, relocation);
772
773      if (r != bfd_reloc_ok)
774	{
775	  const char * msg = (const char *) NULL;
776
777	  switch (r)
778	    {
779	    case bfd_reloc_overflow:
780	      r = info->callbacks->reloc_overflow
781		(info, name, howto->name, (bfd_vma) 0,
782		 input_bfd, input_section, rel->r_offset);
783	      break;
784
785	    case bfd_reloc_undefined:
786	      r = info->callbacks->undefined_symbol
787		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
788	      break;
789
790	    case bfd_reloc_outofrange:
791	      msg = _("internal error: out of range error");
792	      break;
793
794	    case bfd_reloc_notsupported:
795	      msg = _("internal error: unsupported relocation error");
796	      break;
797
798	    case bfd_reloc_dangerous:
799	      msg = _("internal error: dangerous relocation");
800	      break;
801
802	    default:
803	      msg = _("internal error: unknown error");
804	      break;
805	    }
806
807	  if (msg)
808	    r = info->callbacks->warning
809	      (info, msg, name, input_bfd, input_section, rel->r_offset);
810
811	  if (! r)
812	    return FALSE;
813	}
814    }
815
816  return TRUE;
817}
818
819/* The final processing done just before writing out a AVR ELF object
820   file.  This gets the AVR architecture right based on the machine
821   number.  */
822
823static void
824bfd_elf_avr_final_write_processing (abfd, linker)
825     bfd *abfd;
826     bfd_boolean linker ATTRIBUTE_UNUSED;
827{
828  unsigned long val;
829
830  switch (bfd_get_mach (abfd))
831    {
832    default:
833    case bfd_mach_avr2:
834      val = E_AVR_MACH_AVR2;
835      break;
836
837    case bfd_mach_avr1:
838      val = E_AVR_MACH_AVR1;
839      break;
840
841    case bfd_mach_avr3:
842      val = E_AVR_MACH_AVR3;
843      break;
844
845    case bfd_mach_avr4:
846      val = E_AVR_MACH_AVR4;
847      break;
848
849    case bfd_mach_avr5:
850      val = E_AVR_MACH_AVR5;
851      break;
852    }
853
854  elf_elfheader (abfd)->e_machine = EM_AVR;
855  elf_elfheader (abfd)->e_flags &= ~ EF_AVR_MACH;
856  elf_elfheader (abfd)->e_flags |= val;
857}
858
859/* Set the right machine number.  */
860
861static bfd_boolean
862elf32_avr_object_p (abfd)
863     bfd *abfd;
864{
865  unsigned int e_set = bfd_mach_avr2;
866  if (elf_elfheader (abfd)->e_machine == EM_AVR
867      || elf_elfheader (abfd)->e_machine == EM_AVR_OLD)
868    {
869      int e_mach = elf_elfheader (abfd)->e_flags & EF_AVR_MACH;
870      switch (e_mach)
871	{
872	default:
873	case E_AVR_MACH_AVR2:
874	  e_set = bfd_mach_avr2;
875	  break;
876
877	case E_AVR_MACH_AVR1:
878	  e_set = bfd_mach_avr1;
879	  break;
880
881	case E_AVR_MACH_AVR3:
882	  e_set = bfd_mach_avr3;
883	  break;
884
885	case E_AVR_MACH_AVR4:
886	  e_set = bfd_mach_avr4;
887	  break;
888
889	case E_AVR_MACH_AVR5:
890	  e_set = bfd_mach_avr5;
891	  break;
892	}
893    }
894  return bfd_default_set_arch_mach (abfd, bfd_arch_avr,
895				    e_set);
896}
897
898#define ELF_ARCH		bfd_arch_avr
899#define ELF_MACHINE_CODE	EM_AVR
900#define ELF_MACHINE_ALT1	EM_AVR_OLD
901#define ELF_MAXPAGESIZE		1
902
903#define TARGET_LITTLE_SYM       bfd_elf32_avr_vec
904#define TARGET_LITTLE_NAME	"elf32-avr"
905
906#define elf_info_to_howto	             avr_info_to_howto_rela
907#define elf_info_to_howto_rel	             NULL
908#define elf_backend_relocate_section         elf32_avr_relocate_section
909#define elf_backend_gc_mark_hook             elf32_avr_gc_mark_hook
910#define elf_backend_gc_sweep_hook            elf32_avr_gc_sweep_hook
911#define elf_backend_check_relocs             elf32_avr_check_relocs
912#define elf_backend_can_gc_sections          1
913#define elf_backend_rela_normal		     1
914#define elf_backend_final_write_processing \
915					bfd_elf_avr_final_write_processing
916#define elf_backend_object_p		elf32_avr_object_p
917
918#include "elf32-target.h"
919