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/openrisc.h"
00030 #include "libiberty.h"
00031
00032
00033
00034 static reloc_howto_type *openrisc_reloc_type_lookup
00035 PARAMS ((bfd * , bfd_reloc_code_real_type));
00036 static void openrisc_info_to_howto_rela
00037 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
00038 static bfd_boolean openrisc_elf_relocate_section
00039 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00040 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
00041 static bfd_reloc_status_type openrisc_final_link_relocate
00042 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
00043 Elf_Internal_Rela *, bfd_vma));
00044 static bfd_boolean openrisc_elf_gc_sweep_hook
00045 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00046 const Elf_Internal_Rela *));
00047 static asection * openrisc_elf_gc_mark_hook
00048 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
00049 struct elf_link_hash_entry *, Elf_Internal_Sym *));
00050 static bfd_boolean openrisc_elf_check_relocs
00051 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00052 const Elf_Internal_Rela *));
00053 static bfd_boolean openrisc_elf_object_p
00054 PARAMS ((bfd *));
00055 static void openrisc_elf_final_write_processing
00056 PARAMS ((bfd *, bfd_boolean));
00057
00058
00059 static reloc_howto_type openrisc_elf_howto_table[] =
00060 {
00061
00062 HOWTO (R_OPENRISC_NONE,
00063 0,
00064 2,
00065 32,
00066 FALSE,
00067 0,
00068 complain_overflow_bitfield,
00069 bfd_elf_generic_reloc,
00070 "R_OPENRISC_NONE",
00071 FALSE,
00072 0,
00073 0,
00074 FALSE),
00075
00076
00077 HOWTO (R_OPENRISC_INSN_REL_26,
00078 2,
00079 2,
00080 26,
00081 TRUE,
00082 0,
00083 complain_overflow_signed,
00084 bfd_elf_generic_reloc,
00085 "R_OPENRISC_INSN_REL_26",
00086 FALSE,
00087 0x00000000,
00088 0x03ffffff,
00089 FALSE),
00090
00091
00092 HOWTO (R_OPENRISC_INSN_ABS_26,
00093 2,
00094 2,
00095 26,
00096 FALSE,
00097 0,
00098 complain_overflow_signed,
00099 bfd_elf_generic_reloc,
00100 "R_OPENRISC_INSN_ABS_26",
00101 FALSE,
00102 0x00000000,
00103 0x03ffffff,
00104 FALSE),
00105
00106 HOWTO (R_OPENRISC_LO_16_IN_INSN,
00107 0,
00108 1,
00109 16,
00110 FALSE,
00111 0,
00112 complain_overflow_dont,
00113 bfd_elf_generic_reloc,
00114 "R_OPENRISC_LO_16_IN_INSN",
00115 FALSE,
00116 0,
00117 0x0000ffff,
00118 FALSE),
00119
00120 HOWTO (R_OPENRISC_HI_16_IN_INSN,
00121 16,
00122 1,
00123 16,
00124 FALSE,
00125 0,
00126 complain_overflow_dont,
00127 bfd_elf_generic_reloc,
00128 "R_OPENRISC_HI_16_IN_INSN",
00129 FALSE,
00130 0,
00131 0x0000ffff,
00132 FALSE),
00133
00134
00135 HOWTO (R_OPENRISC_8,
00136 0,
00137 0,
00138 8,
00139 FALSE,
00140 0,
00141 complain_overflow_bitfield,
00142 bfd_elf_generic_reloc,
00143 "R_OPENRISC_8",
00144 TRUE,
00145 0x0000,
00146 0x00ff,
00147 FALSE),
00148
00149
00150 HOWTO (R_OPENRISC_16,
00151 0,
00152 1,
00153 16,
00154 FALSE,
00155 0,
00156 complain_overflow_bitfield,
00157 bfd_elf_generic_reloc,
00158 "R_OPENRISC_16",
00159 TRUE,
00160 0x00000000,
00161 0x0000ffff,
00162 FALSE),
00163
00164
00165 HOWTO (R_OPENRISC_32,
00166 0,
00167 2,
00168 32,
00169 FALSE,
00170 0,
00171 complain_overflow_bitfield,
00172 bfd_elf_generic_reloc,
00173 "R_OPENRISC_32",
00174 TRUE,
00175 0x00000000,
00176 0xffffffff,
00177 FALSE),
00178
00179
00180 HOWTO (R_OPENRISC_GNU_VTINHERIT,
00181 0,
00182 2,
00183 0,
00184 FALSE,
00185 0,
00186 complain_overflow_dont,
00187 NULL,
00188 "R_OPENRISC_GNU_VTINHERIT",
00189 FALSE,
00190 0,
00191 0,
00192 FALSE),
00193
00194
00195 HOWTO (R_OPENRISC_GNU_VTENTRY,
00196 0,
00197 2,
00198 0,
00199 FALSE,
00200 0,
00201 complain_overflow_dont,
00202 _bfd_elf_rel_vtable_reloc_fn,
00203 "R_OPENRISC_GNU_VTENTRY",
00204 FALSE,
00205 0,
00206 0,
00207 FALSE),
00208 };
00209
00210
00211
00212 struct openrisc_reloc_map
00213 {
00214 bfd_reloc_code_real_type bfd_reloc_val;
00215 unsigned int openrisc_reloc_val;
00216 };
00217
00218 static const struct openrisc_reloc_map openrisc_reloc_map[] =
00219 {
00220 { BFD_RELOC_NONE, R_OPENRISC_NONE },
00221 { BFD_RELOC_32, R_OPENRISC_32 },
00222 { BFD_RELOC_16, R_OPENRISC_16 },
00223 { BFD_RELOC_8, R_OPENRISC_8 },
00224 { BFD_RELOC_OPENRISC_REL_26,R_OPENRISC_INSN_REL_26 },
00225 { BFD_RELOC_OPENRISC_ABS_26,R_OPENRISC_INSN_ABS_26 },
00226 { BFD_RELOC_HI16, R_OPENRISC_HI_16_IN_INSN },
00227 { BFD_RELOC_LO16, R_OPENRISC_LO_16_IN_INSN },
00228 { BFD_RELOC_VTABLE_INHERIT, R_OPENRISC_GNU_VTINHERIT },
00229 { BFD_RELOC_VTABLE_ENTRY, R_OPENRISC_GNU_VTENTRY }
00230 };
00231
00232 static reloc_howto_type *
00233 openrisc_reloc_type_lookup (abfd, code)
00234 bfd * abfd ATTRIBUTE_UNUSED;
00235 bfd_reloc_code_real_type code;
00236 {
00237 unsigned int i;
00238
00239 for (i = ARRAY_SIZE (openrisc_reloc_map); --i;)
00240 if (openrisc_reloc_map[i].bfd_reloc_val == code)
00241 return & openrisc_elf_howto_table[openrisc_reloc_map[i].
00242 openrisc_reloc_val];
00243
00244 return NULL;
00245 }
00246
00247
00248
00249 static void
00250 openrisc_info_to_howto_rela (abfd, cache_ptr, dst)
00251 bfd * abfd ATTRIBUTE_UNUSED;
00252 arelent * cache_ptr;
00253 Elf_Internal_Rela * dst;
00254 {
00255 unsigned int r_type;
00256
00257 r_type = ELF32_R_TYPE (dst->r_info);
00258 BFD_ASSERT (r_type < (unsigned int) R_OPENRISC_max);
00259 cache_ptr->howto = & openrisc_elf_howto_table[r_type];
00260 }
00261
00262
00263
00264
00265 static bfd_reloc_status_type
00266 openrisc_final_link_relocate (howto, input_bfd, input_section, contents, rel,
00267 relocation)
00268 reloc_howto_type *howto;
00269 bfd *input_bfd;
00270 asection *input_section;
00271 bfd_byte *contents;
00272 Elf_Internal_Rela *rel;
00273 bfd_vma relocation;
00274 {
00275 bfd_reloc_status_type r = bfd_reloc_ok;
00276
00277 switch (howto->type)
00278 {
00279 case R_OPENRISC_LO_16_IN_INSN:
00280 relocation &= 0xffff;
00281 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
00282 contents, rel->r_offset,
00283 relocation, rel->r_addend);
00284 break;
00285
00286 default:
00287 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
00288 contents, rel->r_offset,
00289 relocation, rel->r_addend);
00290 }
00291
00292 return r;
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 static bfd_boolean
00326 openrisc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
00327 contents, relocs, local_syms, local_sections)
00328 bfd *output_bfd;
00329 struct bfd_link_info *info;
00330 bfd *input_bfd;
00331 asection *input_section;
00332 bfd_byte *contents;
00333 Elf_Internal_Rela *relocs;
00334 Elf_Internal_Sym *local_syms;
00335 asection **local_sections;
00336 {
00337 Elf_Internal_Shdr *symtab_hdr;
00338 struct elf_link_hash_entry **sym_hashes;
00339 Elf_Internal_Rela *rel;
00340 Elf_Internal_Rela *relend;
00341
00342 if (info->relocatable)
00343 return TRUE;
00344
00345 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
00346 sym_hashes = elf_sym_hashes (input_bfd);
00347 relend = relocs + input_section->reloc_count;
00348
00349 for (rel = relocs; rel < relend; rel++)
00350 {
00351 reloc_howto_type *howto;
00352 unsigned long r_symndx;
00353 Elf_Internal_Sym *sym;
00354 asection *sec;
00355 struct elf_link_hash_entry *h;
00356 bfd_vma relocation;
00357 bfd_reloc_status_type r;
00358 const char *name = NULL;
00359 int r_type;
00360
00361 r_type = ELF32_R_TYPE (rel->r_info);
00362 r_symndx = ELF32_R_SYM (rel->r_info);
00363
00364 if (r_type == R_OPENRISC_GNU_VTINHERIT
00365 || r_type == R_OPENRISC_GNU_VTENTRY)
00366 continue;
00367
00368 if ((unsigned int) r_type >
00369 (sizeof openrisc_elf_howto_table / sizeof (reloc_howto_type)))
00370 abort ();
00371
00372
00373 howto = openrisc_elf_howto_table + ELF32_R_TYPE (rel->r_info);
00374 h = NULL;
00375 sym = NULL;
00376 sec = NULL;
00377
00378 if (r_symndx < symtab_hdr->sh_info)
00379 {
00380 sym = local_syms + r_symndx;
00381 sec = local_sections[r_symndx];
00382 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
00383
00384 name = bfd_elf_string_from_elf_section
00385 (input_bfd, symtab_hdr->sh_link, sym->st_name);
00386 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
00387 }
00388 else
00389 {
00390 bfd_boolean unresolved_reloc, warned;
00391
00392 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
00393 r_symndx, symtab_hdr, sym_hashes,
00394 h, sec, relocation,
00395 unresolved_reloc, warned);
00396 }
00397
00398 r = openrisc_final_link_relocate (howto, input_bfd, input_section,
00399 contents, rel, relocation);
00400
00401 if (r != bfd_reloc_ok)
00402 {
00403 const char *msg = (const char *) NULL;
00404
00405 switch (r)
00406 {
00407 case bfd_reloc_overflow:
00408 r = info->callbacks->reloc_overflow
00409 (info, (h ? &h->root : NULL), name, howto->name,
00410 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
00411 break;
00412
00413 case bfd_reloc_undefined:
00414 r = info->callbacks->undefined_symbol
00415 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
00416 break;
00417
00418 case bfd_reloc_outofrange:
00419 msg = _("internal error: out of range error");
00420 break;
00421
00422 case bfd_reloc_notsupported:
00423 msg = _("internal error: unsupported relocation error");
00424 break;
00425
00426 case bfd_reloc_dangerous:
00427 msg = _("internal error: dangerous relocation");
00428 break;
00429
00430 default:
00431 msg = _("internal error: unknown error");
00432 break;
00433 }
00434
00435 if (msg)
00436 r = info->callbacks->warning
00437 (info, msg, name, input_bfd, input_section, rel->r_offset);
00438
00439 if (!r)
00440 return FALSE;
00441 }
00442 }
00443
00444 return TRUE;
00445 }
00446
00447
00448
00449
00450 static asection *
00451 openrisc_elf_gc_mark_hook (sec, info, rel, h, sym)
00452 asection *sec;
00453 struct bfd_link_info *info ATTRIBUTE_UNUSED;
00454 Elf_Internal_Rela *rel;
00455 struct elf_link_hash_entry *h;
00456 Elf_Internal_Sym *sym;
00457 {
00458 if (h != NULL)
00459 {
00460 switch (ELF32_R_TYPE (rel->r_info))
00461 {
00462 case R_OPENRISC_GNU_VTINHERIT:
00463 case R_OPENRISC_GNU_VTENTRY:
00464 break;
00465
00466 default:
00467 switch (h->root.type)
00468 {
00469 case bfd_link_hash_defined:
00470 case bfd_link_hash_defweak:
00471 return h->root.u.def.section;
00472
00473 case bfd_link_hash_common:
00474 return h->root.u.c.p->section;
00475
00476 default:
00477 break;
00478 }
00479 }
00480 }
00481 else
00482 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
00483
00484 return NULL;
00485 }
00486
00487
00488
00489 static bfd_boolean
00490 openrisc_elf_gc_sweep_hook (abfd, info, sec, relocs)
00491 bfd *abfd ATTRIBUTE_UNUSED;
00492 struct bfd_link_info *info ATTRIBUTE_UNUSED;
00493 asection *sec ATTRIBUTE_UNUSED;
00494 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
00495 {
00496 return TRUE;
00497 }
00498
00499
00500
00501
00502
00503 static bfd_boolean
00504 openrisc_elf_check_relocs (abfd, info, sec, relocs)
00505 bfd *abfd;
00506 struct bfd_link_info *info;
00507 asection *sec;
00508 const Elf_Internal_Rela *relocs;
00509 {
00510 Elf_Internal_Shdr *symtab_hdr;
00511 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
00512 const Elf_Internal_Rela *rel;
00513 const Elf_Internal_Rela *rel_end;
00514
00515 if (info->relocatable)
00516 return TRUE;
00517
00518 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00519 sym_hashes = elf_sym_hashes (abfd);
00520 sym_hashes_end =
00521 sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
00522 if (!elf_bad_symtab (abfd))
00523 sym_hashes_end -= symtab_hdr->sh_info;
00524
00525 rel_end = relocs + sec->reloc_count;
00526 for (rel = relocs; rel < rel_end; rel++)
00527 {
00528 struct elf_link_hash_entry *h;
00529 unsigned long r_symndx;
00530
00531 r_symndx = ELF32_R_SYM (rel->r_info);
00532 if (r_symndx < symtab_hdr->sh_info)
00533 h = NULL;
00534 else
00535 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
00536
00537 switch (ELF32_R_TYPE (rel->r_info))
00538 {
00539
00540
00541 case R_OPENRISC_GNU_VTINHERIT:
00542 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
00543 return FALSE;
00544 break;
00545
00546
00547
00548 case R_OPENRISC_GNU_VTENTRY:
00549 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
00550 return FALSE;
00551 break;
00552 }
00553 }
00554
00555 return TRUE;
00556 }
00557
00558
00559
00560 static bfd_boolean
00561 openrisc_elf_object_p (abfd)
00562 bfd *abfd;
00563 {
00564 switch (elf_elfheader (abfd)->e_flags & 0xf)
00565 {
00566 default:
00567 (void) bfd_default_set_arch_mach (abfd, bfd_arch_openrisc, 0);
00568 break;
00569 }
00570 return TRUE;
00571 }
00572
00573
00574
00575 static void
00576 openrisc_elf_final_write_processing (abfd, linker)
00577 bfd *abfd;
00578 bfd_boolean linker ATTRIBUTE_UNUSED;
00579 {
00580 unsigned long val;
00581
00582 switch (bfd_get_mach (abfd))
00583 {
00584 default:
00585 val = 0;
00586 break;
00587 }
00588
00589 elf_elfheader (abfd)->e_flags &= ~0xf;
00590 elf_elfheader (abfd)->e_flags |= val;
00591 }
00592
00593
00594 #define ELF_ARCH bfd_arch_openrisc
00595 #define ELF_MACHINE_CODE EM_OPENRISC
00596 #define ELF_MACHINE_ALT1 EM_OPENRISC_OLD
00597 #define ELF_MAXPAGESIZE 0x1000
00598
00599 #define TARGET_BIG_SYM bfd_elf32_openrisc_vec
00600 #define TARGET_BIG_NAME "elf32-openrisc"
00601
00602 #define elf_info_to_howto_rel NULL
00603 #define elf_info_to_howto openrisc_info_to_howto_rela
00604 #define elf_backend_relocate_section openrisc_elf_relocate_section
00605 #define elf_backend_gc_mark_hook openrisc_elf_gc_mark_hook
00606 #define elf_backend_gc_sweep_hook openrisc_elf_gc_sweep_hook
00607 #define elf_backend_check_relocs openrisc_elf_check_relocs
00608
00609 #define elf_backend_can_gc_sections 1
00610 #define elf_backend_rela_normal 1
00611
00612 #define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
00613
00614 #define elf_backend_object_p openrisc_elf_object_p
00615 #define elf_backend_final_write_processing openrisc_elf_final_write_processing
00616
00617 #include "elf32-target.h"