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 *
bfd_elf32_bfd_reloc_type_lookup(abfd,code)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
avr_info_to_howto_rela(abfd,cache_ptr,dst)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 *
elf32_avr_gc_mark_hook(sec,info,rel,h,sym)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
elf32_avr_gc_sweep_hook(abfd,info,sec,relocs)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
elf32_avr_check_relocs(abfd,info,sec,relocs)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
avr_final_link_relocate(howto,input_bfd,input_section,contents,rel,relocation)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
elf32_avr_relocate_section(output_bfd,info,input_bfd,input_section,contents,relocs,local_syms,local_sections)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
bfd_elf_avr_final_write_processing(abfd,linker)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
elf32_avr_object_p(abfd)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"
919