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