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
00029
00030
00031
00032
00033 #include "bfd.h"
00034 #include "sysdep.h"
00035 #include "libbfd.h"
00036 #include "elf-bfd.h"
00037 #include "elf/mmix.h"
00038 #include "opcode/mmix.h"
00039
00040 #define MINUS_ONE (((bfd_vma) 0) - 1)
00041
00042 #define MAX_PUSHJ_STUB_SIZE (5 * 4)
00043
00044
00045 #define FATAL_DEBUG \
00046 _bfd_abort (__FILE__, __LINE__, \
00047 "Internal: Non-debugged code (test-case missing)")
00048
00049 #define BAD_CASE(x) \
00050 _bfd_abort (__FILE__, __LINE__, \
00051 "bad case for " #x)
00052
00053 struct _mmix_elf_section_data
00054 {
00055 struct bfd_elf_section_data elf;
00056 union
00057 {
00058 struct bpo_reloc_section_info *reloc;
00059 struct bpo_greg_section_info *greg;
00060 } bpo;
00061
00062 struct pushj_stub_info
00063 {
00064
00065 bfd_size_type n_pushj_relocs;
00066
00067
00068 bfd_size_type stubs_size_sum;
00069
00070
00071
00072 bfd_size_type *stub_size;
00073
00074
00075
00076
00077 bfd_size_type stub_offset;
00078 } pjs;
00079 };
00080
00081 #define mmix_elf_section_data(sec) \
00082 ((struct _mmix_elf_section_data *) elf_section_data (sec))
00083
00084
00085
00086
00087 struct bpo_reloc_section_info
00088 {
00089
00090 size_t first_base_plus_offset_reloc;
00091
00092
00093 size_t n_bpo_relocs_this_section;
00094
00095
00096 size_t bpo_index;
00097
00098
00099
00100
00101 asection *bpo_greg_section;
00102 };
00103
00104
00105
00106 struct bpo_reloc_request
00107 {
00108 bfd_vma value;
00109
00110
00111
00112 size_t regindex;
00113 size_t offset;
00114
00115
00116
00117
00118 size_t bpo_reloc_no;
00119
00120
00121
00122
00123 bfd_boolean valid;
00124 };
00125
00126
00127
00128
00129
00130
00131
00132 struct bpo_greg_section_info
00133 {
00134
00135
00136 size_t n_bpo_relocs;
00137
00138
00139
00140
00141
00142 size_t n_max_bpo_relocs;
00143
00144
00145
00146 size_t n_remaining_bpo_relocs_this_relaxation_round;
00147
00148
00149
00150
00151
00152 size_t n_allocated_bpo_gregs;
00153
00154
00155
00156 size_t *bpo_reloc_indexes;
00157
00158
00159
00160 struct bpo_reloc_request *reloc_request;
00161 };
00162
00163 static bfd_boolean mmix_elf_link_output_symbol_hook
00164 PARAMS ((struct bfd_link_info *, const char *, Elf_Internal_Sym *,
00165 asection *, struct elf_link_hash_entry *));
00166
00167 static bfd_reloc_status_type mmix_elf_reloc
00168 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00169
00170 static reloc_howto_type *bfd_elf64_bfd_reloc_type_lookup
00171 PARAMS ((bfd *, bfd_reloc_code_real_type));
00172
00173 static void mmix_info_to_howto_rela
00174 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
00175
00176 static int mmix_elf_sort_relocs PARAMS ((const PTR, const PTR));
00177
00178 static bfd_boolean mmix_elf_new_section_hook
00179 PARAMS ((bfd *, asection *));
00180
00181 static bfd_boolean mmix_elf_check_relocs
00182 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00183 const Elf_Internal_Rela *));
00184
00185 static bfd_boolean mmix_elf_check_common_relocs
00186 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00187 const Elf_Internal_Rela *));
00188
00189 static bfd_boolean mmix_elf_relocate_section
00190 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00191 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
00192
00193 static asection * mmix_elf_gc_mark_hook
00194 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
00195 struct elf_link_hash_entry *, Elf_Internal_Sym *));
00196
00197 static bfd_boolean mmix_elf_gc_sweep_hook
00198 PARAMS ((bfd *, struct bfd_link_info *, asection *,
00199 const Elf_Internal_Rela *));
00200
00201 static bfd_reloc_status_type mmix_final_link_relocate
00202 PARAMS ((reloc_howto_type *, asection *, bfd_byte *,
00203 bfd_vma, bfd_signed_vma, bfd_vma, const char *, asection *));
00204
00205 static bfd_reloc_status_type mmix_elf_perform_relocation
00206 PARAMS ((asection *, reloc_howto_type *, PTR, bfd_vma, bfd_vma));
00207
00208 static bfd_boolean mmix_elf_section_from_bfd_section
00209 PARAMS ((bfd *, asection *, int *));
00210
00211 static bfd_boolean mmix_elf_add_symbol_hook
00212 PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Sym *,
00213 const char **, flagword *, asection **, bfd_vma *));
00214
00215 static bfd_boolean mmix_elf_is_local_label_name
00216 PARAMS ((bfd *, const char *));
00217
00218 static int bpo_reloc_request_sort_fn PARAMS ((const PTR, const PTR));
00219
00220 static bfd_boolean mmix_elf_relax_section
00221 PARAMS ((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
00222 bfd_boolean *again));
00223
00224 extern bfd_boolean mmix_elf_final_link PARAMS ((bfd *, struct bfd_link_info *));
00225
00226 extern void mmix_elf_symbol_processing PARAMS ((bfd *, asymbol *));
00227
00228
00229 extern void mmix_dump_bpo_gregs
00230 PARAMS ((struct bfd_link_info *, bfd_error_handler_type));
00231
00232 static void
00233 mmix_set_relaxable_size
00234 PARAMS ((bfd *, asection *, void *));
00235
00236
00237
00238
00239 static reloc_howto_type elf_mmix_howto_table[] =
00240 {
00241
00242 HOWTO (R_MMIX_NONE,
00243 0,
00244 2,
00245 32,
00246 FALSE,
00247 0,
00248 complain_overflow_bitfield,
00249 bfd_elf_generic_reloc,
00250 "R_MMIX_NONE",
00251 FALSE,
00252 0,
00253 0,
00254 FALSE),
00255
00256
00257 HOWTO (R_MMIX_8,
00258 0,
00259 0,
00260 8,
00261 FALSE,
00262 0,
00263 complain_overflow_bitfield,
00264 bfd_elf_generic_reloc,
00265 "R_MMIX_8",
00266 FALSE,
00267 0,
00268 0xff,
00269 FALSE),
00270
00271
00272 HOWTO (R_MMIX_16,
00273 0,
00274 1,
00275 16,
00276 FALSE,
00277 0,
00278 complain_overflow_bitfield,
00279 bfd_elf_generic_reloc,
00280 "R_MMIX_16",
00281 FALSE,
00282 0,
00283 0xffff,
00284 FALSE),
00285
00286
00287 HOWTO (R_MMIX_24,
00288 0,
00289 2,
00290 24,
00291 FALSE,
00292 0,
00293 complain_overflow_bitfield,
00294 bfd_elf_generic_reloc,
00295 "R_MMIX_24",
00296 FALSE,
00297 ~0xffffff,
00298 0xffffff,
00299 FALSE),
00300
00301
00302 HOWTO (R_MMIX_32,
00303 0,
00304 2,
00305 32,
00306 FALSE,
00307 0,
00308 complain_overflow_bitfield,
00309 bfd_elf_generic_reloc,
00310 "R_MMIX_32",
00311 FALSE,
00312 0,
00313 0xffffffff,
00314 FALSE),
00315
00316
00317 HOWTO (R_MMIX_64,
00318 0,
00319 4,
00320 64,
00321 FALSE,
00322 0,
00323 complain_overflow_bitfield,
00324 bfd_elf_generic_reloc,
00325 "R_MMIX_64",
00326 FALSE,
00327 0,
00328 MINUS_ONE,
00329 FALSE),
00330
00331
00332 HOWTO (R_MMIX_PC_8,
00333 0,
00334 0,
00335 8,
00336 TRUE,
00337 0,
00338 complain_overflow_bitfield,
00339 bfd_elf_generic_reloc,
00340 "R_MMIX_PC_8",
00341 FALSE,
00342 0,
00343 0xff,
00344 TRUE),
00345
00346
00347 HOWTO (R_MMIX_PC_16,
00348 0,
00349 1,
00350 16,
00351 TRUE,
00352 0,
00353 complain_overflow_bitfield,
00354 bfd_elf_generic_reloc,
00355 "R_MMIX_PC_16",
00356 FALSE,
00357 0,
00358 0xffff,
00359 TRUE),
00360
00361
00362 HOWTO (R_MMIX_PC_24,
00363 0,
00364 2,
00365 24,
00366 TRUE,
00367 0,
00368 complain_overflow_bitfield,
00369 bfd_elf_generic_reloc,
00370 "R_MMIX_PC_24",
00371 FALSE,
00372 ~0xffffff,
00373 0xffffff,
00374 TRUE),
00375
00376
00377 HOWTO (R_MMIX_PC_32,
00378 0,
00379 2,
00380 32,
00381 TRUE,
00382 0,
00383 complain_overflow_bitfield,
00384 bfd_elf_generic_reloc,
00385 "R_MMIX_PC_32",
00386 FALSE,
00387 0,
00388 0xffffffff,
00389 TRUE),
00390
00391
00392 HOWTO (R_MMIX_PC_64,
00393 0,
00394 4,
00395 64,
00396 TRUE,
00397 0,
00398 complain_overflow_bitfield,
00399 bfd_elf_generic_reloc,
00400 "R_MMIX_PC_64",
00401 FALSE,
00402 0,
00403 MINUS_ONE,
00404 TRUE),
00405
00406
00407 HOWTO (R_MMIX_GNU_VTINHERIT,
00408 0,
00409 0,
00410 0,
00411 FALSE,
00412 0,
00413 complain_overflow_dont,
00414 NULL,
00415 "R_MMIX_GNU_VTINHERIT",
00416 FALSE,
00417 0,
00418 0,
00419 TRUE),
00420
00421
00422 HOWTO (R_MMIX_GNU_VTENTRY,
00423 0,
00424 0,
00425 0,
00426 FALSE,
00427 0,
00428 complain_overflow_dont,
00429 _bfd_elf_rel_vtable_reloc_fn,
00430 "R_MMIX_GNU_VTENTRY",
00431 FALSE,
00432 0,
00433 0,
00434 FALSE),
00435
00436
00437
00438
00439
00440 HOWTO (R_MMIX_GETA,
00441 2,
00442 2,
00443 19,
00444 TRUE,
00445 0,
00446 complain_overflow_signed,
00447 mmix_elf_reloc,
00448 "R_MMIX_GETA",
00449 FALSE,
00450 ~0x0100ffff,
00451 0x0100ffff,
00452 TRUE),
00453
00454 HOWTO (R_MMIX_GETA_1,
00455 2,
00456 2,
00457 19,
00458 TRUE,
00459 0,
00460 complain_overflow_signed,
00461 mmix_elf_reloc,
00462 "R_MMIX_GETA_1",
00463 FALSE,
00464 ~0x0100ffff,
00465 0x0100ffff,
00466 TRUE),
00467
00468 HOWTO (R_MMIX_GETA_2,
00469 2,
00470 2,
00471 19,
00472 TRUE,
00473 0,
00474 complain_overflow_signed,
00475 mmix_elf_reloc,
00476 "R_MMIX_GETA_2",
00477 FALSE,
00478 ~0x0100ffff,
00479 0x0100ffff,
00480 TRUE),
00481
00482 HOWTO (R_MMIX_GETA_3,
00483 2,
00484 2,
00485 19,
00486 TRUE,
00487 0,
00488 complain_overflow_signed,
00489 mmix_elf_reloc,
00490 "R_MMIX_GETA_3",
00491 FALSE,
00492 ~0x0100ffff,
00493 0x0100ffff,
00494 TRUE),
00495
00496
00497
00498
00499
00500 HOWTO (R_MMIX_CBRANCH,
00501 2,
00502 2,
00503 19,
00504 TRUE,
00505 0,
00506 complain_overflow_signed,
00507 mmix_elf_reloc,
00508 "R_MMIX_CBRANCH",
00509 FALSE,
00510 ~0x0100ffff,
00511 0x0100ffff,
00512 TRUE),
00513
00514 HOWTO (R_MMIX_CBRANCH_J,
00515 2,
00516 2,
00517 19,
00518 TRUE,
00519 0,
00520 complain_overflow_signed,
00521 mmix_elf_reloc,
00522 "R_MMIX_CBRANCH_J",
00523 FALSE,
00524 ~0x0100ffff,
00525 0x0100ffff,
00526 TRUE),
00527
00528 HOWTO (R_MMIX_CBRANCH_1,
00529 2,
00530 2,
00531 19,
00532 TRUE,
00533 0,
00534 complain_overflow_signed,
00535 mmix_elf_reloc,
00536 "R_MMIX_CBRANCH_1",
00537 FALSE,
00538 ~0x0100ffff,
00539 0x0100ffff,
00540 TRUE),
00541
00542 HOWTO (R_MMIX_CBRANCH_2,
00543 2,
00544 2,
00545 19,
00546 TRUE,
00547 0,
00548 complain_overflow_signed,
00549 mmix_elf_reloc,
00550 "R_MMIX_CBRANCH_2",
00551 FALSE,
00552 ~0x0100ffff,
00553 0x0100ffff,
00554 TRUE),
00555
00556 HOWTO (R_MMIX_CBRANCH_3,
00557 2,
00558 2,
00559 19,
00560 TRUE,
00561 0,
00562 complain_overflow_signed,
00563 mmix_elf_reloc,
00564 "R_MMIX_CBRANCH_3",
00565 FALSE,
00566 ~0x0100ffff,
00567 0x0100ffff,
00568 TRUE),
00569
00570
00571
00572
00573
00574
00575
00576 HOWTO (R_MMIX_PUSHJ,
00577 2,
00578 2,
00579 19,
00580 TRUE,
00581 0,
00582 complain_overflow_signed,
00583 mmix_elf_reloc,
00584 "R_MMIX_PUSHJ",
00585 FALSE,
00586 ~0x0100ffff,
00587 0x0100ffff,
00588 TRUE),
00589
00590 HOWTO (R_MMIX_PUSHJ_1,
00591 2,
00592 2,
00593 19,
00594 TRUE,
00595 0,
00596 complain_overflow_signed,
00597 mmix_elf_reloc,
00598 "R_MMIX_PUSHJ_1",
00599 FALSE,
00600 ~0x0100ffff,
00601 0x0100ffff,
00602 TRUE),
00603
00604 HOWTO (R_MMIX_PUSHJ_2,
00605 2,
00606 2,
00607 19,
00608 TRUE,
00609 0,
00610 complain_overflow_signed,
00611 mmix_elf_reloc,
00612 "R_MMIX_PUSHJ_2",
00613 FALSE,
00614 ~0x0100ffff,
00615 0x0100ffff,
00616 TRUE),
00617
00618 HOWTO (R_MMIX_PUSHJ_3,
00619 2,
00620 2,
00621 19,
00622 TRUE,
00623 0,
00624 complain_overflow_signed,
00625 mmix_elf_reloc,
00626 "R_MMIX_PUSHJ_3",
00627 FALSE,
00628 ~0x0100ffff,
00629 0x0100ffff,
00630 TRUE),
00631
00632
00633
00634
00635
00636 HOWTO (R_MMIX_JMP,
00637 2,
00638 2,
00639 27,
00640 TRUE,
00641 0,
00642 complain_overflow_signed,
00643 mmix_elf_reloc,
00644 "R_MMIX_JMP",
00645 FALSE,
00646 ~0x1ffffff,
00647 0x1ffffff,
00648 TRUE),
00649
00650 HOWTO (R_MMIX_JMP_1,
00651 2,
00652 2,
00653 27,
00654 TRUE,
00655 0,
00656 complain_overflow_signed,
00657 mmix_elf_reloc,
00658 "R_MMIX_JMP_1",
00659 FALSE,
00660 ~0x1ffffff,
00661 0x1ffffff,
00662 TRUE),
00663
00664 HOWTO (R_MMIX_JMP_2,
00665 2,
00666 2,
00667 27,
00668 TRUE,
00669 0,
00670 complain_overflow_signed,
00671 mmix_elf_reloc,
00672 "R_MMIX_JMP_2",
00673 FALSE,
00674 ~0x1ffffff,
00675 0x1ffffff,
00676 TRUE),
00677
00678 HOWTO (R_MMIX_JMP_3,
00679 2,
00680 2,
00681 27,
00682 TRUE,
00683 0,
00684 complain_overflow_signed,
00685 mmix_elf_reloc,
00686 "R_MMIX_JMP_3",
00687 FALSE,
00688 ~0x1ffffff,
00689 0x1ffffff,
00690 TRUE),
00691
00692
00693
00694
00695 HOWTO (R_MMIX_ADDR19,
00696 2,
00697 2,
00698 19,
00699 TRUE,
00700 0,
00701 complain_overflow_signed,
00702 mmix_elf_reloc,
00703 "R_MMIX_ADDR19",
00704 FALSE,
00705 ~0x0100ffff,
00706 0x0100ffff,
00707 TRUE),
00708
00709
00710 HOWTO (R_MMIX_ADDR27,
00711 2,
00712 2,
00713 27,
00714 TRUE,
00715 0,
00716 complain_overflow_signed,
00717 mmix_elf_reloc,
00718 "R_MMIX_ADDR27",
00719 FALSE,
00720 ~0x1ffffff,
00721 0x1ffffff,
00722 TRUE),
00723
00724
00725
00726 HOWTO (R_MMIX_REG_OR_BYTE,
00727 0,
00728 1,
00729 8,
00730 FALSE,
00731 0,
00732 complain_overflow_bitfield,
00733 mmix_elf_reloc,
00734 "R_MMIX_REG_OR_BYTE",
00735 FALSE,
00736 0,
00737 0xff,
00738 FALSE),
00739
00740
00741 HOWTO (R_MMIX_REG,
00742 0,
00743 1,
00744 8,
00745 FALSE,
00746 0,
00747 complain_overflow_bitfield,
00748 mmix_elf_reloc,
00749 "R_MMIX_REG",
00750 FALSE,
00751 0,
00752 0xff,
00753 FALSE),
00754
00755
00756
00757
00758 HOWTO (R_MMIX_BASE_PLUS_OFFSET,
00759 0,
00760 4,
00761 64,
00762 FALSE,
00763 0,
00764 complain_overflow_bitfield,
00765 mmix_elf_reloc,
00766 "R_MMIX_BASE_PLUS_OFFSET",
00767 FALSE,
00768 0,
00769 0xffff,
00770 FALSE),
00771
00772
00773
00774
00775
00776
00777 HOWTO (R_MMIX_LOCAL,
00778 0,
00779 0,
00780 0,
00781 FALSE,
00782 0,
00783 complain_overflow_dont,
00784 mmix_elf_reloc,
00785 "R_MMIX_LOCAL",
00786 FALSE,
00787 0,
00788 0,
00789 FALSE),
00790
00791 HOWTO (R_MMIX_PUSHJ_STUBBABLE,
00792 2,
00793 2,
00794 19,
00795 TRUE,
00796 0,
00797 complain_overflow_signed,
00798 mmix_elf_reloc,
00799 "R_MMIX_PUSHJ_STUBBABLE",
00800 FALSE,
00801 ~0x0100ffff,
00802 0x0100ffff,
00803 TRUE)
00804 };
00805
00806
00807
00808
00809 struct mmix_reloc_map
00810 {
00811 bfd_reloc_code_real_type bfd_reloc_val;
00812 enum elf_mmix_reloc_type elf_reloc_val;
00813 };
00814
00815
00816 static const struct mmix_reloc_map mmix_reloc_map[] =
00817 {
00818 {BFD_RELOC_NONE, R_MMIX_NONE},
00819 {BFD_RELOC_8, R_MMIX_8},
00820 {BFD_RELOC_16, R_MMIX_16},
00821 {BFD_RELOC_24, R_MMIX_24},
00822 {BFD_RELOC_32, R_MMIX_32},
00823 {BFD_RELOC_64, R_MMIX_64},
00824 {BFD_RELOC_8_PCREL, R_MMIX_PC_8},
00825 {BFD_RELOC_16_PCREL, R_MMIX_PC_16},
00826 {BFD_RELOC_24_PCREL, R_MMIX_PC_24},
00827 {BFD_RELOC_32_PCREL, R_MMIX_PC_32},
00828 {BFD_RELOC_64_PCREL, R_MMIX_PC_64},
00829 {BFD_RELOC_VTABLE_INHERIT, R_MMIX_GNU_VTINHERIT},
00830 {BFD_RELOC_VTABLE_ENTRY, R_MMIX_GNU_VTENTRY},
00831 {BFD_RELOC_MMIX_GETA, R_MMIX_GETA},
00832 {BFD_RELOC_MMIX_CBRANCH, R_MMIX_CBRANCH},
00833 {BFD_RELOC_MMIX_PUSHJ, R_MMIX_PUSHJ},
00834 {BFD_RELOC_MMIX_JMP, R_MMIX_JMP},
00835 {BFD_RELOC_MMIX_ADDR19, R_MMIX_ADDR19},
00836 {BFD_RELOC_MMIX_ADDR27, R_MMIX_ADDR27},
00837 {BFD_RELOC_MMIX_REG_OR_BYTE, R_MMIX_REG_OR_BYTE},
00838 {BFD_RELOC_MMIX_REG, R_MMIX_REG},
00839 {BFD_RELOC_MMIX_BASE_PLUS_OFFSET, R_MMIX_BASE_PLUS_OFFSET},
00840 {BFD_RELOC_MMIX_LOCAL, R_MMIX_LOCAL},
00841 {BFD_RELOC_MMIX_PUSHJ_STUBBABLE, R_MMIX_PUSHJ_STUBBABLE}
00842 };
00843
00844 static reloc_howto_type *
00845 bfd_elf64_bfd_reloc_type_lookup (abfd, code)
00846 bfd *abfd ATTRIBUTE_UNUSED;
00847 bfd_reloc_code_real_type code;
00848 {
00849 unsigned int i;
00850
00851 for (i = 0;
00852 i < sizeof (mmix_reloc_map) / sizeof (mmix_reloc_map[0]);
00853 i++)
00854 {
00855 if (mmix_reloc_map[i].bfd_reloc_val == code)
00856 return &elf_mmix_howto_table[mmix_reloc_map[i].elf_reloc_val];
00857 }
00858
00859 return NULL;
00860 }
00861
00862 static bfd_boolean
00863 mmix_elf_new_section_hook (abfd, sec)
00864 bfd *abfd;
00865 asection *sec;
00866 {
00867 struct _mmix_elf_section_data *sdata;
00868 bfd_size_type amt = sizeof (*sdata);
00869
00870 sdata = (struct _mmix_elf_section_data *) bfd_zalloc (abfd, amt);
00871 if (sdata == NULL)
00872 return FALSE;
00873 sec->used_by_bfd = (PTR) sdata;
00874
00875 return _bfd_elf_new_section_hook (abfd, sec);
00876 }
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926 static bfd_reloc_status_type
00927 mmix_elf_perform_relocation (isec, howto, datap, addr, value)
00928 asection *isec;
00929 reloc_howto_type *howto;
00930 PTR datap;
00931 bfd_vma addr;
00932 bfd_vma value;
00933 {
00934 bfd *abfd = isec->owner;
00935 bfd_reloc_status_type flag = bfd_reloc_ok;
00936 bfd_reloc_status_type r;
00937 int offs = 0;
00938 int reg = 255;
00939
00940
00941
00942 switch (howto->type)
00943 {
00944 case R_MMIX_GETA:
00945 offs = 0;
00946 reg = bfd_get_8 (abfd, (bfd_byte *) datap + 1);
00947
00948
00949 value += addr;
00950 break;
00951
00952 case R_MMIX_CBRANCH:
00953 {
00954 int in1 = bfd_get_16 (abfd, (bfd_byte *) datap) << 16;
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964 bfd_put_32 (abfd,
00965 (((in1 ^ ((PRED_INV_BIT | COND_INV_BIT) << 24)) & ~0xffff)
00966 | (24/4)),
00967 (bfd_byte *) datap);
00968
00969
00970 bfd_put_32 (abfd,
00971 ((GO_INSN_BYTE | IMM_OFFSET_BIT) << 24) | 0xffff00,
00972 (bfd_byte *) datap + 20);
00973
00974
00975 offs = 4;
00976
00977
00978 value += addr;
00979 }
00980 break;
00981
00982 case R_MMIX_PUSHJ_STUBBABLE:
00983
00984 if ((value & 3) == 0
00985
00986 && (r = bfd_check_overflow (complain_overflow_signed,
00987 howto->bitsize,
00988 0,
00989 bfd_arch_bits_per_address (abfd),
00990 value)) == bfd_reloc_ok)
00991 goto pcrel_mmix_reloc_fits;
00992 else
00993 {
00994 bfd_size_type size = isec->rawsize ? isec->rawsize : isec->size;
00995
00996
00997
00998
00999 bfd_byte *stubcontents
01000 = ((bfd_byte *) datap
01001 - (addr - (isec->output_section->vma + isec->output_offset))
01002 + size
01003 + mmix_elf_section_data (isec)->pjs.stub_offset);
01004 bfd_vma stubaddr;
01005
01006
01007
01008 r = mmix_elf_perform_relocation (isec,
01009 &elf_mmix_howto_table
01010 [R_MMIX_ADDR19],
01011 datap,
01012 addr,
01013 isec->output_section->vma
01014 + isec->output_offset
01015 + size
01016 + (mmix_elf_section_data (isec)
01017 ->pjs.stub_offset)
01018 - addr);
01019 if (r != bfd_reloc_ok)
01020 return r;
01021
01022 stubaddr
01023 = (isec->output_section->vma
01024 + isec->output_offset
01025 + size
01026 + mmix_elf_section_data (isec)->pjs.stub_offset);
01027
01028
01029
01030 if (bfd_check_overflow (complain_overflow_signed,
01031 elf_mmix_howto_table[R_MMIX_ADDR27].bitsize,
01032 0,
01033 bfd_arch_bits_per_address (abfd),
01034 addr + value - stubaddr) == bfd_reloc_ok)
01035 {
01036 bfd_put_32 (abfd, JMP_INSN_BYTE << 24, stubcontents);
01037 r = mmix_elf_perform_relocation (isec,
01038 &elf_mmix_howto_table
01039 [R_MMIX_ADDR27],
01040 stubcontents,
01041 stubaddr,
01042 value + addr - stubaddr);
01043 mmix_elf_section_data (isec)->pjs.stub_offset += 4;
01044
01045 if (size + mmix_elf_section_data (isec)->pjs.stub_offset
01046 > isec->size)
01047 abort ();
01048
01049 return r;
01050 }
01051 else
01052 {
01053
01054 bfd_put_32 (abfd,
01055 ((GO_INSN_BYTE | IMM_OFFSET_BIT) << 24)
01056 | 0xff00, (bfd_byte *) stubcontents + 16);
01057
01058
01059
01060 value += addr;
01061 datap = stubcontents;
01062 mmix_elf_section_data (isec)->pjs.stub_offset
01063 += MAX_PUSHJ_STUB_SIZE;
01064 }
01065 }
01066 break;
01067
01068 case R_MMIX_PUSHJ:
01069 {
01070 int inreg = bfd_get_8 (abfd, (bfd_byte *) datap + 1);
01071
01072
01073 bfd_put_32 (abfd,
01074 ((PUSHGO_INSN_BYTE | IMM_OFFSET_BIT) << 24)
01075 | (inreg << 16)
01076 | 0xff00,
01077 (bfd_byte *) datap + 16);
01078
01079
01080 value += addr;
01081 }
01082 break;
01083
01084 case R_MMIX_JMP:
01085
01086
01087
01088
01089
01090
01091
01092
01093 if (! ((value & 3) == 0
01094 && (r = bfd_check_overflow (complain_overflow_signed,
01095 howto->bitsize,
01096 0,
01097 bfd_arch_bits_per_address (abfd),
01098 value)) == bfd_reloc_ok))
01099 {
01100
01101
01102
01103 bfd_put_32 (abfd,
01104 ((GO_INSN_BYTE | IMM_OFFSET_BIT) << 24)
01105 | 0xffff00,
01106 (bfd_byte *) datap + 16);
01107
01108
01109 value += addr;
01110 break;
01111 }
01112
01113 case R_MMIX_ADDR19:
01114 case R_MMIX_ADDR27:
01115 pcrel_mmix_reloc_fits:
01116
01117 if ((value & 3) == 0
01118
01119 && (r = bfd_check_overflow (complain_overflow_signed,
01120 howto->bitsize,
01121 0,
01122 bfd_arch_bits_per_address (abfd),
01123 value)) == bfd_reloc_ok)
01124 {
01125 bfd_vma in1
01126 = bfd_get_32 (abfd, (bfd_byte *) datap);
01127 bfd_vma highbit;
01128
01129 if ((bfd_signed_vma) value < 0)
01130 {
01131 highbit = 1 << 24;
01132 value += (1 << (howto->bitsize - 1));
01133 }
01134 else
01135 highbit = 0;
01136
01137 value >>= 2;
01138
01139 bfd_put_32 (abfd,
01140 (in1 & howto->src_mask)
01141 | highbit
01142 | (value & howto->dst_mask),
01143 (bfd_byte *) datap);
01144
01145 return bfd_reloc_ok;
01146 }
01147 else
01148 return bfd_reloc_overflow;
01149
01150 case R_MMIX_BASE_PLUS_OFFSET:
01151 {
01152 struct bpo_reloc_section_info *bpodata
01153 = mmix_elf_section_data (isec)->bpo.reloc;
01154 asection *bpo_greg_section
01155 = bpodata->bpo_greg_section;
01156 struct bpo_greg_section_info *gregdata
01157 = mmix_elf_section_data (bpo_greg_section)->bpo.greg;
01158 size_t bpo_index
01159 = gregdata->bpo_reloc_indexes[bpodata->bpo_index++];
01160
01161
01162
01163
01164 if (value != gregdata->reloc_request[bpo_index].value)
01165 {
01166 (*_bfd_error_handler)
01167 (_("%s: Internal inconsistency error for value for\n\
01168 linker-allocated global register: linked: 0x%lx%08lx != relaxed: 0x%lx%08lx\n"),
01169 bfd_get_filename (isec->owner),
01170 (unsigned long) (value >> 32), (unsigned long) value,
01171 (unsigned long) (gregdata->reloc_request[bpo_index].value
01172 >> 32),
01173 (unsigned long) gregdata->reloc_request[bpo_index].value);
01174 bfd_set_error (bfd_error_bad_value);
01175 return bfd_reloc_overflow;
01176 }
01177
01178
01179
01180 bfd_put_8 (abfd,
01181 gregdata->reloc_request[bpo_index].regindex
01182 + bpo_greg_section->output_section->vma / 8,
01183 datap);
01184 bfd_put_8 (abfd,
01185 gregdata->reloc_request[bpo_index].offset,
01186 ((unsigned char *) datap) + 1);
01187 return bfd_reloc_ok;
01188 }
01189
01190 case R_MMIX_REG_OR_BYTE:
01191 case R_MMIX_REG:
01192 if (value > 255)
01193 return bfd_reloc_overflow;
01194 bfd_put_8 (abfd, value, datap);
01195 return bfd_reloc_ok;
01196
01197 default:
01198 BAD_CASE (howto->type);
01199 }
01200
01201
01202
01203
01204
01205
01206 if (value & 3)
01207 flag = bfd_reloc_overflow;
01208
01209 bfd_put_32 (abfd,
01210 (SETL_INSN_BYTE << 24) | (value & 0xffff) | (reg << 16),
01211 (bfd_byte *) datap + offs);
01212 bfd_put_32 (abfd,
01213 (INCML_INSN_BYTE << 24) | ((value >> 16) & 0xffff) | (reg << 16),
01214 (bfd_byte *) datap + offs + 4);
01215 bfd_put_32 (abfd,
01216 (INCMH_INSN_BYTE << 24) | ((value >> 32) & 0xffff) | (reg << 16),
01217 (bfd_byte *) datap + offs + 8);
01218 bfd_put_32 (abfd,
01219 (INCH_INSN_BYTE << 24) | ((value >> 48) & 0xffff) | (reg << 16),
01220 (bfd_byte *) datap + offs + 12);
01221
01222 return flag;
01223 }
01224
01225
01226
01227 static void
01228 mmix_info_to_howto_rela (abfd, cache_ptr, dst)
01229 bfd *abfd ATTRIBUTE_UNUSED;
01230 arelent *cache_ptr;
01231 Elf_Internal_Rela *dst;
01232 {
01233 unsigned int r_type;
01234
01235 r_type = ELF64_R_TYPE (dst->r_info);
01236 BFD_ASSERT (r_type < (unsigned int) R_MMIX_max);
01237 cache_ptr->howto = &elf_mmix_howto_table[r_type];
01238 }
01239
01240
01241
01242
01243
01244 static bfd_reloc_status_type
01245 mmix_elf_reloc (abfd, reloc_entry, symbol, data, input_section,
01246 output_bfd, error_message)
01247 bfd *abfd;
01248 arelent *reloc_entry;
01249 asymbol *symbol;
01250 PTR data;
01251 asection *input_section;
01252 bfd *output_bfd;
01253 char **error_message ATTRIBUTE_UNUSED;
01254 {
01255 bfd_vma relocation;
01256 bfd_reloc_status_type r;
01257 asection *reloc_target_output_section;
01258 bfd_reloc_status_type flag = bfd_reloc_ok;
01259 bfd_vma output_base = 0;
01260 bfd_vma addr;
01261
01262 r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
01263 input_section, output_bfd, error_message);
01264
01265
01266
01267 if (r != bfd_reloc_continue)
01268 return r;
01269
01270 if (bfd_is_und_section (symbol->section)
01271 && (symbol->flags & BSF_WEAK) == 0
01272 && output_bfd == (bfd *) NULL)
01273 return bfd_reloc_undefined;
01274
01275
01276 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
01277 return bfd_reloc_outofrange;
01278
01279
01280
01281
01282
01283 if (bfd_is_com_section (symbol->section))
01284 relocation = 0;
01285 else
01286 relocation = symbol->value;
01287
01288 reloc_target_output_section = bfd_get_output_section (symbol);
01289
01290
01291
01292 if (output_bfd)
01293 output_base = 0;
01294 else
01295 output_base = reloc_target_output_section->vma;
01296
01297 relocation += output_base + symbol->section->output_offset;
01298
01299
01300 addr = (reloc_entry->address + input_section->output_section->vma
01301 + input_section->output_offset);
01302 if (output_bfd != (bfd *) NULL)
01303 {
01304
01305 relocation += reloc_entry->addend;
01306
01307
01308
01309
01310 reloc_entry->addend = relocation;
01311 reloc_entry->address += input_section->output_offset;
01312 return flag;
01313 }
01314
01315 return mmix_final_link_relocate (reloc_entry->howto, input_section,
01316 data, reloc_entry->address,
01317 reloc_entry->addend, relocation,
01318 bfd_asymbol_name (symbol),
01319 reloc_target_output_section);
01320 }
01321
01322
01323
01324
01325 static bfd_boolean
01326 mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
01327 contents, relocs, local_syms, local_sections)
01328 bfd *output_bfd ATTRIBUTE_UNUSED;
01329 struct bfd_link_info *info;
01330 bfd *input_bfd;
01331 asection *input_section;
01332 bfd_byte *contents;
01333 Elf_Internal_Rela *relocs;
01334 Elf_Internal_Sym *local_syms;
01335 asection **local_sections;
01336 {
01337 Elf_Internal_Shdr *symtab_hdr;
01338 struct elf_link_hash_entry **sym_hashes;
01339 Elf_Internal_Rela *rel;
01340 Elf_Internal_Rela *relend;
01341 bfd_size_type size;
01342 size_t pjsno = 0;
01343
01344 size = input_section->rawsize ? input_section->rawsize : input_section->size;
01345 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
01346 sym_hashes = elf_sym_hashes (input_bfd);
01347 relend = relocs + input_section->reloc_count;
01348
01349
01350 if (input_section->rawsize != 0
01351 && input_section->size > input_section->rawsize)
01352 memset (contents + input_section->rawsize, 0,
01353 input_section->size - input_section->rawsize);
01354
01355 for (rel = relocs; rel < relend; rel ++)
01356 {
01357 reloc_howto_type *howto;
01358 unsigned long r_symndx;
01359 Elf_Internal_Sym *sym;
01360 asection *sec;
01361 struct elf_link_hash_entry *h;
01362 bfd_vma relocation;
01363 bfd_reloc_status_type r;
01364 const char *name = NULL;
01365 int r_type;
01366 bfd_boolean undefined_signalled = FALSE;
01367
01368 r_type = ELF64_R_TYPE (rel->r_info);
01369
01370 if (r_type == R_MMIX_GNU_VTINHERIT
01371 || r_type == R_MMIX_GNU_VTENTRY)
01372 continue;
01373
01374 r_symndx = ELF64_R_SYM (rel->r_info);
01375
01376 if (info->relocatable)
01377 {
01378
01379
01380
01381
01382 if (r_symndx < symtab_hdr->sh_info)
01383 {
01384 sym = local_syms + r_symndx;
01385
01386 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
01387 {
01388 sec = local_sections [r_symndx];
01389 rel->r_addend += sec->output_offset + sym->st_value;
01390 }
01391 }
01392
01393
01394
01395
01396
01397
01398
01399
01400 if (r_type == R_MMIX_PUSHJ_STUBBABLE)
01401 {
01402
01403
01404 if (mmix_elf_section_data (input_section)->pjs.stub_size[pjsno]
01405 != 0)
01406 {
01407 Elf_Internal_Rela relcpy;
01408
01409 if (mmix_elf_section_data (input_section)
01410 ->pjs.stub_size[pjsno] != MAX_PUSHJ_STUB_SIZE)
01411 abort ();
01412
01413
01414
01415 if (mmix_final_link_relocate (elf_mmix_howto_table
01416 + R_MMIX_ADDR19,
01417 input_section,
01418 contents,
01419 rel->r_offset,
01420 0,
01421 input_section
01422 ->output_section->vma
01423 + input_section->output_offset
01424 + size
01425 + mmix_elf_section_data (input_section)
01426 ->pjs.stub_offset,
01427 NULL, NULL) != bfd_reloc_ok)
01428 return FALSE;
01429
01430
01431
01432 bfd_put_32 (output_bfd, JMP_INSN_BYTE << 24,
01433 contents
01434 + size
01435 + mmix_elf_section_data (input_section)
01436 ->pjs.stub_offset);
01437
01438
01439
01440 rel->r_info = ELF64_R_INFO (r_symndx, R_MMIX_JMP);
01441 rel->r_offset
01442 = (size
01443 + mmix_elf_section_data (input_section)
01444 ->pjs.stub_offset);
01445
01446 mmix_elf_section_data (input_section)->pjs.stub_offset
01447 += MAX_PUSHJ_STUB_SIZE;
01448
01449
01450
01451 relcpy = *rel;
01452 memmove (rel, rel + 1, (char *) relend - (char *) rel);
01453 relend[-1] = relcpy;
01454
01455
01456
01457 rel--;
01458 }
01459
01460 pjsno++;
01461 }
01462 continue;
01463 }
01464
01465
01466 howto = elf_mmix_howto_table + ELF64_R_TYPE (rel->r_info);
01467 h = NULL;
01468 sym = NULL;
01469 sec = NULL;
01470
01471 if (r_symndx < symtab_hdr->sh_info)
01472 {
01473 sym = local_syms + r_symndx;
01474 sec = local_sections [r_symndx];
01475 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
01476
01477 name = bfd_elf_string_from_elf_section (input_bfd,
01478 symtab_hdr->sh_link,
01479 sym->st_name);
01480 if (name == NULL)
01481 name = bfd_section_name (input_bfd, sec);
01482 }
01483 else
01484 {
01485 bfd_boolean unresolved_reloc;
01486
01487 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
01488 r_symndx, symtab_hdr, sym_hashes,
01489 h, sec, relocation,
01490 unresolved_reloc, undefined_signalled);
01491 name = h->root.root.string;
01492 }
01493
01494 r = mmix_final_link_relocate (howto, input_section,
01495 contents, rel->r_offset,
01496 rel->r_addend, relocation, name, sec);
01497
01498 if (r != bfd_reloc_ok)
01499 {
01500 bfd_boolean check_ok = TRUE;
01501 const char * msg = (const char *) NULL;
01502
01503 switch (r)
01504 {
01505 case bfd_reloc_overflow:
01506 check_ok = info->callbacks->reloc_overflow
01507 (info, (h ? &h->root : NULL), name, howto->name,
01508 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
01509 break;
01510
01511 case bfd_reloc_undefined:
01512
01513 if (! undefined_signalled)
01514 check_ok = info->callbacks->undefined_symbol
01515 (info, name, input_bfd, input_section, rel->r_offset,
01516 TRUE);
01517 undefined_signalled = TRUE;
01518 break;
01519
01520 case bfd_reloc_outofrange:
01521 msg = _("internal error: out of range error");
01522 break;
01523
01524 case bfd_reloc_notsupported:
01525 msg = _("internal error: unsupported relocation error");
01526 break;
01527
01528 case bfd_reloc_dangerous:
01529 msg = _("internal error: dangerous relocation");
01530 break;
01531
01532 default:
01533 msg = _("internal error: unknown error");
01534 break;
01535 }
01536
01537 if (msg)
01538 check_ok = info->callbacks->warning
01539 (info, msg, name, input_bfd, input_section, rel->r_offset);
01540
01541 if (! check_ok)
01542 return FALSE;
01543 }
01544 }
01545
01546 return TRUE;
01547 }
01548
01549
01550
01551
01552 static bfd_reloc_status_type
01553 mmix_final_link_relocate (howto, input_section, contents,
01554 r_offset, r_addend, relocation, symname, symsec)
01555 reloc_howto_type *howto;
01556 asection *input_section;
01557 bfd_byte *contents;
01558 bfd_vma r_offset;
01559 bfd_signed_vma r_addend;
01560 bfd_vma relocation;
01561 const char *symname;
01562 asection *symsec;
01563 {
01564 bfd_reloc_status_type r = bfd_reloc_ok;
01565 bfd_vma addr
01566 = (input_section->output_section->vma
01567 + input_section->output_offset
01568 + r_offset);
01569 bfd_signed_vma srel
01570 = (bfd_signed_vma) relocation + r_addend;
01571
01572 switch (howto->type)
01573 {
01574
01575 case R_MMIX_PUSHJ_STUBBABLE:
01576 case R_MMIX_PUSHJ:
01577 case R_MMIX_CBRANCH:
01578 case R_MMIX_ADDR19:
01579 case R_MMIX_GETA:
01580 case R_MMIX_ADDR27:
01581 case R_MMIX_JMP:
01582 contents += r_offset;
01583
01584 srel -= (input_section->output_section->vma
01585 + input_section->output_offset
01586 + r_offset);
01587
01588 r = mmix_elf_perform_relocation (input_section, howto, contents,
01589 addr, srel);
01590 break;
01591
01592 case R_MMIX_BASE_PLUS_OFFSET:
01593 if (symsec == NULL)
01594 return bfd_reloc_undefined;
01595
01596
01597 if (strcmp (bfd_get_section_name (symsec->owner, symsec),
01598 MMIX_REG_CONTENTS_SECTION_NAME) == 0
01599 || strcmp (bfd_get_section_name (symsec->owner, symsec),
01600 MMIX_REG_SECTION_NAME) == 0)
01601 {
01602
01603
01604 if (symname == NULL || *symname == 0)
01605 (*_bfd_error_handler)
01606 (_("%s: base-plus-offset relocation against register symbol: (unknown) in %s"),
01607 bfd_get_filename (input_section->owner),
01608 bfd_get_section_name (symsec->owner, symsec));
01609 else
01610 (*_bfd_error_handler)
01611 (_("%s: base-plus-offset relocation against register symbol: %s in %s"),
01612 bfd_get_filename (input_section->owner), symname,
01613 bfd_get_section_name (symsec->owner, symsec));
01614 return bfd_reloc_overflow;
01615 }
01616 goto do_mmix_reloc;
01617
01618 case R_MMIX_REG_OR_BYTE:
01619 case R_MMIX_REG:
01620
01621
01622
01623
01624
01625
01626
01627 if (symsec == NULL)
01628 return bfd_reloc_undefined;
01629
01630 if (strcmp (bfd_get_section_name (symsec->owner, symsec),
01631 MMIX_REG_CONTENTS_SECTION_NAME) == 0)
01632 {
01633 if ((srel & 7) != 0 || srel < 32*8 || srel > 255*8)
01634 {
01635
01636
01637 return bfd_reloc_overflow;
01638 }
01639 srel /= 8;
01640 }
01641 else if (strcmp (bfd_get_section_name (symsec->owner, symsec),
01642 MMIX_REG_SECTION_NAME) == 0)
01643 {
01644 if (srel < 0 || srel > 255)
01645
01646
01647 return bfd_reloc_overflow;
01648 }
01649 else
01650 {
01651
01652
01653 if (symname == NULL || *symname == 0)
01654 (*_bfd_error_handler)
01655 (_("%s: register relocation against non-register symbol: (unknown) in %s"),
01656 bfd_get_filename (input_section->owner),
01657 bfd_get_section_name (symsec->owner, symsec));
01658 else
01659 (*_bfd_error_handler)
01660 (_("%s: register relocation against non-register symbol: %s in %s"),
01661 bfd_get_filename (input_section->owner), symname,
01662 bfd_get_section_name (symsec->owner, symsec));
01663
01664
01665
01666 return bfd_reloc_overflow;
01667 }
01668 do_mmix_reloc:
01669 contents += r_offset;
01670 r = mmix_elf_perform_relocation (input_section, howto, contents,
01671 addr, srel);
01672 break;
01673
01674 case R_MMIX_LOCAL:
01675
01676
01677
01678 {
01679 asection *regsec
01680 = bfd_get_section_by_name (input_section->output_section->owner,
01681 MMIX_REG_CONTENTS_SECTION_NAME);
01682 bfd_vma first_global;
01683
01684
01685
01686
01687
01688
01689 if (!bfd_is_abs_section (symsec)
01690 && !bfd_is_und_section (symsec)
01691 && strcmp (bfd_get_section_name (symsec->owner, symsec),
01692 MMIX_REG_CONTENTS_SECTION_NAME) != 0
01693 && strcmp (bfd_get_section_name (symsec->owner, symsec),
01694 MMIX_REG_SECTION_NAME) != 0)
01695 {
01696 (*_bfd_error_handler)
01697 (_("%s: directive LOCAL valid only with a register or absolute value"),
01698 bfd_get_filename (input_section->owner));
01699
01700 return bfd_reloc_overflow;
01701 }
01702
01703
01704
01705 if (regsec == NULL)
01706 first_global = 255;
01707 else
01708 {
01709 first_global = bfd_get_section_vma (abfd, regsec) / 8;
01710 if (strcmp (bfd_get_section_name (symsec->owner, symsec),
01711 MMIX_REG_CONTENTS_SECTION_NAME) == 0)
01712 {
01713 if ((srel & 7) != 0 || srel < 32*8 || srel > 255*8)
01714
01715
01716 return bfd_reloc_overflow;
01717 srel /= 8;
01718 }
01719 }
01720
01721 if ((bfd_vma) srel >= first_global)
01722 {
01723
01724 (*_bfd_error_handler)
01725 (_("%s: LOCAL directive: Register $%ld is not a local register. First global register is $%ld."),
01726 bfd_get_filename (input_section->owner), (long) srel, (long) first_global);
01727
01728 return bfd_reloc_overflow;
01729 }
01730 }
01731 r = bfd_reloc_ok;
01732 break;
01733
01734 default:
01735 r = _bfd_final_link_relocate (howto, input_section->owner, input_section,
01736 contents, r_offset,
01737 relocation, r_addend);
01738 }
01739
01740 return r;
01741 }
01742
01743
01744
01745
01746 static asection *
01747 mmix_elf_gc_mark_hook (sec, info, rel, h, sym)
01748 asection *sec;
01749 struct bfd_link_info *info ATTRIBUTE_UNUSED;
01750 Elf_Internal_Rela *rel;
01751 struct elf_link_hash_entry *h;
01752 Elf_Internal_Sym *sym;
01753 {
01754 if (h != NULL)
01755 {
01756 switch (ELF64_R_TYPE (rel->r_info))
01757 {
01758 case R_MMIX_GNU_VTINHERIT:
01759 case R_MMIX_GNU_VTENTRY:
01760 break;
01761
01762 default:
01763 switch (h->root.type)
01764 {
01765 case bfd_link_hash_defined:
01766 case bfd_link_hash_defweak:
01767 return h->root.u.def.section;
01768
01769 case bfd_link_hash_common:
01770 return h->root.u.c.p->section;
01771
01772 default:
01773 break;
01774 }
01775 }
01776 }
01777 else
01778 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
01779
01780 return NULL;
01781 }
01782
01783
01784
01785
01786
01787
01788 static bfd_boolean
01789 mmix_elf_gc_sweep_hook (abfd, info, sec, relocs)
01790 bfd *abfd ATTRIBUTE_UNUSED;
01791 struct bfd_link_info *info ATTRIBUTE_UNUSED;
01792 asection *sec ATTRIBUTE_UNUSED;
01793 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
01794 {
01795 struct bpo_reloc_section_info *bpodata
01796 = mmix_elf_section_data (sec)->bpo.reloc;
01797 asection *allocated_gregs_section;
01798
01799
01800 if (bpodata == NULL)
01801 return TRUE;
01802
01803 allocated_gregs_section = bpodata->bpo_greg_section;
01804
01805 mmix_elf_section_data (allocated_gregs_section)->bpo.greg->n_bpo_relocs
01806 -= bpodata->n_bpo_relocs_this_section;
01807
01808 return TRUE;
01809 }
01810
01811
01812
01813 static int
01814 mmix_elf_sort_relocs (p1, p2)
01815 const PTR p1;
01816 const PTR p2;
01817 {
01818 const Elf_Internal_Rela *r1 = (const Elf_Internal_Rela *) p1;
01819 const Elf_Internal_Rela *r2 = (const Elf_Internal_Rela *) p2;
01820 int r1_is_reg, r2_is_reg;
01821
01822
01823
01824 if ((r1->r_offset & ~(bfd_vma) 3) > (r2->r_offset & ~(bfd_vma) 3))
01825 return 1;
01826 else if ((r1->r_offset & ~(bfd_vma) 3) < (r2->r_offset & ~(bfd_vma) 3))
01827 return -1;
01828
01829 r1_is_reg
01830 = (ELF64_R_TYPE (r1->r_info) == R_MMIX_REG_OR_BYTE
01831 || ELF64_R_TYPE (r1->r_info) == R_MMIX_REG);
01832 r2_is_reg
01833 = (ELF64_R_TYPE (r2->r_info) == R_MMIX_REG_OR_BYTE
01834 || ELF64_R_TYPE (r2->r_info) == R_MMIX_REG);
01835 if (r1_is_reg != r2_is_reg)
01836 return r2_is_reg - r1_is_reg;
01837
01838
01839 if (r1->r_offset > r2->r_offset)
01840 return 1;
01841 else if (r1->r_offset < r2->r_offset)
01842 return -1;
01843 return 0;
01844 }
01845
01846
01847
01848 static bfd_boolean
01849 mmix_elf_check_common_relocs (abfd, info, sec, relocs)
01850 bfd *abfd;
01851 struct bfd_link_info *info;
01852 asection *sec;
01853 const Elf_Internal_Rela *relocs;
01854 {
01855 bfd *bpo_greg_owner = NULL;
01856 asection *allocated_gregs_section = NULL;
01857 struct bpo_greg_section_info *gregdata = NULL;
01858 struct bpo_reloc_section_info *bpodata = NULL;
01859 const Elf_Internal_Rela *rel;
01860 const Elf_Internal_Rela *rel_end;
01861
01862
01863
01864
01865
01866 bpo_greg_owner = (bfd *) info->base_file;
01867
01868 rel_end = relocs + sec->reloc_count;
01869 for (rel = relocs; rel < rel_end; rel++)
01870 {
01871 switch (ELF64_R_TYPE (rel->r_info))
01872 {
01873
01874
01875
01876
01877
01878 case R_MMIX_BASE_PLUS_OFFSET:
01879
01880 if (info->relocatable)
01881 break;
01882
01883 if (bpo_greg_owner == NULL)
01884 {
01885 bpo_greg_owner = abfd;
01886 info->base_file = (PTR) bpo_greg_owner;
01887 }
01888
01889 if (allocated_gregs_section == NULL)
01890 allocated_gregs_section
01891 = bfd_get_section_by_name (bpo_greg_owner,
01892 MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
01893
01894 if (allocated_gregs_section == NULL)
01895 {
01896 allocated_gregs_section
01897 = bfd_make_section (bpo_greg_owner,
01898 MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
01899
01900
01901
01902
01903
01904 if (allocated_gregs_section == NULL
01905 || !bfd_set_section_flags (bpo_greg_owner,
01906 allocated_gregs_section,
01907 (SEC_HAS_CONTENTS
01908 | SEC_IN_MEMORY
01909 | SEC_LINKER_CREATED))
01910 || !bfd_set_section_alignment (bpo_greg_owner,
01911 allocated_gregs_section,
01912 3))
01913 return FALSE;
01914
01915 gregdata = (struct bpo_greg_section_info *)
01916 bfd_zalloc (bpo_greg_owner, sizeof (struct bpo_greg_section_info));
01917 if (gregdata == NULL)
01918 return FALSE;
01919 mmix_elf_section_data (allocated_gregs_section)->bpo.greg
01920 = gregdata;
01921 }
01922 else if (gregdata == NULL)
01923 gregdata
01924 = mmix_elf_section_data (allocated_gregs_section)->bpo.greg;
01925
01926
01927 if (bpodata == NULL)
01928 {
01929
01930
01931 bpodata = (struct bpo_reloc_section_info *)
01932 bfd_alloc (bpo_greg_owner,
01933 sizeof (struct bpo_reloc_section_info)
01934 * (sec->reloc_count + 1));
01935 if (bpodata == NULL)
01936 return FALSE;
01937 mmix_elf_section_data (sec)->bpo.reloc = bpodata;
01938 bpodata->first_base_plus_offset_reloc
01939 = bpodata->bpo_index
01940 = gregdata->n_max_bpo_relocs;
01941 bpodata->bpo_greg_section
01942 = allocated_gregs_section;
01943 bpodata->n_bpo_relocs_this_section = 0;
01944 }
01945
01946 bpodata->n_bpo_relocs_this_section++;
01947 gregdata->n_max_bpo_relocs++;
01948
01949
01950
01951 gregdata->n_bpo_relocs
01952 = gregdata->n_max_bpo_relocs;
01953 break;
01954
01955 case R_MMIX_PUSHJ_STUBBABLE:
01956 mmix_elf_section_data (sec)->pjs.n_pushj_relocs++;
01957 break;
01958 }
01959 }
01960
01961
01962
01963 if (mmix_elf_section_data (sec)->pjs.n_pushj_relocs != 0)
01964 {
01965 size_t i;
01966
01967 mmix_elf_section_data (sec)->pjs.stub_size
01968 = bfd_alloc (abfd, mmix_elf_section_data (sec)->pjs.n_pushj_relocs
01969 * sizeof (mmix_elf_section_data (sec)
01970 ->pjs.stub_size[0]));
01971 if (mmix_elf_section_data (sec)->pjs.stub_size == NULL)
01972 return FALSE;
01973
01974 for (i = 0; i < mmix_elf_section_data (sec)->pjs.n_pushj_relocs; i++)
01975 mmix_elf_section_data (sec)->pjs.stub_size[i] = MAX_PUSHJ_STUB_SIZE;
01976 }
01977
01978 return TRUE;
01979 }
01980
01981
01982
01983 static bfd_boolean
01984 mmix_elf_check_relocs (abfd, info, sec, relocs)
01985 bfd *abfd;
01986 struct bfd_link_info *info;
01987 asection *sec;
01988 const Elf_Internal_Rela *relocs;
01989 {
01990 Elf_Internal_Shdr *symtab_hdr;
01991 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
01992 const Elf_Internal_Rela *rel;
01993 const Elf_Internal_Rela *rel_end;
01994
01995 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
01996 sym_hashes = elf_sym_hashes (abfd);
01997 sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf64_External_Sym);
01998 if (!elf_bad_symtab (abfd))
01999 sym_hashes_end -= symtab_hdr->sh_info;
02000
02001
02002
02003 qsort ((PTR) relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
02004 mmix_elf_sort_relocs);
02005
02006
02007 if (!mmix_elf_check_common_relocs (abfd, info, sec, relocs))
02008 return FALSE;
02009
02010 if (info->relocatable)
02011 return TRUE;
02012
02013 rel_end = relocs + sec->reloc_count;
02014 for (rel = relocs; rel < rel_end; rel++)
02015 {
02016 struct elf_link_hash_entry *h;
02017 unsigned long r_symndx;
02018
02019 r_symndx = ELF64_R_SYM (rel->r_info);
02020 if (r_symndx < symtab_hdr->sh_info)
02021 h = NULL;
02022 else
02023 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
02024
02025 switch (ELF64_R_TYPE (rel->r_info))
02026 {
02027
02028
02029 case R_MMIX_GNU_VTINHERIT:
02030 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
02031 return FALSE;
02032 break;
02033
02034
02035
02036 case R_MMIX_GNU_VTENTRY:
02037 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
02038 return FALSE;
02039 break;
02040 }
02041 }
02042
02043 return TRUE;
02044 }
02045
02046
02047
02048
02049 bfd_boolean
02050 _bfd_mmix_check_all_relocs (abfd, info)
02051 bfd *abfd;
02052 struct bfd_link_info *info;
02053 {
02054 asection *o;
02055
02056 for (o = abfd->sections; o != NULL; o = o->next)
02057 {
02058 Elf_Internal_Rela *internal_relocs;
02059 bfd_boolean ok;
02060
02061 if ((o->flags & SEC_RELOC) == 0
02062 || o->reloc_count == 0
02063 || ((info->strip == strip_all || info->strip == strip_debugger)
02064 && (o->flags & SEC_DEBUGGING) != 0)
02065 || bfd_is_abs_section (o->output_section))
02066 continue;
02067
02068 internal_relocs
02069 = _bfd_elf_link_read_relocs (abfd, o, (PTR) NULL,
02070 (Elf_Internal_Rela *) NULL,
02071 info->keep_memory);
02072 if (internal_relocs == NULL)
02073 return FALSE;
02074
02075 ok = mmix_elf_check_common_relocs (abfd, info, o, internal_relocs);
02076
02077 if (! info->keep_memory)
02078 free (internal_relocs);
02079
02080 if (! ok)
02081 return FALSE;
02082 }
02083
02084 return TRUE;
02085 }
02086
02087
02088
02089
02090
02091 static bfd_boolean
02092 mmix_elf_link_output_symbol_hook (info, name, sym, input_sec, h)
02093 struct bfd_link_info *info ATTRIBUTE_UNUSED;
02094 const char *name ATTRIBUTE_UNUSED;
02095 Elf_Internal_Sym *sym;
02096 asection *input_sec;
02097 struct elf_link_hash_entry *h ATTRIBUTE_UNUSED;
02098 {
02099 if (input_sec != NULL
02100 && input_sec->name != NULL
02101 && ELF_ST_TYPE (sym->st_info) != STT_SECTION
02102 && strcmp (input_sec->name, MMIX_REG_CONTENTS_SECTION_NAME) == 0)
02103 {
02104 sym->st_value /= 8;
02105 sym->st_shndx = SHN_REGISTER;
02106 }
02107
02108 return TRUE;
02109 }
02110
02111
02112
02113
02114
02115 static asection mmix_elf_reg_section;
02116 static asymbol mmix_elf_reg_section_symbol;
02117 static asymbol *mmix_elf_reg_section_symbol_ptr;
02118
02119
02120
02121 void
02122 mmix_elf_symbol_processing (abfd, asym)
02123 bfd *abfd ATTRIBUTE_UNUSED;
02124 asymbol *asym;
02125 {
02126 elf_symbol_type *elfsym;
02127
02128 elfsym = (elf_symbol_type *) asym;
02129 switch (elfsym->internal_elf_sym.st_shndx)
02130 {
02131 case SHN_REGISTER:
02132 if (mmix_elf_reg_section.name == NULL)
02133 {
02134
02135 mmix_elf_reg_section.name = MMIX_REG_SECTION_NAME;
02136 mmix_elf_reg_section.flags = SEC_NO_FLAGS;
02137 mmix_elf_reg_section.output_section = &mmix_elf_reg_section;
02138 mmix_elf_reg_section.symbol = &mmix_elf_reg_section_symbol;
02139 mmix_elf_reg_section.symbol_ptr_ptr = &mmix_elf_reg_section_symbol_ptr;
02140 mmix_elf_reg_section_symbol.name = MMIX_REG_SECTION_NAME;
02141 mmix_elf_reg_section_symbol.flags = BSF_SECTION_SYM;
02142 mmix_elf_reg_section_symbol.section = &mmix_elf_reg_section;
02143 mmix_elf_reg_section_symbol_ptr = &mmix_elf_reg_section_symbol;
02144 }
02145 asym->section = &mmix_elf_reg_section;
02146 break;
02147
02148 default:
02149 break;
02150 }
02151 }
02152
02153
02154
02155
02156 static bfd_boolean
02157 mmix_elf_section_from_bfd_section (abfd, sec, retval)
02158 bfd * abfd ATTRIBUTE_UNUSED;
02159 asection * sec;
02160 int * retval;
02161 {
02162 if (strcmp (bfd_get_section_name (abfd, sec), MMIX_REG_SECTION_NAME) == 0)
02163 *retval = SHN_REGISTER;
02164 else
02165 return FALSE;
02166
02167 return TRUE;
02168 }
02169
02170
02171
02172
02173
02174
02175
02176
02177 bfd_boolean
02178 mmix_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
02179 bfd *abfd;
02180 struct bfd_link_info *info ATTRIBUTE_UNUSED;
02181 Elf_Internal_Sym *sym;
02182 const char **namep ATTRIBUTE_UNUSED;
02183 flagword *flagsp ATTRIBUTE_UNUSED;
02184 asection **secp;
02185 bfd_vma *valp ATTRIBUTE_UNUSED;
02186 {
02187 if (sym->st_shndx == SHN_REGISTER)
02188 *secp = bfd_make_section_old_way (abfd, MMIX_REG_SECTION_NAME);
02189 else if ((*namep)[0] == '_' && (*namep)[1] == '_' && (*namep)[2] == '.'
02190 && strncmp (*namep, MMIX_LOC_SECTION_START_SYMBOL_PREFIX,
02191 strlen (MMIX_LOC_SECTION_START_SYMBOL_PREFIX)) == 0)
02192 {
02193
02194 struct bfd_link_hash_entry *h = bfd_link_hash_lookup (info->hash,
02195 *namep,
02196 FALSE,
02197 FALSE,
02198 FALSE);
02199
02200 if (h != NULL && h->type != bfd_link_hash_undefined)
02201 {
02202
02203
02204 ((*_bfd_error_handler)
02205 (_("%s: Error: multiple definition of `%s'; start of %s is set in a earlier linked file\n"),
02206 bfd_get_filename (abfd), *namep,
02207 *namep + strlen (MMIX_LOC_SECTION_START_SYMBOL_PREFIX)));
02208 bfd_set_error (bfd_error_bad_value);
02209 return FALSE;
02210 }
02211 }
02212
02213 return TRUE;
02214 }
02215
02216
02217
02218 bfd_boolean
02219 mmix_elf_is_local_label_name (abfd, name)
02220 bfd *abfd;
02221 const char *name;
02222 {
02223 const char *colpos;
02224 int digits;
02225
02226
02227 if (_bfd_elf_is_local_label_name (abfd, name))
02228 return TRUE;
02229
02230 if (*name != 'L')
02231 return FALSE;
02232
02233
02234 colpos = strchr (name, ':');
02235 if (colpos == NULL || strchr (colpos + 1, ':') != NULL)
02236 return FALSE;
02237
02238
02239 if (colpos[1] == 0)
02240 return FALSE;
02241
02242 digits = strspn (colpos + 1, "0123456789");
02243 return digits != 0 && colpos[1 + digits] == 0;
02244 }
02245
02246
02247
02248 bfd_boolean
02249 mmix_elf_final_link (abfd, info)
02250 bfd *abfd;
02251 struct bfd_link_info *info;
02252 {
02253
02254
02255 asection *reg_section;
02256 asection **secpp;
02257
02258 reg_section = bfd_get_section_by_name (abfd, MMIX_REG_SECTION_NAME);
02259
02260 if (reg_section != NULL)
02261 {
02262
02263 if (bfd_get_section_flags (abfd, reg_section) & SEC_HAS_CONTENTS)
02264 _bfd_abort (__FILE__, __LINE__, _("Register section has contents\n"));
02265
02266
02267 for (secpp = &abfd->sections;
02268 *secpp != reg_section;
02269 secpp = &(*secpp)->next)
02270 ;
02271 bfd_section_list_remove (abfd, secpp);
02272 --abfd->section_count;
02273 }
02274
02275 if (! bfd_elf_final_link (abfd, info))
02276 return FALSE;
02277
02278
02279
02280
02281 if (info->base_file != NULL)
02282 {
02283 asection *greg_section
02284 = bfd_get_section_by_name ((bfd *) info->base_file,
02285 MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
02286 if (!bfd_set_section_contents (abfd,
02287 greg_section->output_section,
02288 greg_section->contents,
02289 (file_ptr) greg_section->output_offset,
02290 greg_section->size))
02291 return FALSE;
02292 }
02293 return TRUE;
02294 }
02295
02296
02297
02298
02299 static void
02300 mmix_set_relaxable_size (abfd, sec, ptr)
02301 bfd *abfd ATTRIBUTE_UNUSED;
02302 asection *sec;
02303 void *ptr;
02304 {
02305 struct bfd_link_info *info = ptr;
02306
02307
02308
02309 if (mmix_elf_section_data (sec)->pjs.n_pushj_relocs == 0)
02310 return;
02311
02312 sec->rawsize = sec->size;
02313 sec->size += (mmix_elf_section_data (sec)->pjs.n_pushj_relocs
02314 * MAX_PUSHJ_STUB_SIZE);
02315
02316
02317
02318 if (info->relocatable && sec->output_section)
02319 mmix_elf_section_data (sec->output_section)->pjs.stubs_size_sum
02320 += (mmix_elf_section_data (sec)->pjs.n_pushj_relocs
02321 * MAX_PUSHJ_STUB_SIZE);
02322 }
02323
02324
02325
02326
02327 bfd_boolean
02328 _bfd_mmix_before_linker_allocation (abfd, info)
02329 bfd *abfd ATTRIBUTE_UNUSED;
02330 struct bfd_link_info *info;
02331 {
02332 asection *bpo_gregs_section;
02333 bfd *bpo_greg_owner;
02334 struct bpo_greg_section_info *gregdata;
02335 size_t n_gregs;
02336 bfd_vma gregs_size;
02337 size_t i;
02338 size_t *bpo_reloc_indexes;
02339 bfd *ibfd;
02340
02341
02342 for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
02343 bfd_map_over_sections (ibfd, mmix_set_relaxable_size, info);
02344
02345
02346
02347
02348 bpo_greg_owner = (bfd *) info->base_file;
02349 if (bpo_greg_owner == NULL)
02350 return TRUE;
02351
02352 bpo_gregs_section
02353 = bfd_get_section_by_name (bpo_greg_owner,
02354 MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
02355
02356 if (bpo_gregs_section == NULL)
02357 return TRUE;
02358
02359
02360 gregdata = mmix_elf_section_data (bpo_gregs_section)->bpo.greg;
02361 if (gregdata == NULL)
02362 return FALSE;
02363
02364 n_gregs = gregdata->n_bpo_relocs;
02365 gregdata->n_allocated_bpo_gregs = n_gregs;
02366
02367
02368
02369 gregdata->n_remaining_bpo_relocs_this_relaxation_round = n_gregs;
02370
02371
02372 gregs_size = n_gregs * 8;
02373
02374 if (!bfd_set_section_size (bpo_greg_owner, bpo_gregs_section, gregs_size))
02375 return FALSE;
02376
02377
02378
02379
02380 gregdata->reloc_request
02381 = bfd_zalloc (bpo_greg_owner,
02382 sizeof (struct bpo_reloc_request)
02383 * gregdata->n_max_bpo_relocs);
02384
02385 gregdata->bpo_reloc_indexes
02386 = bpo_reloc_indexes
02387 = bfd_alloc (bpo_greg_owner,
02388 gregdata->n_max_bpo_relocs
02389 * sizeof (size_t));
02390 if (bpo_reloc_indexes == NULL)
02391 return FALSE;
02392
02393
02394 for (i = 0; i < gregdata->n_max_bpo_relocs; i++)
02395 {
02396 bpo_reloc_indexes[i] = i;
02397 gregdata->reloc_request[i].bpo_reloc_no = i;
02398 }
02399
02400 return TRUE;
02401 }
02402
02403
02404
02405
02406 bfd_boolean
02407 _bfd_mmix_after_linker_allocation (abfd, link_info)
02408 bfd *abfd ATTRIBUTE_UNUSED;
02409 struct bfd_link_info *link_info;
02410 {
02411 asection *bpo_gregs_section;
02412 bfd *bpo_greg_owner;
02413 struct bpo_greg_section_info *gregdata;
02414 size_t n_gregs;
02415 size_t i, j;
02416 size_t lastreg;
02417 bfd_byte *contents;
02418
02419
02420
02421
02422 bpo_greg_owner = (bfd *) link_info->base_file;
02423 if (bpo_greg_owner == NULL)
02424 return TRUE;
02425
02426 bpo_gregs_section
02427 = bfd_get_section_by_name (bpo_greg_owner,
02428 MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
02429
02430
02431
02432
02433 if (bpo_gregs_section == NULL)
02434 return TRUE;
02435
02436
02437
02438 gregdata = mmix_elf_section_data (bpo_gregs_section)->bpo.greg;
02439 if (gregdata == NULL)
02440 return FALSE;
02441
02442 n_gregs = gregdata->n_allocated_bpo_gregs;
02443
02444 bpo_gregs_section->contents
02445 = contents = bfd_alloc (bpo_greg_owner, bpo_gregs_section->size);
02446 if (contents == NULL)
02447 return FALSE;
02448
02449
02450
02451
02452
02453 if (gregdata->n_remaining_bpo_relocs_this_relaxation_round
02454 != gregdata->n_bpo_relocs)
02455 {
02456 (*_bfd_error_handler)
02457 (_("Internal inconsistency: remaining %u != max %u.\n\
02458 Please report this bug."),
02459 gregdata->n_remaining_bpo_relocs_this_relaxation_round,
02460 gregdata->n_bpo_relocs);
02461 return FALSE;
02462 }
02463
02464 for (lastreg = 255, i = 0, j = 0; j < n_gregs; i++)
02465 if (gregdata->reloc_request[i].regindex != lastreg)
02466 {
02467 bfd_put_64 (bpo_greg_owner, gregdata->reloc_request[i].value,
02468 contents + j * 8);
02469 lastreg = gregdata->reloc_request[i].regindex;
02470 j++;
02471 }
02472
02473 return TRUE;
02474 }
02475
02476
02477
02478
02479 static int
02480 bpo_reloc_request_sort_fn (p1, p2)
02481 const PTR p1;
02482 const PTR p2;
02483 {
02484 const struct bpo_reloc_request *r1 = (const struct bpo_reloc_request *) p1;
02485 const struct bpo_reloc_request *r2 = (const struct bpo_reloc_request *) p2;
02486
02487
02488
02489 if (r1->valid != r2->valid)
02490 return r2->valid - r1->valid;
02491
02492
02493
02494
02495 if (r1->value != r2->value)
02496 return r1->value > r2->value ? 1 : -1;
02497
02498
02499
02500
02501
02502 return r1->bpo_reloc_no > r2->bpo_reloc_no
02503 ? 1 : (r1->bpo_reloc_no < r2->bpo_reloc_no ? -1 : 0);
02504 }
02505
02506
02507
02508
02509 void
02510 mmix_dump_bpo_gregs (link_info, pf)
02511 struct bfd_link_info *link_info;
02512 bfd_error_handler_type pf;
02513 {
02514 bfd *bpo_greg_owner;
02515 asection *bpo_gregs_section;
02516 struct bpo_greg_section_info *gregdata;
02517 unsigned int i;
02518
02519 if (link_info == NULL || link_info->base_file == NULL)
02520 return;
02521
02522 bpo_greg_owner = (bfd *) link_info->base_file;
02523
02524 bpo_gregs_section
02525 = bfd_get_section_by_name (bpo_greg_owner,
02526 MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
02527
02528 if (bpo_gregs_section == NULL)
02529 return;
02530
02531 gregdata = mmix_elf_section_data (bpo_gregs_section)->bpo.greg;
02532 if (gregdata == NULL)
02533 return;
02534
02535 if (pf == NULL)
02536 pf = _bfd_error_handler;
02537
02538
02539
02540
02541 (*pf) (" n_bpo_relocs: %u\n n_max_bpo_relocs: %u\n n_remain...round: %u\n\
02542 n_allocated_bpo_gregs: %u\n", gregdata->n_bpo_relocs,
02543 gregdata->n_max_bpo_relocs,
02544 gregdata->n_remaining_bpo_relocs_this_relaxation_round,
02545 gregdata->n_allocated_bpo_gregs);
02546
02547 if (gregdata->reloc_request)
02548 for (i = 0; i < gregdata->n_max_bpo_relocs; i++)
02549 (*pf) ("%4u (%4u)/%4u#%u: 0x%08lx%08lx r: %3u o: %3u\n",
02550 i,
02551 (gregdata->bpo_reloc_indexes != NULL
02552 ? gregdata->bpo_reloc_indexes[i] : (size_t) -1),
02553 gregdata->reloc_request[i].bpo_reloc_no,
02554 gregdata->reloc_request[i].valid,
02555
02556 (unsigned long) (gregdata->reloc_request[i].value >> 32),
02557 (unsigned long) gregdata->reloc_request[i].value,
02558 gregdata->reloc_request[i].regindex,
02559 gregdata->reloc_request[i].offset);
02560 }
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572 static bfd_boolean
02573 mmix_elf_relax_section (abfd, sec, link_info, again)
02574 bfd *abfd;
02575 asection *sec;
02576 struct bfd_link_info *link_info;
02577 bfd_boolean *again;
02578 {
02579 Elf_Internal_Shdr *symtab_hdr;
02580 Elf_Internal_Rela *internal_relocs;
02581 Elf_Internal_Rela *irel, *irelend;
02582 asection *bpo_gregs_section = NULL;
02583 struct bpo_greg_section_info *gregdata;
02584 struct bpo_reloc_section_info *bpodata
02585 = mmix_elf_section_data (sec)->bpo.reloc;
02586
02587
02588 size_t bpono = (size_t) -1;
02589 size_t pjsno = 0;
02590 bfd *bpo_greg_owner;
02591 Elf_Internal_Sym *isymbuf = NULL;
02592 bfd_size_type size = sec->rawsize ? sec->rawsize : sec->size;
02593
02594 mmix_elf_section_data (sec)->pjs.stubs_size_sum = 0;
02595
02596
02597 *again = FALSE;
02598
02599
02600
02601 if ((sec->flags & SEC_RELOC) == 0
02602 || sec->reloc_count == 0
02603 || (sec->flags & SEC_CODE) == 0
02604 || (sec->flags & SEC_LINKER_CREATED) != 0
02605
02606
02607 || (bpodata == NULL
02608 && mmix_elf_section_data (sec)->pjs.n_pushj_relocs == 0))
02609 return TRUE;
02610
02611 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
02612
02613 bpo_greg_owner = (bfd *) link_info->base_file;
02614
02615 if (bpodata != NULL)
02616 {
02617 bpo_gregs_section = bpodata->bpo_greg_section;
02618 gregdata = mmix_elf_section_data (bpo_gregs_section)->bpo.greg;
02619 bpono = bpodata->first_base_plus_offset_reloc;
02620 }
02621 else
02622 gregdata = NULL;
02623
02624
02625 internal_relocs
02626 = _bfd_elf_link_read_relocs (abfd, sec, (PTR) NULL,
02627 (Elf_Internal_Rela *) NULL,
02628 link_info->keep_memory);
02629 if (internal_relocs == NULL)
02630 goto error_return;
02631
02632
02633 irelend = internal_relocs + sec->reloc_count;
02634 for (irel = internal_relocs; irel < irelend; irel++)
02635 {
02636 bfd_vma symval;
02637 struct elf_link_hash_entry *h = NULL;
02638
02639
02640 if (ELF64_R_TYPE (irel->r_info) != (int) R_MMIX_BASE_PLUS_OFFSET
02641 && ELF64_R_TYPE (irel->r_info) != (int) R_MMIX_PUSHJ_STUBBABLE)
02642 continue;
02643
02644
02645
02646
02647 if (link_info->relocatable)
02648 {
02649
02650
02651
02652
02653
02654
02655 if (ELF64_R_TYPE (irel->r_info) == R_MMIX_PUSHJ_STUBBABLE)
02656 {
02657
02658
02659
02660
02661
02662
02663
02664
02665 if (bfd_check_overflow (complain_overflow_signed,
02666 19,
02667 0,
02668 bfd_arch_bits_per_address (abfd),
02669
02670 sec->output_section->rawsize
02671 + (mmix_elf_section_data (sec
02672 ->output_section)
02673 ->pjs.stubs_size_sum)
02674
02675 - (sec->output_offset + irel->r_offset)
02676
02677 - (mmix_elf_section_data (sec)
02678 ->pjs.stub_size[pjsno]
02679 + MAX_PUSHJ_STUB_SIZE))
02680 == bfd_reloc_ok)
02681 mmix_elf_section_data (sec)->pjs.stub_size[pjsno] = 0;
02682
02683 mmix_elf_section_data (sec)->pjs.stubs_size_sum
02684 += mmix_elf_section_data (sec)->pjs.stub_size[pjsno];
02685
02686 pjsno++;
02687 }
02688
02689 continue;
02690 }
02691
02692
02693 if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
02694 {
02695
02696 Elf_Internal_Sym *isym;
02697 asection *sym_sec;
02698
02699
02700 if (isymbuf == NULL)
02701 {
02702 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
02703 if (isymbuf == NULL)
02704 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
02705 symtab_hdr->sh_info, 0,
02706 NULL, NULL, NULL);
02707 if (isymbuf == 0)
02708 goto error_return;
02709 }
02710
02711 isym = isymbuf + ELF64_R_SYM (irel->r_info);
02712 if (isym->st_shndx == SHN_UNDEF)
02713 sym_sec = bfd_und_section_ptr;
02714 else if (isym->st_shndx == SHN_ABS)
02715 sym_sec = bfd_abs_section_ptr;
02716 else if (isym->st_shndx == SHN_COMMON)
02717 sym_sec = bfd_com_section_ptr;
02718 else
02719 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
02720 symval = (isym->st_value
02721 + sym_sec->output_section->vma
02722 + sym_sec->output_offset);
02723 }
02724 else
02725 {
02726 unsigned long indx;
02727
02728
02729 indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info;
02730 h = elf_sym_hashes (abfd)[indx];
02731 BFD_ASSERT (h != NULL);
02732 if (h->root.type != bfd_link_hash_defined
02733 && h->root.type != bfd_link_hash_defweak)
02734 {
02735
02736
02737
02738
02739 if (ELF64_R_TYPE (irel->r_info) == R_MMIX_BASE_PLUS_OFFSET
02740 && gregdata != NULL)
02741 {
02742 gregdata->n_remaining_bpo_relocs_this_relaxation_round--;
02743 bpono++;
02744 }
02745 continue;
02746 }
02747
02748 symval = (h->root.u.def.value
02749 + h->root.u.def.section->output_section->vma
02750 + h->root.u.def.section->output_offset);
02751 }
02752
02753 if (ELF64_R_TYPE (irel->r_info) == (int) R_MMIX_PUSHJ_STUBBABLE)
02754 {
02755 bfd_vma value = symval + irel->r_addend;
02756 bfd_vma dot
02757 = (sec->output_section->vma
02758 + sec->output_offset
02759 + irel->r_offset);
02760 bfd_vma stubaddr
02761 = (sec->output_section->vma
02762 + sec->output_offset
02763 + size
02764 + mmix_elf_section_data (sec)->pjs.stubs_size_sum);
02765
02766 if ((value & 3) == 0
02767 && bfd_check_overflow (complain_overflow_signed,
02768 19,
02769 0,
02770 bfd_arch_bits_per_address (abfd),
02771 value - dot
02772 - (value > dot
02773 ? mmix_elf_section_data (sec)
02774 ->pjs.stub_size[pjsno]
02775 : 0))
02776 == bfd_reloc_ok)
02777
02778 mmix_elf_section_data (sec)->pjs.stub_size[pjsno] = 0;
02779 else
02780
02781 if ((value & 3) == 0
02782 && bfd_check_overflow (complain_overflow_signed,
02783 27,
02784 0,
02785 bfd_arch_bits_per_address (abfd),
02786 value - stubaddr
02787 - (value > dot
02788 ? mmix_elf_section_data (sec)
02789 ->pjs.stub_size[pjsno] - 4
02790 : 0))
02791 == bfd_reloc_ok)
02792
02793 mmix_elf_section_data (sec)->pjs.stub_size[pjsno] = 4;
02794 else
02795
02796
02797
02798 mmix_elf_section_data (sec)->pjs.stub_size[pjsno]
02799 = MAX_PUSHJ_STUB_SIZE;
02800
02801 mmix_elf_section_data (sec)->pjs.stubs_size_sum
02802 += mmix_elf_section_data (sec)->pjs.stub_size[pjsno];
02803 pjsno++;
02804 continue;
02805 }
02806
02807
02808
02809 gregdata->reloc_request[gregdata->bpo_reloc_indexes[bpono]].value
02810 = symval + irel->r_addend;
02811 gregdata->reloc_request[gregdata->bpo_reloc_indexes[bpono++]].valid = TRUE;
02812 gregdata->n_remaining_bpo_relocs_this_relaxation_round--;
02813 }
02814
02815
02816
02817
02818
02819 if (gregdata != NULL
02820 && gregdata->n_remaining_bpo_relocs_this_relaxation_round == 0)
02821 {
02822 size_t i;
02823 bfd_vma prev_base;
02824 size_t regindex;
02825
02826
02827 gregdata->n_remaining_bpo_relocs_this_relaxation_round
02828 = gregdata->n_bpo_relocs;
02829
02830 qsort ((PTR) gregdata->reloc_request,
02831 gregdata->n_max_bpo_relocs,
02832 sizeof (struct bpo_reloc_request),
02833 bpo_reloc_request_sort_fn);
02834
02835
02836
02837
02838
02839 for (i = 0; i < gregdata->n_max_bpo_relocs; i++)
02840 if (gregdata->bpo_reloc_indexes[gregdata->reloc_request[i].bpo_reloc_no]
02841 != i)
02842 {
02843 gregdata->bpo_reloc_indexes[gregdata->reloc_request[i].bpo_reloc_no]
02844 = i;
02845 *again = TRUE;
02846 }
02847
02848
02849
02850 for (i = 0, regindex = 0, prev_base = gregdata->reloc_request[0].value;
02851 i < gregdata->n_bpo_relocs;
02852 i++)
02853 {
02854 if (gregdata->reloc_request[i].value > prev_base + 255)
02855 {
02856 regindex++;
02857 prev_base = gregdata->reloc_request[i].value;
02858 }
02859 gregdata->reloc_request[i].regindex = regindex;
02860 gregdata->reloc_request[i].offset
02861 = gregdata->reloc_request[i].value - prev_base;
02862 }
02863
02864
02865
02866
02867
02868 if (gregdata->n_allocated_bpo_gregs != regindex + 1)
02869 {
02870 gregdata->n_allocated_bpo_gregs = regindex + 1;
02871 *again = TRUE;
02872 }
02873
02874 bpo_gregs_section->size = (regindex + 1) * 8;
02875 }
02876
02877 if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
02878 {
02879 if (! link_info->keep_memory)
02880 free (isymbuf);
02881 else
02882 {
02883
02884 symtab_hdr->contents = (unsigned char *) isymbuf;
02885 }
02886 }
02887
02888 if (internal_relocs != NULL
02889 && elf_section_data (sec)->relocs != internal_relocs)
02890 free (internal_relocs);
02891
02892 if (sec->size < size + mmix_elf_section_data (sec)->pjs.stubs_size_sum)
02893 abort ();
02894
02895 if (sec->size > size + mmix_elf_section_data (sec)->pjs.stubs_size_sum)
02896 {
02897 sec->size = size + mmix_elf_section_data (sec)->pjs.stubs_size_sum;
02898 *again = TRUE;
02899 }
02900
02901 return TRUE;
02902
02903 error_return:
02904 if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
02905 free (isymbuf);
02906 if (internal_relocs != NULL
02907 && elf_section_data (sec)->relocs != internal_relocs)
02908 free (internal_relocs);
02909 return FALSE;
02910 }
02911
02912 #define ELF_ARCH bfd_arch_mmix
02913 #define ELF_MACHINE_CODE EM_MMIX
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927 #define ELF_MAXPAGESIZE 0x100
02928
02929 #define TARGET_BIG_SYM bfd_elf64_mmix_vec
02930 #define TARGET_BIG_NAME "elf64-mmix"
02931
02932 #define elf_info_to_howto_rel NULL
02933 #define elf_info_to_howto mmix_info_to_howto_rela
02934 #define elf_backend_relocate_section mmix_elf_relocate_section
02935 #define elf_backend_gc_mark_hook mmix_elf_gc_mark_hook
02936 #define elf_backend_gc_sweep_hook mmix_elf_gc_sweep_hook
02937
02938 #define elf_backend_link_output_symbol_hook \
02939 mmix_elf_link_output_symbol_hook
02940 #define elf_backend_add_symbol_hook mmix_elf_add_symbol_hook
02941
02942 #define elf_backend_check_relocs mmix_elf_check_relocs
02943 #define elf_backend_symbol_processing mmix_elf_symbol_processing
02944
02945 #define bfd_elf64_bfd_is_local_label_name \
02946 mmix_elf_is_local_label_name
02947
02948 #define elf_backend_may_use_rel_p 0
02949 #define elf_backend_may_use_rela_p 1
02950 #define elf_backend_default_use_rela_p 1
02951
02952 #define elf_backend_can_gc_sections 1
02953 #define elf_backend_section_from_bfd_section \
02954 mmix_elf_section_from_bfd_section
02955
02956 #define bfd_elf64_new_section_hook mmix_elf_new_section_hook
02957 #define bfd_elf64_bfd_final_link mmix_elf_final_link
02958 #define bfd_elf64_bfd_relax_section mmix_elf_relax_section
02959
02960 #include "elf64-target.h"