00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "bfd.h"
00025 #include "sysdep.h"
00026 #include "libbfd.h"
00027 #include "elf-bfd.h"
00028 #include "elf/xstormy16.h"
00029 #include "libiberty.h"
00030
00031
00032 static reloc_howto_type * xstormy16_reloc_type_lookup
00033 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
00034 static void xstormy16_info_to_howto_rela
00035 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
00036 static bfd_reloc_status_type xstormy16_elf_24_reloc
00037 PARAMS ((bfd *abfd, arelent *reloc_entry, asymbol *symbol,
00038 PTR data, asection *input_section, bfd *output_bfd,
00039 char **error_message));
00040 static bfd_boolean xstormy16_elf_check_relocs
00041 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00042 const Elf_Internal_Rela *));
00043 static bfd_boolean xstormy16_relax_plt_check
00044 PARAMS ((struct elf_link_hash_entry *, PTR));
00045 static bfd_boolean xstormy16_relax_plt_realloc
00046 PARAMS ((struct elf_link_hash_entry *, PTR));
00047 static bfd_boolean xstormy16_elf_relax_section
00048 PARAMS ((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
00049 bfd_boolean *again));
00050 static bfd_boolean xstormy16_elf_always_size_sections
00051 PARAMS ((bfd *, struct bfd_link_info *));
00052 static bfd_boolean xstormy16_elf_relocate_section
00053 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00054 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
00055 static bfd_boolean xstormy16_elf_finish_dynamic_sections
00056 PARAMS((bfd *, struct bfd_link_info *));
00057 static bfd_boolean xstormy16_elf_gc_sweep_hook
00058 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00059 const Elf_Internal_Rela *));
00060 static asection * xstormy16_elf_gc_mark_hook
00061 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
00062 struct elf_link_hash_entry *, Elf_Internal_Sym *));
00063
00064 static reloc_howto_type xstormy16_elf_howto_table [] =
00065 {
00066
00067 HOWTO (R_XSTORMY16_NONE,
00068 0,
00069 2,
00070 32,
00071 FALSE,
00072 0,
00073 complain_overflow_bitfield,
00074 bfd_elf_generic_reloc,
00075 "R_XSTORMY16_NONE",
00076 FALSE,
00077 0,
00078 0,
00079 FALSE),
00080
00081
00082 HOWTO (R_XSTORMY16_32,
00083 0,
00084 2,
00085 32,
00086 FALSE,
00087 0,
00088 complain_overflow_dont,
00089 bfd_elf_generic_reloc,
00090 "R_XSTORMY16_32",
00091 FALSE,
00092 0,
00093 0xffffffff,
00094 FALSE),
00095
00096
00097 HOWTO (R_XSTORMY16_16,
00098 0,
00099 1,
00100 16,
00101 FALSE,
00102 0,
00103 complain_overflow_bitfield,
00104 bfd_elf_generic_reloc,
00105 "R_XSTORMY16_16",
00106 FALSE,
00107 0,
00108 0xffff,
00109 FALSE),
00110
00111
00112 HOWTO (R_XSTORMY16_8,
00113 0,
00114 0,
00115 8,
00116 FALSE,
00117 0,
00118 complain_overflow_unsigned,
00119 bfd_elf_generic_reloc,
00120 "R_XSTORMY16_8",
00121 FALSE,
00122 0,
00123 0xff,
00124 FALSE),
00125
00126
00127 HOWTO (R_XSTORMY16_PC32,
00128 0,
00129 2,
00130 32,
00131 TRUE,
00132 0,
00133 complain_overflow_dont,
00134 bfd_elf_generic_reloc,
00135 "R_XSTORMY16_PC32",
00136 FALSE,
00137 0,
00138 0xffffffff,
00139 TRUE),
00140
00141
00142 HOWTO (R_XSTORMY16_PC16,
00143 0,
00144 1,
00145 16,
00146 TRUE,
00147 0,
00148 complain_overflow_signed,
00149 bfd_elf_generic_reloc,
00150 "R_XSTORMY16_PC16",
00151 FALSE,
00152 0,
00153 0xffffffff,
00154 TRUE),
00155
00156
00157 HOWTO (R_XSTORMY16_PC8,
00158 0,
00159 0,
00160 8,
00161 TRUE,
00162 0,
00163 complain_overflow_signed,
00164 bfd_elf_generic_reloc,
00165 "R_XSTORMY16_PC8",
00166 FALSE,
00167 0,
00168 0xffffffff,
00169 TRUE),
00170
00171
00172 HOWTO (R_XSTORMY16_REL_12,
00173 1,
00174 1,
00175 11,
00176 TRUE,
00177 1,
00178 complain_overflow_signed,
00179 bfd_elf_generic_reloc,
00180 "R_XSTORMY16_REL_12",
00181 FALSE,
00182 0,
00183 0x0ffe,
00184 TRUE),
00185
00186
00187 HOWTO (R_XSTORMY16_24,
00188 0,
00189 2,
00190 24,
00191 FALSE,
00192 0,
00193 complain_overflow_unsigned,
00194 xstormy16_elf_24_reloc,
00195 "R_XSTORMY16_24",
00196 TRUE,
00197 0,
00198 0xffff00ff,
00199 TRUE),
00200
00201
00202 HOWTO (R_XSTORMY16_FPTR16,
00203 0,
00204 1,
00205 16,
00206 FALSE,
00207 0,
00208 complain_overflow_bitfield,
00209 bfd_elf_generic_reloc,
00210 "R_XSTORMY16_FPTR16",
00211 FALSE,
00212 0,
00213 0xffffffff,
00214 FALSE),
00215
00216
00217 HOWTO (R_XSTORMY16_LO16,
00218 0,
00219 1,
00220 16,
00221 FALSE,
00222 0,
00223 complain_overflow_dont,
00224 bfd_elf_generic_reloc,
00225 "R_XSTORMY16_LO16",
00226 FALSE,
00227 0,
00228 0xffff,
00229 FALSE),
00230
00231
00232 HOWTO (R_XSTORMY16_HI16,
00233 16,
00234 1,
00235 16,
00236 FALSE,
00237 0,
00238 complain_overflow_dont,
00239 bfd_elf_generic_reloc,
00240 "R_XSTORMY16_HI16",
00241 FALSE,
00242 0,
00243 0xffff,
00244 FALSE),
00245
00246
00247 HOWTO (R_XSTORMY16_12,
00248 0,
00249 1,
00250 12,
00251 FALSE,
00252 0,
00253 complain_overflow_signed,
00254 bfd_elf_generic_reloc,
00255 "R_XSTORMY16_12",
00256 FALSE,
00257 0x0000,
00258 0x0fff,
00259 FALSE),
00260 };
00261
00262 static reloc_howto_type xstormy16_elf_howto_table2 [] =
00263 {
00264
00265 HOWTO (R_XSTORMY16_GNU_VTINHERIT,
00266 0,
00267 2,
00268 0,
00269 FALSE,
00270 0,
00271 complain_overflow_dont,
00272 NULL,
00273 "R_XSTORMY16_GNU_VTINHERIT",
00274 FALSE,
00275 0,
00276 0,
00277 FALSE),
00278
00279
00280 HOWTO (R_XSTORMY16_GNU_VTENTRY,
00281 0,
00282 2,
00283 0,
00284 FALSE,
00285 0,
00286 complain_overflow_dont,
00287 _bfd_elf_rel_vtable_reloc_fn,
00288 "R_XSTORMY16_GNU_VTENTRY",
00289 FALSE,
00290 0,
00291 0,
00292 FALSE),
00293
00294 };
00295
00296
00297
00298 typedef struct xstormy16_reloc_map
00299 {
00300 bfd_reloc_code_real_type bfd_reloc_val;
00301 unsigned int xstormy16_reloc_val;
00302 reloc_howto_type * table;
00303 } reloc_map;
00304
00305 static const reloc_map xstormy16_reloc_map [] =
00306 {
00307 { BFD_RELOC_NONE, R_XSTORMY16_NONE, xstormy16_elf_howto_table },
00308 { BFD_RELOC_32, R_XSTORMY16_32, xstormy16_elf_howto_table },
00309 { BFD_RELOC_16, R_XSTORMY16_16, xstormy16_elf_howto_table },
00310 { BFD_RELOC_8, R_XSTORMY16_8, xstormy16_elf_howto_table },
00311 { BFD_RELOC_32_PCREL, R_XSTORMY16_PC32, xstormy16_elf_howto_table },
00312 { BFD_RELOC_16_PCREL, R_XSTORMY16_PC16, xstormy16_elf_howto_table },
00313 { BFD_RELOC_8_PCREL, R_XSTORMY16_PC8, xstormy16_elf_howto_table },
00314 { BFD_RELOC_XSTORMY16_REL_12, R_XSTORMY16_REL_12, xstormy16_elf_howto_table },
00315 { BFD_RELOC_XSTORMY16_24, R_XSTORMY16_24, xstormy16_elf_howto_table },
00316 { BFD_RELOC_XSTORMY16_FPTR16, R_XSTORMY16_FPTR16, xstormy16_elf_howto_table },
00317 { BFD_RELOC_LO16, R_XSTORMY16_LO16, xstormy16_elf_howto_table },
00318 { BFD_RELOC_HI16, R_XSTORMY16_HI16, xstormy16_elf_howto_table },
00319 { BFD_RELOC_XSTORMY16_12, R_XSTORMY16_12, xstormy16_elf_howto_table },
00320 { BFD_RELOC_VTABLE_INHERIT, R_XSTORMY16_GNU_VTINHERIT, xstormy16_elf_howto_table2 },
00321 { BFD_RELOC_VTABLE_ENTRY, R_XSTORMY16_GNU_VTENTRY, xstormy16_elf_howto_table2 },
00322 };
00323
00324 static reloc_howto_type *
00325 xstormy16_reloc_type_lookup (abfd, code)
00326 bfd * abfd ATTRIBUTE_UNUSED;
00327 bfd_reloc_code_real_type code;
00328 {
00329 unsigned int i;
00330
00331 for (i = ARRAY_SIZE (xstormy16_reloc_map); --i;)
00332 {
00333 const reloc_map * entry;
00334
00335 entry = xstormy16_reloc_map + i;
00336
00337 if (entry->bfd_reloc_val == code)
00338 return entry->table + (entry->xstormy16_reloc_val
00339 - entry->table[0].type);
00340 }
00341
00342 return NULL;
00343 }
00344
00345
00346
00347 static void
00348 xstormy16_info_to_howto_rela (abfd, cache_ptr, dst)
00349 bfd * abfd ATTRIBUTE_UNUSED;
00350 arelent * cache_ptr;
00351 Elf_Internal_Rela * dst;
00352 {
00353 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
00354
00355 if (r_type <= (unsigned int) R_XSTORMY16_12)
00356 cache_ptr->howto = &xstormy16_elf_howto_table [r_type];
00357 else if (r_type - R_XSTORMY16_GNU_VTINHERIT
00358 <= (unsigned int) R_XSTORMY16_GNU_VTENTRY)
00359 cache_ptr->howto
00360 = &xstormy16_elf_howto_table2 [r_type - R_XSTORMY16_GNU_VTINHERIT];
00361 else
00362 abort ();
00363 }
00364
00365
00366
00367 static bfd_reloc_status_type
00368 xstormy16_elf_24_reloc (abfd, reloc_entry, symbol, data, input_section,
00369 output_bfd, error_message)
00370 bfd *abfd;
00371 arelent *reloc_entry;
00372 asymbol *symbol;
00373 PTR data;
00374 asection *input_section;
00375 bfd *output_bfd;
00376 char **error_message ATTRIBUTE_UNUSED;
00377 {
00378 bfd_vma relocation, x;
00379
00380 if (output_bfd != NULL)
00381 {
00382 reloc_entry->address += input_section->output_offset;
00383 return bfd_reloc_ok;
00384 }
00385
00386 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
00387 return bfd_reloc_outofrange;
00388
00389 if (bfd_is_com_section (symbol->section))
00390 relocation = 0;
00391 else
00392 relocation = symbol->value;
00393
00394 relocation += symbol->section->output_section->vma;
00395 relocation += symbol->section->output_offset;
00396 relocation += reloc_entry->addend;
00397
00398 x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
00399 x &= 0x0000ff00;
00400 x |= relocation & 0xff;
00401 x |= (relocation << 8) & 0xffff0000;
00402 bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address);
00403
00404 if (relocation & ~ (bfd_vma) 0xffffff)
00405 return bfd_reloc_overflow;
00406
00407 return bfd_reloc_ok;
00408 }
00409
00410
00411
00412
00413
00414
00415
00416 static bfd_boolean
00417 xstormy16_elf_check_relocs (abfd, info, sec, relocs)
00418 bfd *abfd;
00419 struct bfd_link_info *info;
00420 asection *sec;
00421 const Elf_Internal_Rela *relocs;
00422 {
00423 const Elf_Internal_Rela *rel, *relend;
00424 struct elf_link_hash_entry **sym_hashes;
00425 Elf_Internal_Shdr *symtab_hdr;
00426 bfd_vma *local_plt_offsets;
00427 asection *splt;
00428 bfd *dynobj;
00429
00430 if (info->relocatable)
00431 return TRUE;
00432
00433 symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
00434 sym_hashes = elf_sym_hashes (abfd);
00435 local_plt_offsets = elf_local_got_offsets (abfd);
00436 splt = NULL;
00437 dynobj = elf_hash_table(info)->dynobj;
00438
00439 relend = relocs + sec->reloc_count;
00440 for (rel = relocs; rel < relend; ++rel)
00441 {
00442 unsigned long r_symndx;
00443 struct elf_link_hash_entry *h;
00444 bfd_vma *offset;
00445
00446 r_symndx = ELF32_R_SYM (rel->r_info);
00447 if (r_symndx < symtab_hdr->sh_info)
00448 h = NULL;
00449 else
00450 {
00451 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
00452 while (h->root.type == bfd_link_hash_indirect
00453 || h->root.type == bfd_link_hash_warning)
00454 h = (struct elf_link_hash_entry *) h->root.u.i.link;
00455 }
00456
00457 switch (ELF32_R_TYPE (rel->r_info))
00458 {
00459
00460
00461
00462 case R_XSTORMY16_FPTR16:
00463 if (rel->r_addend != 0)
00464 {
00465 (*info->callbacks->warning)
00466 (info, _("non-zero addend in @fptr reloc"), 0,
00467 abfd, 0, 0);
00468 }
00469
00470 if (dynobj == NULL)
00471 elf_hash_table (info)->dynobj = dynobj = abfd;
00472 if (splt == NULL)
00473 {
00474 splt = bfd_get_section_by_name (dynobj, ".plt");
00475 if (splt == NULL)
00476 {
00477 splt = bfd_make_section (dynobj, ".plt");
00478 if (splt == NULL
00479 || ! bfd_set_section_flags (dynobj, splt,
00480 (SEC_ALLOC
00481 | SEC_LOAD
00482 | SEC_HAS_CONTENTS
00483 | SEC_IN_MEMORY
00484 | SEC_LINKER_CREATED
00485 | SEC_READONLY
00486 | SEC_CODE))
00487 || ! bfd_set_section_alignment (dynobj, splt, 1))
00488 return FALSE;
00489 }
00490 }
00491
00492 if (h != NULL)
00493 offset = &h->plt.offset;
00494 else
00495 {
00496 if (local_plt_offsets == NULL)
00497 {
00498 size_t size;
00499 unsigned int i;
00500
00501 size = symtab_hdr->sh_info * sizeof (bfd_vma);
00502 local_plt_offsets = (bfd_vma *) bfd_alloc (abfd, size);
00503 if (local_plt_offsets == NULL)
00504 return FALSE;
00505 elf_local_got_offsets (abfd) = local_plt_offsets;
00506
00507 for (i = 0; i < symtab_hdr->sh_info; i++)
00508 local_plt_offsets[i] = (bfd_vma) -1;
00509 }
00510 offset = &local_plt_offsets[r_symndx];
00511 }
00512
00513 if (*offset == (bfd_vma) -1)
00514 {
00515 *offset = splt->size;
00516 splt->size += 4;
00517 }
00518 break;
00519
00520
00521
00522 case R_XSTORMY16_GNU_VTINHERIT:
00523 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
00524 return FALSE;
00525 break;
00526
00527
00528
00529 case R_XSTORMY16_GNU_VTENTRY:
00530 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
00531 return FALSE;
00532 break;
00533 }
00534 }
00535
00536 return TRUE;
00537 }
00538
00539
00540
00541
00542 struct relax_plt_data
00543 {
00544 asection *splt;
00545 bfd_boolean *again;
00546 };
00547
00548 static bfd_boolean
00549 xstormy16_relax_plt_check (h, xdata)
00550 struct elf_link_hash_entry *h;
00551 PTR xdata;
00552 {
00553 struct relax_plt_data *data = (struct relax_plt_data *) xdata;
00554
00555 if (h->root.type == bfd_link_hash_warning)
00556 h = (struct elf_link_hash_entry *) h->root.u.i.link;
00557
00558 if (h->plt.offset != (bfd_vma) -1)
00559 {
00560 bfd_vma address;
00561
00562 if (h->root.type == bfd_link_hash_undefined
00563 || h->root.type == bfd_link_hash_undefweak)
00564 address = 0;
00565 else
00566 address = (h->root.u.def.section->output_section->vma
00567 + h->root.u.def.section->output_offset
00568 + h->root.u.def.value);
00569
00570 if (address <= 0xffff)
00571 {
00572 h->plt.offset = -1;
00573 data->splt->size -= 4;
00574 *data->again = TRUE;
00575 }
00576 }
00577
00578 return TRUE;
00579 }
00580
00581
00582
00583
00584 static bfd_boolean
00585 xstormy16_relax_plt_realloc (h, xdata)
00586 struct elf_link_hash_entry *h;
00587 PTR xdata;
00588 {
00589 bfd_vma *entry = (bfd_vma *) xdata;
00590
00591 if (h->root.type == bfd_link_hash_warning)
00592 h = (struct elf_link_hash_entry *) h->root.u.i.link;
00593
00594 if (h->plt.offset != (bfd_vma) -1)
00595 {
00596 h->plt.offset = *entry;
00597 *entry += 4;
00598 }
00599
00600 return TRUE;
00601 }
00602
00603 static bfd_boolean
00604 xstormy16_elf_relax_section (dynobj, splt, info, again)
00605 bfd *dynobj;
00606 asection *splt;
00607 struct bfd_link_info *info;
00608 bfd_boolean *again;
00609 {
00610 struct relax_plt_data relax_plt_data;
00611 bfd *ibfd;
00612
00613
00614 *again = FALSE;
00615
00616 if (info->relocatable)
00617 return TRUE;
00618
00619
00620 if (dynobj != elf_hash_table (info)->dynobj
00621 || strcmp (splt->name, ".plt") != 0)
00622 return TRUE;
00623
00624
00625 if (splt->size == 0)
00626 return TRUE;
00627
00628
00629
00630 relax_plt_data.splt = splt;
00631 relax_plt_data.again = again;
00632 elf_link_hash_traverse (elf_hash_table (info), xstormy16_relax_plt_check,
00633 &relax_plt_data);
00634
00635
00636
00637 for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
00638 {
00639 bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
00640 Elf_Internal_Shdr *symtab_hdr;
00641 Elf_Internal_Sym *isymbuf = NULL;
00642 unsigned int idx;
00643
00644 if (! local_plt_offsets)
00645 continue;
00646
00647 symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
00648 if (symtab_hdr->sh_info != 0)
00649 {
00650 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
00651 if (isymbuf == NULL)
00652 isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
00653 symtab_hdr->sh_info, 0,
00654 NULL, NULL, NULL);
00655 if (isymbuf == NULL)
00656 return FALSE;
00657 }
00658
00659 for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
00660 {
00661 Elf_Internal_Sym *isym;
00662 asection *tsec;
00663 bfd_vma address;
00664
00665 if (local_plt_offsets[idx] == (bfd_vma) -1)
00666 continue;
00667
00668 isym = &isymbuf[idx];
00669 if (isym->st_shndx == SHN_UNDEF)
00670 continue;
00671 else if (isym->st_shndx == SHN_ABS)
00672 tsec = bfd_abs_section_ptr;
00673 else if (isym->st_shndx == SHN_COMMON)
00674 tsec = bfd_com_section_ptr;
00675 else
00676 tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx);
00677
00678 address = (tsec->output_section->vma
00679 + tsec->output_offset
00680 + isym->st_value);
00681 if (address <= 0xffff)
00682 {
00683 local_plt_offsets[idx] = -1;
00684 splt->size -= 4;
00685 *again = TRUE;
00686 }
00687 }
00688
00689 if (isymbuf != NULL
00690 && symtab_hdr->contents != (unsigned char *) isymbuf)
00691 {
00692 if (! info->keep_memory)
00693 free (isymbuf);
00694 else
00695 {
00696
00697 symtab_hdr->contents = (unsigned char *) isymbuf;
00698 }
00699 }
00700 }
00701
00702
00703
00704 if (*again && splt->size > 0)
00705 {
00706 bfd_vma entry = 0;
00707
00708 elf_link_hash_traverse (elf_hash_table (info),
00709 xstormy16_relax_plt_realloc, &entry);
00710
00711 for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
00712 {
00713 bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
00714 unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info;
00715 unsigned int idx;
00716
00717 if (! local_plt_offsets)
00718 continue;
00719
00720 for (idx = 0; idx < nlocals; ++idx)
00721 if (local_plt_offsets[idx] != (bfd_vma) -1)
00722 {
00723 local_plt_offsets[idx] = entry;
00724 entry += 4;
00725 }
00726 }
00727 }
00728
00729 return TRUE;
00730 }
00731
00732 static bfd_boolean
00733 xstormy16_elf_always_size_sections (output_bfd, info)
00734 bfd *output_bfd ATTRIBUTE_UNUSED;
00735 struct bfd_link_info *info;
00736 {
00737 bfd *dynobj;
00738 asection *splt;
00739
00740 if (info->relocatable)
00741 return TRUE;
00742
00743 dynobj = elf_hash_table (info)->dynobj;
00744 if (dynobj == NULL)
00745 return TRUE;
00746
00747 splt = bfd_get_section_by_name (dynobj, ".plt");
00748 BFD_ASSERT (splt != NULL);
00749
00750 splt->contents = (bfd_byte *) bfd_zalloc (dynobj, splt->size);
00751 if (splt->contents == NULL)
00752 return FALSE;
00753
00754 return TRUE;
00755 }
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787 static bfd_boolean
00788 xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section,
00789 contents, relocs, local_syms, local_sections)
00790 bfd * output_bfd ATTRIBUTE_UNUSED;
00791 struct bfd_link_info * info;
00792 bfd * input_bfd;
00793 asection * input_section;
00794 bfd_byte * contents;
00795 Elf_Internal_Rela * relocs;
00796 Elf_Internal_Sym * local_syms;
00797 asection ** local_sections;
00798 {
00799 Elf_Internal_Shdr * symtab_hdr;
00800 struct elf_link_hash_entry ** sym_hashes;
00801 Elf_Internal_Rela * rel;
00802 Elf_Internal_Rela * relend;
00803 bfd *dynobj;
00804 asection *splt;
00805
00806 if (info->relocatable)
00807 return TRUE;
00808
00809 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
00810 sym_hashes = elf_sym_hashes (input_bfd);
00811 relend = relocs + input_section->reloc_count;
00812
00813 dynobj = elf_hash_table (info)->dynobj;
00814 splt = NULL;
00815 if (dynobj != NULL)
00816 splt = bfd_get_section_by_name (dynobj, ".plt");
00817
00818 for (rel = relocs; rel < relend; rel ++)
00819 {
00820 reloc_howto_type * howto;
00821 unsigned long r_symndx;
00822 Elf_Internal_Sym * sym;
00823 asection * sec;
00824 struct elf_link_hash_entry * h;
00825 bfd_vma relocation;
00826 bfd_reloc_status_type r;
00827 const char * name = NULL;
00828 int r_type;
00829
00830 r_type = ELF32_R_TYPE (rel->r_info);
00831
00832 if ( r_type == R_XSTORMY16_GNU_VTINHERIT
00833 || r_type == R_XSTORMY16_GNU_VTENTRY)
00834 continue;
00835
00836 r_symndx = ELF32_R_SYM (rel->r_info);
00837 howto = xstormy16_elf_howto_table + ELF32_R_TYPE (rel->r_info);
00838 h = NULL;
00839 sym = NULL;
00840 sec = NULL;
00841
00842 if (r_symndx < symtab_hdr->sh_info)
00843 {
00844 sym = local_syms + r_symndx;
00845 sec = local_sections [r_symndx];
00846 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
00847 }
00848 else
00849 {
00850 bfd_boolean unresolved_reloc, warned;
00851
00852 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
00853 r_symndx, symtab_hdr, sym_hashes,
00854 h, sec, relocation,
00855 unresolved_reloc, warned);
00856 }
00857
00858 if (h != NULL)
00859 name = h->root.root.string;
00860 else
00861 {
00862 name = (bfd_elf_string_from_elf_section
00863 (input_bfd, symtab_hdr->sh_link, sym->st_name));
00864 if (name == NULL || *name == '\0')
00865 name = bfd_section_name (input_bfd, sec);
00866 }
00867
00868 switch (ELF32_R_TYPE (rel->r_info))
00869 {
00870 case R_XSTORMY16_24:
00871 {
00872 bfd_vma reloc = relocation + rel->r_addend;
00873 unsigned int x;
00874
00875 x = bfd_get_32 (input_bfd, contents + rel->r_offset);
00876 x &= 0x0000ff00;
00877 x |= reloc & 0xff;
00878 x |= (reloc << 8) & 0xffff0000;
00879 bfd_put_32 (input_bfd, x, contents + rel->r_offset);
00880
00881 if (reloc & ~0xffffff)
00882 r = bfd_reloc_overflow;
00883 else
00884 r = bfd_reloc_ok;
00885 break;
00886 }
00887
00888 case R_XSTORMY16_FPTR16:
00889 {
00890 bfd_vma *plt_offset;
00891
00892 if (h != NULL)
00893 plt_offset = &h->plt.offset;
00894 else
00895 plt_offset = elf_local_got_offsets (input_bfd) + r_symndx;
00896
00897 if (relocation <= 0xffff)
00898 {
00899
00900
00901 BFD_ASSERT (*plt_offset == (bfd_vma) -1);
00902 }
00903 else
00904 {
00905
00906
00907 BFD_ASSERT (*plt_offset != (bfd_vma) -1);
00908
00909
00910
00911 if ((*plt_offset & 1) == 0)
00912 {
00913 unsigned int x;
00914
00915 x = 0x00000200;
00916 x |= relocation & 0xff;
00917 x |= (relocation << 8) & 0xffff0000;
00918 bfd_put_32 (input_bfd, x, splt->contents + *plt_offset);
00919 *plt_offset |= 1;
00920 }
00921
00922 relocation = (splt->output_section->vma
00923 + splt->output_offset
00924 + (*plt_offset & -2));
00925 }
00926 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
00927 contents, rel->r_offset,
00928 relocation, 0);
00929 break;
00930 }
00931
00932 default:
00933 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
00934 contents, rel->r_offset,
00935 relocation, rel->r_addend);
00936 break;
00937 }
00938
00939 if (r != bfd_reloc_ok)
00940 {
00941 const char * msg = (const char *) NULL;
00942
00943 switch (r)
00944 {
00945 case bfd_reloc_overflow:
00946 r = info->callbacks->reloc_overflow
00947 (info, (h ? &h->root : NULL), name, howto->name,
00948 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
00949 break;
00950
00951 case bfd_reloc_undefined:
00952 r = info->callbacks->undefined_symbol
00953 (info, name, input_bfd, input_section, rel->r_offset,
00954 TRUE);
00955 break;
00956
00957 case bfd_reloc_outofrange:
00958 msg = _("internal error: out of range error");
00959 break;
00960
00961 case bfd_reloc_notsupported:
00962 msg = _("internal error: unsupported relocation error");
00963 break;
00964
00965 case bfd_reloc_dangerous:
00966 msg = _("internal error: dangerous relocation");
00967 break;
00968
00969 default:
00970 msg = _("internal error: unknown error");
00971 break;
00972 }
00973
00974 if (msg)
00975 r = info->callbacks->warning
00976 (info, msg, name, input_bfd, input_section, rel->r_offset);
00977
00978 if (! r)
00979 return FALSE;
00980 }
00981 }
00982
00983 return TRUE;
00984 }
00985
00986
00987
00988 static bfd_boolean
00989 xstormy16_elf_finish_dynamic_sections (abfd, info)
00990 bfd *abfd ATTRIBUTE_UNUSED;
00991 struct bfd_link_info *info;
00992 {
00993 bfd *dynobj;
00994 asection *splt;
00995
00996
00997
00998
00999 if ((dynobj = elf_hash_table (info)->dynobj) != NULL
01000 && (splt = bfd_get_section_by_name (dynobj, ".plt")) != NULL)
01001 {
01002 bfd_byte *contents = splt->contents;
01003 unsigned int i, size = splt->size;
01004 for (i = 0; i < size; i += 4)
01005 {
01006 unsigned int x = bfd_get_32 (dynobj, contents + i);
01007 BFD_ASSERT (x != 0);
01008 }
01009 }
01010
01011 return TRUE;
01012 }
01013
01014
01015
01016
01017 static asection *
01018 xstormy16_elf_gc_mark_hook (sec, info, rel, h, sym)
01019 asection * sec;
01020 struct bfd_link_info * info ATTRIBUTE_UNUSED;
01021 Elf_Internal_Rela * rel;
01022 struct elf_link_hash_entry * h;
01023 Elf_Internal_Sym * sym;
01024 {
01025 if (h != NULL)
01026 {
01027 switch (ELF32_R_TYPE (rel->r_info))
01028 {
01029 case R_XSTORMY16_GNU_VTINHERIT:
01030 case R_XSTORMY16_GNU_VTENTRY:
01031 break;
01032
01033 default:
01034 switch (h->root.type)
01035 {
01036 case bfd_link_hash_defined:
01037 case bfd_link_hash_defweak:
01038 return h->root.u.def.section;
01039
01040 case bfd_link_hash_common:
01041 return h->root.u.c.p->section;
01042
01043 default:
01044 break;
01045 }
01046 }
01047 }
01048 else
01049 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
01050
01051 return NULL;
01052 }
01053
01054
01055
01056 static bfd_boolean
01057 xstormy16_elf_gc_sweep_hook (abfd, info, sec, relocs)
01058 bfd * abfd ATTRIBUTE_UNUSED;
01059 struct bfd_link_info * info ATTRIBUTE_UNUSED;
01060 asection * sec ATTRIBUTE_UNUSED;
01061 const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED;
01062 {
01063 return TRUE;
01064 }
01065
01066 #define ELF_ARCH bfd_arch_xstormy16
01067 #define ELF_MACHINE_CODE EM_XSTORMY16
01068 #define ELF_MAXPAGESIZE 0x100
01069
01070 #define TARGET_LITTLE_SYM bfd_elf32_xstormy16_vec
01071 #define TARGET_LITTLE_NAME "elf32-xstormy16"
01072
01073 #define elf_info_to_howto_rel NULL
01074 #define elf_info_to_howto xstormy16_info_to_howto_rela
01075 #define elf_backend_relocate_section xstormy16_elf_relocate_section
01076 #define elf_backend_gc_mark_hook xstormy16_elf_gc_mark_hook
01077 #define elf_backend_gc_sweep_hook xstormy16_elf_gc_sweep_hook
01078 #define elf_backend_check_relocs xstormy16_elf_check_relocs
01079 #define elf_backend_always_size_sections \
01080 xstormy16_elf_always_size_sections
01081 #define elf_backend_finish_dynamic_sections \
01082 xstormy16_elf_finish_dynamic_sections
01083
01084 #define elf_backend_can_gc_sections 1
01085 #define elf_backend_rela_normal 1
01086
01087 #define bfd_elf32_bfd_reloc_type_lookup xstormy16_reloc_type_lookup
01088 #define bfd_elf32_bfd_relax_section xstormy16_elf_relax_section
01089
01090 #include "elf32-target.h"