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