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>
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
*, Elf32_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 boolean elf32_avr_gc_sweep_hook
35 PARAMS ((bfd
*, struct bfd_link_info
*, asection
*,
36 const Elf_Internal_Rela
*));
37 static 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 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
*, boolean
));
47 static 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 Elf32_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 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"