1 /* AVR-specific support for 32-bit ELF
2 Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
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 *));
49 static reloc_howto_type elf_avr_howto_table[] =
51 HOWTO (R_AVR_NONE, /* type */
53 2, /* size (0 = byte, 1 = short, 2 = long) */
55 FALSE, /* pc_relative */
57 complain_overflow_bitfield, /* complain_on_overflow */
58 bfd_elf_generic_reloc, /* special_function */
59 "R_AVR_NONE", /* name */
60 FALSE, /* partial_inplace */
63 FALSE), /* pcrel_offset */
65 HOWTO (R_AVR_32, /* type */
67 2, /* size (0 = byte, 1 = short, 2 = long) */
69 FALSE, /* pc_relative */
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 */
79 /* A 7 bit PC relative relocation. */
80 HOWTO (R_AVR_7_PCREL, /* type */
82 1, /* size (0 = byte, 1 = short, 2 = long) */
84 TRUE, /* pc_relative */
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 */
94 /* A 13 bit PC relative relocation. */
95 HOWTO (R_AVR_13_PCREL, /* type */
97 1, /* size (0 = byte, 1 = short, 2 = long) */
99 TRUE, /* pc_relative */
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 */
109 /* A 16 bit absolute relocation. */
110 HOWTO (R_AVR_16, /* type */
112 1, /* size (0 = byte, 1 = short, 2 = long) */
114 FALSE, /* pc_relative */
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 */
124 /* A 16 bit absolute relocation for command address. */
125 HOWTO (R_AVR_16_PM, /* type */
127 1, /* size (0 = byte, 1 = short, 2 = long) */
129 FALSE, /* pc_relative */
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.
140 HOWTO (R_AVR_LO8_LDI, /* type */
142 1, /* size (0 = byte, 1 = short, 2 = long) */
144 FALSE, /* pc_relative */
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.
155 HOWTO (R_AVR_HI8_LDI, /* type */
157 1, /* size (0 = byte, 1 = short, 2 = long) */
159 FALSE, /* pc_relative */
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.
170 HOWTO (R_AVR_HH8_LDI, /* type */
172 1, /* size (0 = byte, 1 = short, 2 = long) */
174 FALSE, /* pc_relative */
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.
185 HOWTO (R_AVR_LO8_LDI_NEG, /* type */
187 1, /* size (0 = byte, 1 = short, 2 = long) */
189 FALSE, /* pc_relative */
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.
200 HOWTO (R_AVR_HI8_LDI_NEG, /* type */
202 1, /* size (0 = byte, 1 = short, 2 = long) */
204 FALSE, /* pc_relative */
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.
215 HOWTO (R_AVR_HH8_LDI_NEG, /* type */
217 1, /* size (0 = byte, 1 = short, 2 = long) */
219 FALSE, /* pc_relative */
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.
230 HOWTO (R_AVR_LO8_LDI_PM, /* type */
232 1, /* size (0 = byte, 1 = short, 2 = long) */
234 FALSE, /* pc_relative */
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.
245 HOWTO (R_AVR_HI8_LDI_PM, /* type */
247 1, /* size (0 = byte, 1 = short, 2 = long) */
249 FALSE, /* pc_relative */
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.
260 HOWTO (R_AVR_HH8_LDI_PM, /* type */
262 1, /* size (0 = byte, 1 = short, 2 = long) */
264 FALSE, /* pc_relative */
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 */
277 1, /* size (0 = byte, 1 = short, 2 = long) */
279 FALSE, /* pc_relative */
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 */
292 1, /* size (0 = byte, 1 = short, 2 = long) */
294 FALSE, /* pc_relative */
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 */
307 1, /* size (0 = byte, 1 = short, 2 = long) */
309 FALSE, /* pc_relative */
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 */
321 2, /* size (0 = byte, 1 = short, 2 = long) */
323 FALSE, /* pc_relative */
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 */
334 /* Map BFD reloc types to AVR ELF reloc types. */
338 bfd_reloc_code_real_type bfd_reloc_val;
339 unsigned int elf_reloc_val;
342 static const struct avr_reloc_map avr_reloc_map[] =
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 }
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;
373 i < sizeof (avr_reloc_map) / sizeof (struct avr_reloc_map);
376 if (avr_reloc_map[i].bfd_reloc_val == code)
377 return &elf_avr_howto_table[avr_reloc_map[i].elf_reloc_val];
383 /* Set the howto pointer for an AVR ELF reloc. */
386 avr_info_to_howto_rela (abfd, cache_ptr, dst)
387 bfd *abfd ATTRIBUTE_UNUSED;
389 Elf_Internal_Rela *dst;
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];
399 elf32_avr_gc_mark_hook (sec, info, rel, h, sym)
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;
408 switch (ELF32_R_TYPE (rel->r_info))
411 switch (h->root.type)
413 case bfd_link_hash_defined:
414 case bfd_link_hash_defweak:
415 return h->root.u.def.section;
417 case bfd_link_hash_common:
418 return h->root.u.c.p->section;
426 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
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;
438 /* We don't use got and plt entries for avr. */
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. */
447 elf32_avr_check_relocs (abfd, info, sec, relocs)
449 struct bfd_link_info *info;
451 const Elf_Internal_Rela *relocs;
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;
458 if (info->relocateable)
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;
467 rel_end = relocs + sec->reloc_count;
468 for (rel = relocs; rel < rel_end; rel++)
470 struct elf_link_hash_entry *h;
471 unsigned long r_symndx;
473 r_symndx = ELF32_R_SYM (rel->r_info);
474 if (r_symndx < symtab_hdr->sh_info)
477 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
483 /* Perform a single relocation. By default we use the standard BFD
484 routines, but a few relocs, we have to do them ourselves. */
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;
491 asection * input_section;
493 Elf_Internal_Rela * rel;
496 bfd_reloc_status_type r = bfd_reloc_ok;
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);
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);
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);
530 return bfd_reloc_outofrange;
532 /* AVR addresses commands as words. */
535 /* Check for overflow. */
536 if (srel < -2048 || srel > 2047)
538 /* Apply WRAPAROUND if possible. */
539 switch (bfd_get_mach (input_bfd))
546 return bfd_reloc_overflow;
550 x = bfd_get_16 (input_bfd, contents);
551 x = (x & 0xf000) | (srel & 0xfff);
552 bfd_put_16 (input_bfd, x, contents);
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);
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);
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);
581 case R_AVR_LO8_LDI_NEG:
582 contents += rel->r_offset;
583 srel = (bfd_signed_vma) relocation + rel->r_addend;
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);
590 case R_AVR_HI8_LDI_NEG:
591 contents += rel->r_offset;
592 srel = (bfd_signed_vma) relocation + rel->r_addend;
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);
600 case R_AVR_HH8_LDI_NEG:
601 contents += rel->r_offset;
602 srel = (bfd_signed_vma) relocation + rel->r_addend;
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);
610 case R_AVR_LO8_LDI_PM:
611 contents += rel->r_offset;
612 srel = (bfd_signed_vma) relocation + rel->r_addend;
614 return bfd_reloc_outofrange;
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);
621 case R_AVR_HI8_LDI_PM:
622 contents += rel->r_offset;
623 srel = (bfd_signed_vma) relocation + rel->r_addend;
625 return bfd_reloc_outofrange;
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);
633 case R_AVR_HH8_LDI_PM:
634 contents += rel->r_offset;
635 srel = (bfd_signed_vma) relocation + rel->r_addend;
637 return bfd_reloc_outofrange;
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);
645 case R_AVR_LO8_LDI_PM_NEG:
646 contents += rel->r_offset;
647 srel = (bfd_signed_vma) relocation + rel->r_addend;
650 return bfd_reloc_outofrange;
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);
657 case R_AVR_HI8_LDI_PM_NEG:
658 contents += rel->r_offset;
659 srel = (bfd_signed_vma) relocation + rel->r_addend;
662 return bfd_reloc_outofrange;
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);
670 case R_AVR_HH8_LDI_PM_NEG:
671 contents += rel->r_offset;
672 srel = (bfd_signed_vma) relocation + rel->r_addend;
675 return bfd_reloc_outofrange;
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);
684 contents += rel->r_offset;
685 srel = (bfd_signed_vma) relocation + rel->r_addend;
687 return bfd_reloc_outofrange;
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);
696 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
697 contents, rel->r_offset,
698 relocation, rel->r_addend);
704 /* Relocate an AVR ELF section. */
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;
711 asection *input_section;
713 Elf_Internal_Rela *relocs;
714 Elf_Internal_Sym *local_syms;
715 asection **local_sections;
717 Elf_Internal_Shdr * symtab_hdr;
718 struct elf_link_hash_entry ** sym_hashes;
719 Elf_Internal_Rela * rel;
720 Elf_Internal_Rela * relend;
722 if (info->relocateable)
725 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
726 sym_hashes = elf_sym_hashes (input_bfd);
727 relend = relocs + input_section->reloc_count;
729 for (rel = relocs; rel < relend; rel ++)
731 reloc_howto_type * howto;
732 unsigned long r_symndx;
733 Elf_Internal_Sym * sym;
735 struct elf_link_hash_entry * h;
737 bfd_reloc_status_type r;
738 const char * name = NULL;
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);
749 if (r_symndx < symtab_hdr->sh_info)
751 sym = local_syms + r_symndx;
752 sec = local_sections [r_symndx];
753 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
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;
761 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
763 while (h->root.type == bfd_link_hash_indirect
764 || h->root.type == bfd_link_hash_warning)
765 h = (struct elf_link_hash_entry *) h->root.u.i.link;
767 name = h->root.root.string;
769 if (h->root.type == bfd_link_hash_defined
770 || h->root.type == bfd_link_hash_defweak)
772 sec = h->root.u.def.section;
773 relocation = (h->root.u.def.value
774 + sec->output_section->vma
775 + sec->output_offset);
777 else if (h->root.type == bfd_link_hash_undefweak)
783 if (! ((*info->callbacks->undefined_symbol)
784 (info, h->root.root.string, input_bfd,
785 input_section, rel->r_offset, TRUE)))
791 r = avr_final_link_relocate (howto, input_bfd, input_section,
792 contents, rel, relocation);
794 if (r != bfd_reloc_ok)
796 const char * msg = (const char *) NULL;
800 case bfd_reloc_overflow:
801 r = info->callbacks->reloc_overflow
802 (info, name, howto->name, (bfd_vma) 0,
803 input_bfd, input_section, rel->r_offset);
806 case bfd_reloc_undefined:
807 r = info->callbacks->undefined_symbol
808 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
811 case bfd_reloc_outofrange:
812 msg = _("internal error: out of range error");
815 case bfd_reloc_notsupported:
816 msg = _("internal error: unsupported relocation error");
819 case bfd_reloc_dangerous:
820 msg = _("internal error: dangerous relocation");
824 msg = _("internal error: unknown error");
829 r = info->callbacks->warning
830 (info, msg, name, input_bfd, input_section, rel->r_offset);
840 /* The final processing done just before writing out a AVR ELF object
841 file. This gets the AVR architecture right based on the machine
845 bfd_elf_avr_final_write_processing (abfd, linker)
847 bfd_boolean linker ATTRIBUTE_UNUSED;
851 switch (bfd_get_mach (abfd))
855 val = E_AVR_MACH_AVR2;
859 val = E_AVR_MACH_AVR1;
863 val = E_AVR_MACH_AVR3;
867 val = E_AVR_MACH_AVR4;
871 val = E_AVR_MACH_AVR5;
875 elf_elfheader (abfd)->e_machine = EM_AVR;
876 elf_elfheader (abfd)->e_flags &= ~ EF_AVR_MACH;
877 elf_elfheader (abfd)->e_flags |= val;
880 /* Set the right machine number. */
883 elf32_avr_object_p (abfd)
886 unsigned int e_set = bfd_mach_avr2;
887 if (elf_elfheader (abfd)->e_machine == EM_AVR
888 || elf_elfheader (abfd)->e_machine == EM_AVR_OLD)
890 int e_mach = elf_elfheader (abfd)->e_flags & EF_AVR_MACH;
894 case E_AVR_MACH_AVR2:
895 e_set = bfd_mach_avr2;
898 case E_AVR_MACH_AVR1:
899 e_set = bfd_mach_avr1;
902 case E_AVR_MACH_AVR3:
903 e_set = bfd_mach_avr3;
906 case E_AVR_MACH_AVR4:
907 e_set = bfd_mach_avr4;
910 case E_AVR_MACH_AVR5:
911 e_set = bfd_mach_avr5;
915 return bfd_default_set_arch_mach (abfd, bfd_arch_avr,
919 #define ELF_ARCH bfd_arch_avr
920 #define ELF_MACHINE_CODE EM_AVR
921 #define ELF_MACHINE_ALT1 EM_AVR_OLD
922 #define ELF_MAXPAGESIZE 1
924 #define TARGET_LITTLE_SYM bfd_elf32_avr_vec
925 #define TARGET_LITTLE_NAME "elf32-avr"
927 #define elf_info_to_howto avr_info_to_howto_rela
928 #define elf_info_to_howto_rel NULL
929 #define elf_backend_relocate_section elf32_avr_relocate_section
930 #define elf_backend_gc_mark_hook elf32_avr_gc_mark_hook
931 #define elf_backend_gc_sweep_hook elf32_avr_gc_sweep_hook
932 #define elf_backend_check_relocs elf32_avr_check_relocs
933 #define elf_backend_can_gc_sections 1
934 #define elf_backend_rela_normal 1
935 #define elf_backend_final_write_processing \
936 bfd_elf_avr_final_write_processing
937 #define elf_backend_object_p elf32_avr_object_p
939 #include "elf32-target.h"