source: branches/libc-0.6/src/binutils/bfd/elf32-avr.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 28.1 KB
Line 
1/* AVR-specific support for 32-bit ELF
2 Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Denis Chertykov <denisc@overta.ru>
4
5This file is part of BFD, the Binary File Descriptor library.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, 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
27static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
28 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
29static void avr_info_to_howto_rela
30 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
31static 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 *));
34static bfd_boolean elf32_avr_gc_sweep_hook
35 PARAMS ((bfd *, struct bfd_link_info *, asection *,
36 const Elf_Internal_Rela *));
37static bfd_boolean elf32_avr_check_relocs
38 PARAMS ((bfd *, struct bfd_link_info *, asection *,
39 const Elf_Internal_Rela *));
40static bfd_reloc_status_type avr_final_link_relocate
41 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
42 Elf_Internal_Rela *, bfd_vma));
43static 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 **));
46static void bfd_elf_avr_final_write_processing PARAMS ((bfd *, bfd_boolean));
47static bfd_boolean elf32_avr_object_p PARAMS ((bfd *));
48
49static 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
336struct 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
365static reloc_howto_type *
366bfd_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
385static void
386avr_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
398static asection *
399elf32_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
431static bfd_boolean
432elf32_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
446static bfd_boolean
447elf32_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->relocateable)
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
486static bfd_reloc_status_type
487avr_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. */
705static bfd_boolean
706elf32_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->relocateable)
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
844static void
845bfd_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
882static bfd_boolean
883elf32_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"
Note: See TracBrowser for help on using the repository browser.