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 #include "bfd.h"
00028 #include "sysdep.h"
00029 #include "bfdlink.h"
00030 #include "libbfd.h"
00031 #include "coff/internal.h"
00032 #include "coff/sym.h"
00033 #include "coff/symconst.h"
00034 #include "coff/ecoff.h"
00035 #include "coff/alpha.h"
00036 #include "aout/ar.h"
00037 #include "libcoff.h"
00038 #include "libecoff.h"
00039
00040
00041
00042 static const bfd_target *alpha_ecoff_object_p
00043 PARAMS ((bfd *));
00044 static bfd_boolean alpha_ecoff_bad_format_hook
00045 PARAMS ((bfd *abfd, PTR filehdr));
00046 static PTR alpha_ecoff_mkobject_hook
00047 PARAMS ((bfd *, PTR filehdr, PTR aouthdr));
00048 static void alpha_ecoff_swap_reloc_in
00049 PARAMS ((bfd *, PTR, struct internal_reloc *));
00050 static void alpha_ecoff_swap_reloc_out
00051 PARAMS ((bfd *, const struct internal_reloc *, PTR));
00052 static void alpha_adjust_reloc_in
00053 PARAMS ((bfd *, const struct internal_reloc *, arelent *));
00054 static void alpha_adjust_reloc_out
00055 PARAMS ((bfd *, const arelent *, struct internal_reloc *));
00056 static reloc_howto_type *alpha_bfd_reloc_type_lookup
00057 PARAMS ((bfd *, bfd_reloc_code_real_type));
00058 static bfd_byte *alpha_ecoff_get_relocated_section_contents
00059 PARAMS ((bfd *abfd, struct bfd_link_info *, struct bfd_link_order *,
00060 bfd_byte *data, bfd_boolean relocatable, asymbol **symbols));
00061 static bfd_vma alpha_convert_external_reloc
00062 PARAMS ((bfd *, struct bfd_link_info *, bfd *, struct external_reloc *,
00063 struct ecoff_link_hash_entry *));
00064 static bfd_boolean alpha_relocate_section
00065 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, PTR));
00066 static bfd_boolean alpha_adjust_headers
00067 PARAMS ((bfd *, struct internal_filehdr *, struct internal_aouthdr *));
00068 static PTR alpha_ecoff_read_ar_hdr
00069 PARAMS ((bfd *));
00070 static bfd *alpha_ecoff_get_elt_at_filepos
00071 PARAMS ((bfd *, file_ptr));
00072 static bfd *alpha_ecoff_openr_next_archived_file
00073 PARAMS ((bfd *, bfd *));
00074 static bfd *alpha_ecoff_get_elt_at_index
00075 PARAMS ((bfd *, symindex));
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 #define GET_FILEHDR_SYMPTR H_GET_64
00088 #define PUT_FILEHDR_SYMPTR H_PUT_64
00089 #define GET_AOUTHDR_TSIZE H_GET_64
00090 #define PUT_AOUTHDR_TSIZE H_PUT_64
00091 #define GET_AOUTHDR_DSIZE H_GET_64
00092 #define PUT_AOUTHDR_DSIZE H_PUT_64
00093 #define GET_AOUTHDR_BSIZE H_GET_64
00094 #define PUT_AOUTHDR_BSIZE H_PUT_64
00095 #define GET_AOUTHDR_ENTRY H_GET_64
00096 #define PUT_AOUTHDR_ENTRY H_PUT_64
00097 #define GET_AOUTHDR_TEXT_START H_GET_64
00098 #define PUT_AOUTHDR_TEXT_START H_PUT_64
00099 #define GET_AOUTHDR_DATA_START H_GET_64
00100 #define PUT_AOUTHDR_DATA_START H_PUT_64
00101 #define GET_SCNHDR_PADDR H_GET_64
00102 #define PUT_SCNHDR_PADDR H_PUT_64
00103 #define GET_SCNHDR_VADDR H_GET_64
00104 #define PUT_SCNHDR_VADDR H_PUT_64
00105 #define GET_SCNHDR_SIZE H_GET_64
00106 #define PUT_SCNHDR_SIZE H_PUT_64
00107 #define GET_SCNHDR_SCNPTR H_GET_64
00108 #define PUT_SCNHDR_SCNPTR H_PUT_64
00109 #define GET_SCNHDR_RELPTR H_GET_64
00110 #define PUT_SCNHDR_RELPTR H_PUT_64
00111 #define GET_SCNHDR_LNNOPTR H_GET_64
00112 #define PUT_SCNHDR_LNNOPTR H_PUT_64
00113
00114 #define ALPHAECOFF
00115
00116 #define NO_COFF_RELOCS
00117 #define NO_COFF_SYMBOLS
00118 #define NO_COFF_LINENOS
00119 #define coff_swap_filehdr_in alpha_ecoff_swap_filehdr_in
00120 #define coff_swap_filehdr_out alpha_ecoff_swap_filehdr_out
00121 #define coff_swap_aouthdr_in alpha_ecoff_swap_aouthdr_in
00122 #define coff_swap_aouthdr_out alpha_ecoff_swap_aouthdr_out
00123 #define coff_swap_scnhdr_in alpha_ecoff_swap_scnhdr_in
00124 #define coff_swap_scnhdr_out alpha_ecoff_swap_scnhdr_out
00125 #include "coffswap.h"
00126
00127
00128 #define ECOFF_64
00129 #include "ecoffswap.h"
00130
00131
00132
00133 static bfd_reloc_status_type reloc_nil
00134 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00135
00136 static bfd_reloc_status_type
00137 reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message)
00138 bfd *abfd ATTRIBUTE_UNUSED;
00139 arelent *reloc ATTRIBUTE_UNUSED;
00140 asymbol *sym ATTRIBUTE_UNUSED;
00141 PTR data ATTRIBUTE_UNUSED;
00142 asection *sec ATTRIBUTE_UNUSED;
00143 bfd *output_bfd ATTRIBUTE_UNUSED;
00144 char **error_message ATTRIBUTE_UNUSED;
00145 {
00146 return bfd_reloc_ok;
00147 }
00148
00149
00150
00151 #define MINUS_ONE (((bfd_vma)0) - 1)
00152
00153 static reloc_howto_type alpha_howto_table[] =
00154 {
00155
00156
00157
00158 HOWTO (ALPHA_R_IGNORE,
00159 0,
00160 0,
00161 8,
00162 TRUE,
00163 0,
00164 complain_overflow_dont,
00165 reloc_nil,
00166 "IGNORE",
00167 TRUE,
00168 0,
00169 0,
00170 TRUE),
00171
00172
00173 HOWTO (ALPHA_R_REFLONG,
00174 0,
00175 2,
00176 32,
00177 FALSE,
00178 0,
00179 complain_overflow_bitfield,
00180 0,
00181 "REFLONG",
00182 TRUE,
00183 0xffffffff,
00184 0xffffffff,
00185 FALSE),
00186
00187
00188 HOWTO (ALPHA_R_REFQUAD,
00189 0,
00190 4,
00191 64,
00192 FALSE,
00193 0,
00194 complain_overflow_bitfield,
00195 0,
00196 "REFQUAD",
00197 TRUE,
00198 MINUS_ONE,
00199 MINUS_ONE,
00200 FALSE),
00201
00202
00203
00204
00205 HOWTO (ALPHA_R_GPREL32,
00206 0,
00207 2,
00208 32,
00209 FALSE,
00210 0,
00211 complain_overflow_bitfield,
00212 0,
00213 "GPREL32",
00214 TRUE,
00215 0xffffffff,
00216 0xffffffff,
00217 FALSE),
00218
00219
00220
00221
00222 HOWTO (ALPHA_R_LITERAL,
00223 0,
00224 2,
00225 16,
00226 FALSE,
00227 0,
00228 complain_overflow_signed,
00229 0,
00230 "LITERAL",
00231 TRUE,
00232 0xffff,
00233 0xffff,
00234 FALSE),
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 HOWTO (ALPHA_R_LITUSE,
00246 0,
00247 2,
00248 32,
00249 FALSE,
00250 0,
00251 complain_overflow_dont,
00252 reloc_nil,
00253 "LITUSE",
00254 FALSE,
00255 0,
00256 0,
00257 FALSE),
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 HOWTO (ALPHA_R_GPDISP,
00271 16,
00272 2,
00273 16,
00274 TRUE,
00275 0,
00276 complain_overflow_dont,
00277 reloc_nil,
00278 "GPDISP",
00279 TRUE,
00280 0xffff,
00281 0xffff,
00282 TRUE),
00283
00284
00285
00286
00287 HOWTO (ALPHA_R_BRADDR,
00288 2,
00289 2,
00290 21,
00291 TRUE,
00292 0,
00293 complain_overflow_signed,
00294 0,
00295 "BRADDR",
00296 TRUE,
00297 0x1fffff,
00298 0x1fffff,
00299 FALSE),
00300
00301
00302 HOWTO (ALPHA_R_HINT,
00303 2,
00304 2,
00305 14,
00306 TRUE,
00307 0,
00308 complain_overflow_dont,
00309 0,
00310 "HINT",
00311 TRUE,
00312 0x3fff,
00313 0x3fff,
00314 FALSE),
00315
00316
00317 HOWTO (ALPHA_R_SREL16,
00318 0,
00319 1,
00320 16,
00321 TRUE,
00322 0,
00323 complain_overflow_signed,
00324 0,
00325 "SREL16",
00326 TRUE,
00327 0xffff,
00328 0xffff,
00329 FALSE),
00330
00331
00332 HOWTO (ALPHA_R_SREL32,
00333 0,
00334 2,
00335 32,
00336 TRUE,
00337 0,
00338 complain_overflow_signed,
00339 0,
00340 "SREL32",
00341 TRUE,
00342 0xffffffff,
00343 0xffffffff,
00344 FALSE),
00345
00346
00347 HOWTO (ALPHA_R_SREL64,
00348 0,
00349 4,
00350 64,
00351 TRUE,
00352 0,
00353 complain_overflow_signed,
00354 0,
00355 "SREL64",
00356 TRUE,
00357 MINUS_ONE,
00358 MINUS_ONE,
00359 FALSE),
00360
00361
00362 HOWTO (ALPHA_R_OP_PUSH,
00363 0,
00364 0,
00365 0,
00366 FALSE,
00367 0,
00368 complain_overflow_dont,
00369 0,
00370 "OP_PUSH",
00371 FALSE,
00372 0,
00373 0,
00374 FALSE),
00375
00376
00377
00378 HOWTO (ALPHA_R_OP_STORE,
00379 0,
00380 4,
00381 64,
00382 FALSE,
00383 0,
00384 complain_overflow_dont,
00385 0,
00386 "OP_STORE",
00387 FALSE,
00388 0,
00389 MINUS_ONE,
00390 FALSE),
00391
00392
00393
00394 HOWTO (ALPHA_R_OP_PSUB,
00395 0,
00396 0,
00397 0,
00398 FALSE,
00399 0,
00400 complain_overflow_dont,
00401 0,
00402 "OP_PSUB",
00403 FALSE,
00404 0,
00405 0,
00406 FALSE),
00407
00408
00409
00410 HOWTO (ALPHA_R_OP_PRSHIFT,
00411 0,
00412 0,
00413 0,
00414 FALSE,
00415 0,
00416 complain_overflow_dont,
00417 0,
00418 "OP_PRSHIFT",
00419 FALSE,
00420 0,
00421 0,
00422 FALSE),
00423
00424
00425 HOWTO (ALPHA_R_GPVALUE,
00426 0,
00427 0,
00428 0,
00429 FALSE,
00430 0,
00431 complain_overflow_dont,
00432 0,
00433 "GPVALUE",
00434 FALSE,
00435 0,
00436 0,
00437 FALSE)
00438 };
00439
00440
00441
00442 static const bfd_target *
00443 alpha_ecoff_object_p (abfd)
00444 bfd *abfd;
00445 {
00446 static const bfd_target *ret;
00447
00448 ret = coff_object_p (abfd);
00449
00450 if (ret != NULL)
00451 {
00452 asection *sec;
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 sec = bfd_get_section_by_name (abfd, _PDATA);
00464 if (sec != (asection *) NULL)
00465 {
00466 bfd_size_type size;
00467
00468 size = sec->line_filepos * 8;
00469 BFD_ASSERT (size == sec->size
00470 || size + 8 == sec->size);
00471 if (! bfd_set_section_size (abfd, sec, size))
00472 return NULL;
00473 }
00474 }
00475
00476 return ret;
00477 }
00478
00479
00480
00481 static bfd_boolean
00482 alpha_ecoff_bad_format_hook (abfd, filehdr)
00483 bfd *abfd ATTRIBUTE_UNUSED;
00484 PTR filehdr;
00485 {
00486 struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
00487
00488 if (ALPHA_ECOFF_BADMAG (*internal_f))
00489 return FALSE;
00490
00491 return TRUE;
00492 }
00493
00494
00495
00496
00497 static PTR
00498 alpha_ecoff_mkobject_hook (abfd, filehdr, aouthdr)
00499 bfd *abfd;
00500 PTR filehdr;
00501 PTR aouthdr;
00502 {
00503 PTR ecoff;
00504
00505 ecoff = _bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr);
00506
00507 if (ecoff != NULL)
00508 {
00509 struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
00510
00511
00512
00513 switch (internal_f->f_flags & F_ALPHA_OBJECT_TYPE_MASK)
00514 {
00515 case F_ALPHA_SHARABLE:
00516 abfd->flags |= DYNAMIC;
00517 break;
00518 case F_ALPHA_CALL_SHARED:
00519
00520
00521 abfd->flags |= (DYNAMIC | EXEC_P);
00522 break;
00523 }
00524 }
00525 return ecoff;
00526 }
00527
00528
00529
00530
00531
00532 static void
00533 alpha_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
00534 bfd *abfd;
00535 PTR ext_ptr;
00536 struct internal_reloc *intern;
00537 {
00538 const RELOC *ext = (RELOC *) ext_ptr;
00539
00540 intern->r_vaddr = H_GET_64 (abfd, ext->r_vaddr);
00541 intern->r_symndx = H_GET_32 (abfd, ext->r_symndx);
00542
00543 BFD_ASSERT (bfd_header_little_endian (abfd));
00544
00545 intern->r_type = ((ext->r_bits[0] & RELOC_BITS0_TYPE_LITTLE)
00546 >> RELOC_BITS0_TYPE_SH_LITTLE);
00547 intern->r_extern = (ext->r_bits[1] & RELOC_BITS1_EXTERN_LITTLE) != 0;
00548 intern->r_offset = ((ext->r_bits[1] & RELOC_BITS1_OFFSET_LITTLE)
00549 >> RELOC_BITS1_OFFSET_SH_LITTLE);
00550
00551 intern->r_size = ((ext->r_bits[3] & RELOC_BITS3_SIZE_LITTLE)
00552 >> RELOC_BITS3_SIZE_SH_LITTLE);
00553
00554 if (intern->r_type == ALPHA_R_LITUSE
00555 || intern->r_type == ALPHA_R_GPDISP)
00556 {
00557
00558
00559
00560
00561 if (intern->r_size != 0)
00562 abort ();
00563 intern->r_size = intern->r_symndx;
00564 intern->r_symndx = RELOC_SECTION_NONE;
00565 }
00566 else if (intern->r_type == ALPHA_R_IGNORE)
00567 {
00568
00569
00570 if (! intern->r_extern &&
00571 intern->r_symndx == RELOC_SECTION_ABS)
00572 abort ();
00573 if (! intern->r_extern && intern->r_symndx == RELOC_SECTION_LITA)
00574 intern->r_symndx = RELOC_SECTION_ABS;
00575 }
00576 }
00577
00578
00579
00580 static void
00581 alpha_ecoff_swap_reloc_out (abfd, intern, dst)
00582 bfd *abfd;
00583 const struct internal_reloc *intern;
00584 PTR dst;
00585 {
00586 RELOC *ext = (RELOC *) dst;
00587 long symndx;
00588 unsigned char size;
00589
00590
00591 if (intern->r_type == ALPHA_R_LITUSE
00592 || intern->r_type == ALPHA_R_GPDISP)
00593 {
00594 symndx = intern->r_size;
00595 size = 0;
00596 }
00597 else if (intern->r_type == ALPHA_R_IGNORE
00598 && ! intern->r_extern
00599 && intern->r_symndx == RELOC_SECTION_ABS)
00600 {
00601 symndx = RELOC_SECTION_LITA;
00602 size = intern->r_size;
00603 }
00604 else
00605 {
00606 symndx = intern->r_symndx;
00607 size = intern->r_size;
00608 }
00609
00610 BFD_ASSERT (intern->r_extern
00611 || (intern->r_symndx >= 0 && intern->r_symndx <= 14));
00612
00613 H_PUT_64 (abfd, intern->r_vaddr, ext->r_vaddr);
00614 H_PUT_32 (abfd, symndx, ext->r_symndx);
00615
00616 BFD_ASSERT (bfd_header_little_endian (abfd));
00617
00618 ext->r_bits[0] = ((intern->r_type << RELOC_BITS0_TYPE_SH_LITTLE)
00619 & RELOC_BITS0_TYPE_LITTLE);
00620 ext->r_bits[1] = ((intern->r_extern ? RELOC_BITS1_EXTERN_LITTLE : 0)
00621 | ((intern->r_offset << RELOC_BITS1_OFFSET_SH_LITTLE)
00622 & RELOC_BITS1_OFFSET_LITTLE));
00623 ext->r_bits[2] = 0;
00624 ext->r_bits[3] = ((size << RELOC_BITS3_SIZE_SH_LITTLE)
00625 & RELOC_BITS3_SIZE_LITTLE);
00626 }
00627
00628
00629
00630
00631
00632 static void
00633 alpha_adjust_reloc_in (abfd, intern, rptr)
00634 bfd *abfd;
00635 const struct internal_reloc *intern;
00636 arelent *rptr;
00637 {
00638 if (intern->r_type > ALPHA_R_GPVALUE)
00639 abort ();
00640
00641 switch (intern->r_type)
00642 {
00643 case ALPHA_R_BRADDR:
00644 case ALPHA_R_SREL16:
00645 case ALPHA_R_SREL32:
00646 case ALPHA_R_SREL64:
00647
00648
00649
00650 if (! intern->r_extern)
00651 rptr->addend = 0;
00652 else
00653 rptr->addend = - (intern->r_vaddr + 4);
00654 break;
00655
00656 case ALPHA_R_GPREL32:
00657 case ALPHA_R_LITERAL:
00658
00659
00660 if (! intern->r_extern)
00661 rptr->addend += ecoff_data (abfd)->gp;
00662 break;
00663
00664 case ALPHA_R_LITUSE:
00665 case ALPHA_R_GPDISP:
00666
00667
00668
00669 rptr->addend = intern->r_size;
00670 break;
00671
00672 case ALPHA_R_OP_STORE:
00673
00674
00675 BFD_ASSERT (intern->r_offset <= 256);
00676 rptr->addend = (intern->r_offset << 8) + intern->r_size;
00677 break;
00678
00679 case ALPHA_R_OP_PUSH:
00680 case ALPHA_R_OP_PSUB:
00681 case ALPHA_R_OP_PRSHIFT:
00682
00683
00684
00685 rptr->addend = intern->r_vaddr;
00686 break;
00687
00688 case ALPHA_R_GPVALUE:
00689
00690 rptr->addend = intern->r_symndx + ecoff_data (abfd)->gp;
00691 break;
00692
00693 case ALPHA_R_IGNORE:
00694
00695
00696
00697
00698
00699 rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
00700 rptr->address = intern->r_vaddr;
00701 rptr->addend = ecoff_data (abfd)->gp;
00702 break;
00703
00704 default:
00705 break;
00706 }
00707
00708 rptr->howto = &alpha_howto_table[intern->r_type];
00709 }
00710
00711
00712
00713
00714
00715
00716 static void
00717 alpha_adjust_reloc_out (abfd, rel, intern)
00718 bfd *abfd ATTRIBUTE_UNUSED;
00719 const arelent *rel;
00720 struct internal_reloc *intern;
00721 {
00722 switch (intern->r_type)
00723 {
00724 case ALPHA_R_LITUSE:
00725 case ALPHA_R_GPDISP:
00726 intern->r_size = rel->addend;
00727 break;
00728
00729 case ALPHA_R_OP_STORE:
00730 intern->r_size = rel->addend & 0xff;
00731 intern->r_offset = (rel->addend >> 8) & 0xff;
00732 break;
00733
00734 case ALPHA_R_OP_PUSH:
00735 case ALPHA_R_OP_PSUB:
00736 case ALPHA_R_OP_PRSHIFT:
00737 intern->r_vaddr = rel->addend;
00738 break;
00739
00740 case ALPHA_R_IGNORE:
00741 intern->r_vaddr = rel->address;
00742 break;
00743
00744 default:
00745 break;
00746 }
00747 }
00748
00749
00750 #define RELOC_STACKSIZE (10)
00751
00752
00753
00754
00755
00756
00757
00758 static bfd_byte *
00759 alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order,
00760 data, relocatable, symbols)
00761 bfd *abfd;
00762 struct bfd_link_info *link_info;
00763 struct bfd_link_order *link_order;
00764 bfd_byte *data;
00765 bfd_boolean relocatable;
00766 asymbol **symbols;
00767 {
00768 bfd *input_bfd = link_order->u.indirect.section->owner;
00769 asection *input_section = link_order->u.indirect.section;
00770 long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
00771 arelent **reloc_vector = NULL;
00772 long reloc_count;
00773 bfd *output_bfd = relocatable ? abfd : (bfd *) NULL;
00774 bfd_vma gp;
00775 bfd_size_type sz;
00776 bfd_boolean gp_undefined;
00777 bfd_vma stack[RELOC_STACKSIZE];
00778 int tos = 0;
00779
00780 if (reloc_size < 0)
00781 goto error_return;
00782 reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
00783 if (reloc_vector == NULL && reloc_size != 0)
00784 goto error_return;
00785
00786 sz = input_section->rawsize ? input_section->rawsize : input_section->size;
00787 if (! bfd_get_section_contents (input_bfd, input_section, data, 0, sz))
00788 goto error_return;
00789
00790 reloc_count = bfd_canonicalize_reloc (input_bfd, input_section,
00791 reloc_vector, symbols);
00792 if (reloc_count < 0)
00793 goto error_return;
00794 if (reloc_count == 0)
00795 goto successful_return;
00796
00797
00798 gp_undefined = FALSE;
00799 gp = _bfd_get_gp_value (abfd);
00800 if (gp == 0)
00801 {
00802 if (relocatable)
00803 {
00804 asection *sec;
00805 bfd_vma lo;
00806
00807
00808 lo = (bfd_vma) -1;
00809 for (sec = abfd->sections; sec != NULL; sec = sec->next)
00810 {
00811 if (sec->vma < lo
00812 && (strcmp (sec->name, ".sbss") == 0
00813 || strcmp (sec->name, ".sdata") == 0
00814 || strcmp (sec->name, ".lit4") == 0
00815 || strcmp (sec->name, ".lit8") == 0
00816 || strcmp (sec->name, ".lita") == 0))
00817 lo = sec->vma;
00818 }
00819 gp = lo + 0x8000;
00820 _bfd_set_gp_value (abfd, gp);
00821 }
00822 else
00823 {
00824 struct bfd_link_hash_entry *h;
00825
00826 h = bfd_link_hash_lookup (link_info->hash, "_gp", FALSE, FALSE,
00827 TRUE);
00828 if (h == (struct bfd_link_hash_entry *) NULL
00829 || h->type != bfd_link_hash_defined)
00830 gp_undefined = TRUE;
00831 else
00832 {
00833 gp = (h->u.def.value
00834 + h->u.def.section->output_section->vma
00835 + h->u.def.section->output_offset);
00836 _bfd_set_gp_value (abfd, gp);
00837 }
00838 }
00839 }
00840
00841 for (; *reloc_vector != (arelent *) NULL; reloc_vector++)
00842 {
00843 arelent *rel;
00844 bfd_reloc_status_type r;
00845 char *err;
00846
00847 rel = *reloc_vector;
00848 r = bfd_reloc_ok;
00849 switch (rel->howto->type)
00850 {
00851 case ALPHA_R_IGNORE:
00852 rel->address += input_section->output_offset;
00853 break;
00854
00855 case ALPHA_R_REFLONG:
00856 case ALPHA_R_REFQUAD:
00857 case ALPHA_R_BRADDR:
00858 case ALPHA_R_HINT:
00859 case ALPHA_R_SREL16:
00860 case ALPHA_R_SREL32:
00861 case ALPHA_R_SREL64:
00862 if (relocatable
00863 && ((*rel->sym_ptr_ptr)->flags & BSF_SECTION_SYM) == 0)
00864 {
00865 rel->address += input_section->output_offset;
00866 break;
00867 }
00868 r = bfd_perform_relocation (input_bfd, rel, data, input_section,
00869 output_bfd, &err);
00870 break;
00871
00872 case ALPHA_R_GPREL32:
00873
00874
00875
00876
00877
00878
00879 rel->addend -= gp;
00880 r = bfd_perform_relocation (input_bfd, rel, data, input_section,
00881 output_bfd, &err);
00882 if (r == bfd_reloc_ok && gp_undefined)
00883 {
00884 r = bfd_reloc_dangerous;
00885 err = (char *) _("GP relative relocation used when GP not defined");
00886 }
00887 break;
00888
00889 case ALPHA_R_LITERAL:
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906 {
00907 unsigned long insn;
00908
00909
00910
00911 insn = bfd_get_32 (input_bfd, data + rel->address);
00912 BFD_ASSERT (((insn >> 26) & 0x3f) == 0x29
00913 || ((insn >> 26) & 0x3f) == 0x28);
00914
00915 rel->addend -= gp;
00916 r = bfd_perform_relocation (input_bfd, rel, data, input_section,
00917 output_bfd, &err);
00918 if (r == bfd_reloc_ok && gp_undefined)
00919 {
00920 r = bfd_reloc_dangerous;
00921 err =
00922 (char *) _("GP relative relocation used when GP not defined");
00923 }
00924 }
00925 break;
00926
00927 case ALPHA_R_LITUSE:
00928
00929
00930 rel->address += input_section->output_offset;
00931 break;
00932
00933 case ALPHA_R_GPDISP:
00934
00935
00936
00937
00938
00939 {
00940 unsigned long insn1, insn2;
00941 bfd_vma addend;
00942
00943
00944 insn1 = bfd_get_32 (input_bfd, data + rel->address);
00945 insn2 = bfd_get_32 (input_bfd, data + rel->address + rel->addend);
00946
00947 BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09);
00948 BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08);
00949
00950
00951
00952 addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff);
00953 if (insn1 & 0x8000)
00954 {
00955 addend -= 0x80000000;
00956 addend -= 0x80000000;
00957 }
00958 if (insn2 & 0x8000)
00959 addend -= 0x10000;
00960
00961
00962
00963
00964 addend -= (ecoff_data (input_bfd)->gp
00965 - (input_section->vma + rel->address));
00966
00967
00968
00969 addend += (gp
00970 - (input_section->output_section->vma
00971 + input_section->output_offset
00972 + rel->address));
00973
00974
00975
00976 if (addend & 0x8000)
00977 addend += 0x10000;
00978 insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff);
00979 insn2 = (insn2 & 0xffff0000) | (addend & 0xffff);
00980
00981 bfd_put_32 (input_bfd, (bfd_vma) insn1, data + rel->address);
00982 bfd_put_32 (input_bfd, (bfd_vma) insn2,
00983 data + rel->address + rel->addend);
00984
00985 rel->address += input_section->output_offset;
00986 }
00987 break;
00988
00989 case ALPHA_R_OP_PUSH:
00990
00991 {
00992 asymbol *symbol;
00993 bfd_vma relocation;
00994
00995 if (relocatable)
00996 {
00997 rel->address += input_section->output_offset;
00998 break;
00999 }
01000
01001
01002 symbol = *rel->sym_ptr_ptr;
01003
01004 if (bfd_is_und_section (symbol->section))
01005 r = bfd_reloc_undefined;
01006
01007 if (bfd_is_com_section (symbol->section))
01008 relocation = 0;
01009 else
01010 relocation = symbol->value;
01011 relocation += symbol->section->output_section->vma;
01012 relocation += symbol->section->output_offset;
01013 relocation += rel->addend;
01014
01015 if (tos >= RELOC_STACKSIZE)
01016 abort ();
01017
01018 stack[tos++] = relocation;
01019 }
01020 break;
01021
01022 case ALPHA_R_OP_STORE:
01023
01024 {
01025 bfd_vma val;
01026 int offset, size;
01027
01028 if (relocatable)
01029 {
01030 rel->address += input_section->output_offset;
01031 break;
01032 }
01033
01034 if (tos == 0)
01035 abort ();
01036
01037
01038
01039 offset = (rel->addend >> 8) & 0xff;
01040 size = rel->addend & 0xff;
01041
01042 val = bfd_get_64 (abfd, data + rel->address);
01043 val &=~ (((1 << size) - 1) << offset);
01044 val |= (stack[--tos] & ((1 << size) - 1)) << offset;
01045 bfd_put_64 (abfd, val, data + rel->address);
01046 }
01047 break;
01048
01049 case ALPHA_R_OP_PSUB:
01050
01051 {
01052 asymbol *symbol;
01053 bfd_vma relocation;
01054
01055 if (relocatable)
01056 {
01057 rel->address += input_section->output_offset;
01058 break;
01059 }
01060
01061
01062 symbol = *rel->sym_ptr_ptr;
01063
01064 if (bfd_is_und_section (symbol->section))
01065 r = bfd_reloc_undefined;
01066
01067 if (bfd_is_com_section (symbol->section))
01068 relocation = 0;
01069 else
01070 relocation = symbol->value;
01071 relocation += symbol->section->output_section->vma;
01072 relocation += symbol->section->output_offset;
01073 relocation += rel->addend;
01074
01075 if (tos == 0)
01076 abort ();
01077
01078 stack[tos - 1] -= relocation;
01079 }
01080 break;
01081
01082 case ALPHA_R_OP_PRSHIFT:
01083
01084 {
01085 asymbol *symbol;
01086 bfd_vma relocation;
01087
01088 if (relocatable)
01089 {
01090 rel->address += input_section->output_offset;
01091 break;
01092 }
01093
01094
01095 symbol = *rel->sym_ptr_ptr;
01096
01097 if (bfd_is_und_section (symbol->section))
01098 r = bfd_reloc_undefined;
01099
01100 if (bfd_is_com_section (symbol->section))
01101 relocation = 0;
01102 else
01103 relocation = symbol->value;
01104 relocation += symbol->section->output_section->vma;
01105 relocation += symbol->section->output_offset;
01106 relocation += rel->addend;
01107
01108 if (tos == 0)
01109 abort ();
01110
01111 stack[tos - 1] >>= relocation;
01112 }
01113 break;
01114
01115 case ALPHA_R_GPVALUE:
01116
01117 gp = rel->addend;
01118 gp_undefined = FALSE;
01119 break;
01120
01121 default:
01122 abort ();
01123 }
01124
01125 if (relocatable)
01126 {
01127 asection *os = input_section->output_section;
01128
01129
01130 os->orelocation[os->reloc_count] = rel;
01131 os->reloc_count++;
01132 }
01133
01134 if (r != bfd_reloc_ok)
01135 {
01136 switch (r)
01137 {
01138 case bfd_reloc_undefined:
01139 if (! ((*link_info->callbacks->undefined_symbol)
01140 (link_info, bfd_asymbol_name (*rel->sym_ptr_ptr),
01141 input_bfd, input_section, rel->address, TRUE)))
01142 goto error_return;
01143 break;
01144 case bfd_reloc_dangerous:
01145 if (! ((*link_info->callbacks->reloc_dangerous)
01146 (link_info, err, input_bfd, input_section,
01147 rel->address)))
01148 goto error_return;
01149 break;
01150 case bfd_reloc_overflow:
01151 if (! ((*link_info->callbacks->reloc_overflow)
01152 (link_info, NULL,
01153 bfd_asymbol_name (*rel->sym_ptr_ptr),
01154 rel->howto->name, rel->addend, input_bfd,
01155 input_section, rel->address)))
01156 goto error_return;
01157 break;
01158 case bfd_reloc_outofrange:
01159 default:
01160 abort ();
01161 break;
01162 }
01163 }
01164 }
01165
01166 if (tos != 0)
01167 abort ();
01168
01169 successful_return:
01170 if (reloc_vector != NULL)
01171 free (reloc_vector);
01172 return data;
01173
01174 error_return:
01175 if (reloc_vector != NULL)
01176 free (reloc_vector);
01177 return NULL;
01178 }
01179
01180
01181
01182 static reloc_howto_type *
01183 alpha_bfd_reloc_type_lookup (abfd, code)
01184 bfd *abfd ATTRIBUTE_UNUSED;
01185 bfd_reloc_code_real_type code;
01186 {
01187 int alpha_type;
01188
01189 switch (code)
01190 {
01191 case BFD_RELOC_32:
01192 alpha_type = ALPHA_R_REFLONG;
01193 break;
01194 case BFD_RELOC_64:
01195 case BFD_RELOC_CTOR:
01196 alpha_type = ALPHA_R_REFQUAD;
01197 break;
01198 case BFD_RELOC_GPREL32:
01199 alpha_type = ALPHA_R_GPREL32;
01200 break;
01201 case BFD_RELOC_ALPHA_LITERAL:
01202 alpha_type = ALPHA_R_LITERAL;
01203 break;
01204 case BFD_RELOC_ALPHA_LITUSE:
01205 alpha_type = ALPHA_R_LITUSE;
01206 break;
01207 case BFD_RELOC_ALPHA_GPDISP_HI16:
01208 alpha_type = ALPHA_R_GPDISP;
01209 break;
01210 case BFD_RELOC_ALPHA_GPDISP_LO16:
01211 alpha_type = ALPHA_R_IGNORE;
01212 break;
01213 case BFD_RELOC_23_PCREL_S2:
01214 alpha_type = ALPHA_R_BRADDR;
01215 break;
01216 case BFD_RELOC_ALPHA_HINT:
01217 alpha_type = ALPHA_R_HINT;
01218 break;
01219 case BFD_RELOC_16_PCREL:
01220 alpha_type = ALPHA_R_SREL16;
01221 break;
01222 case BFD_RELOC_32_PCREL:
01223 alpha_type = ALPHA_R_SREL32;
01224 break;
01225 case BFD_RELOC_64_PCREL:
01226 alpha_type = ALPHA_R_SREL64;
01227 break;
01228 default:
01229 return (reloc_howto_type *) NULL;
01230 }
01231
01232 return &alpha_howto_table[alpha_type];
01233 }
01234
01235
01236
01237
01238
01239 static bfd_vma
01240 alpha_convert_external_reloc (output_bfd, info, input_bfd, ext_rel, h)
01241 bfd *output_bfd ATTRIBUTE_UNUSED;
01242 struct bfd_link_info *info;
01243 bfd *input_bfd;
01244 struct external_reloc *ext_rel;
01245 struct ecoff_link_hash_entry *h;
01246 {
01247 unsigned long r_symndx;
01248 bfd_vma relocation;
01249
01250 BFD_ASSERT (info->relocatable);
01251
01252 if (h->root.type == bfd_link_hash_defined
01253 || h->root.type == bfd_link_hash_defweak)
01254 {
01255 asection *hsec;
01256 const char *name;
01257
01258
01259
01260
01261
01262 ext_rel->r_bits[1] &=~ RELOC_BITS1_EXTERN_LITTLE;
01263
01264
01265 hsec = h->root.u.def.section;
01266 name = bfd_get_section_name (output_bfd, hsec->output_section);
01267
01268 r_symndx = (unsigned long) -1;
01269 switch (name[1])
01270 {
01271 case 'A':
01272 if (strcmp (name, "*ABS*") == 0)
01273 r_symndx = RELOC_SECTION_ABS;
01274 break;
01275 case 'b':
01276 if (strcmp (name, ".bss") == 0)
01277 r_symndx = RELOC_SECTION_BSS;
01278 break;
01279 case 'd':
01280 if (strcmp (name, ".data") == 0)
01281 r_symndx = RELOC_SECTION_DATA;
01282 break;
01283 case 'f':
01284 if (strcmp (name, ".fini") == 0)
01285 r_symndx = RELOC_SECTION_FINI;
01286 break;
01287 case 'i':
01288 if (strcmp (name, ".init") == 0)
01289 r_symndx = RELOC_SECTION_INIT;
01290 break;
01291 case 'l':
01292 if (strcmp (name, ".lita") == 0)
01293 r_symndx = RELOC_SECTION_LITA;
01294 else if (strcmp (name, ".lit8") == 0)
01295 r_symndx = RELOC_SECTION_LIT8;
01296 else if (strcmp (name, ".lit4") == 0)
01297 r_symndx = RELOC_SECTION_LIT4;
01298 break;
01299 case 'p':
01300 if (strcmp (name, ".pdata") == 0)
01301 r_symndx = RELOC_SECTION_PDATA;
01302 break;
01303 case 'r':
01304 if (strcmp (name, ".rdata") == 0)
01305 r_symndx = RELOC_SECTION_RDATA;
01306 else if (strcmp (name, ".rconst") == 0)
01307 r_symndx = RELOC_SECTION_RCONST;
01308 break;
01309 case 's':
01310 if (strcmp (name, ".sdata") == 0)
01311 r_symndx = RELOC_SECTION_SDATA;
01312 else if (strcmp (name, ".sbss") == 0)
01313 r_symndx = RELOC_SECTION_SBSS;
01314 break;
01315 case 't':
01316 if (strcmp (name, ".text") == 0)
01317 r_symndx = RELOC_SECTION_TEXT;
01318 break;
01319 case 'x':
01320 if (strcmp (name, ".xdata") == 0)
01321 r_symndx = RELOC_SECTION_XDATA;
01322 break;
01323 }
01324
01325 if (r_symndx == (unsigned long) -1)
01326 abort ();
01327
01328
01329 relocation = (h->root.u.def.value
01330 + hsec->output_section->vma
01331 + hsec->output_offset);
01332 }
01333 else
01334 {
01335
01336
01337 r_symndx = h->indx;
01338 if (r_symndx == (unsigned long) -1)
01339 {
01340
01341 r_symndx = 0;
01342 }
01343 relocation = 0;
01344 }
01345
01346
01347 H_PUT_32 (input_bfd, r_symndx, ext_rel->r_symndx);
01348
01349 return relocation;
01350 }
01351
01352
01353
01354
01355
01356 static bfd_boolean
01357 alpha_relocate_section (output_bfd, info, input_bfd, input_section,
01358 contents, external_relocs)
01359 bfd *output_bfd;
01360 struct bfd_link_info *info;
01361 bfd *input_bfd;
01362 asection *input_section;
01363 bfd_byte *contents;
01364 PTR external_relocs;
01365 {
01366 asection **symndx_to_section, *lita_sec;
01367 struct ecoff_link_hash_entry **sym_hashes;
01368 bfd_vma gp;
01369 bfd_boolean gp_undefined;
01370 bfd_vma stack[RELOC_STACKSIZE];
01371 int tos = 0;
01372 struct external_reloc *ext_rel;
01373 struct external_reloc *ext_rel_end;
01374 bfd_size_type amt;
01375
01376
01377
01378
01379 symndx_to_section = ecoff_data (input_bfd)->symndx_to_section;
01380 if (symndx_to_section == (asection **) NULL)
01381 {
01382 amt = NUM_RELOC_SECTIONS * sizeof (asection *);
01383 symndx_to_section = (asection **) bfd_alloc (input_bfd, amt);
01384 if (!symndx_to_section)
01385 return FALSE;
01386
01387 symndx_to_section[RELOC_SECTION_NONE] = NULL;
01388 symndx_to_section[RELOC_SECTION_TEXT] =
01389 bfd_get_section_by_name (input_bfd, ".text");
01390 symndx_to_section[RELOC_SECTION_RDATA] =
01391 bfd_get_section_by_name (input_bfd, ".rdata");
01392 symndx_to_section[RELOC_SECTION_DATA] =
01393 bfd_get_section_by_name (input_bfd, ".data");
01394 symndx_to_section[RELOC_SECTION_SDATA] =
01395 bfd_get_section_by_name (input_bfd, ".sdata");
01396 symndx_to_section[RELOC_SECTION_SBSS] =
01397 bfd_get_section_by_name (input_bfd, ".sbss");
01398 symndx_to_section[RELOC_SECTION_BSS] =
01399 bfd_get_section_by_name (input_bfd, ".bss");
01400 symndx_to_section[RELOC_SECTION_INIT] =
01401 bfd_get_section_by_name (input_bfd, ".init");
01402 symndx_to_section[RELOC_SECTION_LIT8] =
01403 bfd_get_section_by_name (input_bfd, ".lit8");
01404 symndx_to_section[RELOC_SECTION_LIT4] =
01405 bfd_get_section_by_name (input_bfd, ".lit4");
01406 symndx_to_section[RELOC_SECTION_XDATA] =
01407 bfd_get_section_by_name (input_bfd, ".xdata");
01408 symndx_to_section[RELOC_SECTION_PDATA] =
01409 bfd_get_section_by_name (input_bfd, ".pdata");
01410 symndx_to_section[RELOC_SECTION_FINI] =
01411 bfd_get_section_by_name (input_bfd, ".fini");
01412 symndx_to_section[RELOC_SECTION_LITA] =
01413 bfd_get_section_by_name (input_bfd, ".lita");
01414 symndx_to_section[RELOC_SECTION_ABS] = bfd_abs_section_ptr;
01415 symndx_to_section[RELOC_SECTION_RCONST] =
01416 bfd_get_section_by_name (input_bfd, ".rconst");
01417
01418 ecoff_data (input_bfd)->symndx_to_section = symndx_to_section;
01419 }
01420
01421 sym_hashes = ecoff_data (input_bfd)->sym_hashes;
01422
01423
01424
01425
01426
01427
01428
01429 lita_sec = symndx_to_section[RELOC_SECTION_LITA];
01430 gp = _bfd_get_gp_value (output_bfd);
01431 if (! info->relocatable && lita_sec != NULL)
01432 {
01433 struct ecoff_section_tdata *lita_sec_data;
01434
01435
01436
01437 lita_sec_data = ecoff_section_data (input_bfd, lita_sec);
01438 if (lita_sec_data == NULL)
01439 {
01440 amt = sizeof (struct ecoff_section_tdata);
01441 lita_sec_data = ((struct ecoff_section_tdata *)
01442 bfd_zalloc (input_bfd, amt));
01443 lita_sec->used_by_bfd = lita_sec_data;
01444 }
01445
01446 if (lita_sec_data->gp != 0)
01447 {
01448
01449
01450 gp = lita_sec_data->gp;
01451 }
01452 else
01453 {
01454 bfd_vma lita_vma;
01455 bfd_size_type lita_size;
01456
01457 lita_vma = lita_sec->output_offset + lita_sec->output_section->vma;
01458 lita_size = lita_sec->size;
01459
01460 if (gp == 0
01461 || lita_vma < gp - 0x8000
01462 || lita_vma + lita_size >= gp + 0x8000)
01463 {
01464
01465
01466
01467
01468 if (gp && !ecoff_data (output_bfd)->issued_multiple_gp_warning)
01469 {
01470 (*info->callbacks->warning) (info,
01471 _("using multiple gp values"),
01472 (char *) NULL, output_bfd,
01473 (asection *) NULL, (bfd_vma) 0);
01474 ecoff_data (output_bfd)->issued_multiple_gp_warning = TRUE;
01475 }
01476 if (lita_vma < gp - 0x8000)
01477 gp = lita_vma + lita_size - 0x8000;
01478 else
01479 gp = lita_vma + 0x8000;
01480
01481 }
01482
01483 lita_sec_data->gp = gp;
01484 }
01485
01486 _bfd_set_gp_value (output_bfd, gp);
01487 }
01488
01489 gp_undefined = (gp == 0);
01490
01491 BFD_ASSERT (bfd_header_little_endian (output_bfd));
01492 BFD_ASSERT (bfd_header_little_endian (input_bfd));
01493
01494 ext_rel = (struct external_reloc *) external_relocs;
01495 ext_rel_end = ext_rel + input_section->reloc_count;
01496 for (; ext_rel < ext_rel_end; ext_rel++)
01497 {
01498 bfd_vma r_vaddr;
01499 unsigned long r_symndx;
01500 int r_type;
01501 int r_extern;
01502 int r_offset;
01503 int r_size;
01504 bfd_boolean relocatep;
01505 bfd_boolean adjust_addrp;
01506 bfd_boolean gp_usedp;
01507 bfd_vma addend;
01508
01509 r_vaddr = H_GET_64 (input_bfd, ext_rel->r_vaddr);
01510 r_symndx = H_GET_32 (input_bfd, ext_rel->r_symndx);
01511
01512 r_type = ((ext_rel->r_bits[0] & RELOC_BITS0_TYPE_LITTLE)
01513 >> RELOC_BITS0_TYPE_SH_LITTLE);
01514 r_extern = (ext_rel->r_bits[1] & RELOC_BITS1_EXTERN_LITTLE) != 0;
01515 r_offset = ((ext_rel->r_bits[1] & RELOC_BITS1_OFFSET_LITTLE)
01516 >> RELOC_BITS1_OFFSET_SH_LITTLE);
01517
01518 r_size = ((ext_rel->r_bits[3] & RELOC_BITS3_SIZE_LITTLE)
01519 >> RELOC_BITS3_SIZE_SH_LITTLE);
01520
01521 relocatep = FALSE;
01522 adjust_addrp = TRUE;
01523 gp_usedp = FALSE;
01524 addend = 0;
01525
01526 switch (r_type)
01527 {
01528 default:
01529 abort ();
01530
01531 case ALPHA_R_IGNORE:
01532
01533
01534
01535
01536
01537
01538 if (info->relocatable)
01539 H_PUT_64 (input_bfd, input_section->output_offset + r_vaddr,
01540 ext_rel->r_vaddr);
01541 adjust_addrp = FALSE;
01542 break;
01543
01544 case ALPHA_R_REFLONG:
01545 case ALPHA_R_REFQUAD:
01546 case ALPHA_R_HINT:
01547 relocatep = TRUE;
01548 break;
01549
01550 case ALPHA_R_BRADDR:
01551 case ALPHA_R_SREL16:
01552 case ALPHA_R_SREL32:
01553 case ALPHA_R_SREL64:
01554 if (r_extern)
01555 addend += - (r_vaddr + 4);
01556 relocatep = TRUE;
01557 break;
01558
01559 case ALPHA_R_GPREL32:
01560
01561
01562
01563
01564 relocatep = TRUE;
01565 addend = ecoff_data (input_bfd)->gp - gp;
01566 gp_usedp = TRUE;
01567 break;
01568
01569 case ALPHA_R_LITERAL:
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588 {
01589 unsigned long insn;
01590
01591 insn = bfd_get_32 (input_bfd,
01592 contents + r_vaddr - input_section->vma);
01593 BFD_ASSERT (((insn >> 26) & 0x3f) == 0x29
01594 || ((insn >> 26) & 0x3f) == 0x28);
01595 }
01596
01597 relocatep = TRUE;
01598 addend = ecoff_data (input_bfd)->gp - gp;
01599 gp_usedp = TRUE;
01600 break;
01601
01602 case ALPHA_R_LITUSE:
01603
01604
01605 break;
01606
01607 case ALPHA_R_GPDISP:
01608
01609
01610
01611
01612
01613 {
01614 unsigned long insn1, insn2;
01615
01616
01617 insn1 = bfd_get_32 (input_bfd,
01618 contents + r_vaddr - input_section->vma);
01619 insn2 = bfd_get_32 (input_bfd,
01620 (contents
01621 + r_vaddr
01622 - input_section->vma
01623 + r_symndx));
01624
01625 BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09);
01626 BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08);
01627
01628
01629
01630 addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff);
01631 if (insn1 & 0x8000)
01632 {
01633
01634
01635 addend -= 0x80000000;
01636 addend -= 0x80000000;
01637 }
01638 if (insn2 & 0x8000)
01639 addend -= 0x10000;
01640
01641
01642
01643
01644
01645 addend += (gp
01646 - ecoff_data (input_bfd)->gp
01647 + input_section->vma
01648 - (input_section->output_section->vma
01649 + input_section->output_offset));
01650
01651
01652
01653 if (addend & 0x8000)
01654 addend += 0x10000;
01655 insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff);
01656 insn2 = (insn2 & 0xffff0000) | (addend & 0xffff);
01657
01658 bfd_put_32 (input_bfd, (bfd_vma) insn1,
01659 contents + r_vaddr - input_section->vma);
01660 bfd_put_32 (input_bfd, (bfd_vma) insn2,
01661 contents + r_vaddr - input_section->vma + r_symndx);
01662
01663 gp_usedp = TRUE;
01664 }
01665 break;
01666
01667 case ALPHA_R_OP_PUSH:
01668 case ALPHA_R_OP_PSUB:
01669 case ALPHA_R_OP_PRSHIFT:
01670
01671
01672
01673
01674 if (! r_extern)
01675 {
01676 asection *s;
01677
01678 s = symndx_to_section[r_symndx];
01679 if (s == (asection *) NULL)
01680 abort ();
01681 addend = s->output_section->vma + s->output_offset - s->vma;
01682 }
01683 else
01684 {
01685 struct ecoff_link_hash_entry *h;
01686
01687 h = sym_hashes[r_symndx];
01688 if (h == (struct ecoff_link_hash_entry *) NULL)
01689 abort ();
01690
01691 if (! info->relocatable)
01692 {
01693 if (h->root.type == bfd_link_hash_defined
01694 || h->root.type == bfd_link_hash_defweak)
01695 addend = (h->root.u.def.value
01696 + h->root.u.def.section->output_section->vma
01697 + h->root.u.def.section->output_offset);
01698 else
01699 {
01700
01701
01702
01703
01704 if (! ((*info->callbacks->undefined_symbol)
01705 (info, h->root.root.string, input_bfd,
01706 input_section, (bfd_vma) 0, TRUE)))
01707 return FALSE;
01708 addend = 0;
01709 }
01710 }
01711 else
01712 {
01713 if (h->root.type != bfd_link_hash_defined
01714 && h->root.type != bfd_link_hash_defweak
01715 && h->indx == -1)
01716 {
01717
01718
01719
01720 if (! ((*info->callbacks->unattached_reloc)
01721 (info, h->root.root.string, input_bfd,
01722 input_section, (bfd_vma) 0)))
01723 return FALSE;
01724 }
01725
01726 addend = alpha_convert_external_reloc (output_bfd, info,
01727 input_bfd,
01728 ext_rel, h);
01729 }
01730 }
01731
01732 addend += r_vaddr;
01733
01734 if (info->relocatable)
01735 {
01736
01737 H_PUT_64 (input_bfd, addend, ext_rel->r_vaddr);
01738 }
01739 else
01740 {
01741 switch (r_type)
01742 {
01743 case ALPHA_R_OP_PUSH:
01744 if (tos >= RELOC_STACKSIZE)
01745 abort ();
01746 stack[tos++] = addend;
01747 break;
01748
01749 case ALPHA_R_OP_PSUB:
01750 if (tos == 0)
01751 abort ();
01752 stack[tos - 1] -= addend;
01753 break;
01754
01755 case ALPHA_R_OP_PRSHIFT:
01756 if (tos == 0)
01757 abort ();
01758 stack[tos - 1] >>= addend;
01759 break;
01760 }
01761 }
01762
01763 adjust_addrp = FALSE;
01764 break;
01765
01766 case ALPHA_R_OP_STORE:
01767
01768
01769
01770 if (! info->relocatable)
01771 {
01772 bfd_vma mask;
01773 bfd_vma val;
01774
01775 if (tos == 0)
01776 abort ();
01777
01778
01779
01780
01781
01782 mask = 1;
01783 mask <<= (bfd_vma) r_size;
01784 mask -= 1;
01785
01786
01787
01788 val = bfd_get_64 (input_bfd,
01789 contents + r_vaddr - input_section->vma);
01790 val &=~ mask << (bfd_vma) r_offset;
01791 val |= (stack[--tos] & mask) << (bfd_vma) r_offset;
01792 bfd_put_64 (input_bfd, val,
01793 contents + r_vaddr - input_section->vma);
01794 }
01795 break;
01796
01797 case ALPHA_R_GPVALUE:
01798
01799 gp = ecoff_data (input_bfd)->gp + r_symndx;
01800 gp_undefined = FALSE;
01801 break;
01802 }
01803
01804 if (relocatep)
01805 {
01806 reloc_howto_type *howto;
01807 struct ecoff_link_hash_entry *h = NULL;
01808 asection *s = NULL;
01809 bfd_vma relocation;
01810 bfd_reloc_status_type r;
01811
01812
01813
01814 howto = &alpha_howto_table[r_type];
01815
01816 if (r_extern)
01817 {
01818 h = sym_hashes[r_symndx];
01819
01820
01821
01822 if (h == (struct ecoff_link_hash_entry *) NULL)
01823 abort ();
01824 }
01825 else
01826 {
01827 if (r_symndx >= NUM_RELOC_SECTIONS)
01828 s = NULL;
01829 else
01830 s = symndx_to_section[r_symndx];
01831
01832 if (s == (asection *) NULL)
01833 abort ();
01834 }
01835
01836 if (info->relocatable)
01837 {
01838
01839
01840 if (r_extern)
01841 {
01842 if (h->root.type != bfd_link_hash_defined
01843 && h->root.type != bfd_link_hash_defweak
01844 && h->indx == -1)
01845 {
01846
01847 if (! ((*info->callbacks->unattached_reloc)
01848 (info, h->root.root.string, input_bfd,
01849 input_section, r_vaddr - input_section->vma)))
01850 return FALSE;
01851 }
01852
01853 relocation = alpha_convert_external_reloc (output_bfd,
01854 info,
01855 input_bfd,
01856 ext_rel,
01857 h);
01858 }
01859 else
01860 {
01861
01862
01863 relocation = (s->output_section->vma
01864 + s->output_offset
01865 - s->vma);
01866 }
01867
01868
01869
01870
01871
01872 if (howto->pc_relative)
01873 relocation -= (input_section->output_section->vma
01874 + input_section->output_offset
01875 - input_section->vma);
01876
01877
01878 relocation += addend;
01879
01880
01881 r = _bfd_relocate_contents (howto, input_bfd, relocation,
01882 (contents
01883 + r_vaddr
01884 - input_section->vma));
01885 }
01886 else
01887 {
01888
01889 if (r_extern)
01890 {
01891
01892 if (h->root.type == bfd_link_hash_defined
01893 || h->root.type == bfd_link_hash_defweak)
01894 {
01895 asection *hsec;
01896
01897 hsec = h->root.u.def.section;
01898 relocation = (h->root.u.def.value
01899 + hsec->output_section->vma
01900 + hsec->output_offset);
01901 }
01902 else
01903 {
01904 if (! ((*info->callbacks->undefined_symbol)
01905 (info, h->root.root.string, input_bfd,
01906 input_section,
01907 r_vaddr - input_section->vma, TRUE)))
01908 return FALSE;
01909 relocation = 0;
01910 }
01911 }
01912 else
01913 {
01914
01915 relocation = (s->output_section->vma
01916 + s->output_offset
01917 - s->vma);
01918
01919
01920
01921 if (howto->pc_relative)
01922 relocation += input_section->vma;
01923 }
01924
01925 r = _bfd_final_link_relocate (howto,
01926 input_bfd,
01927 input_section,
01928 contents,
01929 r_vaddr - input_section->vma,
01930 relocation,
01931 addend);
01932 }
01933
01934 if (r != bfd_reloc_ok)
01935 {
01936 switch (r)
01937 {
01938 default:
01939 case bfd_reloc_outofrange:
01940 abort ();
01941 case bfd_reloc_overflow:
01942 {
01943 const char *name;
01944
01945 if (r_extern)
01946 name = sym_hashes[r_symndx]->root.root.string;
01947 else
01948 name = bfd_section_name (input_bfd,
01949 symndx_to_section[r_symndx]);
01950 if (! ((*info->callbacks->reloc_overflow)
01951 (info, NULL, name,
01952 alpha_howto_table[r_type].name,
01953 (bfd_vma) 0, input_bfd, input_section,
01954 r_vaddr - input_section->vma)))
01955 return FALSE;
01956 }
01957 break;
01958 }
01959 }
01960 }
01961
01962 if (info->relocatable && adjust_addrp)
01963 {
01964
01965 H_PUT_64 (input_bfd,
01966 (input_section->output_section->vma
01967 + input_section->output_offset
01968 - input_section->vma
01969 + r_vaddr),
01970 ext_rel->r_vaddr);
01971 }
01972
01973 if (gp_usedp && gp_undefined)
01974 {
01975 if (! ((*info->callbacks->reloc_dangerous)
01976 (info, _("GP relative relocation used when GP not defined"),
01977 input_bfd, input_section, r_vaddr - input_section->vma)))
01978 return FALSE;
01979
01980 gp = 4;
01981 _bfd_set_gp_value (output_bfd, gp);
01982 gp_undefined = FALSE;
01983 }
01984 }
01985
01986 if (tos != 0)
01987 abort ();
01988
01989 return TRUE;
01990 }
01991
01992
01993
01994
01995 static bfd_boolean
01996 alpha_adjust_headers (abfd, fhdr, ahdr)
01997 bfd *abfd;
01998 struct internal_filehdr *fhdr;
01999 struct internal_aouthdr *ahdr ATTRIBUTE_UNUSED;
02000 {
02001 if ((abfd->flags & (DYNAMIC | EXEC_P)) == (DYNAMIC | EXEC_P))
02002 fhdr->f_flags |= F_ALPHA_CALL_SHARED;
02003 else if ((abfd->flags & DYNAMIC) != 0)
02004 fhdr->f_flags |= F_ALPHA_SHARABLE;
02005 return TRUE;
02006 }
02007
02008
02009
02010
02011
02012
02013 #define alpha_ecoff_slurp_armap _bfd_ecoff_slurp_armap
02014 #define alpha_ecoff_slurp_extended_name_table \
02015 _bfd_ecoff_slurp_extended_name_table
02016 #define alpha_ecoff_construct_extended_name_table \
02017 _bfd_ecoff_construct_extended_name_table
02018 #define alpha_ecoff_truncate_arname _bfd_ecoff_truncate_arname
02019 #define alpha_ecoff_write_armap _bfd_ecoff_write_armap
02020 #define alpha_ecoff_generic_stat_arch_elt _bfd_ecoff_generic_stat_arch_elt
02021 #define alpha_ecoff_update_armap_timestamp _bfd_ecoff_update_armap_timestamp
02022
02023
02024
02025 #define ARFZMAG "Z\012"
02026
02027
02028
02029
02030 static PTR
02031 alpha_ecoff_read_ar_hdr (abfd)
02032 bfd *abfd;
02033 {
02034 struct areltdata *ret;
02035 struct ar_hdr *h;
02036
02037 ret = (struct areltdata *) _bfd_generic_read_ar_hdr_mag (abfd, ARFZMAG);
02038 if (ret == NULL)
02039 return NULL;
02040
02041 h = (struct ar_hdr *) ret->arch_header;
02042 if (strncmp (h->ar_fmag, ARFZMAG, 2) == 0)
02043 {
02044 bfd_byte ab[8];
02045
02046
02047
02048 if (bfd_seek (abfd, (file_ptr) FILHSZ, SEEK_CUR) != 0
02049 || bfd_bread (ab, (bfd_size_type) 8, abfd) != 8
02050 || bfd_seek (abfd, (file_ptr) (- (FILHSZ + 8)), SEEK_CUR) != 0)
02051 return NULL;
02052
02053 ret->parsed_size = H_GET_64 (abfd, ab);
02054 }
02055
02056 return (PTR) ret;
02057 }
02058
02059
02060
02061
02062 static bfd *
02063 alpha_ecoff_get_elt_at_filepos (archive, filepos)
02064 bfd *archive;
02065 file_ptr filepos;
02066 {
02067 bfd *nbfd = NULL;
02068 struct areltdata *tdata;
02069 struct ar_hdr *hdr;
02070 bfd_byte ab[8];
02071 bfd_size_type size;
02072 bfd_byte *buf, *p;
02073 struct bfd_in_memory *bim;
02074
02075 nbfd = _bfd_get_elt_at_filepos (archive, filepos);
02076 if (nbfd == NULL)
02077 goto error_return;
02078
02079 if ((nbfd->flags & BFD_IN_MEMORY) != 0)
02080 {
02081
02082 return nbfd;
02083 }
02084
02085 tdata = (struct areltdata *) nbfd->arelt_data;
02086 hdr = (struct ar_hdr *) tdata->arch_header;
02087 if (strncmp (hdr->ar_fmag, ARFZMAG, 2) != 0)
02088 return nbfd;
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098 if (bfd_seek (nbfd, (file_ptr) FILHSZ, SEEK_SET) != 0)
02099 goto error_return;
02100
02101
02102 if (bfd_bread (ab, (bfd_size_type) 8, nbfd) != 8)
02103 goto error_return;
02104 size = H_GET_64 (nbfd, ab);
02105
02106 if (size == 0)
02107 buf = NULL;
02108 else
02109 {
02110 bfd_size_type left;
02111 bfd_byte dict[4096];
02112 unsigned int h;
02113 bfd_byte b;
02114
02115 buf = (bfd_byte *) bfd_alloc (nbfd, size);
02116 if (buf == NULL)
02117 goto error_return;
02118 p = buf;
02119
02120 left = size;
02121
02122
02123 if (bfd_bread (ab, (bfd_size_type) 8, nbfd) != 8)
02124 goto error_return;
02125
02126
02127
02128
02129
02130
02131
02132 memset (dict, 0, sizeof dict);
02133 h = 0;
02134 while (bfd_bread (&b, (bfd_size_type) 1, nbfd) == 1)
02135 {
02136 unsigned int i;
02137
02138 for (i = 0; i < 8; i++, b >>= 1)
02139 {
02140 bfd_byte n;
02141
02142 if ((b & 1) == 0)
02143 n = dict[h];
02144 else
02145 {
02146 if (! bfd_bread (&n, (bfd_size_type) 1, nbfd))
02147 goto error_return;
02148 dict[h] = n;
02149 }
02150
02151 *p++ = n;
02152
02153 --left;
02154 if (left == 0)
02155 break;
02156
02157 h <<= 4;
02158 h ^= n;
02159 h &= sizeof dict - 1;
02160 }
02161
02162 if (left == 0)
02163 break;
02164 }
02165 }
02166
02167
02168 bim = ((struct bfd_in_memory *)
02169 bfd_alloc (nbfd, (bfd_size_type) sizeof (struct bfd_in_memory)));
02170 if (bim == NULL)
02171 goto error_return;
02172 bim->size = size;
02173 bim->buffer = buf;
02174
02175 nbfd->mtime_set = TRUE;
02176 nbfd->mtime = strtol (hdr->ar_date, (char **) NULL, 10);
02177
02178 nbfd->flags |= BFD_IN_MEMORY;
02179 nbfd->iostream = (PTR) bim;
02180 BFD_ASSERT (! nbfd->cacheable);
02181
02182 return nbfd;
02183
02184 error_return:
02185 if (nbfd != NULL)
02186 bfd_close (nbfd);
02187 return NULL;
02188 }
02189
02190
02191
02192 static bfd *
02193 alpha_ecoff_openr_next_archived_file (archive, last_file)
02194 bfd *archive;
02195 bfd *last_file;
02196 {
02197 file_ptr filestart;
02198
02199 if (last_file == NULL)
02200 filestart = bfd_ardata (archive)->first_file_filepos;
02201 else
02202 {
02203 struct areltdata *t;
02204 struct ar_hdr *h;
02205 bfd_size_type size;
02206
02207
02208
02209 t = (struct areltdata *) last_file->arelt_data;
02210 h = (struct ar_hdr *) t->arch_header;
02211 size = strtol (h->ar_size, (char **) NULL, 10);
02212
02213
02214
02215
02216 filestart = last_file->origin + size;
02217 filestart += filestart % 2;
02218 }
02219
02220 return alpha_ecoff_get_elt_at_filepos (archive, filestart);
02221 }
02222
02223
02224
02225 static bfd *
02226 alpha_ecoff_get_elt_at_index (abfd, index)
02227 bfd *abfd;
02228 symindex index;
02229 {
02230 carsym *entry;
02231
02232 entry = bfd_ardata (abfd)->symdefs + index;
02233 return alpha_ecoff_get_elt_at_filepos (abfd, entry->file_offset);
02234 }
02235
02236
02237
02238
02239 static const struct ecoff_backend_data alpha_ecoff_backend_data =
02240 {
02241
02242 {
02243 (void (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR))) bfd_void,
02244 (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void,
02245 (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void,
02246 (unsigned (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR)))bfd_void,
02247 (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void,
02248 (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void,
02249 (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void,
02250 alpha_ecoff_swap_filehdr_out, alpha_ecoff_swap_aouthdr_out,
02251 alpha_ecoff_swap_scnhdr_out,
02252 FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, TRUE, FALSE, 4, FALSE, 2,
02253 alpha_ecoff_swap_filehdr_in, alpha_ecoff_swap_aouthdr_in,
02254 alpha_ecoff_swap_scnhdr_in, NULL,
02255 alpha_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
02256 alpha_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
02257 _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
02258 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
02259 NULL, NULL, NULL
02260 },
02261
02262 bfd_arch_alpha,
02263
02264 "________64",
02265
02266
02267 0x2000,
02268
02269
02270
02271 TRUE,
02272
02273 64,
02274
02275 &alpha_howto_table[ALPHA_R_REFQUAD],
02276 {
02277
02278 magicSym2,
02279
02280 8,
02281
02282 sizeof (struct hdr_ext),
02283 sizeof (struct dnr_ext),
02284 sizeof (struct pdr_ext),
02285 sizeof (struct sym_ext),
02286 sizeof (struct opt_ext),
02287 sizeof (struct fdr_ext),
02288 sizeof (struct rfd_ext),
02289 sizeof (struct ext_ext),
02290
02291 ecoff_swap_hdr_in,
02292 ecoff_swap_dnr_in,
02293 ecoff_swap_pdr_in,
02294 ecoff_swap_sym_in,
02295 ecoff_swap_opt_in,
02296 ecoff_swap_fdr_in,
02297 ecoff_swap_rfd_in,
02298 ecoff_swap_ext_in,
02299 _bfd_ecoff_swap_tir_in,
02300 _bfd_ecoff_swap_rndx_in,
02301
02302 ecoff_swap_hdr_out,
02303 ecoff_swap_dnr_out,
02304 ecoff_swap_pdr_out,
02305 ecoff_swap_sym_out,
02306 ecoff_swap_opt_out,
02307 ecoff_swap_fdr_out,
02308 ecoff_swap_rfd_out,
02309 ecoff_swap_ext_out,
02310 _bfd_ecoff_swap_tir_out,
02311 _bfd_ecoff_swap_rndx_out,
02312
02313 _bfd_ecoff_slurp_symbolic_info
02314 },
02315
02316 RELSZ,
02317
02318 alpha_ecoff_swap_reloc_in,
02319 alpha_ecoff_swap_reloc_out,
02320
02321 alpha_adjust_reloc_in,
02322 alpha_adjust_reloc_out,
02323
02324 alpha_relocate_section,
02325
02326 alpha_adjust_headers,
02327
02328 alpha_ecoff_get_elt_at_filepos
02329 };
02330
02331
02332 #define _bfd_ecoff_bfd_reloc_type_lookup alpha_bfd_reloc_type_lookup
02333
02334
02335 #define _bfd_ecoff_bfd_get_relocated_section_contents \
02336 alpha_ecoff_get_relocated_section_contents
02337
02338
02339 #define _bfd_ecoff_get_section_contents_in_window \
02340 _bfd_generic_get_section_contents_in_window
02341
02342
02343 #define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section
02344 #define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
02345 #define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
02346 #define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section
02347 #define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group
02348 #define _bfd_ecoff_section_already_linked \
02349 _bfd_generic_section_already_linked
02350
02351 const bfd_target ecoffalpha_little_vec =
02352 {
02353 "ecoff-littlealpha",
02354 bfd_target_ecoff_flavour,
02355 BFD_ENDIAN_LITTLE,
02356 BFD_ENDIAN_LITTLE,
02357
02358 (HAS_RELOC | EXEC_P |
02359 HAS_LINENO | HAS_DEBUG |
02360 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
02361
02362 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
02363 0,
02364 ' ',
02365 15,
02366 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
02367 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
02368 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
02369 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
02370 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
02371 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
02372
02373 {_bfd_dummy_target, alpha_ecoff_object_p,
02374 _bfd_ecoff_archive_p, _bfd_dummy_target},
02375 {bfd_false, _bfd_ecoff_mkobject,
02376 _bfd_generic_mkarchive, bfd_false},
02377 {bfd_false, _bfd_ecoff_write_object_contents,
02378 _bfd_write_archive_contents, bfd_false},
02379
02380 BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
02381 BFD_JUMP_TABLE_COPY (_bfd_ecoff),
02382 BFD_JUMP_TABLE_CORE (_bfd_nocore),
02383 BFD_JUMP_TABLE_ARCHIVE (alpha_ecoff),
02384 BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
02385 BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
02386 BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
02387 BFD_JUMP_TABLE_LINK (_bfd_ecoff),
02388 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
02389
02390 NULL,
02391
02392 (PTR) &alpha_ecoff_backend_data
02393 };