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 #define TARGETNAME "a.out-sunos-big"
00027
00028
00029
00030
00031 #define MY(OP) CONCAT2 (sunos_big_,OP)
00032
00033 #include "bfd.h"
00034 #include "bfdlink.h"
00035 #include "libaout.h"
00036
00037
00038
00039 static bfd_boolean sunos_read_dynamic_info PARAMS ((bfd *));
00040 static long sunos_get_dynamic_symtab_upper_bound PARAMS ((bfd *));
00041 static bfd_boolean sunos_slurp_dynamic_symtab PARAMS ((bfd *));
00042 static long sunos_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **));
00043 static long sunos_get_dynamic_reloc_upper_bound PARAMS ((bfd *));
00044 static long sunos_canonicalize_dynamic_reloc
00045 PARAMS ((bfd *, arelent **, asymbol **));
00046 static struct bfd_hash_entry *sunos_link_hash_newfunc
00047 PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
00048 static struct bfd_link_hash_table *sunos_link_hash_table_create
00049 PARAMS ((bfd *));
00050 static bfd_boolean sunos_create_dynamic_sections
00051 PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean));
00052 static bfd_boolean sunos_add_dynamic_symbols
00053 PARAMS ((bfd *, struct bfd_link_info *, struct external_nlist **,
00054 bfd_size_type *, char **));
00055 static bfd_boolean sunos_add_one_symbol
00056 PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
00057 bfd_vma, const char *, bfd_boolean, bfd_boolean,
00058 struct bfd_link_hash_entry **));
00059 static bfd_boolean sunos_scan_relocs
00060 PARAMS ((struct bfd_link_info *, bfd *, asection *, bfd_size_type));
00061 static bfd_boolean sunos_scan_std_relocs
00062 PARAMS ((struct bfd_link_info *, bfd *, asection *,
00063 const struct reloc_std_external *, bfd_size_type));
00064 static bfd_boolean sunos_scan_ext_relocs
00065 PARAMS ((struct bfd_link_info *, bfd *, asection *,
00066 const struct reloc_ext_external *, bfd_size_type));
00067 static bfd_boolean sunos_link_dynamic_object
00068 PARAMS ((struct bfd_link_info *, bfd *));
00069 static bfd_boolean sunos_write_dynamic_symbol
00070 PARAMS ((bfd *, struct bfd_link_info *, struct aout_link_hash_entry *));
00071 static bfd_boolean sunos_check_dynamic_reloc
00072 PARAMS ((struct bfd_link_info *, bfd *, asection *,
00073 struct aout_link_hash_entry *, PTR, bfd_byte *, bfd_boolean *,
00074 bfd_vma *));
00075 static bfd_boolean sunos_finish_dynamic_link
00076 PARAMS ((bfd *, struct bfd_link_info *));
00077
00078 #define MY_get_dynamic_symtab_upper_bound sunos_get_dynamic_symtab_upper_bound
00079 #define MY_canonicalize_dynamic_symtab sunos_canonicalize_dynamic_symtab
00080 #define MY_get_synthetic_symtab _bfd_nodynamic_get_synthetic_symtab
00081 #define MY_get_dynamic_reloc_upper_bound sunos_get_dynamic_reloc_upper_bound
00082 #define MY_canonicalize_dynamic_reloc sunos_canonicalize_dynamic_reloc
00083 #define MY_bfd_link_hash_table_create sunos_link_hash_table_create
00084 #define MY_add_dynamic_symbols sunos_add_dynamic_symbols
00085 #define MY_add_one_symbol sunos_add_one_symbol
00086 #define MY_link_dynamic_object sunos_link_dynamic_object
00087 #define MY_write_dynamic_symbol sunos_write_dynamic_symbol
00088 #define MY_check_dynamic_reloc sunos_check_dynamic_reloc
00089 #define MY_finish_dynamic_link sunos_finish_dynamic_link
00090
00091
00092 #define MACHTYPE_OK(mtype) \
00093 (((mtype) == M_SPARC && bfd_lookup_arch (bfd_arch_sparc, 0) != NULL) \
00094 || ((mtype) == M_SPARCLET \
00095 && bfd_lookup_arch (bfd_arch_sparc, bfd_mach_sparc_sparclet) != NULL) \
00096 || ((mtype) == M_SPARCLITE_LE \
00097 && bfd_lookup_arch (bfd_arch_sparc, bfd_mach_sparc_sparclet) != NULL) \
00098 || (((mtype) == M_UNKNOWN || (mtype) == M_68010 || (mtype) == M_68020) \
00099 && bfd_lookup_arch (bfd_arch_m68k, 0) != NULL))
00100
00101
00102 #include "aoutf1.h"
00103
00104
00105 #undef valid
00106
00107
00108
00109
00110 struct sunos_dynamic_info
00111 {
00112
00113 bfd_boolean valid;
00114
00115 struct internal_sun4_dynamic_link dyninfo;
00116
00117 unsigned long dynsym_count;
00118
00119 struct external_nlist *dynsym;
00120
00121 aout_symbol_type *canonical_dynsym;
00122
00123 char *dynstr;
00124
00125 unsigned long dynrel_count;
00126
00127
00128 PTR dynrel;
00129
00130 arelent *canonical_dynrel;
00131 };
00132
00133
00134
00135
00136 #define HASH_ENTRY_SIZE (2 * BYTES_IN_WORD)
00137
00138
00139
00140
00141
00142
00143
00144 static bfd_boolean
00145 sunos_read_dynamic_info (abfd)
00146 bfd *abfd;
00147 {
00148 struct sunos_dynamic_info *info;
00149 asection *dynsec;
00150 bfd_vma dynoff;
00151 struct external_sun4_dynamic dyninfo;
00152 unsigned long dynver;
00153 struct external_sun4_dynamic_link linkinfo;
00154 bfd_size_type amt;
00155
00156 if (obj_aout_dynamic_info (abfd) != (PTR) NULL)
00157 return TRUE;
00158
00159 if ((abfd->flags & DYNAMIC) == 0)
00160 {
00161 bfd_set_error (bfd_error_invalid_operation);
00162 return FALSE;
00163 }
00164
00165 amt = sizeof (struct sunos_dynamic_info);
00166 info = (struct sunos_dynamic_info *) bfd_zalloc (abfd, amt);
00167 if (!info)
00168 return FALSE;
00169 info->valid = FALSE;
00170 info->dynsym = NULL;
00171 info->dynstr = NULL;
00172 info->canonical_dynsym = NULL;
00173 info->dynrel = NULL;
00174 info->canonical_dynrel = NULL;
00175 obj_aout_dynamic_info (abfd) = (PTR) info;
00176
00177
00178
00179
00180
00181
00182
00183
00184 if ((abfd->flags & DYNAMIC) == 0)
00185 return TRUE;
00186 if (! bfd_get_section_contents (abfd, obj_datasec (abfd), (PTR) &dyninfo,
00187 (file_ptr) 0,
00188 (bfd_size_type) sizeof dyninfo))
00189 return TRUE;
00190
00191 dynver = GET_WORD (abfd, dyninfo.ld_version);
00192 if (dynver != 2 && dynver != 3)
00193 return TRUE;
00194
00195 dynoff = GET_WORD (abfd, dyninfo.ld);
00196
00197
00198
00199 if (dynoff < bfd_get_section_vma (abfd, obj_datasec (abfd)))
00200 dynsec = obj_textsec (abfd);
00201 else
00202 dynsec = obj_datasec (abfd);
00203 dynoff -= bfd_get_section_vma (abfd, dynsec);
00204 if (dynoff > dynsec->size)
00205 return TRUE;
00206
00207
00208
00209 if (! bfd_get_section_contents (abfd, dynsec, (PTR) &linkinfo,
00210 (file_ptr) dynoff,
00211 (bfd_size_type) sizeof linkinfo))
00212 return TRUE;
00213
00214
00215 info->dyninfo.ld_loaded = GET_WORD (abfd, linkinfo.ld_loaded);
00216 info->dyninfo.ld_need = GET_WORD (abfd, linkinfo.ld_need);
00217 info->dyninfo.ld_rules = GET_WORD (abfd, linkinfo.ld_rules);
00218 info->dyninfo.ld_got = GET_WORD (abfd, linkinfo.ld_got);
00219 info->dyninfo.ld_plt = GET_WORD (abfd, linkinfo.ld_plt);
00220 info->dyninfo.ld_rel = GET_WORD (abfd, linkinfo.ld_rel);
00221 info->dyninfo.ld_hash = GET_WORD (abfd, linkinfo.ld_hash);
00222 info->dyninfo.ld_stab = GET_WORD (abfd, linkinfo.ld_stab);
00223 info->dyninfo.ld_stab_hash = GET_WORD (abfd, linkinfo.ld_stab_hash);
00224 info->dyninfo.ld_buckets = GET_WORD (abfd, linkinfo.ld_buckets);
00225 info->dyninfo.ld_symbols = GET_WORD (abfd, linkinfo.ld_symbols);
00226 info->dyninfo.ld_symb_size = GET_WORD (abfd, linkinfo.ld_symb_size);
00227 info->dyninfo.ld_text = GET_WORD (abfd, linkinfo.ld_text);
00228 info->dyninfo.ld_plt_sz = GET_WORD (abfd, linkinfo.ld_plt_sz);
00229
00230
00231
00232 if (adata (abfd).magic == n_magic)
00233 {
00234 unsigned long exec_bytes_size = adata (abfd).exec_bytes_size;
00235
00236 info->dyninfo.ld_need += exec_bytes_size;
00237 info->dyninfo.ld_rules += exec_bytes_size;
00238 info->dyninfo.ld_rel += exec_bytes_size;
00239 info->dyninfo.ld_hash += exec_bytes_size;
00240 info->dyninfo.ld_stab += exec_bytes_size;
00241 info->dyninfo.ld_symbols += exec_bytes_size;
00242 }
00243
00244
00245
00246 info->dynsym_count = ((info->dyninfo.ld_symbols - info->dyninfo.ld_stab)
00247 / EXTERNAL_NLIST_SIZE);
00248 BFD_ASSERT (info->dynsym_count * EXTERNAL_NLIST_SIZE
00249 == (unsigned long) (info->dyninfo.ld_symbols
00250 - info->dyninfo.ld_stab));
00251
00252
00253 info->dynrel_count = ((info->dyninfo.ld_hash - info->dyninfo.ld_rel)
00254 / obj_reloc_entry_size (abfd));
00255 BFD_ASSERT (info->dynrel_count * obj_reloc_entry_size (abfd)
00256 == (unsigned long) (info->dyninfo.ld_hash
00257 - info->dyninfo.ld_rel));
00258
00259 info->valid = TRUE;
00260
00261 return TRUE;
00262 }
00263
00264
00265
00266 static long
00267 sunos_get_dynamic_symtab_upper_bound (abfd)
00268 bfd *abfd;
00269 {
00270 struct sunos_dynamic_info *info;
00271
00272 if (! sunos_read_dynamic_info (abfd))
00273 return -1;
00274
00275 info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
00276 if (! info->valid)
00277 {
00278 bfd_set_error (bfd_error_no_symbols);
00279 return -1;
00280 }
00281
00282 return (info->dynsym_count + 1) * sizeof (asymbol *);
00283 }
00284
00285
00286
00287 static bfd_boolean
00288 sunos_slurp_dynamic_symtab (abfd)
00289 bfd *abfd;
00290 {
00291 struct sunos_dynamic_info *info;
00292 bfd_size_type amt;
00293
00294
00295 if (obj_aout_dynamic_info (abfd) == NULL)
00296 {
00297 if (! sunos_read_dynamic_info (abfd))
00298 return FALSE;
00299 }
00300
00301 info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
00302 if (! info->valid)
00303 {
00304 bfd_set_error (bfd_error_no_symbols);
00305 return FALSE;
00306 }
00307
00308
00309 if (info->dynsym == (struct external_nlist *) NULL)
00310 {
00311 amt = (bfd_size_type) info->dynsym_count * EXTERNAL_NLIST_SIZE;
00312 info->dynsym = (struct external_nlist *) bfd_alloc (abfd, amt);
00313 if (info->dynsym == NULL && info->dynsym_count != 0)
00314 return FALSE;
00315 if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_stab, SEEK_SET) != 0
00316 || bfd_bread ((PTR) info->dynsym, amt, abfd) != amt)
00317 {
00318 if (info->dynsym != NULL)
00319 {
00320 bfd_release (abfd, info->dynsym);
00321 info->dynsym = NULL;
00322 }
00323 return FALSE;
00324 }
00325 }
00326
00327
00328 if (info->dynstr == (char *) NULL)
00329 {
00330 amt = info->dyninfo.ld_symb_size;
00331 info->dynstr = (char *) bfd_alloc (abfd, amt);
00332 if (info->dynstr == NULL && info->dyninfo.ld_symb_size != 0)
00333 return FALSE;
00334 if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_symbols, SEEK_SET) != 0
00335 || bfd_bread ((PTR) info->dynstr, amt, abfd) != amt)
00336 {
00337 if (info->dynstr != NULL)
00338 {
00339 bfd_release (abfd, info->dynstr);
00340 info->dynstr = NULL;
00341 }
00342 return FALSE;
00343 }
00344 }
00345
00346 return TRUE;
00347 }
00348
00349
00350
00351 static long
00352 sunos_canonicalize_dynamic_symtab (abfd, storage)
00353 bfd *abfd;
00354 asymbol **storage;
00355 {
00356 struct sunos_dynamic_info *info;
00357 unsigned long i;
00358
00359 if (! sunos_slurp_dynamic_symtab (abfd))
00360 return -1;
00361
00362 info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
00363
00364 #ifdef CHECK_DYNAMIC_HASH
00365
00366
00367 {
00368 bfd_size_type table_size;
00369 bfd_byte *table;
00370 bfd_size_type i;
00371
00372 if (info->dyninfo.ld_buckets > info->dynsym_count)
00373 abort ();
00374 table_size = info->dyninfo.ld_stab - info->dyninfo.ld_hash;
00375 table = (bfd_byte *) bfd_malloc (table_size);
00376 if (table == NULL && table_size != 0)
00377 abort ();
00378 if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_hash, SEEK_SET) != 0
00379 || bfd_bread ((PTR) table, table_size, abfd) != table_size)
00380 abort ();
00381 for (i = 0; i < info->dynsym_count; i++)
00382 {
00383 unsigned char *name;
00384 unsigned long hash;
00385
00386 name = ((unsigned char *) info->dynstr
00387 + GET_WORD (abfd, info->dynsym[i].e_strx));
00388 hash = 0;
00389 while (*name != '\0')
00390 hash = (hash << 1) + *name++;
00391 hash &= 0x7fffffff;
00392 hash %= info->dyninfo.ld_buckets;
00393 while (GET_WORD (abfd, table + hash * HASH_ENTRY_SIZE) != i)
00394 {
00395 hash = GET_WORD (abfd,
00396 table + hash * HASH_ENTRY_SIZE + BYTES_IN_WORD);
00397 if (hash == 0 || hash >= table_size / HASH_ENTRY_SIZE)
00398 abort ();
00399 }
00400 }
00401 free (table);
00402 }
00403 #endif
00404
00405
00406
00407 if (info->canonical_dynsym == (aout_symbol_type *) NULL)
00408 {
00409 bfd_size_type size;
00410 bfd_size_type strsize = info->dyninfo.ld_symb_size;
00411
00412 size = (bfd_size_type) info->dynsym_count * sizeof (aout_symbol_type);
00413 info->canonical_dynsym = (aout_symbol_type *) bfd_alloc (abfd, size);
00414 if (info->canonical_dynsym == NULL && info->dynsym_count != 0)
00415 return -1;
00416
00417 if (! aout_32_translate_symbol_table (abfd, info->canonical_dynsym,
00418 info->dynsym,
00419 (bfd_size_type) info->dynsym_count,
00420 info->dynstr, strsize, TRUE))
00421 {
00422 if (info->canonical_dynsym != NULL)
00423 {
00424 bfd_release (abfd, info->canonical_dynsym);
00425 info->canonical_dynsym = NULL;
00426 }
00427 return -1;
00428 }
00429 }
00430
00431
00432 for (i = 0; i < info->dynsym_count; i++)
00433 *storage++ = (asymbol *) (info->canonical_dynsym + i);
00434 *storage = NULL;
00435
00436 return info->dynsym_count;
00437 }
00438
00439
00440
00441 static long
00442 sunos_get_dynamic_reloc_upper_bound (abfd)
00443 bfd *abfd;
00444 {
00445 struct sunos_dynamic_info *info;
00446
00447 if (! sunos_read_dynamic_info (abfd))
00448 return -1;
00449
00450 info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
00451 if (! info->valid)
00452 {
00453 bfd_set_error (bfd_error_no_symbols);
00454 return -1;
00455 }
00456
00457 return (info->dynrel_count + 1) * sizeof (arelent *);
00458 }
00459
00460
00461
00462 static long
00463 sunos_canonicalize_dynamic_reloc (abfd, storage, syms)
00464 bfd *abfd;
00465 arelent **storage;
00466 asymbol **syms;
00467 {
00468 struct sunos_dynamic_info *info;
00469 unsigned long i;
00470 bfd_size_type size;
00471
00472
00473 if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
00474 {
00475 if (! sunos_read_dynamic_info (abfd))
00476 return -1;
00477 }
00478
00479 info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
00480 if (! info->valid)
00481 {
00482 bfd_set_error (bfd_error_no_symbols);
00483 return -1;
00484 }
00485
00486
00487 if (info->dynrel == NULL)
00488 {
00489 size = (bfd_size_type) info->dynrel_count * obj_reloc_entry_size (abfd);
00490 info->dynrel = (PTR) bfd_alloc (abfd, size);
00491 if (info->dynrel == NULL && size != 0)
00492 return -1;
00493 if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_rel, SEEK_SET) != 0
00494 || bfd_bread ((PTR) info->dynrel, size, abfd) != size)
00495 {
00496 if (info->dynrel != NULL)
00497 {
00498 bfd_release (abfd, info->dynrel);
00499 info->dynrel = NULL;
00500 }
00501 return -1;
00502 }
00503 }
00504
00505
00506
00507 if (info->canonical_dynrel == (arelent *) NULL)
00508 {
00509 arelent *to;
00510
00511 size = (bfd_size_type) info->dynrel_count * sizeof (arelent);
00512 info->canonical_dynrel = (arelent *) bfd_alloc (abfd, size);
00513 if (info->canonical_dynrel == NULL && info->dynrel_count != 0)
00514 return -1;
00515
00516 to = info->canonical_dynrel;
00517
00518 if (obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE)
00519 {
00520 register struct reloc_ext_external *p;
00521 struct reloc_ext_external *pend;
00522
00523 p = (struct reloc_ext_external *) info->dynrel;
00524 pend = p + info->dynrel_count;
00525 for (; p < pend; p++, to++)
00526 NAME(aout,swap_ext_reloc_in) (abfd, p, to, syms,
00527 (bfd_size_type) info->dynsym_count);
00528 }
00529 else
00530 {
00531 register struct reloc_std_external *p;
00532 struct reloc_std_external *pend;
00533
00534 p = (struct reloc_std_external *) info->dynrel;
00535 pend = p + info->dynrel_count;
00536 for (; p < pend; p++, to++)
00537 NAME(aout,swap_std_reloc_in) (abfd, p, to, syms,
00538 (bfd_size_type) info->dynsym_count);
00539 }
00540 }
00541
00542
00543 for (i = 0; i < info->dynrel_count; i++)
00544 *storage++ = info->canonical_dynrel + i;
00545 *storage = NULL;
00546
00547 return info->dynrel_count;
00548 }
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 #define SPARC_PLT_ENTRY_SIZE (12)
00559
00560 static const bfd_byte sparc_plt_first_entry[SPARC_PLT_ENTRY_SIZE] =
00561 {
00562
00563 0x3, 0, 0, 0,
00564
00565 0x81, 0xc0, 0x60, 0,
00566
00567 0x1, 0, 0, 0
00568 };
00569
00570
00571 #define SPARC_PLT_ENTRY_WORD0 ((bfd_vma) 0x9de3bfa0)
00572
00573 #define SPARC_PLT_ENTRY_WORD1 ((bfd_vma) 0x40000000)
00574
00575 #define SPARC_PLT_ENTRY_WORD2 ((bfd_vma) 0x01000000)
00576
00577
00578
00579
00580
00581 #define SPARC_PLT_PIC_WORD0 ((bfd_vma) 0x03000000)
00582
00583 #define SPARC_PLT_PIC_WORD1 ((bfd_vma) 0x81c06000)
00584
00585 #define SPARC_PLT_PIC_WORD2 ((bfd_vma) 0x01000000)
00586
00587
00588
00589
00590
00591
00592 #define M68K_PLT_ENTRY_SIZE (8)
00593
00594 static const bfd_byte m68k_plt_first_entry[M68K_PLT_ENTRY_SIZE] =
00595 {
00596
00597 0x4e, 0xf9,
00598
00599 0, 0, 0, 0,
00600
00601 0, 0
00602 };
00603
00604
00605 #define M68K_PLT_ENTRY_WORD0 ((bfd_vma) 0x61ff)
00606
00607
00608
00609
00610 struct sunos_link_hash_entry
00611 {
00612 struct aout_link_hash_entry root;
00613
00614
00615
00616
00617
00618
00619
00620 long dynindx;
00621
00622
00623
00624 long dynstr_index;
00625
00626
00627
00628 bfd_vma got_offset;
00629
00630
00631
00632 bfd_vma plt_offset;
00633
00634
00635 unsigned char flags;
00636
00637 #define SUNOS_REF_REGULAR 01
00638
00639 #define SUNOS_DEF_REGULAR 02
00640
00641 #define SUNOS_REF_DYNAMIC 04
00642
00643 #define SUNOS_DEF_DYNAMIC 010
00644
00645 #define SUNOS_CONSTRUCTOR 020
00646 };
00647
00648
00649
00650 struct sunos_link_hash_table
00651 {
00652 struct aout_link_hash_table root;
00653
00654
00655 bfd *dynobj;
00656
00657
00658 bfd_boolean dynamic_sections_created;
00659
00660
00661 bfd_boolean dynamic_sections_needed;
00662
00663
00664 bfd_boolean got_needed;
00665
00666
00667 size_t dynsymcount;
00668
00669
00670 size_t bucketcount;
00671
00672
00673
00674 struct bfd_link_needed_list *needed;
00675
00676
00677 bfd_vma got_base;
00678 };
00679
00680
00681
00682 static struct bfd_hash_entry *
00683 sunos_link_hash_newfunc (entry, table, string)
00684 struct bfd_hash_entry *entry;
00685 struct bfd_hash_table *table;
00686 const char *string;
00687 {
00688 struct sunos_link_hash_entry *ret = (struct sunos_link_hash_entry *) entry;
00689
00690
00691
00692 if (ret == (struct sunos_link_hash_entry *) NULL)
00693 ret = ((struct sunos_link_hash_entry *)
00694 bfd_hash_allocate (table, sizeof (struct sunos_link_hash_entry)));
00695 if (ret == (struct sunos_link_hash_entry *) NULL)
00696 return (struct bfd_hash_entry *) ret;
00697
00698
00699 ret = ((struct sunos_link_hash_entry *)
00700 NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret,
00701 table, string));
00702 if (ret != NULL)
00703 {
00704
00705 ret->dynindx = -1;
00706 ret->dynstr_index = -1;
00707 ret->got_offset = 0;
00708 ret->plt_offset = 0;
00709 ret->flags = 0;
00710 }
00711
00712 return (struct bfd_hash_entry *) ret;
00713 }
00714
00715
00716
00717 static struct bfd_link_hash_table *
00718 sunos_link_hash_table_create (abfd)
00719 bfd *abfd;
00720 {
00721 struct sunos_link_hash_table *ret;
00722 bfd_size_type amt = sizeof (struct sunos_link_hash_table);
00723
00724 ret = (struct sunos_link_hash_table *) bfd_malloc (amt);
00725 if (ret == (struct sunos_link_hash_table *) NULL)
00726 return (struct bfd_link_hash_table *) NULL;
00727 if (! NAME(aout,link_hash_table_init) (&ret->root, abfd,
00728 sunos_link_hash_newfunc))
00729 {
00730 free (ret);
00731 return (struct bfd_link_hash_table *) NULL;
00732 }
00733
00734 ret->dynobj = NULL;
00735 ret->dynamic_sections_created = FALSE;
00736 ret->dynamic_sections_needed = FALSE;
00737 ret->got_needed = FALSE;
00738 ret->dynsymcount = 0;
00739 ret->bucketcount = 0;
00740 ret->needed = NULL;
00741 ret->got_base = 0;
00742
00743 return &ret->root.root;
00744 }
00745
00746
00747
00748 #define sunos_link_hash_lookup(table, string, create, copy, follow) \
00749 ((struct sunos_link_hash_entry *) \
00750 aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\
00751 (follow)))
00752
00753
00754
00755 #define sunos_link_hash_traverse(table, func, info) \
00756 (aout_link_hash_traverse \
00757 (&(table)->root, \
00758 (bfd_boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \
00759 (info)))
00760
00761
00762
00763
00764 #define sunos_hash_table(p) ((struct sunos_link_hash_table *) ((p)->hash))
00765
00766 static bfd_boolean sunos_scan_dynamic_symbol
00767 PARAMS ((struct sunos_link_hash_entry *, PTR));
00768
00769
00770
00771
00772
00773
00774
00775
00776 static bfd_boolean
00777 sunos_create_dynamic_sections (abfd, info, needed)
00778 bfd *abfd;
00779 struct bfd_link_info *info;
00780 bfd_boolean needed;
00781 {
00782 asection *s;
00783
00784 if (! sunos_hash_table (info)->dynamic_sections_created)
00785 {
00786 flagword flags;
00787
00788 sunos_hash_table (info)->dynobj = abfd;
00789
00790 flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
00791 | SEC_LINKER_CREATED);
00792
00793
00794
00795
00796 s = bfd_make_section (abfd, ".dynamic");
00797 if (s == NULL
00798 || ! bfd_set_section_flags (abfd, s, flags)
00799 || ! bfd_set_section_alignment (abfd, s, 2))
00800 return FALSE;
00801
00802
00803
00804 s = bfd_make_section (abfd, ".got");
00805 if (s == NULL
00806 || ! bfd_set_section_flags (abfd, s, flags)
00807 || ! bfd_set_section_alignment (abfd, s, 2))
00808 return FALSE;
00809
00810
00811
00812 s = bfd_make_section (abfd, ".plt");
00813 if (s == NULL
00814 || ! bfd_set_section_flags (abfd, s, flags | SEC_CODE)
00815 || ! bfd_set_section_alignment (abfd, s, 2))
00816 return FALSE;
00817
00818
00819
00820 s = bfd_make_section (abfd, ".dynrel");
00821 if (s == NULL
00822 || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
00823 || ! bfd_set_section_alignment (abfd, s, 2))
00824 return FALSE;
00825
00826
00827
00828 s = bfd_make_section (abfd, ".hash");
00829 if (s == NULL
00830 || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
00831 || ! bfd_set_section_alignment (abfd, s, 2))
00832 return FALSE;
00833
00834
00835
00836 s = bfd_make_section (abfd, ".dynsym");
00837 if (s == NULL
00838 || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
00839 || ! bfd_set_section_alignment (abfd, s, 2))
00840 return FALSE;
00841
00842
00843
00844 s = bfd_make_section (abfd, ".dynstr");
00845 if (s == NULL
00846 || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
00847 || ! bfd_set_section_alignment (abfd, s, 2))
00848 return FALSE;
00849
00850 sunos_hash_table (info)->dynamic_sections_created = TRUE;
00851 }
00852
00853 if ((needed && ! sunos_hash_table (info)->dynamic_sections_needed)
00854 || info->shared)
00855 {
00856 bfd *dynobj;
00857
00858 dynobj = sunos_hash_table (info)->dynobj;
00859
00860 s = bfd_get_section_by_name (dynobj, ".got");
00861 if (s->size == 0)
00862 s->size = BYTES_IN_WORD;
00863
00864 sunos_hash_table (info)->dynamic_sections_needed = TRUE;
00865 sunos_hash_table (info)->got_needed = TRUE;
00866 }
00867
00868 return TRUE;
00869 }
00870
00871
00872
00873
00874 static bfd_boolean
00875 sunos_add_dynamic_symbols (abfd, info, symsp, sym_countp, stringsp)
00876 bfd *abfd;
00877 struct bfd_link_info *info;
00878 struct external_nlist **symsp;
00879 bfd_size_type *sym_countp;
00880 char **stringsp;
00881 {
00882 bfd *dynobj;
00883 struct sunos_dynamic_info *dinfo;
00884 unsigned long need;
00885 asection **ps;
00886
00887
00888 if (info->hash->creator == abfd->xvec)
00889 {
00890 if (! sunos_create_dynamic_sections (abfd, info,
00891 ((abfd->flags & DYNAMIC) != 0
00892 && !info->relocatable)))
00893 return FALSE;
00894 }
00895
00896
00897 if ((abfd->flags & DYNAMIC) == 0)
00898 return TRUE;
00899
00900 dynobj = sunos_hash_table (info)->dynobj;
00901
00902
00903
00904
00905
00906
00907
00908
00909 for (ps = &abfd->sections; *ps != NULL; )
00910 {
00911 if (abfd != dynobj || ((*ps)->flags & SEC_LINKER_CREATED) == 0)
00912 bfd_section_list_remove (abfd, ps);
00913 else
00914 ps = &(*ps)->next;
00915 }
00916
00917
00918
00919 if (info->relocatable)
00920 return TRUE;
00921
00922
00923
00924 if (info->hash->creator != abfd->xvec)
00925 {
00926 bfd_set_error (bfd_error_invalid_operation);
00927 return FALSE;
00928 }
00929
00930
00931
00932
00933 if (bfd_get_section_by_name (dynobj, ".need") == NULL)
00934 {
00935
00936
00937
00938 asection *s = bfd_make_section (dynobj, ".need");
00939 if (s == NULL
00940 || ! bfd_set_section_flags (dynobj, s,
00941 (SEC_ALLOC
00942 | SEC_LOAD
00943 | SEC_HAS_CONTENTS
00944 | SEC_IN_MEMORY
00945 | SEC_READONLY))
00946 || ! bfd_set_section_alignment (dynobj, s, 2))
00947 return FALSE;
00948 }
00949
00950 if (bfd_get_section_by_name (dynobj, ".rules") == NULL)
00951 {
00952
00953
00954
00955 asection *s = bfd_make_section (dynobj, ".rules");
00956 if (s == NULL
00957 || ! bfd_set_section_flags (dynobj, s,
00958 (SEC_ALLOC
00959 | SEC_LOAD
00960 | SEC_HAS_CONTENTS
00961 | SEC_IN_MEMORY
00962 | SEC_READONLY))
00963 || ! bfd_set_section_alignment (dynobj, s, 2))
00964 return FALSE;
00965 }
00966
00967
00968 if (! sunos_slurp_dynamic_symtab (abfd))
00969 return FALSE;
00970
00971 dinfo = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
00972 *symsp = dinfo->dynsym;
00973 *sym_countp = dinfo->dynsym_count;
00974 *stringsp = dinfo->dynstr;
00975
00976
00977 need = dinfo->dyninfo.ld_need;
00978 while (need != 0)
00979 {
00980 bfd_byte buf[16];
00981 unsigned long name, flags;
00982 unsigned short major_vno, minor_vno;
00983 struct bfd_link_needed_list *needed, **pp;
00984 char *namebuf, *p;
00985 bfd_size_type alc;
00986 bfd_byte b;
00987 char *namecopy;
00988
00989 if (bfd_seek (abfd, (file_ptr) need, SEEK_SET) != 0
00990 || bfd_bread (buf, (bfd_size_type) 16, abfd) != 16)
00991 return FALSE;
00992
00993
00994
00995
00996 name = bfd_get_32 (abfd, buf);
00997 flags = bfd_get_32 (abfd, buf + 4);
00998 major_vno = (unsigned short) bfd_get_16 (abfd, buf + 8);
00999 minor_vno = (unsigned short) bfd_get_16 (abfd, buf + 10);
01000 need = bfd_get_32 (abfd, buf + 12);
01001
01002 alc = sizeof (struct bfd_link_needed_list);
01003 needed = (struct bfd_link_needed_list *) bfd_alloc (abfd, alc);
01004 if (needed == NULL)
01005 return FALSE;
01006 needed->by = abfd;
01007
01008
01009 alc = 30;
01010 namebuf = (char *) bfd_malloc (alc + 1);
01011 if (namebuf == NULL)
01012 return FALSE;
01013 p = namebuf;
01014
01015 if ((flags & 0x80000000) != 0)
01016 {
01017 *p++ = '-';
01018 *p++ = 'l';
01019 }
01020 if (bfd_seek (abfd, (file_ptr) name, SEEK_SET) != 0)
01021 {
01022 free (namebuf);
01023 return FALSE;
01024 }
01025
01026 do
01027 {
01028 if (bfd_bread (&b, (bfd_size_type) 1, abfd) != 1)
01029 {
01030 free (namebuf);
01031 return FALSE;
01032 }
01033
01034 if ((bfd_size_type) (p - namebuf) >= alc)
01035 {
01036 char *n;
01037
01038 alc *= 2;
01039 n = (char *) bfd_realloc (namebuf, alc + 1);
01040 if (n == NULL)
01041 {
01042 free (namebuf);
01043 return FALSE;
01044 }
01045 p = n + (p - namebuf);
01046 namebuf = n;
01047 }
01048
01049 *p++ = b;
01050 }
01051 while (b != '\0');
01052
01053 if (major_vno == 0)
01054 *p = '\0';
01055 else
01056 {
01057 char majbuf[30];
01058 char minbuf[30];
01059
01060 sprintf (majbuf, ".%d", major_vno);
01061 if (minor_vno == 0)
01062 minbuf[0] = '\0';
01063 else
01064 sprintf (minbuf, ".%d", minor_vno);
01065
01066 if ((p - namebuf) + strlen (majbuf) + strlen (minbuf) >= alc)
01067 {
01068 char *n;
01069
01070 alc = (p - namebuf) + strlen (majbuf) + strlen (minbuf);
01071 n = (char *) bfd_realloc (namebuf, alc + 1);
01072 if (n == NULL)
01073 {
01074 free (namebuf);
01075 return FALSE;
01076 }
01077 p = n + (p - namebuf);
01078 namebuf = n;
01079 }
01080
01081 strcpy (p, majbuf);
01082 strcat (p, minbuf);
01083 }
01084
01085 namecopy = bfd_alloc (abfd, (bfd_size_type) strlen (namebuf) + 1);
01086 if (namecopy == NULL)
01087 {
01088 free (namebuf);
01089 return FALSE;
01090 }
01091 strcpy (namecopy, namebuf);
01092 free (namebuf);
01093 needed->name = namecopy;
01094
01095 needed->next = NULL;
01096
01097 for (pp = &sunos_hash_table (info)->needed;
01098 *pp != NULL;
01099 pp = &(*pp)->next)
01100 ;
01101 *pp = needed;
01102 }
01103
01104 return TRUE;
01105 }
01106
01107
01108
01109
01110
01111 static bfd_boolean
01112 sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
01113 copy, collect, hashp)
01114 struct bfd_link_info *info;
01115 bfd *abfd;
01116 const char *name;
01117 flagword flags;
01118 asection *section;
01119 bfd_vma value;
01120 const char *string;
01121 bfd_boolean copy;
01122 bfd_boolean collect;
01123 struct bfd_link_hash_entry **hashp;
01124 {
01125 struct sunos_link_hash_entry *h;
01126 int new_flag;
01127
01128 if ((flags & (BSF_INDIRECT | BSF_WARNING | BSF_CONSTRUCTOR)) != 0
01129 || ! bfd_is_und_section (section))
01130 h = sunos_link_hash_lookup (sunos_hash_table (info), name, TRUE, copy,
01131 FALSE);
01132 else
01133 h = ((struct sunos_link_hash_entry *)
01134 bfd_wrapped_link_hash_lookup (abfd, info, name, TRUE, copy, FALSE));
01135 if (h == NULL)
01136 return FALSE;
01137
01138 if (hashp != NULL)
01139 *hashp = (struct bfd_link_hash_entry *) h;
01140
01141
01142
01143
01144 if ((abfd->flags & DYNAMIC) != 0
01145 && bfd_is_com_section (section))
01146 section = obj_bsssec (abfd);
01147
01148 if (! bfd_is_und_section (section)
01149 && h->root.root.type != bfd_link_hash_new
01150 && h->root.root.type != bfd_link_hash_undefined
01151 && h->root.root.type != bfd_link_hash_defweak)
01152 {
01153
01154
01155 if ((abfd->flags & DYNAMIC) != 0)
01156 {
01157
01158
01159
01160
01161 section = bfd_und_section_ptr;
01162 }
01163 else if (h->root.root.type == bfd_link_hash_defined
01164 && h->root.root.u.def.section->owner != NULL
01165 && (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
01166 {
01167
01168
01169
01170 h->root.root.type = bfd_link_hash_undefined;
01171 h->root.root.u.undef.abfd = h->root.root.u.def.section->owner;
01172 }
01173 else if (h->root.root.type == bfd_link_hash_common
01174 && (h->root.root.u.c.p->section->owner->flags & DYNAMIC) != 0)
01175 {
01176
01177
01178
01179
01180 h->root.root.type = bfd_link_hash_undefined;
01181 h->root.root.u.undef.abfd = h->root.root.u.c.p->section->owner;
01182 }
01183 }
01184
01185 if ((abfd->flags & DYNAMIC) != 0
01186 && abfd->xvec == info->hash->creator
01187 && (h->flags & SUNOS_CONSTRUCTOR) != 0)
01188 {
01189
01190
01191
01192
01193
01194 section = bfd_und_section_ptr;
01195 }
01196 else if ((flags & BSF_CONSTRUCTOR) != 0
01197 && (abfd->flags & DYNAMIC) == 0
01198 && h->root.root.type == bfd_link_hash_defined
01199 && h->root.root.u.def.section->owner != NULL
01200 && (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
01201 {
01202
01203
01204
01205 h->root.root.type = bfd_link_hash_new;
01206 }
01207
01208
01209 if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
01210 value, string, copy, collect,
01211 hashp))
01212 return FALSE;
01213
01214 if (abfd->xvec == info->hash->creator)
01215 {
01216
01217
01218
01219
01220
01221 if ((abfd->flags & DYNAMIC) == 0)
01222 {
01223 if (bfd_is_und_section (section))
01224 new_flag = SUNOS_REF_REGULAR;
01225 else
01226 new_flag = SUNOS_DEF_REGULAR;
01227 }
01228 else
01229 {
01230 if (bfd_is_und_section (section))
01231 new_flag = SUNOS_REF_DYNAMIC;
01232 else
01233 new_flag = SUNOS_DEF_DYNAMIC;
01234 }
01235 h->flags |= new_flag;
01236
01237 if (h->dynindx == -1
01238 && (h->flags & (SUNOS_DEF_REGULAR | SUNOS_REF_REGULAR)) != 0)
01239 {
01240 ++sunos_hash_table (info)->dynsymcount;
01241 h->dynindx = -2;
01242 }
01243
01244 if ((flags & BSF_CONSTRUCTOR) != 0
01245 && (abfd->flags & DYNAMIC) == 0)
01246 h->flags |= SUNOS_CONSTRUCTOR;
01247 }
01248
01249 return TRUE;
01250 }
01251
01252
01253
01254 struct bfd_link_needed_list *
01255 bfd_sunos_get_needed_list (abfd, info)
01256 bfd *abfd ATTRIBUTE_UNUSED;
01257 struct bfd_link_info *info;
01258 {
01259 if (info->hash->creator != &MY(vec))
01260 return NULL;
01261 return sunos_hash_table (info)->needed;
01262 }
01263
01264
01265
01266
01267 bfd_boolean
01268 bfd_sunos_record_link_assignment (output_bfd, info, name)
01269 bfd *output_bfd;
01270 struct bfd_link_info *info;
01271 const char *name;
01272 {
01273 struct sunos_link_hash_entry *h;
01274
01275 if (output_bfd->xvec != &MY(vec))
01276 return TRUE;
01277
01278
01279
01280
01281 h = sunos_link_hash_lookup (sunos_hash_table (info), name,
01282 FALSE, FALSE, FALSE);
01283 if (h == NULL)
01284 return TRUE;
01285
01286
01287
01288 if (! info->shared || strcmp (name, "__DYNAMIC") != 0)
01289 {
01290 h->flags |= SUNOS_DEF_REGULAR;
01291
01292 if (h->dynindx == -1)
01293 {
01294 ++sunos_hash_table (info)->dynsymcount;
01295 h->dynindx = -2;
01296 }
01297 }
01298
01299 return TRUE;
01300 }
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311 bfd_boolean
01312 bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
01313 srulesptr)
01314 bfd *output_bfd;
01315 struct bfd_link_info *info;
01316 asection **sdynptr;
01317 asection **sneedptr;
01318 asection **srulesptr;
01319 {
01320 bfd *dynobj;
01321 bfd_size_type dynsymcount;
01322 struct sunos_link_hash_entry *h;
01323 asection *s;
01324 size_t bucketcount;
01325 bfd_size_type hashalloc;
01326 size_t i;
01327 bfd *sub;
01328
01329 *sdynptr = NULL;
01330 *sneedptr = NULL;
01331 *srulesptr = NULL;
01332
01333 if (info->relocatable)
01334 return TRUE;
01335
01336 if (output_bfd->xvec != &MY(vec))
01337 return TRUE;
01338
01339
01340
01341
01342
01343
01344 for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
01345 {
01346 if ((sub->flags & DYNAMIC) == 0
01347 && sub->xvec == output_bfd->xvec)
01348 {
01349 if (! sunos_scan_relocs (info, sub, obj_textsec (sub),
01350 exec_hdr (sub)->a_trsize)
01351 || ! sunos_scan_relocs (info, sub, obj_datasec (sub),
01352 exec_hdr (sub)->a_drsize))
01353 return FALSE;
01354 }
01355 }
01356
01357 dynobj = sunos_hash_table (info)->dynobj;
01358 dynsymcount = sunos_hash_table (info)->dynsymcount;
01359
01360
01361
01362 if (! sunos_hash_table (info)->dynamic_sections_needed
01363 && ! sunos_hash_table (info)->got_needed)
01364 return TRUE;
01365
01366
01367 h = sunos_link_hash_lookup (sunos_hash_table (info),
01368 "__GLOBAL_OFFSET_TABLE_", FALSE, FALSE, FALSE);
01369 if (h != NULL && (h->flags & SUNOS_REF_REGULAR) != 0)
01370 {
01371 h->flags |= SUNOS_DEF_REGULAR;
01372 if (h->dynindx == -1)
01373 {
01374 ++sunos_hash_table (info)->dynsymcount;
01375 h->dynindx = -2;
01376 }
01377 h->root.root.type = bfd_link_hash_defined;
01378 h->root.root.u.def.section = bfd_get_section_by_name (dynobj, ".got");
01379
01380
01381
01382
01383 s = bfd_get_section_by_name (dynobj, ".got");
01384 BFD_ASSERT (s != NULL);
01385 if (s->size >= 0x1000)
01386 h->root.root.u.def.value = 0x1000;
01387 else
01388 h->root.root.u.def.value = 0;
01389
01390 sunos_hash_table (info)->got_base = h->root.root.u.def.value;
01391 }
01392
01393
01394
01395 if (sunos_hash_table (info)->dynamic_sections_needed)
01396 {
01397 *sdynptr = bfd_get_section_by_name (dynobj, ".dynamic");
01398
01399
01400 s = *sdynptr;
01401 BFD_ASSERT (s != NULL);
01402 s->size = (sizeof (struct external_sun4_dynamic)
01403 + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE
01404 + sizeof (struct external_sun4_dynamic_link));
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414 s = bfd_get_section_by_name (dynobj, ".dynsym");
01415 BFD_ASSERT (s != NULL);
01416 s->size = dynsymcount * sizeof (struct external_nlist);
01417 s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->size);
01418 if (s->contents == NULL && s->size != 0)
01419 return FALSE;
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429 if (dynsymcount >= 4)
01430 bucketcount = dynsymcount / 4;
01431 else if (dynsymcount > 0)
01432 bucketcount = dynsymcount;
01433 else
01434 bucketcount = 1;
01435 s = bfd_get_section_by_name (dynobj, ".hash");
01436 BFD_ASSERT (s != NULL);
01437 hashalloc = (dynsymcount + bucketcount - 1) * HASH_ENTRY_SIZE;
01438 s->contents = (bfd_byte *) bfd_zalloc (dynobj, hashalloc);
01439 if (s->contents == NULL && dynsymcount > 0)
01440 return FALSE;
01441 for (i = 0; i < bucketcount; i++)
01442 PUT_WORD (output_bfd, (bfd_vma) -1, s->contents + i * HASH_ENTRY_SIZE);
01443 s->size = bucketcount * HASH_ENTRY_SIZE;
01444
01445 sunos_hash_table (info)->bucketcount = bucketcount;
01446
01447
01448
01449
01450 sunos_hash_table (info)->dynsymcount = 0;
01451 sunos_link_hash_traverse (sunos_hash_table (info),
01452 sunos_scan_dynamic_symbol,
01453 (PTR) info);
01454 BFD_ASSERT (sunos_hash_table (info)->dynsymcount == dynsymcount);
01455
01456
01457
01458
01459 s = bfd_get_section_by_name (dynobj, ".dynstr");
01460 BFD_ASSERT (s != NULL);
01461 if ((s->size & 7) != 0)
01462 {
01463 bfd_size_type add;
01464 bfd_byte *contents;
01465
01466 add = 8 - (s->size & 7);
01467 contents = (bfd_byte *) bfd_realloc (s->contents,
01468 s->size + add);
01469 if (contents == NULL)
01470 return FALSE;
01471 memset (contents + s->size, 0, (size_t) add);
01472 s->contents = contents;
01473 s->size += add;
01474 }
01475 }
01476
01477
01478
01479 s = bfd_get_section_by_name (dynobj, ".plt");
01480 BFD_ASSERT (s != NULL);
01481 if (s->size != 0)
01482 {
01483 s->contents = (bfd_byte *) bfd_alloc (dynobj, s->size);
01484 if (s->contents == NULL)
01485 return FALSE;
01486
01487
01488 switch (bfd_get_arch (dynobj))
01489 {
01490 case bfd_arch_sparc:
01491 memcpy (s->contents, sparc_plt_first_entry, SPARC_PLT_ENTRY_SIZE);
01492 break;
01493
01494 case bfd_arch_m68k:
01495 memcpy (s->contents, m68k_plt_first_entry, M68K_PLT_ENTRY_SIZE);
01496 break;
01497
01498 default:
01499 abort ();
01500 }
01501 }
01502
01503 s = bfd_get_section_by_name (dynobj, ".dynrel");
01504 if (s->size != 0)
01505 {
01506 s->contents = (bfd_byte *) bfd_alloc (dynobj, s->size);
01507 if (s->contents == NULL)
01508 return FALSE;
01509 }
01510
01511
01512 s->reloc_count = 0;
01513
01514
01515 s = bfd_get_section_by_name (dynobj, ".got");
01516 s->contents = (bfd_byte *) bfd_alloc (dynobj, s->size);
01517 if (s->contents == NULL)
01518 return FALSE;
01519
01520 *sneedptr = bfd_get_section_by_name (dynobj, ".need");
01521 *srulesptr = bfd_get_section_by_name (dynobj, ".rules");
01522
01523 return TRUE;
01524 }
01525
01526
01527
01528 static bfd_boolean
01529 sunos_scan_relocs (info, abfd, sec, rel_size)
01530 struct bfd_link_info *info;
01531 bfd *abfd;
01532 asection *sec;
01533 bfd_size_type rel_size;
01534 {
01535 PTR relocs;
01536 PTR free_relocs = NULL;
01537
01538 if (rel_size == 0)
01539 return TRUE;
01540
01541 if (! info->keep_memory)
01542 relocs = free_relocs = bfd_malloc (rel_size);
01543 else
01544 {
01545 struct aout_section_data_struct *n;
01546 bfd_size_type amt = sizeof (struct aout_section_data_struct);
01547
01548 n = (struct aout_section_data_struct *) bfd_alloc (abfd, amt);
01549 if (n == NULL)
01550 relocs = NULL;
01551 else
01552 {
01553 set_aout_section_data (sec, n);
01554 relocs = bfd_malloc (rel_size);
01555 aout_section_data (sec)->relocs = relocs;
01556 }
01557 }
01558 if (relocs == NULL)
01559 return FALSE;
01560
01561 if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
01562 || bfd_bread (relocs, rel_size, abfd) != rel_size)
01563 goto error_return;
01564
01565 if (obj_reloc_entry_size (abfd) == RELOC_STD_SIZE)
01566 {
01567 if (! sunos_scan_std_relocs (info, abfd, sec,
01568 (struct reloc_std_external *) relocs,
01569 rel_size))
01570 goto error_return;
01571 }
01572 else
01573 {
01574 if (! sunos_scan_ext_relocs (info, abfd, sec,
01575 (struct reloc_ext_external *) relocs,
01576 rel_size))
01577 goto error_return;
01578 }
01579
01580 if (free_relocs != NULL)
01581 free (free_relocs);
01582
01583 return TRUE;
01584
01585 error_return:
01586 if (free_relocs != NULL)
01587 free (free_relocs);
01588 return FALSE;
01589 }
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601 static bfd_boolean
01602 sunos_scan_std_relocs (info, abfd, sec, relocs, rel_size)
01603 struct bfd_link_info *info;
01604 bfd *abfd;
01605 asection *sec ATTRIBUTE_UNUSED;
01606 const struct reloc_std_external *relocs;
01607 bfd_size_type rel_size;
01608 {
01609 bfd *dynobj;
01610 asection *splt = NULL;
01611 asection *srel = NULL;
01612 struct sunos_link_hash_entry **sym_hashes;
01613 const struct reloc_std_external *rel, *relend;
01614
01615
01616 if (bfd_get_arch (abfd) != bfd_arch_m68k)
01617 {
01618 bfd_set_error (bfd_error_invalid_target);
01619 return FALSE;
01620 }
01621
01622 dynobj = NULL;
01623
01624 sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd);
01625
01626 relend = relocs + rel_size / RELOC_STD_SIZE;
01627 for (rel = relocs; rel < relend; rel++)
01628 {
01629 int r_index;
01630 struct sunos_link_hash_entry *h;
01631
01632
01633 if (bfd_header_big_endian (abfd))
01634 {
01635 if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG) == 0)
01636 continue;
01637 }
01638 else
01639 {
01640 if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE) == 0)
01641 continue;
01642 }
01643
01644
01645 if (bfd_header_big_endian (abfd))
01646 r_index = ((rel->r_index[0] << 16)
01647 | (rel->r_index[1] << 8)
01648 | rel->r_index[2]);
01649 else
01650 r_index = ((rel->r_index[2] << 16)
01651 | (rel->r_index[1] << 8)
01652 | rel->r_index[0]);
01653
01654
01655 h = sym_hashes[r_index];
01656 if (h == NULL)
01657 {
01658
01659
01660 continue;
01661 }
01662
01663
01664
01665
01666
01667
01668 if (h->root.root.type != bfd_link_hash_defined
01669 && h->root.root.type != bfd_link_hash_defweak
01670 && h->root.root.type != bfd_link_hash_undefined)
01671 continue;
01672
01673 if ((h->flags & SUNOS_DEF_DYNAMIC) == 0
01674 || (h->flags & SUNOS_DEF_REGULAR) != 0)
01675 continue;
01676
01677 if (dynobj == NULL)
01678 {
01679 asection *sgot;
01680
01681 if (! sunos_create_dynamic_sections (abfd, info, FALSE))
01682 return FALSE;
01683 dynobj = sunos_hash_table (info)->dynobj;
01684 splt = bfd_get_section_by_name (dynobj, ".plt");
01685 srel = bfd_get_section_by_name (dynobj, ".dynrel");
01686 BFD_ASSERT (splt != NULL && srel != NULL);
01687
01688 sgot = bfd_get_section_by_name (dynobj, ".got");
01689 BFD_ASSERT (sgot != NULL);
01690 if (sgot->size == 0)
01691 sgot->size = BYTES_IN_WORD;
01692 sunos_hash_table (info)->got_needed = TRUE;
01693 }
01694
01695 BFD_ASSERT ((h->flags & SUNOS_REF_REGULAR) != 0);
01696 BFD_ASSERT (h->plt_offset != 0
01697 || ((h->root.root.type == bfd_link_hash_defined
01698 || h->root.root.type == bfd_link_hash_defweak)
01699 ? (h->root.root.u.def.section->owner->flags
01700 & DYNAMIC) != 0
01701 : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0));
01702
01703
01704
01705
01706 if (h->root.root.type == bfd_link_hash_undefined)
01707 {
01708
01709
01710 srel->size += RELOC_STD_SIZE;
01711 }
01712 else if ((h->root.root.u.def.section->flags & SEC_CODE) == 0)
01713 {
01714 bfd *sub;
01715
01716
01717
01718
01719 srel->size += RELOC_STD_SIZE;
01720 sub = h->root.root.u.def.section->owner;
01721 h->root.root.type = bfd_link_hash_undefined;
01722 h->root.root.u.undef.abfd = sub;
01723 }
01724 else
01725 {
01726
01727
01728
01729
01730
01731 if (h->plt_offset == 0)
01732 {
01733 if (splt->size == 0)
01734 splt->size = M68K_PLT_ENTRY_SIZE;
01735 h->plt_offset = splt->size;
01736
01737 if ((h->flags & SUNOS_DEF_REGULAR) == 0)
01738 {
01739 h->root.root.u.def.section = splt;
01740 h->root.root.u.def.value = splt->size;
01741 }
01742
01743 splt->size += M68K_PLT_ENTRY_SIZE;
01744
01745
01746 if ((h->flags & SUNOS_DEF_REGULAR) == 0)
01747 srel->size += RELOC_STD_SIZE;
01748 }
01749 }
01750 }
01751
01752 return TRUE;
01753 }
01754
01755
01756
01757
01758
01759
01760
01761 static bfd_boolean
01762 sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
01763 struct bfd_link_info *info;
01764 bfd *abfd;
01765 asection *sec ATTRIBUTE_UNUSED;
01766 const struct reloc_ext_external *relocs;
01767 bfd_size_type rel_size;
01768 {
01769 bfd *dynobj;
01770 struct sunos_link_hash_entry **sym_hashes;
01771 const struct reloc_ext_external *rel, *relend;
01772 asection *splt = NULL;
01773 asection *sgot = NULL;
01774 asection *srel = NULL;
01775 bfd_size_type amt;
01776
01777
01778 if (bfd_get_arch (abfd) != bfd_arch_sparc)
01779 {
01780 bfd_set_error (bfd_error_invalid_target);
01781 return FALSE;
01782 }
01783
01784 dynobj = NULL;
01785
01786 sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd);
01787
01788 relend = relocs + rel_size / RELOC_EXT_SIZE;
01789 for (rel = relocs; rel < relend; rel++)
01790 {
01791 unsigned int r_index;
01792 int r_extern;
01793 int r_type;
01794 struct sunos_link_hash_entry *h = NULL;
01795
01796
01797 if (bfd_header_big_endian (abfd))
01798 {
01799 r_index = ((rel->r_index[0] << 16)
01800 | (rel->r_index[1] << 8)
01801 | rel->r_index[2]);
01802 r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
01803 r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
01804 >> RELOC_EXT_BITS_TYPE_SH_BIG);
01805 }
01806 else
01807 {
01808 r_index = ((rel->r_index[2] << 16)
01809 | (rel->r_index[1] << 8)
01810 | rel->r_index[0]);
01811 r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
01812 r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
01813 >> RELOC_EXT_BITS_TYPE_SH_LITTLE);
01814 }
01815
01816 if (r_extern)
01817 {
01818 h = sym_hashes[r_index];
01819 if (h == NULL)
01820 {
01821
01822
01823 continue;
01824 }
01825 }
01826
01827
01828
01829 if (r_type == RELOC_BASE10
01830 || r_type == RELOC_BASE13
01831 || r_type == RELOC_BASE22)
01832 {
01833 if (dynobj == NULL)
01834 {
01835 if (! sunos_create_dynamic_sections (abfd, info, FALSE))
01836 return FALSE;
01837 dynobj = sunos_hash_table (info)->dynobj;
01838 splt = bfd_get_section_by_name (dynobj, ".plt");
01839 sgot = bfd_get_section_by_name (dynobj, ".got");
01840 srel = bfd_get_section_by_name (dynobj, ".dynrel");
01841 BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
01842
01843
01844 if (sgot->size == 0)
01845 sgot->size = BYTES_IN_WORD;
01846 sunos_hash_table (info)->got_needed = TRUE;
01847 }
01848
01849 if (r_extern)
01850 {
01851 if (h->got_offset != 0)
01852 continue;
01853
01854 h->got_offset = sgot->size;
01855 }
01856 else
01857 {
01858 if (r_index >= bfd_get_symcount (abfd))
01859 {
01860
01861
01862 continue;
01863 }
01864
01865 if (adata (abfd).local_got_offsets == NULL)
01866 {
01867 amt = bfd_get_symcount (abfd);
01868 amt *= sizeof (bfd_vma);
01869 adata (abfd).local_got_offsets =
01870 (bfd_vma *) bfd_zalloc (abfd, amt);
01871 if (adata (abfd).local_got_offsets == NULL)
01872 return FALSE;
01873 }
01874
01875 if (adata (abfd).local_got_offsets[r_index] != 0)
01876 continue;
01877
01878 adata (abfd).local_got_offsets[r_index] = sgot->size;
01879 }
01880
01881 sgot->size += BYTES_IN_WORD;
01882
01883
01884
01885
01886 if (info->shared
01887 || (h != NULL
01888 && (h->flags & SUNOS_DEF_DYNAMIC) != 0
01889 && (h->flags & SUNOS_DEF_REGULAR) == 0))
01890 srel->size += RELOC_EXT_SIZE;
01891
01892 continue;
01893 }
01894
01895
01896
01897
01898 if (! r_extern)
01899 {
01900
01901
01902 if (info->shared)
01903 {
01904 if (dynobj == NULL)
01905 {
01906 if (! sunos_create_dynamic_sections (abfd, info, TRUE))
01907 return FALSE;
01908 dynobj = sunos_hash_table (info)->dynobj;
01909 splt = bfd_get_section_by_name (dynobj, ".plt");
01910 sgot = bfd_get_section_by_name (dynobj, ".got");
01911 srel = bfd_get_section_by_name (dynobj, ".dynrel");
01912 BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
01913 }
01914
01915 srel->size += RELOC_EXT_SIZE;
01916 }
01917
01918 continue;
01919 }
01920
01921
01922
01923
01924
01925
01926 if (h->root.root.type != bfd_link_hash_defined
01927 && h->root.root.type != bfd_link_hash_defweak
01928 && h->root.root.type != bfd_link_hash_undefined)
01929 continue;
01930
01931 if (r_type != RELOC_JMP_TBL
01932 && ! info->shared
01933 && ((h->flags & SUNOS_DEF_DYNAMIC) == 0
01934 || (h->flags & SUNOS_DEF_REGULAR) != 0))
01935 continue;
01936
01937 if (r_type == RELOC_JMP_TBL
01938 && ! info->shared
01939 && (h->flags & SUNOS_DEF_DYNAMIC) == 0
01940 && (h->flags & SUNOS_DEF_REGULAR) == 0)
01941 {
01942
01943
01944
01945 continue;
01946 }
01947
01948 if (strcmp (h->root.root.root.string, "__GLOBAL_OFFSET_TABLE_") == 0)
01949 continue;
01950
01951 if (dynobj == NULL)
01952 {
01953 if (! sunos_create_dynamic_sections (abfd, info, FALSE))
01954 return FALSE;
01955 dynobj = sunos_hash_table (info)->dynobj;
01956 splt = bfd_get_section_by_name (dynobj, ".plt");
01957 sgot = bfd_get_section_by_name (dynobj, ".got");
01958 srel = bfd_get_section_by_name (dynobj, ".dynrel");
01959 BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
01960
01961
01962 if (sgot->size == 0)
01963 sgot->size = BYTES_IN_WORD;
01964 sunos_hash_table (info)->got_needed = TRUE;
01965 }
01966
01967 BFD_ASSERT (r_type == RELOC_JMP_TBL
01968 || info->shared
01969 || (h->flags & SUNOS_REF_REGULAR) != 0);
01970 BFD_ASSERT (r_type == RELOC_JMP_TBL
01971 || info->shared
01972 || h->plt_offset != 0
01973 || ((h->root.root.type == bfd_link_hash_defined
01974 || h->root.root.type == bfd_link_hash_defweak)
01975 ? (h->root.root.u.def.section->owner->flags
01976 & DYNAMIC) != 0
01977 : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0));
01978
01979
01980
01981
01982 if (r_type != RELOC_JMP_TBL
01983 && h->root.root.type == bfd_link_hash_undefined)
01984 {
01985
01986
01987 srel->size += RELOC_EXT_SIZE;
01988 }
01989 else if (r_type != RELOC_JMP_TBL
01990 && (h->root.root.u.def.section->flags & SEC_CODE) == 0)
01991 {
01992 bfd *sub;
01993
01994
01995
01996
01997 srel->size += RELOC_EXT_SIZE;
01998 if ((h->flags & SUNOS_DEF_REGULAR) == 0)
01999 {
02000 sub = h->root.root.u.def.section->owner;
02001 h->root.root.type = bfd_link_hash_undefined;
02002 h->root.root.u.undef.abfd = sub;
02003 }
02004 }
02005 else
02006 {
02007
02008
02009
02010
02011
02012 if (h->plt_offset == 0)
02013 {
02014 if (splt->size == 0)
02015 splt->size = SPARC_PLT_ENTRY_SIZE;
02016 h->plt_offset = splt->size;
02017
02018 if ((h->flags & SUNOS_DEF_REGULAR) == 0)
02019 {
02020 if (h->root.root.type == bfd_link_hash_undefined)
02021 h->root.root.type = bfd_link_hash_defined;
02022 h->root.root.u.def.section = splt;
02023 h->root.root.u.def.value = splt->size;
02024 }
02025
02026 splt->size += SPARC_PLT_ENTRY_SIZE;
02027
02028
02029
02030
02031 if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
02032 srel->size += RELOC_EXT_SIZE;
02033 }
02034
02035
02036
02037 if (info->shared && r_type != RELOC_JMP_TBL)
02038 srel->size += RELOC_EXT_SIZE;
02039 }
02040 }
02041
02042 return TRUE;
02043 }
02044
02045
02046
02047
02048 static bfd_boolean
02049 sunos_scan_dynamic_symbol (h, data)
02050 struct sunos_link_hash_entry *h;
02051 PTR data;
02052 {
02053 struct bfd_link_info *info = (struct bfd_link_info *) data;
02054
02055 if (h->root.root.type == bfd_link_hash_warning)
02056 h = (struct sunos_link_hash_entry *) h->root.root.u.i.link;
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067 if ((h->flags & SUNOS_DEF_REGULAR) == 0
02068 && (h->flags & SUNOS_DEF_DYNAMIC) != 0
02069 && strcmp (h->root.root.root.string, "__DYNAMIC") != 0)
02070 h->root.written = TRUE;
02071
02072
02073
02074
02075
02076 if ((h->flags & SUNOS_DEF_REGULAR) == 0
02077 && (h->flags & SUNOS_DEF_DYNAMIC) != 0
02078 && (h->flags & SUNOS_REF_REGULAR) != 0)
02079 {
02080 if ((h->root.root.type == bfd_link_hash_defined
02081 || h->root.root.type == bfd_link_hash_defweak)
02082 && ((h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
02083 && h->root.root.u.def.section->output_section == NULL)
02084 {
02085 bfd *sub;
02086
02087
02088
02089
02090
02091
02092 sub = h->root.root.u.def.section->owner;
02093 h->root.root.type = bfd_link_hash_undefined;
02094 h->root.root.u.undef.abfd = sub;
02095 }
02096 }
02097
02098
02099
02100 if ((h->flags & (SUNOS_DEF_REGULAR | SUNOS_REF_REGULAR)) != 0)
02101 {
02102 asection *s;
02103 size_t len;
02104 bfd_byte *contents;
02105 unsigned char *name;
02106 unsigned long hash;
02107 bfd *dynobj;
02108
02109 BFD_ASSERT (h->dynindx == -2);
02110
02111 dynobj = sunos_hash_table (info)->dynobj;
02112
02113 h->dynindx = sunos_hash_table (info)->dynsymcount;
02114 ++sunos_hash_table (info)->dynsymcount;
02115
02116 len = strlen (h->root.root.root.string);
02117
02118
02119
02120
02121
02122
02123
02124 s = bfd_get_section_by_name (dynobj, ".dynstr");
02125 BFD_ASSERT (s != NULL);
02126 contents = (bfd_byte *) bfd_realloc (s->contents,
02127 s->size + len + 1);
02128 if (contents == NULL)
02129 return FALSE;
02130 s->contents = contents;
02131
02132 h->dynstr_index = s->size;
02133 strcpy ((char *) contents + s->size, h->root.root.root.string);
02134 s->size += len + 1;
02135
02136
02137 name = (unsigned char *) h->root.root.root.string;
02138 hash = 0;
02139 while (*name != '\0')
02140 hash = (hash << 1) + *name++;
02141 hash &= 0x7fffffff;
02142 hash %= sunos_hash_table (info)->bucketcount;
02143
02144 s = bfd_get_section_by_name (dynobj, ".hash");
02145 BFD_ASSERT (s != NULL);
02146
02147 if (GET_SWORD (dynobj, s->contents + hash * HASH_ENTRY_SIZE) == -1)
02148 PUT_WORD (dynobj, h->dynindx, s->contents + hash * HASH_ENTRY_SIZE);
02149 else
02150 {
02151 bfd_vma next;
02152
02153 next = GET_WORD (dynobj,
02154 (s->contents
02155 + hash * HASH_ENTRY_SIZE
02156 + BYTES_IN_WORD));
02157 PUT_WORD (dynobj, s->size / HASH_ENTRY_SIZE,
02158 s->contents + hash * HASH_ENTRY_SIZE + BYTES_IN_WORD);
02159 PUT_WORD (dynobj, h->dynindx, s->contents + s->size);
02160 PUT_WORD (dynobj, next, s->contents + s->size + BYTES_IN_WORD);
02161 s->size += HASH_ENTRY_SIZE;
02162 }
02163 }
02164
02165 return TRUE;
02166 }
02167
02168
02169
02170
02171
02172 static bfd_boolean
02173 sunos_link_dynamic_object (info, abfd)
02174 struct bfd_link_info *info ATTRIBUTE_UNUSED;
02175 bfd *abfd ATTRIBUTE_UNUSED;
02176 {
02177 return TRUE;
02178 }
02179
02180
02181
02182
02183 static bfd_boolean
02184 sunos_write_dynamic_symbol (output_bfd, info, harg)
02185 bfd *output_bfd;
02186 struct bfd_link_info *info;
02187 struct aout_link_hash_entry *harg;
02188 {
02189 struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg;
02190 int type;
02191 bfd_vma val;
02192 asection *s;
02193 struct external_nlist *outsym;
02194
02195
02196
02197 if (h->plt_offset != 0)
02198 {
02199 bfd *dynobj;
02200 asection *splt;
02201 bfd_byte *p;
02202 bfd_vma r_address;
02203
02204 dynobj = sunos_hash_table (info)->dynobj;
02205 splt = bfd_get_section_by_name (dynobj, ".plt");
02206 p = splt->contents + h->plt_offset;
02207
02208 s = bfd_get_section_by_name (dynobj, ".dynrel");
02209
02210 r_address = (splt->output_section->vma
02211 + splt->output_offset
02212 + h->plt_offset);
02213
02214 switch (bfd_get_arch (output_bfd))
02215 {
02216 case bfd_arch_sparc:
02217 if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
02218 {
02219 bfd_put_32 (output_bfd, SPARC_PLT_ENTRY_WORD0, p);
02220 bfd_put_32 (output_bfd,
02221 (SPARC_PLT_ENTRY_WORD1
02222 + (((- (h->plt_offset + 4) >> 2)
02223 & 0x3fffffff))),
02224 p + 4);
02225 bfd_put_32 (output_bfd, SPARC_PLT_ENTRY_WORD2 + s->reloc_count,
02226 p + 8);
02227 }
02228 else
02229 {
02230 val = (h->root.root.u.def.section->output_section->vma
02231 + h->root.root.u.def.section->output_offset
02232 + h->root.root.u.def.value);
02233 bfd_put_32 (output_bfd,
02234 SPARC_PLT_PIC_WORD0 + ((val >> 10) & 0x3fffff),
02235 p);
02236 bfd_put_32 (output_bfd,
02237 SPARC_PLT_PIC_WORD1 + (val & 0x3ff),
02238 p + 4);
02239 bfd_put_32 (output_bfd, SPARC_PLT_PIC_WORD2, p + 8);
02240 }
02241 break;
02242
02243 case bfd_arch_m68k:
02244 if (! info->shared && (h->flags & SUNOS_DEF_REGULAR) != 0)
02245 abort ();
02246 bfd_put_16 (output_bfd, M68K_PLT_ENTRY_WORD0, p);
02247 bfd_put_32 (output_bfd, (- (h->plt_offset + 2)), p + 2);
02248 bfd_put_16 (output_bfd, (bfd_vma) s->reloc_count, p + 6);
02249 r_address += 2;
02250 break;
02251
02252 default:
02253 abort ();
02254 }
02255
02256
02257
02258 if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
02259 {
02260 BFD_ASSERT (h->dynindx >= 0);
02261 BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
02262 < s->size);
02263 p = s->contents + s->reloc_count * obj_reloc_entry_size (output_bfd);
02264 if (obj_reloc_entry_size (output_bfd) == RELOC_STD_SIZE)
02265 {
02266 struct reloc_std_external *srel;
02267
02268 srel = (struct reloc_std_external *) p;
02269 PUT_WORD (output_bfd, r_address, srel->r_address);
02270 if (bfd_header_big_endian (output_bfd))
02271 {
02272 srel->r_index[0] = (bfd_byte) (h->dynindx >> 16);
02273 srel->r_index[1] = (bfd_byte) (h->dynindx >> 8);
02274 srel->r_index[2] = (bfd_byte) (h->dynindx);
02275 srel->r_type[0] = (RELOC_STD_BITS_EXTERN_BIG
02276 | RELOC_STD_BITS_JMPTABLE_BIG);
02277 }
02278 else
02279 {
02280 srel->r_index[2] = (bfd_byte) (h->dynindx >> 16);
02281 srel->r_index[1] = (bfd_byte) (h->dynindx >> 8);
02282 srel->r_index[0] = (bfd_byte)h->dynindx;
02283 srel->r_type[0] = (RELOC_STD_BITS_EXTERN_LITTLE
02284 | RELOC_STD_BITS_JMPTABLE_LITTLE);
02285 }
02286 }
02287 else
02288 {
02289 struct reloc_ext_external *erel;
02290
02291 erel = (struct reloc_ext_external *) p;
02292 PUT_WORD (output_bfd, r_address, erel->r_address);
02293 if (bfd_header_big_endian (output_bfd))
02294 {
02295 erel->r_index[0] = (bfd_byte) (h->dynindx >> 16);
02296 erel->r_index[1] = (bfd_byte) (h->dynindx >> 8);
02297 erel->r_index[2] = (bfd_byte)h->dynindx;
02298 erel->r_type[0] =
02299 (RELOC_EXT_BITS_EXTERN_BIG
02300 | (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_BIG));
02301 }
02302 else
02303 {
02304 erel->r_index[2] = (bfd_byte) (h->dynindx >> 16);
02305 erel->r_index[1] = (bfd_byte) (h->dynindx >> 8);
02306 erel->r_index[0] = (bfd_byte)h->dynindx;
02307 erel->r_type[0] =
02308 (RELOC_EXT_BITS_EXTERN_LITTLE
02309 | (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_LITTLE));
02310 }
02311 PUT_WORD (output_bfd, (bfd_vma) 0, erel->r_addend);
02312 }
02313
02314 ++s->reloc_count;
02315 }
02316 }
02317
02318
02319
02320
02321
02322 if (h->dynindx < 0)
02323 return TRUE;
02324
02325 switch (h->root.root.type)
02326 {
02327 default:
02328 case bfd_link_hash_new:
02329 abort ();
02330
02331 return TRUE;
02332 case bfd_link_hash_undefined:
02333 type = N_UNDF | N_EXT;
02334 val = 0;
02335 break;
02336 case bfd_link_hash_defined:
02337 case bfd_link_hash_defweak:
02338 {
02339 asection *sec;
02340 asection *output_section;
02341
02342 sec = h->root.root.u.def.section;
02343 output_section = sec->output_section;
02344 BFD_ASSERT (bfd_is_abs_section (output_section)
02345 || output_section->owner == output_bfd);
02346 if (h->plt_offset != 0
02347 && (h->flags & SUNOS_DEF_REGULAR) == 0)
02348 {
02349 type = N_UNDF | N_EXT;
02350 val = 0;
02351 }
02352 else
02353 {
02354 if (output_section == obj_textsec (output_bfd))
02355 type = (h->root.root.type == bfd_link_hash_defined
02356 ? N_TEXT
02357 : N_WEAKT);
02358 else if (output_section == obj_datasec (output_bfd))
02359 type = (h->root.root.type == bfd_link_hash_defined
02360 ? N_DATA
02361 : N_WEAKD);
02362 else if (output_section == obj_bsssec (output_bfd))
02363 type = (h->root.root.type == bfd_link_hash_defined
02364 ? N_BSS
02365 : N_WEAKB);
02366 else
02367 type = (h->root.root.type == bfd_link_hash_defined
02368 ? N_ABS
02369 : N_WEAKA);
02370 type |= N_EXT;
02371 val = (h->root.root.u.def.value
02372 + output_section->vma
02373 + sec->output_offset);
02374 }
02375 }
02376 break;
02377 case bfd_link_hash_common:
02378 type = N_UNDF | N_EXT;
02379 val = h->root.root.u.c.size;
02380 break;
02381 case bfd_link_hash_undefweak:
02382 type = N_WEAKU;
02383 val = 0;
02384 break;
02385 case bfd_link_hash_indirect:
02386 case bfd_link_hash_warning:
02387
02388
02389 return TRUE;
02390 }
02391
02392 s = bfd_get_section_by_name (sunos_hash_table (info)->dynobj, ".dynsym");
02393 BFD_ASSERT (s != NULL);
02394 outsym = ((struct external_nlist *)
02395 (s->contents + h->dynindx * EXTERNAL_NLIST_SIZE));
02396
02397 H_PUT_8 (output_bfd, type, outsym->e_type);
02398 H_PUT_8 (output_bfd, 0, outsym->e_other);
02399
02400
02401
02402
02403 H_PUT_16 (output_bfd, 0, outsym->e_desc);
02404
02405 PUT_WORD (output_bfd, h->dynstr_index, outsym->e_strx);
02406 PUT_WORD (output_bfd, val, outsym->e_value);
02407
02408 return TRUE;
02409 }
02410
02411
02412
02413
02414
02415
02416 static bfd_boolean
02417 sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
02418 contents, skip, relocationp)
02419 struct bfd_link_info *info;
02420 bfd *input_bfd;
02421 asection *input_section;
02422 struct aout_link_hash_entry *harg;
02423 PTR reloc;
02424 bfd_byte *contents ATTRIBUTE_UNUSED;
02425 bfd_boolean *skip;
02426 bfd_vma *relocationp;
02427 {
02428 struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg;
02429 bfd *dynobj;
02430 bfd_boolean baserel;
02431 bfd_boolean jmptbl;
02432 bfd_boolean pcrel;
02433 asection *s;
02434 bfd_byte *p;
02435 long indx;
02436
02437 *skip = FALSE;
02438
02439 dynobj = sunos_hash_table (info)->dynobj;
02440
02441 if (h != NULL
02442 && h->plt_offset != 0
02443 && (info->shared
02444 || (h->flags & SUNOS_DEF_REGULAR) == 0))
02445 {
02446 asection *splt;
02447
02448
02449 splt = bfd_get_section_by_name (dynobj, ".plt");
02450 *relocationp = (splt->output_section->vma
02451 + splt->output_offset
02452 + h->plt_offset);
02453 }
02454
02455 if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE)
02456 {
02457 struct reloc_std_external *srel;
02458
02459 srel = (struct reloc_std_external *) reloc;
02460 if (bfd_header_big_endian (input_bfd))
02461 {
02462 baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
02463 jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
02464 pcrel = (0 != (srel->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
02465 }
02466 else
02467 {
02468 baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
02469 jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
02470 pcrel = (0 != (srel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
02471 }
02472 }
02473 else
02474 {
02475 struct reloc_ext_external *erel;
02476 int r_type;
02477
02478 erel = (struct reloc_ext_external *) reloc;
02479 if (bfd_header_big_endian (input_bfd))
02480 r_type = ((erel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
02481 >> RELOC_EXT_BITS_TYPE_SH_BIG);
02482 else
02483 r_type = ((erel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
02484 >> RELOC_EXT_BITS_TYPE_SH_LITTLE);
02485 baserel = (r_type == RELOC_BASE10
02486 || r_type == RELOC_BASE13
02487 || r_type == RELOC_BASE22);
02488 jmptbl = r_type == RELOC_JMP_TBL;
02489 pcrel = (r_type == RELOC_DISP8
02490 || r_type == RELOC_DISP16
02491 || r_type == RELOC_DISP32
02492 || r_type == RELOC_WDISP30
02493 || r_type == RELOC_WDISP22);
02494
02495
02496 }
02497
02498 if (baserel)
02499 {
02500 bfd_vma *got_offsetp;
02501 asection *sgot;
02502
02503 if (h != NULL)
02504 got_offsetp = &h->got_offset;
02505 else if (adata (input_bfd).local_got_offsets == NULL)
02506 got_offsetp = NULL;
02507 else
02508 {
02509 struct reloc_std_external *srel;
02510 int r_index;
02511
02512 srel = (struct reloc_std_external *) reloc;
02513 if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE)
02514 {
02515 if (bfd_header_big_endian (input_bfd))
02516 r_index = ((srel->r_index[0] << 16)
02517 | (srel->r_index[1] << 8)
02518 | srel->r_index[2]);
02519 else
02520 r_index = ((srel->r_index[2] << 16)
02521 | (srel->r_index[1] << 8)
02522 | srel->r_index[0]);
02523 }
02524 else
02525 {
02526 struct reloc_ext_external *erel;
02527
02528 erel = (struct reloc_ext_external *) reloc;
02529 if (bfd_header_big_endian (input_bfd))
02530 r_index = ((erel->r_index[0] << 16)
02531 | (erel->r_index[1] << 8)
02532 | erel->r_index[2]);
02533 else
02534 r_index = ((erel->r_index[2] << 16)
02535 | (erel->r_index[1] << 8)
02536 | erel->r_index[0]);
02537 }
02538
02539 got_offsetp = adata (input_bfd).local_got_offsets + r_index;
02540 }
02541
02542 BFD_ASSERT (got_offsetp != NULL && *got_offsetp != 0);
02543
02544 sgot = bfd_get_section_by_name (dynobj, ".got");
02545
02546
02547
02548 if ((*got_offsetp & 1) == 0)
02549 {
02550 if (h == NULL
02551 || (! info->shared
02552 && ((h->flags & SUNOS_DEF_DYNAMIC) == 0
02553 || (h->flags & SUNOS_DEF_REGULAR) != 0)))
02554 PUT_WORD (dynobj, *relocationp, sgot->contents + *got_offsetp);
02555 else
02556 PUT_WORD (dynobj, 0, sgot->contents + *got_offsetp);
02557
02558 if (info->shared
02559 || (h != NULL
02560 && (h->flags & SUNOS_DEF_DYNAMIC) != 0
02561 && (h->flags & SUNOS_DEF_REGULAR) == 0))
02562 {
02563
02564
02565
02566 s = bfd_get_section_by_name (dynobj, ".dynrel");
02567 BFD_ASSERT (s != NULL);
02568 BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
02569 < s->size);
02570
02571 p = (s->contents
02572 + s->reloc_count * obj_reloc_entry_size (dynobj));
02573
02574 if (h != NULL)
02575 indx = h->dynindx;
02576 else
02577 indx = 0;
02578
02579 if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE)
02580 {
02581 struct reloc_std_external *srel;
02582
02583 srel = (struct reloc_std_external *) p;
02584 PUT_WORD (dynobj,
02585 (*got_offsetp
02586 + sgot->output_section->vma
02587 + sgot->output_offset),
02588 srel->r_address);
02589 if (bfd_header_big_endian (dynobj))
02590 {
02591 srel->r_index[0] = (bfd_byte) (indx >> 16);
02592 srel->r_index[1] = (bfd_byte) (indx >> 8);
02593 srel->r_index[2] = (bfd_byte)indx;
02594 if (h == NULL)
02595 srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_BIG;
02596 else
02597 srel->r_type[0] =
02598 (RELOC_STD_BITS_EXTERN_BIG
02599 | RELOC_STD_BITS_BASEREL_BIG
02600 | RELOC_STD_BITS_RELATIVE_BIG
02601 | (2 << RELOC_STD_BITS_LENGTH_SH_BIG));
02602 }
02603 else
02604 {
02605 srel->r_index[2] = (bfd_byte) (indx >> 16);
02606 srel->r_index[1] = (bfd_byte) (indx >> 8);
02607 srel->r_index[0] = (bfd_byte)indx;
02608 if (h == NULL)
02609 srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_LITTLE;
02610 else
02611 srel->r_type[0] =
02612 (RELOC_STD_BITS_EXTERN_LITTLE
02613 | RELOC_STD_BITS_BASEREL_LITTLE
02614 | RELOC_STD_BITS_RELATIVE_LITTLE
02615 | (2 << RELOC_STD_BITS_LENGTH_SH_LITTLE));
02616 }
02617 }
02618 else
02619 {
02620 struct reloc_ext_external *erel;
02621
02622 erel = (struct reloc_ext_external *) p;
02623 PUT_WORD (dynobj,
02624 (*got_offsetp
02625 + sgot->output_section->vma
02626 + sgot->output_offset),
02627 erel->r_address);
02628 if (bfd_header_big_endian (dynobj))
02629 {
02630 erel->r_index[0] = (bfd_byte) (indx >> 16);
02631 erel->r_index[1] = (bfd_byte) (indx >> 8);
02632 erel->r_index[2] = (bfd_byte)indx;
02633 if (h == NULL)
02634 erel->r_type[0] =
02635 RELOC_32 << RELOC_EXT_BITS_TYPE_SH_BIG;
02636 else
02637 erel->r_type[0] =
02638 (RELOC_EXT_BITS_EXTERN_BIG
02639 | (RELOC_GLOB_DAT << RELOC_EXT_BITS_TYPE_SH_BIG));
02640 }
02641 else
02642 {
02643 erel->r_index[2] = (bfd_byte) (indx >> 16);
02644 erel->r_index[1] = (bfd_byte) (indx >> 8);
02645 erel->r_index[0] = (bfd_byte)indx;
02646 if (h == NULL)
02647 erel->r_type[0] =
02648 RELOC_32 << RELOC_EXT_BITS_TYPE_SH_LITTLE;
02649 else
02650 erel->r_type[0] =
02651 (RELOC_EXT_BITS_EXTERN_LITTLE
02652 | (RELOC_GLOB_DAT
02653 << RELOC_EXT_BITS_TYPE_SH_LITTLE));
02654 }
02655 PUT_WORD (dynobj, 0, erel->r_addend);
02656 }
02657
02658 ++s->reloc_count;
02659 }
02660
02661 *got_offsetp |= 1;
02662 }
02663
02664 *relocationp = (sgot->vma
02665 + (*got_offsetp &~ (bfd_vma) 1)
02666 - sunos_hash_table (info)->got_base);
02667
02668
02669 return TRUE;
02670 }
02671
02672 if (! sunos_hash_table (info)->dynamic_sections_needed)
02673 return TRUE;
02674 if (! info->shared)
02675 {
02676 if (h == NULL
02677 || h->dynindx == -1
02678 || h->root.root.type != bfd_link_hash_undefined
02679 || (h->flags & SUNOS_DEF_REGULAR) != 0
02680 || (h->flags & SUNOS_DEF_DYNAMIC) == 0
02681 || (h->root.root.u.undef.abfd->flags & DYNAMIC) == 0)
02682 return TRUE;
02683 }
02684 else
02685 {
02686 if (h != NULL
02687 && (h->dynindx == -1
02688 || jmptbl
02689 || strcmp (h->root.root.root.string,
02690 "__GLOBAL_OFFSET_TABLE_") == 0))
02691 return TRUE;
02692 }
02693
02694
02695
02696 s = bfd_get_section_by_name (dynobj, ".dynrel");
02697 BFD_ASSERT (s != NULL);
02698 BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) < s->size);
02699
02700 p = s->contents + s->reloc_count * obj_reloc_entry_size (dynobj);
02701
02702
02703 memcpy (p, reloc, obj_reloc_entry_size (dynobj));
02704
02705 if (h != NULL)
02706 indx = h->dynindx;
02707 else
02708 indx = 0;
02709
02710
02711 if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE)
02712 {
02713 struct reloc_std_external *srel;
02714
02715 srel = (struct reloc_std_external *) p;
02716 PUT_WORD (dynobj,
02717 (GET_WORD (dynobj, srel->r_address)
02718 + input_section->output_section->vma
02719 + input_section->output_offset),
02720 srel->r_address);
02721 if (bfd_header_big_endian (dynobj))
02722 {
02723 srel->r_index[0] = (bfd_byte) (indx >> 16);
02724 srel->r_index[1] = (bfd_byte) (indx >> 8);
02725 srel->r_index[2] = (bfd_byte)indx;
02726 }
02727 else
02728 {
02729 srel->r_index[2] = (bfd_byte) (indx >> 16);
02730 srel->r_index[1] = (bfd_byte) (indx >> 8);
02731 srel->r_index[0] = (bfd_byte)indx;
02732 }
02733
02734
02735 }
02736 else
02737 {
02738 struct reloc_ext_external *erel;
02739
02740 erel = (struct reloc_ext_external *) p;
02741 PUT_WORD (dynobj,
02742 (GET_WORD (dynobj, erel->r_address)
02743 + input_section->output_section->vma
02744 + input_section->output_offset),
02745 erel->r_address);
02746 if (bfd_header_big_endian (dynobj))
02747 {
02748 erel->r_index[0] = (bfd_byte) (indx >> 16);
02749 erel->r_index[1] = (bfd_byte) (indx >> 8);
02750 erel->r_index[2] = (bfd_byte)indx;
02751 }
02752 else
02753 {
02754 erel->r_index[2] = (bfd_byte) (indx >> 16);
02755 erel->r_index[1] = (bfd_byte) (indx >> 8);
02756 erel->r_index[0] = (bfd_byte)indx;
02757 }
02758 if (pcrel && h != NULL)
02759 {
02760
02761 PUT_WORD (dynobj,
02762 (GET_WORD (dynobj, erel->r_addend)
02763 - (input_section->output_section->vma
02764 + input_section->output_offset
02765 - input_section->vma)),
02766 erel->r_addend);
02767 }
02768 }
02769
02770 ++s->reloc_count;
02771
02772 if (h != NULL)
02773 *skip = TRUE;
02774
02775 return TRUE;
02776 }
02777
02778
02779
02780 static bfd_boolean
02781 sunos_finish_dynamic_link (abfd, info)
02782 bfd *abfd;
02783 struct bfd_link_info *info;
02784 {
02785 bfd *dynobj;
02786 asection *o;
02787 asection *s;
02788 asection *sdyn;
02789
02790 if (! sunos_hash_table (info)->dynamic_sections_needed
02791 && ! sunos_hash_table (info)->got_needed)
02792 return TRUE;
02793
02794 dynobj = sunos_hash_table (info)->dynobj;
02795
02796 sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
02797 BFD_ASSERT (sdyn != NULL);
02798
02799
02800
02801
02802
02803 s = bfd_get_section_by_name (dynobj, ".need");
02804 if (s != NULL && s->size != 0)
02805 {
02806 file_ptr filepos;
02807 bfd_byte *p;
02808
02809 filepos = s->output_section->filepos + s->output_offset;
02810 p = s->contents;
02811 while (1)
02812 {
02813 bfd_vma val;
02814
02815 PUT_WORD (dynobj, GET_WORD (dynobj, p) + filepos, p);
02816 val = GET_WORD (dynobj, p + 12);
02817 if (val == 0)
02818 break;
02819 PUT_WORD (dynobj, val + filepos, p + 12);
02820 p += 16;
02821 }
02822 }
02823
02824
02825
02826 s = bfd_get_section_by_name (dynobj, ".got");
02827 BFD_ASSERT (s != NULL);
02828 if (info->shared || sdyn->size == 0)
02829 PUT_WORD (dynobj, 0, s->contents);
02830 else
02831 PUT_WORD (dynobj, sdyn->output_section->vma + sdyn->output_offset,
02832 s->contents);
02833
02834 for (o = dynobj->sections; o != NULL; o = o->next)
02835 {
02836 if ((o->flags & SEC_HAS_CONTENTS) != 0
02837 && o->contents != NULL)
02838 {
02839 BFD_ASSERT (o->output_section != NULL
02840 && o->output_section->owner == abfd);
02841 if (! bfd_set_section_contents (abfd, o->output_section,
02842 o->contents,
02843 (file_ptr) o->output_offset,
02844 o->size))
02845 return FALSE;
02846 }
02847 }
02848
02849 if (sdyn->size > 0)
02850 {
02851 struct external_sun4_dynamic esd;
02852 struct external_sun4_dynamic_link esdl;
02853 file_ptr pos;
02854
02855
02856 PUT_WORD (dynobj, (bfd_vma) 3, esd.ld_version);
02857 PUT_WORD (dynobj,
02858 sdyn->output_section->vma + sdyn->output_offset + sizeof esd,
02859 esd.ldd);
02860 PUT_WORD (dynobj,
02861 (sdyn->output_section->vma
02862 + sdyn->output_offset
02863 + sizeof esd
02864 + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE),
02865 esd.ld);
02866
02867 if (! bfd_set_section_contents (abfd, sdyn->output_section, &esd,
02868 (file_ptr) sdyn->output_offset,
02869 (bfd_size_type) sizeof esd))
02870 return FALSE;
02871
02872 PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_loaded);
02873
02874 s = bfd_get_section_by_name (dynobj, ".need");
02875 if (s == NULL || s->size == 0)
02876 PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_need);
02877 else
02878 PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
02879 esdl.ld_need);
02880
02881 s = bfd_get_section_by_name (dynobj, ".rules");
02882 if (s == NULL || s->size == 0)
02883 PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_rules);
02884 else
02885 PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
02886 esdl.ld_rules);
02887
02888 s = bfd_get_section_by_name (dynobj, ".got");
02889 BFD_ASSERT (s != NULL);
02890 PUT_WORD (dynobj, s->output_section->vma + s->output_offset,
02891 esdl.ld_got);
02892
02893 s = bfd_get_section_by_name (dynobj, ".plt");
02894 BFD_ASSERT (s != NULL);
02895 PUT_WORD (dynobj, s->output_section->vma + s->output_offset,
02896 esdl.ld_plt);
02897 PUT_WORD (dynobj, s->size, esdl.ld_plt_sz);
02898
02899 s = bfd_get_section_by_name (dynobj, ".dynrel");
02900 BFD_ASSERT (s != NULL);
02901 BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
02902 == s->size);
02903 PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
02904 esdl.ld_rel);
02905
02906 s = bfd_get_section_by_name (dynobj, ".hash");
02907 BFD_ASSERT (s != NULL);
02908 PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
02909 esdl.ld_hash);
02910
02911 s = bfd_get_section_by_name (dynobj, ".dynsym");
02912 BFD_ASSERT (s != NULL);
02913 PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
02914 esdl.ld_stab);
02915
02916 PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_stab_hash);
02917
02918 PUT_WORD (dynobj, (bfd_vma) sunos_hash_table (info)->bucketcount,
02919 esdl.ld_buckets);
02920
02921 s = bfd_get_section_by_name (dynobj, ".dynstr");
02922 BFD_ASSERT (s != NULL);
02923 PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
02924 esdl.ld_symbols);
02925 PUT_WORD (dynobj, s->size, esdl.ld_symb_size);
02926
02927
02928
02929
02930 PUT_WORD (dynobj,
02931 BFD_ALIGN (obj_textsec (abfd)->size, 0x2000),
02932 esdl.ld_text);
02933
02934 pos = sdyn->output_offset;
02935 pos += sizeof esd + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE;
02936 if (! bfd_set_section_contents (abfd, sdyn->output_section, &esdl,
02937 pos, (bfd_size_type) sizeof esdl))
02938 return FALSE;
02939
02940 abfd->flags |= DYNAMIC;
02941 }
02942
02943 return TRUE;
02944 }