7649d456157a5dda2550dcbb1e1cc1172d909bb0
[external/binutils.git] / bfd / elf32-avr.c
1 /* AVR-specific support for 32-bit ELF
2    Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3    Contributed by Denis Chertykov <denisc@overta.ru>
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "elf-bfd.h"
25 #include "elf/avr.h"
26
27 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
28   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
29 static void avr_info_to_howto_rela
30   PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
31 static asection *elf32_avr_gc_mark_hook
32   PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
33            struct elf_link_hash_entry *, Elf_Internal_Sym *));
34 static bfd_boolean elf32_avr_gc_sweep_hook
35   PARAMS ((bfd *, struct bfd_link_info *, asection *,
36            const Elf_Internal_Rela *));
37 static bfd_boolean elf32_avr_check_relocs
38   PARAMS ((bfd *, struct bfd_link_info *, asection *,
39            const Elf_Internal_Rela *));
40 static bfd_reloc_status_type avr_final_link_relocate
41   PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
42            Elf_Internal_Rela *, bfd_vma));
43 static bfd_boolean elf32_avr_relocate_section
44   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
45            Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
46 static void bfd_elf_avr_final_write_processing PARAMS ((bfd *, bfd_boolean));
47 static bfd_boolean elf32_avr_object_p PARAMS ((bfd *));
48
49 static reloc_howto_type elf_avr_howto_table[] =
50 {
51   HOWTO (R_AVR_NONE,            /* type */
52          0,                     /* rightshift */
53          2,                     /* size (0 = byte, 1 = short, 2 = long) */
54          32,                    /* bitsize */
55          FALSE,                 /* pc_relative */
56          0,                     /* bitpos */
57          complain_overflow_bitfield, /* complain_on_overflow */
58          bfd_elf_generic_reloc, /* special_function */
59          "R_AVR_NONE",          /* name */
60          FALSE,                 /* partial_inplace */
61          0,                     /* src_mask */
62          0,                     /* dst_mask */
63          FALSE),                /* pcrel_offset */
64
65   HOWTO (R_AVR_32,              /* type */
66          0,                     /* rightshift */
67          2,                     /* size (0 = byte, 1 = short, 2 = long) */
68          32,                    /* bitsize */
69          FALSE,                 /* pc_relative */
70          0,                     /* bitpos */
71          complain_overflow_bitfield, /* complain_on_overflow */
72          bfd_elf_generic_reloc, /* special_function */
73          "R_AVR_32",            /* name */
74          FALSE,                 /* partial_inplace */
75          0xffffffff,            /* src_mask */
76          0xffffffff,            /* dst_mask */
77          FALSE),                /* pcrel_offset */
78
79   /* A 7 bit PC relative relocation.  */
80   HOWTO (R_AVR_7_PCREL,         /* type */
81          1,                     /* rightshift */
82          1,                     /* size (0 = byte, 1 = short, 2 = long) */
83          7,                     /* bitsize */
84          TRUE,                  /* pc_relative */
85          3,                     /* bitpos */
86          complain_overflow_bitfield, /* complain_on_overflow */
87          bfd_elf_generic_reloc, /* special_function */
88          "R_AVR_7_PCREL",       /* name */
89          FALSE,                 /* partial_inplace */
90          0xffff,                /* src_mask */
91          0xffff,                /* dst_mask */
92          TRUE),                 /* pcrel_offset */
93
94   /* A 13 bit PC relative relocation.  */
95   HOWTO (R_AVR_13_PCREL,        /* type */
96          1,                     /* rightshift */
97          1,                     /* size (0 = byte, 1 = short, 2 = long) */
98          13,                    /* bitsize */
99          TRUE,                  /* pc_relative */
100          0,                     /* bitpos */
101          complain_overflow_bitfield, /* complain_on_overflow */
102          bfd_elf_generic_reloc, /* special_function */
103          "R_AVR_13_PCREL",      /* name */
104          FALSE,                 /* partial_inplace */
105          0xfff,                 /* src_mask */
106          0xfff,                 /* dst_mask */
107          TRUE),                 /* pcrel_offset */
108
109   /* A 16 bit absolute relocation.  */
110   HOWTO (R_AVR_16,              /* type */
111          0,                     /* rightshift */
112          1,                     /* size (0 = byte, 1 = short, 2 = long) */
113          16,                    /* bitsize */
114          FALSE,                 /* pc_relative */
115          0,                     /* bitpos */
116          complain_overflow_dont, /* complain_on_overflow */
117          bfd_elf_generic_reloc, /* special_function */
118          "R_AVR_16",            /* name */
119          FALSE,                 /* partial_inplace */
120          0xffff,                /* src_mask */
121          0xffff,                /* dst_mask */
122          FALSE),                /* pcrel_offset */
123
124   /* A 16 bit absolute relocation for command address.  */
125   HOWTO (R_AVR_16_PM,           /* type */
126          1,                     /* rightshift */
127          1,                     /* size (0 = byte, 1 = short, 2 = long) */
128          16,                    /* bitsize */
129          FALSE,                 /* pc_relative */
130          0,                     /* bitpos */
131          complain_overflow_bitfield, /* complain_on_overflow */
132          bfd_elf_generic_reloc, /* special_function */
133          "R_AVR_16_PM",         /* name */
134          FALSE,                 /* partial_inplace */
135          0xffff,                /* src_mask */
136          0xffff,                /* dst_mask */
137          FALSE),                /* pcrel_offset */
138   /* A low 8 bit absolute relocation of 16 bit address.
139      For LDI command.  */
140   HOWTO (R_AVR_LO8_LDI,         /* type */
141          0,                     /* rightshift */
142          1,                     /* size (0 = byte, 1 = short, 2 = long) */
143          8,                     /* bitsize */
144          FALSE,                 /* pc_relative */
145          0,                     /* bitpos */
146          complain_overflow_dont, /* complain_on_overflow */
147          bfd_elf_generic_reloc, /* special_function */
148          "R_AVR_LO8_LDI",       /* name */
149          FALSE,                 /* partial_inplace */
150          0xffff,                /* src_mask */
151          0xffff,                /* dst_mask */
152          FALSE),                /* pcrel_offset */
153   /* A high 8 bit absolute relocation of 16 bit address.
154      For LDI command.  */
155   HOWTO (R_AVR_HI8_LDI,         /* type */
156          8,                     /* rightshift */
157          1,                     /* size (0 = byte, 1 = short, 2 = long) */
158          8,                     /* bitsize */
159          FALSE,                 /* pc_relative */
160          0,                     /* bitpos */
161          complain_overflow_dont, /* complain_on_overflow */
162          bfd_elf_generic_reloc, /* special_function */
163          "R_AVR_HI8_LDI",       /* name */
164          FALSE,                 /* partial_inplace */
165          0xffff,                /* src_mask */
166          0xffff,                /* dst_mask */
167          FALSE),                /* pcrel_offset */
168   /* A high 6 bit absolute relocation of 22 bit address.
169      For LDI command.  */
170   HOWTO (R_AVR_HH8_LDI,         /* type */
171          16,                    /* rightshift */
172          1,                     /* size (0 = byte, 1 = short, 2 = long) */
173          8,                     /* bitsize */
174          FALSE,                 /* pc_relative */
175          0,                     /* bitpos */
176          complain_overflow_dont, /* complain_on_overflow */
177          bfd_elf_generic_reloc, /* special_function */
178          "R_AVR_HH8_LDI",       /* name */
179          FALSE,                 /* partial_inplace */
180          0xffff,                /* src_mask */
181          0xffff,                /* dst_mask */
182          FALSE),                /* pcrel_offset */
183   /* A negative low 8 bit absolute relocation of 16 bit address.
184      For LDI command.  */
185   HOWTO (R_AVR_LO8_LDI_NEG,     /* type */
186          0,                     /* rightshift */
187          1,                     /* size (0 = byte, 1 = short, 2 = long) */
188          8,                     /* bitsize */
189          FALSE,                 /* pc_relative */
190          0,                     /* bitpos */
191          complain_overflow_dont, /* complain_on_overflow */
192          bfd_elf_generic_reloc, /* special_function */
193          "R_AVR_LO8_LDI_NEG",   /* name */
194          FALSE,                 /* partial_inplace */
195          0xffff,                /* src_mask */
196          0xffff,                /* dst_mask */
197          FALSE),                /* pcrel_offset */
198   /* A hegative high 8 bit absolute relocation of 16 bit address.
199      For LDI command.  */
200   HOWTO (R_AVR_HI8_LDI_NEG,     /* type */
201          8,                     /* rightshift */
202          1,                     /* size (0 = byte, 1 = short, 2 = long) */
203          8,                     /* bitsize */
204          FALSE,                 /* pc_relative */
205          0,                     /* bitpos */
206          complain_overflow_dont, /* complain_on_overflow */
207          bfd_elf_generic_reloc, /* special_function */
208          "R_AVR_HI8_LDI_NEG",   /* name */
209          FALSE,                 /* partial_inplace */
210          0xffff,                /* src_mask */
211          0xffff,                /* dst_mask */
212          FALSE),                /* pcrel_offset */
213   /* A hegative high 6 bit absolute relocation of 22 bit address.
214      For LDI command.  */
215   HOWTO (R_AVR_HH8_LDI_NEG,     /* type */
216          16,                    /* rightshift */
217          1,                     /* size (0 = byte, 1 = short, 2 = long) */
218          8,                     /* bitsize */
219          FALSE,                 /* pc_relative */
220          0,                     /* bitpos */
221          complain_overflow_dont, /* complain_on_overflow */
222          bfd_elf_generic_reloc, /* special_function */
223          "R_AVR_HH8_LDI_NEG",   /* name */
224          FALSE,                 /* partial_inplace */
225          0xffff,                /* src_mask */
226          0xffff,                /* dst_mask */
227          FALSE),                /* pcrel_offset */
228   /* A low 8 bit absolute relocation of 24 bit program memory address.
229      For LDI command.  */
230   HOWTO (R_AVR_LO8_LDI_PM,      /* type */
231          1,                     /* rightshift */
232          1,                     /* size (0 = byte, 1 = short, 2 = long) */
233          8,                     /* bitsize */
234          FALSE,                 /* pc_relative */
235          0,                     /* bitpos */
236          complain_overflow_dont, /* complain_on_overflow */
237          bfd_elf_generic_reloc, /* special_function */
238          "R_AVR_LO8_LDI_PM",    /* name */
239          FALSE,                 /* partial_inplace */
240          0xffff,                /* src_mask */
241          0xffff,                /* dst_mask */
242          FALSE),                /* pcrel_offset */
243   /* A high 8 bit absolute relocation of 16 bit program memory address.
244      For LDI command.  */
245   HOWTO (R_AVR_HI8_LDI_PM,      /* type */
246          9,                     /* rightshift */
247          1,                     /* size (0 = byte, 1 = short, 2 = long) */
248          8,                     /* bitsize */
249          FALSE,                 /* pc_relative */
250          0,                     /* bitpos */
251          complain_overflow_dont, /* complain_on_overflow */
252          bfd_elf_generic_reloc, /* special_function */
253          "R_AVR_HI8_LDI_PM",    /* name */
254          FALSE,                 /* partial_inplace */
255          0xffff,                /* src_mask */
256          0xffff,                /* dst_mask */
257          FALSE),                /* pcrel_offset */
258   /* A high 8 bit absolute relocation of 24 bit program memory address.
259      For LDI command.  */
260   HOWTO (R_AVR_HH8_LDI_PM,      /* type */
261          17,                    /* rightshift */
262          1,                     /* size (0 = byte, 1 = short, 2 = long) */
263          8,                     /* bitsize */
264          FALSE,                 /* pc_relative */
265          0,                     /* bitpos */
266          complain_overflow_dont, /* complain_on_overflow */
267          bfd_elf_generic_reloc, /* special_function */
268          "R_AVR_HH8_LDI_PM",    /* name */
269          FALSE,                 /* partial_inplace */
270          0xffff,                /* src_mask */
271          0xffff,                /* dst_mask */
272          FALSE),                /* pcrel_offset */
273   /* A low 8 bit absolute relocation of a negative 24 bit
274      program memory address.  For LDI command.  */
275   HOWTO (R_AVR_LO8_LDI_PM_NEG,  /* type */
276          1,                     /* rightshift */
277          1,                     /* size (0 = byte, 1 = short, 2 = long) */
278          8,                     /* bitsize */
279          FALSE,                 /* pc_relative */
280          0,                     /* bitpos */
281          complain_overflow_dont, /* complain_on_overflow */
282          bfd_elf_generic_reloc, /* special_function */
283          "R_AVR_LO8_LDI_PM_NEG", /* name */
284          FALSE,                 /* partial_inplace */
285          0xffff,                /* src_mask */
286          0xffff,                /* dst_mask */
287          FALSE),                /* pcrel_offset */
288   /* A high 8 bit absolute relocation of a negative 16 bit
289      program memory address.  For LDI command.  */
290   HOWTO (R_AVR_HI8_LDI_PM_NEG,  /* type */
291          9,                     /* rightshift */
292          1,                     /* size (0 = byte, 1 = short, 2 = long) */
293          8,                     /* bitsize */
294          FALSE,                 /* pc_relative */
295          0,                     /* bitpos */
296          complain_overflow_dont, /* complain_on_overflow */
297          bfd_elf_generic_reloc, /* special_function */
298          "R_AVR_HI8_LDI_PM_NEG", /* name */
299          FALSE,                 /* partial_inplace */
300          0xffff,                /* src_mask */
301          0xffff,                /* dst_mask */
302          FALSE),                /* pcrel_offset */
303   /* A high 8 bit absolute relocation of a negative 24 bit
304      program memory address.  For LDI command.  */
305   HOWTO (R_AVR_HH8_LDI_PM_NEG,  /* type */
306          17,                    /* rightshift */
307          1,                     /* size (0 = byte, 1 = short, 2 = long) */
308          8,                     /* bitsize */
309          FALSE,                 /* pc_relative */
310          0,                     /* bitpos */
311          complain_overflow_dont, /* complain_on_overflow */
312          bfd_elf_generic_reloc, /* special_function */
313          "R_AVR_HH8_LDI_PM_NEG", /* name */
314          FALSE,                 /* partial_inplace */
315          0xffff,                /* src_mask */
316          0xffff,                /* dst_mask */
317          FALSE),                /* pcrel_offset */
318   /* Relocation for CALL command in ATmega.  */
319   HOWTO (R_AVR_CALL,            /* type */
320          1,                     /* rightshift */
321          2,                     /* size (0 = byte, 1 = short, 2 = long) */
322          23,                    /* bitsize */
323          FALSE,                 /* pc_relative */
324          0,                     /* bitpos */
325          complain_overflow_dont, /* complain_on_overflow */
326          bfd_elf_generic_reloc, /* special_function */
327          "R_AVR_CALL",          /* name */
328          FALSE,                 /* partial_inplace */
329          0xffffffff,            /* src_mask */
330          0xffffffff,            /* dst_mask */
331          FALSE)                 /* pcrel_offset */
332 };
333
334 /* Map BFD reloc types to AVR ELF reloc types.  */
335
336 struct avr_reloc_map
337 {
338   bfd_reloc_code_real_type bfd_reloc_val;
339   unsigned int elf_reloc_val;
340 };
341
342  static const struct avr_reloc_map avr_reloc_map[] =
343 {
344   { BFD_RELOC_NONE,                 R_AVR_NONE },
345   { BFD_RELOC_32,                   R_AVR_32 },
346   { BFD_RELOC_AVR_7_PCREL,          R_AVR_7_PCREL },
347   { BFD_RELOC_AVR_13_PCREL,         R_AVR_13_PCREL },
348   { BFD_RELOC_16,                   R_AVR_16 },
349   { BFD_RELOC_AVR_16_PM,            R_AVR_16_PM },
350   { BFD_RELOC_AVR_LO8_LDI,          R_AVR_LO8_LDI},
351   { BFD_RELOC_AVR_HI8_LDI,          R_AVR_HI8_LDI },
352   { BFD_RELOC_AVR_HH8_LDI,          R_AVR_HH8_LDI },
353   { BFD_RELOC_AVR_LO8_LDI_NEG,      R_AVR_LO8_LDI_NEG },
354   { BFD_RELOC_AVR_HI8_LDI_NEG,      R_AVR_HI8_LDI_NEG },
355   { BFD_RELOC_AVR_HH8_LDI_NEG,      R_AVR_HH8_LDI_NEG },
356   { BFD_RELOC_AVR_LO8_LDI_PM,       R_AVR_LO8_LDI_PM },
357   { BFD_RELOC_AVR_HI8_LDI_PM,       R_AVR_HI8_LDI_PM },
358   { BFD_RELOC_AVR_HH8_LDI_PM,       R_AVR_HH8_LDI_PM },
359   { BFD_RELOC_AVR_LO8_LDI_PM_NEG,   R_AVR_LO8_LDI_PM_NEG },
360   { BFD_RELOC_AVR_HI8_LDI_PM_NEG,   R_AVR_HI8_LDI_PM_NEG },
361   { BFD_RELOC_AVR_HH8_LDI_PM_NEG,   R_AVR_HH8_LDI_PM_NEG },
362   { BFD_RELOC_AVR_CALL,             R_AVR_CALL }
363 };
364
365 static reloc_howto_type *
366 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
367      bfd *abfd ATTRIBUTE_UNUSED;
368      bfd_reloc_code_real_type code;
369 {
370   unsigned int i;
371
372   for (i = 0;
373        i < sizeof (avr_reloc_map) / sizeof (struct avr_reloc_map);
374        i++)
375     {
376       if (avr_reloc_map[i].bfd_reloc_val == code)
377         return &elf_avr_howto_table[avr_reloc_map[i].elf_reloc_val];
378     }
379
380   return NULL;
381 }
382
383 /* Set the howto pointer for an AVR ELF reloc.  */
384
385 static void
386 avr_info_to_howto_rela (abfd, cache_ptr, dst)
387      bfd *abfd ATTRIBUTE_UNUSED;
388      arelent *cache_ptr;
389      Elf_Internal_Rela *dst;
390 {
391   unsigned int r_type;
392
393   r_type = ELF32_R_TYPE (dst->r_info);
394   BFD_ASSERT (r_type < (unsigned int) R_AVR_max);
395   cache_ptr->howto = &elf_avr_howto_table[r_type];
396 }
397
398 static asection *
399 elf32_avr_gc_mark_hook (sec, info, rel, h, sym)
400      asection *sec;
401      struct bfd_link_info *info ATTRIBUTE_UNUSED;
402      Elf_Internal_Rela *rel;
403      struct elf_link_hash_entry *h;
404      Elf_Internal_Sym *sym;
405 {
406   if (h != NULL)
407     {
408       switch (ELF32_R_TYPE (rel->r_info))
409         {
410         default:
411           switch (h->root.type)
412             {
413             case bfd_link_hash_defined:
414             case bfd_link_hash_defweak:
415               return h->root.u.def.section;
416
417             case bfd_link_hash_common:
418               return h->root.u.c.p->section;
419
420             default:
421               break;
422             }
423         }
424     }
425   else
426     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
427
428   return NULL;
429 }
430
431 static bfd_boolean
432 elf32_avr_gc_sweep_hook (abfd, info, sec, relocs)
433      bfd *abfd ATTRIBUTE_UNUSED;
434      struct bfd_link_info *info ATTRIBUTE_UNUSED;
435      asection *sec ATTRIBUTE_UNUSED;
436      const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
437 {
438   /* We don't use got and plt entries for avr.  */
439   return TRUE;
440 }
441
442 /* Look through the relocs for a section during the first phase.
443    Since we don't do .gots or .plts, we just need to consider the
444    virtual table relocs for gc.  */
445
446 static bfd_boolean
447 elf32_avr_check_relocs (abfd, info, sec, relocs)
448      bfd *abfd;
449      struct bfd_link_info *info;
450      asection *sec;
451      const Elf_Internal_Rela *relocs;
452 {
453   Elf_Internal_Shdr *symtab_hdr;
454   struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
455   const Elf_Internal_Rela *rel;
456   const Elf_Internal_Rela *rel_end;
457
458   if (info->relocatable)
459     return TRUE;
460
461   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
462   sym_hashes = elf_sym_hashes (abfd);
463   sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
464   if (!elf_bad_symtab (abfd))
465     sym_hashes_end -= symtab_hdr->sh_info;
466
467   rel_end = relocs + sec->reloc_count;
468   for (rel = relocs; rel < rel_end; rel++)
469     {
470       struct elf_link_hash_entry *h;
471       unsigned long r_symndx;
472
473       r_symndx = ELF32_R_SYM (rel->r_info);
474       if (r_symndx < symtab_hdr->sh_info)
475         h = NULL;
476       else
477         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
478     }
479
480   return TRUE;
481 }
482
483 /* Perform a single relocation.  By default we use the standard BFD
484    routines, but a few relocs, we have to do them ourselves.  */
485
486 static bfd_reloc_status_type
487 avr_final_link_relocate (howto, input_bfd, input_section,
488                          contents, rel, relocation)
489      reloc_howto_type *  howto;
490      bfd *               input_bfd;
491      asection *          input_section;
492      bfd_byte *          contents;
493      Elf_Internal_Rela * rel;
494      bfd_vma             relocation;
495 {
496   bfd_reloc_status_type r = bfd_reloc_ok;
497   bfd_vma               x;
498   bfd_signed_vma        srel;
499
500   switch (howto->type)
501     {
502     case R_AVR_7_PCREL:
503       contents += rel->r_offset;
504       srel = (bfd_signed_vma) relocation;
505       srel += rel->r_addend;
506       srel -= rel->r_offset;
507       srel -= 2;        /* Branch instructions add 2 to the PC...  */
508       srel -= (input_section->output_section->vma +
509                input_section->output_offset);
510
511       if (srel & 1)
512         return bfd_reloc_outofrange;
513       if (srel > ((1 << 7) - 1) || (srel < - (1 << 7)))
514         return bfd_reloc_overflow;
515       x = bfd_get_16 (input_bfd, contents);
516       x = (x & 0xfc07) | (((srel >> 1) << 3) & 0x3f8);
517       bfd_put_16 (input_bfd, x, contents);
518       break;
519
520     case R_AVR_13_PCREL:
521       contents   += rel->r_offset;
522       srel = (bfd_signed_vma) relocation;
523       srel += rel->r_addend;
524       srel -= rel->r_offset;
525       srel -= 2;        /* Branch instructions add 2 to the PC...  */
526       srel -= (input_section->output_section->vma +
527                input_section->output_offset);
528
529       if (srel & 1)
530         return bfd_reloc_outofrange;
531
532       /* AVR addresses commands as words.  */
533       srel >>= 1;
534
535       /* Check for overflow.  */
536       if (srel < -2048 || srel > 2047)
537         {
538           /* Apply WRAPAROUND if possible.  */
539           switch (bfd_get_mach (input_bfd))
540             {
541             case bfd_mach_avr2:
542             case bfd_mach_avr4:
543               break;
544
545             default:
546               return bfd_reloc_overflow;
547             }
548         }
549
550       x = bfd_get_16 (input_bfd, contents);
551       x = (x & 0xf000) | (srel & 0xfff);
552       bfd_put_16 (input_bfd, x, contents);
553       break;
554
555     case R_AVR_LO8_LDI:
556       contents += rel->r_offset;
557       srel = (bfd_signed_vma) relocation + rel->r_addend;
558       x = bfd_get_16 (input_bfd, contents);
559       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
560       bfd_put_16 (input_bfd, x, contents);
561       break;
562
563     case R_AVR_HI8_LDI:
564       contents += rel->r_offset;
565       srel = (bfd_signed_vma) relocation + rel->r_addend;
566       srel = (srel >> 8) & 0xff;
567       x = bfd_get_16 (input_bfd, contents);
568       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
569       bfd_put_16 (input_bfd, x, contents);
570       break;
571
572     case R_AVR_HH8_LDI:
573       contents += rel->r_offset;
574       srel = (bfd_signed_vma) relocation + rel->r_addend;
575       srel = (srel >> 16) & 0xff;
576       x = bfd_get_16 (input_bfd, contents);
577       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
578       bfd_put_16 (input_bfd, x, contents);
579       break;
580
581     case R_AVR_LO8_LDI_NEG:
582       contents += rel->r_offset;
583       srel = (bfd_signed_vma) relocation + rel->r_addend;
584       srel = -srel;
585       x = bfd_get_16 (input_bfd, contents);
586       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
587       bfd_put_16 (input_bfd, x, contents);
588       break;
589
590     case R_AVR_HI8_LDI_NEG:
591       contents += rel->r_offset;
592       srel = (bfd_signed_vma) relocation + rel->r_addend;
593       srel = -srel;
594       srel = (srel >> 8) & 0xff;
595       x = bfd_get_16 (input_bfd, contents);
596       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
597       bfd_put_16 (input_bfd, x, contents);
598       break;
599
600     case R_AVR_HH8_LDI_NEG:
601       contents += rel->r_offset;
602       srel = (bfd_signed_vma) relocation + rel->r_addend;
603       srel = -srel;
604       srel = (srel >> 16) & 0xff;
605       x = bfd_get_16 (input_bfd, contents);
606       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
607       bfd_put_16 (input_bfd, x, contents);
608       break;
609
610     case R_AVR_LO8_LDI_PM:
611       contents += rel->r_offset;
612       srel = (bfd_signed_vma) relocation + rel->r_addend;
613       if (srel & 1)
614         return bfd_reloc_outofrange;
615       srel = srel >> 1;
616       x = bfd_get_16 (input_bfd, contents);
617       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
618       bfd_put_16 (input_bfd, x, contents);
619       break;
620
621     case R_AVR_HI8_LDI_PM:
622       contents += rel->r_offset;
623       srel = (bfd_signed_vma) relocation + rel->r_addend;
624       if (srel & 1)
625         return bfd_reloc_outofrange;
626       srel = srel >> 1;
627       srel = (srel >> 8) & 0xff;
628       x = bfd_get_16 (input_bfd, contents);
629       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
630       bfd_put_16 (input_bfd, x, contents);
631       break;
632
633     case R_AVR_HH8_LDI_PM:
634       contents += rel->r_offset;
635       srel = (bfd_signed_vma) relocation + rel->r_addend;
636       if (srel & 1)
637         return bfd_reloc_outofrange;
638       srel = srel >> 1;
639       srel = (srel >> 16) & 0xff;
640       x = bfd_get_16 (input_bfd, contents);
641       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
642       bfd_put_16 (input_bfd, x, contents);
643       break;
644
645     case R_AVR_LO8_LDI_PM_NEG:
646       contents += rel->r_offset;
647       srel = (bfd_signed_vma) relocation + rel->r_addend;
648       srel = -srel;
649       if (srel & 1)
650         return bfd_reloc_outofrange;
651       srel = srel >> 1;
652       x = bfd_get_16 (input_bfd, contents);
653       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
654       bfd_put_16 (input_bfd, x, contents);
655       break;
656
657     case R_AVR_HI8_LDI_PM_NEG:
658       contents += rel->r_offset;
659       srel = (bfd_signed_vma) relocation + rel->r_addend;
660       srel = -srel;
661       if (srel & 1)
662         return bfd_reloc_outofrange;
663       srel = srel >> 1;
664       srel = (srel >> 8) & 0xff;
665       x = bfd_get_16 (input_bfd, contents);
666       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
667       bfd_put_16 (input_bfd, x, contents);
668       break;
669
670     case R_AVR_HH8_LDI_PM_NEG:
671       contents += rel->r_offset;
672       srel = (bfd_signed_vma) relocation + rel->r_addend;
673       srel = -srel;
674       if (srel & 1)
675         return bfd_reloc_outofrange;
676       srel = srel >> 1;
677       srel = (srel >> 16) & 0xff;
678       x = bfd_get_16 (input_bfd, contents);
679       x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
680       bfd_put_16 (input_bfd, x, contents);
681       break;
682
683     case R_AVR_CALL:
684       contents += rel->r_offset;
685       srel = (bfd_signed_vma) relocation + rel->r_addend;
686       if (srel & 1)
687         return bfd_reloc_outofrange;
688       srel = srel >> 1;
689       x = bfd_get_16 (input_bfd, contents);
690       x |= ((srel & 0x10000) | ((srel << 3) & 0x1f00000)) >> 16;
691       bfd_put_16 (input_bfd, x, contents);
692       bfd_put_16 (input_bfd, (bfd_vma) srel & 0xffff, contents+2);
693       break;
694
695     default:
696       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
697                                     contents, rel->r_offset,
698                                     relocation, rel->r_addend);
699     }
700
701   return r;
702 }
703
704 /* Relocate an AVR ELF section.  */
705 static bfd_boolean
706 elf32_avr_relocate_section (output_bfd, info, input_bfd, input_section,
707                             contents, relocs, local_syms, local_sections)
708      bfd *output_bfd ATTRIBUTE_UNUSED;
709      struct bfd_link_info *info;
710      bfd *input_bfd;
711      asection *input_section;
712      bfd_byte *contents;
713      Elf_Internal_Rela *relocs;
714      Elf_Internal_Sym *local_syms;
715      asection **local_sections;
716 {
717   Elf_Internal_Shdr *           symtab_hdr;
718   struct elf_link_hash_entry ** sym_hashes;
719   Elf_Internal_Rela *           rel;
720   Elf_Internal_Rela *           relend;
721
722   if (info->relocatable)
723     return TRUE;
724
725   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
726   sym_hashes = elf_sym_hashes (input_bfd);
727   relend     = relocs + input_section->reloc_count;
728
729   for (rel = relocs; rel < relend; rel ++)
730     {
731       reloc_howto_type *           howto;
732       unsigned long                r_symndx;
733       Elf_Internal_Sym *           sym;
734       asection *                   sec;
735       struct elf_link_hash_entry * h;
736       bfd_vma                      relocation;
737       bfd_reloc_status_type        r;
738       const char *                 name = NULL;
739       int                          r_type;
740
741       /* This is a final link.  */
742       r_type = ELF32_R_TYPE (rel->r_info);
743       r_symndx = ELF32_R_SYM (rel->r_info);
744       howto  = elf_avr_howto_table + ELF32_R_TYPE (rel->r_info);
745       h      = NULL;
746       sym    = NULL;
747       sec    = NULL;
748
749       if (r_symndx < symtab_hdr->sh_info)
750         {
751           sym = local_syms + r_symndx;
752           sec = local_sections [r_symndx];
753           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
754
755           name = bfd_elf_string_from_elf_section
756             (input_bfd, symtab_hdr->sh_link, sym->st_name);
757           name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
758         }
759       else
760         {
761           bfd_boolean unresolved_reloc, warned;
762
763           RELOC_FOR_GLOBAL_SYMBOL (h, sym_hashes, r_symndx, symtab_hdr,
764                                    relocation, sec, unresolved_reloc,
765                                    info, warned);
766         }
767
768       r = avr_final_link_relocate (howto, input_bfd, input_section,
769                                    contents, rel, relocation);
770
771       if (r != bfd_reloc_ok)
772         {
773           const char * msg = (const char *) NULL;
774
775           switch (r)
776             {
777             case bfd_reloc_overflow:
778               r = info->callbacks->reloc_overflow
779                 (info, name, howto->name, (bfd_vma) 0,
780                  input_bfd, input_section, rel->r_offset);
781               break;
782
783             case bfd_reloc_undefined:
784               r = info->callbacks->undefined_symbol
785                 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
786               break;
787
788             case bfd_reloc_outofrange:
789               msg = _("internal error: out of range error");
790               break;
791
792             case bfd_reloc_notsupported:
793               msg = _("internal error: unsupported relocation error");
794               break;
795
796             case bfd_reloc_dangerous:
797               msg = _("internal error: dangerous relocation");
798               break;
799
800             default:
801               msg = _("internal error: unknown error");
802               break;
803             }
804
805           if (msg)
806             r = info->callbacks->warning
807               (info, msg, name, input_bfd, input_section, rel->r_offset);
808
809           if (! r)
810             return FALSE;
811         }
812     }
813
814   return TRUE;
815 }
816
817 /* The final processing done just before writing out a AVR ELF object
818    file.  This gets the AVR architecture right based on the machine
819    number.  */
820
821 static void
822 bfd_elf_avr_final_write_processing (abfd, linker)
823      bfd *abfd;
824      bfd_boolean linker ATTRIBUTE_UNUSED;
825 {
826   unsigned long val;
827
828   switch (bfd_get_mach (abfd))
829     {
830     default:
831     case bfd_mach_avr2:
832       val = E_AVR_MACH_AVR2;
833       break;
834
835     case bfd_mach_avr1:
836       val = E_AVR_MACH_AVR1;
837       break;
838
839     case bfd_mach_avr3:
840       val = E_AVR_MACH_AVR3;
841       break;
842
843     case bfd_mach_avr4:
844       val = E_AVR_MACH_AVR4;
845       break;
846
847     case bfd_mach_avr5:
848       val = E_AVR_MACH_AVR5;
849       break;
850     }
851
852   elf_elfheader (abfd)->e_machine = EM_AVR;
853   elf_elfheader (abfd)->e_flags &= ~ EF_AVR_MACH;
854   elf_elfheader (abfd)->e_flags |= val;
855 }
856
857 /* Set the right machine number.  */
858
859 static bfd_boolean
860 elf32_avr_object_p (abfd)
861      bfd *abfd;
862 {
863   unsigned int e_set = bfd_mach_avr2;
864   if (elf_elfheader (abfd)->e_machine == EM_AVR
865       || elf_elfheader (abfd)->e_machine == EM_AVR_OLD)
866     {
867       int e_mach = elf_elfheader (abfd)->e_flags & EF_AVR_MACH;
868       switch (e_mach)
869         {
870         default:
871         case E_AVR_MACH_AVR2:
872           e_set = bfd_mach_avr2;
873           break;
874
875         case E_AVR_MACH_AVR1:
876           e_set = bfd_mach_avr1;
877           break;
878
879         case E_AVR_MACH_AVR3:
880           e_set = bfd_mach_avr3;
881           break;
882
883         case E_AVR_MACH_AVR4:
884           e_set = bfd_mach_avr4;
885           break;
886
887         case E_AVR_MACH_AVR5:
888           e_set = bfd_mach_avr5;
889           break;
890         }
891     }
892   return bfd_default_set_arch_mach (abfd, bfd_arch_avr,
893                                     e_set);
894 }
895
896 #define ELF_ARCH                bfd_arch_avr
897 #define ELF_MACHINE_CODE        EM_AVR
898 #define ELF_MACHINE_ALT1        EM_AVR_OLD
899 #define ELF_MAXPAGESIZE         1
900
901 #define TARGET_LITTLE_SYM       bfd_elf32_avr_vec
902 #define TARGET_LITTLE_NAME      "elf32-avr"
903
904 #define elf_info_to_howto                    avr_info_to_howto_rela
905 #define elf_info_to_howto_rel                NULL
906 #define elf_backend_relocate_section         elf32_avr_relocate_section
907 #define elf_backend_gc_mark_hook             elf32_avr_gc_mark_hook
908 #define elf_backend_gc_sweep_hook            elf32_avr_gc_sweep_hook
909 #define elf_backend_check_relocs             elf32_avr_check_relocs
910 #define elf_backend_can_gc_sections          1
911 #define elf_backend_rela_normal              1
912 #define elf_backend_final_write_processing \
913                                         bfd_elf_avr_final_write_processing
914 #define elf_backend_object_p            elf32_avr_object_p
915
916 #include "elf32-target.h"