]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - bfd/elf32-avr.c
Import the binutils-2_15-branch from the sourceware CVS repository,
[FreeBSD/FreeBSD.git] / bfd / elf32-avr.c
1 /* AVR-specific support for 32-bit ELF
2    Copyright 1999, 2000, 2001, 2002, 2003, 2004
3    Free Software Foundation, Inc.
4    Contributed by Denis Chertykov <denisc@overta.ru>
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/avr.h"
27
28 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
29   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
30 static void avr_info_to_howto_rela
31   PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
32 static asection *elf32_avr_gc_mark_hook
33   PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
34            struct elf_link_hash_entry *, Elf_Internal_Sym *));
35 static bfd_boolean elf32_avr_gc_sweep_hook
36   PARAMS ((bfd *, struct bfd_link_info *, asection *,
37            const Elf_Internal_Rela *));
38 static bfd_boolean elf32_avr_check_relocs
39   PARAMS ((bfd *, struct bfd_link_info *, asection *,
40            const Elf_Internal_Rela *));
41 static bfd_reloc_status_type avr_final_link_relocate
42   PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
43            Elf_Internal_Rela *, bfd_vma));
44 static bfd_boolean elf32_avr_relocate_section
45   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
46            Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
47 static void bfd_elf_avr_final_write_processing PARAMS ((bfd *, bfd_boolean));
48 static bfd_boolean elf32_avr_object_p PARAMS ((bfd *));
49
50 static reloc_howto_type elf_avr_howto_table[] =
51 {
52   HOWTO (R_AVR_NONE,            /* type */
53          0,                     /* rightshift */
54          2,                     /* size (0 = byte, 1 = short, 2 = long) */
55          32,                    /* bitsize */
56          FALSE,                 /* pc_relative */
57          0,                     /* bitpos */
58          complain_overflow_bitfield, /* complain_on_overflow */
59          bfd_elf_generic_reloc, /* special_function */
60          "R_AVR_NONE",          /* name */
61          FALSE,                 /* partial_inplace */
62          0,                     /* src_mask */
63          0,                     /* dst_mask */
64          FALSE),                /* pcrel_offset */
65
66   HOWTO (R_AVR_32,              /* type */
67          0,                     /* rightshift */
68          2,                     /* size (0 = byte, 1 = short, 2 = long) */
69          32,                    /* bitsize */
70          FALSE,                 /* pc_relative */
71          0,                     /* bitpos */
72          complain_overflow_bitfield, /* complain_on_overflow */
73          bfd_elf_generic_reloc, /* special_function */
74          "R_AVR_32",            /* name */
75          FALSE,                 /* partial_inplace */
76          0xffffffff,            /* src_mask */
77          0xffffffff,            /* dst_mask */
78          FALSE),                /* pcrel_offset */
79
80   /* A 7 bit PC relative relocation.  */
81   HOWTO (R_AVR_7_PCREL,         /* type */
82          1,                     /* rightshift */
83          1,                     /* size (0 = byte, 1 = short, 2 = long) */
84          7,                     /* bitsize */
85          TRUE,                  /* pc_relative */
86          3,                     /* bitpos */
87          complain_overflow_bitfield, /* complain_on_overflow */
88          bfd_elf_generic_reloc, /* special_function */
89          "R_AVR_7_PCREL",       /* name */
90          FALSE,                 /* partial_inplace */
91          0xffff,                /* src_mask */
92          0xffff,                /* dst_mask */
93          TRUE),                 /* pcrel_offset */
94
95   /* A 13 bit PC relative relocation.  */
96   HOWTO (R_AVR_13_PCREL,        /* type */
97          1,                     /* rightshift */
98          1,                     /* size (0 = byte, 1 = short, 2 = long) */
99          13,                    /* bitsize */
100          TRUE,                  /* pc_relative */
101          0,                     /* bitpos */
102          complain_overflow_bitfield, /* complain_on_overflow */
103          bfd_elf_generic_reloc, /* special_function */
104          "R_AVR_13_PCREL",      /* name */
105          FALSE,                 /* partial_inplace */
106          0xfff,                 /* src_mask */
107          0xfff,                 /* dst_mask */
108          TRUE),                 /* pcrel_offset */
109
110   /* A 16 bit absolute relocation.  */
111   HOWTO (R_AVR_16,              /* type */
112          0,                     /* rightshift */
113          1,                     /* size (0 = byte, 1 = short, 2 = long) */
114          16,                    /* bitsize */
115          FALSE,                 /* pc_relative */
116          0,                     /* bitpos */
117          complain_overflow_dont, /* complain_on_overflow */
118          bfd_elf_generic_reloc, /* special_function */
119          "R_AVR_16",            /* name */
120          FALSE,                 /* partial_inplace */
121          0xffff,                /* src_mask */
122          0xffff,                /* dst_mask */
123          FALSE),                /* pcrel_offset */
124
125   /* A 16 bit absolute relocation for command address.  */
126   HOWTO (R_AVR_16_PM,           /* type */
127          1,                     /* rightshift */
128          1,                     /* size (0 = byte, 1 = short, 2 = long) */
129          16,                    /* bitsize */
130          FALSE,                 /* pc_relative */
131          0,                     /* bitpos */
132          complain_overflow_bitfield, /* complain_on_overflow */
133          bfd_elf_generic_reloc, /* special_function */
134          "R_AVR_16_PM",         /* name */
135          FALSE,                 /* partial_inplace */
136          0xffff,                /* src_mask */
137          0xffff,                /* dst_mask */
138          FALSE),                /* pcrel_offset */
139   /* A low 8 bit absolute relocation of 16 bit address.
140      For LDI command.  */
141   HOWTO (R_AVR_LO8_LDI,         /* type */
142          0,                     /* rightshift */
143          1,                     /* size (0 = byte, 1 = short, 2 = long) */
144          8,                     /* bitsize */
145          FALSE,                 /* pc_relative */
146          0,                     /* bitpos */
147          complain_overflow_dont, /* complain_on_overflow */
148          bfd_elf_generic_reloc, /* special_function */
149          "R_AVR_LO8_LDI",       /* name */
150          FALSE,                 /* partial_inplace */
151          0xffff,                /* src_mask */
152          0xffff,                /* dst_mask */
153          FALSE),                /* pcrel_offset */
154   /* A high 8 bit absolute relocation of 16 bit address.
155      For LDI command.  */
156   HOWTO (R_AVR_HI8_LDI,         /* type */
157          8,                     /* rightshift */
158          1,                     /* size (0 = byte, 1 = short, 2 = long) */
159          8,                     /* bitsize */
160          FALSE,                 /* pc_relative */
161          0,                     /* bitpos */
162          complain_overflow_dont, /* complain_on_overflow */
163          bfd_elf_generic_reloc, /* special_function */
164          "R_AVR_HI8_LDI",       /* name */
165          FALSE,                 /* partial_inplace */
166          0xffff,                /* src_mask */
167          0xffff,                /* dst_mask */
168          FALSE),                /* pcrel_offset */
169   /* A high 6 bit absolute relocation of 22 bit address.
170      For LDI command.  */
171   HOWTO (R_AVR_HH8_LDI,         /* type */
172          16,                    /* rightshift */
173          1,                     /* size (0 = byte, 1 = short, 2 = long) */
174          8,                     /* bitsize */
175          FALSE,                 /* pc_relative */
176          0,                     /* bitpos */
177          complain_overflow_dont, /* complain_on_overflow */
178          bfd_elf_generic_reloc, /* special_function */
179          "R_AVR_HH8_LDI",       /* name */
180          FALSE,                 /* partial_inplace */
181          0xffff,                /* src_mask */
182          0xffff,                /* dst_mask */
183          FALSE),                /* pcrel_offset */
184   /* A negative low 8 bit absolute relocation of 16 bit address.
185      For LDI command.  */
186   HOWTO (R_AVR_LO8_LDI_NEG,     /* type */
187          0,                     /* rightshift */
188          1,                     /* size (0 = byte, 1 = short, 2 = long) */
189          8,                     /* bitsize */
190          FALSE,                 /* pc_relative */
191          0,                     /* bitpos */
192          complain_overflow_dont, /* complain_on_overflow */
193          bfd_elf_generic_reloc, /* special_function */
194          "R_AVR_LO8_LDI_NEG",   /* name */
195          FALSE,                 /* partial_inplace */
196          0xffff,                /* src_mask */
197          0xffff,                /* dst_mask */
198          FALSE),                /* pcrel_offset */
199   /* A hegative high 8 bit absolute relocation of 16 bit address.
200      For LDI command.  */
201   HOWTO (R_AVR_HI8_LDI_NEG,     /* type */
202          8,                     /* rightshift */
203          1,                     /* size (0 = byte, 1 = short, 2 = long) */
204          8,                     /* bitsize */
205          FALSE,                 /* pc_relative */
206          0,                     /* bitpos */
207          complain_overflow_dont, /* complain_on_overflow */
208          bfd_elf_generic_reloc, /* special_function */
209          "R_AVR_HI8_LDI_NEG",   /* name */
210          FALSE,                 /* partial_inplace */
211          0xffff,                /* src_mask */
212          0xffff,                /* dst_mask */
213          FALSE),                /* pcrel_offset */
214   /* A hegative high 6 bit absolute relocation of 22 bit address.
215      For LDI command.  */
216   HOWTO (R_AVR_HH8_LDI_NEG,     /* type */
217          16,                    /* rightshift */
218          1,                     /* size (0 = byte, 1 = short, 2 = long) */
219          8,                     /* bitsize */
220          FALSE,                 /* pc_relative */
221          0,                     /* bitpos */
222          complain_overflow_dont, /* complain_on_overflow */
223          bfd_elf_generic_reloc, /* special_function */
224          "R_AVR_HH8_LDI_NEG",   /* name */
225          FALSE,                 /* partial_inplace */
226          0xffff,                /* src_mask */
227          0xffff,                /* dst_mask */
228          FALSE),                /* pcrel_offset */
229   /* A low 8 bit absolute relocation of 24 bit program memory address.
230      For LDI command.  */
231   HOWTO (R_AVR_LO8_LDI_PM,      /* type */
232          1,                     /* rightshift */
233          1,                     /* size (0 = byte, 1 = short, 2 = long) */
234          8,                     /* bitsize */
235          FALSE,                 /* pc_relative */
236          0,                     /* bitpos */
237          complain_overflow_dont, /* complain_on_overflow */
238          bfd_elf_generic_reloc, /* special_function */
239          "R_AVR_LO8_LDI_PM",    /* name */
240          FALSE,                 /* partial_inplace */
241          0xffff,                /* src_mask */
242          0xffff,                /* dst_mask */
243          FALSE),                /* pcrel_offset */
244   /* A high 8 bit absolute relocation of 16 bit program memory address.
245      For LDI command.  */
246   HOWTO (R_AVR_HI8_LDI_PM,      /* type */
247          9,                     /* rightshift */
248          1,                     /* size (0 = byte, 1 = short, 2 = long) */
249          8,                     /* bitsize */
250          FALSE,                 /* pc_relative */
251          0,                     /* bitpos */
252          complain_overflow_dont, /* complain_on_overflow */
253          bfd_elf_generic_reloc, /* special_function */
254          "R_AVR_HI8_LDI_PM",    /* name */
255          FALSE,                 /* partial_inplace */
256          0xffff,                /* src_mask */
257          0xffff,                /* dst_mask */
258          FALSE),                /* pcrel_offset */
259   /* A high 8 bit absolute relocation of 24 bit program memory address.
260      For LDI command.  */
261   HOWTO (R_AVR_HH8_LDI_PM,      /* type */
262          17,                    /* rightshift */
263          1,                     /* size (0 = byte, 1 = short, 2 = long) */
264          8,                     /* bitsize */
265          FALSE,                 /* pc_relative */
266          0,                     /* bitpos */
267          complain_overflow_dont, /* complain_on_overflow */
268          bfd_elf_generic_reloc, /* special_function */
269          "R_AVR_HH8_LDI_PM",    /* name */
270          FALSE,                 /* partial_inplace */
271          0xffff,                /* src_mask */
272          0xffff,                /* dst_mask */
273          FALSE),                /* pcrel_offset */
274   /* A low 8 bit absolute relocation of a negative 24 bit
275      program memory address.  For LDI command.  */
276   HOWTO (R_AVR_LO8_LDI_PM_NEG,  /* type */
277          1,                     /* rightshift */
278          1,                     /* size (0 = byte, 1 = short, 2 = long) */
279          8,                     /* bitsize */
280          FALSE,                 /* pc_relative */
281          0,                     /* bitpos */
282          complain_overflow_dont, /* complain_on_overflow */
283          bfd_elf_generic_reloc, /* special_function */
284          "R_AVR_LO8_LDI_PM_NEG", /* name */
285          FALSE,                 /* partial_inplace */
286          0xffff,                /* src_mask */
287          0xffff,                /* dst_mask */
288          FALSE),                /* pcrel_offset */
289   /* A high 8 bit absolute relocation of a negative 16 bit
290      program memory address.  For LDI command.  */
291   HOWTO (R_AVR_HI8_LDI_PM_NEG,  /* type */
292          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
337 struct 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
366 static reloc_howto_type *
367 bfd_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
386 static void
387 avr_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
399 static asection *
400 elf32_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
432 static bfd_boolean
433 elf32_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
447 static bfd_boolean
448 elf32_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
487 static bfd_reloc_status_type
488 avr_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.  */
706 static bfd_boolean
707 elf32_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
823 static void
824 bfd_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
861 static bfd_boolean
862 elf32_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"