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 #include "bfd.h"
00030 #include "sysdep.h"
00031 #include "libbfd.h"
00032 #include "elf-bfd.h"
00033
00034 #include "elf/alpha.h"
00035
00036 #define ALPHAECOFF
00037
00038 #define NO_COFF_RELOCS
00039 #define NO_COFF_SYMBOLS
00040 #define NO_COFF_LINENOS
00041
00042
00043 #include "coff/internal.h"
00044 #include "coff/sym.h"
00045 #include "coff/symconst.h"
00046 #include "coff/ecoff.h"
00047 #include "coff/alpha.h"
00048 #include "aout/ar.h"
00049 #include "libcoff.h"
00050 #include "libecoff.h"
00051 #define ECOFF_64
00052 #include "ecoffswap.h"
00053
00054 static bfd_boolean alpha_elf_dynamic_symbol_p
00055 PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *));
00056 static struct bfd_hash_entry * elf64_alpha_link_hash_newfunc
00057 PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
00058 static struct bfd_link_hash_table * elf64_alpha_bfd_link_hash_table_create
00059 PARAMS ((bfd *));
00060
00061 static bfd_reloc_status_type elf64_alpha_reloc_nil
00062 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00063 static bfd_reloc_status_type elf64_alpha_reloc_bad
00064 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00065 static bfd_reloc_status_type elf64_alpha_do_reloc_gpdisp
00066 PARAMS ((bfd *, bfd_vma, bfd_byte *, bfd_byte *));
00067 static bfd_reloc_status_type elf64_alpha_reloc_gpdisp
00068 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00069
00070 static reloc_howto_type * elf64_alpha_bfd_reloc_type_lookup
00071 PARAMS ((bfd *, bfd_reloc_code_real_type));
00072 static void elf64_alpha_info_to_howto
00073 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
00074
00075 static bfd_boolean elf64_alpha_mkobject
00076 PARAMS ((bfd *));
00077 static bfd_boolean elf64_alpha_object_p
00078 PARAMS ((bfd *));
00079 static bfd_boolean elf64_alpha_section_from_shdr
00080 PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
00081 static bfd_boolean elf64_alpha_section_flags
00082 PARAMS ((flagword *, const Elf_Internal_Shdr *));
00083 static bfd_boolean elf64_alpha_fake_sections
00084 PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
00085 static bfd_boolean elf64_alpha_create_got_section
00086 PARAMS ((bfd *, struct bfd_link_info *));
00087 static bfd_boolean elf64_alpha_create_dynamic_sections
00088 PARAMS ((bfd *, struct bfd_link_info *));
00089
00090 static bfd_boolean elf64_alpha_read_ecoff_info
00091 PARAMS ((bfd *, asection *, struct ecoff_debug_info *));
00092 static bfd_boolean elf64_alpha_is_local_label_name
00093 PARAMS ((bfd *, const char *));
00094 static bfd_boolean elf64_alpha_find_nearest_line
00095 PARAMS ((bfd *, asection *, asymbol **, bfd_vma, const char **,
00096 const char **, unsigned int *));
00097
00098 #if defined(__STDC__) || defined(ALMOST_STDC)
00099 struct alpha_elf_link_hash_entry;
00100 #endif
00101
00102 static bfd_boolean elf64_alpha_output_extsym
00103 PARAMS ((struct alpha_elf_link_hash_entry *, PTR));
00104
00105 static bfd_boolean elf64_alpha_can_merge_gots
00106 PARAMS ((bfd *, bfd *));
00107 static void elf64_alpha_merge_gots
00108 PARAMS ((bfd *, bfd *));
00109 static bfd_boolean elf64_alpha_calc_got_offsets_for_symbol
00110 PARAMS ((struct alpha_elf_link_hash_entry *, PTR));
00111 static void elf64_alpha_calc_got_offsets
00112 PARAMS ((struct bfd_link_info *));
00113 static bfd_boolean elf64_alpha_size_got_sections
00114 PARAMS ((struct bfd_link_info *));
00115 static bfd_boolean elf64_alpha_size_plt_section
00116 PARAMS ((struct bfd_link_info *));
00117 static bfd_boolean elf64_alpha_size_plt_section_1
00118 PARAMS ((struct alpha_elf_link_hash_entry *, PTR));
00119 static bfd_boolean elf64_alpha_always_size_sections
00120 PARAMS ((bfd *, struct bfd_link_info *));
00121 static int alpha_dynamic_entries_for_reloc
00122 PARAMS ((int, int, int));
00123 static bfd_boolean elf64_alpha_calc_dynrel_sizes
00124 PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *));
00125 static bfd_boolean elf64_alpha_size_rela_got_section
00126 PARAMS ((struct bfd_link_info *));
00127 static bfd_boolean elf64_alpha_size_rela_got_1
00128 PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *));
00129 static bfd_boolean elf64_alpha_add_symbol_hook
00130 PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Sym *,
00131 const char **, flagword *, asection **, bfd_vma *));
00132 static struct alpha_elf_got_entry *get_got_entry
00133 PARAMS ((bfd *, struct alpha_elf_link_hash_entry *, unsigned long,
00134 unsigned long, bfd_vma));
00135 static bfd_boolean elf64_alpha_check_relocs
00136 PARAMS ((bfd *, struct bfd_link_info *, asection *sec,
00137 const Elf_Internal_Rela *));
00138 static bfd_boolean elf64_alpha_adjust_dynamic_symbol
00139 PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
00140 static bfd_boolean elf64_alpha_size_dynamic_sections
00141 PARAMS ((bfd *, struct bfd_link_info *));
00142 static void elf64_alpha_emit_dynrel
00143 PARAMS ((bfd *, struct bfd_link_info *, asection *, asection *,
00144 bfd_vma, long, long, bfd_vma));
00145 static bfd_boolean elf64_alpha_relocate_section_r
00146 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00147 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
00148 static bfd_boolean elf64_alpha_relocate_section
00149 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00150 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
00151 static bfd_boolean elf64_alpha_finish_dynamic_symbol
00152 PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
00153 Elf_Internal_Sym *));
00154 static bfd_boolean elf64_alpha_finish_dynamic_sections
00155 PARAMS ((bfd *, struct bfd_link_info *));
00156 static bfd_boolean elf64_alpha_final_link
00157 PARAMS ((bfd *, struct bfd_link_info *));
00158 static bfd_boolean elf64_alpha_merge_ind_symbols
00159 PARAMS ((struct alpha_elf_link_hash_entry *, PTR));
00160 static Elf_Internal_Rela * elf64_alpha_find_reloc_at_ofs
00161 PARAMS ((Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_vma, int));
00162 static enum elf_reloc_type_class elf64_alpha_reloc_type_class
00163 PARAMS ((const Elf_Internal_Rela *));
00164
00165 struct alpha_elf_link_hash_entry
00166 {
00167 struct elf_link_hash_entry root;
00168
00169
00170 EXTR esym;
00171
00172
00173 int flags;
00174
00175
00176 #define ALPHA_ELF_LINK_HASH_LU_ADDR 0x01
00177 #define ALPHA_ELF_LINK_HASH_LU_MEM 0x02
00178 #define ALPHA_ELF_LINK_HASH_LU_BYTE 0x04
00179 #define ALPHA_ELF_LINK_HASH_LU_JSR 0x08
00180 #define ALPHA_ELF_LINK_HASH_LU_TLSGD 0x10
00181 #define ALPHA_ELF_LINK_HASH_LU_TLSLDM 0x20
00182 #define ALPHA_ELF_LINK_HASH_LU_FUNC 0x38
00183 #define ALPHA_ELF_LINK_HASH_TLS_IE 0x40
00184 #define ALPHA_ELF_LINK_HASH_PLT_LOC 0x80
00185
00186
00187 asection *plt_old_section;
00188 bfd_vma plt_old_value;
00189
00190
00191 struct alpha_elf_got_entry
00192 {
00193 struct alpha_elf_got_entry *next;
00194
00195
00196 bfd *gotobj;
00197
00198
00199 bfd_vma addend;
00200
00201
00202 int got_offset;
00203
00204
00205 int use_count;
00206
00207
00208 unsigned char reloc_type;
00209
00210
00211 unsigned char flags;
00212
00213
00214 unsigned char reloc_done;
00215
00216
00217 unsigned char reloc_xlated;
00218 } *got_entries;
00219
00220
00221
00222 struct alpha_elf_reloc_entry
00223 {
00224 struct alpha_elf_reloc_entry *next;
00225
00226
00227 asection *srel;
00228
00229
00230 unsigned int rtype;
00231
00232
00233 unsigned int reltext : 1;
00234
00235
00236 unsigned long count;
00237 } *reloc_entries;
00238 };
00239
00240
00241
00242 struct alpha_elf_link_hash_table
00243 {
00244 struct elf_link_hash_table root;
00245
00246
00247
00248 bfd *got_list;
00249 };
00250
00251
00252
00253 #define alpha_elf_link_hash_lookup(table, string, create, copy, follow) \
00254 ((struct alpha_elf_link_hash_entry *) \
00255 elf_link_hash_lookup (&(table)->root, (string), (create), \
00256 (copy), (follow)))
00257
00258
00259
00260 #define alpha_elf_link_hash_traverse(table, func, info) \
00261 (elf_link_hash_traverse \
00262 (&(table)->root, \
00263 (bfd_boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
00264 (info)))
00265
00266
00267
00268 #define alpha_elf_hash_table(p) \
00269 ((struct alpha_elf_link_hash_table *) ((p)->hash))
00270
00271
00272
00273 #define alpha_elf_sym_hashes(abfd) \
00274 ((struct alpha_elf_link_hash_entry **)elf_sym_hashes(abfd))
00275
00276
00277
00278
00279
00280
00281 static inline bfd_boolean
00282 alpha_elf_dynamic_symbol_p (h, info)
00283 struct elf_link_hash_entry *h;
00284 struct bfd_link_info *info;
00285 {
00286 return _bfd_elf_dynamic_symbol_p (h, info, 0);
00287 }
00288
00289
00290
00291 static struct bfd_hash_entry *
00292 elf64_alpha_link_hash_newfunc (entry, table, string)
00293 struct bfd_hash_entry *entry;
00294 struct bfd_hash_table *table;
00295 const char *string;
00296 {
00297 struct alpha_elf_link_hash_entry *ret =
00298 (struct alpha_elf_link_hash_entry *) entry;
00299
00300
00301
00302 if (ret == (struct alpha_elf_link_hash_entry *) NULL)
00303 ret = ((struct alpha_elf_link_hash_entry *)
00304 bfd_hash_allocate (table,
00305 sizeof (struct alpha_elf_link_hash_entry)));
00306 if (ret == (struct alpha_elf_link_hash_entry *) NULL)
00307 return (struct bfd_hash_entry *) ret;
00308
00309
00310 ret = ((struct alpha_elf_link_hash_entry *)
00311 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
00312 table, string));
00313 if (ret != (struct alpha_elf_link_hash_entry *) NULL)
00314 {
00315
00316 memset (&ret->esym, 0, sizeof (EXTR));
00317
00318
00319 ret->esym.ifd = -2;
00320 ret->flags = 0;
00321 ret->got_entries = NULL;
00322 ret->reloc_entries = NULL;
00323 }
00324
00325 return (struct bfd_hash_entry *) ret;
00326 }
00327
00328
00329
00330 static struct bfd_link_hash_table *
00331 elf64_alpha_bfd_link_hash_table_create (abfd)
00332 bfd *abfd;
00333 {
00334 struct alpha_elf_link_hash_table *ret;
00335 bfd_size_type amt = sizeof (struct alpha_elf_link_hash_table);
00336
00337 ret = (struct alpha_elf_link_hash_table *) bfd_zmalloc (amt);
00338 if (ret == (struct alpha_elf_link_hash_table *) NULL)
00339 return NULL;
00340
00341 if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
00342 elf64_alpha_link_hash_newfunc))
00343 {
00344 free (ret);
00345 return NULL;
00346 }
00347
00348 return &ret->root.root;
00349 }
00350
00351
00352
00353 struct alpha_elf_obj_tdata
00354 {
00355 struct elf_obj_tdata root;
00356
00357
00358
00359 struct alpha_elf_got_entry ** local_got_entries;
00360
00361
00362
00363 bfd *gotobj;
00364
00365
00366 bfd *in_got_link_next;
00367
00368
00369 bfd *got_link_next;
00370
00371
00372 asection *got;
00373
00374
00375 int total_got_size;
00376
00377
00378
00379 int local_got_size;
00380 };
00381
00382 #define alpha_elf_tdata(abfd) \
00383 ((struct alpha_elf_obj_tdata *) (abfd)->tdata.any)
00384
00385 static bfd_boolean
00386 elf64_alpha_mkobject (abfd)
00387 bfd *abfd;
00388 {
00389 bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata);
00390 abfd->tdata.any = bfd_zalloc (abfd, amt);
00391 if (abfd->tdata.any == NULL)
00392 return FALSE;
00393 return TRUE;
00394 }
00395
00396 static bfd_boolean
00397 elf64_alpha_object_p (abfd)
00398 bfd *abfd;
00399 {
00400
00401 return bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0);
00402 }
00403
00404
00405
00406 #define MINUS_ONE (((bfd_vma)0) - 1)
00407
00408 #define SKIP_HOWTO(N) \
00409 HOWTO(N, 0, 0, 0, 0, 0, 0, elf64_alpha_reloc_bad, 0, 0, 0, 0, 0)
00410
00411 static reloc_howto_type elf64_alpha_howto_table[] =
00412 {
00413 HOWTO (R_ALPHA_NONE,
00414 0,
00415 0,
00416 8,
00417 TRUE,
00418 0,
00419 complain_overflow_dont,
00420 elf64_alpha_reloc_nil,
00421 "NONE",
00422 FALSE,
00423 0,
00424 0,
00425 TRUE),
00426
00427
00428 HOWTO (R_ALPHA_REFLONG,
00429 0,
00430 2,
00431 32,
00432 FALSE,
00433 0,
00434 complain_overflow_bitfield,
00435 0,
00436 "REFLONG",
00437 FALSE,
00438 0xffffffff,
00439 0xffffffff,
00440 FALSE),
00441
00442
00443 HOWTO (R_ALPHA_REFQUAD,
00444 0,
00445 4,
00446 64,
00447 FALSE,
00448 0,
00449 complain_overflow_bitfield,
00450 0,
00451 "REFQUAD",
00452 FALSE,
00453 MINUS_ONE,
00454 MINUS_ONE,
00455 FALSE),
00456
00457
00458
00459
00460 HOWTO (R_ALPHA_GPREL32,
00461 0,
00462 2,
00463 32,
00464 FALSE,
00465 0,
00466 complain_overflow_bitfield,
00467 0,
00468 "GPREL32",
00469 FALSE,
00470 0xffffffff,
00471 0xffffffff,
00472 FALSE),
00473
00474
00475 HOWTO (R_ALPHA_LITERAL,
00476 0,
00477 1,
00478 16,
00479 FALSE,
00480 0,
00481 complain_overflow_signed,
00482 0,
00483 "ELF_LITERAL",
00484 FALSE,
00485 0xffff,
00486 0xffff,
00487 FALSE),
00488
00489
00490
00491
00492
00493
00494
00495
00496 HOWTO (R_ALPHA_LITUSE,
00497 0,
00498 1,
00499 32,
00500 FALSE,
00501 0,
00502 complain_overflow_dont,
00503 elf64_alpha_reloc_nil,
00504 "LITUSE",
00505 FALSE,
00506 0,
00507 0,
00508 FALSE),
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 HOWTO (R_ALPHA_GPDISP,
00527 16,
00528 2,
00529 16,
00530 FALSE,
00531 0,
00532 complain_overflow_dont,
00533 elf64_alpha_reloc_gpdisp,
00534 "GPDISP",
00535 FALSE,
00536 0xffff,
00537 0xffff,
00538 TRUE),
00539
00540
00541 HOWTO (R_ALPHA_BRADDR,
00542 2,
00543 2,
00544 21,
00545 TRUE,
00546 0,
00547 complain_overflow_signed,
00548 0,
00549 "BRADDR",
00550 FALSE,
00551 0x1fffff,
00552 0x1fffff,
00553 TRUE),
00554
00555
00556 HOWTO (R_ALPHA_HINT,
00557 2,
00558 1,
00559 14,
00560 TRUE,
00561 0,
00562 complain_overflow_dont,
00563 0,
00564 "HINT",
00565 FALSE,
00566 0x3fff,
00567 0x3fff,
00568 TRUE),
00569
00570
00571 HOWTO (R_ALPHA_SREL16,
00572 0,
00573 1,
00574 16,
00575 TRUE,
00576 0,
00577 complain_overflow_signed,
00578 0,
00579 "SREL16",
00580 FALSE,
00581 0xffff,
00582 0xffff,
00583 TRUE),
00584
00585
00586 HOWTO (R_ALPHA_SREL32,
00587 0,
00588 2,
00589 32,
00590 TRUE,
00591 0,
00592 complain_overflow_signed,
00593 0,
00594 "SREL32",
00595 FALSE,
00596 0xffffffff,
00597 0xffffffff,
00598 TRUE),
00599
00600
00601 HOWTO (R_ALPHA_SREL64,
00602 0,
00603 4,
00604 64,
00605 TRUE,
00606 0,
00607 complain_overflow_signed,
00608 0,
00609 "SREL64",
00610 FALSE,
00611 MINUS_ONE,
00612 MINUS_ONE,
00613 TRUE),
00614
00615
00616 SKIP_HOWTO (12),
00617 SKIP_HOWTO (13),
00618 SKIP_HOWTO (14),
00619 SKIP_HOWTO (15),
00620 SKIP_HOWTO (16),
00621
00622
00623 HOWTO (R_ALPHA_GPRELHIGH,
00624 0,
00625 1,
00626 16,
00627 FALSE,
00628 0,
00629 complain_overflow_signed,
00630 0,
00631 "GPRELHIGH",
00632 FALSE,
00633 0xffff,
00634 0xffff,
00635 FALSE),
00636
00637
00638 HOWTO (R_ALPHA_GPRELLOW,
00639 0,
00640 1,
00641 16,
00642 FALSE,
00643 0,
00644 complain_overflow_dont,
00645 0,
00646 "GPRELLOW",
00647 FALSE,
00648 0xffff,
00649 0xffff,
00650 FALSE),
00651
00652
00653 HOWTO (R_ALPHA_GPREL16,
00654 0,
00655 1,
00656 16,
00657 FALSE,
00658 0,
00659 complain_overflow_signed,
00660 0,
00661 "GPREL16",
00662 FALSE,
00663 0xffff,
00664 0xffff,
00665 FALSE),
00666
00667
00668 SKIP_HOWTO (20),
00669 SKIP_HOWTO (21),
00670 SKIP_HOWTO (22),
00671 SKIP_HOWTO (23),
00672
00673
00674
00675
00676
00677
00678
00679 HOWTO (R_ALPHA_COPY,
00680 0,
00681 0,
00682 0,
00683 FALSE,
00684 0,
00685 complain_overflow_dont,
00686 bfd_elf_generic_reloc,
00687 "COPY",
00688 FALSE,
00689 0,
00690 0,
00691 TRUE),
00692
00693
00694 HOWTO (R_ALPHA_GLOB_DAT,
00695 0,
00696 0,
00697 0,
00698 FALSE,
00699 0,
00700 complain_overflow_dont,
00701 bfd_elf_generic_reloc,
00702 "GLOB_DAT",
00703 FALSE,
00704 0,
00705 0,
00706 TRUE),
00707
00708
00709 HOWTO (R_ALPHA_JMP_SLOT,
00710 0,
00711 0,
00712 0,
00713 FALSE,
00714 0,
00715 complain_overflow_dont,
00716 bfd_elf_generic_reloc,
00717 "JMP_SLOT",
00718 FALSE,
00719 0,
00720 0,
00721 TRUE),
00722
00723
00724 HOWTO (R_ALPHA_RELATIVE,
00725 0,
00726 0,
00727 0,
00728 FALSE,
00729 0,
00730 complain_overflow_dont,
00731 bfd_elf_generic_reloc,
00732 "RELATIVE",
00733 FALSE,
00734 0,
00735 0,
00736 TRUE),
00737
00738
00739 HOWTO (R_ALPHA_BRSGP,
00740 2,
00741 2,
00742 21,
00743 TRUE,
00744 0,
00745 complain_overflow_signed,
00746 0,
00747 "BRSGP",
00748 FALSE,
00749 0x1fffff,
00750 0x1fffff,
00751 TRUE),
00752
00753
00754 HOWTO (R_ALPHA_TLSGD,
00755 0,
00756 1,
00757 16,
00758 FALSE,
00759 0,
00760 complain_overflow_signed,
00761 0,
00762 "TLSGD",
00763 FALSE,
00764 0xffff,
00765 0xffff,
00766 FALSE),
00767
00768
00769 HOWTO (R_ALPHA_TLSLDM,
00770 0,
00771 1,
00772 16,
00773 FALSE,
00774 0,
00775 complain_overflow_signed,
00776 0,
00777 "TLSLDM",
00778 FALSE,
00779 0xffff,
00780 0xffff,
00781 FALSE),
00782
00783
00784 HOWTO (R_ALPHA_DTPMOD64,
00785 0,
00786 4,
00787 64,
00788 FALSE,
00789 0,
00790 complain_overflow_bitfield,
00791 0,
00792 "DTPMOD64",
00793 FALSE,
00794 MINUS_ONE,
00795 MINUS_ONE,
00796 FALSE),
00797
00798
00799
00800 HOWTO (R_ALPHA_GOTDTPREL,
00801 0,
00802 1,
00803 16,
00804 FALSE,
00805 0,
00806 complain_overflow_signed,
00807 0,
00808 "GOTDTPREL",
00809 FALSE,
00810 0xffff,
00811 0xffff,
00812 FALSE),
00813
00814
00815 HOWTO (R_ALPHA_DTPREL64,
00816 0,
00817 4,
00818 64,
00819 FALSE,
00820 0,
00821 complain_overflow_bitfield,
00822 0,
00823 "DTPREL64",
00824 FALSE,
00825 MINUS_ONE,
00826 MINUS_ONE,
00827 FALSE),
00828
00829
00830 HOWTO (R_ALPHA_DTPRELHI,
00831 0,
00832 1,
00833 16,
00834 FALSE,
00835 0,
00836 complain_overflow_signed,
00837 0,
00838 "DTPRELHI",
00839 FALSE,
00840 0xffff,
00841 0xffff,
00842 FALSE),
00843
00844
00845 HOWTO (R_ALPHA_DTPRELLO,
00846 0,
00847 1,
00848 16,
00849 FALSE,
00850 0,
00851 complain_overflow_dont,
00852 0,
00853 "DTPRELLO",
00854 FALSE,
00855 0xffff,
00856 0xffff,
00857 FALSE),
00858
00859
00860 HOWTO (R_ALPHA_DTPREL16,
00861 0,
00862 1,
00863 16,
00864 FALSE,
00865 0,
00866 complain_overflow_signed,
00867 0,
00868 "DTPREL16",
00869 FALSE,
00870 0xffff,
00871 0xffff,
00872 FALSE),
00873
00874
00875
00876 HOWTO (R_ALPHA_GOTTPREL,
00877 0,
00878 1,
00879 16,
00880 FALSE,
00881 0,
00882 complain_overflow_signed,
00883 0,
00884 "GOTTPREL",
00885 FALSE,
00886 0xffff,
00887 0xffff,
00888 FALSE),
00889
00890
00891 HOWTO (R_ALPHA_TPREL64,
00892 0,
00893 4,
00894 64,
00895 FALSE,
00896 0,
00897 complain_overflow_bitfield,
00898 0,
00899 "TPREL64",
00900 FALSE,
00901 MINUS_ONE,
00902 MINUS_ONE,
00903 FALSE),
00904
00905
00906 HOWTO (R_ALPHA_TPRELHI,
00907 0,
00908 1,
00909 16,
00910 FALSE,
00911 0,
00912 complain_overflow_signed,
00913 0,
00914 "TPRELHI",
00915 FALSE,
00916 0xffff,
00917 0xffff,
00918 FALSE),
00919
00920
00921 HOWTO (R_ALPHA_TPRELLO,
00922 0,
00923 1,
00924 16,
00925 FALSE,
00926 0,
00927 complain_overflow_dont,
00928 0,
00929 "TPRELLO",
00930 FALSE,
00931 0xffff,
00932 0xffff,
00933 FALSE),
00934
00935
00936 HOWTO (R_ALPHA_TPREL16,
00937 0,
00938 1,
00939 16,
00940 FALSE,
00941 0,
00942 complain_overflow_signed,
00943 0,
00944 "TPREL16",
00945 FALSE,
00946 0xffff,
00947 0xffff,
00948 FALSE),
00949 };
00950
00951
00952
00953 static bfd_reloc_status_type
00954 elf64_alpha_reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message)
00955 bfd *abfd ATTRIBUTE_UNUSED;
00956 arelent *reloc;
00957 asymbol *sym ATTRIBUTE_UNUSED;
00958 PTR data ATTRIBUTE_UNUSED;
00959 asection *sec;
00960 bfd *output_bfd;
00961 char **error_message ATTRIBUTE_UNUSED;
00962 {
00963 if (output_bfd)
00964 reloc->address += sec->output_offset;
00965 return bfd_reloc_ok;
00966 }
00967
00968
00969
00970 static bfd_reloc_status_type
00971 elf64_alpha_reloc_bad (abfd, reloc, sym, data, sec, output_bfd, error_message)
00972 bfd *abfd ATTRIBUTE_UNUSED;
00973 arelent *reloc;
00974 asymbol *sym ATTRIBUTE_UNUSED;
00975 PTR data ATTRIBUTE_UNUSED;
00976 asection *sec;
00977 bfd *output_bfd;
00978 char **error_message ATTRIBUTE_UNUSED;
00979 {
00980 if (output_bfd)
00981 reloc->address += sec->output_offset;
00982 return bfd_reloc_notsupported;
00983 }
00984
00985
00986
00987 static bfd_reloc_status_type
00988 elf64_alpha_do_reloc_gpdisp (abfd, gpdisp, p_ldah, p_lda)
00989 bfd *abfd;
00990 bfd_vma gpdisp;
00991 bfd_byte *p_ldah;
00992 bfd_byte *p_lda;
00993 {
00994 bfd_reloc_status_type ret = bfd_reloc_ok;
00995 bfd_vma addend;
00996 unsigned long i_ldah, i_lda;
00997
00998 i_ldah = bfd_get_32 (abfd, p_ldah);
00999 i_lda = bfd_get_32 (abfd, p_lda);
01000
01001
01002 if (((i_ldah >> 26) & 0x3f) != 0x09
01003 || ((i_lda >> 26) & 0x3f) != 0x08)
01004 ret = bfd_reloc_dangerous;
01005
01006
01007
01008 addend = ((i_ldah & 0xffff) << 16) | (i_lda & 0xffff);
01009 addend = (addend ^ 0x80008000) - 0x80008000;
01010
01011 gpdisp += addend;
01012
01013 if ((bfd_signed_vma) gpdisp < -(bfd_signed_vma) 0x80000000
01014 || (bfd_signed_vma) gpdisp >= (bfd_signed_vma) 0x7fff8000)
01015 ret = bfd_reloc_overflow;
01016
01017
01018 i_ldah = ((i_ldah & 0xffff0000)
01019 | (((gpdisp >> 16) + ((gpdisp >> 15) & 1)) & 0xffff));
01020 i_lda = (i_lda & 0xffff0000) | (gpdisp & 0xffff);
01021
01022 bfd_put_32 (abfd, (bfd_vma) i_ldah, p_ldah);
01023 bfd_put_32 (abfd, (bfd_vma) i_lda, p_lda);
01024
01025 return ret;
01026 }
01027
01028
01029
01030 static bfd_reloc_status_type
01031 elf64_alpha_reloc_gpdisp (abfd, reloc_entry, sym, data, input_section,
01032 output_bfd, err_msg)
01033 bfd *abfd;
01034 arelent *reloc_entry;
01035 asymbol *sym ATTRIBUTE_UNUSED;
01036 PTR data;
01037 asection *input_section;
01038 bfd *output_bfd;
01039 char **err_msg;
01040 {
01041 bfd_reloc_status_type ret;
01042 bfd_vma gp, relocation;
01043 bfd_vma high_address;
01044 bfd_byte *p_ldah, *p_lda;
01045
01046
01047 if (output_bfd)
01048 {
01049 reloc_entry->address += input_section->output_offset;
01050 return bfd_reloc_ok;
01051 }
01052
01053 high_address = bfd_get_section_limit (abfd, input_section);
01054 if (reloc_entry->address > high_address
01055 || reloc_entry->address + reloc_entry->addend > high_address)
01056 return bfd_reloc_outofrange;
01057
01058
01059
01060 gp = _bfd_get_gp_value (abfd);
01061
01062 relocation = (input_section->output_section->vma
01063 + input_section->output_offset
01064 + reloc_entry->address);
01065
01066 p_ldah = (bfd_byte *) data + reloc_entry->address;
01067 p_lda = p_ldah + reloc_entry->addend;
01068
01069 ret = elf64_alpha_do_reloc_gpdisp (abfd, gp - relocation, p_ldah, p_lda);
01070
01071
01072 if (ret == bfd_reloc_dangerous)
01073 *err_msg = _("GPDISP relocation did not find ldah and lda instructions");
01074
01075 return ret;
01076 }
01077
01078
01079
01080 struct elf_reloc_map
01081 {
01082 bfd_reloc_code_real_type bfd_reloc_val;
01083 int elf_reloc_val;
01084 };
01085
01086 static const struct elf_reloc_map elf64_alpha_reloc_map[] =
01087 {
01088 {BFD_RELOC_NONE, R_ALPHA_NONE},
01089 {BFD_RELOC_32, R_ALPHA_REFLONG},
01090 {BFD_RELOC_64, R_ALPHA_REFQUAD},
01091 {BFD_RELOC_CTOR, R_ALPHA_REFQUAD},
01092 {BFD_RELOC_GPREL32, R_ALPHA_GPREL32},
01093 {BFD_RELOC_ALPHA_ELF_LITERAL, R_ALPHA_LITERAL},
01094 {BFD_RELOC_ALPHA_LITUSE, R_ALPHA_LITUSE},
01095 {BFD_RELOC_ALPHA_GPDISP, R_ALPHA_GPDISP},
01096 {BFD_RELOC_23_PCREL_S2, R_ALPHA_BRADDR},
01097 {BFD_RELOC_ALPHA_HINT, R_ALPHA_HINT},
01098 {BFD_RELOC_16_PCREL, R_ALPHA_SREL16},
01099 {BFD_RELOC_32_PCREL, R_ALPHA_SREL32},
01100 {BFD_RELOC_64_PCREL, R_ALPHA_SREL64},
01101 {BFD_RELOC_ALPHA_GPREL_HI16, R_ALPHA_GPRELHIGH},
01102 {BFD_RELOC_ALPHA_GPREL_LO16, R_ALPHA_GPRELLOW},
01103 {BFD_RELOC_GPREL16, R_ALPHA_GPREL16},
01104 {BFD_RELOC_ALPHA_BRSGP, R_ALPHA_BRSGP},
01105 {BFD_RELOC_ALPHA_TLSGD, R_ALPHA_TLSGD},
01106 {BFD_RELOC_ALPHA_TLSLDM, R_ALPHA_TLSLDM},
01107 {BFD_RELOC_ALPHA_DTPMOD64, R_ALPHA_DTPMOD64},
01108 {BFD_RELOC_ALPHA_GOTDTPREL16, R_ALPHA_GOTDTPREL},
01109 {BFD_RELOC_ALPHA_DTPREL64, R_ALPHA_DTPREL64},
01110 {BFD_RELOC_ALPHA_DTPREL_HI16, R_ALPHA_DTPRELHI},
01111 {BFD_RELOC_ALPHA_DTPREL_LO16, R_ALPHA_DTPRELLO},
01112 {BFD_RELOC_ALPHA_DTPREL16, R_ALPHA_DTPREL16},
01113 {BFD_RELOC_ALPHA_GOTTPREL16, R_ALPHA_GOTTPREL},
01114 {BFD_RELOC_ALPHA_TPREL64, R_ALPHA_TPREL64},
01115 {BFD_RELOC_ALPHA_TPREL_HI16, R_ALPHA_TPRELHI},
01116 {BFD_RELOC_ALPHA_TPREL_LO16, R_ALPHA_TPRELLO},
01117 {BFD_RELOC_ALPHA_TPREL16, R_ALPHA_TPREL16},
01118 };
01119
01120
01121
01122 static reloc_howto_type *
01123 elf64_alpha_bfd_reloc_type_lookup (abfd, code)
01124 bfd *abfd ATTRIBUTE_UNUSED;
01125 bfd_reloc_code_real_type code;
01126 {
01127 const struct elf_reloc_map *i, *e;
01128 i = e = elf64_alpha_reloc_map;
01129 e += sizeof (elf64_alpha_reloc_map) / sizeof (struct elf_reloc_map);
01130 for (; i != e; ++i)
01131 {
01132 if (i->bfd_reloc_val == code)
01133 return &elf64_alpha_howto_table[i->elf_reloc_val];
01134 }
01135 return 0;
01136 }
01137
01138
01139
01140 static void
01141 elf64_alpha_info_to_howto (abfd, cache_ptr, dst)
01142 bfd *abfd ATTRIBUTE_UNUSED;
01143 arelent *cache_ptr;
01144 Elf_Internal_Rela *dst;
01145 {
01146 unsigned r_type;
01147
01148 r_type = ELF64_R_TYPE(dst->r_info);
01149 BFD_ASSERT (r_type < (unsigned int) R_ALPHA_max);
01150 cache_ptr->howto = &elf64_alpha_howto_table[r_type];
01151 }
01152
01153
01154 #define alpha_got_entry_size(r_type) \
01155 (r_type == R_ALPHA_TLSGD || r_type == R_ALPHA_TLSLDM ? 16 : 8)
01156
01157
01158 #define alpha_get_dtprel_base(info) \
01159 (elf_hash_table (info)->tls_sec->vma)
01160
01161
01162
01163 #define alpha_get_tprel_base(info) \
01164 (elf_hash_table (info)->tls_sec->vma \
01165 - align_power ((bfd_vma) 16, \
01166 elf_hash_table (info)->tls_sec->alignment_power))
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 #define OP_LDA 0x08
01182 #define OP_LDAH 0x09
01183 #define INSN_JSR 0x68004000
01184 #define INSN_JSR_MASK 0xfc00c000
01185 #define OP_LDQ 0x29
01186 #define OP_BR 0x30
01187 #define OP_BSR 0x34
01188 #define INSN_UNOP 0x2ffe0000
01189 #define INSN_ADDQ 0x40000400
01190 #define INSN_RDUNIQ 0x0000009e
01191
01192 struct alpha_relax_info
01193 {
01194 bfd *abfd;
01195 asection *sec;
01196 bfd_byte *contents;
01197 Elf_Internal_Shdr *symtab_hdr;
01198 Elf_Internal_Rela *relocs, *relend;
01199 struct bfd_link_info *link_info;
01200 bfd_vma gp;
01201 bfd *gotobj;
01202 asection *tsec;
01203 struct alpha_elf_link_hash_entry *h;
01204 struct alpha_elf_got_entry **first_gotent;
01205 struct alpha_elf_got_entry *gotent;
01206 bfd_boolean changed_contents;
01207 bfd_boolean changed_relocs;
01208 unsigned char other;
01209 };
01210
01211 static bfd_boolean elf64_alpha_relax_with_lituse
01212 PARAMS((struct alpha_relax_info *info, bfd_vma symval,
01213 Elf_Internal_Rela *irel));
01214 static bfd_vma elf64_alpha_relax_opt_call
01215 PARAMS((struct alpha_relax_info *info, bfd_vma symval));
01216 static bfd_boolean elf64_alpha_relax_got_load
01217 PARAMS((struct alpha_relax_info *info, bfd_vma symval,
01218 Elf_Internal_Rela *irel, unsigned long));
01219 static bfd_boolean elf64_alpha_relax_gprelhilo
01220 PARAMS((struct alpha_relax_info *info, bfd_vma symval,
01221 Elf_Internal_Rela *irel, bfd_boolean));
01222 static bfd_boolean elf64_alpha_relax_tls_get_addr
01223 PARAMS((struct alpha_relax_info *info, bfd_vma symval,
01224 Elf_Internal_Rela *irel, bfd_boolean));
01225 static bfd_boolean elf64_alpha_relax_section
01226 PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
01227 bfd_boolean *again));
01228
01229 static Elf_Internal_Rela *
01230 elf64_alpha_find_reloc_at_ofs (rel, relend, offset, type)
01231 Elf_Internal_Rela *rel, *relend;
01232 bfd_vma offset;
01233 int type;
01234 {
01235 while (rel < relend)
01236 {
01237 if (rel->r_offset == offset
01238 && ELF64_R_TYPE (rel->r_info) == (unsigned int) type)
01239 return rel;
01240 ++rel;
01241 }
01242 return NULL;
01243 }
01244
01245 static bfd_boolean
01246 elf64_alpha_relax_with_lituse (info, symval, irel)
01247 struct alpha_relax_info *info;
01248 bfd_vma symval;
01249 Elf_Internal_Rela *irel;
01250 {
01251 Elf_Internal_Rela *urel, *irelend = info->relend;
01252 int flags, count, i;
01253 bfd_signed_vma disp;
01254 bfd_boolean fits16;
01255 bfd_boolean fits32;
01256 bfd_boolean lit_reused = FALSE;
01257 bfd_boolean all_optimized = TRUE;
01258 unsigned int lit_insn;
01259
01260 lit_insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset);
01261 if (lit_insn >> 26 != OP_LDQ)
01262 {
01263 ((*_bfd_error_handler)
01264 ("%B: %A+0x%lx: warning: LITERAL relocation against unexpected insn",
01265 info->abfd, info->sec,
01266 (unsigned long) irel->r_offset));
01267 return TRUE;
01268 }
01269
01270
01271 if (alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info))
01272 return TRUE;
01273
01274
01275 for (urel = irel+1, flags = count = 0; urel < irelend; ++urel, ++count)
01276 {
01277 if (ELF64_R_TYPE (urel->r_info) != R_ALPHA_LITUSE)
01278 break;
01279 if (urel->r_addend <= 3)
01280 flags |= 1 << urel->r_addend;
01281 }
01282
01283
01284 disp = symval - info->gp;
01285
01286 for (urel = irel+1, i = 0; i < count; ++i, ++urel)
01287 {
01288 unsigned int insn;
01289 int insn_disp;
01290 bfd_signed_vma xdisp;
01291
01292 insn = bfd_get_32 (info->abfd, info->contents + urel->r_offset);
01293
01294 switch (urel->r_addend)
01295 {
01296 case LITUSE_ALPHA_ADDR:
01297 default:
01298
01299
01300 all_optimized = FALSE;
01301 break;
01302
01303 case LITUSE_ALPHA_BASE:
01304
01305
01306
01307
01308
01309 insn_disp = ((insn & 0xffff) ^ 0x8000) - 0x8000;
01310
01311 xdisp = disp + insn_disp;
01312 fits16 = (xdisp >= - (bfd_signed_vma) 0x8000 && xdisp < 0x8000);
01313 fits32 = (xdisp >= - (bfd_signed_vma) 0x80000000
01314 && xdisp < 0x7fff8000);
01315
01316 if (fits16)
01317 {
01318
01319
01320 insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000);
01321 urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
01322 R_ALPHA_GPREL16);
01323 urel->r_addend = irel->r_addend;
01324 info->changed_relocs = TRUE;
01325
01326 bfd_put_32 (info->abfd, (bfd_vma) insn,
01327 info->contents + urel->r_offset);
01328 info->changed_contents = TRUE;
01329 }
01330
01331
01332 else if (fits32 && !(flags & ~6))
01333 {
01334
01335
01336 irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
01337 R_ALPHA_GPRELHIGH);
01338 lit_insn = (OP_LDAH << 26) | (lit_insn & 0x03ff0000);
01339 bfd_put_32 (info->abfd, (bfd_vma) lit_insn,
01340 info->contents + irel->r_offset);
01341 lit_reused = TRUE;
01342 info->changed_contents = TRUE;
01343
01344 urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
01345 R_ALPHA_GPRELLOW);
01346 urel->r_addend = irel->r_addend;
01347 info->changed_relocs = TRUE;
01348 }
01349 else
01350 all_optimized = FALSE;
01351 break;
01352
01353 case LITUSE_ALPHA_BYTOFF:
01354
01355
01356
01357
01358
01359 insn &= ~ (unsigned) 0x001ff000;
01360 insn |= ((symval & 7) << 13) | 0x1000;
01361
01362 urel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
01363 urel->r_addend = 0;
01364 info->changed_relocs = TRUE;
01365
01366 bfd_put_32 (info->abfd, (bfd_vma) insn,
01367 info->contents + urel->r_offset);
01368 info->changed_contents = TRUE;
01369 break;
01370
01371 case LITUSE_ALPHA_JSR:
01372 case LITUSE_ALPHA_TLSGD:
01373 case LITUSE_ALPHA_TLSLDM:
01374 {
01375 bfd_vma optdest, org;
01376 bfd_signed_vma odisp;
01377
01378
01379
01380
01381 if (info->h && info->h->root.root.type == bfd_link_hash_undefweak)
01382 {
01383 insn |= 31 << 16;
01384 bfd_put_32 (info->abfd, (bfd_vma) insn,
01385 info->contents + urel->r_offset);
01386
01387 info->changed_contents = TRUE;
01388 break;
01389 }
01390
01391
01392 optdest = elf64_alpha_relax_opt_call (info, symval);
01393 org = (info->sec->output_section->vma
01394 + info->sec->output_offset
01395 + urel->r_offset + 4);
01396 odisp = (optdest ? optdest : symval) - org;
01397
01398 if (odisp >= -0x400000 && odisp < 0x400000)
01399 {
01400 Elf_Internal_Rela *xrel;
01401
01402
01403 if ((insn & INSN_JSR_MASK) == INSN_JSR)
01404 insn = (OP_BSR << 26) | (insn & 0x03e00000);
01405 else
01406 insn = (OP_BR << 26) | (insn & 0x03e00000);
01407
01408 urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
01409 R_ALPHA_BRADDR);
01410 urel->r_addend = irel->r_addend;
01411
01412 if (optdest)
01413 urel->r_addend += optdest - symval;
01414 else
01415 all_optimized = FALSE;
01416
01417 bfd_put_32 (info->abfd, (bfd_vma) insn,
01418 info->contents + urel->r_offset);
01419
01420
01421 xrel = (elf64_alpha_find_reloc_at_ofs
01422 (info->relocs, info->relend, urel->r_offset,
01423 R_ALPHA_HINT));
01424 if (xrel)
01425 xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
01426
01427 info->changed_contents = TRUE;
01428 info->changed_relocs = TRUE;
01429 }
01430 else
01431 all_optimized = FALSE;
01432
01433
01434
01435 if (optdest)
01436 {
01437 Elf_Internal_Rela *gpdisp
01438 = (elf64_alpha_find_reloc_at_ofs
01439 (info->relocs, irelend, urel->r_offset + 4,
01440 R_ALPHA_GPDISP));
01441 if (gpdisp)
01442 {
01443 bfd_byte *p_ldah = info->contents + gpdisp->r_offset;
01444 bfd_byte *p_lda = p_ldah + gpdisp->r_addend;
01445 unsigned int ldah = bfd_get_32 (info->abfd, p_ldah);
01446 unsigned int lda = bfd_get_32 (info->abfd, p_lda);
01447
01448
01449
01450
01451
01452
01453 if (ldah == 0x27ba0000 && lda == 0x23bd0000)
01454 {
01455 bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_ldah);
01456 bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_lda);
01457
01458 gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
01459 info->changed_contents = TRUE;
01460 info->changed_relocs = TRUE;
01461 }
01462 }
01463 }
01464 }
01465 break;
01466 }
01467 }
01468
01469
01470
01471 if (all_optimized)
01472 {
01473 if (--info->gotent->use_count == 0)
01474 {
01475 int sz = alpha_got_entry_size (R_ALPHA_LITERAL);
01476 alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
01477 if (!info->h)
01478 alpha_elf_tdata (info->gotobj)->local_got_size -= sz;
01479 }
01480
01481
01482
01483
01484
01485 if (!lit_reused)
01486 {
01487 irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
01488 info->changed_relocs = TRUE;
01489
01490 bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP,
01491 info->contents + irel->r_offset);
01492 info->changed_contents = TRUE;
01493 }
01494
01495 return TRUE;
01496 }
01497 else
01498 return elf64_alpha_relax_got_load (info, symval, irel, R_ALPHA_LITERAL);
01499 }
01500
01501 static bfd_vma
01502 elf64_alpha_relax_opt_call (info, symval)
01503 struct alpha_relax_info *info;
01504 bfd_vma symval;
01505 {
01506
01507
01508
01509
01510
01511
01512 if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_NOPV)
01513 return symval;
01514
01515
01516
01517 else if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_STD_GPLOAD)
01518 ;
01519
01520
01521
01522 else
01523 {
01524 Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp;
01525 bfd_vma ofs;
01526
01527
01528 if (info->sec == info->tsec)
01529 {
01530 tsec_relocs = info->relocs;
01531 tsec_relend = info->relend;
01532 tsec_free = NULL;
01533 }
01534 else
01535 {
01536 tsec_relocs = (_bfd_elf_link_read_relocs
01537 (info->abfd, info->tsec, (PTR) NULL,
01538 (Elf_Internal_Rela *) NULL,
01539 info->link_info->keep_memory));
01540 if (tsec_relocs == NULL)
01541 return 0;
01542 tsec_relend = tsec_relocs + info->tsec->reloc_count;
01543 tsec_free = (info->link_info->keep_memory ? NULL : tsec_relocs);
01544 }
01545
01546
01547 ofs = (symval - info->tsec->output_section->vma
01548 - info->tsec->output_offset);
01549
01550
01551 gpdisp = (elf64_alpha_find_reloc_at_ofs
01552 (tsec_relocs, tsec_relend, ofs, R_ALPHA_GPDISP));
01553
01554 if (!gpdisp || gpdisp->r_addend != 4)
01555 {
01556 if (tsec_free)
01557 free (tsec_free);
01558 return 0;
01559 }
01560 if (tsec_free)
01561 free (tsec_free);
01562 }
01563
01564
01565
01566 if (info->link_info->hash->creator != info->tsec->owner->xvec
01567 || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj)
01568 return 0;
01569
01570 return symval + 8;
01571 }
01572
01573 static bfd_boolean
01574 elf64_alpha_relax_got_load (info, symval, irel, r_type)
01575 struct alpha_relax_info *info;
01576 bfd_vma symval;
01577 Elf_Internal_Rela *irel;
01578 unsigned long r_type;
01579 {
01580 unsigned int insn;
01581 bfd_signed_vma disp;
01582
01583
01584 insn = bfd_get_32 (info->abfd, info->contents + irel->r_offset);
01585
01586 if (insn >> 26 != OP_LDQ)
01587 {
01588 reloc_howto_type *howto = elf64_alpha_howto_table + r_type;
01589 ((*_bfd_error_handler)
01590 ("%B: %A+0x%lx: warning: %s relocation against unexpected insn",
01591 info->abfd, info->sec,
01592 (unsigned long) irel->r_offset, howto->name));
01593 return TRUE;
01594 }
01595
01596
01597 if (alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info))
01598 return TRUE;
01599
01600
01601 if (r_type == R_ALPHA_GOTTPREL && info->link_info->shared)
01602 return TRUE;
01603
01604 if (r_type == R_ALPHA_LITERAL)
01605 {
01606
01607
01608 if ((info->h && info->h->root.root.type == bfd_link_hash_undefweak)
01609 || (!info->link_info->shared
01610 && (symval >= (bfd_vma)-0x8000 || symval < 0x8000)))
01611 {
01612 disp = 0;
01613 insn = (OP_LDA << 26) | (insn & (31 << 21)) | (31 << 16);
01614 insn |= (symval & 0xffff);
01615 r_type = R_ALPHA_NONE;
01616 }
01617 else
01618 {
01619 disp = symval - info->gp;
01620 insn = (OP_LDA << 26) | (insn & 0x03ff0000);
01621 r_type = R_ALPHA_GPREL16;
01622 }
01623 }
01624 else
01625 {
01626 bfd_vma dtp_base, tp_base;
01627
01628 BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL);
01629 dtp_base = alpha_get_dtprel_base (info->link_info);
01630 tp_base = alpha_get_tprel_base (info->link_info);
01631 disp = symval - (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base);
01632
01633 insn = (OP_LDA << 26) | (insn & (31 << 21)) | (31 << 16);
01634
01635 switch (r_type)
01636 {
01637 case R_ALPHA_GOTDTPREL:
01638 r_type = R_ALPHA_DTPREL16;
01639 break;
01640 case R_ALPHA_GOTTPREL:
01641 r_type = R_ALPHA_TPREL16;
01642 break;
01643 default:
01644 BFD_ASSERT (0);
01645 return FALSE;
01646 }
01647 }
01648
01649 if (disp < -0x8000 || disp >= 0x8000)
01650 return TRUE;
01651
01652 bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset);
01653 info->changed_contents = TRUE;
01654
01655
01656
01657 if (--info->gotent->use_count == 0)
01658 {
01659 int sz = alpha_got_entry_size (r_type);
01660 alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
01661 if (!info->h)
01662 alpha_elf_tdata (info->gotobj)->local_got_size -= sz;
01663 }
01664
01665
01666 irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), r_type);
01667 info->changed_relocs = TRUE;
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682 return TRUE;
01683 }
01684
01685 static bfd_boolean
01686 elf64_alpha_relax_gprelhilo (info, symval, irel, hi)
01687 struct alpha_relax_info *info;
01688 bfd_vma symval;
01689 Elf_Internal_Rela *irel;
01690 bfd_boolean hi;
01691 {
01692 unsigned int insn;
01693 bfd_signed_vma disp;
01694 bfd_byte *pos = info->contents + irel->r_offset;
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706 return TRUE;
01707
01708 disp = symval - info->gp;
01709 if (disp < -0x8000 || disp >= 0x8000)
01710 return TRUE;
01711
01712 if (hi)
01713 {
01714
01715
01716 bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos);
01717 info->changed_contents = TRUE;
01718
01719 irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
01720 irel->r_addend = 0;
01721 info->changed_relocs = TRUE;
01722 }
01723 else
01724 {
01725
01726
01727 insn = bfd_get_32 (info->abfd, pos);
01728 insn = (insn & 0xffe00000) | (29 << 16);
01729 bfd_put_32 (info->abfd, (bfd_vma) insn, pos);
01730 info->changed_contents = TRUE;
01731
01732 irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
01733 R_ALPHA_GPREL16);
01734 info->changed_relocs = TRUE;
01735 }
01736
01737 return TRUE;
01738 }
01739
01740 static bfd_boolean
01741 elf64_alpha_relax_tls_get_addr (info, symval, irel, is_gd)
01742 struct alpha_relax_info *info;
01743 bfd_vma symval;
01744 Elf_Internal_Rela *irel;
01745 bfd_boolean is_gd;
01746 {
01747 bfd_byte *pos[5];
01748 unsigned int insn;
01749 Elf_Internal_Rela *gpdisp, *hint;
01750 bfd_boolean dynamic, use_gottprel, pos1_unusable;
01751 unsigned long new_symndx;
01752
01753 dynamic = alpha_elf_dynamic_symbol_p (&info->h->root, info->link_info);
01754
01755
01756
01757 if (is_gd && info->h && (info->h->flags & ALPHA_ELF_LINK_HASH_TLS_IE))
01758 ;
01759
01760
01761
01762 else if (info->link_info->shared && !dynamic
01763 && (info->link_info->flags & DF_STATIC_TLS))
01764 ;
01765
01766
01767 else if (info->link_info->shared)
01768 return TRUE;
01769
01770
01771
01772 if (irel + 2 >= info->relend)
01773 return TRUE;
01774 if (ELF64_R_TYPE (irel[1].r_info) != R_ALPHA_LITERAL
01775 || ELF64_R_TYPE (irel[2].r_info) != R_ALPHA_LITUSE
01776 || irel[2].r_addend != (is_gd ? LITUSE_ALPHA_TLSGD : LITUSE_ALPHA_TLSLDM))
01777 return TRUE;
01778
01779
01780
01781 gpdisp = elf64_alpha_find_reloc_at_ofs (info->relocs, info->relend,
01782 irel[2].r_offset + 4, R_ALPHA_GPDISP);
01783 if (!gpdisp)
01784 return TRUE;
01785
01786 pos[0] = info->contents + irel[0].r_offset;
01787 pos[1] = info->contents + irel[1].r_offset;
01788 pos[2] = info->contents + irel[2].r_offset;
01789 pos[3] = info->contents + gpdisp->r_offset;
01790 pos[4] = pos[3] + gpdisp->r_addend;
01791 pos1_unusable = FALSE;
01792
01793
01794
01795
01796 if (pos[1] + 4 == pos[0])
01797 {
01798 bfd_byte *tmp = pos[0];
01799 pos[0] = pos[1];
01800 pos[1] = tmp;
01801 }
01802 else if (pos[1] < pos[0])
01803 pos1_unusable = TRUE;
01804 if (pos[1] >= pos[2] || pos[2] >= pos[3])
01805 return TRUE;
01806
01807
01808
01809 {
01810 struct alpha_elf_got_entry *lit_gotent;
01811 struct alpha_elf_link_hash_entry *lit_h;
01812 unsigned long indx;
01813
01814 BFD_ASSERT (ELF64_R_SYM (irel[1].r_info) >= info->symtab_hdr->sh_info);
01815 indx = ELF64_R_SYM (irel[1].r_info) - info->symtab_hdr->sh_info;
01816 lit_h = alpha_elf_sym_hashes (info->abfd)[indx];
01817
01818 while (lit_h->root.root.type == bfd_link_hash_indirect
01819 || lit_h->root.root.type == bfd_link_hash_warning)
01820 lit_h = (struct alpha_elf_link_hash_entry *) lit_h->root.root.u.i.link;
01821
01822 for (lit_gotent = lit_h->got_entries; lit_gotent ;
01823 lit_gotent = lit_gotent->next)
01824 if (lit_gotent->gotobj == info->gotobj
01825 && lit_gotent->reloc_type == R_ALPHA_LITERAL
01826 && lit_gotent->addend == irel[1].r_addend)
01827 break;
01828 BFD_ASSERT (lit_gotent);
01829
01830 if (--lit_gotent->use_count == 0)
01831 {
01832 int sz = alpha_got_entry_size (R_ALPHA_LITERAL);
01833 alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
01834 }
01835 }
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859 use_gottprel = FALSE;
01860 new_symndx = is_gd ? ELF64_R_SYM (irel->r_info) : 0;
01861 switch (!dynamic && !info->link_info->shared)
01862 {
01863 case 1:
01864 {
01865 bfd_vma tp_base;
01866 bfd_signed_vma disp;
01867
01868 BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL);
01869 tp_base = alpha_get_tprel_base (info->link_info);
01870 disp = symval - tp_base;
01871
01872 if (disp >= -0x8000 && disp < 0x8000)
01873 {
01874 insn = (OP_LDA << 26) | (16 << 21) | (31 << 16);
01875 bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]);
01876 bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]);
01877
01878 irel[0].r_offset = pos[0] - info->contents;
01879 irel[0].r_info = ELF64_R_INFO (new_symndx, R_ALPHA_TPREL16);
01880 irel[1].r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
01881 break;
01882 }
01883 else if (disp >= -(bfd_signed_vma) 0x80000000
01884 && disp < (bfd_signed_vma) 0x7fff8000
01885 && !pos1_unusable)
01886 {
01887 insn = (OP_LDAH << 26) | (16 << 21) | (31 << 16);
01888 bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]);
01889 insn = (OP_LDA << 26) | (16 << 21) | (16 << 16);
01890 bfd_put_32 (info->abfd, (bfd_vma) insn, pos[1]);
01891
01892 irel[0].r_offset = pos[0] - info->contents;
01893 irel[0].r_info = ELF64_R_INFO (new_symndx, R_ALPHA_TPRELHI);
01894 irel[1].r_offset = pos[1] - info->contents;
01895 irel[1].r_info = ELF64_R_INFO (new_symndx, R_ALPHA_TPRELLO);
01896 break;
01897 }
01898 }
01899
01900
01901 default:
01902 use_gottprel = TRUE;
01903
01904 insn = (OP_LDQ << 26) | (16 << 21) | (29 << 16);
01905 bfd_put_32 (info->abfd, (bfd_vma) insn, pos[0]);
01906 bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[1]);
01907
01908 irel[0].r_offset = pos[0] - info->contents;
01909 irel[0].r_info = ELF64_R_INFO (new_symndx, R_ALPHA_GOTTPREL);
01910 irel[1].r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
01911 break;
01912 }
01913
01914 bfd_put_32 (info->abfd, (bfd_vma) INSN_RDUNIQ, pos[2]);
01915
01916 insn = INSN_ADDQ | (16 << 21) | (0 << 16) | (0 << 0);
01917 bfd_put_32 (info->abfd, (bfd_vma) insn, pos[3]);
01918
01919 bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, pos[4]);
01920
01921 irel[2].r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
01922 gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
01923
01924 hint = elf64_alpha_find_reloc_at_ofs (info->relocs, info->relend,
01925 irel[2].r_offset, R_ALPHA_HINT);
01926 if (hint)
01927 hint->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
01928
01929 info->changed_contents = TRUE;
01930 info->changed_relocs = TRUE;
01931
01932
01933 if (--info->gotent->use_count == 0)
01934 {
01935 int sz = alpha_got_entry_size (info->gotent->reloc_type);
01936 alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
01937 if (!info->h)
01938 alpha_elf_tdata (info->gotobj)->local_got_size -= sz;
01939 }
01940
01941
01942
01943 if (use_gottprel)
01944 {
01945 struct alpha_elf_got_entry *tprel_gotent;
01946
01947 for (tprel_gotent = *info->first_gotent; tprel_gotent ;
01948 tprel_gotent = tprel_gotent->next)
01949 if (tprel_gotent->gotobj == info->gotobj
01950 && tprel_gotent->reloc_type == R_ALPHA_GOTTPREL
01951 && tprel_gotent->addend == irel->r_addend)
01952 break;
01953 if (tprel_gotent)
01954 tprel_gotent->use_count++;
01955 else
01956 {
01957 if (info->gotent->use_count == 0)
01958 tprel_gotent = info->gotent;
01959 else
01960 {
01961 tprel_gotent = (struct alpha_elf_got_entry *)
01962 bfd_alloc (info->abfd, sizeof (struct alpha_elf_got_entry));
01963 if (!tprel_gotent)
01964 return FALSE;
01965
01966 tprel_gotent->next = *info->first_gotent;
01967 *info->first_gotent = tprel_gotent;
01968
01969 tprel_gotent->gotobj = info->gotobj;
01970 tprel_gotent->addend = irel->r_addend;
01971 tprel_gotent->got_offset = -1;
01972 tprel_gotent->reloc_done = 0;
01973 tprel_gotent->reloc_xlated = 0;
01974 }
01975
01976 tprel_gotent->use_count = 1;
01977 tprel_gotent->reloc_type = R_ALPHA_GOTTPREL;
01978 }
01979 }
01980
01981 return TRUE;
01982 }
01983
01984 static bfd_boolean
01985 elf64_alpha_relax_section (abfd, sec, link_info, again)
01986 bfd *abfd;
01987 asection *sec;
01988 struct bfd_link_info *link_info;
01989 bfd_boolean *again;
01990 {
01991 Elf_Internal_Shdr *symtab_hdr;
01992 Elf_Internal_Rela *internal_relocs;
01993 Elf_Internal_Rela *irel, *irelend;
01994 Elf_Internal_Sym *isymbuf = NULL;
01995 struct alpha_elf_got_entry **local_got_entries;
01996 struct alpha_relax_info info;
01997
01998
01999 *again = FALSE;
02000
02001 if (link_info->relocatable
02002 || ((sec->flags & (SEC_CODE | SEC_RELOC | SEC_ALLOC))
02003 != (SEC_CODE | SEC_RELOC | SEC_ALLOC))
02004 || sec->reloc_count == 0)
02005 return TRUE;
02006
02007 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
02008 local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
02009
02010
02011 internal_relocs = (_bfd_elf_link_read_relocs
02012 (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
02013 link_info->keep_memory));
02014 if (internal_relocs == NULL)
02015 return FALSE;
02016
02017 memset(&info, 0, sizeof (info));
02018 info.abfd = abfd;
02019 info.sec = sec;
02020 info.link_info = link_info;
02021 info.symtab_hdr = symtab_hdr;
02022 info.relocs = internal_relocs;
02023 info.relend = irelend = internal_relocs + sec->reloc_count;
02024
02025
02026
02027 info.gotobj = alpha_elf_tdata (abfd)->gotobj;
02028 if (info.gotobj)
02029 {
02030 asection *sgot = alpha_elf_tdata (info.gotobj)->got;
02031 info.gp = (sgot->output_section->vma
02032 + sgot->output_offset
02033 + 0x8000);
02034 }
02035
02036
02037 if (elf_section_data (sec)->this_hdr.contents != NULL)
02038 info.contents = elf_section_data (sec)->this_hdr.contents;
02039 else
02040 {
02041 if (!bfd_malloc_and_get_section (abfd, sec, &info.contents))
02042 goto error_return;
02043 }
02044
02045 for (irel = internal_relocs; irel < irelend; irel++)
02046 {
02047 bfd_vma symval;
02048 struct alpha_elf_got_entry *gotent;
02049 unsigned long r_type = ELF64_R_TYPE (irel->r_info);
02050 unsigned long r_symndx = ELF64_R_SYM (irel->r_info);
02051
02052
02053 switch (r_type)
02054 {
02055 case R_ALPHA_LITERAL:
02056 case R_ALPHA_GPRELHIGH:
02057 case R_ALPHA_GPRELLOW:
02058 case R_ALPHA_GOTDTPREL:
02059 case R_ALPHA_GOTTPREL:
02060 case R_ALPHA_TLSGD:
02061 break;
02062
02063 case R_ALPHA_TLSLDM:
02064
02065
02066 r_symndx = 0;
02067 break;
02068
02069 default:
02070 continue;
02071 }
02072
02073
02074 if (r_symndx < symtab_hdr->sh_info)
02075 {
02076
02077 Elf_Internal_Sym *isym;
02078
02079
02080 if (isymbuf == NULL)
02081 {
02082 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
02083 if (isymbuf == NULL)
02084 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
02085 symtab_hdr->sh_info, 0,
02086 NULL, NULL, NULL);
02087 if (isymbuf == NULL)
02088 goto error_return;
02089 }
02090
02091 isym = isymbuf + r_symndx;
02092
02093
02094
02095 if (r_type == R_ALPHA_TLSLDM)
02096 {
02097 info.tsec = bfd_abs_section_ptr;
02098 symval = alpha_get_tprel_base (info.link_info);
02099 }
02100 else
02101 {
02102 symval = isym->st_value;
02103 if (isym->st_shndx == SHN_UNDEF)
02104 continue;
02105 else if (isym->st_shndx == SHN_ABS)
02106 info.tsec = bfd_abs_section_ptr;
02107 else if (isym->st_shndx == SHN_COMMON)
02108 info.tsec = bfd_com_section_ptr;
02109 else
02110 info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
02111 }
02112
02113 info.h = NULL;
02114 info.other = isym->st_other;
02115 if (local_got_entries)
02116 info.first_gotent = &local_got_entries[r_symndx];
02117 else
02118 {
02119 info.first_gotent = &info.gotent;
02120 info.gotent = NULL;
02121 }
02122 }
02123 else
02124 {
02125 unsigned long indx;
02126 struct alpha_elf_link_hash_entry *h;
02127
02128 indx = r_symndx - symtab_hdr->sh_info;
02129 h = alpha_elf_sym_hashes (abfd)[indx];
02130 BFD_ASSERT (h != NULL);
02131
02132 while (h->root.root.type == bfd_link_hash_indirect
02133 || h->root.root.type == bfd_link_hash_warning)
02134 h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
02135
02136
02137 if (h->root.root.type == bfd_link_hash_undefined)
02138 continue;
02139
02140
02141
02142 if (h->root.root.type == bfd_link_hash_undefweak)
02143 {
02144 info.tsec = bfd_abs_section_ptr;
02145 symval = 0;
02146 }
02147 else if (!h->root.def_regular)
02148 {
02149
02150
02151 if (r_type != R_ALPHA_TLSGD)
02152 continue;
02153 info.tsec = bfd_abs_section_ptr;
02154 symval = 0;
02155 }
02156 else
02157 {
02158 info.tsec = h->root.root.u.def.section;
02159 symval = h->root.root.u.def.value;
02160 }
02161
02162 info.h = h;
02163 info.other = h->root.other;
02164 info.first_gotent = &h->got_entries;
02165 }
02166
02167
02168 for (gotent = *info.first_gotent; gotent ; gotent = gotent->next)
02169 if (gotent->gotobj == info.gotobj
02170 && gotent->reloc_type == r_type
02171 && gotent->addend == irel->r_addend)
02172 break;
02173 info.gotent = gotent;
02174
02175 symval += info.tsec->output_section->vma + info.tsec->output_offset;
02176 symval += irel->r_addend;
02177
02178 switch (r_type)
02179 {
02180 case R_ALPHA_LITERAL:
02181 BFD_ASSERT(info.gotent != NULL);
02182
02183
02184
02185
02186 if (irel+1 < irelend
02187 && ELF64_R_TYPE (irel[1].r_info) == R_ALPHA_LITUSE)
02188 {
02189 if (!elf64_alpha_relax_with_lituse (&info, symval, irel))
02190 goto error_return;
02191 }
02192 else
02193 {
02194 if (!elf64_alpha_relax_got_load (&info, symval, irel, r_type))
02195 goto error_return;
02196 }
02197 break;
02198
02199 case R_ALPHA_GPRELHIGH:
02200 case R_ALPHA_GPRELLOW:
02201 if (!elf64_alpha_relax_gprelhilo (&info, symval, irel,
02202 r_type == R_ALPHA_GPRELHIGH))
02203 goto error_return;
02204 break;
02205
02206 case R_ALPHA_GOTDTPREL:
02207 case R_ALPHA_GOTTPREL:
02208 BFD_ASSERT(info.gotent != NULL);
02209 if (!elf64_alpha_relax_got_load (&info, symval, irel, r_type))
02210 goto error_return;
02211 break;
02212
02213 case R_ALPHA_TLSGD:
02214 case R_ALPHA_TLSLDM:
02215 BFD_ASSERT(info.gotent != NULL);
02216 if (!elf64_alpha_relax_tls_get_addr (&info, symval, irel,
02217 r_type == R_ALPHA_TLSGD))
02218 goto error_return;
02219 break;
02220 }
02221 }
02222
02223 if (!elf64_alpha_size_plt_section (link_info))
02224 return FALSE;
02225 if (!elf64_alpha_size_got_sections (link_info))
02226 return FALSE;
02227 if (!elf64_alpha_size_rela_got_section (link_info))
02228 return FALSE;
02229
02230 if (isymbuf != NULL
02231 && symtab_hdr->contents != (unsigned char *) isymbuf)
02232 {
02233 if (!link_info->keep_memory)
02234 free (isymbuf);
02235 else
02236 {
02237
02238 symtab_hdr->contents = (unsigned char *) isymbuf;
02239 }
02240 }
02241
02242 if (info.contents != NULL
02243 && elf_section_data (sec)->this_hdr.contents != info.contents)
02244 {
02245 if (!info.changed_contents && !link_info->keep_memory)
02246 free (info.contents);
02247 else
02248 {
02249
02250 elf_section_data (sec)->this_hdr.contents = info.contents;
02251 }
02252 }
02253
02254 if (elf_section_data (sec)->relocs != internal_relocs)
02255 {
02256 if (!info.changed_relocs)
02257 free (internal_relocs);
02258 else
02259 elf_section_data (sec)->relocs = internal_relocs;
02260 }
02261
02262 *again = info.changed_contents || info.changed_relocs;
02263
02264 return TRUE;
02265
02266 error_return:
02267 if (isymbuf != NULL
02268 && symtab_hdr->contents != (unsigned char *) isymbuf)
02269 free (isymbuf);
02270 if (info.contents != NULL
02271 && elf_section_data (sec)->this_hdr.contents != info.contents)
02272 free (info.contents);
02273 if (internal_relocs != NULL
02274 && elf_section_data (sec)->relocs != internal_relocs)
02275 free (internal_relocs);
02276 return FALSE;
02277 }
02278
02279
02280 #define PLT_HEADER_SIZE 32
02281 #define PLT_HEADER_WORD1 (bfd_vma) 0xc3600000
02282 #define PLT_HEADER_WORD2 (bfd_vma) 0xa77b000c
02283 #define PLT_HEADER_WORD3 (bfd_vma) 0x47ff041f
02284 #define PLT_HEADER_WORD4 (bfd_vma) 0x6b7b0000
02285
02286 #define PLT_ENTRY_SIZE 12
02287 #define PLT_ENTRY_WORD1 0xc3800000
02288 #define PLT_ENTRY_WORD2 0
02289 #define PLT_ENTRY_WORD3 0
02290
02291 #define MAX_GOT_SIZE (64*1024)
02292
02293 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so"
02294
02295
02296
02297
02298
02299
02300 static bfd_boolean
02301 elf64_alpha_section_from_shdr (abfd, hdr, name)
02302 bfd *abfd;
02303 Elf_Internal_Shdr *hdr;
02304 const char *name;
02305 {
02306 asection *newsect;
02307
02308
02309
02310
02311
02312
02313 switch (hdr->sh_type)
02314 {
02315 case SHT_ALPHA_DEBUG:
02316 if (strcmp (name, ".mdebug") != 0)
02317 return FALSE;
02318 break;
02319 default:
02320 return FALSE;
02321 }
02322
02323 if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
02324 return FALSE;
02325 newsect = hdr->bfd_section;
02326
02327 if (hdr->sh_type == SHT_ALPHA_DEBUG)
02328 {
02329 if (! bfd_set_section_flags (abfd, newsect,
02330 (bfd_get_section_flags (abfd, newsect)
02331 | SEC_DEBUGGING)))
02332 return FALSE;
02333 }
02334
02335 return TRUE;
02336 }
02337
02338
02339
02340 static bfd_boolean
02341 elf64_alpha_section_flags (flags, hdr)
02342 flagword *flags;
02343 const Elf_Internal_Shdr *hdr;
02344 {
02345 if (hdr->sh_flags & SHF_ALPHA_GPREL)
02346 *flags |= SEC_SMALL_DATA;
02347
02348 return TRUE;
02349 }
02350
02351
02352
02353
02354 static bfd_boolean
02355 elf64_alpha_fake_sections (abfd, hdr, sec)
02356 bfd *abfd;
02357 Elf_Internal_Shdr *hdr;
02358 asection *sec;
02359 {
02360 register const char *name;
02361
02362 name = bfd_get_section_name (abfd, sec);
02363
02364 if (strcmp (name, ".mdebug") == 0)
02365 {
02366 hdr->sh_type = SHT_ALPHA_DEBUG;
02367
02368
02369 if ((abfd->flags & DYNAMIC) != 0 )
02370 hdr->sh_entsize = 0;
02371 else
02372 hdr->sh_entsize = 1;
02373 }
02374 else if ((sec->flags & SEC_SMALL_DATA)
02375 || strcmp (name, ".sdata") == 0
02376 || strcmp (name, ".sbss") == 0
02377 || strcmp (name, ".lit4") == 0
02378 || strcmp (name, ".lit8") == 0)
02379 hdr->sh_flags |= SHF_ALPHA_GPREL;
02380
02381 return TRUE;
02382 }
02383
02384
02385
02386
02387 static bfd_boolean
02388 elf64_alpha_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
02389 bfd *abfd;
02390 struct bfd_link_info *info;
02391 Elf_Internal_Sym *sym;
02392 const char **namep ATTRIBUTE_UNUSED;
02393 flagword *flagsp ATTRIBUTE_UNUSED;
02394 asection **secp;
02395 bfd_vma *valp;
02396 {
02397 if (sym->st_shndx == SHN_COMMON
02398 && !info->relocatable
02399 && sym->st_size <= elf_gp_size (abfd))
02400 {
02401
02402
02403
02404 asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
02405
02406 if (scomm == NULL)
02407 {
02408 scomm = bfd_make_section (abfd, ".scommon");
02409 if (scomm == NULL
02410 || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
02411 | SEC_IS_COMMON
02412 | SEC_LINKER_CREATED)))
02413 return FALSE;
02414 }
02415
02416 *secp = scomm;
02417 *valp = sym->st_size;
02418 }
02419
02420 return TRUE;
02421 }
02422
02423
02424
02425 static bfd_boolean
02426 elf64_alpha_create_got_section(abfd, info)
02427 bfd *abfd;
02428 struct bfd_link_info *info ATTRIBUTE_UNUSED;
02429 {
02430 asection *s;
02431
02432 if ((s = bfd_get_section_by_name (abfd, ".got")))
02433 {
02434
02435 if (alpha_elf_tdata (abfd)->got == NULL)
02436 alpha_elf_tdata (abfd)->got = s;
02437 return TRUE;
02438 }
02439
02440 s = bfd_make_section (abfd, ".got");
02441 if (s == NULL
02442 || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
02443 | SEC_HAS_CONTENTS
02444 | SEC_IN_MEMORY
02445 | SEC_LINKER_CREATED))
02446 || !bfd_set_section_alignment (abfd, s, 3))
02447 return FALSE;
02448
02449 alpha_elf_tdata (abfd)->got = s;
02450
02451 return TRUE;
02452 }
02453
02454
02455
02456 static bfd_boolean
02457 elf64_alpha_create_dynamic_sections (abfd, info)
02458 bfd *abfd;
02459 struct bfd_link_info *info;
02460 {
02461 asection *s;
02462 struct elf_link_hash_entry *h;
02463 struct bfd_link_hash_entry *bh;
02464
02465
02466
02467 s = bfd_make_section (abfd, ".plt");
02468 if (s == NULL
02469 || ! bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
02470 | SEC_HAS_CONTENTS
02471 | SEC_IN_MEMORY
02472 | SEC_LINKER_CREATED
02473 | SEC_CODE))
02474 || ! bfd_set_section_alignment (abfd, s, 3))
02475 return FALSE;
02476
02477
02478
02479 bh = NULL;
02480 if (! (_bfd_generic_link_add_one_symbol
02481 (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s,
02482 (bfd_vma) 0, (const char *) NULL, FALSE,
02483 get_elf_backend_data (abfd)->collect, &bh)))
02484 return FALSE;
02485 h = (struct elf_link_hash_entry *) bh;
02486 h->def_regular = 1;
02487 h->type = STT_OBJECT;
02488
02489 if (info->shared
02490 && ! bfd_elf_link_record_dynamic_symbol (info, h))
02491 return FALSE;
02492
02493 s = bfd_make_section (abfd, ".rela.plt");
02494 if (s == NULL
02495 || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
02496 | SEC_HAS_CONTENTS
02497 | SEC_IN_MEMORY
02498 | SEC_LINKER_CREATED
02499 | SEC_READONLY))
02500 || ! bfd_set_section_alignment (abfd, s, 3))
02501 return FALSE;
02502
02503
02504
02505
02506 if (!elf64_alpha_create_got_section (abfd, info))
02507 return FALSE;
02508
02509 s = bfd_make_section(abfd, ".rela.got");
02510 if (s == NULL
02511 || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
02512 | SEC_HAS_CONTENTS
02513 | SEC_IN_MEMORY
02514 | SEC_LINKER_CREATED
02515 | SEC_READONLY))
02516 || !bfd_set_section_alignment (abfd, s, 3))
02517 return FALSE;
02518
02519
02520
02521
02522
02523 bh = NULL;
02524 if (!(_bfd_generic_link_add_one_symbol
02525 (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL,
02526 alpha_elf_tdata(abfd)->got, (bfd_vma) 0, (const char *) NULL,
02527 FALSE, get_elf_backend_data (abfd)->collect, &bh)))
02528 return FALSE;
02529 h = (struct elf_link_hash_entry *) bh;
02530 h->def_regular = 1;
02531 h->type = STT_OBJECT;
02532
02533 if (info->shared
02534 && ! bfd_elf_link_record_dynamic_symbol (info, h))
02535 return FALSE;
02536
02537 elf_hash_table (info)->hgot = h;
02538
02539 return TRUE;
02540 }
02541
02542
02543
02544
02545 static bfd_boolean
02546 elf64_alpha_read_ecoff_info (abfd, section, debug)
02547 bfd *abfd;
02548 asection *section;
02549 struct ecoff_debug_info *debug;
02550 {
02551 HDRR *symhdr;
02552 const struct ecoff_debug_swap *swap;
02553 char *ext_hdr = NULL;
02554
02555 swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
02556 memset (debug, 0, sizeof (*debug));
02557
02558 ext_hdr = (char *) bfd_malloc (swap->external_hdr_size);
02559 if (ext_hdr == NULL && swap->external_hdr_size != 0)
02560 goto error_return;
02561
02562 if (! bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0,
02563 swap->external_hdr_size))
02564 goto error_return;
02565
02566 symhdr = &debug->symbolic_header;
02567 (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr);
02568
02569
02570
02571 #define READ(ptr, offset, count, size, type) \
02572 if (symhdr->count == 0) \
02573 debug->ptr = NULL; \
02574 else \
02575 { \
02576 bfd_size_type amt = (bfd_size_type) size * symhdr->count; \
02577 debug->ptr = (type) bfd_malloc (amt); \
02578 if (debug->ptr == NULL) \
02579 goto error_return; \
02580 if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \
02581 || bfd_bread (debug->ptr, amt, abfd) != amt) \
02582 goto error_return; \
02583 }
02584
02585 READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
02586 READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR);
02587 READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR);
02588 READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR);
02589 READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR);
02590 READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext),
02591 union aux_ext *);
02592 READ (ss, cbSsOffset, issMax, sizeof (char), char *);
02593 READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
02594 READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR);
02595 READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR);
02596 READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR);
02597 #undef READ
02598
02599 debug->fdr = NULL;
02600
02601 return TRUE;
02602
02603 error_return:
02604 if (ext_hdr != NULL)
02605 free (ext_hdr);
02606 if (debug->line != NULL)
02607 free (debug->line);
02608 if (debug->external_dnr != NULL)
02609 free (debug->external_dnr);
02610 if (debug->external_pdr != NULL)
02611 free (debug->external_pdr);
02612 if (debug->external_sym != NULL)
02613 free (debug->external_sym);
02614 if (debug->external_opt != NULL)
02615 free (debug->external_opt);
02616 if (debug->external_aux != NULL)
02617 free (debug->external_aux);
02618 if (debug->ss != NULL)
02619 free (debug->ss);
02620 if (debug->ssext != NULL)
02621 free (debug->ssext);
02622 if (debug->external_fdr != NULL)
02623 free (debug->external_fdr);
02624 if (debug->external_rfd != NULL)
02625 free (debug->external_rfd);
02626 if (debug->external_ext != NULL)
02627 free (debug->external_ext);
02628 return FALSE;
02629 }
02630
02631
02632
02633 static bfd_boolean
02634 elf64_alpha_is_local_label_name (abfd, name)
02635 bfd *abfd ATTRIBUTE_UNUSED;
02636 const char *name;
02637 {
02638 return name[0] == '$';
02639 }
02640
02641
02642
02643
02644
02645
02646 struct mips_elf_find_line
02647 {
02648 struct ecoff_debug_info d;
02649 struct ecoff_find_line i;
02650 };
02651
02652 static bfd_boolean
02653 elf64_alpha_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
02654 functionname_ptr, line_ptr)
02655 bfd *abfd;
02656 asection *section;
02657 asymbol **symbols;
02658 bfd_vma offset;
02659 const char **filename_ptr;
02660 const char **functionname_ptr;
02661 unsigned int *line_ptr;
02662 {
02663 asection *msec;
02664
02665 if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
02666 filename_ptr, functionname_ptr,
02667 line_ptr, 0,
02668 &elf_tdata (abfd)->dwarf2_find_line_info))
02669 return TRUE;
02670
02671 msec = bfd_get_section_by_name (abfd, ".mdebug");
02672 if (msec != NULL)
02673 {
02674 flagword origflags;
02675 struct mips_elf_find_line *fi;
02676 const struct ecoff_debug_swap * const swap =
02677 get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
02678
02679
02680
02681
02682 origflags = msec->flags;
02683 if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS)
02684 msec->flags |= SEC_HAS_CONTENTS;
02685
02686 fi = elf_tdata (abfd)->find_line_info;
02687 if (fi == NULL)
02688 {
02689 bfd_size_type external_fdr_size;
02690 char *fraw_src;
02691 char *fraw_end;
02692 struct fdr *fdr_ptr;
02693 bfd_size_type amt = sizeof (struct mips_elf_find_line);
02694
02695 fi = (struct mips_elf_find_line *) bfd_zalloc (abfd, amt);
02696 if (fi == NULL)
02697 {
02698 msec->flags = origflags;
02699 return FALSE;
02700 }
02701
02702 if (!elf64_alpha_read_ecoff_info (abfd, msec, &fi->d))
02703 {
02704 msec->flags = origflags;
02705 return FALSE;
02706 }
02707
02708
02709 amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr);
02710 fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt);
02711 if (fi->d.fdr == NULL)
02712 {
02713 msec->flags = origflags;
02714 return FALSE;
02715 }
02716 external_fdr_size = swap->external_fdr_size;
02717 fdr_ptr = fi->d.fdr;
02718 fraw_src = (char *) fi->d.external_fdr;
02719 fraw_end = (fraw_src
02720 + fi->d.symbolic_header.ifdMax * external_fdr_size);
02721 for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
02722 (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
02723
02724 elf_tdata (abfd)->find_line_info = fi;
02725
02726
02727
02728
02729
02730
02731
02732 }
02733
02734 if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap,
02735 &fi->i, filename_ptr, functionname_ptr,
02736 line_ptr))
02737 {
02738 msec->flags = origflags;
02739 return TRUE;
02740 }
02741
02742 msec->flags = origflags;
02743 }
02744
02745
02746
02747 return _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
02748 filename_ptr, functionname_ptr,
02749 line_ptr);
02750 }
02751
02752
02753
02754 struct extsym_info
02755 {
02756 bfd *abfd;
02757 struct bfd_link_info *info;
02758 struct ecoff_debug_info *debug;
02759 const struct ecoff_debug_swap *swap;
02760 bfd_boolean failed;
02761 };
02762
02763 static bfd_boolean
02764 elf64_alpha_output_extsym (h, data)
02765 struct alpha_elf_link_hash_entry *h;
02766 PTR data;
02767 {
02768 struct extsym_info *einfo = (struct extsym_info *) data;
02769 bfd_boolean strip;
02770 asection *sec, *output_section;
02771
02772 if (h->root.root.type == bfd_link_hash_warning)
02773 h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
02774
02775 if (h->root.indx == -2)
02776 strip = FALSE;
02777 else if ((h->root.def_dynamic
02778 || h->root.ref_dynamic
02779 || h->root.root.type == bfd_link_hash_new)
02780 && !h->root.def_regular
02781 && !h->root.ref_regular)
02782 strip = TRUE;
02783 else if (einfo->info->strip == strip_all
02784 || (einfo->info->strip == strip_some
02785 && bfd_hash_lookup (einfo->info->keep_hash,
02786 h->root.root.root.string,
02787 FALSE, FALSE) == NULL))
02788 strip = TRUE;
02789 else
02790 strip = FALSE;
02791
02792 if (strip)
02793 return TRUE;
02794
02795 if (h->esym.ifd == -2)
02796 {
02797 h->esym.jmptbl = 0;
02798 h->esym.cobol_main = 0;
02799 h->esym.weakext = 0;
02800 h->esym.reserved = 0;
02801 h->esym.ifd = ifdNil;
02802 h->esym.asym.value = 0;
02803 h->esym.asym.st = stGlobal;
02804
02805 if (h->root.root.type != bfd_link_hash_defined
02806 && h->root.root.type != bfd_link_hash_defweak)
02807 h->esym.asym.sc = scAbs;
02808 else
02809 {
02810 const char *name;
02811
02812 sec = h->root.root.u.def.section;
02813 output_section = sec->output_section;
02814
02815
02816
02817 if (output_section == NULL)
02818 h->esym.asym.sc = scUndefined;
02819 else
02820 {
02821 name = bfd_section_name (output_section->owner, output_section);
02822
02823 if (strcmp (name, ".text") == 0)
02824 h->esym.asym.sc = scText;
02825 else if (strcmp (name, ".data") == 0)
02826 h->esym.asym.sc = scData;
02827 else if (strcmp (name, ".sdata") == 0)
02828 h->esym.asym.sc = scSData;
02829 else if (strcmp (name, ".rodata") == 0
02830 || strcmp (name, ".rdata") == 0)
02831 h->esym.asym.sc = scRData;
02832 else if (strcmp (name, ".bss") == 0)
02833 h->esym.asym.sc = scBss;
02834 else if (strcmp (name, ".sbss") == 0)
02835 h->esym.asym.sc = scSBss;
02836 else if (strcmp (name, ".init") == 0)
02837 h->esym.asym.sc = scInit;
02838 else if (strcmp (name, ".fini") == 0)
02839 h->esym.asym.sc = scFini;
02840 else
02841 h->esym.asym.sc = scAbs;
02842 }
02843 }
02844
02845 h->esym.asym.reserved = 0;
02846 h->esym.asym.index = indexNil;
02847 }
02848
02849 if (h->root.root.type == bfd_link_hash_common)
02850 h->esym.asym.value = h->root.root.u.c.size;
02851 else if (h->root.root.type == bfd_link_hash_defined
02852 || h->root.root.type == bfd_link_hash_defweak)
02853 {
02854 if (h->esym.asym.sc == scCommon)
02855 h->esym.asym.sc = scBss;
02856 else if (h->esym.asym.sc == scSCommon)
02857 h->esym.asym.sc = scSBss;
02858
02859 sec = h->root.root.u.def.section;
02860 output_section = sec->output_section;
02861 if (output_section != NULL)
02862 h->esym.asym.value = (h->root.root.u.def.value
02863 + sec->output_offset
02864 + output_section->vma);
02865 else
02866 h->esym.asym.value = 0;
02867 }
02868 else if (h->root.needs_plt)
02869 {
02870
02871 h->esym.asym.st = stProc;
02872 sec = bfd_get_section_by_name (einfo->abfd, ".plt");
02873 if (sec == NULL)
02874 h->esym.asym.value = 0;
02875 else
02876 {
02877 output_section = sec->output_section;
02878 if (output_section != NULL)
02879 h->esym.asym.value = (h->root.plt.offset
02880 + sec->output_offset
02881 + output_section->vma);
02882 else
02883 h->esym.asym.value = 0;
02884 }
02885 }
02886
02887 if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
02888 h->root.root.root.string,
02889 &h->esym))
02890 {
02891 einfo->failed = TRUE;
02892 return FALSE;
02893 }
02894
02895 return TRUE;
02896 }
02897
02898
02899
02900 static struct alpha_elf_got_entry *
02901 get_got_entry (abfd, h, r_type, r_symndx, r_addend)
02902 bfd *abfd;
02903 struct alpha_elf_link_hash_entry *h;
02904 unsigned long r_type, r_symndx;
02905 bfd_vma r_addend;
02906 {
02907 struct alpha_elf_got_entry *gotent;
02908 struct alpha_elf_got_entry **slot;
02909
02910 if (h)
02911 slot = &h->got_entries;
02912 else
02913 {
02914
02915
02916 struct alpha_elf_got_entry **local_got_entries;
02917
02918 local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
02919 if (!local_got_entries)
02920 {
02921 bfd_size_type size;
02922 Elf_Internal_Shdr *symtab_hdr;
02923
02924 symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
02925 size = symtab_hdr->sh_info;
02926 size *= sizeof (struct alpha_elf_got_entry *);
02927
02928 local_got_entries
02929 = (struct alpha_elf_got_entry **) bfd_zalloc (abfd, size);
02930 if (!local_got_entries)
02931 return NULL;
02932
02933 alpha_elf_tdata (abfd)->local_got_entries = local_got_entries;
02934 }
02935
02936 slot = &local_got_entries[r_symndx];
02937 }
02938
02939 for (gotent = *slot; gotent ; gotent = gotent->next)
02940 if (gotent->gotobj == abfd
02941 && gotent->reloc_type == r_type
02942 && gotent->addend == r_addend)
02943 break;
02944
02945 if (!gotent)
02946 {
02947 int entry_size;
02948 bfd_size_type amt;
02949
02950 amt = sizeof (struct alpha_elf_got_entry);
02951 gotent = (struct alpha_elf_got_entry *) bfd_alloc (abfd, amt);
02952 if (!gotent)
02953 return NULL;
02954
02955 gotent->gotobj = abfd;
02956 gotent->addend = r_addend;
02957 gotent->got_offset = -1;
02958 gotent->use_count = 1;
02959 gotent->reloc_type = r_type;
02960 gotent->reloc_done = 0;
02961 gotent->reloc_xlated = 0;
02962
02963 gotent->next = *slot;
02964 *slot = gotent;
02965
02966 entry_size = alpha_got_entry_size (r_type);
02967 alpha_elf_tdata (abfd)->total_got_size += entry_size;
02968 if (!h)
02969 alpha_elf_tdata(abfd)->local_got_size += entry_size;
02970 }
02971 else
02972 gotent->use_count += 1;
02973
02974 return gotent;
02975 }
02976
02977
02978
02979 static bfd_boolean
02980 elf64_alpha_check_relocs (abfd, info, sec, relocs)
02981 bfd *abfd;
02982 struct bfd_link_info *info;
02983 asection *sec;
02984 const Elf_Internal_Rela *relocs;
02985 {
02986 bfd *dynobj;
02987 asection *sreloc;
02988 const char *rel_sec_name;
02989 Elf_Internal_Shdr *symtab_hdr;
02990 struct alpha_elf_link_hash_entry **sym_hashes;
02991 const Elf_Internal_Rela *rel, *relend;
02992 bfd_boolean got_created;
02993 bfd_size_type amt;
02994
02995 if (info->relocatable)
02996 return TRUE;
02997
02998
02999
03000
03001
03002
03003
03004 if ((sec->flags & SEC_ALLOC) == 0)
03005 return TRUE;
03006
03007 dynobj = elf_hash_table(info)->dynobj;
03008 if (dynobj == NULL)
03009 elf_hash_table(info)->dynobj = dynobj = abfd;
03010
03011 sreloc = NULL;
03012 rel_sec_name = NULL;
03013 symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
03014 sym_hashes = alpha_elf_sym_hashes(abfd);
03015 got_created = FALSE;
03016
03017 relend = relocs + sec->reloc_count;
03018 for (rel = relocs; rel < relend; ++rel)
03019 {
03020 enum {
03021 NEED_GOT = 1,
03022 NEED_GOT_ENTRY = 2,
03023 NEED_DYNREL = 4
03024 };
03025
03026 unsigned long r_symndx, r_type;
03027 struct alpha_elf_link_hash_entry *h;
03028 unsigned int gotent_flags;
03029 bfd_boolean maybe_dynamic;
03030 unsigned int need;
03031 bfd_vma addend;
03032
03033 r_symndx = ELF64_R_SYM (rel->r_info);
03034 if (r_symndx < symtab_hdr->sh_info)
03035 h = NULL;
03036 else
03037 {
03038 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
03039
03040 while (h->root.root.type == bfd_link_hash_indirect
03041 || h->root.root.type == bfd_link_hash_warning)
03042 h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
03043
03044 h->root.ref_regular = 1;
03045 }
03046
03047
03048
03049
03050
03051 maybe_dynamic = FALSE;
03052 if (h && ((info->shared
03053 && (!info->symbolic || info->unresolved_syms_in_shared_libs == RM_IGNORE))
03054 || !h->root.def_regular
03055 || h->root.root.type == bfd_link_hash_defweak))
03056 maybe_dynamic = TRUE;
03057
03058 need = 0;
03059 gotent_flags = 0;
03060 r_type = ELF64_R_TYPE (rel->r_info);
03061 addend = rel->r_addend;
03062
03063 switch (r_type)
03064 {
03065 case R_ALPHA_LITERAL:
03066 need = NEED_GOT | NEED_GOT_ENTRY;
03067
03068
03069
03070
03071 while (++rel < relend && ELF64_R_TYPE (rel->r_info) == R_ALPHA_LITUSE)
03072 if (rel->r_addend >= 1 && rel->r_addend <= 5)
03073 gotent_flags |= 1 << rel->r_addend;
03074 --rel;
03075
03076
03077 if (gotent_flags == 0)
03078 gotent_flags = ALPHA_ELF_LINK_HASH_LU_ADDR;
03079 break;
03080
03081 case R_ALPHA_GPDISP:
03082 case R_ALPHA_GPREL16:
03083 case R_ALPHA_GPREL32:
03084 case R_ALPHA_GPRELHIGH:
03085 case R_ALPHA_GPRELLOW:
03086 case R_ALPHA_BRSGP:
03087 need = NEED_GOT;
03088 break;
03089
03090 case R_ALPHA_REFLONG:
03091 case R_ALPHA_REFQUAD:
03092 if (info->shared || maybe_dynamic)
03093 need = NEED_DYNREL;
03094 break;
03095
03096 case R_ALPHA_TLSLDM:
03097
03098
03099 r_symndx = 0;
03100 h = 0;
03101 maybe_dynamic = FALSE;
03102
03103
03104 case R_ALPHA_TLSGD:
03105 case R_ALPHA_GOTDTPREL:
03106 need = NEED_GOT | NEED_GOT_ENTRY;
03107 break;
03108
03109 case R_ALPHA_GOTTPREL:
03110 need = NEED_GOT | NEED_GOT_ENTRY;
03111 gotent_flags = ALPHA_ELF_LINK_HASH_TLS_IE;
03112 if (info->shared)
03113 info->flags |= DF_STATIC_TLS;
03114 break;
03115
03116 case R_ALPHA_TPREL64:
03117 if (info->shared || maybe_dynamic)
03118 need = NEED_DYNREL;
03119 if (info->shared)
03120 info->flags |= DF_STATIC_TLS;
03121 break;
03122 }
03123
03124 if (need & NEED_GOT)
03125 {
03126 if (!got_created)
03127 {
03128 if (!elf64_alpha_create_got_section (abfd, info))
03129 return FALSE;
03130
03131
03132
03133
03134
03135 alpha_elf_tdata(abfd)->gotobj = abfd;
03136
03137 got_created = 1;
03138 }
03139 }
03140
03141 if (need & NEED_GOT_ENTRY)
03142 {
03143 struct alpha_elf_got_entry *gotent;
03144
03145 gotent = get_got_entry (abfd, h, r_type, r_symndx, addend);
03146 if (!gotent)
03147 return FALSE;
03148
03149 if (gotent_flags)
03150 {
03151 gotent->flags |= gotent_flags;
03152 if (h)
03153 {
03154 gotent_flags |= h->flags;
03155 h->flags = gotent_flags;
03156
03157
03158 if ((gotent_flags & ALPHA_ELF_LINK_HASH_LU_FUNC)
03159 && !(gotent_flags & ~ALPHA_ELF_LINK_HASH_LU_FUNC))
03160 h->root.needs_plt = 1;
03161 else
03162 h->root.needs_plt = 0;
03163 }
03164 }
03165 }
03166
03167 if (need & NEED_DYNREL)
03168 {
03169 if (rel_sec_name == NULL)
03170 {
03171 rel_sec_name = (bfd_elf_string_from_elf_section
03172 (abfd, elf_elfheader(abfd)->e_shstrndx,
03173 elf_section_data(sec)->rel_hdr.sh_name));
03174 if (rel_sec_name == NULL)
03175 return FALSE;
03176
03177 BFD_ASSERT (strncmp (rel_sec_name, ".rela", 5) == 0
03178 && strcmp (bfd_get_section_name (abfd, sec),
03179 rel_sec_name+5) == 0);
03180 }
03181
03182
03183
03184
03185
03186 if (sreloc == NULL)
03187 {
03188 sreloc = bfd_get_section_by_name (dynobj, rel_sec_name);
03189 if (sreloc == NULL)
03190 {
03191 flagword flags;
03192
03193 sreloc = bfd_make_section (dynobj, rel_sec_name);
03194 flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
03195 | SEC_LINKER_CREATED | SEC_READONLY);
03196 if (sec->flags & SEC_ALLOC)
03197 flags |= SEC_ALLOC | SEC_LOAD;
03198 if (sreloc == NULL
03199 || !bfd_set_section_flags (dynobj, sreloc, flags)
03200 || !bfd_set_section_alignment (dynobj, sreloc, 3))
03201 return FALSE;
03202 }
03203 }
03204
03205 if (h)
03206 {
03207
03208
03209
03210
03211
03212
03213 struct alpha_elf_reloc_entry *rent;
03214
03215 for (rent = h->reloc_entries; rent; rent = rent->next)
03216 if (rent->rtype == r_type && rent->srel == sreloc)
03217 break;
03218
03219 if (!rent)
03220 {
03221 amt = sizeof (struct alpha_elf_reloc_entry);
03222 rent = (struct alpha_elf_reloc_entry *) bfd_alloc (abfd, amt);
03223 if (!rent)
03224 return FALSE;
03225
03226 rent->srel = sreloc;
03227 rent->rtype = r_type;
03228 rent->count = 1;
03229 rent->reltext = (sec->flags & SEC_READONLY) != 0;
03230
03231 rent->next = h->reloc_entries;
03232 h->reloc_entries = rent;
03233 }
03234 else
03235 rent->count++;
03236 }
03237 else if (info->shared)
03238 {
03239
03240
03241 sreloc->size += sizeof (Elf64_External_Rela);
03242 if (sec->flags & SEC_READONLY)
03243 info->flags |= DF_TEXTREL;
03244 }
03245 }
03246 }
03247
03248 return TRUE;
03249 }
03250
03251
03252
03253
03254
03255
03256
03257 static bfd_boolean
03258 elf64_alpha_adjust_dynamic_symbol (info, h)
03259 struct bfd_link_info *info;
03260 struct elf_link_hash_entry *h;
03261 {
03262 bfd *dynobj;
03263 asection *s;
03264 struct alpha_elf_link_hash_entry *ah;
03265
03266 dynobj = elf_hash_table(info)->dynobj;
03267 ah = (struct alpha_elf_link_hash_entry *)h;
03268
03269
03270
03271
03272 if (alpha_elf_dynamic_symbol_p (h, info)
03273 && ((h->type == STT_FUNC
03274 && !(ah->flags & ALPHA_ELF_LINK_HASH_LU_ADDR))
03275 || (h->type == STT_NOTYPE
03276 && (ah->flags & ALPHA_ELF_LINK_HASH_LU_FUNC)
03277 && !(ah->flags & ~ALPHA_ELF_LINK_HASH_LU_FUNC)))
03278
03279
03280
03281
03282 && ah->got_entries)
03283 {
03284 h->needs_plt = 1;
03285
03286 s = bfd_get_section_by_name(dynobj, ".plt");
03287 if (!s && !elf64_alpha_create_dynamic_sections (dynobj, info))
03288 return FALSE;
03289
03290
03291 if (s->size == 0)
03292 s->size = PLT_HEADER_SIZE;
03293
03294 h->plt.offset = s->size;
03295 s->size += PLT_ENTRY_SIZE;
03296
03297
03298
03299
03300
03301 if (! info->shared
03302 && h->root.type != bfd_link_hash_defweak)
03303 {
03304 ah->plt_old_section = h->root.u.def.section;
03305 ah->plt_old_value = h->root.u.def.value;
03306 ah->flags |= ALPHA_ELF_LINK_HASH_PLT_LOC;
03307 h->root.u.def.section = s;
03308 h->root.u.def.value = h->plt.offset;
03309 }
03310
03311
03312 s = bfd_get_section_by_name (dynobj, ".rela.plt");
03313 BFD_ASSERT (s != NULL);
03314 s->size += sizeof (Elf64_External_Rela);
03315
03316 return TRUE;
03317 }
03318 else
03319 h->needs_plt = 0;
03320
03321
03322
03323
03324 if (h->u.weakdef != NULL)
03325 {
03326 BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
03327 || h->u.weakdef->root.type == bfd_link_hash_defweak);
03328 h->root.u.def.section = h->u.weakdef->root.u.def.section;
03329 h->root.u.def.value = h->u.weakdef->root.u.def.value;
03330 return TRUE;
03331 }
03332
03333
03334
03335
03336
03337
03338 return TRUE;
03339 }
03340
03341
03342
03343
03344
03345 static bfd_boolean
03346 elf64_alpha_merge_ind_symbols (hi, dummy)
03347 struct alpha_elf_link_hash_entry *hi;
03348 PTR dummy ATTRIBUTE_UNUSED;
03349 {
03350 struct alpha_elf_link_hash_entry *hs;
03351
03352 if (hi->root.root.type != bfd_link_hash_indirect)
03353 return TRUE;
03354 hs = hi;
03355 do {
03356 hs = (struct alpha_elf_link_hash_entry *)hs->root.root.u.i.link;
03357 } while (hs->root.root.type == bfd_link_hash_indirect);
03358
03359
03360
03361 hs->flags |= hi->flags;
03362
03363
03364
03365
03366 if (hs->got_entries == NULL)
03367 hs->got_entries = hi->got_entries;
03368 else
03369 {
03370 struct alpha_elf_got_entry *gi, *gs, *gin, *gsh;
03371
03372 gsh = hs->got_entries;
03373 for (gi = hi->got_entries; gi ; gi = gin)
03374 {
03375 gin = gi->next;
03376 for (gs = gsh; gs ; gs = gs->next)
03377 if (gi->gotobj == gs->gotobj
03378 && gi->reloc_type == gs->reloc_type
03379 && gi->addend == gs->addend)
03380 {
03381 gi->use_count += gs->use_count;
03382 goto got_found;
03383 }
03384 gi->next = hs->got_entries;
03385 hs->got_entries = gi;
03386 got_found:;
03387 }
03388 }
03389 hi->got_entries = NULL;
03390
03391
03392
03393 if (hs->reloc_entries == NULL)
03394 hs->reloc_entries = hi->reloc_entries;
03395 else
03396 {
03397 struct alpha_elf_reloc_entry *ri, *rs, *rin, *rsh;
03398
03399 rsh = hs->reloc_entries;
03400 for (ri = hi->reloc_entries; ri ; ri = rin)
03401 {
03402 rin = ri->next;
03403 for (rs = rsh; rs ; rs = rs->next)
03404 if (ri->rtype == rs->rtype && ri->srel == rs->srel)
03405 {
03406 rs->count += ri->count;
03407 goto found_reloc;
03408 }
03409 ri->next = hs->reloc_entries;
03410 hs->reloc_entries = ri;
03411 found_reloc:;
03412 }
03413 }
03414 hi->reloc_entries = NULL;
03415
03416 return TRUE;
03417 }
03418
03419
03420
03421 static bfd_boolean
03422 elf64_alpha_can_merge_gots (a, b)
03423 bfd *a, *b;
03424 {
03425 int total = alpha_elf_tdata (a)->total_got_size;
03426 bfd *bsub;
03427
03428
03429 if (total + alpha_elf_tdata (b)->total_got_size <= MAX_GOT_SIZE)
03430 return TRUE;
03431
03432
03433 if ((total += alpha_elf_tdata (b)->local_got_size) > MAX_GOT_SIZE)
03434 return FALSE;
03435
03436
03437
03438
03439 for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
03440 {
03441 struct alpha_elf_link_hash_entry **hashes = alpha_elf_sym_hashes (bsub);
03442 Elf_Internal_Shdr *symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
03443 int i, n;
03444
03445 n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
03446 for (i = 0; i < n; ++i)
03447 {
03448 struct alpha_elf_got_entry *ae, *be;
03449 struct alpha_elf_link_hash_entry *h;
03450
03451 h = hashes[i];
03452 while (h->root.root.type == bfd_link_hash_indirect
03453 || h->root.root.type == bfd_link_hash_warning)
03454 h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
03455
03456 for (be = h->got_entries; be ; be = be->next)
03457 {
03458 if (be->use_count == 0)
03459 continue;
03460 if (be->gotobj != b)
03461 continue;
03462
03463 for (ae = h->got_entries; ae ; ae = ae->next)
03464 if (ae->gotobj == a
03465 && ae->reloc_type == be->reloc_type
03466 && ae->addend == be->addend)
03467 goto global_found;
03468
03469 total += alpha_got_entry_size (be->reloc_type);
03470 if (total > MAX_GOT_SIZE)
03471 return FALSE;
03472 global_found:;
03473 }
03474 }
03475 }
03476
03477 return TRUE;
03478 }
03479
03480
03481
03482 static void
03483 elf64_alpha_merge_gots (a, b)
03484 bfd *a, *b;
03485 {
03486 int total = alpha_elf_tdata (a)->total_got_size;
03487 bfd *bsub;
03488
03489
03490 {
03491 int e = alpha_elf_tdata (b)->local_got_size;
03492 total += e;
03493 alpha_elf_tdata (a)->local_got_size += e;
03494 }
03495
03496 for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
03497 {
03498 struct alpha_elf_got_entry **local_got_entries;
03499 struct alpha_elf_link_hash_entry **hashes;
03500 Elf_Internal_Shdr *symtab_hdr;
03501 int i, n;
03502
03503
03504 local_got_entries = alpha_elf_tdata (bsub)->local_got_entries;
03505 if (local_got_entries)
03506 {
03507 n = elf_tdata (bsub)->symtab_hdr.sh_info;
03508 for (i = 0; i < n; ++i)
03509 {
03510 struct alpha_elf_got_entry *ent;
03511 for (ent = local_got_entries[i]; ent; ent = ent->next)
03512 ent->gotobj = a;
03513 }
03514 }
03515
03516
03517 hashes = alpha_elf_sym_hashes (bsub);
03518 symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
03519
03520 n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
03521 for (i = 0; i < n; ++i)
03522 {
03523 struct alpha_elf_got_entry *ae, *be, **pbe, **start;
03524 struct alpha_elf_link_hash_entry *h;
03525
03526 h = hashes[i];
03527 while (h->root.root.type == bfd_link_hash_indirect
03528 || h->root.root.type == bfd_link_hash_warning)
03529 h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
03530
03531 start = &h->got_entries;
03532 for (pbe = start, be = *start; be ; pbe = &be->next, be = be->next)
03533 {
03534 if (be->use_count == 0)
03535 {
03536 *pbe = be->next;
03537 continue;
03538 }
03539 if (be->gotobj != b)
03540 continue;
03541
03542 for (ae = *start; ae ; ae = ae->next)
03543 if (ae->gotobj == a
03544 && ae->reloc_type == be->reloc_type
03545 && ae->addend == be->addend)
03546 {
03547 ae->flags |= be->flags;
03548 ae->use_count += be->use_count;
03549 *pbe = be->next;
03550 goto global_found;
03551 }
03552 be->gotobj = a;
03553 total += alpha_got_entry_size (be->reloc_type);
03554
03555 global_found:;
03556 }
03557 }
03558
03559 alpha_elf_tdata (bsub)->gotobj = a;
03560 }
03561 alpha_elf_tdata (a)->total_got_size = total;
03562
03563
03564 {
03565 bfd *next;
03566
03567 bsub = a;
03568 while ((next = alpha_elf_tdata (bsub)->in_got_link_next) != NULL)
03569 bsub = next;
03570
03571 alpha_elf_tdata (bsub)->in_got_link_next = b;
03572 }
03573 }
03574
03575
03576
03577 static bfd_boolean
03578 elf64_alpha_calc_got_offsets_for_symbol (h, arg)
03579 struct alpha_elf_link_hash_entry *h;
03580 PTR arg ATTRIBUTE_UNUSED;
03581 {
03582 bfd_boolean result = TRUE;
03583 struct alpha_elf_got_entry *gotent;
03584
03585 if (h->root.root.type == bfd_link_hash_warning)
03586 h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
03587
03588 for (gotent = h->got_entries; gotent; gotent = gotent->next)
03589 if (gotent->use_count > 0)
03590 {
03591 struct alpha_elf_obj_tdata *td;
03592 bfd_size_type *plge;
03593
03594 td = alpha_elf_tdata (gotent->gotobj);
03595 if (td == NULL)
03596 {
03597 _bfd_error_handler (_("Symbol %s has no GOT subsection for offset 0x%x"),
03598 h->root.root.root.string, gotent->got_offset);
03599 result = FALSE;
03600 continue;
03601 }
03602 plge = &td->got->size;
03603 gotent->got_offset = *plge;
03604 *plge += alpha_got_entry_size (gotent->reloc_type);
03605 }
03606
03607 return result;
03608 }
03609
03610 static void
03611 elf64_alpha_calc_got_offsets (info)
03612 struct bfd_link_info *info;
03613 {
03614 bfd *i, *got_list = alpha_elf_hash_table(info)->got_list;
03615
03616
03617
03618 for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next)
03619 alpha_elf_tdata(i)->got->size = 0;
03620
03621
03622 alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
03623 elf64_alpha_calc_got_offsets_for_symbol,
03624 NULL);
03625
03626
03627 for (i = got_list; i ; i = alpha_elf_tdata(i)->got_link_next)
03628 {
03629 bfd_size_type got_offset = alpha_elf_tdata(i)->got->size;
03630 bfd *j;
03631
03632 for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next)
03633 {
03634 struct alpha_elf_got_entry **local_got_entries, *gotent;
03635 int k, n;
03636
03637 local_got_entries = alpha_elf_tdata(j)->local_got_entries;
03638 if (!local_got_entries)
03639 continue;
03640
03641 for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k)
03642 for (gotent = local_got_entries[k]; gotent; gotent = gotent->next)
03643 if (gotent->use_count > 0)
03644 {
03645 gotent->got_offset = got_offset;
03646 got_offset += alpha_got_entry_size (gotent->reloc_type);
03647 }
03648 }
03649
03650 alpha_elf_tdata(i)->got->size = got_offset;
03651 }
03652 }
03653
03654
03655
03656 static bfd_boolean
03657 elf64_alpha_size_got_sections (info)
03658 struct bfd_link_info *info;
03659 {
03660 bfd *i, *got_list, *cur_got_obj = NULL;
03661 int something_changed = 0;
03662
03663 got_list = alpha_elf_hash_table (info)->got_list;
03664
03665
03666
03667 if (got_list == NULL)
03668 {
03669 for (i = info->input_bfds; i ; i = i->link_next)
03670 {
03671 bfd *this_got = alpha_elf_tdata (i)->gotobj;
03672 if (this_got == NULL)
03673 continue;
03674
03675
03676 BFD_ASSERT (this_got == i);
03677
03678 if (alpha_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE)
03679 {
03680
03681 (*_bfd_error_handler)
03682 (_("%B: .got subsegment exceeds 64K (size %d)"),
03683 i, alpha_elf_tdata (this_got)->total_got_size);
03684 return FALSE;
03685 }
03686
03687 if (got_list == NULL)
03688 got_list = this_got;
03689 else
03690 alpha_elf_tdata(cur_got_obj)->got_link_next = this_got;
03691 cur_got_obj = this_got;
03692 }
03693
03694
03695 if (got_list == NULL)
03696 return TRUE;
03697
03698 alpha_elf_hash_table (info)->got_list = got_list;
03699
03700
03701 something_changed = 1;
03702 }
03703
03704 cur_got_obj = got_list;
03705 i = alpha_elf_tdata(cur_got_obj)->got_link_next;
03706 while (i != NULL)
03707 {
03708 if (elf64_alpha_can_merge_gots (cur_got_obj, i))
03709 {
03710 elf64_alpha_merge_gots (cur_got_obj, i);
03711 i = alpha_elf_tdata(i)->got_link_next;
03712 alpha_elf_tdata(cur_got_obj)->got_link_next = i;
03713 something_changed = 1;
03714 }
03715 else
03716 {
03717 cur_got_obj = i;
03718 i = alpha_elf_tdata(i)->got_link_next;
03719 }
03720 }
03721
03722
03723
03724 if (1 || something_changed)
03725 elf64_alpha_calc_got_offsets (info);
03726
03727 return TRUE;
03728 }
03729
03730
03731
03732
03733 static bfd_boolean
03734 elf64_alpha_size_plt_section (info)
03735 struct bfd_link_info *info;
03736 {
03737 asection *splt, *spltrel;
03738 unsigned long entries;
03739 bfd *dynobj;
03740
03741 dynobj = elf_hash_table(info)->dynobj;
03742 splt = bfd_get_section_by_name(dynobj, ".plt");
03743 if (splt == NULL)
03744 return TRUE;
03745
03746 splt->size = 0;
03747
03748 alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
03749 elf64_alpha_size_plt_section_1, splt);
03750
03751
03752 spltrel = bfd_get_section_by_name (dynobj, ".rela.plt");
03753 if (splt->size)
03754 entries = (splt->size - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
03755 else
03756 entries = 0;
03757 spltrel->size = entries * sizeof (Elf64_External_Rela);
03758
03759 return TRUE;
03760 }
03761
03762 static bfd_boolean
03763 elf64_alpha_size_plt_section_1 (h, data)
03764 struct alpha_elf_link_hash_entry *h;
03765 PTR data;
03766 {
03767 asection *splt = (asection *) data;
03768 struct alpha_elf_got_entry *gotent;
03769
03770
03771 if (!h->root.needs_plt)
03772 return TRUE;
03773
03774
03775 for (gotent = h->got_entries; gotent ; gotent = gotent->next)
03776 if (gotent->reloc_type == R_ALPHA_LITERAL
03777 && gotent->use_count > 0)
03778 break;
03779
03780
03781
03782 if (gotent)
03783 {
03784 if (splt->size == 0)
03785 splt->size = PLT_HEADER_SIZE;
03786 h->root.plt.offset = splt->size;
03787 splt->size += PLT_ENTRY_SIZE;
03788 }
03789 else
03790 {
03791 h->root.needs_plt = 0;
03792 h->root.plt.offset = -1;
03793
03794
03795 if (h->flags & ALPHA_ELF_LINK_HASH_PLT_LOC)
03796 {
03797 h->root.root.u.def.section = h->plt_old_section;
03798 h->root.root.u.def.value = h->plt_old_value;
03799 h->flags &= ~ALPHA_ELF_LINK_HASH_PLT_LOC;
03800 }
03801 }
03802
03803 return TRUE;
03804 }
03805
03806 static bfd_boolean
03807 elf64_alpha_always_size_sections (output_bfd, info)
03808 bfd *output_bfd ATTRIBUTE_UNUSED;
03809 struct bfd_link_info *info;
03810 {
03811 bfd *i;
03812
03813 if (info->relocatable)
03814 return TRUE;
03815
03816
03817 alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
03818 elf64_alpha_merge_ind_symbols,
03819 NULL);
03820
03821 if (!elf64_alpha_size_got_sections (info))
03822 return FALSE;
03823
03824
03825 i = alpha_elf_hash_table (info)->got_list;
03826 for ( ; i ; i = alpha_elf_tdata(i)->got_link_next)
03827 {
03828 asection *s = alpha_elf_tdata(i)->got;
03829 if (s->size > 0)
03830 {
03831 s->contents = (bfd_byte *) bfd_zalloc (i, s->size);
03832 if (s->contents == NULL)
03833 return FALSE;
03834 }
03835 }
03836
03837 return TRUE;
03838 }
03839
03840
03841
03842 static int
03843 alpha_dynamic_entries_for_reloc (r_type, dynamic, shared)
03844 int r_type, dynamic, shared;
03845 {
03846 switch (r_type)
03847 {
03848
03849 case R_ALPHA_TLSGD:
03850 return (dynamic ? 2 : shared ? 1 : 0);
03851 case R_ALPHA_TLSLDM:
03852 return shared;
03853 case R_ALPHA_LITERAL:
03854 case R_ALPHA_GOTTPREL:
03855 return dynamic || shared;
03856 case R_ALPHA_GOTDTPREL:
03857 return dynamic;
03858
03859
03860 case R_ALPHA_REFLONG:
03861 case R_ALPHA_REFQUAD:
03862 case R_ALPHA_TPREL64:
03863 return dynamic || shared;
03864
03865
03866
03867 default:
03868 return 0;
03869 }
03870 }
03871
03872
03873
03874 static bfd_boolean
03875 elf64_alpha_calc_dynrel_sizes (h, info)
03876 struct alpha_elf_link_hash_entry *h;
03877 struct bfd_link_info *info;
03878 {
03879 bfd_boolean dynamic;
03880 struct alpha_elf_reloc_entry *relent;
03881 unsigned long entries;
03882
03883 if (h->root.root.type == bfd_link_hash_warning)
03884 h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
03885
03886
03887
03888
03889
03890
03891
03892
03893 if (!h->root.def_regular
03894 && h->root.ref_regular
03895 && !h->root.def_dynamic
03896 && (h->root.root.type == bfd_link_hash_defined
03897 || h->root.root.type == bfd_link_hash_defweak)
03898 && !(h->root.root.u.def.section->owner->flags & DYNAMIC))
03899 h->root.def_regular = 1;
03900
03901
03902
03903
03904 dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
03905
03906
03907
03908
03909 if (h->root.root.type == bfd_link_hash_undefweak && !dynamic)
03910 return TRUE;
03911
03912 for (relent = h->reloc_entries; relent; relent = relent->next)
03913 {
03914 entries = alpha_dynamic_entries_for_reloc (relent->rtype, dynamic,
03915 info->shared);
03916 if (entries)
03917 {
03918 relent->srel->size +=
03919 entries * sizeof (Elf64_External_Rela) * relent->count;
03920 if (relent->reltext)
03921 info->flags |= DT_TEXTREL;
03922 }
03923 }
03924
03925 return TRUE;
03926 }
03927
03928
03929
03930 static bfd_boolean
03931 elf64_alpha_size_rela_got_section (info)
03932 struct bfd_link_info *info;
03933 {
03934 unsigned long entries;
03935 bfd *i, *dynobj;
03936 asection *srel;
03937
03938
03939
03940
03941 entries = 0;
03942 for (i = alpha_elf_hash_table(info)->got_list;
03943 i ; i = alpha_elf_tdata(i)->got_link_next)
03944 {
03945 bfd *j;
03946
03947 for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next)
03948 {
03949 struct alpha_elf_got_entry **local_got_entries, *gotent;
03950 int k, n;
03951
03952 local_got_entries = alpha_elf_tdata(j)->local_got_entries;
03953 if (!local_got_entries)
03954 continue;
03955
03956 for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k)
03957 for (gotent = local_got_entries[k];
03958 gotent ; gotent = gotent->next)
03959 if (gotent->use_count > 0)
03960 entries += (alpha_dynamic_entries_for_reloc
03961 (gotent->reloc_type, 0, info->shared));
03962 }
03963 }
03964
03965 dynobj = elf_hash_table(info)->dynobj;
03966 srel = bfd_get_section_by_name (dynobj, ".rela.got");
03967 if (!srel)
03968 {
03969 BFD_ASSERT (entries == 0);
03970 return TRUE;
03971 }
03972 srel->size = sizeof (Elf64_External_Rela) * entries;
03973
03974
03975 alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
03976 elf64_alpha_size_rela_got_1, info);
03977
03978 return TRUE;
03979 }
03980
03981
03982
03983
03984 static bfd_boolean
03985 elf64_alpha_size_rela_got_1 (h, info)
03986 struct alpha_elf_link_hash_entry *h;
03987 struct bfd_link_info *info;
03988 {
03989 bfd_boolean dynamic;
03990 struct alpha_elf_got_entry *gotent;
03991 unsigned long entries;
03992
03993 if (h->root.root.type == bfd_link_hash_warning)
03994 h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
03995
03996
03997
03998
03999 dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
04000
04001
04002
04003
04004 if (h->root.root.type == bfd_link_hash_undefweak && !dynamic)
04005 return TRUE;
04006
04007 entries = 0;
04008 for (gotent = h->got_entries; gotent ; gotent = gotent->next)
04009 if (gotent->use_count > 0)
04010 entries += alpha_dynamic_entries_for_reloc (gotent->reloc_type,
04011 dynamic, info->shared);
04012
04013
04014
04015 if (h->root.plt.offset != MINUS_ONE)
04016 entries--;
04017
04018 if (entries > 0)
04019 {
04020 bfd *dynobj = elf_hash_table(info)->dynobj;
04021 asection *srel = bfd_get_section_by_name (dynobj, ".rela.got");
04022 BFD_ASSERT (srel != NULL);
04023 srel->size += sizeof (Elf64_External_Rela) * entries;
04024 }
04025
04026 return TRUE;
04027 }
04028
04029
04030
04031 static bfd_boolean
04032 elf64_alpha_size_dynamic_sections (output_bfd, info)
04033 bfd *output_bfd ATTRIBUTE_UNUSED;
04034 struct bfd_link_info *info;
04035 {
04036 bfd *dynobj;
04037 asection *s;
04038 bfd_boolean relplt;
04039
04040 dynobj = elf_hash_table(info)->dynobj;
04041 BFD_ASSERT(dynobj != NULL);
04042
04043 if (elf_hash_table (info)->dynamic_sections_created)
04044 {
04045
04046 if (info->executable)
04047 {
04048 s = bfd_get_section_by_name (dynobj, ".interp");
04049 BFD_ASSERT (s != NULL);
04050 s->size = sizeof ELF_DYNAMIC_INTERPRETER;
04051 s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
04052 }
04053
04054
04055
04056
04057
04058 alpha_elf_link_hash_traverse (alpha_elf_hash_table (info),
04059 elf64_alpha_calc_dynrel_sizes, info);
04060
04061 elf64_alpha_size_rela_got_section (info);
04062 }
04063
04064
04065
04066
04067
04068 relplt = FALSE;
04069 for (s = dynobj->sections; s != NULL; s = s->next)
04070 {
04071 const char *name;
04072 bfd_boolean strip;
04073
04074 if (!(s->flags & SEC_LINKER_CREATED))
04075 continue;
04076
04077
04078
04079 name = bfd_get_section_name (dynobj, s);
04080
04081
04082
04083
04084
04085
04086
04087
04088
04089 strip = FALSE;
04090
04091 if (strncmp (name, ".rela", 5) == 0)
04092 {
04093 strip = (s->size == 0);
04094
04095 if (!strip)
04096 {
04097 if (strcmp(name, ".rela.plt") == 0)
04098 relplt = TRUE;
04099
04100
04101
04102 s->reloc_count = 0;
04103 }
04104 }
04105 else if (strcmp (name, ".plt") != 0)
04106 {
04107
04108 continue;
04109 }
04110
04111 if (strip)
04112 _bfd_strip_section_from_output (info, s);
04113 else
04114 {
04115
04116 s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
04117 if (s->contents == NULL && s->size != 0)
04118 return FALSE;
04119 }
04120 }
04121
04122 if (elf_hash_table (info)->dynamic_sections_created)
04123 {
04124
04125
04126
04127
04128
04129 #define add_dynamic_entry(TAG, VAL) \
04130 _bfd_elf_add_dynamic_entry (info, TAG, VAL)
04131
04132 if (info->executable)
04133 {
04134 if (!add_dynamic_entry (DT_DEBUG, 0))
04135 return FALSE;
04136 }
04137
04138 if (relplt)
04139 {
04140 if (!add_dynamic_entry (DT_PLTGOT, 0)
04141 || !add_dynamic_entry (DT_PLTRELSZ, 0)
04142 || !add_dynamic_entry (DT_PLTREL, DT_RELA)
04143 || !add_dynamic_entry (DT_JMPREL, 0))
04144 return FALSE;
04145 }
04146
04147 if (!add_dynamic_entry (DT_RELA, 0)
04148 || !add_dynamic_entry (DT_RELASZ, 0)
04149 || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
04150 return FALSE;
04151
04152 if (info->flags & DF_TEXTREL)
04153 {
04154 if (!add_dynamic_entry (DT_TEXTREL, 0))
04155 return FALSE;
04156 }
04157 }
04158 #undef add_dynamic_entry
04159
04160 return TRUE;
04161 }
04162
04163
04164
04165
04166 static void
04167 elf64_alpha_emit_dynrel (abfd, info, sec, srel, offset, dynindx, rtype, addend)
04168 bfd *abfd;
04169 struct bfd_link_info *info;
04170 asection *sec, *srel;
04171 bfd_vma offset, addend;
04172 long dynindx, rtype;
04173 {
04174 Elf_Internal_Rela outrel;
04175 bfd_byte *loc;
04176
04177 BFD_ASSERT (srel != NULL);
04178
04179 outrel.r_info = ELF64_R_INFO (dynindx, rtype);
04180 outrel.r_addend = addend;
04181
04182 offset = _bfd_elf_section_offset (abfd, info, sec, offset);
04183 if ((offset | 1) != (bfd_vma) -1)
04184 outrel.r_offset = sec->output_section->vma + sec->output_offset + offset;
04185 else
04186 memset (&outrel, 0, sizeof (outrel));
04187
04188 loc = srel->contents;
04189 loc += srel->reloc_count++ * sizeof (Elf64_External_Rela);
04190 bfd_elf64_swap_reloca_out (abfd, &outrel, loc);
04191 BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count <= srel->size);
04192 }
04193
04194
04195
04196
04197
04198
04199
04200 static bfd_boolean
04201 elf64_alpha_relocate_section_r (output_bfd, info, input_bfd, input_section,
04202 contents, relocs, local_syms, local_sections)
04203 bfd *output_bfd ATTRIBUTE_UNUSED;
04204 struct bfd_link_info *info ATTRIBUTE_UNUSED;
04205 bfd *input_bfd;
04206 asection *input_section;
04207 bfd_byte *contents ATTRIBUTE_UNUSED;
04208 Elf_Internal_Rela *relocs;
04209 Elf_Internal_Sym *local_syms;
04210 asection **local_sections;
04211 {
04212 unsigned long symtab_hdr_sh_info;
04213 Elf_Internal_Rela *rel;
04214 Elf_Internal_Rela *relend;
04215 bfd_boolean ret_val = TRUE;
04216
04217 symtab_hdr_sh_info = elf_tdata (input_bfd)->symtab_hdr.sh_info;
04218
04219 relend = relocs + input_section->reloc_count;
04220 for (rel = relocs; rel < relend; rel++)
04221 {
04222 unsigned long r_symndx;
04223 Elf_Internal_Sym *sym;
04224 asection *sec;
04225 unsigned long r_type;
04226
04227 r_type = ELF64_R_TYPE(rel->r_info);
04228 if (r_type >= R_ALPHA_max)
04229 {
04230 (*_bfd_error_handler)
04231 (_("%B: unknown relocation type %d"),
04232 input_bfd, (int) r_type);
04233 bfd_set_error (bfd_error_bad_value);
04234 ret_val = FALSE;
04235 continue;
04236 }
04237
04238 r_symndx = ELF64_R_SYM(rel->r_info);
04239
04240
04241
04242 if (r_type == R_ALPHA_GPDISP || r_type == R_ALPHA_LITUSE)
04243 continue;
04244
04245 if (r_symndx < symtab_hdr_sh_info)
04246 {
04247 sym = local_syms + r_symndx;
04248 if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
04249 {
04250 sec = local_sections[r_symndx];
04251 rel->r_addend += sec->output_offset + sym->st_value;
04252 }
04253 }
04254 }
04255
04256 return ret_val;
04257 }
04258
04259
04260
04261 static bfd_boolean
04262 elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
04263 contents, relocs, local_syms, local_sections)
04264 bfd *output_bfd;
04265 struct bfd_link_info *info;
04266 bfd *input_bfd;
04267 asection *input_section;
04268 bfd_byte *contents;
04269 Elf_Internal_Rela *relocs;
04270 Elf_Internal_Sym *local_syms;
04271 asection **local_sections;
04272 {
04273 Elf_Internal_Shdr *symtab_hdr;
04274 Elf_Internal_Rela *rel;
04275 Elf_Internal_Rela *relend;
04276 asection *sgot, *srel, *srelgot;
04277 bfd *dynobj, *gotobj;
04278 bfd_vma gp, tp_base, dtp_base;
04279 struct alpha_elf_got_entry **local_got_entries;
04280 bfd_boolean ret_val;
04281
04282
04283 if (info->relocatable)
04284 return elf64_alpha_relocate_section_r (output_bfd, info, input_bfd,
04285 input_section, contents, relocs,
04286 local_syms, local_sections);
04287
04288
04289
04290 ret_val = TRUE;
04291
04292 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
04293
04294 dynobj = elf_hash_table (info)->dynobj;
04295 if (dynobj)
04296 srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
04297 else
04298 srelgot = NULL;
04299
04300 if (input_section->flags & SEC_ALLOC)
04301 {
04302 const char *section_name;
04303 section_name = (bfd_elf_string_from_elf_section
04304 (input_bfd, elf_elfheader(input_bfd)->e_shstrndx,
04305 elf_section_data(input_section)->rel_hdr.sh_name));
04306 BFD_ASSERT(section_name != NULL);
04307 srel = bfd_get_section_by_name (dynobj, section_name);
04308 }
04309 else
04310 srel = NULL;
04311
04312
04313 gotobj = alpha_elf_tdata (input_bfd)->gotobj;
04314 if (gotobj)
04315 {
04316 sgot = alpha_elf_tdata (gotobj)->got;
04317 gp = _bfd_get_gp_value (gotobj);
04318 if (gp == 0)
04319 {
04320 gp = (sgot->output_section->vma
04321 + sgot->output_offset
04322 + 0x8000);
04323 _bfd_set_gp_value (gotobj, gp);
04324 }
04325 }
04326 else
04327 {
04328 sgot = NULL;
04329 gp = 0;
04330 }
04331
04332 local_got_entries = alpha_elf_tdata(input_bfd)->local_got_entries;
04333
04334 if (elf_hash_table (info)->tls_sec != NULL)
04335 {
04336 dtp_base = alpha_get_dtprel_base (info);
04337 tp_base = alpha_get_tprel_base (info);
04338 }
04339 else
04340 dtp_base = tp_base = 0;
04341
04342 relend = relocs + input_section->reloc_count;
04343 for (rel = relocs; rel < relend; rel++)
04344 {
04345 struct alpha_elf_link_hash_entry *h = NULL;
04346 struct alpha_elf_got_entry *gotent;
04347 bfd_reloc_status_type r;
04348 reloc_howto_type *howto;
04349 unsigned long r_symndx;
04350 Elf_Internal_Sym *sym = NULL;
04351 asection *sec = NULL;
04352 bfd_vma value;
04353 bfd_vma addend;
04354 bfd_boolean dynamic_symbol_p;
04355 bfd_boolean undef_weak_ref = FALSE;
04356 unsigned long r_type;
04357
04358 r_type = ELF64_R_TYPE(rel->r_info);
04359 if (r_type >= R_ALPHA_max)
04360 {
04361 (*_bfd_error_handler)
04362 (_("%B: unknown relocation type %d"),
04363 input_bfd, (int) r_type);
04364 bfd_set_error (bfd_error_bad_value);
04365 ret_val = FALSE;
04366 continue;
04367 }
04368
04369 howto = elf64_alpha_howto_table + r_type;
04370 r_symndx = ELF64_R_SYM(rel->r_info);
04371
04372
04373
04374 if (r_type == R_ALPHA_TLSLDM)
04375 r_symndx = 0;
04376
04377 if (r_symndx < symtab_hdr->sh_info)
04378 {
04379 asection *msec;
04380 sym = local_syms + r_symndx;
04381 sec = local_sections[r_symndx];
04382 msec = sec;
04383 value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel);
04384
04385
04386
04387
04388 if (r_symndx == 0
04389 && (r_type == R_ALPHA_TLSLDM
04390 || r_type == R_ALPHA_GOTTPREL
04391 || r_type == R_ALPHA_TPREL64
04392 || r_type == R_ALPHA_TPRELHI
04393 || r_type == R_ALPHA_TPRELLO
04394 || r_type == R_ALPHA_TPREL16))
04395 value = tp_base;
04396
04397 if (local_got_entries)
04398 gotent = local_got_entries[r_symndx];
04399 else
04400 gotent = NULL;
04401
04402
04403
04404 if ((sec->flags & SEC_MERGE)
04405 && ELF_ST_TYPE (sym->st_info) == STT_SECTION
04406 && sec->sec_info_type == ELF_INFO_TYPE_MERGE
04407 && gotent
04408 && !gotent->reloc_xlated)
04409 {
04410 struct alpha_elf_got_entry *ent;
04411
04412 for (ent = gotent; ent; ent = ent->next)
04413 {
04414 ent->reloc_xlated = 1;
04415 if (ent->use_count == 0)
04416 continue;
04417 msec = sec;
04418 ent->addend =
04419 _bfd_merged_section_offset (output_bfd, &msec,
04420 elf_section_data (sec)->
04421 sec_info,
04422 sym->st_value + ent->addend);
04423 ent->addend -= sym->st_value;
04424 ent->addend += msec->output_section->vma
04425 + msec->output_offset
04426 - sec->output_section->vma
04427 - sec->output_offset;
04428 }
04429 }
04430
04431 dynamic_symbol_p = FALSE;
04432 }
04433 else
04434 {
04435 bfd_boolean warned;
04436 bfd_boolean unresolved_reloc;
04437 struct elf_link_hash_entry *hh;
04438 struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
04439
04440 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
04441 r_symndx, symtab_hdr, sym_hashes,
04442 hh, sec, value,
04443 unresolved_reloc, warned);
04444
04445 if (warned)
04446 continue;
04447
04448 if (value == 0
04449 && ! unresolved_reloc
04450 && hh->root.type == bfd_link_hash_undefweak)
04451 undef_weak_ref = TRUE;
04452
04453 h = (struct alpha_elf_link_hash_entry *) hh;
04454 dynamic_symbol_p = alpha_elf_dynamic_symbol_p (&h->root, info);
04455 gotent = h->got_entries;
04456 }
04457
04458 addend = rel->r_addend;
04459 value += addend;
04460
04461
04462 for (; gotent ; gotent = gotent->next)
04463 if (gotent->gotobj == gotobj
04464 && gotent->reloc_type == r_type
04465 && gotent->addend == addend)
04466 break;
04467
04468 switch (r_type)
04469 {
04470 case R_ALPHA_GPDISP:
04471 {
04472 bfd_byte *p_ldah, *p_lda;
04473
04474 BFD_ASSERT(gp != 0);
04475
04476 value = (input_section->output_section->vma
04477 + input_section->output_offset
04478 + rel->r_offset);
04479
04480 p_ldah = contents + rel->r_offset;
04481 p_lda = p_ldah + rel->r_addend;
04482
04483 r = elf64_alpha_do_reloc_gpdisp (input_bfd, gp - value,
04484 p_ldah, p_lda);
04485 }
04486 break;
04487
04488 case R_ALPHA_LITERAL:
04489 BFD_ASSERT(sgot != NULL);
04490 BFD_ASSERT(gp != 0);
04491 BFD_ASSERT(gotent != NULL);
04492 BFD_ASSERT(gotent->use_count >= 1);
04493
04494 if (!gotent->reloc_done)
04495 {
04496 gotent->reloc_done = 1;
04497
04498 bfd_put_64 (output_bfd, value,
04499 sgot->contents + gotent->got_offset);
04500
04501
04502
04503
04504 if (info->shared && !dynamic_symbol_p && !undef_weak_ref)
04505 elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
04506 gotent->got_offset, 0,
04507 R_ALPHA_RELATIVE, value);
04508 }
04509
04510 value = (sgot->output_section->vma
04511 + sgot->output_offset
04512 + gotent->got_offset);
04513 value -= gp;
04514 goto default_reloc;
04515
04516 case R_ALPHA_GPREL32:
04517
04518
04519
04520
04521
04522 if (r_symndx == 0)
04523 {
04524 r = bfd_reloc_ok;
04525 break;
04526 }
04527
04528
04529 case R_ALPHA_GPREL16:
04530 case R_ALPHA_GPRELLOW:
04531 if (dynamic_symbol_p)
04532 {
04533 (*_bfd_error_handler)
04534 (_("%B: gp-relative relocation against dynamic symbol %s"),
04535 input_bfd, h->root.root.root.string);
04536 ret_val = FALSE;
04537 }
04538 BFD_ASSERT(gp != 0);
04539 value -= gp;
04540 goto default_reloc;
04541
04542 case R_ALPHA_GPRELHIGH:
04543 if (dynamic_symbol_p)
04544 {
04545 (*_bfd_error_handler)
04546 (_("%B: gp-relative relocation against dynamic symbol %s"),
04547 input_bfd, h->root.root.root.string);
04548 ret_val = FALSE;
04549 }
04550 BFD_ASSERT(gp != 0);
04551 value -= gp;
04552 value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
04553 goto default_reloc;
04554
04555 case R_ALPHA_HINT:
04556
04557
04558 if (dynamic_symbol_p)
04559 {
04560 r = bfd_reloc_ok;
04561 break;
04562 }
04563
04564
04565 value -= 4;
04566 goto default_reloc;
04567
04568 case R_ALPHA_BRADDR:
04569 if (dynamic_symbol_p)
04570 {
04571 (*_bfd_error_handler)
04572 (_("%B: pc-relative relocation against dynamic symbol %s"),
04573 input_bfd, h->root.root.root.string);
04574 ret_val = FALSE;
04575 }
04576
04577
04578 value -= 4;
04579 goto default_reloc;
04580
04581 case R_ALPHA_BRSGP:
04582 {
04583 int other;
04584 const char *name;
04585
04586
04587
04588 value -= 4;
04589
04590
04591
04592
04593
04594
04595 if (h != NULL && sec != NULL
04596 && alpha_elf_tdata (sec->owner)->gotobj
04597 && gotobj != alpha_elf_tdata (sec->owner)->gotobj)
04598 {
04599 (*_bfd_error_handler)
04600 (_("%B: change in gp: BRSGP %s"),
04601 input_bfd, h->root.root.root.string);
04602 ret_val = FALSE;
04603 }
04604
04605
04606 if (h != NULL)
04607 other = h->root.other;
04608 else
04609 other = sym->st_other;
04610 switch (other & STO_ALPHA_STD_GPLOAD)
04611 {
04612 case STO_ALPHA_NOPV:
04613 break;
04614 case STO_ALPHA_STD_GPLOAD:
04615 value += 8;
04616 break;
04617 default:
04618 if (h != NULL)
04619 name = h->root.root.root.string;
04620 else
04621 {
04622 name = (bfd_elf_string_from_elf_section
04623 (input_bfd, symtab_hdr->sh_link, sym->st_name));
04624 if (name == NULL)
04625 name = _("<unknown>");
04626 else if (name[0] == 0)
04627 name = bfd_section_name (input_bfd, sec);
04628 }
04629 (*_bfd_error_handler)
04630 (_("%B: !samegp reloc against symbol without .prologue: %s"),
04631 input_bfd, name);
04632 ret_val = FALSE;
04633 break;
04634 }
04635
04636 goto default_reloc;
04637 }
04638
04639 case R_ALPHA_REFLONG:
04640 case R_ALPHA_REFQUAD:
04641 case R_ALPHA_DTPREL64:
04642 case R_ALPHA_TPREL64:
04643 {
04644 long dynindx, dyntype = r_type;
04645 bfd_vma dynaddend;
04646
04647
04648
04649
04650 if (dynamic_symbol_p)
04651 {
04652 BFD_ASSERT(h->root.dynindx != -1);
04653 dynindx = h->root.dynindx;
04654 dynaddend = addend;
04655 addend = 0, value = 0;
04656 }
04657 else if (r_type == R_ALPHA_DTPREL64)
04658 {
04659 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
04660 value -= dtp_base;
04661 goto default_reloc;
04662 }
04663 else if (r_type == R_ALPHA_TPREL64)
04664 {
04665 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
04666 if (!info->shared)
04667 {
04668 value -= tp_base;
04669 goto default_reloc;
04670 }
04671 dynindx = 0;
04672 dynaddend = value - dtp_base;
04673 }
04674 else if (info->shared
04675 && r_symndx != 0
04676 && (input_section->flags & SEC_ALLOC)
04677 && !undef_weak_ref)
04678 {
04679 if (r_type == R_ALPHA_REFLONG)
04680 {
04681 (*_bfd_error_handler)
04682 (_("%B: unhandled dynamic relocation against %s"),
04683 input_bfd,
04684 h->root.root.root.string);
04685 ret_val = FALSE;
04686 }
04687 dynindx = 0;
04688 dyntype = R_ALPHA_RELATIVE;
04689 dynaddend = value;
04690 }
04691 else
04692 goto default_reloc;
04693
04694 if (input_section->flags & SEC_ALLOC)
04695 elf64_alpha_emit_dynrel (output_bfd, info, input_section,
04696 srel, rel->r_offset, dynindx,
04697 dyntype, dynaddend);
04698 }
04699 goto default_reloc;
04700
04701 case R_ALPHA_SREL16:
04702 case R_ALPHA_SREL32:
04703 case R_ALPHA_SREL64:
04704 if (dynamic_symbol_p)
04705 {
04706 (*_bfd_error_handler)
04707 (_("%B: pc-relative relocation against dynamic symbol %s"),
04708 input_bfd, h->root.root.root.string);
04709 ret_val = FALSE;
04710 }
04711 else if ((info->shared || info->pie) && undef_weak_ref)
04712 {
04713 (*_bfd_error_handler)
04714 (_("%B: pc-relative relocation against undefined weak symbol %s"),
04715 input_bfd, h->root.root.root.string);
04716 ret_val = FALSE;
04717 }
04718
04719
04720
04721
04722
04723 if (r_symndx == 0)
04724 howto = (elf64_alpha_howto_table
04725 + (r_type - R_ALPHA_SREL32 + R_ALPHA_REFLONG));
04726 goto default_reloc;
04727
04728 case R_ALPHA_TLSLDM:
04729
04730
04731 dynamic_symbol_p = 0;
04732
04733
04734 case R_ALPHA_TLSGD:
04735 if (!gotent->reloc_done)
04736 {
04737 gotent->reloc_done = 1;
04738
04739
04740 bfd_put_64 (output_bfd, !info->shared && !dynamic_symbol_p,
04741 sgot->contents + gotent->got_offset);
04742
04743
04744
04745
04746 if (info->shared && !dynamic_symbol_p)
04747 elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
04748 gotent->got_offset, 0,
04749 R_ALPHA_DTPMOD64, 0);
04750
04751 if (dynamic_symbol_p || r_type == R_ALPHA_TLSLDM)
04752 value = 0;
04753 else
04754 {
04755 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
04756 value -= dtp_base;
04757 }
04758 bfd_put_64 (output_bfd, value,
04759 sgot->contents + gotent->got_offset + 8);
04760 }
04761
04762 value = (sgot->output_section->vma
04763 + sgot->output_offset
04764 + gotent->got_offset);
04765 value -= gp;
04766 goto default_reloc;
04767
04768 case R_ALPHA_DTPRELHI:
04769 case R_ALPHA_DTPRELLO:
04770 case R_ALPHA_DTPREL16:
04771 if (dynamic_symbol_p)
04772 {
04773 (*_bfd_error_handler)
04774 (_("%B: dtp-relative relocation against dynamic symbol %s"),
04775 input_bfd, h->root.root.root.string);
04776 ret_val = FALSE;
04777 }
04778 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
04779 value -= dtp_base;
04780 if (r_type == R_ALPHA_DTPRELHI)
04781 value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
04782 goto default_reloc;
04783
04784 case R_ALPHA_TPRELHI:
04785 case R_ALPHA_TPRELLO:
04786 case R_ALPHA_TPREL16:
04787 if (info->shared)
04788 {
04789 (*_bfd_error_handler)
04790 (_("%B: TLS local exec code cannot be linked into shared objects"),
04791 input_bfd);
04792 ret_val = FALSE;
04793 }
04794 else if (dynamic_symbol_p)
04795 {
04796 (*_bfd_error_handler)
04797 (_("%B: tp-relative relocation against dynamic symbol %s"),
04798 input_bfd, h->root.root.root.string);
04799 ret_val = FALSE;
04800 }
04801 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
04802 value -= tp_base;
04803 if (r_type == R_ALPHA_TPRELHI)
04804 value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
04805 goto default_reloc;
04806
04807 case R_ALPHA_GOTDTPREL:
04808 case R_ALPHA_GOTTPREL:
04809 BFD_ASSERT(sgot != NULL);
04810 BFD_ASSERT(gp != 0);
04811 BFD_ASSERT(gotent != NULL);
04812 BFD_ASSERT(gotent->use_count >= 1);
04813
04814 if (!gotent->reloc_done)
04815 {
04816 gotent->reloc_done = 1;
04817
04818 if (dynamic_symbol_p)
04819 value = 0;
04820 else
04821 {
04822 BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
04823 if (r_type == R_ALPHA_GOTDTPREL)
04824 value -= dtp_base;
04825 else if (!info->shared)
04826 value -= tp_base;
04827 else
04828 {
04829 elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
04830 gotent->got_offset, 0,
04831 R_ALPHA_TPREL64,
04832 value - dtp_base);
04833 value = 0;
04834 }
04835 }
04836 bfd_put_64 (output_bfd, value,
04837 sgot->contents + gotent->got_offset);
04838 }
04839
04840 value = (sgot->output_section->vma
04841 + sgot->output_offset
04842 + gotent->got_offset);
04843 value -= gp;
04844 goto default_reloc;
04845
04846 default:
04847 default_reloc:
04848 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
04849 contents, rel->r_offset, value, 0);
04850 break;
04851 }
04852
04853 switch (r)
04854 {
04855 case bfd_reloc_ok:
04856 break;
04857
04858 case bfd_reloc_overflow:
04859 {
04860 const char *name;
04861
04862
04863
04864
04865
04866 if (r_symndx < symtab_hdr->sh_info
04867 && sec != NULL && howto->pc_relative
04868 && elf_discarded_section (sec))
04869 break;
04870
04871 if (h != NULL)
04872 name = NULL;
04873 else
04874 {
04875 name = (bfd_elf_string_from_elf_section
04876 (input_bfd, symtab_hdr->sh_link, sym->st_name));
04877 if (name == NULL)
04878 return FALSE;
04879 if (*name == '\0')
04880 name = bfd_section_name (input_bfd, sec);
04881 }
04882 if (! ((*info->callbacks->reloc_overflow)
04883 (info, (h ? &h->root.root : NULL), name, howto->name,
04884 (bfd_vma) 0, input_bfd, input_section,
04885 rel->r_offset)))
04886 ret_val = FALSE;
04887 }
04888 break;
04889
04890 default:
04891 case bfd_reloc_outofrange:
04892 abort ();
04893 }
04894 }
04895
04896 return ret_val;
04897 }
04898
04899
04900
04901
04902 static bfd_boolean
04903 elf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym)
04904 bfd *output_bfd;
04905 struct bfd_link_info *info;
04906 struct elf_link_hash_entry *h;
04907 Elf_Internal_Sym *sym;
04908 {
04909 bfd *dynobj = elf_hash_table(info)->dynobj;
04910
04911 if (h->plt.offset != MINUS_ONE)
04912 {
04913
04914 asection *splt, *sgot, *srel;
04915 Elf_Internal_Rela outrel;
04916 bfd_byte *loc;
04917 bfd_vma got_addr, plt_addr;
04918 bfd_vma plt_index;
04919 struct alpha_elf_got_entry *gotent;
04920
04921 BFD_ASSERT (h->dynindx != -1);
04922
04923
04924
04925 gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
04926 BFD_ASSERT (gotent && gotent->addend == 0);
04927
04928 splt = bfd_get_section_by_name (dynobj, ".plt");
04929 BFD_ASSERT (splt != NULL);
04930 srel = bfd_get_section_by_name (dynobj, ".rela.plt");
04931 BFD_ASSERT (srel != NULL);
04932 sgot = alpha_elf_tdata (gotent->gotobj)->got;
04933 BFD_ASSERT (sgot != NULL);
04934
04935 got_addr = (sgot->output_section->vma
04936 + sgot->output_offset
04937 + gotent->got_offset);
04938 plt_addr = (splt->output_section->vma
04939 + splt->output_offset
04940 + h->plt.offset);
04941
04942 plt_index = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
04943
04944
04945 {
04946 bfd_vma insn1, insn2, insn3;
04947
04948 insn1 = PLT_ENTRY_WORD1 | ((-(h->plt.offset + 4) >> 2) & 0x1fffff);
04949 insn2 = PLT_ENTRY_WORD2;
04950 insn3 = PLT_ENTRY_WORD3;
04951
04952 bfd_put_32 (output_bfd, insn1, splt->contents + h->plt.offset);
04953 bfd_put_32 (output_bfd, insn2, splt->contents + h->plt.offset + 4);
04954 bfd_put_32 (output_bfd, insn3, splt->contents + h->plt.offset + 8);
04955 }
04956
04957
04958 outrel.r_offset = got_addr;
04959 outrel.r_info = ELF64_R_INFO(h->dynindx, R_ALPHA_JMP_SLOT);
04960 outrel.r_addend = 0;
04961
04962 loc = srel->contents + plt_index * sizeof (Elf64_External_Rela);
04963 bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
04964
04965 if (!h->def_regular)
04966 {
04967
04968
04969 sym->st_shndx = SHN_UNDEF;
04970 }
04971
04972
04973 bfd_put_64 (output_bfd, plt_addr, sgot->contents + gotent->got_offset);
04974
04975
04976 if (gotent->next)
04977 {
04978 srel = bfd_get_section_by_name (dynobj, ".rela.got");
04979 BFD_ASSERT (! info->shared || srel != NULL);
04980
04981 gotent = gotent->next;
04982 do
04983 {
04984 sgot = alpha_elf_tdata(gotent->gotobj)->got;
04985 BFD_ASSERT(sgot != NULL);
04986 BFD_ASSERT(gotent->addend == 0);
04987
04988 bfd_put_64 (output_bfd, plt_addr,
04989 sgot->contents + gotent->got_offset);
04990
04991 if (info->shared)
04992 elf64_alpha_emit_dynrel (output_bfd, info, sgot, srel,
04993 gotent->got_offset, 0,
04994 R_ALPHA_RELATIVE, plt_addr);
04995
04996 gotent = gotent->next;
04997 }
04998 while (gotent != NULL);
04999 }
05000 }
05001 else if (alpha_elf_dynamic_symbol_p (h, info))
05002 {
05003
05004 asection *srel;
05005 struct alpha_elf_got_entry *gotent;
05006
05007 srel = bfd_get_section_by_name (dynobj, ".rela.got");
05008 BFD_ASSERT (srel != NULL);
05009
05010 for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
05011 gotent != NULL;
05012 gotent = gotent->next)
05013 {
05014 asection *sgot;
05015 long r_type;
05016
05017 if (gotent->use_count == 0)
05018 continue;
05019
05020 sgot = alpha_elf_tdata (gotent->gotobj)->got;
05021
05022 r_type = gotent->reloc_type;
05023 switch (r_type)
05024 {
05025 case R_ALPHA_LITERAL:
05026 r_type = R_ALPHA_GLOB_DAT;
05027 break;
05028 case R_ALPHA_TLSGD:
05029 r_type = R_ALPHA_DTPMOD64;
05030 break;
05031 case R_ALPHA_GOTDTPREL:
05032 r_type = R_ALPHA_DTPREL64;
05033 break;
05034 case R_ALPHA_GOTTPREL:
05035 r_type = R_ALPHA_TPREL64;
05036 break;
05037 case R_ALPHA_TLSLDM:
05038 default:
05039 abort ();
05040 }
05041
05042 elf64_alpha_emit_dynrel (output_bfd, info, sgot, srel,
05043 gotent->got_offset, h->dynindx,
05044 r_type, gotent->addend);
05045
05046 if (gotent->reloc_type == R_ALPHA_TLSGD)
05047 elf64_alpha_emit_dynrel (output_bfd, info, sgot, srel,
05048 gotent->got_offset + 8, h->dynindx,
05049 R_ALPHA_DTPREL64, gotent->addend);
05050 }
05051 }
05052
05053
05054 if (strcmp (h->root.root.string, "_DYNAMIC") == 0
05055 || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
05056 || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
05057 sym->st_shndx = SHN_ABS;
05058
05059 return TRUE;
05060 }
05061
05062
05063
05064 static bfd_boolean
05065 elf64_alpha_finish_dynamic_sections (output_bfd, info)
05066 bfd *output_bfd;
05067 struct bfd_link_info *info;
05068 {
05069 bfd *dynobj;
05070 asection *sdyn;
05071
05072 dynobj = elf_hash_table (info)->dynobj;
05073 sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
05074
05075 if (elf_hash_table (info)->dynamic_sections_created)
05076 {
05077 asection *splt;
05078 Elf64_External_Dyn *dyncon, *dynconend;
05079
05080 splt = bfd_get_section_by_name (dynobj, ".plt");
05081 BFD_ASSERT (splt != NULL && sdyn != NULL);
05082
05083 dyncon = (Elf64_External_Dyn *) sdyn->contents;
05084 dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size);
05085 for (; dyncon < dynconend; dyncon++)
05086 {
05087 Elf_Internal_Dyn dyn;
05088 const char *name;
05089 asection *s;
05090
05091 bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
05092
05093 switch (dyn.d_tag)
05094 {
05095 case DT_PLTGOT:
05096 name = ".plt";
05097 goto get_vma;
05098 case DT_PLTRELSZ:
05099 name = ".rela.plt";
05100 goto get_size;
05101 case DT_JMPREL:
05102 name = ".rela.plt";
05103 goto get_vma;
05104
05105 case DT_RELASZ:
05106
05107
05108
05109
05110
05111 s = bfd_get_section_by_name (output_bfd, ".rela.plt");
05112 if (s)
05113 dyn.d_un.d_val -= s->size;
05114 break;
05115
05116 get_vma:
05117 s = bfd_get_section_by_name (output_bfd, name);
05118 dyn.d_un.d_ptr = (s ? s->vma : 0);
05119 break;
05120
05121 get_size:
05122 s = bfd_get_section_by_name (output_bfd, name);
05123 dyn.d_un.d_val = s->size;
05124 break;
05125 }
05126
05127 bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
05128 }
05129
05130
05131 if (splt->size > 0)
05132 {
05133 bfd_put_32 (output_bfd, PLT_HEADER_WORD1, splt->contents);
05134 bfd_put_32 (output_bfd, PLT_HEADER_WORD2, splt->contents + 4);
05135 bfd_put_32 (output_bfd, PLT_HEADER_WORD3, splt->contents + 8);
05136 bfd_put_32 (output_bfd, PLT_HEADER_WORD4, splt->contents + 12);
05137
05138
05139 bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 16);
05140 bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 24);
05141
05142 elf_section_data (splt->output_section)->this_hdr.sh_entsize = 0;
05143 }
05144 }
05145
05146 return TRUE;
05147 }
05148
05149
05150
05151
05152
05153 static bfd_boolean
05154 elf64_alpha_final_link (abfd, info)
05155 bfd *abfd;
05156 struct bfd_link_info *info;
05157 {
05158 asection *o;
05159 struct bfd_link_order *p;
05160 asection *mdebug_sec;
05161 struct ecoff_debug_info debug;
05162 const struct ecoff_debug_swap *swap
05163 = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
05164 HDRR *symhdr = &debug.symbolic_header;
05165 PTR mdebug_handle = NULL;
05166
05167
05168 mdebug_sec = NULL;
05169 for (o = abfd->sections; o != (asection *) NULL; o = o->next)
05170 {
05171 if (strcmp (o->name, ".mdebug") == 0)
05172 {
05173 struct extsym_info einfo;
05174
05175
05176
05177
05178 symhdr->magic = swap->sym_magic;
05179
05180 symhdr->vstamp = 0;
05181 symhdr->ilineMax = 0;
05182 symhdr->cbLine = 0;
05183 symhdr->idnMax = 0;
05184 symhdr->ipdMax = 0;
05185 symhdr->isymMax = 0;
05186 symhdr->ioptMax = 0;
05187 symhdr->iauxMax = 0;
05188 symhdr->issMax = 0;
05189 symhdr->issExtMax = 0;
05190 symhdr->ifdMax = 0;
05191 symhdr->crfd = 0;
05192 symhdr->iextMax = 0;
05193
05194
05195
05196 debug.line = NULL;
05197 debug.external_dnr = NULL;
05198 debug.external_pdr = NULL;
05199 debug.external_sym = NULL;
05200 debug.external_opt = NULL;
05201 debug.external_aux = NULL;
05202 debug.ss = NULL;
05203 debug.ssext = debug.ssext_end = NULL;
05204 debug.external_fdr = NULL;
05205 debug.external_rfd = NULL;
05206 debug.external_ext = debug.external_ext_end = NULL;
05207
05208 mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info);
05209 if (mdebug_handle == (PTR) NULL)
05210 return FALSE;
05211
05212 if (1)
05213 {
05214 asection *s;
05215 EXTR esym;
05216 bfd_vma last = 0;
05217 unsigned int i;
05218 static const char * const name[] =
05219 {
05220 ".text", ".init", ".fini", ".data",
05221 ".rodata", ".sdata", ".sbss", ".bss"
05222 };
05223 static const int sc[] = { scText, scInit, scFini, scData,
05224 scRData, scSData, scSBss, scBss };
05225
05226 esym.jmptbl = 0;
05227 esym.cobol_main = 0;
05228 esym.weakext = 0;
05229 esym.reserved = 0;
05230 esym.ifd = ifdNil;
05231 esym.asym.iss = issNil;
05232 esym.asym.st = stLocal;
05233 esym.asym.reserved = 0;
05234 esym.asym.index = indexNil;
05235 for (i = 0; i < 8; i++)
05236 {
05237 esym.asym.sc = sc[i];
05238 s = bfd_get_section_by_name (abfd, name[i]);
05239 if (s != NULL)
05240 {
05241 esym.asym.value = s->vma;
05242 last = s->vma + s->size;
05243 }
05244 else
05245 esym.asym.value = last;
05246
05247 if (! bfd_ecoff_debug_one_external (abfd, &debug, swap,
05248 name[i], &esym))
05249 return FALSE;
05250 }
05251 }
05252
05253 for (p = o->link_order_head;
05254 p != (struct bfd_link_order *) NULL;
05255 p = p->next)
05256 {
05257 asection *input_section;
05258 bfd *input_bfd;
05259 const struct ecoff_debug_swap *input_swap;
05260 struct ecoff_debug_info input_debug;
05261 char *eraw_src;
05262 char *eraw_end;
05263
05264 if (p->type != bfd_indirect_link_order)
05265 {
05266 if (p->type == bfd_data_link_order)
05267 continue;
05268 abort ();
05269 }
05270
05271 input_section = p->u.indirect.section;
05272 input_bfd = input_section->owner;
05273
05274 if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour
05275 || (get_elf_backend_data (input_bfd)
05276 ->elf_backend_ecoff_debug_swap) == NULL)
05277 {
05278
05279
05280
05281 continue;
05282 }
05283
05284 input_swap = (get_elf_backend_data (input_bfd)
05285 ->elf_backend_ecoff_debug_swap);
05286
05287 BFD_ASSERT (p->size == input_section->size);
05288
05289
05290
05291
05292 if (!elf64_alpha_read_ecoff_info (input_bfd, input_section,
05293 &input_debug))
05294 return FALSE;
05295
05296 if (! (bfd_ecoff_debug_accumulate
05297 (mdebug_handle, abfd, &debug, swap, input_bfd,
05298 &input_debug, input_swap, info)))
05299 return FALSE;
05300
05301
05302
05303
05304
05305 eraw_src = input_debug.external_ext;
05306 eraw_end = (eraw_src
05307 + (input_debug.symbolic_header.iextMax
05308 * input_swap->external_ext_size));
05309 for (;
05310 eraw_src < eraw_end;
05311 eraw_src += input_swap->external_ext_size)
05312 {
05313 EXTR ext;
05314 const char *name;
05315 struct alpha_elf_link_hash_entry *h;
05316
05317 (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext);
05318 if (ext.asym.sc == scNil
05319 || ext.asym.sc == scUndefined
05320 || ext.asym.sc == scSUndefined)
05321 continue;
05322
05323 name = input_debug.ssext + ext.asym.iss;
05324 h = alpha_elf_link_hash_lookup (alpha_elf_hash_table (info),
05325 name, FALSE, FALSE, TRUE);
05326 if (h == NULL || h->esym.ifd != -2)
05327 continue;
05328
05329 if (ext.ifd != -1)
05330 {
05331 BFD_ASSERT (ext.ifd
05332 < input_debug.symbolic_header.ifdMax);
05333 ext.ifd = input_debug.ifdmap[ext.ifd];
05334 }
05335
05336 h->esym = ext;
05337 }
05338
05339
05340 free (input_debug.line);
05341 free (input_debug.external_dnr);
05342 free (input_debug.external_pdr);
05343 free (input_debug.external_sym);
05344 free (input_debug.external_opt);
05345 free (input_debug.external_aux);
05346 free (input_debug.ss);
05347 free (input_debug.ssext);
05348 free (input_debug.external_fdr);
05349 free (input_debug.external_rfd);
05350 free (input_debug.external_ext);
05351
05352
05353
05354 input_section->flags &=~ SEC_HAS_CONTENTS;
05355 }
05356
05357
05358 einfo.abfd = abfd;
05359 einfo.info = info;
05360 einfo.debug = &debug;
05361 einfo.swap = swap;
05362 einfo.failed = FALSE;
05363 elf_link_hash_traverse (elf_hash_table (info),
05364 elf64_alpha_output_extsym,
05365 (PTR) &einfo);
05366 if (einfo.failed)
05367 return FALSE;
05368
05369
05370 o->size = bfd_ecoff_debug_size (abfd, &debug, swap);
05371
05372
05373
05374 o->link_order_head = (struct bfd_link_order *) NULL;
05375
05376 mdebug_sec = o;
05377 }
05378 }
05379
05380
05381 if (! bfd_elf_final_link (abfd, info))
05382 return FALSE;
05383
05384
05385
05386
05387 {
05388 bfd *i, *dynobj = elf_hash_table(info)->dynobj;
05389 for (i = alpha_elf_hash_table(info)->got_list;
05390 i != NULL;
05391 i = alpha_elf_tdata(i)->got_link_next)
05392 {
05393 asection *sgot;
05394
05395
05396 if (i == dynobj)
05397 continue;
05398
05399 sgot = alpha_elf_tdata(i)->got;
05400 if (! bfd_set_section_contents (abfd, sgot->output_section,
05401 sgot->contents,
05402 (file_ptr) sgot->output_offset,
05403 sgot->size))
05404 return FALSE;
05405 }
05406 }
05407
05408 if (mdebug_sec != (asection *) NULL)
05409 {
05410 BFD_ASSERT (abfd->output_has_begun);
05411 if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug,
05412 swap, info,
05413 mdebug_sec->filepos))
05414 return FALSE;
05415
05416 bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info);
05417 }
05418
05419 return TRUE;
05420 }
05421
05422 static enum elf_reloc_type_class
05423 elf64_alpha_reloc_type_class (rela)
05424 const Elf_Internal_Rela *rela;
05425 {
05426 switch ((int) ELF64_R_TYPE (rela->r_info))
05427 {
05428 case R_ALPHA_RELATIVE:
05429 return reloc_class_relative;
05430 case R_ALPHA_JMP_SLOT:
05431 return reloc_class_plt;
05432 case R_ALPHA_COPY:
05433 return reloc_class_copy;
05434 default:
05435 return reloc_class_normal;
05436 }
05437 }
05438
05439 static struct bfd_elf_special_section const elf64_alpha_special_sections[]=
05440 {
05441 { ".sdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
05442 { ".sbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL },
05443 { NULL, 0, 0, 0, 0 }
05444 };
05445
05446
05447
05448
05449 static const struct ecoff_debug_swap
05450 elf64_alpha_ecoff_debug_swap =
05451 {
05452
05453 magicSym2,
05454
05455 8,
05456
05457 sizeof (struct hdr_ext),
05458 sizeof (struct dnr_ext),
05459 sizeof (struct pdr_ext),
05460 sizeof (struct sym_ext),
05461 sizeof (struct opt_ext),
05462 sizeof (struct fdr_ext),
05463 sizeof (struct rfd_ext),
05464 sizeof (struct ext_ext),
05465
05466 ecoff_swap_hdr_in,
05467 ecoff_swap_dnr_in,
05468 ecoff_swap_pdr_in,
05469 ecoff_swap_sym_in,
05470 ecoff_swap_opt_in,
05471 ecoff_swap_fdr_in,
05472 ecoff_swap_rfd_in,
05473 ecoff_swap_ext_in,
05474 _bfd_ecoff_swap_tir_in,
05475 _bfd_ecoff_swap_rndx_in,
05476
05477 ecoff_swap_hdr_out,
05478 ecoff_swap_dnr_out,
05479 ecoff_swap_pdr_out,
05480 ecoff_swap_sym_out,
05481 ecoff_swap_opt_out,
05482 ecoff_swap_fdr_out,
05483 ecoff_swap_rfd_out,
05484 ecoff_swap_ext_out,
05485 _bfd_ecoff_swap_tir_out,
05486 _bfd_ecoff_swap_rndx_out,
05487
05488 elf64_alpha_read_ecoff_info
05489 };
05490
05491
05492
05493 static const struct elf_size_info alpha_elf_size_info =
05494 {
05495 sizeof (Elf64_External_Ehdr),
05496 sizeof (Elf64_External_Phdr),
05497 sizeof (Elf64_External_Shdr),
05498 sizeof (Elf64_External_Rel),
05499 sizeof (Elf64_External_Rela),
05500 sizeof (Elf64_External_Sym),
05501 sizeof (Elf64_External_Dyn),
05502 sizeof (Elf_External_Note),
05503 8,
05504 1,
05505 64, 3,
05506 ELFCLASS64, EV_CURRENT,
05507 bfd_elf64_write_out_phdrs,
05508 bfd_elf64_write_shdrs_and_ehdr,
05509 bfd_elf64_write_relocs,
05510 bfd_elf64_swap_symbol_in,
05511 bfd_elf64_swap_symbol_out,
05512 bfd_elf64_slurp_reloc_table,
05513 bfd_elf64_slurp_symbol_table,
05514 bfd_elf64_swap_dyn_in,
05515 bfd_elf64_swap_dyn_out,
05516 bfd_elf64_swap_reloc_in,
05517 bfd_elf64_swap_reloc_out,
05518 bfd_elf64_swap_reloca_in,
05519 bfd_elf64_swap_reloca_out
05520 };
05521
05522 #define TARGET_LITTLE_SYM bfd_elf64_alpha_vec
05523 #define TARGET_LITTLE_NAME "elf64-alpha"
05524 #define ELF_ARCH bfd_arch_alpha
05525 #define ELF_MACHINE_CODE EM_ALPHA
05526 #define ELF_MAXPAGESIZE 0x10000
05527
05528 #define bfd_elf64_bfd_link_hash_table_create \
05529 elf64_alpha_bfd_link_hash_table_create
05530
05531 #define bfd_elf64_bfd_reloc_type_lookup \
05532 elf64_alpha_bfd_reloc_type_lookup
05533 #define elf_info_to_howto \
05534 elf64_alpha_info_to_howto
05535
05536 #define bfd_elf64_mkobject \
05537 elf64_alpha_mkobject
05538 #define elf_backend_object_p \
05539 elf64_alpha_object_p
05540
05541 #define elf_backend_section_from_shdr \
05542 elf64_alpha_section_from_shdr
05543 #define elf_backend_section_flags \
05544 elf64_alpha_section_flags
05545 #define elf_backend_fake_sections \
05546 elf64_alpha_fake_sections
05547
05548 #define bfd_elf64_bfd_is_local_label_name \
05549 elf64_alpha_is_local_label_name
05550 #define bfd_elf64_find_nearest_line \
05551 elf64_alpha_find_nearest_line
05552 #define bfd_elf64_bfd_relax_section \
05553 elf64_alpha_relax_section
05554
05555 #define elf_backend_add_symbol_hook \
05556 elf64_alpha_add_symbol_hook
05557 #define elf_backend_check_relocs \
05558 elf64_alpha_check_relocs
05559 #define elf_backend_create_dynamic_sections \
05560 elf64_alpha_create_dynamic_sections
05561 #define elf_backend_adjust_dynamic_symbol \
05562 elf64_alpha_adjust_dynamic_symbol
05563 #define elf_backend_always_size_sections \
05564 elf64_alpha_always_size_sections
05565 #define elf_backend_size_dynamic_sections \
05566 elf64_alpha_size_dynamic_sections
05567 #define elf_backend_relocate_section \
05568 elf64_alpha_relocate_section
05569 #define elf_backend_finish_dynamic_symbol \
05570 elf64_alpha_finish_dynamic_symbol
05571 #define elf_backend_finish_dynamic_sections \
05572 elf64_alpha_finish_dynamic_sections
05573 #define bfd_elf64_bfd_final_link \
05574 elf64_alpha_final_link
05575 #define elf_backend_reloc_type_class \
05576 elf64_alpha_reloc_type_class
05577
05578 #define elf_backend_ecoff_debug_swap \
05579 &elf64_alpha_ecoff_debug_swap
05580
05581 #define elf_backend_size_info \
05582 alpha_elf_size_info
05583
05584 #define elf_backend_special_sections \
05585 elf64_alpha_special_sections
05586
05587
05588 #define elf_backend_want_got_plt 0
05589 #define elf_backend_plt_readonly 0
05590 #define elf_backend_want_plt_sym 1
05591 #define elf_backend_got_header_size 0
05592
05593 #include "elf64-target.h"
05594
05595
05596
05597 #undef TARGET_LITTLE_SYM
05598 #define TARGET_LITTLE_SYM bfd_elf64_alpha_freebsd_vec
05599 #undef TARGET_LITTLE_NAME
05600 #define TARGET_LITTLE_NAME "elf64-alpha-freebsd"
05601
05602
05603
05604
05605
05606 static void elf64_alpha_fbsd_post_process_headers
05607 PARAMS ((bfd *, struct bfd_link_info *));
05608
05609 static void
05610 elf64_alpha_fbsd_post_process_headers (abfd, link_info)
05611 bfd * abfd;
05612 struct bfd_link_info * link_info ATTRIBUTE_UNUSED;
05613 {
05614 Elf_Internal_Ehdr * i_ehdrp;
05615
05616 i_ehdrp = elf_elfheader (abfd);
05617
05618
05619 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
05620 #ifdef OLD_FREEBSD_ABI_LABEL
05621
05622 memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
05623 #endif
05624 }
05625
05626 #undef elf_backend_post_process_headers
05627 #define elf_backend_post_process_headers \
05628 elf64_alpha_fbsd_post_process_headers
05629
05630 #undef elf64_bed
05631 #define elf64_bed elf64_alpha_fbsd_bed
05632
05633 #include "elf64-target.h"