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 #include "bfd.h"
00026 #include "sysdep.h"
00027 #include "libbfd.h"
00028 #include "elf-bfd.h"
00029 #include "elf/fr30.h"
00030
00031
00032 static bfd_reloc_status_type fr30_elf_i20_reloc
00033 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00034 static bfd_reloc_status_type fr30_elf_i32_reloc
00035 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00036 static reloc_howto_type * fr30_reloc_type_lookup
00037 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
00038 static void fr30_info_to_howto_rela
00039 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
00040 static bfd_boolean fr30_elf_relocate_section
00041 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00042 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
00043 static bfd_reloc_status_type fr30_final_link_relocate
00044 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
00045 Elf_Internal_Rela *, bfd_vma));
00046 static bfd_boolean fr30_elf_gc_sweep_hook
00047 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00048 const Elf_Internal_Rela *));
00049 static asection * fr30_elf_gc_mark_hook
00050 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
00051 struct elf_link_hash_entry *, Elf_Internal_Sym *));
00052 static bfd_boolean fr30_elf_check_relocs
00053 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00054 const Elf_Internal_Rela *));
00055
00056 static reloc_howto_type fr30_elf_howto_table [] =
00057 {
00058
00059 HOWTO (R_FR30_NONE,
00060 0,
00061 2,
00062 32,
00063 FALSE,
00064 0,
00065 complain_overflow_bitfield,
00066 bfd_elf_generic_reloc,
00067 "R_FR30_NONE",
00068 FALSE,
00069 0,
00070 0,
00071 FALSE),
00072
00073
00074 HOWTO (R_FR30_8,
00075 0,
00076 1,
00077 8,
00078 FALSE,
00079 4,
00080 complain_overflow_bitfield,
00081 bfd_elf_generic_reloc,
00082 "R_FR30_8",
00083 TRUE,
00084 0x0000,
00085 0x0ff0,
00086 FALSE),
00087
00088
00089 HOWTO (R_FR30_20,
00090 0,
00091 2,
00092 20,
00093 FALSE,
00094 0,
00095 complain_overflow_bitfield,
00096 fr30_elf_i20_reloc,
00097 "R_FR30_20",
00098 TRUE,
00099 0x00000000,
00100 0x00f0ffff,
00101 FALSE),
00102
00103
00104 HOWTO (R_FR30_32,
00105 0,
00106 2,
00107 32,
00108 FALSE,
00109 0,
00110 complain_overflow_bitfield,
00111 bfd_elf_generic_reloc,
00112 "R_FR30_32",
00113 TRUE,
00114 0x00000000,
00115 0xffffffff,
00116 FALSE),
00117
00118
00119 HOWTO (R_FR30_48,
00120 0,
00121 2,
00122 32,
00123 FALSE,
00124 0,
00125 complain_overflow_bitfield,
00126 fr30_elf_i32_reloc,
00127 "R_FR30_48",
00128 TRUE,
00129 0x00000000,
00130 0xffffffff,
00131 FALSE),
00132
00133
00134 HOWTO (R_FR30_6_IN_4,
00135 2,
00136 1,
00137 6,
00138 FALSE,
00139 4,
00140 complain_overflow_unsigned,
00141 bfd_elf_generic_reloc,
00142 "R_FR30_6_IN_4",
00143 TRUE,
00144 0x0000,
00145 0x00f0,
00146 FALSE),
00147
00148
00149 HOWTO (R_FR30_8_IN_8,
00150 0,
00151 1,
00152 8,
00153 FALSE,
00154 4,
00155 complain_overflow_signed,
00156 bfd_elf_generic_reloc,
00157 "R_FR30_8_IN_8",
00158 TRUE,
00159 0x0000,
00160 0x0ff0,
00161 FALSE),
00162
00163
00164 HOWTO (R_FR30_9_IN_8,
00165 1,
00166 1,
00167 9,
00168 FALSE,
00169 4,
00170 complain_overflow_signed,
00171 bfd_elf_generic_reloc,
00172 "R_FR30_9_IN_8",
00173 TRUE,
00174 0x0000,
00175 0x0ff0,
00176 FALSE),
00177
00178
00179 HOWTO (R_FR30_10_IN_8,
00180 2,
00181 1,
00182 10,
00183 FALSE,
00184 4,
00185 complain_overflow_signed,
00186 bfd_elf_generic_reloc,
00187 "R_FR30_10_IN_8",
00188 TRUE,
00189 0x0000,
00190 0x0ff0,
00191 FALSE),
00192
00193
00194 HOWTO (R_FR30_9_PCREL,
00195 1,
00196 1,
00197 9,
00198 TRUE,
00199 0,
00200 complain_overflow_signed,
00201 bfd_elf_generic_reloc,
00202 "R_FR30_9_PCREL",
00203 FALSE,
00204 0x0000,
00205 0x00ff,
00206 FALSE),
00207
00208
00209 HOWTO (R_FR30_12_PCREL,
00210 1,
00211 1,
00212 12,
00213 TRUE,
00214 0,
00215 complain_overflow_signed,
00216 bfd_elf_generic_reloc,
00217 "R_FR30_12_PCREL",
00218 FALSE,
00219 0x0000,
00220 0x07ff,
00221 FALSE),
00222
00223 HOWTO (R_FR30_GNU_VTINHERIT,
00224 0,
00225 2,
00226 0,
00227 FALSE,
00228 0,
00229 complain_overflow_dont,
00230 NULL,
00231 "R_FR30_GNU_VTINHERIT",
00232 FALSE,
00233 0,
00234 0,
00235 FALSE),
00236
00237
00238 HOWTO (R_FR30_GNU_VTENTRY,
00239 0,
00240 2,
00241 0,
00242 FALSE,
00243 0,
00244 complain_overflow_dont,
00245 _bfd_elf_rel_vtable_reloc_fn,
00246 "R_FR30_GNU_VTENTRY",
00247 FALSE,
00248 0,
00249 0,
00250 FALSE),
00251 };
00252
00253
00254
00255 static bfd_reloc_status_type
00256 fr30_elf_i20_reloc (abfd, reloc_entry, symbol, data,
00257 input_section, output_bfd, error_message)
00258 bfd *abfd;
00259 arelent *reloc_entry;
00260 asymbol *symbol;
00261 PTR data;
00262 asection *input_section;
00263 bfd *output_bfd;
00264 char **error_message ATTRIBUTE_UNUSED;
00265 {
00266 bfd_vma relocation;
00267 unsigned long x;
00268
00269
00270 if (output_bfd != (bfd *) NULL
00271 && (symbol->flags & BSF_SECTION_SYM) == 0
00272 && (! reloc_entry->howto->partial_inplace
00273 || reloc_entry->addend == 0))
00274 {
00275 reloc_entry->address += input_section->output_offset;
00276 return bfd_reloc_ok;
00277 }
00278
00279 if (output_bfd != NULL)
00280
00281 return bfd_reloc_ok;
00282
00283 relocation =
00284 symbol->value
00285 + symbol->section->output_section->vma
00286 + symbol->section->output_offset
00287 + reloc_entry->addend;
00288
00289 if (relocation > (((bfd_vma) 1 << 20) - 1))
00290 return bfd_reloc_overflow;
00291
00292 x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
00293 x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
00294 bfd_put_32 (abfd, (bfd_vma) x, (char *) data + reloc_entry->address);
00295
00296 return bfd_reloc_ok;
00297 }
00298
00299
00300
00301 static bfd_reloc_status_type
00302 fr30_elf_i32_reloc (abfd, reloc_entry, symbol, data,
00303 input_section, output_bfd, error_message)
00304 bfd *abfd;
00305 arelent *reloc_entry;
00306 asymbol *symbol;
00307 PTR data;
00308 asection *input_section;
00309 bfd *output_bfd;
00310 char **error_message ATTRIBUTE_UNUSED;
00311 {
00312 bfd_vma relocation;
00313
00314
00315 if (output_bfd != (bfd *) NULL
00316 && (symbol->flags & BSF_SECTION_SYM) == 0
00317 && (! reloc_entry->howto->partial_inplace
00318 || reloc_entry->addend == 0))
00319 {
00320 reloc_entry->address += input_section->output_offset;
00321 return bfd_reloc_ok;
00322 }
00323
00324 if (output_bfd != NULL)
00325
00326 return bfd_reloc_ok;
00327
00328 relocation =
00329 symbol->value
00330 + symbol->section->output_section->vma
00331 + symbol->section->output_offset
00332 + reloc_entry->addend;
00333
00334 bfd_put_32 (abfd, relocation, (char *) data + reloc_entry->address + 2);
00335
00336 return bfd_reloc_ok;
00337 }
00338
00339
00340
00341 struct fr30_reloc_map
00342 {
00343 bfd_reloc_code_real_type bfd_reloc_val;
00344 unsigned int fr30_reloc_val;
00345 };
00346
00347 static const struct fr30_reloc_map fr30_reloc_map [] =
00348 {
00349 { BFD_RELOC_NONE, R_FR30_NONE },
00350 { BFD_RELOC_8, R_FR30_8 },
00351 { BFD_RELOC_FR30_20, R_FR30_20 },
00352 { BFD_RELOC_32, R_FR30_32 },
00353 { BFD_RELOC_FR30_48, R_FR30_48 },
00354 { BFD_RELOC_FR30_6_IN_4, R_FR30_6_IN_4 },
00355 { BFD_RELOC_FR30_8_IN_8, R_FR30_8_IN_8 },
00356 { BFD_RELOC_FR30_9_IN_8, R_FR30_9_IN_8 },
00357 { BFD_RELOC_FR30_10_IN_8, R_FR30_10_IN_8 },
00358 { BFD_RELOC_FR30_9_PCREL, R_FR30_9_PCREL },
00359 { BFD_RELOC_FR30_12_PCREL, R_FR30_12_PCREL },
00360 { BFD_RELOC_VTABLE_INHERIT, R_FR30_GNU_VTINHERIT },
00361 { BFD_RELOC_VTABLE_ENTRY, R_FR30_GNU_VTENTRY },
00362 };
00363
00364 static reloc_howto_type *
00365 fr30_reloc_type_lookup (abfd, code)
00366 bfd *abfd ATTRIBUTE_UNUSED;
00367 bfd_reloc_code_real_type code;
00368 {
00369 unsigned int i;
00370
00371 for (i = sizeof (fr30_reloc_map) / sizeof (fr30_reloc_map[0]);
00372 --i;)
00373 if (fr30_reloc_map [i].bfd_reloc_val == code)
00374 return & fr30_elf_howto_table [fr30_reloc_map[i].fr30_reloc_val];
00375
00376 return NULL;
00377 }
00378
00379
00380
00381 static void
00382 fr30_info_to_howto_rela (abfd, cache_ptr, dst)
00383 bfd *abfd ATTRIBUTE_UNUSED;
00384 arelent *cache_ptr;
00385 Elf_Internal_Rela *dst;
00386 {
00387 unsigned int r_type;
00388
00389 r_type = ELF32_R_TYPE (dst->r_info);
00390 BFD_ASSERT (r_type < (unsigned int) R_FR30_max);
00391 cache_ptr->howto = & fr30_elf_howto_table [r_type];
00392 }
00393
00394
00395
00396
00397 static bfd_reloc_status_type
00398 fr30_final_link_relocate (howto, input_bfd, input_section, contents, rel,
00399 relocation)
00400 reloc_howto_type *howto;
00401 bfd *input_bfd;
00402 asection *input_section;
00403 bfd_byte *contents;
00404 Elf_Internal_Rela *rel;
00405 bfd_vma relocation;
00406 {
00407 bfd_reloc_status_type r = bfd_reloc_ok;
00408 bfd_vma x;
00409 bfd_signed_vma srel;
00410
00411 switch (howto->type)
00412 {
00413 case R_FR30_20:
00414 contents += rel->r_offset;
00415 relocation += rel->r_addend;
00416
00417 if (relocation > ((1 << 20) - 1))
00418 return bfd_reloc_overflow;
00419
00420 x = bfd_get_32 (input_bfd, contents);
00421 x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
00422 bfd_put_32 (input_bfd, x, contents);
00423 break;
00424
00425 case R_FR30_48:
00426 contents += rel->r_offset + 2;
00427 relocation += rel->r_addend;
00428 bfd_put_32 (input_bfd, relocation, contents);
00429 break;
00430
00431 case R_FR30_9_PCREL:
00432 contents += rel->r_offset + 1;
00433 srel = (bfd_signed_vma) relocation;
00434 srel += rel->r_addend;
00435 srel -= rel->r_offset;
00436 srel -= 2;
00437 srel -= (input_section->output_section->vma +
00438 input_section->output_offset);
00439
00440 if (srel & 1)
00441 return bfd_reloc_outofrange;
00442 if (srel > ((1 << 8) - 1) || (srel < - (1 << 8)))
00443 return bfd_reloc_overflow;
00444
00445 bfd_put_8 (input_bfd, srel >> 1, contents);
00446 break;
00447
00448 case R_FR30_12_PCREL:
00449 contents += rel->r_offset;
00450 srel = (bfd_signed_vma) relocation;
00451 srel += rel->r_addend;
00452 srel -= rel->r_offset;
00453 srel -= 2;
00454 srel -= (input_section->output_section->vma +
00455 input_section->output_offset);
00456
00457 if (srel & 1)
00458 return bfd_reloc_outofrange;
00459 if (srel > ((1 << 11) - 1) || (srel < - (1 << 11)))
00460 return bfd_reloc_overflow;
00461
00462 x = bfd_get_16 (input_bfd, contents);
00463 x = (x & 0xf800) | ((srel >> 1) & 0x7ff);
00464 bfd_put_16 (input_bfd, x, contents);
00465 break;
00466
00467 default:
00468 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
00469 contents, rel->r_offset,
00470 relocation, rel->r_addend);
00471 }
00472
00473 return r;
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 static bfd_boolean
00507 fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
00508 contents, relocs, local_syms, local_sections)
00509 bfd *output_bfd;
00510 struct bfd_link_info *info;
00511 bfd *input_bfd;
00512 asection *input_section;
00513 bfd_byte *contents;
00514 Elf_Internal_Rela *relocs;
00515 Elf_Internal_Sym *local_syms;
00516 asection **local_sections;
00517 {
00518 Elf_Internal_Shdr *symtab_hdr;
00519 struct elf_link_hash_entry **sym_hashes;
00520 Elf_Internal_Rela *rel;
00521 Elf_Internal_Rela *relend;
00522
00523 if (info->relocatable)
00524 return TRUE;
00525
00526 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
00527 sym_hashes = elf_sym_hashes (input_bfd);
00528 relend = relocs + input_section->reloc_count;
00529
00530 for (rel = relocs; rel < relend; rel ++)
00531 {
00532 reloc_howto_type *howto;
00533 unsigned long r_symndx;
00534 Elf_Internal_Sym *sym;
00535 asection *sec;
00536 struct elf_link_hash_entry *h;
00537 bfd_vma relocation;
00538 bfd_reloc_status_type r;
00539 const char *name;
00540 int r_type;
00541
00542 r_type = ELF32_R_TYPE (rel->r_info);
00543
00544 if ( r_type == R_FR30_GNU_VTINHERIT
00545 || r_type == R_FR30_GNU_VTENTRY)
00546 continue;
00547
00548 r_symndx = ELF32_R_SYM (rel->r_info);
00549
00550 howto = fr30_elf_howto_table + ELF32_R_TYPE (rel->r_info);
00551 h = NULL;
00552 sym = NULL;
00553 sec = NULL;
00554
00555 if (r_symndx < symtab_hdr->sh_info)
00556 {
00557 sym = local_syms + r_symndx;
00558 sec = local_sections [r_symndx];
00559 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
00560
00561 name = bfd_elf_string_from_elf_section
00562 (input_bfd, symtab_hdr->sh_link, sym->st_name);
00563 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
00564 }
00565 else
00566 {
00567 bfd_boolean unresolved_reloc, warned;
00568
00569 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
00570 r_symndx, symtab_hdr, sym_hashes,
00571 h, sec, relocation,
00572 unresolved_reloc, warned);
00573
00574 name = h->root.root.string;
00575 }
00576
00577 r = fr30_final_link_relocate (howto, input_bfd, input_section,
00578 contents, rel, relocation);
00579
00580 if (r != bfd_reloc_ok)
00581 {
00582 const char * msg = (const char *) NULL;
00583
00584 switch (r)
00585 {
00586 case bfd_reloc_overflow:
00587 r = info->callbacks->reloc_overflow
00588 (info, (h ? &h->root : NULL), name, howto->name,
00589 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
00590 break;
00591
00592 case bfd_reloc_undefined:
00593 r = info->callbacks->undefined_symbol
00594 (info, name, input_bfd, input_section, rel->r_offset,
00595 TRUE);
00596 break;
00597
00598 case bfd_reloc_outofrange:
00599 msg = _("internal error: out of range error");
00600 break;
00601
00602 case bfd_reloc_notsupported:
00603 msg = _("internal error: unsupported relocation error");
00604 break;
00605
00606 case bfd_reloc_dangerous:
00607 msg = _("internal error: dangerous relocation");
00608 break;
00609
00610 default:
00611 msg = _("internal error: unknown error");
00612 break;
00613 }
00614
00615 if (msg)
00616 r = info->callbacks->warning
00617 (info, msg, name, input_bfd, input_section, rel->r_offset);
00618
00619 if (! r)
00620 return FALSE;
00621 }
00622 }
00623
00624 return TRUE;
00625 }
00626
00627
00628
00629
00630 static asection *
00631 fr30_elf_gc_mark_hook (sec, info, rel, h, sym)
00632 asection *sec;
00633 struct bfd_link_info *info ATTRIBUTE_UNUSED;
00634 Elf_Internal_Rela *rel;
00635 struct elf_link_hash_entry *h;
00636 Elf_Internal_Sym * sym;
00637 {
00638 if (h != NULL)
00639 {
00640 switch (ELF32_R_TYPE (rel->r_info))
00641 {
00642 case R_FR30_GNU_VTINHERIT:
00643 case R_FR30_GNU_VTENTRY:
00644 break;
00645
00646 default:
00647 switch (h->root.type)
00648 {
00649 case bfd_link_hash_defined:
00650 case bfd_link_hash_defweak:
00651 return h->root.u.def.section;
00652
00653 case bfd_link_hash_common:
00654 return h->root.u.c.p->section;
00655
00656 default:
00657 break;
00658 }
00659 }
00660 }
00661 else
00662 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
00663
00664 return NULL;
00665 }
00666
00667
00668
00669 static bfd_boolean
00670 fr30_elf_gc_sweep_hook (abfd, info, sec, relocs)
00671 bfd *abfd ATTRIBUTE_UNUSED;
00672 struct bfd_link_info *info ATTRIBUTE_UNUSED;
00673 asection *sec ATTRIBUTE_UNUSED;
00674 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
00675 {
00676 return TRUE;
00677 }
00678
00679
00680
00681
00682
00683 static bfd_boolean
00684 fr30_elf_check_relocs (abfd, info, sec, relocs)
00685 bfd *abfd;
00686 struct bfd_link_info *info;
00687 asection *sec;
00688 const Elf_Internal_Rela *relocs;
00689 {
00690 Elf_Internal_Shdr *symtab_hdr;
00691 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
00692 const Elf_Internal_Rela *rel;
00693 const Elf_Internal_Rela *rel_end;
00694
00695 if (info->relocatable)
00696 return TRUE;
00697
00698 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00699 sym_hashes = elf_sym_hashes (abfd);
00700 sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
00701 if (!elf_bad_symtab (abfd))
00702 sym_hashes_end -= symtab_hdr->sh_info;
00703
00704 rel_end = relocs + sec->reloc_count;
00705 for (rel = relocs; rel < rel_end; rel++)
00706 {
00707 struct elf_link_hash_entry *h;
00708 unsigned long r_symndx;
00709
00710 r_symndx = ELF32_R_SYM (rel->r_info);
00711 if (r_symndx < symtab_hdr->sh_info)
00712 h = NULL;
00713 else
00714 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
00715
00716 switch (ELF32_R_TYPE (rel->r_info))
00717 {
00718
00719
00720 case R_FR30_GNU_VTINHERIT:
00721 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
00722 return FALSE;
00723 break;
00724
00725
00726
00727 case R_FR30_GNU_VTENTRY:
00728 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
00729 return FALSE;
00730 break;
00731 }
00732 }
00733
00734 return TRUE;
00735 }
00736
00737 #define ELF_ARCH bfd_arch_fr30
00738 #define ELF_MACHINE_CODE EM_FR30
00739 #define ELF_MACHINE_ALT1 EM_CYGNUS_FR30
00740 #define ELF_MAXPAGESIZE 0x1000
00741
00742 #define TARGET_BIG_SYM bfd_elf32_fr30_vec
00743 #define TARGET_BIG_NAME "elf32-fr30"
00744
00745 #define elf_info_to_howto_rel NULL
00746 #define elf_info_to_howto fr30_info_to_howto_rela
00747 #define elf_backend_relocate_section fr30_elf_relocate_section
00748 #define elf_backend_gc_mark_hook fr30_elf_gc_mark_hook
00749 #define elf_backend_gc_sweep_hook fr30_elf_gc_sweep_hook
00750 #define elf_backend_check_relocs fr30_elf_check_relocs
00751
00752 #define elf_backend_can_gc_sections 1
00753 #define elf_backend_rela_normal 1
00754
00755 #define bfd_elf32_bfd_reloc_type_lookup fr30_reloc_type_lookup
00756
00757 #include "elf32-target.h"