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
00027
00028 #include "bfd.h"
00029 #include "sysdep.h"
00030 #include "bfdlink.h"
00031 #include "libbfd.h"
00032 #include "elf-bfd.h"
00033 #include "elf/v850.h"
00034 #include "libiberty.h"
00035
00036
00037 #define SEXT24(x) ((((x) & 0xffffff) ^ 0x800000) - 0x800000)
00038
00039 static reloc_howto_type *v850_elf_reloc_type_lookup
00040 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
00041 static void v850_elf_info_to_howto_rel
00042 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
00043 static void v850_elf_info_to_howto_rela
00044 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
00045 static bfd_reloc_status_type v850_elf_reloc
00046 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00047 static bfd_boolean v850_elf_is_local_label_name
00048 PARAMS ((bfd *, const char *));
00049 static bfd_boolean v850_elf_relocate_section
00050 PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00051 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
00052 static bfd_reloc_status_type v850_elf_perform_relocation
00053 PARAMS ((bfd *, unsigned int, bfd_vma, bfd_byte *));
00054 static bfd_boolean v850_elf_check_relocs
00055 PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));
00056 static void remember_hi16s_reloc
00057 PARAMS ((bfd *, bfd_vma, bfd_byte *));
00058 static bfd_byte * find_remembered_hi16s_reloc
00059 PARAMS ((bfd_vma, bfd_boolean *));
00060 static bfd_reloc_status_type v850_elf_final_link_relocate
00061 PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *, bfd_vma,
00062 bfd_vma, bfd_vma, struct bfd_link_info *, asection *, int));
00063 static bfd_boolean v850_elf_object_p
00064 PARAMS ((bfd *));
00065 static bfd_boolean v850_elf_fake_sections
00066 PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
00067 static void v850_elf_final_write_processing
00068 PARAMS ((bfd *, bfd_boolean));
00069 static bfd_boolean v850_elf_set_private_flags
00070 PARAMS ((bfd *, flagword));
00071 static bfd_boolean v850_elf_merge_private_bfd_data
00072 PARAMS ((bfd *, bfd *));
00073 static bfd_boolean v850_elf_print_private_bfd_data
00074 PARAMS ((bfd *, PTR));
00075 static bfd_boolean v850_elf_section_from_bfd_section
00076 PARAMS ((bfd *, asection *, int *));
00077 static void v850_elf_symbol_processing
00078 PARAMS ((bfd *, asymbol *));
00079 static bfd_boolean v850_elf_add_symbol_hook
00080 PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Sym *,
00081 const char **, flagword *, asection **, bfd_vma *));
00082 static bfd_boolean v850_elf_link_output_symbol_hook
00083 PARAMS ((struct bfd_link_info *, const char *, Elf_Internal_Sym *,
00084 asection *, struct elf_link_hash_entry *));
00085 static bfd_boolean v850_elf_section_from_shdr
00086 PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
00087 static bfd_boolean v850_elf_gc_sweep_hook
00088 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00089 const Elf_Internal_Rela *));
00090 static asection * v850_elf_gc_mark_hook
00091 PARAMS ((asection *, struct bfd_link_info *,
00092 Elf_Internal_Rela *, struct elf_link_hash_entry *,
00093 Elf_Internal_Sym *));
00094 static bfd_reloc_status_type v850_elf_ignore_reloc
00095 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00096 static bfd_boolean v850_elf_relax_delete_bytes
00097 PARAMS ((bfd *, asection *, bfd_vma, bfd_vma, int));
00098 static bfd_boolean v850_elf_relax_section
00099 PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
00100
00101
00102
00103 static reloc_howto_type v850_elf_howto_table[] =
00104 {
00105
00106 HOWTO (R_V850_NONE,
00107 0,
00108 2,
00109 32,
00110 FALSE,
00111 0,
00112 complain_overflow_bitfield,
00113 bfd_elf_generic_reloc,
00114 "R_V850_NONE",
00115 FALSE,
00116 0,
00117 0,
00118 FALSE),
00119
00120
00121 HOWTO (R_V850_9_PCREL,
00122 2,
00123 2,
00124 26,
00125 TRUE,
00126 0,
00127 complain_overflow_bitfield,
00128 v850_elf_reloc,
00129 "R_V850_9_PCREL",
00130 FALSE,
00131 0x00ffffff,
00132 0x00ffffff,
00133 TRUE),
00134
00135
00136 HOWTO (R_V850_22_PCREL,
00137 2,
00138 2,
00139 22,
00140 TRUE,
00141 7,
00142 complain_overflow_signed,
00143 v850_elf_reloc,
00144 "R_V850_22_PCREL",
00145 FALSE,
00146 0x07ffff80,
00147 0x07ffff80,
00148 TRUE),
00149
00150
00151 HOWTO (R_V850_HI16_S,
00152 0,
00153 1,
00154 16,
00155 FALSE,
00156 0,
00157 complain_overflow_dont,
00158 v850_elf_reloc,
00159 "R_V850_HI16_S",
00160 FALSE,
00161 0xffff,
00162 0xffff,
00163 FALSE),
00164
00165
00166 HOWTO (R_V850_HI16,
00167 0,
00168 1,
00169 16,
00170 FALSE,
00171 0,
00172 complain_overflow_dont,
00173 v850_elf_reloc,
00174 "R_V850_HI16",
00175 FALSE,
00176 0xffff,
00177 0xffff,
00178 FALSE),
00179
00180
00181 HOWTO (R_V850_LO16,
00182 0,
00183 1,
00184 16,
00185 FALSE,
00186 0,
00187 complain_overflow_dont,
00188 v850_elf_reloc,
00189 "R_V850_LO16",
00190 FALSE,
00191 0xffff,
00192 0xffff,
00193 FALSE),
00194
00195
00196 HOWTO (R_V850_ABS32,
00197 0,
00198 2,
00199 32,
00200 FALSE,
00201 0,
00202 complain_overflow_dont,
00203 v850_elf_reloc,
00204 "R_V850_ABS32",
00205 FALSE,
00206 0xffffffff,
00207 0xffffffff,
00208 FALSE),
00209
00210
00211 HOWTO (R_V850_16,
00212 0,
00213 1,
00214 16,
00215 FALSE,
00216 0,
00217 complain_overflow_dont,
00218 bfd_elf_generic_reloc,
00219 "R_V850_16",
00220 FALSE,
00221 0xffff,
00222 0xffff,
00223 FALSE),
00224
00225
00226 HOWTO (R_V850_8,
00227 0,
00228 0,
00229 8,
00230 FALSE,
00231 0,
00232 complain_overflow_dont,
00233 bfd_elf_generic_reloc,
00234 "R_V850_8",
00235 FALSE,
00236 0xff,
00237 0xff,
00238 FALSE),
00239
00240
00241 HOWTO (R_V850_SDA_16_16_OFFSET,
00242 0,
00243 1,
00244 16,
00245 FALSE,
00246 0,
00247 complain_overflow_dont,
00248 v850_elf_reloc,
00249 "R_V850_SDA_16_16_OFFSET",
00250 FALSE,
00251 0xffff,
00252 0xffff,
00253 FALSE),
00254
00255
00256 HOWTO (R_V850_SDA_15_16_OFFSET,
00257 1,
00258 1,
00259 16,
00260 FALSE,
00261 1,
00262 complain_overflow_dont,
00263 v850_elf_reloc,
00264 "R_V850_SDA_15_16_OFFSET",
00265 FALSE,
00266 0xfffe,
00267 0xfffe,
00268 FALSE),
00269
00270
00271 HOWTO (R_V850_ZDA_16_16_OFFSET,
00272 0,
00273 1,
00274 16,
00275 FALSE,
00276 0,
00277 complain_overflow_dont,
00278 v850_elf_reloc,
00279 "R_V850_ZDA_16_16_OFFSET",
00280 FALSE,
00281 0xffff,
00282 0xffff,
00283 FALSE),
00284
00285
00286 HOWTO (R_V850_ZDA_15_16_OFFSET,
00287 1,
00288 1,
00289 16,
00290 FALSE,
00291 1,
00292 complain_overflow_dont,
00293 v850_elf_reloc,
00294 "R_V850_ZDA_15_16_OFFSET",
00295 FALSE,
00296 0xfffe,
00297 0xfffe,
00298 FALSE),
00299
00300
00301 HOWTO (R_V850_TDA_6_8_OFFSET,
00302 2,
00303 1,
00304 8,
00305 FALSE,
00306 1,
00307 complain_overflow_dont,
00308 v850_elf_reloc,
00309 "R_V850_TDA_6_8_OFFSET",
00310 FALSE,
00311 0x7e,
00312 0x7e,
00313 FALSE),
00314
00315
00316 HOWTO (R_V850_TDA_7_8_OFFSET,
00317 1,
00318 1,
00319 8,
00320 FALSE,
00321 0,
00322 complain_overflow_dont,
00323 v850_elf_reloc,
00324 "R_V850_TDA_7_8_OFFSET",
00325 FALSE,
00326 0x7f,
00327 0x7f,
00328 FALSE),
00329
00330
00331 HOWTO (R_V850_TDA_7_7_OFFSET,
00332 0,
00333 1,
00334 7,
00335 FALSE,
00336 0,
00337 complain_overflow_dont,
00338 v850_elf_reloc,
00339 "R_V850_TDA_7_7_OFFSET",
00340 FALSE,
00341 0x7f,
00342 0x7f,
00343 FALSE),
00344
00345
00346 HOWTO (R_V850_TDA_16_16_OFFSET,
00347 0,
00348 1,
00349 16,
00350 FALSE,
00351 0,
00352 complain_overflow_dont,
00353 v850_elf_reloc,
00354 "R_V850_TDA_16_16_OFFSET",
00355 FALSE,
00356 0xffff,
00357 0xfff,
00358 FALSE),
00359
00360
00361 HOWTO (R_V850_TDA_4_5_OFFSET,
00362 1,
00363 1,
00364 5,
00365 FALSE,
00366 0,
00367 complain_overflow_dont,
00368 v850_elf_reloc,
00369 "R_V850_TDA_4_5_OFFSET",
00370 FALSE,
00371 0x0f,
00372 0x0f,
00373 FALSE),
00374
00375
00376 HOWTO (R_V850_TDA_4_4_OFFSET,
00377 0,
00378 1,
00379 4,
00380 FALSE,
00381 0,
00382 complain_overflow_dont,
00383 v850_elf_reloc,
00384 "R_V850_TDA_4_4_OFFSET",
00385 FALSE,
00386 0x0f,
00387 0x0f,
00388 FALSE),
00389
00390
00391 HOWTO (R_V850_SDA_16_16_SPLIT_OFFSET,
00392 0,
00393 2,
00394 16,
00395 FALSE,
00396 0,
00397 complain_overflow_dont,
00398 v850_elf_reloc,
00399 "R_V850_SDA_16_16_SPLIT_OFFSET",
00400 FALSE,
00401 0xfffe0020,
00402 0xfffe0020,
00403 FALSE),
00404
00405
00406 HOWTO (R_V850_ZDA_16_16_SPLIT_OFFSET,
00407 0,
00408 2,
00409 16,
00410 FALSE,
00411 0,
00412 complain_overflow_dont,
00413 v850_elf_reloc,
00414 "R_V850_ZDA_16_16_SPLIT_OFFSET",
00415 FALSE,
00416 0xfffe0020,
00417 0xfffe0020,
00418 FALSE),
00419
00420
00421 HOWTO (R_V850_CALLT_6_7_OFFSET,
00422 0,
00423 1,
00424 7,
00425 FALSE,
00426 0,
00427 complain_overflow_dont,
00428 v850_elf_reloc,
00429 "R_V850_CALLT_6_7_OFFSET",
00430 FALSE,
00431 0x3f,
00432 0x3f,
00433 FALSE),
00434
00435
00436 HOWTO (R_V850_CALLT_16_16_OFFSET,
00437 0,
00438 1,
00439 16,
00440 FALSE,
00441 0,
00442 complain_overflow_dont,
00443 v850_elf_reloc,
00444 "R_V850_CALLT_16_16_OFFSET",
00445 FALSE,
00446 0xffff,
00447 0xffff,
00448 FALSE),
00449
00450
00451 HOWTO (R_V850_GNU_VTINHERIT,
00452 0,
00453 2,
00454 0,
00455 FALSE,
00456 0,
00457 complain_overflow_dont,
00458 NULL,
00459 "R_V850_GNU_VTINHERIT",
00460 FALSE,
00461 0,
00462 0,
00463 FALSE),
00464
00465
00466 HOWTO (R_V850_GNU_VTENTRY,
00467 0,
00468 2,
00469 0,
00470 FALSE,
00471 0,
00472 complain_overflow_dont,
00473 _bfd_elf_rel_vtable_reloc_fn,
00474 "R_V850_GNU_VTENTRY",
00475 FALSE,
00476 0,
00477 0,
00478 FALSE),
00479
00480
00481
00482 HOWTO (R_V850_LONGCALL,
00483 0,
00484 2,
00485 32,
00486 TRUE,
00487 0,
00488 complain_overflow_signed,
00489 v850_elf_ignore_reloc,
00490 "R_V850_LONGCALL",
00491 FALSE,
00492 0,
00493 0,
00494 TRUE),
00495
00496
00497
00498 HOWTO (R_V850_LONGJUMP,
00499 0,
00500 2,
00501 32,
00502 TRUE,
00503 0,
00504 complain_overflow_signed,
00505 v850_elf_ignore_reloc,
00506 "R_V850_LONGJUMP",
00507 FALSE,
00508 0,
00509 0,
00510 TRUE),
00511
00512 HOWTO (R_V850_ALIGN,
00513 0,
00514 1,
00515 0,
00516 FALSE,
00517 0,
00518 complain_overflow_unsigned,
00519 v850_elf_ignore_reloc,
00520 "R_V850_ALIGN",
00521 FALSE,
00522 0,
00523 0,
00524 TRUE),
00525
00526
00527 HOWTO (R_V850_REL32,
00528 0,
00529 2,
00530 32,
00531 TRUE,
00532 0,
00533 complain_overflow_dont,
00534 v850_elf_reloc,
00535 "R_V850_REL32",
00536 FALSE,
00537 0xffffffff,
00538 0xffffffff,
00539 FALSE),
00540
00541
00542 HOWTO (R_V850_LO16_SPLIT_OFFSET,
00543 0,
00544 2,
00545 16,
00546 FALSE,
00547 0,
00548 complain_overflow_dont,
00549 v850_elf_reloc,
00550 "R_V850_LO16_SPLIT_OFFSET",
00551 FALSE,
00552 0xfffe0020,
00553 0xfffe0020,
00554 FALSE),
00555 };
00556
00557
00558
00559 struct v850_elf_reloc_map
00560 {
00561
00562
00563 bfd_reloc_code_real_type bfd_reloc_val;
00564 unsigned int elf_reloc_val;
00565 };
00566
00567 static const struct v850_elf_reloc_map v850_elf_reloc_map[] =
00568 {
00569 { BFD_RELOC_NONE, R_V850_NONE },
00570 { BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL },
00571 { BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL },
00572 { BFD_RELOC_HI16_S, R_V850_HI16_S },
00573 { BFD_RELOC_HI16, R_V850_HI16 },
00574 { BFD_RELOC_LO16, R_V850_LO16 },
00575 { BFD_RELOC_32, R_V850_ABS32 },
00576 { BFD_RELOC_32_PCREL, R_V850_REL32 },
00577 { BFD_RELOC_16, R_V850_16 },
00578 { BFD_RELOC_8, R_V850_8 },
00579 { BFD_RELOC_V850_SDA_16_16_OFFSET, R_V850_SDA_16_16_OFFSET },
00580 { BFD_RELOC_V850_SDA_15_16_OFFSET, R_V850_SDA_15_16_OFFSET },
00581 { BFD_RELOC_V850_ZDA_16_16_OFFSET, R_V850_ZDA_16_16_OFFSET },
00582 { BFD_RELOC_V850_ZDA_15_16_OFFSET, R_V850_ZDA_15_16_OFFSET },
00583 { BFD_RELOC_V850_TDA_6_8_OFFSET, R_V850_TDA_6_8_OFFSET },
00584 { BFD_RELOC_V850_TDA_7_8_OFFSET, R_V850_TDA_7_8_OFFSET },
00585 { BFD_RELOC_V850_TDA_7_7_OFFSET, R_V850_TDA_7_7_OFFSET },
00586 { BFD_RELOC_V850_TDA_16_16_OFFSET, R_V850_TDA_16_16_OFFSET },
00587 { BFD_RELOC_V850_TDA_4_5_OFFSET, R_V850_TDA_4_5_OFFSET },
00588 { BFD_RELOC_V850_TDA_4_4_OFFSET, R_V850_TDA_4_4_OFFSET },
00589 { BFD_RELOC_V850_LO16_SPLIT_OFFSET, R_V850_LO16_SPLIT_OFFSET },
00590 { BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, R_V850_SDA_16_16_SPLIT_OFFSET },
00591 { BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, R_V850_ZDA_16_16_SPLIT_OFFSET },
00592 { BFD_RELOC_V850_CALLT_6_7_OFFSET, R_V850_CALLT_6_7_OFFSET },
00593 { BFD_RELOC_V850_CALLT_16_16_OFFSET, R_V850_CALLT_16_16_OFFSET },
00594 { BFD_RELOC_VTABLE_INHERIT, R_V850_GNU_VTINHERIT },
00595 { BFD_RELOC_VTABLE_ENTRY, R_V850_GNU_VTENTRY },
00596 { BFD_RELOC_V850_LONGCALL, R_V850_LONGCALL },
00597 { BFD_RELOC_V850_LONGJUMP, R_V850_LONGJUMP },
00598 { BFD_RELOC_V850_ALIGN, R_V850_ALIGN },
00599
00600 };
00601
00602
00603
00604 static reloc_howto_type *
00605 v850_elf_reloc_type_lookup (abfd, code)
00606 bfd *abfd ATTRIBUTE_UNUSED;
00607 bfd_reloc_code_real_type code;
00608 {
00609 unsigned int i;
00610
00611 for (i = ARRAY_SIZE (v850_elf_reloc_map); i --;)
00612 if (v850_elf_reloc_map[i].bfd_reloc_val == code)
00613 {
00614 unsigned int elf_reloc_val = v850_elf_reloc_map[i].elf_reloc_val;
00615
00616 BFD_ASSERT (v850_elf_howto_table[elf_reloc_val].type == elf_reloc_val);
00617
00618 return v850_elf_howto_table + elf_reloc_val;
00619 }
00620
00621 return NULL;
00622 }
00623
00624
00625
00626 static void
00627 v850_elf_info_to_howto_rel (abfd, cache_ptr, dst)
00628 bfd *abfd ATTRIBUTE_UNUSED;
00629 arelent *cache_ptr;
00630 Elf_Internal_Rela *dst;
00631 {
00632 unsigned int r_type;
00633
00634 r_type = ELF32_R_TYPE (dst->r_info);
00635 BFD_ASSERT (r_type < (unsigned int) R_V850_max);
00636 cache_ptr->howto = &v850_elf_howto_table[r_type];
00637 }
00638
00639
00640 static void
00641 v850_elf_info_to_howto_rela (abfd, cache_ptr, dst)
00642 bfd *abfd ATTRIBUTE_UNUSED;
00643 arelent * cache_ptr;
00644 Elf_Internal_Rela *dst;
00645 {
00646 unsigned int r_type;
00647
00648 r_type = ELF32_R_TYPE (dst->r_info);
00649 BFD_ASSERT (r_type < (unsigned int) R_V850_max);
00650 cache_ptr->howto = &v850_elf_howto_table[r_type];
00651 }
00652
00653
00654
00655
00656
00657 static bfd_boolean
00658 v850_elf_check_relocs (abfd, info, sec, relocs)
00659 bfd *abfd;
00660 struct bfd_link_info *info;
00661 asection *sec;
00662 const Elf_Internal_Rela *relocs;
00663 {
00664 bfd_boolean ret = TRUE;
00665 bfd *dynobj;
00666 Elf_Internal_Shdr *symtab_hdr;
00667 struct elf_link_hash_entry **sym_hashes;
00668 const Elf_Internal_Rela *rel;
00669 const Elf_Internal_Rela *rel_end;
00670 asection *sreloc;
00671 enum v850_reloc_type r_type;
00672 int other = 0;
00673 const char *common = (const char *)0;
00674
00675 if (info->relocatable)
00676 return TRUE;
00677
00678 #ifdef DEBUG
00679 _bfd_error_handler ("v850_elf_check_relocs called for section %A in %B",
00680 sec, abfd);
00681 #endif
00682
00683 dynobj = elf_hash_table (info)->dynobj;
00684 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00685 sym_hashes = elf_sym_hashes (abfd);
00686 sreloc = NULL;
00687
00688 rel_end = relocs + sec->reloc_count;
00689 for (rel = relocs; rel < rel_end; rel++)
00690 {
00691 unsigned long r_symndx;
00692 struct elf_link_hash_entry *h;
00693
00694 r_symndx = ELF32_R_SYM (rel->r_info);
00695 if (r_symndx < symtab_hdr->sh_info)
00696 h = NULL;
00697 else
00698 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
00699
00700 r_type = (enum v850_reloc_type) ELF32_R_TYPE (rel->r_info);
00701 switch (r_type)
00702 {
00703 default:
00704 case R_V850_NONE:
00705 case R_V850_9_PCREL:
00706 case R_V850_22_PCREL:
00707 case R_V850_HI16_S:
00708 case R_V850_HI16:
00709 case R_V850_LO16:
00710 case R_V850_LO16_SPLIT_OFFSET:
00711 case R_V850_ABS32:
00712 case R_V850_REL32:
00713 case R_V850_16:
00714 case R_V850_8:
00715 case R_V850_CALLT_6_7_OFFSET:
00716 case R_V850_CALLT_16_16_OFFSET:
00717 break;
00718
00719
00720
00721 case R_V850_GNU_VTINHERIT:
00722 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
00723 return FALSE;
00724 break;
00725
00726
00727
00728 case R_V850_GNU_VTENTRY:
00729 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
00730 return FALSE;
00731 break;
00732
00733 case R_V850_SDA_16_16_SPLIT_OFFSET:
00734 case R_V850_SDA_16_16_OFFSET:
00735 case R_V850_SDA_15_16_OFFSET:
00736 other = V850_OTHER_SDA;
00737 common = ".scommon";
00738 goto small_data_common;
00739
00740 case R_V850_ZDA_16_16_SPLIT_OFFSET:
00741 case R_V850_ZDA_16_16_OFFSET:
00742 case R_V850_ZDA_15_16_OFFSET:
00743 other = V850_OTHER_ZDA;
00744 common = ".zcommon";
00745 goto small_data_common;
00746
00747 case R_V850_TDA_4_5_OFFSET:
00748 case R_V850_TDA_4_4_OFFSET:
00749 case R_V850_TDA_6_8_OFFSET:
00750 case R_V850_TDA_7_8_OFFSET:
00751 case R_V850_TDA_7_7_OFFSET:
00752 case R_V850_TDA_16_16_OFFSET:
00753 other = V850_OTHER_TDA;
00754 common = ".tcommon";
00755
00756
00757 #define V850_OTHER_MASK (V850_OTHER_TDA | V850_OTHER_SDA | V850_OTHER_ZDA)
00758
00759 small_data_common:
00760 if (h)
00761 {
00762
00763 h->other |= other;
00764 if ((h->other & V850_OTHER_MASK) != (other & V850_OTHER_MASK)
00765 && (h->other & V850_OTHER_ERROR) == 0)
00766 {
00767 const char * msg;
00768 static char buff[200];
00769
00770 switch (h->other & V850_OTHER_MASK)
00771 {
00772 default:
00773 msg = _("Variable `%s' cannot occupy in multiple small data regions");
00774 break;
00775 case V850_OTHER_SDA | V850_OTHER_ZDA | V850_OTHER_TDA:
00776 msg = _("Variable `%s' can only be in one of the small, zero, and tiny data regions");
00777 break;
00778 case V850_OTHER_SDA | V850_OTHER_ZDA:
00779 msg = _("Variable `%s' cannot be in both small and zero data regions simultaneously");
00780 break;
00781 case V850_OTHER_SDA | V850_OTHER_TDA:
00782 msg = _("Variable `%s' cannot be in both small and tiny data regions simultaneously");
00783 break;
00784 case V850_OTHER_ZDA | V850_OTHER_TDA:
00785 msg = _("Variable `%s' cannot be in both zero and tiny data regions simultaneously");
00786 break;
00787 }
00788
00789 sprintf (buff, msg, h->root.root.string);
00790 info->callbacks->warning (info, buff, h->root.root.string,
00791 abfd, h->root.u.def.section,
00792 (bfd_vma) 0);
00793
00794 bfd_set_error (bfd_error_bad_value);
00795 h->other |= V850_OTHER_ERROR;
00796 ret = FALSE;
00797 }
00798 }
00799
00800 if (h && h->root.type == bfd_link_hash_common
00801 && h->root.u.c.p
00802 && !strcmp (bfd_get_section_name (abfd, h->root.u.c.p->section), "COMMON"))
00803 {
00804 asection * section;
00805
00806 section = h->root.u.c.p->section = bfd_make_section_old_way (abfd, common);
00807 section->flags |= SEC_IS_COMMON;
00808 }
00809
00810 #ifdef DEBUG
00811 fprintf (stderr, "v850_elf_check_relocs, found %s relocation for %s%s\n",
00812 v850_elf_howto_table[ (int)r_type ].name,
00813 (h && h->root.root.string) ? h->root.root.string : "<unknown>",
00814 (h->root.type == bfd_link_hash_common) ? ", symbol is common" : "");
00815 #endif
00816 break;
00817 }
00818 }
00819
00820 return ret;
00821 }
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836 typedef struct hi16s_location
00837 {
00838 bfd_vma addend;
00839 bfd_byte *address;
00840 unsigned long counter;
00841 bfd_boolean found;
00842 struct hi16s_location *next;
00843 }
00844 hi16s_location;
00845
00846 static hi16s_location *previous_hi16s;
00847 static hi16s_location *free_hi16s;
00848 static unsigned long hi16s_counter;
00849
00850 static void
00851 remember_hi16s_reloc (abfd, addend, address)
00852 bfd *abfd;
00853 bfd_vma addend;
00854 bfd_byte *address;
00855 {
00856 hi16s_location * entry = NULL;
00857 bfd_size_type amt = sizeof (* free_hi16s);
00858
00859
00860 if (free_hi16s == NULL)
00861 free_hi16s = (hi16s_location *) bfd_zalloc (abfd, amt);
00862
00863 entry = free_hi16s;
00864 free_hi16s = free_hi16s->next;
00865
00866 entry->addend = addend;
00867 entry->address = address;
00868 entry->counter = hi16s_counter ++;
00869 entry->found = FALSE;
00870 entry->next = previous_hi16s;
00871 previous_hi16s = entry;
00872
00873
00874 if (hi16s_counter == 0)
00875 {
00876
00877 for (entry = previous_hi16s; entry != NULL; entry = entry->next)
00878 entry->counter &= 0xffff;
00879
00880 hi16s_counter = 0x10000;
00881 }
00882
00883 return;
00884 }
00885
00886 static bfd_byte *
00887 find_remembered_hi16s_reloc (addend, already_found)
00888 bfd_vma addend;
00889 bfd_boolean *already_found;
00890 {
00891 hi16s_location *match = NULL;
00892 hi16s_location *entry;
00893 hi16s_location *previous = NULL;
00894 hi16s_location *prev;
00895 bfd_byte *addr;
00896
00897
00898 for (entry = previous_hi16s; entry; entry = entry->next)
00899 {
00900 if (entry->addend == addend
00901 && (match == NULL || match->counter < entry->counter))
00902 {
00903 previous = prev;
00904 match = entry;
00905 }
00906
00907 prev = entry;
00908 }
00909
00910 if (match == NULL)
00911 return NULL;
00912
00913
00914 addr = match->address;
00915
00916
00917 if (already_found)
00918 * already_found = match->found;
00919
00920
00921 match->found = TRUE;
00922
00923 return addr;
00924 }
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068 static bfd_boolean
01069 v850_elf_perform_lo16_relocation (bfd *abfd, unsigned long *insn,
01070 unsigned long addend)
01071 {
01072 #define BIT15_SET(x) ((x) & 0x8000)
01073 #define OVERFLOWS(a,i) ((((a) & 0xffff) + (i)) > 0xffff)
01074 if ((BIT15_SET (*insn + addend) && ! BIT15_SET (addend))
01075 || (OVERFLOWS (addend, *insn)
01076 && ((! BIT15_SET (*insn)) || (BIT15_SET (addend)))))
01077 {
01078 bfd_boolean already_updated;
01079 bfd_byte *hi16s_address = find_remembered_hi16s_reloc
01080 (addend, & already_updated);
01081
01082
01083 if (hi16s_address != NULL)
01084 {
01085 if (! already_updated)
01086 {
01087 unsigned long hi_insn = bfd_get_16 (abfd, hi16s_address);
01088 hi_insn += 1;
01089 bfd_put_16 (abfd, hi_insn, hi16s_address);
01090 }
01091 }
01092 else
01093 {
01094 fprintf (stderr, _("FAILED to find previous HI16 reloc\n"));
01095 return FALSE;
01096 }
01097 }
01098 #undef OVERFLOWS
01099 #undef BIT15_SET
01100
01101
01102
01103 *insn = (*insn + addend) & 0xffff;
01104 return TRUE;
01105 }
01106
01107
01108
01109
01110 static bfd_reloc_status_type
01111 v850_elf_perform_relocation (abfd, r_type, addend, address)
01112 bfd *abfd;
01113 unsigned int r_type;
01114 bfd_vma addend;
01115 bfd_byte *address;
01116 {
01117 unsigned long insn;
01118 unsigned long result;
01119 bfd_signed_vma saddend = (bfd_signed_vma) addend;
01120
01121 switch (r_type)
01122 {
01123 default:
01124
01125 return bfd_reloc_notsupported;
01126
01127 case R_V850_REL32:
01128 case R_V850_ABS32:
01129 bfd_put_32 (abfd, addend, address);
01130 return bfd_reloc_ok;
01131
01132 case R_V850_22_PCREL:
01133 if (saddend > 0x1fffff || saddend < -0x200000)
01134 return bfd_reloc_overflow;
01135
01136 if ((addend % 2) != 0)
01137 return bfd_reloc_dangerous;
01138
01139 insn = bfd_get_32 (abfd, address);
01140 insn &= ~0xfffe003f;
01141 insn |= (((addend & 0xfffe) << 16) | ((addend & 0x3f0000) >> 16));
01142 bfd_put_32 (abfd, (bfd_vma) insn, address);
01143 return bfd_reloc_ok;
01144
01145 case R_V850_9_PCREL:
01146 if (saddend > 0xff || saddend < -0x100)
01147 return bfd_reloc_overflow;
01148
01149 if ((addend % 2) != 0)
01150 return bfd_reloc_dangerous;
01151
01152 insn = bfd_get_16 (abfd, address);
01153 insn &= ~ 0xf870;
01154 insn |= ((addend & 0x1f0) << 7) | ((addend & 0x0e) << 3);
01155 break;
01156
01157 case R_V850_HI16:
01158 addend += (bfd_get_16 (abfd, address) << 16);
01159 addend = (addend >> 16);
01160 insn = addend;
01161 break;
01162
01163 case R_V850_HI16_S:
01164
01165 remember_hi16s_reloc (abfd, addend, address);
01166
01167 addend += (bfd_get_16 (abfd, address) << 16);
01168 addend = (addend >> 16) + ((addend & 0x8000) != 0);
01169
01170
01171 if (addend > 0x7fff)
01172 addend = 0;
01173
01174 insn = addend;
01175 break;
01176
01177 case R_V850_LO16:
01178 insn = bfd_get_16 (abfd, address);
01179 if (! v850_elf_perform_lo16_relocation (abfd, &insn, addend))
01180 return bfd_reloc_overflow;
01181 break;
01182
01183 case R_V850_8:
01184 addend += (char) bfd_get_8 (abfd, address);
01185
01186 saddend = (bfd_signed_vma) addend;
01187
01188 if (saddend > 0x7f || saddend < -0x80)
01189 return bfd_reloc_overflow;
01190
01191 bfd_put_8 (abfd, addend, address);
01192 return bfd_reloc_ok;
01193
01194 case R_V850_CALLT_16_16_OFFSET:
01195 addend += bfd_get_16 (abfd, address);
01196
01197 saddend = (bfd_signed_vma) addend;
01198
01199 if (saddend > 0xffff || saddend < 0)
01200 return bfd_reloc_overflow;
01201
01202 insn = addend;
01203 break;
01204
01205 case R_V850_16:
01206
01207
01208 case R_V850_SDA_16_16_OFFSET:
01209 case R_V850_ZDA_16_16_OFFSET:
01210 case R_V850_TDA_16_16_OFFSET:
01211 addend += bfd_get_16 (abfd, address);
01212
01213 saddend = (bfd_signed_vma) addend;
01214
01215 if (saddend > 0x7fff || saddend < -0x8000)
01216 return bfd_reloc_overflow;
01217
01218 insn = addend;
01219 break;
01220
01221 case R_V850_SDA_15_16_OFFSET:
01222 case R_V850_ZDA_15_16_OFFSET:
01223 insn = bfd_get_16 (abfd, address);
01224 addend += (insn & 0xfffe);
01225
01226 saddend = (bfd_signed_vma) addend;
01227
01228 if (saddend > 0x7ffe || saddend < -0x8000)
01229 return bfd_reloc_overflow;
01230
01231 if (addend & 1)
01232 return bfd_reloc_dangerous;
01233
01234 insn = (addend &~ (bfd_vma) 1) | (insn & 1);
01235 break;
01236
01237 case R_V850_TDA_6_8_OFFSET:
01238 insn = bfd_get_16 (abfd, address);
01239 addend += ((insn & 0x7e) << 1);
01240
01241 saddend = (bfd_signed_vma) addend;
01242
01243 if (saddend > 0xfc || saddend < 0)
01244 return bfd_reloc_overflow;
01245
01246 if (addend & 3)
01247 return bfd_reloc_dangerous;
01248
01249 insn &= 0xff81;
01250 insn |= (addend >> 1);
01251 break;
01252
01253 case R_V850_TDA_7_8_OFFSET:
01254 insn = bfd_get_16 (abfd, address);
01255 addend += ((insn & 0x7f) << 1);
01256
01257 saddend = (bfd_signed_vma) addend;
01258
01259 if (saddend > 0xfe || saddend < 0)
01260 return bfd_reloc_overflow;
01261
01262 if (addend & 1)
01263 return bfd_reloc_dangerous;
01264
01265 insn &= 0xff80;
01266 insn |= (addend >> 1);
01267 break;
01268
01269 case R_V850_TDA_7_7_OFFSET:
01270 insn = bfd_get_16 (abfd, address);
01271 addend += insn & 0x7f;
01272
01273 saddend = (bfd_signed_vma) addend;
01274
01275 if (saddend > 0x7f || saddend < 0)
01276 return bfd_reloc_overflow;
01277
01278 insn &= 0xff80;
01279 insn |= addend;
01280 break;
01281
01282 case R_V850_TDA_4_5_OFFSET:
01283 insn = bfd_get_16 (abfd, address);
01284 addend += ((insn & 0xf) << 1);
01285
01286 saddend = (bfd_signed_vma) addend;
01287
01288 if (saddend > 0x1e || saddend < 0)
01289 return bfd_reloc_overflow;
01290
01291 if (addend & 1)
01292 return bfd_reloc_dangerous;
01293
01294 insn &= 0xfff0;
01295 insn |= (addend >> 1);
01296 break;
01297
01298 case R_V850_TDA_4_4_OFFSET:
01299 insn = bfd_get_16 (abfd, address);
01300 addend += insn & 0xf;
01301
01302 saddend = (bfd_signed_vma) addend;
01303
01304 if (saddend > 0xf || saddend < 0)
01305 return bfd_reloc_overflow;
01306
01307 insn &= 0xfff0;
01308 insn |= addend;
01309 break;
01310
01311 case R_V850_LO16_SPLIT_OFFSET:
01312 insn = bfd_get_32 (abfd, address);
01313 result = ((insn & 0xfffe0000) >> 16) | ((insn & 0x20) >> 5);
01314 if (! v850_elf_perform_lo16_relocation (abfd, &result, addend))
01315 return bfd_reloc_overflow;
01316 insn = (((result << 16) & 0xfffe0000)
01317 | ((result << 5) & 0x20)
01318 | (insn & ~0xfffe0020));
01319 bfd_put_32 (abfd, insn, address);
01320 return bfd_reloc_ok;
01321
01322 case R_V850_ZDA_16_16_SPLIT_OFFSET:
01323 case R_V850_SDA_16_16_SPLIT_OFFSET:
01324 insn = bfd_get_32 (abfd, address);
01325 addend += ((insn & 0xfffe0000) >> 16) + ((insn & 0x20) >> 5);
01326
01327 saddend = (bfd_signed_vma) addend;
01328
01329 if (saddend > 0x7fff || saddend < -0x8000)
01330 return bfd_reloc_overflow;
01331
01332 insn &= 0x0001ffdf;
01333 insn |= (addend & 1) << 5;
01334 insn |= (addend &~ (bfd_vma) 1) << 16;
01335
01336 bfd_put_32 (abfd, (bfd_vma) insn, address);
01337 return bfd_reloc_ok;
01338
01339 case R_V850_CALLT_6_7_OFFSET:
01340 insn = bfd_get_16 (abfd, address);
01341 addend += ((insn & 0x3f) << 1);
01342
01343 saddend = (bfd_signed_vma) addend;
01344
01345 if (saddend > 0x7e || saddend < 0)
01346 return bfd_reloc_overflow;
01347
01348 if (addend & 1)
01349 return bfd_reloc_dangerous;
01350
01351 insn &= 0xff80;
01352 insn |= (addend >> 1);
01353 break;
01354
01355 case R_V850_GNU_VTINHERIT:
01356 case R_V850_GNU_VTENTRY:
01357 return bfd_reloc_ok;
01358
01359 }
01360
01361 bfd_put_16 (abfd, (bfd_vma) insn, address);
01362 return bfd_reloc_ok;
01363 }
01364
01365
01366
01367 static bfd_reloc_status_type
01368 v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err)
01369 bfd *abfd ATTRIBUTE_UNUSED;
01370 arelent *reloc;
01371 asymbol *symbol;
01372 PTR data ATTRIBUTE_UNUSED;
01373 asection *isection;
01374 bfd *obfd;
01375 char **err ATTRIBUTE_UNUSED;
01376 {
01377 long relocation;
01378
01379
01380
01381
01382
01383
01384 if (obfd != (bfd *) NULL
01385 && (symbol->flags & BSF_SECTION_SYM) == 0
01386 && (! reloc->howto->partial_inplace
01387 || reloc->addend == 0))
01388 {
01389 reloc->address += isection->output_offset;
01390 return bfd_reloc_ok;
01391 }
01392
01393
01394 if (bfd_is_und_section (symbol->section)
01395 && (symbol->flags & BSF_WEAK) == 0
01396 && obfd == NULL)
01397 return bfd_reloc_undefined;
01398
01399
01400
01401
01402 if (reloc->address > bfd_get_section_limit (abfd, isection))
01403 return bfd_reloc_outofrange;
01404
01405
01406
01407
01408 if (reloc->howto->pc_relative)
01409 return bfd_reloc_ok;
01410
01411
01412 if (bfd_is_com_section (symbol->section))
01413 relocation = 0;
01414 else
01415 relocation = symbol->value;
01416
01417
01418 relocation += symbol->section->output_section->vma;
01419 relocation += symbol->section->output_offset;
01420 relocation += reloc->addend;
01421
01422 reloc->addend = relocation;
01423 return bfd_reloc_ok;
01424 }
01425
01426
01427
01428
01429 static bfd_reloc_status_type
01430 v850_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
01431 output_bfd, error_message)
01432 bfd *abfd ATTRIBUTE_UNUSED;
01433 arelent *reloc_entry;
01434 asymbol *symbol ATTRIBUTE_UNUSED;
01435 PTR data ATTRIBUTE_UNUSED;
01436 asection *input_section;
01437 bfd *output_bfd;
01438 char **error_message ATTRIBUTE_UNUSED;
01439 {
01440 if (output_bfd != NULL)
01441 reloc_entry->address += input_section->output_offset;
01442
01443 return bfd_reloc_ok;
01444 }
01445
01446 static bfd_boolean
01447 v850_elf_is_local_label_name (abfd, name)
01448 bfd *abfd ATTRIBUTE_UNUSED;
01449 const char *name;
01450 {
01451 return ( (name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
01452 || (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_'));
01453 }
01454
01455
01456 #define bfd_reloc_gp_not_found bfd_reloc_other
01457 #define bfd_reloc_ep_not_found bfd_reloc_continue
01458 #define bfd_reloc_ctbp_not_found (bfd_reloc_dangerous + 1)
01459
01460
01461
01462 static bfd_reloc_status_type
01463 v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
01464 input_section, contents, offset, value,
01465 addend, info, sym_sec, is_local)
01466 reloc_howto_type *howto;
01467 bfd *input_bfd;
01468 bfd *output_bfd ATTRIBUTE_UNUSED;
01469 asection *input_section;
01470 bfd_byte *contents;
01471 bfd_vma offset;
01472 bfd_vma value;
01473 bfd_vma addend;
01474 struct bfd_link_info *info;
01475 asection *sym_sec;
01476 int is_local ATTRIBUTE_UNUSED;
01477 {
01478 unsigned int r_type = howto->type;
01479 bfd_byte *hit_data = contents + offset;
01480
01481
01482 switch (r_type)
01483 {
01484 case R_V850_9_PCREL:
01485 value -= (input_section->output_section->vma
01486 + input_section->output_offset);
01487 value -= offset;
01488 break;
01489
01490 case R_V850_22_PCREL:
01491 value -= (input_section->output_section->vma
01492 + input_section->output_offset
01493 + offset);
01494
01495
01496 if (((value & 0xff000000) != 0x0) && ((value & 0xff000000) != 0xff000000))
01497 return bfd_reloc_overflow;
01498
01499
01500 value = SEXT24 (value);
01501 break;
01502
01503 case R_V850_REL32:
01504 value -= (input_section->output_section->vma
01505 + input_section->output_offset
01506 + offset);
01507 break;
01508
01509 case R_V850_HI16_S:
01510 case R_V850_HI16:
01511 case R_V850_LO16:
01512 case R_V850_LO16_SPLIT_OFFSET:
01513 case R_V850_16:
01514 case R_V850_ABS32:
01515 case R_V850_8:
01516 break;
01517
01518 case R_V850_ZDA_15_16_OFFSET:
01519 case R_V850_ZDA_16_16_OFFSET:
01520 case R_V850_ZDA_16_16_SPLIT_OFFSET:
01521 if (sym_sec == NULL)
01522 return bfd_reloc_undefined;
01523
01524 value -= sym_sec->output_section->vma;
01525 break;
01526
01527 case R_V850_SDA_15_16_OFFSET:
01528 case R_V850_SDA_16_16_OFFSET:
01529 case R_V850_SDA_16_16_SPLIT_OFFSET:
01530 {
01531 unsigned long gp;
01532 struct bfd_link_hash_entry * h;
01533
01534 if (sym_sec == NULL)
01535 return bfd_reloc_undefined;
01536
01537
01538 h = bfd_link_hash_lookup (info->hash, "__gp", FALSE, FALSE, TRUE);
01539 if (h == (struct bfd_link_hash_entry *) NULL
01540 || h->type != bfd_link_hash_defined)
01541 return bfd_reloc_gp_not_found;
01542
01543 gp = (h->u.def.value
01544 + h->u.def.section->output_section->vma
01545 + h->u.def.section->output_offset);
01546
01547 value -= sym_sec->output_section->vma;
01548 value -= (gp - sym_sec->output_section->vma);
01549 }
01550 break;
01551
01552 case R_V850_TDA_4_4_OFFSET:
01553 case R_V850_TDA_4_5_OFFSET:
01554 case R_V850_TDA_16_16_OFFSET:
01555 case R_V850_TDA_7_7_OFFSET:
01556 case R_V850_TDA_7_8_OFFSET:
01557 case R_V850_TDA_6_8_OFFSET:
01558 {
01559 unsigned long ep;
01560 struct bfd_link_hash_entry * h;
01561
01562
01563 h = bfd_link_hash_lookup (info->hash, "__ep", FALSE, FALSE, TRUE);
01564 if (h == (struct bfd_link_hash_entry *) NULL
01565 || h->type != bfd_link_hash_defined)
01566 return bfd_reloc_ep_not_found;
01567
01568 ep = (h->u.def.value
01569 + h->u.def.section->output_section->vma
01570 + h->u.def.section->output_offset);
01571
01572 value -= ep;
01573 }
01574 break;
01575
01576 case R_V850_CALLT_6_7_OFFSET:
01577 {
01578 unsigned long ctbp;
01579 struct bfd_link_hash_entry * h;
01580
01581
01582 h = bfd_link_hash_lookup (info->hash, "__ctbp", FALSE, FALSE, TRUE);
01583 if (h == (struct bfd_link_hash_entry *) NULL
01584 || h->type != bfd_link_hash_defined)
01585 return bfd_reloc_ctbp_not_found;
01586
01587 ctbp = (h->u.def.value
01588 + h->u.def.section->output_section->vma
01589 + h->u.def.section->output_offset);
01590 value -= ctbp;
01591 }
01592 break;
01593
01594 case R_V850_CALLT_16_16_OFFSET:
01595 {
01596 unsigned long ctbp;
01597 struct bfd_link_hash_entry * h;
01598
01599 if (sym_sec == NULL)
01600 return bfd_reloc_undefined;
01601
01602
01603 h = bfd_link_hash_lookup (info->hash, "__ctbp", FALSE, FALSE, TRUE);
01604 if (h == (struct bfd_link_hash_entry *) NULL
01605 || h->type != bfd_link_hash_defined)
01606 return bfd_reloc_ctbp_not_found;
01607
01608 ctbp = (h->u.def.value
01609 + h->u.def.section->output_section->vma
01610 + h->u.def.section->output_offset);
01611
01612 value -= sym_sec->output_section->vma;
01613 value -= (ctbp - sym_sec->output_section->vma);
01614 }
01615 break;
01616
01617 case R_V850_NONE:
01618 case R_V850_GNU_VTINHERIT:
01619 case R_V850_GNU_VTENTRY:
01620 case R_V850_LONGCALL:
01621 case R_V850_LONGJUMP:
01622 case R_V850_ALIGN:
01623 return bfd_reloc_ok;
01624
01625 default:
01626 return bfd_reloc_notsupported;
01627 }
01628
01629
01630 return v850_elf_perform_relocation (input_bfd, r_type, value + addend, hit_data);
01631 }
01632
01633
01634
01635 static bfd_boolean
01636 v850_elf_relocate_section (output_bfd, info, input_bfd, input_section,
01637 contents, relocs, local_syms, local_sections)
01638 bfd *output_bfd;
01639 struct bfd_link_info *info;
01640 bfd *input_bfd;
01641 asection *input_section;
01642 bfd_byte *contents;
01643 Elf_Internal_Rela *relocs;
01644 Elf_Internal_Sym *local_syms;
01645 asection **local_sections;
01646 {
01647 Elf_Internal_Shdr *symtab_hdr;
01648 struct elf_link_hash_entry **sym_hashes;
01649 Elf_Internal_Rela *rel;
01650 Elf_Internal_Rela *relend;
01651
01652 if (info->relocatable)
01653 return TRUE;
01654
01655 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
01656 sym_hashes = elf_sym_hashes (input_bfd);
01657
01658 if (sym_hashes == NULL)
01659 {
01660 info->callbacks->warning
01661 (info, "no hash table available",
01662 NULL, input_bfd, input_section, (bfd_vma) 0);
01663
01664 return FALSE;
01665 }
01666
01667
01668 free_hi16s = previous_hi16s;
01669 previous_hi16s = NULL;
01670 hi16s_counter = 0;
01671
01672 rel = relocs;
01673 relend = relocs + input_section->reloc_count;
01674 for (; rel < relend; rel++)
01675 {
01676 int r_type;
01677 reloc_howto_type *howto;
01678 unsigned long r_symndx;
01679 Elf_Internal_Sym *sym;
01680 asection *sec;
01681 struct elf_link_hash_entry *h;
01682 bfd_vma relocation;
01683 bfd_reloc_status_type r;
01684
01685 r_symndx = ELF32_R_SYM (rel->r_info);
01686 r_type = ELF32_R_TYPE (rel->r_info);
01687
01688 if (r_type == R_V850_GNU_VTENTRY
01689 || r_type == R_V850_GNU_VTINHERIT)
01690 continue;
01691
01692
01693 howto = v850_elf_howto_table + r_type;
01694 h = NULL;
01695 sym = NULL;
01696 sec = NULL;
01697 if (r_symndx < symtab_hdr->sh_info)
01698 {
01699 sym = local_syms + r_symndx;
01700 sec = local_sections[r_symndx];
01701 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
01702 }
01703 else
01704 {
01705 bfd_boolean unresolved_reloc, warned;
01706
01707 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
01708 r_symndx, symtab_hdr, sym_hashes,
01709 h, sec, relocation,
01710 unresolved_reloc, warned);
01711 }
01712
01713
01714 r = v850_elf_final_link_relocate (howto, input_bfd, output_bfd,
01715 input_section,
01716 contents, rel->r_offset,
01717 relocation, rel->r_addend,
01718 info, sec, h == NULL);
01719
01720 if (r != bfd_reloc_ok)
01721 {
01722 const char * name;
01723 const char * msg = (const char *)0;
01724
01725 if (h != NULL)
01726 name = h->root.root.string;
01727 else
01728 {
01729 name = (bfd_elf_string_from_elf_section
01730 (input_bfd, symtab_hdr->sh_link, sym->st_name));
01731 if (name == NULL || *name == '\0')
01732 name = bfd_section_name (input_bfd, sec);
01733 }
01734
01735 switch (r)
01736 {
01737 case bfd_reloc_overflow:
01738 if (! ((*info->callbacks->reloc_overflow)
01739 (info, (h ? &h->root : NULL), name, howto->name,
01740 (bfd_vma) 0, input_bfd, input_section,
01741 rel->r_offset)))
01742 return FALSE;
01743 break;
01744
01745 case bfd_reloc_undefined:
01746 if (! ((*info->callbacks->undefined_symbol)
01747 (info, name, input_bfd, input_section,
01748 rel->r_offset, TRUE)))
01749 return FALSE;
01750 break;
01751
01752 case bfd_reloc_outofrange:
01753 msg = _("internal error: out of range error");
01754 goto common_error;
01755
01756 case bfd_reloc_notsupported:
01757 msg = _("internal error: unsupported relocation error");
01758 goto common_error;
01759
01760 case bfd_reloc_dangerous:
01761 msg = _("internal error: dangerous relocation");
01762 goto common_error;
01763
01764 case bfd_reloc_gp_not_found:
01765 msg = _("could not locate special linker symbol __gp");
01766 goto common_error;
01767
01768 case bfd_reloc_ep_not_found:
01769 msg = _("could not locate special linker symbol __ep");
01770 goto common_error;
01771
01772 case bfd_reloc_ctbp_not_found:
01773 msg = _("could not locate special linker symbol __ctbp");
01774 goto common_error;
01775
01776 default:
01777 msg = _("internal error: unknown error");
01778
01779
01780 common_error:
01781 if (!((*info->callbacks->warning)
01782 (info, msg, name, input_bfd, input_section,
01783 rel->r_offset)))
01784 return FALSE;
01785 break;
01786 }
01787 }
01788 }
01789
01790 return TRUE;
01791 }
01792
01793 static bfd_boolean
01794 v850_elf_gc_sweep_hook (abfd, info, sec, relocs)
01795 bfd *abfd ATTRIBUTE_UNUSED;
01796 struct bfd_link_info *info ATTRIBUTE_UNUSED;
01797 asection *sec ATTRIBUTE_UNUSED;
01798 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
01799 {
01800
01801 return TRUE;
01802 }
01803
01804 static asection *
01805 v850_elf_gc_mark_hook (sec, info, rel, h, sym)
01806 asection *sec;
01807 struct bfd_link_info *info ATTRIBUTE_UNUSED;
01808 Elf_Internal_Rela *rel;
01809 struct elf_link_hash_entry *h;
01810 Elf_Internal_Sym *sym;
01811 {
01812 if (h != NULL)
01813 {
01814 switch (ELF32_R_TYPE (rel->r_info))
01815 {
01816 case R_V850_GNU_VTINHERIT:
01817 case R_V850_GNU_VTENTRY:
01818 break;
01819
01820 default:
01821 switch (h->root.type)
01822 {
01823 case bfd_link_hash_defined:
01824 case bfd_link_hash_defweak:
01825 return h->root.u.def.section;
01826
01827 case bfd_link_hash_common:
01828 return h->root.u.c.p->section;
01829
01830 default:
01831 break;
01832 }
01833 }
01834 }
01835 else
01836 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
01837
01838 return NULL;
01839 }
01840
01841
01842
01843 static bfd_boolean
01844 v850_elf_object_p (abfd)
01845 bfd *abfd;
01846 {
01847 switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
01848 {
01849 default:
01850 case E_V850_ARCH:
01851 bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850);
01852 break;
01853 case E_V850E_ARCH:
01854 bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e);
01855 break;
01856 case E_V850E1_ARCH:
01857 bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e1);
01858 break;
01859 }
01860 return TRUE;
01861 }
01862
01863
01864
01865 static void
01866 v850_elf_final_write_processing (abfd, linker)
01867 bfd *abfd;
01868 bfd_boolean linker ATTRIBUTE_UNUSED;
01869 {
01870 unsigned long val;
01871
01872 switch (bfd_get_mach (abfd))
01873 {
01874 default:
01875 case bfd_mach_v850: val = E_V850_ARCH; break;
01876 case bfd_mach_v850e: val = E_V850E_ARCH; break;
01877 case bfd_mach_v850e1: val = E_V850E1_ARCH; break;
01878 }
01879
01880 elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH;
01881 elf_elfheader (abfd)->e_flags |= val;
01882 }
01883
01884
01885
01886 static bfd_boolean
01887 v850_elf_set_private_flags (abfd, flags)
01888 bfd *abfd;
01889 flagword flags;
01890 {
01891 BFD_ASSERT (!elf_flags_init (abfd)
01892 || elf_elfheader (abfd)->e_flags == flags);
01893
01894 elf_elfheader (abfd)->e_flags = flags;
01895 elf_flags_init (abfd) = TRUE;
01896 return TRUE;
01897 }
01898
01899
01900
01901 static bfd_boolean
01902 v850_elf_merge_private_bfd_data (ibfd, obfd)
01903 bfd *ibfd;
01904 bfd *obfd;
01905 {
01906 flagword out_flags;
01907 flagword in_flags;
01908
01909 if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
01910 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
01911 return TRUE;
01912
01913 in_flags = elf_elfheader (ibfd)->e_flags;
01914 out_flags = elf_elfheader (obfd)->e_flags;
01915
01916 if (! elf_flags_init (obfd))
01917 {
01918
01919
01920
01921
01922
01923
01924 if (bfd_get_arch_info (ibfd)->the_default)
01925 return TRUE;
01926
01927 elf_flags_init (obfd) = TRUE;
01928 elf_elfheader (obfd)->e_flags = in_flags;
01929
01930 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
01931 && bfd_get_arch_info (obfd)->the_default)
01932 return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
01933
01934 return TRUE;
01935 }
01936
01937
01938 if (in_flags == out_flags)
01939 return TRUE;
01940
01941 if ((in_flags & EF_V850_ARCH) != (out_flags & EF_V850_ARCH)
01942 && (in_flags & EF_V850_ARCH) != E_V850_ARCH)
01943 {
01944
01945
01946 if ((in_flags & EF_V850_ARCH) == E_V850E1_ARCH
01947 && (out_flags & EF_V850_ARCH) == E_V850E_ARCH)
01948 return TRUE;
01949
01950 if ((in_flags & EF_V850_ARCH) == E_V850E_ARCH
01951 && (out_flags & EF_V850_ARCH) == E_V850E1_ARCH)
01952 {
01953 elf_elfheader (obfd)->e_flags =
01954 ((out_flags & ~ EF_V850_ARCH) | E_V850E_ARCH);
01955 return TRUE;
01956 }
01957
01958 _bfd_error_handler (_("%B: Architecture mismatch with previous modules"),
01959 ibfd);
01960 }
01961
01962 return TRUE;
01963 }
01964
01965
01966
01967 static bfd_boolean
01968 v850_elf_print_private_bfd_data (abfd, ptr)
01969 bfd *abfd;
01970 PTR ptr;
01971 {
01972 FILE * file = (FILE *) ptr;
01973
01974 BFD_ASSERT (abfd != NULL && ptr != NULL);
01975
01976 _bfd_elf_print_private_bfd_data (abfd, ptr);
01977
01978
01979 fprintf (file, _("private flags = %lx: "), elf_elfheader (abfd)->e_flags);
01980
01981 switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH)
01982 {
01983 default:
01984 case E_V850_ARCH: fprintf (file, _("v850 architecture")); break;
01985 case E_V850E_ARCH: fprintf (file, _("v850e architecture")); break;
01986 case E_V850E1_ARCH: fprintf (file, _("v850e1 architecture")); break;
01987 }
01988
01989 fputc ('\n', file);
01990
01991 return TRUE;
01992 }
01993
01994
01995
01996
01997
01998
01999
02000
02001 static asection v850_elf_scom_section;
02002 static asymbol v850_elf_scom_symbol;
02003 static asymbol * v850_elf_scom_symbol_ptr;
02004 static asection v850_elf_tcom_section;
02005 static asymbol v850_elf_tcom_symbol;
02006 static asymbol * v850_elf_tcom_symbol_ptr;
02007 static asection v850_elf_zcom_section;
02008 static asymbol v850_elf_zcom_symbol;
02009 static asymbol * v850_elf_zcom_symbol_ptr;
02010
02011
02012
02013
02014 static bfd_boolean
02015 v850_elf_section_from_bfd_section (abfd, sec, retval)
02016 bfd *abfd ATTRIBUTE_UNUSED;
02017 asection *sec;
02018 int *retval;
02019 {
02020 if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
02021 *retval = SHN_V850_SCOMMON;
02022 else if (strcmp (bfd_get_section_name (abfd, sec), ".tcommon") == 0)
02023 *retval = SHN_V850_TCOMMON;
02024 else if (strcmp (bfd_get_section_name (abfd, sec), ".zcommon") == 0)
02025 *retval = SHN_V850_ZCOMMON;
02026 else
02027 return FALSE;
02028
02029 return TRUE;
02030 }
02031
02032
02033
02034 static void
02035 v850_elf_symbol_processing (abfd, asym)
02036 bfd *abfd;
02037 asymbol *asym;
02038 {
02039 elf_symbol_type * elfsym = (elf_symbol_type *) asym;
02040 unsigned int indx;
02041
02042 indx = elfsym->internal_elf_sym.st_shndx;
02043
02044
02045
02046
02047
02048
02049
02050 if (indx < elf_numsections (abfd))
02051 switch (elf_elfsections(abfd)[indx]->sh_type)
02052 {
02053 case SHT_V850_SCOMMON:
02054 indx = SHN_V850_SCOMMON;
02055 break;
02056
02057 case SHT_V850_TCOMMON:
02058 indx = SHN_V850_TCOMMON;
02059 break;
02060
02061 case SHT_V850_ZCOMMON:
02062 indx = SHN_V850_ZCOMMON;
02063 break;
02064
02065 default:
02066 break;
02067 }
02068
02069 switch (indx)
02070 {
02071 case SHN_V850_SCOMMON:
02072 if (v850_elf_scom_section.name == NULL)
02073 {
02074
02075 v850_elf_scom_section.name = ".scommon";
02076 v850_elf_scom_section.flags = SEC_IS_COMMON | SEC_ALLOC | SEC_DATA;
02077 v850_elf_scom_section.output_section = & v850_elf_scom_section;
02078 v850_elf_scom_section.symbol = & v850_elf_scom_symbol;
02079 v850_elf_scom_section.symbol_ptr_ptr = & v850_elf_scom_symbol_ptr;
02080 v850_elf_scom_symbol.name = ".scommon";
02081 v850_elf_scom_symbol.flags = BSF_SECTION_SYM;
02082 v850_elf_scom_symbol.section = & v850_elf_scom_section;
02083 v850_elf_scom_symbol_ptr = & v850_elf_scom_symbol;
02084 }
02085 asym->section = & v850_elf_scom_section;
02086 asym->value = elfsym->internal_elf_sym.st_size;
02087 break;
02088
02089 case SHN_V850_TCOMMON:
02090 if (v850_elf_tcom_section.name == NULL)
02091 {
02092
02093 v850_elf_tcom_section.name = ".tcommon";
02094 v850_elf_tcom_section.flags = SEC_IS_COMMON;
02095 v850_elf_tcom_section.output_section = & v850_elf_tcom_section;
02096 v850_elf_tcom_section.symbol = & v850_elf_tcom_symbol;
02097 v850_elf_tcom_section.symbol_ptr_ptr = & v850_elf_tcom_symbol_ptr;
02098 v850_elf_tcom_symbol.name = ".tcommon";
02099 v850_elf_tcom_symbol.flags = BSF_SECTION_SYM;
02100 v850_elf_tcom_symbol.section = & v850_elf_tcom_section;
02101 v850_elf_tcom_symbol_ptr = & v850_elf_tcom_symbol;
02102 }
02103 asym->section = & v850_elf_tcom_section;
02104 asym->value = elfsym->internal_elf_sym.st_size;
02105 break;
02106
02107 case SHN_V850_ZCOMMON:
02108 if (v850_elf_zcom_section.name == NULL)
02109 {
02110
02111 v850_elf_zcom_section.name = ".zcommon";
02112 v850_elf_zcom_section.flags = SEC_IS_COMMON;
02113 v850_elf_zcom_section.output_section = & v850_elf_zcom_section;
02114 v850_elf_zcom_section.symbol = & v850_elf_zcom_symbol;
02115 v850_elf_zcom_section.symbol_ptr_ptr = & v850_elf_zcom_symbol_ptr;
02116 v850_elf_zcom_symbol.name = ".zcommon";
02117 v850_elf_zcom_symbol.flags = BSF_SECTION_SYM;
02118 v850_elf_zcom_symbol.section = & v850_elf_zcom_section;
02119 v850_elf_zcom_symbol_ptr = & v850_elf_zcom_symbol;
02120 }
02121 asym->section = & v850_elf_zcom_section;
02122 asym->value = elfsym->internal_elf_sym.st_size;
02123 break;
02124 }
02125 }
02126
02127
02128
02129
02130 static bfd_boolean
02131 v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
02132 bfd *abfd;
02133 struct bfd_link_info *info ATTRIBUTE_UNUSED;
02134 Elf_Internal_Sym *sym;
02135 const char **namep ATTRIBUTE_UNUSED;
02136 flagword *flagsp ATTRIBUTE_UNUSED;
02137 asection **secp;
02138 bfd_vma *valp;
02139 {
02140 unsigned int indx = sym->st_shndx;
02141
02142
02143
02144
02145
02146
02147
02148 if (indx < elf_numsections (abfd))
02149 switch (elf_elfsections(abfd)[indx]->sh_type)
02150 {
02151 case SHT_V850_SCOMMON:
02152 indx = SHN_V850_SCOMMON;
02153 break;
02154
02155 case SHT_V850_TCOMMON:
02156 indx = SHN_V850_TCOMMON;
02157 break;
02158
02159 case SHT_V850_ZCOMMON:
02160 indx = SHN_V850_ZCOMMON;
02161 break;
02162
02163 default:
02164 break;
02165 }
02166
02167 switch (indx)
02168 {
02169 case SHN_V850_SCOMMON:
02170 *secp = bfd_make_section_old_way (abfd, ".scommon");
02171 (*secp)->flags |= SEC_IS_COMMON;
02172 *valp = sym->st_size;
02173 break;
02174
02175 case SHN_V850_TCOMMON:
02176 *secp = bfd_make_section_old_way (abfd, ".tcommon");
02177 (*secp)->flags |= SEC_IS_COMMON;
02178 *valp = sym->st_size;
02179 break;
02180
02181 case SHN_V850_ZCOMMON:
02182 *secp = bfd_make_section_old_way (abfd, ".zcommon");
02183 (*secp)->flags |= SEC_IS_COMMON;
02184 *valp = sym->st_size;
02185 break;
02186 }
02187
02188 return TRUE;
02189 }
02190
02191 static bfd_boolean
02192 v850_elf_link_output_symbol_hook (info, name, sym, input_sec, h)
02193 struct bfd_link_info *info ATTRIBUTE_UNUSED;
02194 const char *name ATTRIBUTE_UNUSED;
02195 Elf_Internal_Sym *sym;
02196 asection *input_sec;
02197 struct elf_link_hash_entry *h ATTRIBUTE_UNUSED;
02198 {
02199
02200
02201
02202
02203 if (sym->st_shndx == SHN_COMMON)
02204 {
02205 if (strcmp (input_sec->name, ".scommon") == 0)
02206 sym->st_shndx = SHN_V850_SCOMMON;
02207 else if (strcmp (input_sec->name, ".tcommon") == 0)
02208 sym->st_shndx = SHN_V850_TCOMMON;
02209 else if (strcmp (input_sec->name, ".zcommon") == 0)
02210 sym->st_shndx = SHN_V850_ZCOMMON;
02211 }
02212
02213 return TRUE;
02214 }
02215
02216 static bfd_boolean
02217 v850_elf_section_from_shdr (abfd, hdr, name)
02218 bfd *abfd;
02219 Elf_Internal_Shdr *hdr;
02220 const char *name;
02221 {
02222
02223
02224
02225
02226 if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
02227 return FALSE;
02228
02229 switch (hdr->sh_type)
02230 {
02231 case SHT_V850_SCOMMON:
02232 case SHT_V850_TCOMMON:
02233 case SHT_V850_ZCOMMON:
02234 if (! bfd_set_section_flags (abfd, hdr->bfd_section,
02235 (bfd_get_section_flags (abfd,
02236 hdr->bfd_section)
02237 | SEC_IS_COMMON)))
02238 return FALSE;
02239 }
02240
02241 return TRUE;
02242 }
02243
02244
02245
02246
02247 static bfd_boolean
02248 v850_elf_fake_sections (abfd, hdr, sec)
02249 bfd *abfd ATTRIBUTE_UNUSED;
02250 Elf_Internal_Shdr *hdr;
02251 asection *sec;
02252 {
02253 register const char * name;
02254
02255 name = bfd_get_section_name (abfd, sec);
02256
02257 if (strcmp (name, ".scommon") == 0)
02258 {
02259 hdr->sh_type = SHT_V850_SCOMMON;
02260 }
02261 else if (strcmp (name, ".tcommon") == 0)
02262 {
02263 hdr->sh_type = SHT_V850_TCOMMON;
02264 }
02265 else if (strcmp (name, ".zcommon") == 0)
02266 hdr->sh_type = SHT_V850_ZCOMMON;
02267
02268 return TRUE;
02269 }
02270
02271
02272
02273 static bfd_boolean
02274 v850_elf_relax_delete_bytes (abfd, sec, addr, toaddr, count)
02275 bfd *abfd;
02276 asection *sec;
02277 bfd_vma addr;
02278 bfd_vma toaddr;
02279 int count;
02280 {
02281 Elf_Internal_Shdr *symtab_hdr;
02282 Elf32_External_Sym *extsyms;
02283 Elf32_External_Sym *esym;
02284 Elf32_External_Sym *esymend;
02285 int index;
02286 unsigned int sec_shndx;
02287 bfd_byte *contents;
02288 Elf_Internal_Rela *irel;
02289 Elf_Internal_Rela *irelend;
02290 struct elf_link_hash_entry *sym_hash;
02291 Elf_Internal_Shdr *shndx_hdr;
02292 Elf_External_Sym_Shndx *shndx;
02293
02294 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
02295 extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
02296
02297 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
02298
02299 contents = elf_section_data (sec)->this_hdr.contents;
02300
02301
02302
02303
02304
02305 #if (DEBUG_RELAX & 2)
02306 fprintf (stderr, "relax_delete: contents: sec: %s %p .. %p %x\n",
02307 sec->name, addr, toaddr, count );
02308 #endif
02309 memmove (contents + addr, contents + addr + count,
02310 toaddr - addr - count);
02311 memset (contents + toaddr-count, 0, count);
02312
02313
02314 irel = elf_section_data (sec)->relocs;
02315 irelend = irel + sec->reloc_count;
02316 shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
02317 shndx = (Elf_External_Sym_Shndx *) shndx_hdr->contents;
02318
02319 for (; irel < irelend; irel++)
02320 {
02321 bfd_vma raddr, paddr, symval;
02322 Elf_Internal_Sym isym;
02323
02324
02325 raddr = irel->r_offset;
02326 if ((raddr >= (addr + count) && raddr < toaddr))
02327 irel->r_offset -= count;
02328
02329 if (raddr >= addr && raddr < addr + count)
02330 {
02331 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
02332 (int) R_V850_NONE);
02333 continue;
02334 }
02335
02336 if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_ALIGN)
02337 continue;
02338
02339 bfd_elf32_swap_symbol_in (abfd,
02340 extsyms + ELF32_R_SYM (irel->r_info),
02341 shndx ? shndx + ELF32_R_SYM (irel->r_info) : NULL,
02342 & isym);
02343
02344 if (isym.st_shndx != sec_shndx)
02345 continue;
02346
02347
02348 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
02349 {
02350 symval = isym.st_value;
02351 #if (DEBUG_RELAX & 2)
02352 {
02353 char * name = bfd_elf_string_from_elf_section
02354 (abfd, symtab_hdr->sh_link, isym.st_name);
02355 fprintf (stderr,
02356 "relax_delete: local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
02357 sec->name, name, isym.st_name,
02358 sec->output_section->vma, sec->output_offset,
02359 isym.st_value, irel->r_addend);
02360 }
02361 #endif
02362 }
02363 else
02364 {
02365 unsigned long indx;
02366 struct elf_link_hash_entry * h;
02367
02368
02369 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
02370
02371 h = elf_sym_hashes (abfd) [indx];
02372 BFD_ASSERT (h != NULL);
02373
02374 symval = h->root.u.def.value;
02375 #if (DEBUG_RELAX & 2)
02376 fprintf (stderr,
02377 "relax_delete: defined: sec: %s, name: %s, value: %x + %x + %x addend %x\n",
02378 sec->name, h->root.root.string, h->root.u.def.value,
02379 sec->output_section->vma, sec->output_offset, irel->r_addend);
02380 #endif
02381 }
02382
02383 paddr = symval + irel->r_addend;
02384
02385 if ( (symval >= addr + count && symval < toaddr)
02386 && (paddr < addr + count || paddr >= toaddr))
02387 irel->r_addend += count;
02388 else if ( (symval < addr + count || symval >= toaddr)
02389 && (paddr >= addr + count && paddr < toaddr))
02390 irel->r_addend -= count;
02391 }
02392
02393
02394 esym = extsyms;
02395 esymend = esym + symtab_hdr->sh_info;
02396
02397 for (; esym < esymend; esym++, shndx = (shndx ? shndx + 1 : NULL))
02398 {
02399 Elf_Internal_Sym isym;
02400
02401 bfd_elf32_swap_symbol_in (abfd, esym, shndx, & isym);
02402
02403 if (isym.st_shndx == sec_shndx
02404 && isym.st_value >= addr + count
02405 && isym.st_value < toaddr)
02406 {
02407 isym.st_value -= count;
02408
02409 if (isym.st_value + isym.st_size >= toaddr)
02410 isym.st_size += count;
02411
02412 bfd_elf32_swap_symbol_out (abfd, & isym, esym, shndx);
02413 }
02414 else if (isym.st_shndx == sec_shndx
02415 && isym.st_value < addr + count)
02416 {
02417 if (isym.st_value+isym.st_size >= addr + count
02418 && isym.st_value+isym.st_size < toaddr)
02419 isym.st_size -= count;
02420
02421 if (isym.st_value >= addr
02422 && isym.st_value < addr + count)
02423 isym.st_value = addr;
02424
02425 bfd_elf32_swap_symbol_out (abfd, & isym, esym, shndx);
02426 }
02427 }
02428
02429
02430 esym = extsyms + symtab_hdr->sh_info;
02431 esymend = extsyms + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym));
02432
02433 for (index = 0; esym < esymend; esym ++, index ++)
02434 {
02435 Elf_Internal_Sym isym;
02436
02437 bfd_elf32_swap_symbol_in (abfd, esym, shndx, & isym);
02438 sym_hash = elf_sym_hashes (abfd) [index];
02439
02440 if (isym.st_shndx == sec_shndx
02441 && ((sym_hash)->root.type == bfd_link_hash_defined
02442 || (sym_hash)->root.type == bfd_link_hash_defweak)
02443 && (sym_hash)->root.u.def.section == sec
02444 && (sym_hash)->root.u.def.value >= addr + count
02445 && (sym_hash)->root.u.def.value < toaddr)
02446 {
02447 if ((sym_hash)->root.u.def.value + isym.st_size >= toaddr)
02448 {
02449 isym.st_size += count;
02450 bfd_elf32_swap_symbol_out (abfd, & isym, esym, shndx);
02451 }
02452
02453 (sym_hash)->root.u.def.value -= count;
02454 }
02455 else if (isym.st_shndx == sec_shndx
02456 && ((sym_hash)->root.type == bfd_link_hash_defined
02457 || (sym_hash)->root.type == bfd_link_hash_defweak)
02458 && (sym_hash)->root.u.def.section == sec
02459 && (sym_hash)->root.u.def.value < addr + count)
02460 {
02461 if ((sym_hash)->root.u.def.value+isym.st_size >= addr + count
02462 && (sym_hash)->root.u.def.value+isym.st_size < toaddr)
02463 isym.st_size -= count;
02464
02465 if ((sym_hash)->root.u.def.value >= addr
02466 && (sym_hash)->root.u.def.value < addr + count)
02467 (sym_hash)->root.u.def.value = addr;
02468
02469 bfd_elf32_swap_symbol_out (abfd, & isym, esym, shndx);
02470 }
02471
02472 if (shndx)
02473 ++ shndx;
02474 }
02475
02476 return TRUE;
02477 }
02478
02479 #define NOP_OPCODE (0x0000)
02480 #define MOVHI 0x0640
02481 #define MOVHI_MASK 0x07e0
02482 #define MOVHI_R1(insn) ((insn) & 0x1f)
02483 #define MOVHI_R2(insn) ((insn) >> 11)
02484 #define MOVEA 0x0620
02485 #define MOVEA_MASK 0x07e0
02486 #define MOVEA_R1(insn) ((insn) & 0x1f)
02487 #define MOVEA_R2(insn) ((insn) >> 11)
02488 #define JARL_4 0x00040780
02489 #define JARL_4_MASK 0xFFFF07FF
02490 #define JARL_R2(insn) (int)(((insn) & (~JARL_4_MASK)) >> 11)
02491 #define ADD_I 0x0240
02492 #define ADD_I_MASK 0x07e0
02493 #define ADD_I5(insn) ((((insn) & 0x001f) << 11) >> 11)
02494 #define ADD_R2(insn) ((insn) >> 11)
02495 #define JMP_R 0x0060
02496 #define JMP_R_MASK 0xFFE0
02497 #define JMP_R1(insn) ((insn) & 0x1f)
02498
02499 static bfd_boolean
02500 v850_elf_relax_section (abfd, sec, link_info, again)
02501 bfd *abfd;
02502 asection *sec;
02503 struct bfd_link_info *link_info;
02504 bfd_boolean *again;
02505 {
02506 Elf_Internal_Shdr *symtab_hdr;
02507 Elf_Internal_Rela *internal_relocs;
02508 Elf_Internal_Rela *irel;
02509 Elf_Internal_Rela *irelend;
02510 Elf_Internal_Rela *irelalign = NULL;
02511 Elf_Internal_Sym *isymbuf = NULL;
02512 bfd_byte *contents = NULL;
02513 bfd_vma addr = 0;
02514 bfd_vma toaddr;
02515 int align_pad_size = 0;
02516 bfd_boolean result = TRUE;
02517
02518 *again = FALSE;
02519
02520 if (link_info->relocatable
02521 || (sec->flags & SEC_RELOC) == 0
02522 || sec->reloc_count == 0)
02523 return TRUE;
02524
02525 symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
02526
02527 internal_relocs = (_bfd_elf_link_read_relocs
02528 (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
02529 link_info->keep_memory));
02530 if (internal_relocs == NULL)
02531 goto error_return;
02532
02533 irelend = internal_relocs + sec->reloc_count;
02534
02535 while (addr < sec->size)
02536 {
02537 toaddr = sec->size;
02538
02539 for (irel = internal_relocs; irel < irelend; irel ++)
02540 if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_ALIGN
02541 && irel->r_offset > addr
02542 && irel->r_offset < toaddr)
02543 toaddr = irel->r_offset;
02544
02545 #ifdef DEBUG_RELAX
02546 fprintf (stderr, "relax region 0x%x to 0x%x align pad %d\n",
02547 addr, toaddr, align_pad_size);
02548 #endif
02549 if (irelalign)
02550 {
02551 bfd_vma alignto;
02552 bfd_vma alignmoveto;
02553
02554 alignmoveto = BFD_ALIGN (addr - align_pad_size, 1 << irelalign->r_addend);
02555 alignto = BFD_ALIGN (addr, 1 << irelalign->r_addend);
02556
02557 if (alignmoveto < alignto)
02558 {
02559 unsigned int i;
02560
02561 align_pad_size = alignto - alignmoveto;
02562 #ifdef DEBUG_RELAX
02563 fprintf (stderr, "relax move region 0x%x to 0x%x delete size 0x%x\n",
02564 alignmoveto, toaddr, align_pad_size);
02565 #endif
02566 if (!v850_elf_relax_delete_bytes (abfd, sec, alignmoveto,
02567 toaddr, align_pad_size))
02568 goto error_return;
02569
02570 for (i = BFD_ALIGN (toaddr - align_pad_size, 1);
02571 (i + 1) < toaddr; i += 2)
02572 bfd_put_16 (abfd, NOP_OPCODE, contents + i);
02573
02574 addr = alignmoveto;
02575 }
02576 else
02577 align_pad_size = 0;
02578 }
02579
02580 for (irel = internal_relocs; irel < irelend; irel++)
02581 {
02582 bfd_vma laddr;
02583 bfd_vma addend;
02584 bfd_vma symval;
02585 int insn[5];
02586 int no_match = -1;
02587 Elf_Internal_Rela *hi_irelfn;
02588 Elf_Internal_Rela *lo_irelfn;
02589 Elf_Internal_Rela *irelcall;
02590 bfd_signed_vma foff;
02591
02592 if (! (irel->r_offset >= addr && irel->r_offset < toaddr
02593 && (ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGCALL
02594 || ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGJUMP)))
02595 continue;
02596
02597 #ifdef DEBUG_RELAX
02598 fprintf (stderr, "relax check r_info 0x%x r_offset 0x%x r_addend 0x%x\n",
02599 irel->r_info,
02600 irel->r_offset,
02601 irel->r_addend );
02602 #endif
02603
02604
02605 if (contents == NULL)
02606 {
02607 if (elf_section_data (sec)->this_hdr.contents != NULL)
02608 contents = elf_section_data (sec)->this_hdr.contents;
02609 else
02610 {
02611 if (!bfd_malloc_and_get_section (abfd, sec, &contents))
02612 goto error_return;
02613 }
02614 }
02615
02616
02617 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
02618 {
02619 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
02620 if (isymbuf == NULL)
02621 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
02622 symtab_hdr->sh_info, 0,
02623 NULL, NULL, NULL);
02624 if (isymbuf == NULL)
02625 goto error_return;
02626 }
02627
02628 laddr = irel->r_offset;
02629
02630 if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGCALL)
02631 {
02632
02633 if (laddr + 16 <= (bfd_vma) sec->size)
02634 {
02635 insn[0] = bfd_get_16 (abfd, contents + laddr);
02636 insn[1] = bfd_get_16 (abfd, contents + laddr + 4);
02637 insn[2] = bfd_get_32 (abfd, contents + laddr + 8);
02638 insn[3] = bfd_get_16 (abfd, contents + laddr + 12);
02639 insn[4] = bfd_get_16 (abfd, contents + laddr + 14);
02640
02641 if ((insn[0] & MOVHI_MASK) != MOVHI
02642 || MOVHI_R1 (insn[0]) != 0)
02643 no_match = 0;
02644
02645 if (no_match < 0
02646 && ((insn[1] & MOVEA_MASK) != MOVEA
02647 || MOVHI_R2 (insn[0]) != MOVEA_R1 (insn[1])))
02648 no_match = 1;
02649
02650 if (no_match < 0
02651 && (insn[2] & JARL_4_MASK) != JARL_4)
02652 no_match = 2;
02653
02654 if (no_match < 0
02655 && ((insn[3] & ADD_I_MASK) != ADD_I
02656 || ADD_I5 (insn[3]) != 4
02657 || JARL_R2 (insn[2]) != ADD_R2 (insn[3])))
02658 no_match = 3;
02659
02660 if (no_match < 0
02661 && ((insn[4] & JMP_R_MASK) != JMP_R
02662 || MOVEA_R2 (insn[1]) != JMP_R1 (insn[4])))
02663 no_match = 4;
02664 }
02665 else
02666 {
02667 ((*_bfd_error_handler)
02668 ("%s: 0x%lx: warning: R_V850_LONGCALL points to unrecognized insns",
02669 bfd_get_filename (abfd), (unsigned long) irel->r_offset));
02670
02671 continue;
02672 }
02673
02674 if (no_match >= 0)
02675 {
02676 ((*_bfd_error_handler)
02677 ("%s: 0x%lx: warning: R_V850_LONGCALL points to unrecognized insn 0x%x",
02678 bfd_get_filename (abfd), (unsigned long) irel->r_offset+no_match, insn[no_match]));
02679
02680 continue;
02681 }
02682
02683
02684
02685
02686 for (hi_irelfn = internal_relocs; hi_irelfn < irelend; hi_irelfn ++)
02687 if (hi_irelfn->r_offset == laddr + 2
02688 && ELF32_R_TYPE (hi_irelfn->r_info)
02689 == (int) R_V850_HI16_S)
02690 break;
02691
02692 for (lo_irelfn = internal_relocs; lo_irelfn < irelend; lo_irelfn ++)
02693 if (lo_irelfn->r_offset == laddr + 6
02694 && ELF32_R_TYPE (lo_irelfn->r_info)
02695 == (int) R_V850_LO16)
02696 break;
02697
02698 for (irelcall = internal_relocs; irelcall < irelend; irelcall ++)
02699 if (irelcall->r_offset == laddr + 8
02700 && ELF32_R_TYPE (irelcall->r_info)
02701 == (int) R_V850_22_PCREL)
02702 break;
02703
02704 if ( hi_irelfn == irelend
02705 || lo_irelfn == irelend
02706 || irelcall == irelend)
02707 {
02708 ((*_bfd_error_handler)
02709 ("%s: 0x%lx: warning: R_V850_LONGCALL points to unrecognized reloc",
02710 bfd_get_filename (abfd), (unsigned long) irel->r_offset ));
02711
02712 continue;
02713 }
02714
02715 if (ELF32_R_SYM (irelcall->r_info) < symtab_hdr->sh_info)
02716 {
02717 Elf_Internal_Sym * isym;
02718
02719
02720 isym = isymbuf + ELF32_R_SYM (irelcall->r_info);
02721
02722 symval = isym->st_value;
02723 }
02724 else
02725 {
02726 unsigned long indx;
02727 struct elf_link_hash_entry * h;
02728
02729
02730 indx = ELF32_R_SYM (irelcall->r_info) - symtab_hdr->sh_info;
02731 h = elf_sym_hashes (abfd)[indx];
02732 BFD_ASSERT (h != NULL);
02733
02734 if ( h->root.type != bfd_link_hash_defined
02735 && h->root.type != bfd_link_hash_defweak)
02736
02737
02738
02739 continue;
02740
02741 symval = h->root.u.def.value;
02742 }
02743
02744 if (symval + irelcall->r_addend != irelcall->r_offset + 4)
02745 {
02746 ((*_bfd_error_handler)
02747 ("%s: 0x%lx: warning: R_V850_LONGCALL points to unrecognized reloc 0x%lx",
02748 bfd_get_filename (abfd), (unsigned long) irel->r_offset, irelcall->r_offset ));
02749
02750 continue;
02751 }
02752
02753
02754 if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info)
02755 {
02756 Elf_Internal_Sym *isym;
02757 asection *sym_sec;
02758
02759
02760 isym = isymbuf + ELF32_R_SYM (hi_irelfn->r_info);
02761
02762 if (isym->st_shndx == SHN_UNDEF)
02763 sym_sec = bfd_und_section_ptr;
02764 else if (isym->st_shndx == SHN_ABS)
02765 sym_sec = bfd_abs_section_ptr;
02766 else if (isym->st_shndx == SHN_COMMON)
02767 sym_sec = bfd_com_section_ptr;
02768 else
02769 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
02770 symval = (isym->st_value
02771 + sym_sec->output_section->vma
02772 + sym_sec->output_offset);
02773 }
02774 else
02775 {
02776 unsigned long indx;
02777 struct elf_link_hash_entry *h;
02778
02779
02780 indx = ELF32_R_SYM (hi_irelfn->r_info) - symtab_hdr->sh_info;
02781 h = elf_sym_hashes (abfd)[indx];
02782 BFD_ASSERT (h != NULL);
02783
02784 if ( h->root.type != bfd_link_hash_defined
02785 && h->root.type != bfd_link_hash_defweak)
02786
02787
02788
02789 continue;
02790
02791 symval = (h->root.u.def.value
02792 + h->root.u.def.section->output_section->vma
02793 + h->root.u.def.section->output_offset);
02794 }
02795
02796 addend = irel->r_addend;
02797
02798 foff = (symval + addend
02799 - (irel->r_offset
02800 + sec->output_section->vma
02801 + sec->output_offset
02802 + 4));
02803 #ifdef DEBUG_RELAX
02804 fprintf (stderr, "relax longcall r_offset 0x%x ptr 0x%x symbol 0x%x addend 0x%x distance 0x%x\n",
02805 irel->r_offset,
02806 (irel->r_offset
02807 + sec->output_section->vma
02808 + sec->output_offset),
02809 symval, addend, foff);
02810 #endif
02811
02812 if (foff < -0x100000 || foff >= 0x100000)
02813
02814 continue;
02815
02816
02817
02818
02819
02820
02821
02822
02823 elf_section_data (sec)->relocs = internal_relocs;
02824 elf_section_data (sec)->this_hdr.contents = contents;
02825 symtab_hdr->contents = (bfd_byte *) isymbuf;
02826
02827
02828 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_22_PCREL);
02829
02830 addend = 0;
02831
02832 if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info)
02833
02834
02835
02836 bfd_put_32 (abfd,
02837 0x00000780 | (JARL_R2 (insn[2])<<11) | ((addend << 16) & 0xffff) | ((addend >> 16) & 0xf),
02838 contents + irel->r_offset);
02839 else
02840
02841
02842
02843 bfd_put_32 (abfd, 0x00000780 | (JARL_R2 (insn[2])<<11),
02844 contents + irel->r_offset);
02845
02846 hi_irelfn->r_info =
02847 ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_NONE);
02848 lo_irelfn->r_info =
02849 ELF32_R_INFO (ELF32_R_SYM (lo_irelfn->r_info), R_V850_NONE);
02850 irelcall->r_info =
02851 ELF32_R_INFO (ELF32_R_SYM (irelcall->r_info), R_V850_NONE);
02852
02853 if (! v850_elf_relax_delete_bytes (abfd, sec,
02854 irel->r_offset + 4, toaddr, 12))
02855 goto error_return;
02856
02857 align_pad_size += 12;
02858 }
02859 else if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGJUMP)
02860 {
02861
02862 if (laddr + 10 <= (bfd_vma) sec->size)
02863 {
02864 insn[0] = bfd_get_16 (abfd, contents + laddr);
02865 insn[1] = bfd_get_16 (abfd, contents + laddr + 4);
02866 insn[2] = bfd_get_16 (abfd, contents + laddr + 8);
02867
02868 if ((insn[0] & MOVHI_MASK) != MOVHI
02869 || MOVHI_R1 (insn[0]) != 0)
02870 no_match = 0;
02871
02872 if (no_match < 0
02873 && ((insn[1] & MOVEA_MASK) != MOVEA
02874 || MOVHI_R2 (insn[0]) != MOVEA_R1 (insn[1])))
02875 no_match = 1;
02876
02877 if (no_match < 0
02878 && ((insn[2] & JMP_R_MASK) != JMP_R
02879 || MOVEA_R2 (insn[1]) != JMP_R1 (insn[2])))
02880 no_match = 4;
02881 }
02882 else
02883 {
02884 ((*_bfd_error_handler)
02885 ("%s: 0x%lx: warning: R_V850_LONGJUMP points to unrecognized insns",
02886 bfd_get_filename (abfd), (unsigned long) irel->r_offset));
02887
02888 continue;
02889 }
02890
02891 if (no_match >= 0)
02892 {
02893 ((*_bfd_error_handler)
02894 ("%s: 0x%lx: warning: R_V850_LONGJUMP points to unrecognized insn 0x%x",
02895 bfd_get_filename (abfd), (unsigned long) irel->r_offset+no_match, insn[no_match]));
02896
02897 continue;
02898 }
02899
02900
02901
02902
02903 for (hi_irelfn = internal_relocs; hi_irelfn < irelend; hi_irelfn ++)
02904 if (hi_irelfn->r_offset == laddr + 2
02905 && ELF32_R_TYPE (hi_irelfn->r_info) == (int) R_V850_HI16_S)
02906 break;
02907
02908 for (lo_irelfn = internal_relocs; lo_irelfn < irelend; lo_irelfn ++)
02909 if (lo_irelfn->r_offset == laddr + 6
02910 && ELF32_R_TYPE (lo_irelfn->r_info) == (int) R_V850_LO16)
02911 break;
02912
02913 if ( hi_irelfn == irelend
02914 || lo_irelfn == irelend)
02915 {
02916 ((*_bfd_error_handler)
02917 ("%s: 0x%lx: warning: R_V850_LONGJUMP points to unrecognized reloc",
02918 bfd_get_filename (abfd), (unsigned long) irel->r_offset ));
02919
02920 continue;
02921 }
02922
02923
02924 if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info)
02925 {
02926 Elf_Internal_Sym * isym;
02927 asection * sym_sec;
02928
02929
02930 isym = isymbuf + ELF32_R_SYM (hi_irelfn->r_info);
02931
02932 if (isym->st_shndx == SHN_UNDEF)
02933 sym_sec = bfd_und_section_ptr;
02934 else if (isym->st_shndx == SHN_ABS)
02935 sym_sec = bfd_abs_section_ptr;
02936 else if (isym->st_shndx == SHN_COMMON)
02937 sym_sec = bfd_com_section_ptr;
02938 else
02939 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
02940 symval = (isym->st_value
02941 + sym_sec->output_section->vma
02942 + sym_sec->output_offset);
02943 #ifdef DEBUG_RELAX
02944 {
02945 char * name = bfd_elf_string_from_elf_section
02946 (abfd, symtab_hdr->sh_link, isym->st_name);
02947
02948 fprintf (stderr, "relax long jump local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
02949 sym_sec->name, name, isym->st_name,
02950 sym_sec->output_section->vma,
02951 sym_sec->output_offset,
02952 isym->st_value, irel->r_addend);
02953 }
02954 #endif
02955 }
02956 else
02957 {
02958 unsigned long indx;
02959 struct elf_link_hash_entry * h;
02960
02961
02962 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
02963 h = elf_sym_hashes (abfd)[indx];
02964 BFD_ASSERT (h != NULL);
02965
02966 if ( h->root.type != bfd_link_hash_defined
02967 && h->root.type != bfd_link_hash_defweak)
02968
02969
02970
02971 continue;
02972
02973 symval = (h->root.u.def.value
02974 + h->root.u.def.section->output_section->vma
02975 + h->root.u.def.section->output_offset);
02976 #ifdef DEBUG_RELAX
02977 fprintf (stderr,
02978 "relax longjump defined: sec: %s, name: %s, value: %x + %x + %x addend %x\n",
02979 sec->name, h->root.root.string, h->root.u.def.value,
02980 sec->output_section->vma, sec->output_offset, irel->r_addend);
02981 #endif
02982 }
02983
02984 addend = irel->r_addend;
02985
02986 foff = (symval + addend
02987 - (irel->r_offset
02988 + sec->output_section->vma
02989 + sec->output_offset
02990 + 4));
02991 #ifdef DEBUG_RELAX
02992 fprintf (stderr, "relax longjump r_offset 0x%x ptr 0x%x symbol 0x%x addend 0x%x distance 0x%x\n",
02993 irel->r_offset,
02994 (irel->r_offset
02995 + sec->output_section->vma
02996 + sec->output_offset),
02997 symval, addend, foff);
02998 #endif
02999 if (foff < -0x100000 || foff >= 0x100000)
03000
03001 continue;
03002
03003
03004
03005
03006
03007
03008
03009
03010 elf_section_data (sec)->relocs = internal_relocs;
03011 elf_section_data (sec)->this_hdr.contents = contents;
03012 symtab_hdr->contents = (bfd_byte *) isymbuf;
03013
03014 if (foff < -0x100 || foff >= 0x100)
03015 {
03016
03017
03018 irel->r_info =
03019 ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_22_PCREL);
03020
03021 irel->r_addend = addend;
03022 addend = 0;
03023
03024 if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info)
03025
03026
03027
03028 bfd_put_32 (abfd,
03029 0x00000780 | ((addend << 15) & 0xffff0000) | ((addend >> 17) & 0xf),
03030 contents + irel->r_offset);
03031 else
03032
03033
03034
03035 bfd_put_32 (abfd, 0x00000780, contents + irel->r_offset);
03036
03037 hi_irelfn->r_info =
03038 ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_NONE);
03039 lo_irelfn->r_info =
03040 ELF32_R_INFO (ELF32_R_SYM (lo_irelfn->r_info), R_V850_NONE);
03041 if (!v850_elf_relax_delete_bytes (abfd, sec,
03042 irel->r_offset + 4, toaddr, 6))
03043 goto error_return;
03044
03045 align_pad_size += 6;
03046 }
03047 else
03048 {
03049
03050
03051 irel->r_info =
03052 ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_9_PCREL);
03053
03054 irel->r_addend = addend;
03055 addend = 0;
03056
03057 if (ELF32_R_SYM (hi_irelfn->r_info) < symtab_hdr->sh_info)
03058
03059
03060
03061 bfd_put_16 (abfd,
03062 0x0585 | ((addend << 10) & 0xf800) | ((addend << 3) & 0x0070),
03063 contents + irel->r_offset);
03064 else
03065
03066
03067
03068 bfd_put_16 (abfd, 0x0585, contents + irel->r_offset);
03069
03070 hi_irelfn->r_info =
03071 ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_NONE);
03072 lo_irelfn->r_info =
03073 ELF32_R_INFO (ELF32_R_SYM (lo_irelfn->r_info), R_V850_NONE);
03074 if (!v850_elf_relax_delete_bytes (abfd, sec,
03075 irel->r_offset + 2, toaddr, 8))
03076 goto error_return;
03077
03078 align_pad_size += 8;
03079 }
03080 }
03081 }
03082
03083 irelalign = NULL;
03084 for (irel = internal_relocs; irel < irelend; irel++)
03085 {
03086 if (ELF32_R_TYPE (irel->r_info) == (int) R_V850_ALIGN
03087 && irel->r_offset == toaddr)
03088 {
03089 irel->r_offset -= align_pad_size;
03090
03091 if (irelalign == NULL || irelalign->r_addend > irel->r_addend)
03092 irelalign = irel;
03093 }
03094 }
03095
03096 addr = toaddr;
03097 }
03098
03099 if (!irelalign)
03100 {
03101 #ifdef DEBUG_RELAX
03102 fprintf (stderr, "relax pad %d shorten %d -> %d\n",
03103 align_pad_size,
03104 sec->size,
03105 sec->size - align_pad_size);
03106 #endif
03107 sec->size -= align_pad_size;
03108 }
03109
03110 finish:
03111 if (internal_relocs != NULL
03112 && elf_section_data (sec)->relocs != internal_relocs)
03113 free (internal_relocs);
03114
03115 if (contents != NULL
03116 && elf_section_data (sec)->this_hdr.contents != (unsigned char *) contents)
03117 free (contents);
03118
03119 if (isymbuf != NULL
03120 && symtab_hdr->contents != (bfd_byte *) isymbuf)
03121 free (isymbuf);
03122
03123 return result;
03124
03125 error_return:
03126 result = FALSE;
03127 goto finish;
03128 }
03129
03130 static struct bfd_elf_special_section const v850_elf_special_sections[]=
03131 {
03132 { ".sdata", 6, -2, SHT_PROGBITS, (SHF_ALLOC + SHF_WRITE
03133 + SHF_V850_GPREL) },
03134 { ".rosdata", 8, -2, SHT_PROGBITS, (SHF_ALLOC
03135 + SHF_V850_GPREL) },
03136 { ".sbss", 5, -2, SHT_NOBITS, (SHF_ALLOC + SHF_WRITE
03137 + SHF_V850_GPREL) },
03138 { ".scommon", 8, -2, SHT_V850_SCOMMON, (SHF_ALLOC + SHF_WRITE
03139 + SHF_V850_GPREL) },
03140 { ".tdata", 6, -2, SHT_PROGBITS, (SHF_ALLOC + SHF_WRITE
03141 + SHF_V850_EPREL) },
03142 { ".tbss", 5, -2, SHT_NOBITS, (SHF_ALLOC + SHF_WRITE
03143 + SHF_V850_EPREL) },
03144 { ".tcommon", 8, -2, SHT_V850_TCOMMON, (SHF_ALLOC + SHF_WRITE
03145 + SHF_V850_R0REL) },
03146 { ".zdata", 6, -2, SHT_PROGBITS, (SHF_ALLOC + SHF_WRITE
03147 + SHF_V850_R0REL) },
03148 { ".rozdata", 8, -2, SHT_PROGBITS, (SHF_ALLOC
03149 + SHF_V850_R0REL) },
03150 { ".zbss", 5, -2, SHT_NOBITS, (SHF_ALLOC + SHF_WRITE
03151 + SHF_V850_R0REL) },
03152 { ".zcommon", 8, -2, SHT_V850_ZCOMMON, (SHF_ALLOC + SHF_WRITE
03153 + SHF_V850_R0REL) },
03154 { ".call_table_data", 16, 0, SHT_PROGBITS, (SHF_ALLOC
03155 + SHF_WRITE) },
03156 { ".call_table_text", 16, 0, SHT_PROGBITS, (SHF_ALLOC + SHF_WRITE
03157 + SHF_EXECINSTR) },
03158 { NULL, 0, 0, 0, 0 }
03159 };
03160
03161 #define TARGET_LITTLE_SYM bfd_elf32_v850_vec
03162 #define TARGET_LITTLE_NAME "elf32-v850"
03163 #define ELF_ARCH bfd_arch_v850
03164 #define ELF_MACHINE_CODE EM_V850
03165 #define ELF_MACHINE_ALT1 EM_CYGNUS_V850
03166 #define ELF_MAXPAGESIZE 0x1000
03167
03168 #define elf_info_to_howto v850_elf_info_to_howto_rela
03169 #define elf_info_to_howto_rel v850_elf_info_to_howto_rel
03170
03171 #define elf_backend_check_relocs v850_elf_check_relocs
03172 #define elf_backend_relocate_section v850_elf_relocate_section
03173 #define elf_backend_object_p v850_elf_object_p
03174 #define elf_backend_final_write_processing v850_elf_final_write_processing
03175 #define elf_backend_section_from_bfd_section v850_elf_section_from_bfd_section
03176 #define elf_backend_symbol_processing v850_elf_symbol_processing
03177 #define elf_backend_add_symbol_hook v850_elf_add_symbol_hook
03178 #define elf_backend_link_output_symbol_hook v850_elf_link_output_symbol_hook
03179 #define elf_backend_section_from_shdr v850_elf_section_from_shdr
03180 #define elf_backend_fake_sections v850_elf_fake_sections
03181 #define elf_backend_gc_mark_hook v850_elf_gc_mark_hook
03182 #define elf_backend_gc_sweep_hook v850_elf_gc_sweep_hook
03183 #define elf_backend_special_sections v850_elf_special_sections
03184
03185 #define elf_backend_can_gc_sections 1
03186 #define elf_backend_rela_normal 1
03187
03188 #define bfd_elf32_bfd_is_local_label_name v850_elf_is_local_label_name
03189 #define bfd_elf32_bfd_reloc_type_lookup v850_elf_reloc_type_lookup
03190 #define bfd_elf32_bfd_merge_private_bfd_data v850_elf_merge_private_bfd_data
03191 #define bfd_elf32_bfd_set_private_flags v850_elf_set_private_flags
03192 #define bfd_elf32_bfd_print_private_bfd_data v850_elf_print_private_bfd_data
03193 #define bfd_elf32_bfd_relax_section v850_elf_relax_section
03194
03195 #define elf_symbol_leading_char '_'
03196
03197 #include "elf32-target.h"