00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "bfd.h"
00027 #include "sysdep.h"
00028 #include "libbfd.h"
00029 #include "elf-bfd.h"
00030 #include "elf/avr.h"
00031
00032 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
00033 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
00034 static void avr_info_to_howto_rela
00035 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
00036 static asection *elf32_avr_gc_mark_hook
00037 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
00038 struct elf_link_hash_entry *, Elf_Internal_Sym *));
00039 static bfd_boolean elf32_avr_gc_sweep_hook
00040 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00041 const Elf_Internal_Rela *));
00042 static bfd_boolean elf32_avr_check_relocs
00043 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00044 const Elf_Internal_Rela *));
00045 static bfd_reloc_status_type avr_final_link_relocate
00046 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
00047 Elf_Internal_Rela *, bfd_vma));
00048 static bfd_boolean elf32_avr_relocate_section
00049 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00050 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
00051 static void bfd_elf_avr_final_write_processing PARAMS ((bfd *, bfd_boolean));
00052 static bfd_boolean elf32_avr_object_p PARAMS ((bfd *));
00053
00054 static reloc_howto_type elf_avr_howto_table[] =
00055 {
00056 HOWTO (R_AVR_NONE,
00057 0,
00058 2,
00059 32,
00060 FALSE,
00061 0,
00062 complain_overflow_bitfield,
00063 bfd_elf_generic_reloc,
00064 "R_AVR_NONE",
00065 FALSE,
00066 0,
00067 0,
00068 FALSE),
00069
00070 HOWTO (R_AVR_32,
00071 0,
00072 2,
00073 32,
00074 FALSE,
00075 0,
00076 complain_overflow_bitfield,
00077 bfd_elf_generic_reloc,
00078 "R_AVR_32",
00079 FALSE,
00080 0xffffffff,
00081 0xffffffff,
00082 FALSE),
00083
00084
00085 HOWTO (R_AVR_7_PCREL,
00086 1,
00087 1,
00088 7,
00089 TRUE,
00090 3,
00091 complain_overflow_bitfield,
00092 bfd_elf_generic_reloc,
00093 "R_AVR_7_PCREL",
00094 FALSE,
00095 0xffff,
00096 0xffff,
00097 TRUE),
00098
00099
00100 HOWTO (R_AVR_13_PCREL,
00101 1,
00102 1,
00103 13,
00104 TRUE,
00105 0,
00106 complain_overflow_bitfield,
00107 bfd_elf_generic_reloc,
00108 "R_AVR_13_PCREL",
00109 FALSE,
00110 0xfff,
00111 0xfff,
00112 TRUE),
00113
00114
00115 HOWTO (R_AVR_16,
00116 0,
00117 1,
00118 16,
00119 FALSE,
00120 0,
00121 complain_overflow_dont,
00122 bfd_elf_generic_reloc,
00123 "R_AVR_16",
00124 FALSE,
00125 0xffff,
00126 0xffff,
00127 FALSE),
00128
00129
00130 HOWTO (R_AVR_16_PM,
00131 1,
00132 1,
00133 16,
00134 FALSE,
00135 0,
00136 complain_overflow_bitfield,
00137 bfd_elf_generic_reloc,
00138 "R_AVR_16_PM",
00139 FALSE,
00140 0xffff,
00141 0xffff,
00142 FALSE),
00143
00144
00145 HOWTO (R_AVR_LO8_LDI,
00146 0,
00147 1,
00148 8,
00149 FALSE,
00150 0,
00151 complain_overflow_dont,
00152 bfd_elf_generic_reloc,
00153 "R_AVR_LO8_LDI",
00154 FALSE,
00155 0xffff,
00156 0xffff,
00157 FALSE),
00158
00159
00160 HOWTO (R_AVR_HI8_LDI,
00161 8,
00162 1,
00163 8,
00164 FALSE,
00165 0,
00166 complain_overflow_dont,
00167 bfd_elf_generic_reloc,
00168 "R_AVR_HI8_LDI",
00169 FALSE,
00170 0xffff,
00171 0xffff,
00172 FALSE),
00173
00174
00175 HOWTO (R_AVR_HH8_LDI,
00176 16,
00177 1,
00178 8,
00179 FALSE,
00180 0,
00181 complain_overflow_dont,
00182 bfd_elf_generic_reloc,
00183 "R_AVR_HH8_LDI",
00184 FALSE,
00185 0xffff,
00186 0xffff,
00187 FALSE),
00188
00189
00190 HOWTO (R_AVR_LO8_LDI_NEG,
00191 0,
00192 1,
00193 8,
00194 FALSE,
00195 0,
00196 complain_overflow_dont,
00197 bfd_elf_generic_reloc,
00198 "R_AVR_LO8_LDI_NEG",
00199 FALSE,
00200 0xffff,
00201 0xffff,
00202 FALSE),
00203
00204
00205 HOWTO (R_AVR_HI8_LDI_NEG,
00206 8,
00207 1,
00208 8,
00209 FALSE,
00210 0,
00211 complain_overflow_dont,
00212 bfd_elf_generic_reloc,
00213 "R_AVR_HI8_LDI_NEG",
00214 FALSE,
00215 0xffff,
00216 0xffff,
00217 FALSE),
00218
00219
00220 HOWTO (R_AVR_HH8_LDI_NEG,
00221 16,
00222 1,
00223 8,
00224 FALSE,
00225 0,
00226 complain_overflow_dont,
00227 bfd_elf_generic_reloc,
00228 "R_AVR_HH8_LDI_NEG",
00229 FALSE,
00230 0xffff,
00231 0xffff,
00232 FALSE),
00233
00234
00235 HOWTO (R_AVR_LO8_LDI_PM,
00236 1,
00237 1,
00238 8,
00239 FALSE,
00240 0,
00241 complain_overflow_dont,
00242 bfd_elf_generic_reloc,
00243 "R_AVR_LO8_LDI_PM",
00244 FALSE,
00245 0xffff,
00246 0xffff,
00247 FALSE),
00248
00249
00250 HOWTO (R_AVR_HI8_LDI_PM,
00251 9,
00252 1,
00253 8,
00254 FALSE,
00255 0,
00256 complain_overflow_dont,
00257 bfd_elf_generic_reloc,
00258 "R_AVR_HI8_LDI_PM",
00259 FALSE,
00260 0xffff,
00261 0xffff,
00262 FALSE),
00263
00264
00265 HOWTO (R_AVR_HH8_LDI_PM,
00266 17,
00267 1,
00268 8,
00269 FALSE,
00270 0,
00271 complain_overflow_dont,
00272 bfd_elf_generic_reloc,
00273 "R_AVR_HH8_LDI_PM",
00274 FALSE,
00275 0xffff,
00276 0xffff,
00277 FALSE),
00278
00279
00280 HOWTO (R_AVR_LO8_LDI_PM_NEG,
00281 1,
00282 1,
00283 8,
00284 FALSE,
00285 0,
00286 complain_overflow_dont,
00287 bfd_elf_generic_reloc,
00288 "R_AVR_LO8_LDI_PM_NEG",
00289 FALSE,
00290 0xffff,
00291 0xffff,
00292 FALSE),
00293
00294
00295 HOWTO (R_AVR_HI8_LDI_PM_NEG,
00296 9,
00297 1,
00298 8,
00299 FALSE,
00300 0,
00301 complain_overflow_dont,
00302 bfd_elf_generic_reloc,
00303 "R_AVR_HI8_LDI_PM_NEG",
00304 FALSE,
00305 0xffff,
00306 0xffff,
00307 FALSE),
00308
00309
00310 HOWTO (R_AVR_HH8_LDI_PM_NEG,
00311 17,
00312 1,
00313 8,
00314 FALSE,
00315 0,
00316 complain_overflow_dont,
00317 bfd_elf_generic_reloc,
00318 "R_AVR_HH8_LDI_PM_NEG",
00319 FALSE,
00320 0xffff,
00321 0xffff,
00322 FALSE),
00323
00324 HOWTO (R_AVR_CALL,
00325 1,
00326 2,
00327 23,
00328 FALSE,
00329 0,
00330 complain_overflow_dont,
00331 bfd_elf_generic_reloc,
00332 "R_AVR_CALL",
00333 FALSE,
00334 0xffffffff,
00335 0xffffffff,
00336 FALSE),
00337
00338
00339 HOWTO (R_AVR_LDI,
00340 0,
00341 1,
00342 16,
00343 FALSE,
00344 0,
00345 complain_overflow_dont,
00346 bfd_elf_generic_reloc,
00347 "R_AVR_LDI",
00348 FALSE,
00349 0xffff,
00350 0xffff,
00351 FALSE),
00352
00353
00354 HOWTO (R_AVR_6,
00355 0,
00356 0,
00357 6,
00358 FALSE,
00359 0,
00360 complain_overflow_dont,
00361 bfd_elf_generic_reloc,
00362 "R_AVR_6",
00363 FALSE,
00364 0xffff,
00365 0xffff,
00366 FALSE),
00367
00368
00369 HOWTO (R_AVR_6_ADIW,
00370 0,
00371 0,
00372 6,
00373 FALSE,
00374 0,
00375 complain_overflow_dont,
00376 bfd_elf_generic_reloc,
00377 "R_AVR_6_ADIW",
00378 FALSE,
00379 0xffff,
00380 0xffff,
00381 FALSE)
00382 };
00383
00384
00385
00386 struct avr_reloc_map
00387 {
00388 bfd_reloc_code_real_type bfd_reloc_val;
00389 unsigned int elf_reloc_val;
00390 };
00391
00392 static const struct avr_reloc_map avr_reloc_map[] =
00393 {
00394 { BFD_RELOC_NONE, R_AVR_NONE },
00395 { BFD_RELOC_32, R_AVR_32 },
00396 { BFD_RELOC_AVR_7_PCREL, R_AVR_7_PCREL },
00397 { BFD_RELOC_AVR_13_PCREL, R_AVR_13_PCREL },
00398 { BFD_RELOC_16, R_AVR_16 },
00399 { BFD_RELOC_AVR_16_PM, R_AVR_16_PM },
00400 { BFD_RELOC_AVR_LO8_LDI, R_AVR_LO8_LDI},
00401 { BFD_RELOC_AVR_HI8_LDI, R_AVR_HI8_LDI },
00402 { BFD_RELOC_AVR_HH8_LDI, R_AVR_HH8_LDI },
00403 { BFD_RELOC_AVR_LO8_LDI_NEG, R_AVR_LO8_LDI_NEG },
00404 { BFD_RELOC_AVR_HI8_LDI_NEG, R_AVR_HI8_LDI_NEG },
00405 { BFD_RELOC_AVR_HH8_LDI_NEG, R_AVR_HH8_LDI_NEG },
00406 { BFD_RELOC_AVR_LO8_LDI_PM, R_AVR_LO8_LDI_PM },
00407 { BFD_RELOC_AVR_HI8_LDI_PM, R_AVR_HI8_LDI_PM },
00408 { BFD_RELOC_AVR_HH8_LDI_PM, R_AVR_HH8_LDI_PM },
00409 { BFD_RELOC_AVR_LO8_LDI_PM_NEG, R_AVR_LO8_LDI_PM_NEG },
00410 { BFD_RELOC_AVR_HI8_LDI_PM_NEG, R_AVR_HI8_LDI_PM_NEG },
00411 { BFD_RELOC_AVR_HH8_LDI_PM_NEG, R_AVR_HH8_LDI_PM_NEG },
00412 { BFD_RELOC_AVR_CALL, R_AVR_CALL },
00413 { BFD_RELOC_AVR_LDI, R_AVR_LDI },
00414 { BFD_RELOC_AVR_6, R_AVR_6 },
00415 { BFD_RELOC_AVR_6_ADIW, R_AVR_6_ADIW }
00416 };
00417
00418 static reloc_howto_type *
00419 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
00420 bfd *abfd ATTRIBUTE_UNUSED;
00421 bfd_reloc_code_real_type code;
00422 {
00423 unsigned int i;
00424
00425 for (i = 0;
00426 i < sizeof (avr_reloc_map) / sizeof (struct avr_reloc_map);
00427 i++)
00428 {
00429 if (avr_reloc_map[i].bfd_reloc_val == code)
00430 return &elf_avr_howto_table[avr_reloc_map[i].elf_reloc_val];
00431 }
00432
00433 return NULL;
00434 }
00435
00436
00437
00438 static void
00439 avr_info_to_howto_rela (abfd, cache_ptr, dst)
00440 bfd *abfd ATTRIBUTE_UNUSED;
00441 arelent *cache_ptr;
00442 Elf_Internal_Rela *dst;
00443 {
00444 unsigned int r_type;
00445
00446 r_type = ELF32_R_TYPE (dst->r_info);
00447 BFD_ASSERT (r_type < (unsigned int) R_AVR_max);
00448 cache_ptr->howto = &elf_avr_howto_table[r_type];
00449 }
00450
00451 static asection *
00452 elf32_avr_gc_mark_hook (sec, info, rel, h, sym)
00453 asection *sec;
00454 struct bfd_link_info *info ATTRIBUTE_UNUSED;
00455 Elf_Internal_Rela *rel;
00456 struct elf_link_hash_entry *h;
00457 Elf_Internal_Sym *sym;
00458 {
00459 if (h != NULL)
00460 {
00461 switch (ELF32_R_TYPE (rel->r_info))
00462 {
00463 default:
00464 switch (h->root.type)
00465 {
00466 case bfd_link_hash_defined:
00467 case bfd_link_hash_defweak:
00468 return h->root.u.def.section;
00469
00470 case bfd_link_hash_common:
00471 return h->root.u.c.p->section;
00472
00473 default:
00474 break;
00475 }
00476 }
00477 }
00478 else
00479 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
00480
00481 return NULL;
00482 }
00483
00484 static bfd_boolean
00485 elf32_avr_gc_sweep_hook (abfd, info, sec, relocs)
00486 bfd *abfd ATTRIBUTE_UNUSED;
00487 struct bfd_link_info *info ATTRIBUTE_UNUSED;
00488 asection *sec ATTRIBUTE_UNUSED;
00489 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
00490 {
00491
00492 return TRUE;
00493 }
00494
00495
00496
00497
00498
00499 static bfd_boolean
00500 elf32_avr_check_relocs (abfd, info, sec, relocs)
00501 bfd *abfd;
00502 struct bfd_link_info *info;
00503 asection *sec;
00504 const Elf_Internal_Rela *relocs;
00505 {
00506 Elf_Internal_Shdr *symtab_hdr;
00507 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
00508 const Elf_Internal_Rela *rel;
00509 const Elf_Internal_Rela *rel_end;
00510
00511 if (info->relocatable)
00512 return TRUE;
00513
00514 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00515 sym_hashes = elf_sym_hashes (abfd);
00516 sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
00517 if (!elf_bad_symtab (abfd))
00518 sym_hashes_end -= symtab_hdr->sh_info;
00519
00520 rel_end = relocs + sec->reloc_count;
00521 for (rel = relocs; rel < rel_end; rel++)
00522 {
00523 struct elf_link_hash_entry *h;
00524 unsigned long r_symndx;
00525
00526 r_symndx = ELF32_R_SYM (rel->r_info);
00527 if (r_symndx < symtab_hdr->sh_info)
00528 h = NULL;
00529 else
00530 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
00531 }
00532
00533 return TRUE;
00534 }
00535
00536
00537
00538
00539 static bfd_reloc_status_type
00540 avr_final_link_relocate (howto, input_bfd, input_section,
00541 contents, rel, relocation)
00542 reloc_howto_type * howto;
00543 bfd * input_bfd;
00544 asection * input_section;
00545 bfd_byte * contents;
00546 Elf_Internal_Rela * rel;
00547 bfd_vma relocation;
00548 {
00549 bfd_reloc_status_type r = bfd_reloc_ok;
00550 bfd_vma x;
00551 bfd_signed_vma srel;
00552
00553 switch (howto->type)
00554 {
00555 case R_AVR_7_PCREL:
00556 contents += rel->r_offset;
00557 srel = (bfd_signed_vma) relocation;
00558 srel += rel->r_addend;
00559 srel -= rel->r_offset;
00560 srel -= 2;
00561 srel -= (input_section->output_section->vma +
00562 input_section->output_offset);
00563
00564 if (srel & 1)
00565 return bfd_reloc_outofrange;
00566 if (srel > ((1 << 7) - 1) || (srel < - (1 << 7)))
00567 return bfd_reloc_overflow;
00568 x = bfd_get_16 (input_bfd, contents);
00569 x = (x & 0xfc07) | (((srel >> 1) << 3) & 0x3f8);
00570 bfd_put_16 (input_bfd, x, contents);
00571 break;
00572
00573 case R_AVR_13_PCREL:
00574 contents += rel->r_offset;
00575 srel = (bfd_signed_vma) relocation;
00576 srel += rel->r_addend;
00577 srel -= rel->r_offset;
00578 srel -= 2;
00579 srel -= (input_section->output_section->vma +
00580 input_section->output_offset);
00581
00582 if (srel & 1)
00583 return bfd_reloc_outofrange;
00584
00585
00586 srel >>= 1;
00587
00588
00589 if (srel < -2048 || srel > 2047)
00590 {
00591
00592 switch (bfd_get_mach (input_bfd))
00593 {
00594 case bfd_mach_avr2:
00595 case bfd_mach_avr4:
00596 break;
00597
00598 default:
00599 return bfd_reloc_overflow;
00600 }
00601 }
00602
00603 x = bfd_get_16 (input_bfd, contents);
00604 x = (x & 0xf000) | (srel & 0xfff);
00605 bfd_put_16 (input_bfd, x, contents);
00606 break;
00607
00608 case R_AVR_LO8_LDI:
00609 contents += rel->r_offset;
00610 srel = (bfd_signed_vma) relocation + rel->r_addend;
00611 x = bfd_get_16 (input_bfd, contents);
00612 x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
00613 bfd_put_16 (input_bfd, x, contents);
00614 break;
00615
00616 case R_AVR_LDI:
00617 contents += rel->r_offset;
00618 srel = (bfd_signed_vma) relocation + rel->r_addend;
00619 if ((srel & 0xffff) > 255)
00620
00621 return bfd_reloc_overflow;
00622 x = bfd_get_16 (input_bfd, contents);
00623 x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
00624 bfd_put_16 (input_bfd, x, contents);
00625 break;
00626
00627 case R_AVR_6:
00628 contents += rel->r_offset;
00629 srel = (bfd_signed_vma) relocation + rel->r_addend;
00630 if (((srel & 0xffff) > 63) || (srel < 0))
00631
00632 return bfd_reloc_overflow;
00633 x = bfd_get_16 (input_bfd, contents);
00634 x = (x & 0xd3f8) | ((srel & 7) | ((srel & (3 << 3)) << 7) | ((srel & (1 << 5)) << 8));
00635 bfd_put_16 (input_bfd, x, contents);
00636 break;
00637
00638 case R_AVR_6_ADIW:
00639 contents += rel->r_offset;
00640 srel = (bfd_signed_vma) relocation + rel->r_addend;
00641 if (((srel & 0xffff) > 63) || (srel < 0))
00642
00643 return bfd_reloc_overflow;
00644 x = bfd_get_16 (input_bfd, contents);
00645 x = (x & 0xff30) | (srel & 0xf) | ((srel & 0x30) << 2);
00646 bfd_put_16 (input_bfd, x, contents);
00647 break;
00648
00649 case R_AVR_HI8_LDI:
00650 contents += rel->r_offset;
00651 srel = (bfd_signed_vma) relocation + rel->r_addend;
00652 srel = (srel >> 8) & 0xff;
00653 x = bfd_get_16 (input_bfd, contents);
00654 x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
00655 bfd_put_16 (input_bfd, x, contents);
00656 break;
00657
00658 case R_AVR_HH8_LDI:
00659 contents += rel->r_offset;
00660 srel = (bfd_signed_vma) relocation + rel->r_addend;
00661 srel = (srel >> 16) & 0xff;
00662 x = bfd_get_16 (input_bfd, contents);
00663 x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
00664 bfd_put_16 (input_bfd, x, contents);
00665 break;
00666
00667 case R_AVR_LO8_LDI_NEG:
00668 contents += rel->r_offset;
00669 srel = (bfd_signed_vma) relocation + rel->r_addend;
00670 srel = -srel;
00671 x = bfd_get_16 (input_bfd, contents);
00672 x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
00673 bfd_put_16 (input_bfd, x, contents);
00674 break;
00675
00676 case R_AVR_HI8_LDI_NEG:
00677 contents += rel->r_offset;
00678 srel = (bfd_signed_vma) relocation + rel->r_addend;
00679 srel = -srel;
00680 srel = (srel >> 8) & 0xff;
00681 x = bfd_get_16 (input_bfd, contents);
00682 x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
00683 bfd_put_16 (input_bfd, x, contents);
00684 break;
00685
00686 case R_AVR_HH8_LDI_NEG:
00687 contents += rel->r_offset;
00688 srel = (bfd_signed_vma) relocation + rel->r_addend;
00689 srel = -srel;
00690 srel = (srel >> 16) & 0xff;
00691 x = bfd_get_16 (input_bfd, contents);
00692 x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
00693 bfd_put_16 (input_bfd, x, contents);
00694 break;
00695
00696 case R_AVR_LO8_LDI_PM:
00697 contents += rel->r_offset;
00698 srel = (bfd_signed_vma) relocation + rel->r_addend;
00699 if (srel & 1)
00700 return bfd_reloc_outofrange;
00701 srel = srel >> 1;
00702 x = bfd_get_16 (input_bfd, contents);
00703 x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
00704 bfd_put_16 (input_bfd, x, contents);
00705 break;
00706
00707 case R_AVR_HI8_LDI_PM:
00708 contents += rel->r_offset;
00709 srel = (bfd_signed_vma) relocation + rel->r_addend;
00710 if (srel & 1)
00711 return bfd_reloc_outofrange;
00712 srel = srel >> 1;
00713 srel = (srel >> 8) & 0xff;
00714 x = bfd_get_16 (input_bfd, contents);
00715 x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
00716 bfd_put_16 (input_bfd, x, contents);
00717 break;
00718
00719 case R_AVR_HH8_LDI_PM:
00720 contents += rel->r_offset;
00721 srel = (bfd_signed_vma) relocation + rel->r_addend;
00722 if (srel & 1)
00723 return bfd_reloc_outofrange;
00724 srel = srel >> 1;
00725 srel = (srel >> 16) & 0xff;
00726 x = bfd_get_16 (input_bfd, contents);
00727 x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
00728 bfd_put_16 (input_bfd, x, contents);
00729 break;
00730
00731 case R_AVR_LO8_LDI_PM_NEG:
00732 contents += rel->r_offset;
00733 srel = (bfd_signed_vma) relocation + rel->r_addend;
00734 srel = -srel;
00735 if (srel & 1)
00736 return bfd_reloc_outofrange;
00737 srel = srel >> 1;
00738 x = bfd_get_16 (input_bfd, contents);
00739 x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
00740 bfd_put_16 (input_bfd, x, contents);
00741 break;
00742
00743 case R_AVR_HI8_LDI_PM_NEG:
00744 contents += rel->r_offset;
00745 srel = (bfd_signed_vma) relocation + rel->r_addend;
00746 srel = -srel;
00747 if (srel & 1)
00748 return bfd_reloc_outofrange;
00749 srel = srel >> 1;
00750 srel = (srel >> 8) & 0xff;
00751 x = bfd_get_16 (input_bfd, contents);
00752 x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
00753 bfd_put_16 (input_bfd, x, contents);
00754 break;
00755
00756 case R_AVR_HH8_LDI_PM_NEG:
00757 contents += rel->r_offset;
00758 srel = (bfd_signed_vma) relocation + rel->r_addend;
00759 srel = -srel;
00760 if (srel & 1)
00761 return bfd_reloc_outofrange;
00762 srel = srel >> 1;
00763 srel = (srel >> 16) & 0xff;
00764 x = bfd_get_16 (input_bfd, contents);
00765 x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00);
00766 bfd_put_16 (input_bfd, x, contents);
00767 break;
00768
00769 case R_AVR_CALL:
00770 contents += rel->r_offset;
00771 srel = (bfd_signed_vma) relocation + rel->r_addend;
00772 if (srel & 1)
00773 return bfd_reloc_outofrange;
00774 srel = srel >> 1;
00775 x = bfd_get_16 (input_bfd, contents);
00776 x |= ((srel & 0x10000) | ((srel << 3) & 0x1f00000)) >> 16;
00777 bfd_put_16 (input_bfd, x, contents);
00778 bfd_put_16 (input_bfd, (bfd_vma) srel & 0xffff, contents+2);
00779 break;
00780
00781 default:
00782 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
00783 contents, rel->r_offset,
00784 relocation, rel->r_addend);
00785 }
00786
00787 return r;
00788 }
00789
00790
00791 static bfd_boolean
00792 elf32_avr_relocate_section (output_bfd, info, input_bfd, input_section,
00793 contents, relocs, local_syms, local_sections)
00794 bfd *output_bfd ATTRIBUTE_UNUSED;
00795 struct bfd_link_info *info;
00796 bfd *input_bfd;
00797 asection *input_section;
00798 bfd_byte *contents;
00799 Elf_Internal_Rela *relocs;
00800 Elf_Internal_Sym *local_syms;
00801 asection **local_sections;
00802 {
00803 Elf_Internal_Shdr * symtab_hdr;
00804 struct elf_link_hash_entry ** sym_hashes;
00805 Elf_Internal_Rela * rel;
00806 Elf_Internal_Rela * relend;
00807
00808 if (info->relocatable)
00809 return TRUE;
00810
00811 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
00812 sym_hashes = elf_sym_hashes (input_bfd);
00813 relend = relocs + input_section->reloc_count;
00814
00815 for (rel = relocs; rel < relend; rel ++)
00816 {
00817 reloc_howto_type * howto;
00818 unsigned long r_symndx;
00819 Elf_Internal_Sym * sym;
00820 asection * sec;
00821 struct elf_link_hash_entry * h;
00822 bfd_vma relocation;
00823 bfd_reloc_status_type r;
00824 const char * name;
00825 int r_type;
00826
00827
00828 r_type = ELF32_R_TYPE (rel->r_info);
00829 r_symndx = ELF32_R_SYM (rel->r_info);
00830 howto = elf_avr_howto_table + ELF32_R_TYPE (rel->r_info);
00831 h = NULL;
00832 sym = NULL;
00833 sec = NULL;
00834
00835 if (r_symndx < symtab_hdr->sh_info)
00836 {
00837 sym = local_syms + r_symndx;
00838 sec = local_sections [r_symndx];
00839 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
00840
00841 name = bfd_elf_string_from_elf_section
00842 (input_bfd, symtab_hdr->sh_link, sym->st_name);
00843 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
00844 }
00845 else
00846 {
00847 bfd_boolean unresolved_reloc, warned;
00848
00849 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
00850 r_symndx, symtab_hdr, sym_hashes,
00851 h, sec, relocation,
00852 unresolved_reloc, warned);
00853
00854 name = h->root.root.string;
00855 }
00856
00857 r = avr_final_link_relocate (howto, input_bfd, input_section,
00858 contents, rel, relocation);
00859
00860 if (r != bfd_reloc_ok)
00861 {
00862 const char * msg = (const char *) NULL;
00863
00864 switch (r)
00865 {
00866 case bfd_reloc_overflow:
00867 r = info->callbacks->reloc_overflow
00868 (info, (h ? &h->root : NULL),
00869 name, howto->name, (bfd_vma) 0,
00870 input_bfd, input_section, rel->r_offset);
00871 break;
00872
00873 case bfd_reloc_undefined:
00874 r = info->callbacks->undefined_symbol
00875 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
00876 break;
00877
00878 case bfd_reloc_outofrange:
00879 msg = _("internal error: out of range error");
00880 break;
00881
00882 case bfd_reloc_notsupported:
00883 msg = _("internal error: unsupported relocation error");
00884 break;
00885
00886 case bfd_reloc_dangerous:
00887 msg = _("internal error: dangerous relocation");
00888 break;
00889
00890 default:
00891 msg = _("internal error: unknown error");
00892 break;
00893 }
00894
00895 if (msg)
00896 r = info->callbacks->warning
00897 (info, msg, name, input_bfd, input_section, rel->r_offset);
00898
00899 if (! r)
00900 return FALSE;
00901 }
00902 }
00903
00904 return TRUE;
00905 }
00906
00907
00908
00909
00910
00911 static void
00912 bfd_elf_avr_final_write_processing (abfd, linker)
00913 bfd *abfd;
00914 bfd_boolean linker ATTRIBUTE_UNUSED;
00915 {
00916 unsigned long val;
00917
00918 switch (bfd_get_mach (abfd))
00919 {
00920 default:
00921 case bfd_mach_avr2:
00922 val = E_AVR_MACH_AVR2;
00923 break;
00924
00925 case bfd_mach_avr1:
00926 val = E_AVR_MACH_AVR1;
00927 break;
00928
00929 case bfd_mach_avr3:
00930 val = E_AVR_MACH_AVR3;
00931 break;
00932
00933 case bfd_mach_avr4:
00934 val = E_AVR_MACH_AVR4;
00935 break;
00936
00937 case bfd_mach_avr5:
00938 val = E_AVR_MACH_AVR5;
00939 break;
00940 }
00941
00942 elf_elfheader (abfd)->e_machine = EM_AVR;
00943 elf_elfheader (abfd)->e_flags &= ~ EF_AVR_MACH;
00944 elf_elfheader (abfd)->e_flags |= val;
00945 }
00946
00947
00948
00949 static bfd_boolean
00950 elf32_avr_object_p (abfd)
00951 bfd *abfd;
00952 {
00953 unsigned int e_set = bfd_mach_avr2;
00954 if (elf_elfheader (abfd)->e_machine == EM_AVR
00955 || elf_elfheader (abfd)->e_machine == EM_AVR_OLD)
00956 {
00957 int e_mach = elf_elfheader (abfd)->e_flags & EF_AVR_MACH;
00958 switch (e_mach)
00959 {
00960 default:
00961 case E_AVR_MACH_AVR2:
00962 e_set = bfd_mach_avr2;
00963 break;
00964
00965 case E_AVR_MACH_AVR1:
00966 e_set = bfd_mach_avr1;
00967 break;
00968
00969 case E_AVR_MACH_AVR3:
00970 e_set = bfd_mach_avr3;
00971 break;
00972
00973 case E_AVR_MACH_AVR4:
00974 e_set = bfd_mach_avr4;
00975 break;
00976
00977 case E_AVR_MACH_AVR5:
00978 e_set = bfd_mach_avr5;
00979 break;
00980 }
00981 }
00982 return bfd_default_set_arch_mach (abfd, bfd_arch_avr,
00983 e_set);
00984 }
00985
00986 #define ELF_ARCH bfd_arch_avr
00987 #define ELF_MACHINE_CODE EM_AVR
00988 #define ELF_MACHINE_ALT1 EM_AVR_OLD
00989 #define ELF_MAXPAGESIZE 1
00990
00991 #define TARGET_LITTLE_SYM bfd_elf32_avr_vec
00992 #define TARGET_LITTLE_NAME "elf32-avr"
00993
00994 #define elf_info_to_howto avr_info_to_howto_rela
00995 #define elf_info_to_howto_rel NULL
00996 #define elf_backend_relocate_section elf32_avr_relocate_section
00997 #define elf_backend_gc_mark_hook elf32_avr_gc_mark_hook
00998 #define elf_backend_gc_sweep_hook elf32_avr_gc_sweep_hook
00999 #define elf_backend_check_relocs elf32_avr_check_relocs
01000 #define elf_backend_can_gc_sections 1
01001 #define elf_backend_rela_normal 1
01002 #define elf_backend_final_write_processing \
01003 bfd_elf_avr_final_write_processing
01004 #define elf_backend_object_p elf32_avr_object_p
01005
01006 #include "elf32-target.h"