159024Sobrien/* BFD backend for SunOS binaries. 2218822Sdim Copyright 1990, 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 3218822Sdim 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 459024Sobrien Written by Cygnus Support. 559024Sobrien 6218822Sdim This file is part of BFD, the Binary File Descriptor library. 759024Sobrien 8218822Sdim This program is free software; you can redistribute it and/or modify 9218822Sdim it under the terms of the GNU General Public License as published by 10218822Sdim the Free Software Foundation; either version 2 of the License, or 11218822Sdim (at your option) any later version. 1259024Sobrien 13218822Sdim This program is distributed in the hope that it will be useful, 14218822Sdim but WITHOUT ANY WARRANTY; without even the implied warranty of 15218822Sdim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16218822Sdim GNU General Public License for more details. 1759024Sobrien 18218822Sdim You should have received a copy of the GNU General Public License 19218822Sdim along with this program; if not, write to the Free Software 20218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2159024Sobrien 2259024Sobrien#define TARGETNAME "a.out-sunos-big" 2359024Sobrien 2489857Sobrien/* Do not "beautify" the CONCAT* macro args. Traditional C will not 2589857Sobrien remove whitespace added here, and thus will fail to concatenate 2689857Sobrien the tokens. */ 2789857Sobrien#define MY(OP) CONCAT2 (sunos_big_,OP) 2889857Sobrien 2959024Sobrien#include "bfd.h" 3059024Sobrien#include "bfdlink.h" 3159024Sobrien#include "libaout.h" 3259024Sobrien 3359024Sobrien/* ??? Where should this go? */ 3459024Sobrien#define MACHTYPE_OK(mtype) \ 3559024Sobrien (((mtype) == M_SPARC && bfd_lookup_arch (bfd_arch_sparc, 0) != NULL) \ 3659024Sobrien || ((mtype) == M_SPARCLET \ 3759024Sobrien && bfd_lookup_arch (bfd_arch_sparc, bfd_mach_sparc_sparclet) != NULL) \ 3884865Sobrien || ((mtype) == M_SPARCLITE_LE \ 3984865Sobrien && bfd_lookup_arch (bfd_arch_sparc, bfd_mach_sparc_sparclet) != NULL) \ 4059024Sobrien || (((mtype) == M_UNKNOWN || (mtype) == M_68010 || (mtype) == M_68020) \ 4159024Sobrien && bfd_lookup_arch (bfd_arch_m68k, 0) != NULL)) 4259024Sobrien 43218822Sdim#define MY_get_dynamic_symtab_upper_bound sunos_get_dynamic_symtab_upper_bound 44218822Sdim#define MY_canonicalize_dynamic_symtab sunos_canonicalize_dynamic_symtab 45218822Sdim#define MY_get_synthetic_symtab _bfd_nodynamic_get_synthetic_symtab 46218822Sdim#define MY_get_dynamic_reloc_upper_bound sunos_get_dynamic_reloc_upper_bound 47218822Sdim#define MY_canonicalize_dynamic_reloc sunos_canonicalize_dynamic_reloc 48218822Sdim#define MY_bfd_link_hash_table_create sunos_link_hash_table_create 49218822Sdim#define MY_add_dynamic_symbols sunos_add_dynamic_symbols 50218822Sdim#define MY_add_one_symbol sunos_add_one_symbol 51218822Sdim#define MY_link_dynamic_object sunos_link_dynamic_object 52218822Sdim#define MY_write_dynamic_symbol sunos_write_dynamic_symbol 53218822Sdim#define MY_check_dynamic_reloc sunos_check_dynamic_reloc 54218822Sdim#define MY_finish_dynamic_link sunos_finish_dynamic_link 55218822Sdim 56218822Sdimstatic bfd_boolean sunos_add_dynamic_symbols (bfd *, struct bfd_link_info *, struct external_nlist **, bfd_size_type *, char **); 57218822Sdimstatic bfd_boolean sunos_add_one_symbol (struct bfd_link_info *, bfd *, const char *, flagword, asection *, bfd_vma, const char *, bfd_boolean, bfd_boolean, struct bfd_link_hash_entry **); 58218822Sdimstatic bfd_boolean sunos_link_dynamic_object (struct bfd_link_info *, bfd *); 59218822Sdimstatic bfd_boolean sunos_write_dynamic_symbol (bfd *, struct bfd_link_info *, struct aout_link_hash_entry *); 60218822Sdimstatic bfd_boolean sunos_check_dynamic_reloc (struct bfd_link_info *, bfd *, asection *, struct aout_link_hash_entry *, void *, bfd_byte *, bfd_boolean *, bfd_vma *); 61218822Sdimstatic bfd_boolean sunos_finish_dynamic_link (bfd *, struct bfd_link_info *); 62218822Sdimstatic struct bfd_link_hash_table *sunos_link_hash_table_create (bfd *); 63218822Sdimstatic long sunos_get_dynamic_symtab_upper_bound (bfd *); 64218822Sdimstatic long sunos_canonicalize_dynamic_symtab (bfd *, asymbol **); 65218822Sdimstatic long sunos_get_dynamic_reloc_upper_bound (bfd *); 66218822Sdimstatic long sunos_canonicalize_dynamic_reloc (bfd *, arelent **, asymbol **); 67218822Sdim 6859024Sobrien/* Include the usual a.out support. */ 6959024Sobrien#include "aoutf1.h" 7059024Sobrien 7184865Sobrien/* The SunOS 4.1.4 /usr/include/locale.h defines valid as a macro. */ 7284865Sobrien#undef valid 7384865Sobrien 7459024Sobrien/* SunOS shared library support. We store a pointer to this structure 7559024Sobrien in obj_aout_dynamic_info (abfd). */ 7659024Sobrien 7759024Sobrienstruct sunos_dynamic_info 7859024Sobrien{ 7959024Sobrien /* Whether we found any dynamic information. */ 80130561Sobrien bfd_boolean valid; 8159024Sobrien /* Dynamic information. */ 8259024Sobrien struct internal_sun4_dynamic_link dyninfo; 8359024Sobrien /* Number of dynamic symbols. */ 8459024Sobrien unsigned long dynsym_count; 8559024Sobrien /* Read in nlists for dynamic symbols. */ 8659024Sobrien struct external_nlist *dynsym; 8759024Sobrien /* asymbol structures for dynamic symbols. */ 8859024Sobrien aout_symbol_type *canonical_dynsym; 8959024Sobrien /* Read in dynamic string table. */ 9059024Sobrien char *dynstr; 9159024Sobrien /* Number of dynamic relocs. */ 9259024Sobrien unsigned long dynrel_count; 9359024Sobrien /* Read in dynamic relocs. This may be reloc_std_external or 9459024Sobrien reloc_ext_external. */ 95218822Sdim void * dynrel; 9659024Sobrien /* arelent structures for dynamic relocs. */ 9759024Sobrien arelent *canonical_dynrel; 9859024Sobrien}; 9959024Sobrien 10059024Sobrien/* The hash table of dynamic symbols is composed of two word entries. 10159024Sobrien See include/aout/sun4.h for details. */ 10259024Sobrien 10359024Sobrien#define HASH_ENTRY_SIZE (2 * BYTES_IN_WORD) 10459024Sobrien 10559024Sobrien/* Read in the basic dynamic information. This locates the __DYNAMIC 10659024Sobrien structure and uses it to find the dynamic_link structure. It 10759024Sobrien creates and saves a sunos_dynamic_info structure. If it can't find 10859024Sobrien __DYNAMIC, it sets the valid field of the sunos_dynamic_info 109130561Sobrien structure to FALSE to avoid doing this work again. */ 11059024Sobrien 111130561Sobrienstatic bfd_boolean 112218822Sdimsunos_read_dynamic_info (bfd *abfd) 11359024Sobrien{ 11459024Sobrien struct sunos_dynamic_info *info; 11559024Sobrien asection *dynsec; 11659024Sobrien bfd_vma dynoff; 11759024Sobrien struct external_sun4_dynamic dyninfo; 11859024Sobrien unsigned long dynver; 11959024Sobrien struct external_sun4_dynamic_link linkinfo; 12089857Sobrien bfd_size_type amt; 12159024Sobrien 122218822Sdim if (obj_aout_dynamic_info (abfd) != NULL) 123130561Sobrien return TRUE; 12459024Sobrien 12559024Sobrien if ((abfd->flags & DYNAMIC) == 0) 12659024Sobrien { 12759024Sobrien bfd_set_error (bfd_error_invalid_operation); 128130561Sobrien return FALSE; 12959024Sobrien } 13059024Sobrien 13189857Sobrien amt = sizeof (struct sunos_dynamic_info); 132218822Sdim info = bfd_zalloc (abfd, amt); 13359024Sobrien if (!info) 134130561Sobrien return FALSE; 135130561Sobrien info->valid = FALSE; 13659024Sobrien info->dynsym = NULL; 13759024Sobrien info->dynstr = NULL; 13859024Sobrien info->canonical_dynsym = NULL; 13959024Sobrien info->dynrel = NULL; 14059024Sobrien info->canonical_dynrel = NULL; 141218822Sdim obj_aout_dynamic_info (abfd) = (void *) info; 14259024Sobrien 14359024Sobrien /* This code used to look for the __DYNAMIC symbol to locate the dynamic 14459024Sobrien linking information. 14559024Sobrien However this inhibits recovering the dynamic symbols from a 14659024Sobrien stripped object file, so blindly assume that the dynamic linking 14759024Sobrien information is located at the start of the data section. 14859024Sobrien We could verify this assumption later by looking through the dynamic 14959024Sobrien symbols for the __DYNAMIC symbol. */ 15059024Sobrien if ((abfd->flags & DYNAMIC) == 0) 151130561Sobrien return TRUE; 152218822Sdim if (! bfd_get_section_contents (abfd, obj_datasec (abfd), (void *) &dyninfo, 15389857Sobrien (file_ptr) 0, 15489857Sobrien (bfd_size_type) sizeof dyninfo)) 155130561Sobrien return TRUE; 15659024Sobrien 15759024Sobrien dynver = GET_WORD (abfd, dyninfo.ld_version); 15859024Sobrien if (dynver != 2 && dynver != 3) 159130561Sobrien return TRUE; 16059024Sobrien 16159024Sobrien dynoff = GET_WORD (abfd, dyninfo.ld); 16259024Sobrien 16359024Sobrien /* dynoff is a virtual address. It is probably always in the .data 16459024Sobrien section, but this code should work even if it moves. */ 16559024Sobrien if (dynoff < bfd_get_section_vma (abfd, obj_datasec (abfd))) 16659024Sobrien dynsec = obj_textsec (abfd); 16759024Sobrien else 16859024Sobrien dynsec = obj_datasec (abfd); 16959024Sobrien dynoff -= bfd_get_section_vma (abfd, dynsec); 170218822Sdim if (dynoff > dynsec->size) 171130561Sobrien return TRUE; 17259024Sobrien 17359024Sobrien /* This executable appears to be dynamically linked in a way that we 17459024Sobrien can understand. */ 175218822Sdim if (! bfd_get_section_contents (abfd, dynsec, (void *) &linkinfo, 17689857Sobrien (file_ptr) dynoff, 17759024Sobrien (bfd_size_type) sizeof linkinfo)) 178130561Sobrien return TRUE; 17959024Sobrien 18059024Sobrien /* Swap in the dynamic link information. */ 18159024Sobrien info->dyninfo.ld_loaded = GET_WORD (abfd, linkinfo.ld_loaded); 18259024Sobrien info->dyninfo.ld_need = GET_WORD (abfd, linkinfo.ld_need); 18359024Sobrien info->dyninfo.ld_rules = GET_WORD (abfd, linkinfo.ld_rules); 18459024Sobrien info->dyninfo.ld_got = GET_WORD (abfd, linkinfo.ld_got); 18559024Sobrien info->dyninfo.ld_plt = GET_WORD (abfd, linkinfo.ld_plt); 18659024Sobrien info->dyninfo.ld_rel = GET_WORD (abfd, linkinfo.ld_rel); 18759024Sobrien info->dyninfo.ld_hash = GET_WORD (abfd, linkinfo.ld_hash); 18859024Sobrien info->dyninfo.ld_stab = GET_WORD (abfd, linkinfo.ld_stab); 18959024Sobrien info->dyninfo.ld_stab_hash = GET_WORD (abfd, linkinfo.ld_stab_hash); 19059024Sobrien info->dyninfo.ld_buckets = GET_WORD (abfd, linkinfo.ld_buckets); 19159024Sobrien info->dyninfo.ld_symbols = GET_WORD (abfd, linkinfo.ld_symbols); 19259024Sobrien info->dyninfo.ld_symb_size = GET_WORD (abfd, linkinfo.ld_symb_size); 19359024Sobrien info->dyninfo.ld_text = GET_WORD (abfd, linkinfo.ld_text); 19459024Sobrien info->dyninfo.ld_plt_sz = GET_WORD (abfd, linkinfo.ld_plt_sz); 19559024Sobrien 19659024Sobrien /* Reportedly the addresses need to be offset by the size of the 19759024Sobrien exec header in an NMAGIC file. */ 19859024Sobrien if (adata (abfd).magic == n_magic) 19959024Sobrien { 20059024Sobrien unsigned long exec_bytes_size = adata (abfd).exec_bytes_size; 20159024Sobrien 20259024Sobrien info->dyninfo.ld_need += exec_bytes_size; 20359024Sobrien info->dyninfo.ld_rules += exec_bytes_size; 20459024Sobrien info->dyninfo.ld_rel += exec_bytes_size; 20559024Sobrien info->dyninfo.ld_hash += exec_bytes_size; 20659024Sobrien info->dyninfo.ld_stab += exec_bytes_size; 20759024Sobrien info->dyninfo.ld_symbols += exec_bytes_size; 20859024Sobrien } 20959024Sobrien 21059024Sobrien /* The only way to get the size of the symbol information appears to 21159024Sobrien be to determine the distance between it and the string table. */ 21259024Sobrien info->dynsym_count = ((info->dyninfo.ld_symbols - info->dyninfo.ld_stab) 21359024Sobrien / EXTERNAL_NLIST_SIZE); 21459024Sobrien BFD_ASSERT (info->dynsym_count * EXTERNAL_NLIST_SIZE 21559024Sobrien == (unsigned long) (info->dyninfo.ld_symbols 21659024Sobrien - info->dyninfo.ld_stab)); 21759024Sobrien 21859024Sobrien /* Similarly, the relocs end at the hash table. */ 21959024Sobrien info->dynrel_count = ((info->dyninfo.ld_hash - info->dyninfo.ld_rel) 22059024Sobrien / obj_reloc_entry_size (abfd)); 22159024Sobrien BFD_ASSERT (info->dynrel_count * obj_reloc_entry_size (abfd) 22259024Sobrien == (unsigned long) (info->dyninfo.ld_hash 22359024Sobrien - info->dyninfo.ld_rel)); 22459024Sobrien 225130561Sobrien info->valid = TRUE; 22659024Sobrien 227130561Sobrien return TRUE; 22859024Sobrien} 22959024Sobrien 23059024Sobrien/* Return the amount of memory required for the dynamic symbols. */ 23159024Sobrien 23259024Sobrienstatic long 233218822Sdimsunos_get_dynamic_symtab_upper_bound (bfd *abfd) 23459024Sobrien{ 23559024Sobrien struct sunos_dynamic_info *info; 23659024Sobrien 23759024Sobrien if (! sunos_read_dynamic_info (abfd)) 23859024Sobrien return -1; 23959024Sobrien 24059024Sobrien info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); 24159024Sobrien if (! info->valid) 24259024Sobrien { 24359024Sobrien bfd_set_error (bfd_error_no_symbols); 24459024Sobrien return -1; 24559024Sobrien } 24659024Sobrien 24759024Sobrien return (info->dynsym_count + 1) * sizeof (asymbol *); 24859024Sobrien} 24959024Sobrien 25059024Sobrien/* Read the external dynamic symbols. */ 25159024Sobrien 252130561Sobrienstatic bfd_boolean 253218822Sdimsunos_slurp_dynamic_symtab (bfd *abfd) 25459024Sobrien{ 25559024Sobrien struct sunos_dynamic_info *info; 25689857Sobrien bfd_size_type amt; 25759024Sobrien 25859024Sobrien /* Get the general dynamic information. */ 25959024Sobrien if (obj_aout_dynamic_info (abfd) == NULL) 26059024Sobrien { 26159024Sobrien if (! sunos_read_dynamic_info (abfd)) 262130561Sobrien return FALSE; 26359024Sobrien } 26459024Sobrien 26559024Sobrien info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); 26659024Sobrien if (! info->valid) 26759024Sobrien { 26859024Sobrien bfd_set_error (bfd_error_no_symbols); 269130561Sobrien return FALSE; 27059024Sobrien } 27159024Sobrien 27259024Sobrien /* Get the dynamic nlist structures. */ 273218822Sdim if (info->dynsym == NULL) 27459024Sobrien { 27589857Sobrien amt = (bfd_size_type) info->dynsym_count * EXTERNAL_NLIST_SIZE; 276218822Sdim info->dynsym = bfd_alloc (abfd, amt); 27759024Sobrien if (info->dynsym == NULL && info->dynsym_count != 0) 278130561Sobrien return FALSE; 27989857Sobrien if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_stab, SEEK_SET) != 0 280218822Sdim || bfd_bread ((void *) info->dynsym, amt, abfd) != amt) 28159024Sobrien { 28259024Sobrien if (info->dynsym != NULL) 28359024Sobrien { 28459024Sobrien bfd_release (abfd, info->dynsym); 28559024Sobrien info->dynsym = NULL; 28659024Sobrien } 287130561Sobrien return FALSE; 28859024Sobrien } 28959024Sobrien } 29059024Sobrien 29159024Sobrien /* Get the dynamic strings. */ 292218822Sdim if (info->dynstr == NULL) 29359024Sobrien { 29489857Sobrien amt = info->dyninfo.ld_symb_size; 295218822Sdim info->dynstr = bfd_alloc (abfd, amt); 29659024Sobrien if (info->dynstr == NULL && info->dyninfo.ld_symb_size != 0) 297130561Sobrien return FALSE; 29889857Sobrien if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_symbols, SEEK_SET) != 0 299218822Sdim || bfd_bread ((void *) info->dynstr, amt, abfd) != amt) 30059024Sobrien { 30159024Sobrien if (info->dynstr != NULL) 30259024Sobrien { 30359024Sobrien bfd_release (abfd, info->dynstr); 30459024Sobrien info->dynstr = NULL; 30559024Sobrien } 306130561Sobrien return FALSE; 30759024Sobrien } 30859024Sobrien } 30959024Sobrien 310130561Sobrien return TRUE; 31159024Sobrien} 31259024Sobrien 31359024Sobrien/* Read in the dynamic symbols. */ 31459024Sobrien 31559024Sobrienstatic long 316218822Sdimsunos_canonicalize_dynamic_symtab (bfd *abfd, asymbol **storage) 31759024Sobrien{ 31859024Sobrien struct sunos_dynamic_info *info; 31959024Sobrien unsigned long i; 32059024Sobrien 32159024Sobrien if (! sunos_slurp_dynamic_symtab (abfd)) 32259024Sobrien return -1; 32359024Sobrien 32459024Sobrien info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); 32559024Sobrien 32659024Sobrien#ifdef CHECK_DYNAMIC_HASH 32759024Sobrien /* Check my understanding of the dynamic hash table by making sure 32859024Sobrien that each symbol can be located in the hash table. */ 32959024Sobrien { 33059024Sobrien bfd_size_type table_size; 33159024Sobrien bfd_byte *table; 33259024Sobrien bfd_size_type i; 33359024Sobrien 33459024Sobrien if (info->dyninfo.ld_buckets > info->dynsym_count) 33559024Sobrien abort (); 33659024Sobrien table_size = info->dyninfo.ld_stab - info->dyninfo.ld_hash; 337218822Sdim table = bfd_malloc (table_size); 33859024Sobrien if (table == NULL && table_size != 0) 33959024Sobrien abort (); 34089857Sobrien if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_hash, SEEK_SET) != 0 341218822Sdim || bfd_bread ((void *) table, table_size, abfd) != table_size) 34259024Sobrien abort (); 34359024Sobrien for (i = 0; i < info->dynsym_count; i++) 34459024Sobrien { 34559024Sobrien unsigned char *name; 34659024Sobrien unsigned long hash; 34759024Sobrien 34859024Sobrien name = ((unsigned char *) info->dynstr 34959024Sobrien + GET_WORD (abfd, info->dynsym[i].e_strx)); 35059024Sobrien hash = 0; 35159024Sobrien while (*name != '\0') 35259024Sobrien hash = (hash << 1) + *name++; 35359024Sobrien hash &= 0x7fffffff; 35459024Sobrien hash %= info->dyninfo.ld_buckets; 35559024Sobrien while (GET_WORD (abfd, table + hash * HASH_ENTRY_SIZE) != i) 35659024Sobrien { 35759024Sobrien hash = GET_WORD (abfd, 35859024Sobrien table + hash * HASH_ENTRY_SIZE + BYTES_IN_WORD); 35959024Sobrien if (hash == 0 || hash >= table_size / HASH_ENTRY_SIZE) 36059024Sobrien abort (); 36159024Sobrien } 36259024Sobrien } 36359024Sobrien free (table); 36459024Sobrien } 36559024Sobrien#endif /* CHECK_DYNAMIC_HASH */ 36659024Sobrien 36759024Sobrien /* Get the asymbol structures corresponding to the dynamic nlist 36859024Sobrien structures. */ 369218822Sdim if (info->canonical_dynsym == NULL) 37059024Sobrien { 37189857Sobrien bfd_size_type size; 37289857Sobrien bfd_size_type strsize = info->dyninfo.ld_symb_size; 37389857Sobrien 37489857Sobrien size = (bfd_size_type) info->dynsym_count * sizeof (aout_symbol_type); 375218822Sdim info->canonical_dynsym = bfd_alloc (abfd, size); 37659024Sobrien if (info->canonical_dynsym == NULL && info->dynsym_count != 0) 37759024Sobrien return -1; 37859024Sobrien 37959024Sobrien if (! aout_32_translate_symbol_table (abfd, info->canonical_dynsym, 38089857Sobrien info->dynsym, 38189857Sobrien (bfd_size_type) info->dynsym_count, 382130561Sobrien info->dynstr, strsize, TRUE)) 38359024Sobrien { 38459024Sobrien if (info->canonical_dynsym != NULL) 38559024Sobrien { 38659024Sobrien bfd_release (abfd, info->canonical_dynsym); 38759024Sobrien info->canonical_dynsym = NULL; 38859024Sobrien } 38959024Sobrien return -1; 39059024Sobrien } 39159024Sobrien } 39259024Sobrien 39359024Sobrien /* Return pointers to the dynamic asymbol structures. */ 39459024Sobrien for (i = 0; i < info->dynsym_count; i++) 39559024Sobrien *storage++ = (asymbol *) (info->canonical_dynsym + i); 39659024Sobrien *storage = NULL; 39759024Sobrien 39859024Sobrien return info->dynsym_count; 39959024Sobrien} 40059024Sobrien 40159024Sobrien/* Return the amount of memory required for the dynamic relocs. */ 40259024Sobrien 40359024Sobrienstatic long 404218822Sdimsunos_get_dynamic_reloc_upper_bound (bfd *abfd) 40559024Sobrien{ 40659024Sobrien struct sunos_dynamic_info *info; 40759024Sobrien 40859024Sobrien if (! sunos_read_dynamic_info (abfd)) 40959024Sobrien return -1; 41059024Sobrien 41159024Sobrien info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); 41259024Sobrien if (! info->valid) 41359024Sobrien { 41459024Sobrien bfd_set_error (bfd_error_no_symbols); 41559024Sobrien return -1; 41659024Sobrien } 41759024Sobrien 41859024Sobrien return (info->dynrel_count + 1) * sizeof (arelent *); 41959024Sobrien} 42059024Sobrien 42159024Sobrien/* Read in the dynamic relocs. */ 42259024Sobrien 42359024Sobrienstatic long 424218822Sdimsunos_canonicalize_dynamic_reloc (bfd *abfd, arelent **storage, asymbol **syms) 42559024Sobrien{ 42659024Sobrien struct sunos_dynamic_info *info; 42759024Sobrien unsigned long i; 42889857Sobrien bfd_size_type size; 42959024Sobrien 43059024Sobrien /* Get the general dynamic information. */ 431218822Sdim if (obj_aout_dynamic_info (abfd) == NULL) 43259024Sobrien { 43359024Sobrien if (! sunos_read_dynamic_info (abfd)) 43459024Sobrien return -1; 43559024Sobrien } 43659024Sobrien 43759024Sobrien info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); 43859024Sobrien if (! info->valid) 43959024Sobrien { 44059024Sobrien bfd_set_error (bfd_error_no_symbols); 44159024Sobrien return -1; 44259024Sobrien } 44359024Sobrien 44459024Sobrien /* Get the dynamic reloc information. */ 44559024Sobrien if (info->dynrel == NULL) 44659024Sobrien { 44789857Sobrien size = (bfd_size_type) info->dynrel_count * obj_reloc_entry_size (abfd); 448218822Sdim info->dynrel = bfd_alloc (abfd, size); 44989857Sobrien if (info->dynrel == NULL && size != 0) 45059024Sobrien return -1; 45189857Sobrien if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_rel, SEEK_SET) != 0 452218822Sdim || bfd_bread ((void *) info->dynrel, size, abfd) != size) 45359024Sobrien { 45459024Sobrien if (info->dynrel != NULL) 45559024Sobrien { 45659024Sobrien bfd_release (abfd, info->dynrel); 45759024Sobrien info->dynrel = NULL; 45859024Sobrien } 45959024Sobrien return -1; 46059024Sobrien } 46159024Sobrien } 46259024Sobrien 46359024Sobrien /* Get the arelent structures corresponding to the dynamic reloc 46459024Sobrien information. */ 465218822Sdim if (info->canonical_dynrel == NULL) 46659024Sobrien { 46759024Sobrien arelent *to; 46859024Sobrien 46989857Sobrien size = (bfd_size_type) info->dynrel_count * sizeof (arelent); 470218822Sdim info->canonical_dynrel = bfd_alloc (abfd, size); 47159024Sobrien if (info->canonical_dynrel == NULL && info->dynrel_count != 0) 47259024Sobrien return -1; 47384865Sobrien 47459024Sobrien to = info->canonical_dynrel; 47559024Sobrien 47659024Sobrien if (obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE) 47759024Sobrien { 478218822Sdim struct reloc_ext_external *p; 47959024Sobrien struct reloc_ext_external *pend; 48059024Sobrien 48159024Sobrien p = (struct reloc_ext_external *) info->dynrel; 48259024Sobrien pend = p + info->dynrel_count; 48359024Sobrien for (; p < pend; p++, to++) 484218822Sdim NAME (aout, swap_ext_reloc_in) (abfd, p, to, syms, 485218822Sdim (bfd_size_type) info->dynsym_count); 48659024Sobrien } 48759024Sobrien else 48859024Sobrien { 489218822Sdim struct reloc_std_external *p; 49059024Sobrien struct reloc_std_external *pend; 49159024Sobrien 49259024Sobrien p = (struct reloc_std_external *) info->dynrel; 49359024Sobrien pend = p + info->dynrel_count; 49459024Sobrien for (; p < pend; p++, to++) 495218822Sdim NAME (aout, swap_std_reloc_in) (abfd, p, to, syms, 496218822Sdim (bfd_size_type) info->dynsym_count); 49759024Sobrien } 49859024Sobrien } 49959024Sobrien 50059024Sobrien /* Return pointers to the dynamic arelent structures. */ 50159024Sobrien for (i = 0; i < info->dynrel_count; i++) 50259024Sobrien *storage++ = info->canonical_dynrel + i; 50359024Sobrien *storage = NULL; 50459024Sobrien 50559024Sobrien return info->dynrel_count; 50659024Sobrien} 50759024Sobrien 50859024Sobrien/* Code to handle linking of SunOS shared libraries. */ 50959024Sobrien 51059024Sobrien/* A SPARC procedure linkage table entry is 12 bytes. The first entry 51159024Sobrien in the table is a jump which is filled in by the runtime linker. 51259024Sobrien The remaining entries are branches back to the first entry, 51359024Sobrien followed by an index into the relocation table encoded to look like 51459024Sobrien a sethi of %g0. */ 51559024Sobrien 51659024Sobrien#define SPARC_PLT_ENTRY_SIZE (12) 51759024Sobrien 51859024Sobrienstatic const bfd_byte sparc_plt_first_entry[SPARC_PLT_ENTRY_SIZE] = 51959024Sobrien{ 52059024Sobrien /* sethi %hi(0),%g1; address filled in by runtime linker. */ 52159024Sobrien 0x3, 0, 0, 0, 52259024Sobrien /* jmp %g1; offset filled in by runtime linker. */ 52359024Sobrien 0x81, 0xc0, 0x60, 0, 52459024Sobrien /* nop */ 52559024Sobrien 0x1, 0, 0, 0 52659024Sobrien}; 52759024Sobrien 52859024Sobrien/* save %sp, -96, %sp */ 52989857Sobrien#define SPARC_PLT_ENTRY_WORD0 ((bfd_vma) 0x9de3bfa0) 53059024Sobrien/* call; address filled in later. */ 53189857Sobrien#define SPARC_PLT_ENTRY_WORD1 ((bfd_vma) 0x40000000) 53259024Sobrien/* sethi; reloc index filled in later. */ 53389857Sobrien#define SPARC_PLT_ENTRY_WORD2 ((bfd_vma) 0x01000000) 53459024Sobrien 53559024Sobrien/* This sequence is used when for the jump table entry to a defined 53659024Sobrien symbol in a complete executable. It is used when linking PIC 53759024Sobrien compiled code which is not being put into a shared library. */ 53859024Sobrien/* sethi <address to be filled in later>, %g1 */ 53989857Sobrien#define SPARC_PLT_PIC_WORD0 ((bfd_vma) 0x03000000) 54059024Sobrien/* jmp %g1 + <address to be filled in later> */ 54189857Sobrien#define SPARC_PLT_PIC_WORD1 ((bfd_vma) 0x81c06000) 54259024Sobrien/* nop */ 54389857Sobrien#define SPARC_PLT_PIC_WORD2 ((bfd_vma) 0x01000000) 54459024Sobrien 54559024Sobrien/* An m68k procedure linkage table entry is 8 bytes. The first entry 54659024Sobrien in the table is a jump which is filled in the by the runtime 54759024Sobrien linker. The remaining entries are branches back to the first 54859024Sobrien entry, followed by a two byte index into the relocation table. */ 54959024Sobrien 55059024Sobrien#define M68K_PLT_ENTRY_SIZE (8) 55159024Sobrien 55259024Sobrienstatic const bfd_byte m68k_plt_first_entry[M68K_PLT_ENTRY_SIZE] = 55359024Sobrien{ 55459024Sobrien /* jmps @# */ 55559024Sobrien 0x4e, 0xf9, 55659024Sobrien /* Filled in by runtime linker with a magic address. */ 55759024Sobrien 0, 0, 0, 0, 55859024Sobrien /* Not used? */ 55959024Sobrien 0, 0 56059024Sobrien}; 56159024Sobrien 56259024Sobrien/* bsrl */ 56389857Sobrien#define M68K_PLT_ENTRY_WORD0 ((bfd_vma) 0x61ff) 56459024Sobrien/* Remaining words filled in later. */ 56559024Sobrien 56659024Sobrien/* An entry in the SunOS linker hash table. */ 56759024Sobrien 56859024Sobrienstruct sunos_link_hash_entry 56959024Sobrien{ 57059024Sobrien struct aout_link_hash_entry root; 57159024Sobrien 57259024Sobrien /* If this is a dynamic symbol, this is its index into the dynamic 57359024Sobrien symbol table. This is initialized to -1. As the linker looks at 57459024Sobrien the input files, it changes this to -2 if it will be added to the 57559024Sobrien dynamic symbol table. After all the input files have been seen, 57659024Sobrien the linker will know whether to build a dynamic symbol table; if 57759024Sobrien it does build one, this becomes the index into the table. */ 57859024Sobrien long dynindx; 57959024Sobrien 58059024Sobrien /* If this is a dynamic symbol, this is the index of the name in the 58159024Sobrien dynamic symbol string table. */ 58259024Sobrien long dynstr_index; 58359024Sobrien 58459024Sobrien /* The offset into the global offset table used for this symbol. If 58559024Sobrien the symbol does not require a GOT entry, this is 0. */ 58659024Sobrien bfd_vma got_offset; 58759024Sobrien 58859024Sobrien /* The offset into the procedure linkage table used for this symbol. 58959024Sobrien If the symbol does not require a PLT entry, this is 0. */ 59059024Sobrien bfd_vma plt_offset; 59159024Sobrien 59259024Sobrien /* Some linker flags. */ 59359024Sobrien unsigned char flags; 59459024Sobrien /* Symbol is referenced by a regular object. */ 59559024Sobrien#define SUNOS_REF_REGULAR 01 59659024Sobrien /* Symbol is defined by a regular object. */ 59759024Sobrien#define SUNOS_DEF_REGULAR 02 59859024Sobrien /* Symbol is referenced by a dynamic object. */ 59959024Sobrien#define SUNOS_REF_DYNAMIC 04 60059024Sobrien /* Symbol is defined by a dynamic object. */ 60159024Sobrien#define SUNOS_DEF_DYNAMIC 010 60259024Sobrien /* Symbol is a constructor symbol in a regular object. */ 60359024Sobrien#define SUNOS_CONSTRUCTOR 020 60459024Sobrien}; 60559024Sobrien 60659024Sobrien/* The SunOS linker hash table. */ 60759024Sobrien 60859024Sobrienstruct sunos_link_hash_table 60959024Sobrien{ 61059024Sobrien struct aout_link_hash_table root; 61159024Sobrien 61259024Sobrien /* The object which holds the dynamic sections. */ 61359024Sobrien bfd *dynobj; 61459024Sobrien 61559024Sobrien /* Whether we have created the dynamic sections. */ 616130561Sobrien bfd_boolean dynamic_sections_created; 61759024Sobrien 61859024Sobrien /* Whether we need the dynamic sections. */ 619130561Sobrien bfd_boolean dynamic_sections_needed; 62059024Sobrien 62159024Sobrien /* Whether we need the .got table. */ 622130561Sobrien bfd_boolean got_needed; 62359024Sobrien 62459024Sobrien /* The number of dynamic symbols. */ 62559024Sobrien size_t dynsymcount; 62659024Sobrien 62759024Sobrien /* The number of buckets in the hash table. */ 62859024Sobrien size_t bucketcount; 62959024Sobrien 63059024Sobrien /* The list of dynamic objects needed by dynamic objects included in 63159024Sobrien the link. */ 63259024Sobrien struct bfd_link_needed_list *needed; 63359024Sobrien 63459024Sobrien /* The offset of __GLOBAL_OFFSET_TABLE_ into the .got section. */ 63559024Sobrien bfd_vma got_base; 63659024Sobrien}; 63759024Sobrien 63859024Sobrien/* Routine to create an entry in an SunOS link hash table. */ 63959024Sobrien 64059024Sobrienstatic struct bfd_hash_entry * 641218822Sdimsunos_link_hash_newfunc (struct bfd_hash_entry *entry, 642218822Sdim struct bfd_hash_table *table, 643218822Sdim const char *string) 64459024Sobrien{ 64559024Sobrien struct sunos_link_hash_entry *ret = (struct sunos_link_hash_entry *) entry; 64659024Sobrien 64759024Sobrien /* Allocate the structure if it has not already been allocated by a 64859024Sobrien subclass. */ 649218822Sdim if (ret == NULL) 650218822Sdim ret = bfd_hash_allocate (table, sizeof (* ret)); 651218822Sdim if (ret == NULL) 652218822Sdim return NULL; 65359024Sobrien 65459024Sobrien /* Call the allocation method of the superclass. */ 65559024Sobrien ret = ((struct sunos_link_hash_entry *) 656218822Sdim NAME (aout, link_hash_newfunc) ((struct bfd_hash_entry *) ret, 657218822Sdim table, string)); 65859024Sobrien if (ret != NULL) 65959024Sobrien { 66059024Sobrien /* Set local fields. */ 66159024Sobrien ret->dynindx = -1; 66259024Sobrien ret->dynstr_index = -1; 66359024Sobrien ret->got_offset = 0; 66459024Sobrien ret->plt_offset = 0; 66559024Sobrien ret->flags = 0; 66659024Sobrien } 66759024Sobrien 66859024Sobrien return (struct bfd_hash_entry *) ret; 66959024Sobrien} 67059024Sobrien 67159024Sobrien/* Create a SunOS link hash table. */ 67259024Sobrien 67359024Sobrienstatic struct bfd_link_hash_table * 674218822Sdimsunos_link_hash_table_create (bfd *abfd) 67559024Sobrien{ 67659024Sobrien struct sunos_link_hash_table *ret; 67789857Sobrien bfd_size_type amt = sizeof (struct sunos_link_hash_table); 67859024Sobrien 679218822Sdim ret = bfd_malloc (amt); 680218822Sdim if (ret == NULL) 681218822Sdim return NULL; 682218822Sdim if (!NAME (aout, link_hash_table_init) (&ret->root, abfd, 683218822Sdim sunos_link_hash_newfunc, 684218822Sdim sizeof (struct sunos_link_hash_entry))) 68559024Sobrien { 686104834Sobrien free (ret); 687218822Sdim return NULL; 68859024Sobrien } 68959024Sobrien 69059024Sobrien ret->dynobj = NULL; 691130561Sobrien ret->dynamic_sections_created = FALSE; 692130561Sobrien ret->dynamic_sections_needed = FALSE; 693130561Sobrien ret->got_needed = FALSE; 69459024Sobrien ret->dynsymcount = 0; 69559024Sobrien ret->bucketcount = 0; 69659024Sobrien ret->needed = NULL; 69759024Sobrien ret->got_base = 0; 69859024Sobrien 69959024Sobrien return &ret->root.root; 70059024Sobrien} 70159024Sobrien 70259024Sobrien/* Look up an entry in an SunOS link hash table. */ 70359024Sobrien 70459024Sobrien#define sunos_link_hash_lookup(table, string, create, copy, follow) \ 70559024Sobrien ((struct sunos_link_hash_entry *) \ 70659024Sobrien aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\ 70759024Sobrien (follow))) 70859024Sobrien 70959024Sobrien/* Traverse a SunOS link hash table. */ 71059024Sobrien 71159024Sobrien#define sunos_link_hash_traverse(table, func, info) \ 71259024Sobrien (aout_link_hash_traverse \ 71359024Sobrien (&(table)->root, \ 714218822Sdim (bfd_boolean (*) (struct aout_link_hash_entry *, void *)) (func), \ 71559024Sobrien (info))) 71659024Sobrien 71759024Sobrien/* Get the SunOS link hash table from the info structure. This is 71859024Sobrien just a cast. */ 71959024Sobrien 72059024Sobrien#define sunos_hash_table(p) ((struct sunos_link_hash_table *) ((p)->hash)) 72159024Sobrien 72259024Sobrien/* Create the dynamic sections needed if we are linking against a 72359024Sobrien dynamic object, or if we are linking PIC compiled code. ABFD is a 72459024Sobrien bfd we can attach the dynamic sections to. The linker script will 72559024Sobrien look for these special sections names and put them in the right 72659024Sobrien place in the output file. See include/aout/sun4.h for more details 72759024Sobrien of the dynamic linking information. */ 72859024Sobrien 729130561Sobrienstatic bfd_boolean 730218822Sdimsunos_create_dynamic_sections (bfd *abfd, 731218822Sdim struct bfd_link_info *info, 732218822Sdim bfd_boolean needed) 73359024Sobrien{ 73459024Sobrien asection *s; 73559024Sobrien 73659024Sobrien if (! sunos_hash_table (info)->dynamic_sections_created) 73759024Sobrien { 73859024Sobrien flagword flags; 73959024Sobrien 74059024Sobrien sunos_hash_table (info)->dynobj = abfd; 74159024Sobrien 74259024Sobrien flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY 74359024Sobrien | SEC_LINKER_CREATED); 74459024Sobrien 74559024Sobrien /* The .dynamic section holds the basic dynamic information: the 74659024Sobrien sun4_dynamic structure, the dynamic debugger information, and 74759024Sobrien the sun4_dynamic_link structure. */ 748218822Sdim s = bfd_make_section_with_flags (abfd, ".dynamic", flags); 74959024Sobrien if (s == NULL 75059024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 751130561Sobrien return FALSE; 75259024Sobrien 75359024Sobrien /* The .got section holds the global offset table. The address 75459024Sobrien is put in the ld_got field. */ 755218822Sdim s = bfd_make_section_with_flags (abfd, ".got", flags); 75659024Sobrien if (s == NULL 75759024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 758130561Sobrien return FALSE; 75959024Sobrien 76059024Sobrien /* The .plt section holds the procedure linkage table. The 76159024Sobrien address is put in the ld_plt field. */ 762218822Sdim s = bfd_make_section_with_flags (abfd, ".plt", flags | SEC_CODE); 76359024Sobrien if (s == NULL 76459024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 765130561Sobrien return FALSE; 76659024Sobrien 76759024Sobrien /* The .dynrel section holds the dynamic relocs. The address is 76859024Sobrien put in the ld_rel field. */ 769218822Sdim s = bfd_make_section_with_flags (abfd, ".dynrel", flags | SEC_READONLY); 77059024Sobrien if (s == NULL 77159024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 772130561Sobrien return FALSE; 77359024Sobrien 77459024Sobrien /* The .hash section holds the dynamic hash table. The address 77559024Sobrien is put in the ld_hash field. */ 776218822Sdim s = bfd_make_section_with_flags (abfd, ".hash", flags | SEC_READONLY); 77759024Sobrien if (s == NULL 77859024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 779130561Sobrien return FALSE; 78059024Sobrien 78159024Sobrien /* The .dynsym section holds the dynamic symbols. The address 78259024Sobrien is put in the ld_stab field. */ 783218822Sdim s = bfd_make_section_with_flags (abfd, ".dynsym", flags | SEC_READONLY); 78459024Sobrien if (s == NULL 78559024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 786130561Sobrien return FALSE; 78759024Sobrien 78859024Sobrien /* The .dynstr section holds the dynamic symbol string table. 78959024Sobrien The address is put in the ld_symbols field. */ 790218822Sdim s = bfd_make_section_with_flags (abfd, ".dynstr", flags | SEC_READONLY); 79159024Sobrien if (s == NULL 79259024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 793130561Sobrien return FALSE; 79459024Sobrien 795130561Sobrien sunos_hash_table (info)->dynamic_sections_created = TRUE; 79659024Sobrien } 79759024Sobrien 79859024Sobrien if ((needed && ! sunos_hash_table (info)->dynamic_sections_needed) 79959024Sobrien || info->shared) 80059024Sobrien { 80159024Sobrien bfd *dynobj; 80259024Sobrien 80359024Sobrien dynobj = sunos_hash_table (info)->dynobj; 80459024Sobrien 80559024Sobrien s = bfd_get_section_by_name (dynobj, ".got"); 806218822Sdim if (s->size == 0) 807218822Sdim s->size = BYTES_IN_WORD; 80859024Sobrien 809130561Sobrien sunos_hash_table (info)->dynamic_sections_needed = TRUE; 810130561Sobrien sunos_hash_table (info)->got_needed = TRUE; 81159024Sobrien } 81259024Sobrien 813130561Sobrien return TRUE; 81459024Sobrien} 81559024Sobrien 81659024Sobrien/* Add dynamic symbols during a link. This is called by the a.out 81759024Sobrien backend linker for each object it encounters. */ 81859024Sobrien 819130561Sobrienstatic bfd_boolean 820218822Sdimsunos_add_dynamic_symbols (bfd *abfd, 821218822Sdim struct bfd_link_info *info, 822218822Sdim struct external_nlist **symsp, 823218822Sdim bfd_size_type *sym_countp, 824218822Sdim char **stringsp) 82559024Sobrien{ 82659024Sobrien bfd *dynobj; 82759024Sobrien struct sunos_dynamic_info *dinfo; 82859024Sobrien unsigned long need; 82959024Sobrien 83059024Sobrien /* Make sure we have all the required sections. */ 83159024Sobrien if (info->hash->creator == abfd->xvec) 83259024Sobrien { 83359024Sobrien if (! sunos_create_dynamic_sections (abfd, info, 834130561Sobrien ((abfd->flags & DYNAMIC) != 0 835130561Sobrien && !info->relocatable))) 836130561Sobrien return FALSE; 83759024Sobrien } 83859024Sobrien 83959024Sobrien /* There is nothing else to do for a normal object. */ 84059024Sobrien if ((abfd->flags & DYNAMIC) == 0) 841130561Sobrien return TRUE; 84259024Sobrien 84359024Sobrien dynobj = sunos_hash_table (info)->dynobj; 84459024Sobrien 84559024Sobrien /* We do not want to include the sections in a dynamic object in the 84659024Sobrien output file. We hack by simply clobbering the list of sections 84759024Sobrien in the BFD. This could be handled more cleanly by, say, a new 84859024Sobrien section flag; the existing SEC_NEVER_LOAD flag is not the one we 84959024Sobrien want, because that one still implies that the section takes up 85059024Sobrien space in the output file. If this is the first object we have 85159024Sobrien seen, we must preserve the dynamic sections we just created. */ 852218822Sdim if (abfd != dynobj) 853218822Sdim abfd->sections = NULL; 854218822Sdim else 85559024Sobrien { 856218822Sdim asection *s; 857218822Sdim 858218822Sdim for (s = abfd->sections; s != NULL; s = s->next) 859218822Sdim { 860218822Sdim if ((s->flags & SEC_LINKER_CREATED) == 0) 861218822Sdim bfd_section_list_remove (abfd, s); 862218822Sdim } 86359024Sobrien } 86459024Sobrien 86559024Sobrien /* The native linker seems to just ignore dynamic objects when -r is 86659024Sobrien used. */ 867130561Sobrien if (info->relocatable) 868130561Sobrien return TRUE; 86959024Sobrien 87059024Sobrien /* There's no hope of using a dynamic object which does not exactly 87159024Sobrien match the format of the output file. */ 87259024Sobrien if (info->hash->creator != abfd->xvec) 87359024Sobrien { 87459024Sobrien bfd_set_error (bfd_error_invalid_operation); 875130561Sobrien return FALSE; 87659024Sobrien } 87759024Sobrien 87859024Sobrien /* Make sure we have a .need and a .rules sections. These are only 87959024Sobrien needed if there really is a dynamic object in the link, so they 88059024Sobrien are not added by sunos_create_dynamic_sections. */ 88159024Sobrien if (bfd_get_section_by_name (dynobj, ".need") == NULL) 88259024Sobrien { 88359024Sobrien /* The .need section holds the list of names of shared objets 88459024Sobrien which must be included at runtime. The address of this 88559024Sobrien section is put in the ld_need field. */ 886218822Sdim flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS 887218822Sdim | SEC_IN_MEMORY | SEC_READONLY); 888218822Sdim asection *s = bfd_make_section_with_flags (dynobj, ".need", flags); 88959024Sobrien if (s == NULL 89059024Sobrien || ! bfd_set_section_alignment (dynobj, s, 2)) 891130561Sobrien return FALSE; 89259024Sobrien } 89359024Sobrien 89459024Sobrien if (bfd_get_section_by_name (dynobj, ".rules") == NULL) 89559024Sobrien { 89659024Sobrien /* The .rules section holds the path to search for shared 89759024Sobrien objects. The address of this section is put in the ld_rules 89859024Sobrien field. */ 899218822Sdim flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS 900218822Sdim | SEC_IN_MEMORY | SEC_READONLY); 901218822Sdim asection *s = bfd_make_section_with_flags (dynobj, ".rules", flags); 90259024Sobrien if (s == NULL 90359024Sobrien || ! bfd_set_section_alignment (dynobj, s, 2)) 904130561Sobrien return FALSE; 90559024Sobrien } 90659024Sobrien 90759024Sobrien /* Pick up the dynamic symbols and return them to the caller. */ 90859024Sobrien if (! sunos_slurp_dynamic_symtab (abfd)) 909130561Sobrien return FALSE; 91059024Sobrien 91159024Sobrien dinfo = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); 91259024Sobrien *symsp = dinfo->dynsym; 91359024Sobrien *sym_countp = dinfo->dynsym_count; 91459024Sobrien *stringsp = dinfo->dynstr; 91559024Sobrien 91659024Sobrien /* Record information about any other objects needed by this one. */ 91759024Sobrien need = dinfo->dyninfo.ld_need; 91859024Sobrien while (need != 0) 91959024Sobrien { 92059024Sobrien bfd_byte buf[16]; 92159024Sobrien unsigned long name, flags; 92259024Sobrien unsigned short major_vno, minor_vno; 92359024Sobrien struct bfd_link_needed_list *needed, **pp; 92459024Sobrien char *namebuf, *p; 92589857Sobrien bfd_size_type alc; 92659024Sobrien bfd_byte b; 92759024Sobrien char *namecopy; 92859024Sobrien 92989857Sobrien if (bfd_seek (abfd, (file_ptr) need, SEEK_SET) != 0 93089857Sobrien || bfd_bread (buf, (bfd_size_type) 16, abfd) != 16) 931130561Sobrien return FALSE; 93259024Sobrien 93359024Sobrien /* For the format of an ld_need entry, see aout/sun4.h. We 934130561Sobrien should probably define structs for this manipulation. */ 93559024Sobrien name = bfd_get_32 (abfd, buf); 93659024Sobrien flags = bfd_get_32 (abfd, buf + 4); 93789857Sobrien major_vno = (unsigned short) bfd_get_16 (abfd, buf + 8); 93889857Sobrien minor_vno = (unsigned short) bfd_get_16 (abfd, buf + 10); 93959024Sobrien need = bfd_get_32 (abfd, buf + 12); 94059024Sobrien 94189857Sobrien alc = sizeof (struct bfd_link_needed_list); 942218822Sdim needed = bfd_alloc (abfd, alc); 94359024Sobrien if (needed == NULL) 944130561Sobrien return FALSE; 94559024Sobrien needed->by = abfd; 94659024Sobrien 94759024Sobrien /* We return the name as [-l]name[.maj][.min]. */ 94859024Sobrien alc = 30; 949218822Sdim namebuf = bfd_malloc (alc + 1); 95059024Sobrien if (namebuf == NULL) 951130561Sobrien return FALSE; 95259024Sobrien p = namebuf; 95359024Sobrien 95459024Sobrien if ((flags & 0x80000000) != 0) 95559024Sobrien { 95659024Sobrien *p++ = '-'; 95759024Sobrien *p++ = 'l'; 95859024Sobrien } 95989857Sobrien if (bfd_seek (abfd, (file_ptr) name, SEEK_SET) != 0) 96059024Sobrien { 96159024Sobrien free (namebuf); 962130561Sobrien return FALSE; 96359024Sobrien } 96459024Sobrien 96559024Sobrien do 96659024Sobrien { 96789857Sobrien if (bfd_bread (&b, (bfd_size_type) 1, abfd) != 1) 96859024Sobrien { 96959024Sobrien free (namebuf); 970130561Sobrien return FALSE; 97159024Sobrien } 97259024Sobrien 97389857Sobrien if ((bfd_size_type) (p - namebuf) >= alc) 97459024Sobrien { 97559024Sobrien char *n; 97659024Sobrien 97759024Sobrien alc *= 2; 978218822Sdim n = bfd_realloc (namebuf, alc + 1); 97959024Sobrien if (n == NULL) 98059024Sobrien { 98159024Sobrien free (namebuf); 982130561Sobrien return FALSE; 98359024Sobrien } 98459024Sobrien p = n + (p - namebuf); 98559024Sobrien namebuf = n; 98659024Sobrien } 98759024Sobrien 98859024Sobrien *p++ = b; 98959024Sobrien } 99059024Sobrien while (b != '\0'); 99159024Sobrien 99259024Sobrien if (major_vno == 0) 99359024Sobrien *p = '\0'; 99459024Sobrien else 99559024Sobrien { 99659024Sobrien char majbuf[30]; 99759024Sobrien char minbuf[30]; 99859024Sobrien 99959024Sobrien sprintf (majbuf, ".%d", major_vno); 100059024Sobrien if (minor_vno == 0) 100159024Sobrien minbuf[0] = '\0'; 100259024Sobrien else 100359024Sobrien sprintf (minbuf, ".%d", minor_vno); 100459024Sobrien 100559024Sobrien if ((p - namebuf) + strlen (majbuf) + strlen (minbuf) >= alc) 100659024Sobrien { 100759024Sobrien char *n; 100859024Sobrien 100959024Sobrien alc = (p - namebuf) + strlen (majbuf) + strlen (minbuf); 1010218822Sdim n = bfd_realloc (namebuf, alc + 1); 101159024Sobrien if (n == NULL) 101259024Sobrien { 101359024Sobrien free (namebuf); 1014130561Sobrien return FALSE; 101559024Sobrien } 101659024Sobrien p = n + (p - namebuf); 101759024Sobrien namebuf = n; 101859024Sobrien } 101959024Sobrien 102059024Sobrien strcpy (p, majbuf); 102159024Sobrien strcat (p, minbuf); 102259024Sobrien } 102359024Sobrien 102489857Sobrien namecopy = bfd_alloc (abfd, (bfd_size_type) strlen (namebuf) + 1); 102559024Sobrien if (namecopy == NULL) 102659024Sobrien { 102759024Sobrien free (namebuf); 1028130561Sobrien return FALSE; 102959024Sobrien } 103059024Sobrien strcpy (namecopy, namebuf); 103159024Sobrien free (namebuf); 103259024Sobrien needed->name = namecopy; 103359024Sobrien 103459024Sobrien needed->next = NULL; 103559024Sobrien 103659024Sobrien for (pp = &sunos_hash_table (info)->needed; 103759024Sobrien *pp != NULL; 103859024Sobrien pp = &(*pp)->next) 103959024Sobrien ; 104059024Sobrien *pp = needed; 104159024Sobrien } 104259024Sobrien 1043130561Sobrien return TRUE; 104459024Sobrien} 104559024Sobrien 104659024Sobrien/* Function to add a single symbol to the linker hash table. This is 104759024Sobrien a wrapper around _bfd_generic_link_add_one_symbol which handles the 104859024Sobrien tweaking needed for dynamic linking support. */ 104959024Sobrien 1050130561Sobrienstatic bfd_boolean 1051218822Sdimsunos_add_one_symbol (struct bfd_link_info *info, 1052218822Sdim bfd *abfd, 1053218822Sdim const char *name, 1054218822Sdim flagword flags, 1055218822Sdim asection *section, 1056218822Sdim bfd_vma value, 1057218822Sdim const char *string, 1058218822Sdim bfd_boolean copy, 1059218822Sdim bfd_boolean collect, 1060218822Sdim struct bfd_link_hash_entry **hashp) 106159024Sobrien{ 106259024Sobrien struct sunos_link_hash_entry *h; 106359024Sobrien int new_flag; 106459024Sobrien 106559024Sobrien if ((flags & (BSF_INDIRECT | BSF_WARNING | BSF_CONSTRUCTOR)) != 0 106659024Sobrien || ! bfd_is_und_section (section)) 1067130561Sobrien h = sunos_link_hash_lookup (sunos_hash_table (info), name, TRUE, copy, 1068130561Sobrien FALSE); 106959024Sobrien else 107059024Sobrien h = ((struct sunos_link_hash_entry *) 1071130561Sobrien bfd_wrapped_link_hash_lookup (abfd, info, name, TRUE, copy, FALSE)); 107259024Sobrien if (h == NULL) 1073130561Sobrien return FALSE; 107459024Sobrien 107559024Sobrien if (hashp != NULL) 107659024Sobrien *hashp = (struct bfd_link_hash_entry *) h; 107759024Sobrien 107859024Sobrien /* Treat a common symbol in a dynamic object as defined in the .bss 107959024Sobrien section of the dynamic object. We don't want to allocate space 108059024Sobrien for it in our process image. */ 108159024Sobrien if ((abfd->flags & DYNAMIC) != 0 108259024Sobrien && bfd_is_com_section (section)) 108359024Sobrien section = obj_bsssec (abfd); 108459024Sobrien 108559024Sobrien if (! bfd_is_und_section (section) 108659024Sobrien && h->root.root.type != bfd_link_hash_new 108759024Sobrien && h->root.root.type != bfd_link_hash_undefined 108859024Sobrien && h->root.root.type != bfd_link_hash_defweak) 108959024Sobrien { 109059024Sobrien /* We are defining the symbol, and it is already defined. This 109159024Sobrien is a potential multiple definition error. */ 109259024Sobrien if ((abfd->flags & DYNAMIC) != 0) 109359024Sobrien { 109459024Sobrien /* The definition we are adding is from a dynamic object. 109559024Sobrien We do not want this new definition to override the 109659024Sobrien existing definition, so we pretend it is just a 109759024Sobrien reference. */ 109859024Sobrien section = bfd_und_section_ptr; 109959024Sobrien } 110059024Sobrien else if (h->root.root.type == bfd_link_hash_defined 110159024Sobrien && h->root.root.u.def.section->owner != NULL 110259024Sobrien && (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0) 110359024Sobrien { 110459024Sobrien /* The existing definition is from a dynamic object. We 110559024Sobrien want to override it with the definition we just found. 110659024Sobrien Clobber the existing definition. */ 110759024Sobrien h->root.root.type = bfd_link_hash_undefined; 110859024Sobrien h->root.root.u.undef.abfd = h->root.root.u.def.section->owner; 110959024Sobrien } 111059024Sobrien else if (h->root.root.type == bfd_link_hash_common 111159024Sobrien && (h->root.root.u.c.p->section->owner->flags & DYNAMIC) != 0) 111259024Sobrien { 111359024Sobrien /* The existing definition is from a dynamic object. We 111459024Sobrien want to override it with the definition we just found. 111559024Sobrien Clobber the existing definition. We can't set it to new, 111659024Sobrien because it is on the undefined list. */ 111759024Sobrien h->root.root.type = bfd_link_hash_undefined; 111859024Sobrien h->root.root.u.undef.abfd = h->root.root.u.c.p->section->owner; 111959024Sobrien } 112059024Sobrien } 112159024Sobrien 112259024Sobrien if ((abfd->flags & DYNAMIC) != 0 112359024Sobrien && abfd->xvec == info->hash->creator 112459024Sobrien && (h->flags & SUNOS_CONSTRUCTOR) != 0) 1125218822Sdim /* The existing symbol is a constructor symbol, and this symbol 1126218822Sdim is from a dynamic object. A constructor symbol is actually a 1127218822Sdim definition, although the type will be bfd_link_hash_undefined 1128218822Sdim at this point. We want to ignore the definition from the 1129218822Sdim dynamic object. */ 1130218822Sdim section = bfd_und_section_ptr; 113159024Sobrien else if ((flags & BSF_CONSTRUCTOR) != 0 113259024Sobrien && (abfd->flags & DYNAMIC) == 0 113359024Sobrien && h->root.root.type == bfd_link_hash_defined 113459024Sobrien && h->root.root.u.def.section->owner != NULL 113559024Sobrien && (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0) 1136218822Sdim /* The existing symbol is defined by a dynamic object, and this 1137218822Sdim is a constructor symbol. As above, we want to force the use 1138218822Sdim of the constructor symbol from the regular object. */ 1139218822Sdim h->root.root.type = bfd_link_hash_new; 114059024Sobrien 114159024Sobrien /* Do the usual procedure for adding a symbol. */ 114259024Sobrien if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, 114359024Sobrien value, string, copy, collect, 114459024Sobrien hashp)) 1145130561Sobrien return FALSE; 114659024Sobrien 114759024Sobrien if (abfd->xvec == info->hash->creator) 114859024Sobrien { 114959024Sobrien /* Set a flag in the hash table entry indicating the type of 115059024Sobrien reference or definition we just found. Keep a count of the 115159024Sobrien number of dynamic symbols we find. A dynamic symbol is one 115259024Sobrien which is referenced or defined by both a regular object and a 115359024Sobrien shared object. */ 115459024Sobrien if ((abfd->flags & DYNAMIC) == 0) 115559024Sobrien { 115659024Sobrien if (bfd_is_und_section (section)) 115759024Sobrien new_flag = SUNOS_REF_REGULAR; 115859024Sobrien else 115959024Sobrien new_flag = SUNOS_DEF_REGULAR; 116059024Sobrien } 116159024Sobrien else 116259024Sobrien { 116359024Sobrien if (bfd_is_und_section (section)) 116459024Sobrien new_flag = SUNOS_REF_DYNAMIC; 116559024Sobrien else 116659024Sobrien new_flag = SUNOS_DEF_DYNAMIC; 116759024Sobrien } 116859024Sobrien h->flags |= new_flag; 116959024Sobrien 117059024Sobrien if (h->dynindx == -1 117159024Sobrien && (h->flags & (SUNOS_DEF_REGULAR | SUNOS_REF_REGULAR)) != 0) 117259024Sobrien { 117359024Sobrien ++sunos_hash_table (info)->dynsymcount; 117459024Sobrien h->dynindx = -2; 117559024Sobrien } 117659024Sobrien 117759024Sobrien if ((flags & BSF_CONSTRUCTOR) != 0 117859024Sobrien && (abfd->flags & DYNAMIC) == 0) 117959024Sobrien h->flags |= SUNOS_CONSTRUCTOR; 118059024Sobrien } 118159024Sobrien 1182130561Sobrien return TRUE; 118359024Sobrien} 118459024Sobrien 1185218822Sdimextern const bfd_target MY (vec); 1186218822Sdim 118759024Sobrien/* Return the list of objects needed by BFD. */ 118859024Sobrien 118959024Sobrienstruct bfd_link_needed_list * 1190218822Sdimbfd_sunos_get_needed_list (bfd *abfd ATTRIBUTE_UNUSED, 1191218822Sdim struct bfd_link_info *info) 119259024Sobrien{ 1193218822Sdim if (info->hash->creator != &MY (vec)) 119459024Sobrien return NULL; 119559024Sobrien return sunos_hash_table (info)->needed; 119659024Sobrien} 119759024Sobrien 119859024Sobrien/* Record an assignment made to a symbol by a linker script. We need 119959024Sobrien this in case some dynamic object refers to this symbol. */ 120059024Sobrien 1201130561Sobrienbfd_boolean 1202218822Sdimbfd_sunos_record_link_assignment (bfd *output_bfd, 1203218822Sdim struct bfd_link_info *info, 1204218822Sdim const char *name) 120559024Sobrien{ 120659024Sobrien struct sunos_link_hash_entry *h; 120759024Sobrien 120859024Sobrien if (output_bfd->xvec != &MY(vec)) 1209130561Sobrien return TRUE; 121059024Sobrien 121159024Sobrien /* This is called after we have examined all the input objects. If 121259024Sobrien the symbol does not exist, it merely means that no object refers 121359024Sobrien to it, and we can just ignore it at this point. */ 121459024Sobrien h = sunos_link_hash_lookup (sunos_hash_table (info), name, 1215130561Sobrien FALSE, FALSE, FALSE); 121659024Sobrien if (h == NULL) 1217130561Sobrien return TRUE; 121859024Sobrien 121959024Sobrien /* In a shared library, the __DYNAMIC symbol does not appear in the 122059024Sobrien dynamic symbol table. */ 122159024Sobrien if (! info->shared || strcmp (name, "__DYNAMIC") != 0) 122259024Sobrien { 122359024Sobrien h->flags |= SUNOS_DEF_REGULAR; 122459024Sobrien 122559024Sobrien if (h->dynindx == -1) 122659024Sobrien { 122759024Sobrien ++sunos_hash_table (info)->dynsymcount; 122859024Sobrien h->dynindx = -2; 122959024Sobrien } 123059024Sobrien } 123159024Sobrien 1232130561Sobrien return TRUE; 123359024Sobrien} 123459024Sobrien 123559024Sobrien/* Scan the relocs for an input section using standard relocs. We 123659024Sobrien need to figure out what to do for each reloc against a dynamic 123759024Sobrien symbol. If the symbol is in the .text section, an entry is made in 123859024Sobrien the procedure linkage table. Note that this will do the wrong 123959024Sobrien thing if the symbol is actually data; I don't think the Sun 3 124059024Sobrien native linker handles this case correctly either. If the symbol is 124159024Sobrien not in the .text section, we must preserve the reloc as a dynamic 124259024Sobrien reloc. FIXME: We should also handle the PIC relocs here by 124359024Sobrien building global offset table entries. */ 124459024Sobrien 1245130561Sobrienstatic bfd_boolean 1246218822Sdimsunos_scan_std_relocs (struct bfd_link_info *info, 1247218822Sdim bfd *abfd, 1248218822Sdim asection *sec ATTRIBUTE_UNUSED, 1249218822Sdim const struct reloc_std_external *relocs, 1250218822Sdim bfd_size_type rel_size) 125159024Sobrien{ 125259024Sobrien bfd *dynobj; 125359024Sobrien asection *splt = NULL; 125459024Sobrien asection *srel = NULL; 125559024Sobrien struct sunos_link_hash_entry **sym_hashes; 125659024Sobrien const struct reloc_std_external *rel, *relend; 125759024Sobrien 125859024Sobrien /* We only know how to handle m68k plt entries. */ 125959024Sobrien if (bfd_get_arch (abfd) != bfd_arch_m68k) 126059024Sobrien { 126159024Sobrien bfd_set_error (bfd_error_invalid_target); 1262130561Sobrien return FALSE; 126359024Sobrien } 126459024Sobrien 126559024Sobrien dynobj = NULL; 126659024Sobrien 126759024Sobrien sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd); 126859024Sobrien 126959024Sobrien relend = relocs + rel_size / RELOC_STD_SIZE; 127059024Sobrien for (rel = relocs; rel < relend; rel++) 127159024Sobrien { 127259024Sobrien int r_index; 127359024Sobrien struct sunos_link_hash_entry *h; 127459024Sobrien 127559024Sobrien /* We only want relocs against external symbols. */ 127659024Sobrien if (bfd_header_big_endian (abfd)) 127759024Sobrien { 127859024Sobrien if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG) == 0) 127959024Sobrien continue; 128059024Sobrien } 128159024Sobrien else 128259024Sobrien { 128359024Sobrien if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE) == 0) 128459024Sobrien continue; 128559024Sobrien } 128659024Sobrien 128759024Sobrien /* Get the symbol index. */ 128859024Sobrien if (bfd_header_big_endian (abfd)) 128959024Sobrien r_index = ((rel->r_index[0] << 16) 129059024Sobrien | (rel->r_index[1] << 8) 129159024Sobrien | rel->r_index[2]); 129259024Sobrien else 129359024Sobrien r_index = ((rel->r_index[2] << 16) 129459024Sobrien | (rel->r_index[1] << 8) 129559024Sobrien | rel->r_index[0]); 129659024Sobrien 129759024Sobrien /* Get the hash table entry. */ 129859024Sobrien h = sym_hashes[r_index]; 129959024Sobrien if (h == NULL) 1300218822Sdim /* This should not normally happen, but it will in any case 1301218822Sdim be caught in the relocation phase. */ 1302218822Sdim continue; 130359024Sobrien 130459024Sobrien /* At this point common symbols have already been allocated, so 130559024Sobrien we don't have to worry about them. We need to consider that 130659024Sobrien we may have already seen this symbol and marked it undefined; 130759024Sobrien if the symbol is really undefined, then SUNOS_DEF_DYNAMIC 130859024Sobrien will be zero. */ 130959024Sobrien if (h->root.root.type != bfd_link_hash_defined 131059024Sobrien && h->root.root.type != bfd_link_hash_defweak 131159024Sobrien && h->root.root.type != bfd_link_hash_undefined) 131259024Sobrien continue; 131359024Sobrien 131459024Sobrien if ((h->flags & SUNOS_DEF_DYNAMIC) == 0 131559024Sobrien || (h->flags & SUNOS_DEF_REGULAR) != 0) 131659024Sobrien continue; 131759024Sobrien 131859024Sobrien if (dynobj == NULL) 131959024Sobrien { 132059024Sobrien asection *sgot; 132159024Sobrien 1322130561Sobrien if (! sunos_create_dynamic_sections (abfd, info, FALSE)) 1323130561Sobrien return FALSE; 132459024Sobrien dynobj = sunos_hash_table (info)->dynobj; 132559024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 132659024Sobrien srel = bfd_get_section_by_name (dynobj, ".dynrel"); 132759024Sobrien BFD_ASSERT (splt != NULL && srel != NULL); 132859024Sobrien 132959024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 133059024Sobrien BFD_ASSERT (sgot != NULL); 1331218822Sdim if (sgot->size == 0) 1332218822Sdim sgot->size = BYTES_IN_WORD; 1333130561Sobrien sunos_hash_table (info)->got_needed = TRUE; 133459024Sobrien } 133559024Sobrien 133659024Sobrien BFD_ASSERT ((h->flags & SUNOS_REF_REGULAR) != 0); 133759024Sobrien BFD_ASSERT (h->plt_offset != 0 133859024Sobrien || ((h->root.root.type == bfd_link_hash_defined 133959024Sobrien || h->root.root.type == bfd_link_hash_defweak) 134059024Sobrien ? (h->root.root.u.def.section->owner->flags 134159024Sobrien & DYNAMIC) != 0 134259024Sobrien : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0)); 134359024Sobrien 134459024Sobrien /* This reloc is against a symbol defined only by a dynamic 134559024Sobrien object. */ 134659024Sobrien if (h->root.root.type == bfd_link_hash_undefined) 1347218822Sdim /* Presumably this symbol was marked as being undefined by 1348218822Sdim an earlier reloc. */ 1349218822Sdim srel->size += RELOC_STD_SIZE; 135059024Sobrien else if ((h->root.root.u.def.section->flags & SEC_CODE) == 0) 135159024Sobrien { 135259024Sobrien bfd *sub; 135359024Sobrien 135459024Sobrien /* This reloc is not in the .text section. It must be 135559024Sobrien copied into the dynamic relocs. We mark the symbol as 135659024Sobrien being undefined. */ 1357218822Sdim srel->size += RELOC_STD_SIZE; 135859024Sobrien sub = h->root.root.u.def.section->owner; 135959024Sobrien h->root.root.type = bfd_link_hash_undefined; 136059024Sobrien h->root.root.u.undef.abfd = sub; 136159024Sobrien } 136259024Sobrien else 136359024Sobrien { 136459024Sobrien /* This symbol is in the .text section. We must give it an 136559024Sobrien entry in the procedure linkage table, if we have not 136659024Sobrien already done so. We change the definition of the symbol 136759024Sobrien to the .plt section; this will cause relocs against it to 136859024Sobrien be handled correctly. */ 136959024Sobrien if (h->plt_offset == 0) 137059024Sobrien { 1371218822Sdim if (splt->size == 0) 1372218822Sdim splt->size = M68K_PLT_ENTRY_SIZE; 1373218822Sdim h->plt_offset = splt->size; 137459024Sobrien 137559024Sobrien if ((h->flags & SUNOS_DEF_REGULAR) == 0) 137659024Sobrien { 137759024Sobrien h->root.root.u.def.section = splt; 1378218822Sdim h->root.root.u.def.value = splt->size; 137959024Sobrien } 138059024Sobrien 1381218822Sdim splt->size += M68K_PLT_ENTRY_SIZE; 138259024Sobrien 138359024Sobrien /* We may also need a dynamic reloc entry. */ 138459024Sobrien if ((h->flags & SUNOS_DEF_REGULAR) == 0) 1385218822Sdim srel->size += RELOC_STD_SIZE; 138659024Sobrien } 138759024Sobrien } 138859024Sobrien } 138959024Sobrien 1390130561Sobrien return TRUE; 139159024Sobrien} 139259024Sobrien 139359024Sobrien/* Scan the relocs for an input section using extended relocs. We 139459024Sobrien need to figure out what to do for each reloc against a dynamic 139559024Sobrien symbol. If the reloc is a WDISP30, and the symbol is in the .text 139659024Sobrien section, an entry is made in the procedure linkage table. 139759024Sobrien Otherwise, we must preserve the reloc as a dynamic reloc. */ 139859024Sobrien 1399130561Sobrienstatic bfd_boolean 1400218822Sdimsunos_scan_ext_relocs (struct bfd_link_info *info, 1401218822Sdim bfd *abfd, 1402218822Sdim asection *sec ATTRIBUTE_UNUSED, 1403218822Sdim const struct reloc_ext_external *relocs, 1404218822Sdim bfd_size_type rel_size) 140559024Sobrien{ 140659024Sobrien bfd *dynobj; 140759024Sobrien struct sunos_link_hash_entry **sym_hashes; 140859024Sobrien const struct reloc_ext_external *rel, *relend; 140959024Sobrien asection *splt = NULL; 141059024Sobrien asection *sgot = NULL; 141159024Sobrien asection *srel = NULL; 141289857Sobrien bfd_size_type amt; 141359024Sobrien 141459024Sobrien /* We only know how to handle SPARC plt entries. */ 141559024Sobrien if (bfd_get_arch (abfd) != bfd_arch_sparc) 141659024Sobrien { 141759024Sobrien bfd_set_error (bfd_error_invalid_target); 1418130561Sobrien return FALSE; 141959024Sobrien } 142059024Sobrien 142159024Sobrien dynobj = NULL; 142259024Sobrien 142359024Sobrien sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd); 142459024Sobrien 142559024Sobrien relend = relocs + rel_size / RELOC_EXT_SIZE; 142659024Sobrien for (rel = relocs; rel < relend; rel++) 142759024Sobrien { 142859024Sobrien unsigned int r_index; 142959024Sobrien int r_extern; 143059024Sobrien int r_type; 143159024Sobrien struct sunos_link_hash_entry *h = NULL; 143259024Sobrien 143359024Sobrien /* Swap in the reloc information. */ 143459024Sobrien if (bfd_header_big_endian (abfd)) 143559024Sobrien { 143659024Sobrien r_index = ((rel->r_index[0] << 16) 143759024Sobrien | (rel->r_index[1] << 8) 143859024Sobrien | rel->r_index[2]); 143959024Sobrien r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG)); 144059024Sobrien r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) 144159024Sobrien >> RELOC_EXT_BITS_TYPE_SH_BIG); 144259024Sobrien } 144359024Sobrien else 144459024Sobrien { 144559024Sobrien r_index = ((rel->r_index[2] << 16) 144659024Sobrien | (rel->r_index[1] << 8) 144759024Sobrien | rel->r_index[0]); 144859024Sobrien r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE)); 144959024Sobrien r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) 145059024Sobrien >> RELOC_EXT_BITS_TYPE_SH_LITTLE); 145159024Sobrien } 145259024Sobrien 145359024Sobrien if (r_extern) 145459024Sobrien { 145559024Sobrien h = sym_hashes[r_index]; 145659024Sobrien if (h == NULL) 145759024Sobrien { 145859024Sobrien /* This should not normally happen, but it will in any 145959024Sobrien case be caught in the relocation phase. */ 146059024Sobrien continue; 146159024Sobrien } 146259024Sobrien } 146359024Sobrien 146459024Sobrien /* If this is a base relative reloc, we need to make an entry in 1465130561Sobrien the .got section. */ 146659024Sobrien if (r_type == RELOC_BASE10 146759024Sobrien || r_type == RELOC_BASE13 146859024Sobrien || r_type == RELOC_BASE22) 146959024Sobrien { 147059024Sobrien if (dynobj == NULL) 147159024Sobrien { 1472130561Sobrien if (! sunos_create_dynamic_sections (abfd, info, FALSE)) 1473130561Sobrien return FALSE; 147459024Sobrien dynobj = sunos_hash_table (info)->dynobj; 147559024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 147659024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 147759024Sobrien srel = bfd_get_section_by_name (dynobj, ".dynrel"); 147859024Sobrien BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL); 147959024Sobrien 148059024Sobrien /* Make sure we have an initial entry in the .got table. */ 1481218822Sdim if (sgot->size == 0) 1482218822Sdim sgot->size = BYTES_IN_WORD; 1483130561Sobrien sunos_hash_table (info)->got_needed = TRUE; 148459024Sobrien } 148559024Sobrien 148659024Sobrien if (r_extern) 148759024Sobrien { 148859024Sobrien if (h->got_offset != 0) 148959024Sobrien continue; 149059024Sobrien 1491218822Sdim h->got_offset = sgot->size; 149259024Sobrien } 149359024Sobrien else 149459024Sobrien { 149559024Sobrien if (r_index >= bfd_get_symcount (abfd)) 1496218822Sdim /* This is abnormal, but should be caught in the 1497218822Sdim relocation phase. */ 1498218822Sdim continue; 149959024Sobrien 150059024Sobrien if (adata (abfd).local_got_offsets == NULL) 150159024Sobrien { 150289857Sobrien amt = bfd_get_symcount (abfd); 150389857Sobrien amt *= sizeof (bfd_vma); 1504218822Sdim adata (abfd).local_got_offsets = bfd_zalloc (abfd, amt); 150559024Sobrien if (adata (abfd).local_got_offsets == NULL) 1506130561Sobrien return FALSE; 150759024Sobrien } 150859024Sobrien 150959024Sobrien if (adata (abfd).local_got_offsets[r_index] != 0) 151059024Sobrien continue; 151159024Sobrien 1512218822Sdim adata (abfd).local_got_offsets[r_index] = sgot->size; 151359024Sobrien } 151459024Sobrien 1515218822Sdim sgot->size += BYTES_IN_WORD; 151659024Sobrien 151759024Sobrien /* If we are making a shared library, or if the symbol is 151859024Sobrien defined by a dynamic object, we will need a dynamic reloc 151959024Sobrien entry. */ 152059024Sobrien if (info->shared 152159024Sobrien || (h != NULL 152259024Sobrien && (h->flags & SUNOS_DEF_DYNAMIC) != 0 152359024Sobrien && (h->flags & SUNOS_DEF_REGULAR) == 0)) 1524218822Sdim srel->size += RELOC_EXT_SIZE; 152559024Sobrien 152659024Sobrien continue; 152759024Sobrien } 152859024Sobrien 152959024Sobrien /* Otherwise, we are only interested in relocs against symbols 1530130561Sobrien defined in dynamic objects but not in regular objects. We 1531130561Sobrien only need to consider relocs against external symbols. */ 153259024Sobrien if (! r_extern) 153359024Sobrien { 153459024Sobrien /* But, if we are creating a shared library, we need to 1535130561Sobrien generate an absolute reloc. */ 153659024Sobrien if (info->shared) 153759024Sobrien { 153859024Sobrien if (dynobj == NULL) 153959024Sobrien { 1540130561Sobrien if (! sunos_create_dynamic_sections (abfd, info, TRUE)) 1541130561Sobrien return FALSE; 154259024Sobrien dynobj = sunos_hash_table (info)->dynobj; 154359024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 154459024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 154559024Sobrien srel = bfd_get_section_by_name (dynobj, ".dynrel"); 154659024Sobrien BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL); 154759024Sobrien } 154859024Sobrien 1549218822Sdim srel->size += RELOC_EXT_SIZE; 155059024Sobrien } 155159024Sobrien 155259024Sobrien continue; 155359024Sobrien } 155459024Sobrien 155559024Sobrien /* At this point common symbols have already been allocated, so 155659024Sobrien we don't have to worry about them. We need to consider that 155759024Sobrien we may have already seen this symbol and marked it undefined; 155859024Sobrien if the symbol is really undefined, then SUNOS_DEF_DYNAMIC 155959024Sobrien will be zero. */ 156059024Sobrien if (h->root.root.type != bfd_link_hash_defined 156159024Sobrien && h->root.root.type != bfd_link_hash_defweak 156259024Sobrien && h->root.root.type != bfd_link_hash_undefined) 156359024Sobrien continue; 156459024Sobrien 156559024Sobrien if (r_type != RELOC_JMP_TBL 156659024Sobrien && ! info->shared 156759024Sobrien && ((h->flags & SUNOS_DEF_DYNAMIC) == 0 156859024Sobrien || (h->flags & SUNOS_DEF_REGULAR) != 0)) 156959024Sobrien continue; 157059024Sobrien 157159024Sobrien if (r_type == RELOC_JMP_TBL 157259024Sobrien && ! info->shared 157359024Sobrien && (h->flags & SUNOS_DEF_DYNAMIC) == 0 157459024Sobrien && (h->flags & SUNOS_DEF_REGULAR) == 0) 157559024Sobrien { 157659024Sobrien /* This symbol is apparently undefined. Don't do anything 1577130561Sobrien here; just let the relocation routine report an undefined 1578130561Sobrien symbol. */ 157959024Sobrien continue; 158059024Sobrien } 158159024Sobrien 158259024Sobrien if (strcmp (h->root.root.root.string, "__GLOBAL_OFFSET_TABLE_") == 0) 158359024Sobrien continue; 158459024Sobrien 158559024Sobrien if (dynobj == NULL) 158659024Sobrien { 1587130561Sobrien if (! sunos_create_dynamic_sections (abfd, info, FALSE)) 1588130561Sobrien return FALSE; 158959024Sobrien dynobj = sunos_hash_table (info)->dynobj; 159059024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 159159024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 159259024Sobrien srel = bfd_get_section_by_name (dynobj, ".dynrel"); 159359024Sobrien BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL); 159459024Sobrien 159559024Sobrien /* Make sure we have an initial entry in the .got table. */ 1596218822Sdim if (sgot->size == 0) 1597218822Sdim sgot->size = BYTES_IN_WORD; 1598130561Sobrien sunos_hash_table (info)->got_needed = TRUE; 159959024Sobrien } 160059024Sobrien 160159024Sobrien BFD_ASSERT (r_type == RELOC_JMP_TBL 160259024Sobrien || info->shared 160359024Sobrien || (h->flags & SUNOS_REF_REGULAR) != 0); 160459024Sobrien BFD_ASSERT (r_type == RELOC_JMP_TBL 160559024Sobrien || info->shared 160659024Sobrien || h->plt_offset != 0 160759024Sobrien || ((h->root.root.type == bfd_link_hash_defined 160859024Sobrien || h->root.root.type == bfd_link_hash_defweak) 160959024Sobrien ? (h->root.root.u.def.section->owner->flags 161059024Sobrien & DYNAMIC) != 0 161159024Sobrien : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0)); 161259024Sobrien 161359024Sobrien /* This reloc is against a symbol defined only by a dynamic 161459024Sobrien object, or it is a jump table reloc from PIC compiled code. */ 161559024Sobrien 161659024Sobrien if (r_type != RELOC_JMP_TBL 161759024Sobrien && h->root.root.type == bfd_link_hash_undefined) 1618218822Sdim /* Presumably this symbol was marked as being undefined by 1619218822Sdim an earlier reloc. */ 1620218822Sdim srel->size += RELOC_EXT_SIZE; 1621218822Sdim 162259024Sobrien else if (r_type != RELOC_JMP_TBL 162359024Sobrien && (h->root.root.u.def.section->flags & SEC_CODE) == 0) 162459024Sobrien { 162559024Sobrien bfd *sub; 162659024Sobrien 162759024Sobrien /* This reloc is not in the .text section. It must be 162859024Sobrien copied into the dynamic relocs. We mark the symbol as 162959024Sobrien being undefined. */ 1630218822Sdim srel->size += RELOC_EXT_SIZE; 163159024Sobrien if ((h->flags & SUNOS_DEF_REGULAR) == 0) 163259024Sobrien { 163359024Sobrien sub = h->root.root.u.def.section->owner; 163459024Sobrien h->root.root.type = bfd_link_hash_undefined; 163559024Sobrien h->root.root.u.undef.abfd = sub; 163659024Sobrien } 163759024Sobrien } 163859024Sobrien else 163959024Sobrien { 164059024Sobrien /* This symbol is in the .text section. We must give it an 164159024Sobrien entry in the procedure linkage table, if we have not 164259024Sobrien already done so. We change the definition of the symbol 164359024Sobrien to the .plt section; this will cause relocs against it to 164459024Sobrien be handled correctly. */ 164559024Sobrien if (h->plt_offset == 0) 164659024Sobrien { 1647218822Sdim if (splt->size == 0) 1648218822Sdim splt->size = SPARC_PLT_ENTRY_SIZE; 1649218822Sdim h->plt_offset = splt->size; 165059024Sobrien 165159024Sobrien if ((h->flags & SUNOS_DEF_REGULAR) == 0) 165259024Sobrien { 165359024Sobrien if (h->root.root.type == bfd_link_hash_undefined) 165459024Sobrien h->root.root.type = bfd_link_hash_defined; 165559024Sobrien h->root.root.u.def.section = splt; 1656218822Sdim h->root.root.u.def.value = splt->size; 165759024Sobrien } 165859024Sobrien 1659218822Sdim splt->size += SPARC_PLT_ENTRY_SIZE; 166059024Sobrien 166159024Sobrien /* We will also need a dynamic reloc entry, unless this 1662130561Sobrien is a JMP_TBL reloc produced by linking PIC compiled 1663130561Sobrien code, and we are not making a shared library. */ 166459024Sobrien if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0) 1665218822Sdim srel->size += RELOC_EXT_SIZE; 166659024Sobrien } 166759024Sobrien 166859024Sobrien /* If we are creating a shared library, we need to copy over 1669130561Sobrien any reloc other than a jump table reloc. */ 167059024Sobrien if (info->shared && r_type != RELOC_JMP_TBL) 1671218822Sdim srel->size += RELOC_EXT_SIZE; 167259024Sobrien } 167359024Sobrien } 167459024Sobrien 1675130561Sobrien return TRUE; 167659024Sobrien} 167759024Sobrien 1678218822Sdim/* Scan the relocs for an input section. */ 1679218822Sdim 1680218822Sdimstatic bfd_boolean 1681218822Sdimsunos_scan_relocs (struct bfd_link_info *info, 1682218822Sdim bfd *abfd, 1683218822Sdim asection *sec, 1684218822Sdim bfd_size_type rel_size) 1685218822Sdim{ 1686218822Sdim void * relocs; 1687218822Sdim void * free_relocs = NULL; 1688218822Sdim 1689218822Sdim if (rel_size == 0) 1690218822Sdim return TRUE; 1691218822Sdim 1692218822Sdim if (! info->keep_memory) 1693218822Sdim relocs = free_relocs = bfd_malloc (rel_size); 1694218822Sdim else 1695218822Sdim { 1696218822Sdim struct aout_section_data_struct *n; 1697218822Sdim bfd_size_type amt = sizeof (struct aout_section_data_struct); 1698218822Sdim 1699218822Sdim n = bfd_alloc (abfd, amt); 1700218822Sdim if (n == NULL) 1701218822Sdim relocs = NULL; 1702218822Sdim else 1703218822Sdim { 1704218822Sdim set_aout_section_data (sec, n); 1705218822Sdim relocs = bfd_malloc (rel_size); 1706218822Sdim aout_section_data (sec)->relocs = relocs; 1707218822Sdim } 1708218822Sdim } 1709218822Sdim if (relocs == NULL) 1710218822Sdim return FALSE; 1711218822Sdim 1712218822Sdim if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0 1713218822Sdim || bfd_bread (relocs, rel_size, abfd) != rel_size) 1714218822Sdim goto error_return; 1715218822Sdim 1716218822Sdim if (obj_reloc_entry_size (abfd) == RELOC_STD_SIZE) 1717218822Sdim { 1718218822Sdim if (! sunos_scan_std_relocs (info, abfd, sec, 1719218822Sdim (struct reloc_std_external *) relocs, 1720218822Sdim rel_size)) 1721218822Sdim goto error_return; 1722218822Sdim } 1723218822Sdim else 1724218822Sdim { 1725218822Sdim if (! sunos_scan_ext_relocs (info, abfd, sec, 1726218822Sdim (struct reloc_ext_external *) relocs, 1727218822Sdim rel_size)) 1728218822Sdim goto error_return; 1729218822Sdim } 1730218822Sdim 1731218822Sdim if (free_relocs != NULL) 1732218822Sdim free (free_relocs); 1733218822Sdim 1734218822Sdim return TRUE; 1735218822Sdim 1736218822Sdim error_return: 1737218822Sdim if (free_relocs != NULL) 1738218822Sdim free (free_relocs); 1739218822Sdim return FALSE; 1740218822Sdim} 1741218822Sdim 174259024Sobrien/* Build the hash table of dynamic symbols, and to mark as written all 174359024Sobrien symbols from dynamic objects which we do not plan to write out. */ 174459024Sobrien 1745130561Sobrienstatic bfd_boolean 1746218822Sdimsunos_scan_dynamic_symbol (struct sunos_link_hash_entry *h, void * data) 174759024Sobrien{ 174859024Sobrien struct bfd_link_info *info = (struct bfd_link_info *) data; 174959024Sobrien 175094536Sobrien if (h->root.root.type == bfd_link_hash_warning) 175194536Sobrien h = (struct sunos_link_hash_entry *) h->root.root.u.i.link; 175294536Sobrien 175359024Sobrien /* Set the written flag for symbols we do not want to write out as 175459024Sobrien part of the regular symbol table. This is all symbols which are 175559024Sobrien not defined in a regular object file. For some reason symbols 175659024Sobrien which are referenced by a regular object and defined by a dynamic 175759024Sobrien object do not seem to show up in the regular symbol table. It is 175859024Sobrien possible for a symbol to have only SUNOS_REF_REGULAR set here, it 175959024Sobrien is an undefined symbol which was turned into a common symbol 176059024Sobrien because it was found in an archive object which was not included 176159024Sobrien in the link. */ 176259024Sobrien if ((h->flags & SUNOS_DEF_REGULAR) == 0 176359024Sobrien && (h->flags & SUNOS_DEF_DYNAMIC) != 0 176459024Sobrien && strcmp (h->root.root.root.string, "__DYNAMIC") != 0) 1765130561Sobrien h->root.written = TRUE; 176659024Sobrien 176759024Sobrien /* If this symbol is defined by a dynamic object and referenced by a 176859024Sobrien regular object, see whether we gave it a reasonable value while 176959024Sobrien scanning the relocs. */ 177059024Sobrien if ((h->flags & SUNOS_DEF_REGULAR) == 0 177159024Sobrien && (h->flags & SUNOS_DEF_DYNAMIC) != 0 177259024Sobrien && (h->flags & SUNOS_REF_REGULAR) != 0) 177359024Sobrien { 177459024Sobrien if ((h->root.root.type == bfd_link_hash_defined 177559024Sobrien || h->root.root.type == bfd_link_hash_defweak) 177659024Sobrien && ((h->root.root.u.def.section->owner->flags & DYNAMIC) != 0) 177759024Sobrien && h->root.root.u.def.section->output_section == NULL) 177859024Sobrien { 177959024Sobrien bfd *sub; 178059024Sobrien 178159024Sobrien /* This symbol is currently defined in a dynamic section 178259024Sobrien which is not being put into the output file. This 178359024Sobrien implies that there is no reloc against the symbol. I'm 178459024Sobrien not sure why this case would ever occur. In any case, we 178559024Sobrien change the symbol to be undefined. */ 178659024Sobrien sub = h->root.root.u.def.section->owner; 178759024Sobrien h->root.root.type = bfd_link_hash_undefined; 178859024Sobrien h->root.root.u.undef.abfd = sub; 178959024Sobrien } 179059024Sobrien } 179159024Sobrien 179259024Sobrien /* If this symbol is defined or referenced by a regular file, add it 179359024Sobrien to the dynamic symbols. */ 179459024Sobrien if ((h->flags & (SUNOS_DEF_REGULAR | SUNOS_REF_REGULAR)) != 0) 179559024Sobrien { 179659024Sobrien asection *s; 179759024Sobrien size_t len; 179859024Sobrien bfd_byte *contents; 179959024Sobrien unsigned char *name; 180059024Sobrien unsigned long hash; 180159024Sobrien bfd *dynobj; 180259024Sobrien 180359024Sobrien BFD_ASSERT (h->dynindx == -2); 180459024Sobrien 180559024Sobrien dynobj = sunos_hash_table (info)->dynobj; 180659024Sobrien 180759024Sobrien h->dynindx = sunos_hash_table (info)->dynsymcount; 180859024Sobrien ++sunos_hash_table (info)->dynsymcount; 180959024Sobrien 181059024Sobrien len = strlen (h->root.root.root.string); 181159024Sobrien 181259024Sobrien /* We don't bother to construct a BFD hash table for the strings 181359024Sobrien which are the names of the dynamic symbols. Using a hash 181459024Sobrien table for the regular symbols is beneficial, because the 181559024Sobrien regular symbols includes the debugging symbols, which have 181659024Sobrien long names and are often duplicated in several object files. 181759024Sobrien There are no debugging symbols in the dynamic symbols. */ 181859024Sobrien s = bfd_get_section_by_name (dynobj, ".dynstr"); 181959024Sobrien BFD_ASSERT (s != NULL); 1820218822Sdim contents = bfd_realloc (s->contents, s->size + len + 1); 182159024Sobrien if (contents == NULL) 1822130561Sobrien return FALSE; 182359024Sobrien s->contents = contents; 182459024Sobrien 1825218822Sdim h->dynstr_index = s->size; 1826218822Sdim strcpy ((char *) contents + s->size, h->root.root.root.string); 1827218822Sdim s->size += len + 1; 182859024Sobrien 182959024Sobrien /* Add it to the dynamic hash table. */ 183059024Sobrien name = (unsigned char *) h->root.root.root.string; 183159024Sobrien hash = 0; 183259024Sobrien while (*name != '\0') 183359024Sobrien hash = (hash << 1) + *name++; 183459024Sobrien hash &= 0x7fffffff; 183559024Sobrien hash %= sunos_hash_table (info)->bucketcount; 183659024Sobrien 183759024Sobrien s = bfd_get_section_by_name (dynobj, ".hash"); 183859024Sobrien BFD_ASSERT (s != NULL); 183959024Sobrien 184059024Sobrien if (GET_SWORD (dynobj, s->contents + hash * HASH_ENTRY_SIZE) == -1) 184159024Sobrien PUT_WORD (dynobj, h->dynindx, s->contents + hash * HASH_ENTRY_SIZE); 184259024Sobrien else 184359024Sobrien { 184459024Sobrien bfd_vma next; 184559024Sobrien 184659024Sobrien next = GET_WORD (dynobj, 184759024Sobrien (s->contents 184859024Sobrien + hash * HASH_ENTRY_SIZE 184959024Sobrien + BYTES_IN_WORD)); 1850218822Sdim PUT_WORD (dynobj, s->size / HASH_ENTRY_SIZE, 185159024Sobrien s->contents + hash * HASH_ENTRY_SIZE + BYTES_IN_WORD); 1852218822Sdim PUT_WORD (dynobj, h->dynindx, s->contents + s->size); 1853218822Sdim PUT_WORD (dynobj, next, s->contents + s->size + BYTES_IN_WORD); 1854218822Sdim s->size += HASH_ENTRY_SIZE; 185559024Sobrien } 185659024Sobrien } 185759024Sobrien 1858130561Sobrien return TRUE; 185959024Sobrien} 186059024Sobrien 1861218822Sdim/* Set up the sizes and contents of the dynamic sections created in 1862218822Sdim sunos_add_dynamic_symbols. This is called by the SunOS linker 1863218822Sdim emulation before_allocation routine. We must set the sizes of the 1864218822Sdim sections before the linker sets the addresses of the various 1865218822Sdim sections. This unfortunately requires reading all the relocs so 1866218822Sdim that we can work out which ones need to become dynamic relocs. If 1867218822Sdim info->keep_memory is TRUE, we keep the relocs in memory; otherwise, 1868218822Sdim we discard them, and will read them again later. */ 1869218822Sdim 1870218822Sdimbfd_boolean 1871218822Sdimbfd_sunos_size_dynamic_sections (bfd *output_bfd, 1872218822Sdim struct bfd_link_info *info, 1873218822Sdim asection **sdynptr, 1874218822Sdim asection **sneedptr, 1875218822Sdim asection **srulesptr) 1876218822Sdim{ 1877218822Sdim bfd *dynobj; 1878218822Sdim bfd_size_type dynsymcount; 1879218822Sdim struct sunos_link_hash_entry *h; 1880218822Sdim asection *s; 1881218822Sdim size_t bucketcount; 1882218822Sdim bfd_size_type hashalloc; 1883218822Sdim size_t i; 1884218822Sdim bfd *sub; 1885218822Sdim 1886218822Sdim *sdynptr = NULL; 1887218822Sdim *sneedptr = NULL; 1888218822Sdim *srulesptr = NULL; 1889218822Sdim 1890218822Sdim if (info->relocatable) 1891218822Sdim return TRUE; 1892218822Sdim 1893218822Sdim if (output_bfd->xvec != &MY(vec)) 1894218822Sdim return TRUE; 1895218822Sdim 1896218822Sdim /* Look through all the input BFD's and read their relocs. It would 1897218822Sdim be better if we didn't have to do this, but there is no other way 1898218822Sdim to determine the number of dynamic relocs we need, and, more 1899218822Sdim importantly, there is no other way to know which symbols should 1900218822Sdim get an entry in the procedure linkage table. */ 1901218822Sdim for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) 1902218822Sdim { 1903218822Sdim if ((sub->flags & DYNAMIC) == 0 1904218822Sdim && sub->xvec == output_bfd->xvec) 1905218822Sdim { 1906218822Sdim if (! sunos_scan_relocs (info, sub, obj_textsec (sub), 1907218822Sdim exec_hdr (sub)->a_trsize) 1908218822Sdim || ! sunos_scan_relocs (info, sub, obj_datasec (sub), 1909218822Sdim exec_hdr (sub)->a_drsize)) 1910218822Sdim return FALSE; 1911218822Sdim } 1912218822Sdim } 1913218822Sdim 1914218822Sdim dynobj = sunos_hash_table (info)->dynobj; 1915218822Sdim dynsymcount = sunos_hash_table (info)->dynsymcount; 1916218822Sdim 1917218822Sdim /* If there were no dynamic objects in the link, and we don't need 1918218822Sdim to build a global offset table, there is nothing to do here. */ 1919218822Sdim if (! sunos_hash_table (info)->dynamic_sections_needed 1920218822Sdim && ! sunos_hash_table (info)->got_needed) 1921218822Sdim return TRUE; 1922218822Sdim 1923218822Sdim /* If __GLOBAL_OFFSET_TABLE_ was mentioned, define it. */ 1924218822Sdim h = sunos_link_hash_lookup (sunos_hash_table (info), 1925218822Sdim "__GLOBAL_OFFSET_TABLE_", FALSE, FALSE, FALSE); 1926218822Sdim if (h != NULL && (h->flags & SUNOS_REF_REGULAR) != 0) 1927218822Sdim { 1928218822Sdim h->flags |= SUNOS_DEF_REGULAR; 1929218822Sdim if (h->dynindx == -1) 1930218822Sdim { 1931218822Sdim ++sunos_hash_table (info)->dynsymcount; 1932218822Sdim h->dynindx = -2; 1933218822Sdim } 1934218822Sdim h->root.root.type = bfd_link_hash_defined; 1935218822Sdim h->root.root.u.def.section = bfd_get_section_by_name (dynobj, ".got"); 1936218822Sdim 1937218822Sdim /* If the .got section is more than 0x1000 bytes, we set 1938218822Sdim __GLOBAL_OFFSET_TABLE_ to be 0x1000 bytes into the section, 1939218822Sdim so that 13 bit relocations have a greater chance of working. */ 1940218822Sdim s = bfd_get_section_by_name (dynobj, ".got"); 1941218822Sdim BFD_ASSERT (s != NULL); 1942218822Sdim if (s->size >= 0x1000) 1943218822Sdim h->root.root.u.def.value = 0x1000; 1944218822Sdim else 1945218822Sdim h->root.root.u.def.value = 0; 1946218822Sdim 1947218822Sdim sunos_hash_table (info)->got_base = h->root.root.u.def.value; 1948218822Sdim } 1949218822Sdim 1950218822Sdim /* If there are any shared objects in the link, then we need to set 1951218822Sdim up the dynamic linking information. */ 1952218822Sdim if (sunos_hash_table (info)->dynamic_sections_needed) 1953218822Sdim { 1954218822Sdim *sdynptr = bfd_get_section_by_name (dynobj, ".dynamic"); 1955218822Sdim 1956218822Sdim /* The .dynamic section is always the same size. */ 1957218822Sdim s = *sdynptr; 1958218822Sdim BFD_ASSERT (s != NULL); 1959218822Sdim s->size = (sizeof (struct external_sun4_dynamic) 1960218822Sdim + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE 1961218822Sdim + sizeof (struct external_sun4_dynamic_link)); 1962218822Sdim 1963218822Sdim /* Set the size of the .dynsym and .hash sections. We counted 1964218822Sdim the number of dynamic symbols as we read the input files. We 1965218822Sdim will build the dynamic symbol table (.dynsym) and the hash 1966218822Sdim table (.hash) when we build the final symbol table, because 1967218822Sdim until then we do not know the correct value to give the 1968218822Sdim symbols. We build the dynamic symbol string table (.dynstr) 1969218822Sdim in a traversal of the symbol table using 1970218822Sdim sunos_scan_dynamic_symbol. */ 1971218822Sdim s = bfd_get_section_by_name (dynobj, ".dynsym"); 1972218822Sdim BFD_ASSERT (s != NULL); 1973218822Sdim s->size = dynsymcount * sizeof (struct external_nlist); 1974218822Sdim s->contents = bfd_alloc (output_bfd, s->size); 1975218822Sdim if (s->contents == NULL && s->size != 0) 1976218822Sdim return FALSE; 1977218822Sdim 1978218822Sdim /* The number of buckets is just the number of symbols divided 1979218822Sdim by four. To compute the final size of the hash table, we 1980218822Sdim must actually compute the hash table. Normally we need 1981218822Sdim exactly as many entries in the hash table as there are 1982218822Sdim dynamic symbols, but if some of the buckets are not used we 1983218822Sdim will need additional entries. In the worst case, every 1984218822Sdim symbol will hash to the same bucket, and we will need 1985218822Sdim BUCKETCOUNT - 1 extra entries. */ 1986218822Sdim if (dynsymcount >= 4) 1987218822Sdim bucketcount = dynsymcount / 4; 1988218822Sdim else if (dynsymcount > 0) 1989218822Sdim bucketcount = dynsymcount; 1990218822Sdim else 1991218822Sdim bucketcount = 1; 1992218822Sdim s = bfd_get_section_by_name (dynobj, ".hash"); 1993218822Sdim BFD_ASSERT (s != NULL); 1994218822Sdim hashalloc = (dynsymcount + bucketcount - 1) * HASH_ENTRY_SIZE; 1995218822Sdim s->contents = bfd_zalloc (dynobj, hashalloc); 1996218822Sdim if (s->contents == NULL && dynsymcount > 0) 1997218822Sdim return FALSE; 1998218822Sdim for (i = 0; i < bucketcount; i++) 1999218822Sdim PUT_WORD (output_bfd, (bfd_vma) -1, s->contents + i * HASH_ENTRY_SIZE); 2000218822Sdim s->size = bucketcount * HASH_ENTRY_SIZE; 2001218822Sdim 2002218822Sdim sunos_hash_table (info)->bucketcount = bucketcount; 2003218822Sdim 2004218822Sdim /* Scan all the symbols, place them in the dynamic symbol table, 2005218822Sdim and build the dynamic hash table. We reuse dynsymcount as a 2006218822Sdim counter for the number of symbols we have added so far. */ 2007218822Sdim sunos_hash_table (info)->dynsymcount = 0; 2008218822Sdim sunos_link_hash_traverse (sunos_hash_table (info), 2009218822Sdim sunos_scan_dynamic_symbol, 2010218822Sdim (void *) info); 2011218822Sdim BFD_ASSERT (sunos_hash_table (info)->dynsymcount == dynsymcount); 2012218822Sdim 2013218822Sdim /* The SunOS native linker seems to align the total size of the 2014218822Sdim symbol strings to a multiple of 8. I don't know if this is 2015218822Sdim important, but it can't hurt much. */ 2016218822Sdim s = bfd_get_section_by_name (dynobj, ".dynstr"); 2017218822Sdim BFD_ASSERT (s != NULL); 2018218822Sdim if ((s->size & 7) != 0) 2019218822Sdim { 2020218822Sdim bfd_size_type add; 2021218822Sdim bfd_byte *contents; 2022218822Sdim 2023218822Sdim add = 8 - (s->size & 7); 2024218822Sdim contents = bfd_realloc (s->contents, s->size + add); 2025218822Sdim if (contents == NULL) 2026218822Sdim return FALSE; 2027218822Sdim memset (contents + s->size, 0, (size_t) add); 2028218822Sdim s->contents = contents; 2029218822Sdim s->size += add; 2030218822Sdim } 2031218822Sdim } 2032218822Sdim 2033218822Sdim /* Now that we have worked out the sizes of the procedure linkage 2034218822Sdim table and the dynamic relocs, allocate storage for them. */ 2035218822Sdim s = bfd_get_section_by_name (dynobj, ".plt"); 2036218822Sdim BFD_ASSERT (s != NULL); 2037218822Sdim if (s->size != 0) 2038218822Sdim { 2039218822Sdim s->contents = bfd_alloc (dynobj, s->size); 2040218822Sdim if (s->contents == NULL) 2041218822Sdim return FALSE; 2042218822Sdim 2043218822Sdim /* Fill in the first entry in the table. */ 2044218822Sdim switch (bfd_get_arch (dynobj)) 2045218822Sdim { 2046218822Sdim case bfd_arch_sparc: 2047218822Sdim memcpy (s->contents, sparc_plt_first_entry, SPARC_PLT_ENTRY_SIZE); 2048218822Sdim break; 2049218822Sdim 2050218822Sdim case bfd_arch_m68k: 2051218822Sdim memcpy (s->contents, m68k_plt_first_entry, M68K_PLT_ENTRY_SIZE); 2052218822Sdim break; 2053218822Sdim 2054218822Sdim default: 2055218822Sdim abort (); 2056218822Sdim } 2057218822Sdim } 2058218822Sdim 2059218822Sdim s = bfd_get_section_by_name (dynobj, ".dynrel"); 2060218822Sdim if (s->size != 0) 2061218822Sdim { 2062218822Sdim s->contents = bfd_alloc (dynobj, s->size); 2063218822Sdim if (s->contents == NULL) 2064218822Sdim return FALSE; 2065218822Sdim } 2066218822Sdim /* We use the reloc_count field to keep track of how many of the 2067218822Sdim relocs we have output so far. */ 2068218822Sdim s->reloc_count = 0; 2069218822Sdim 2070218822Sdim /* Make space for the global offset table. */ 2071218822Sdim s = bfd_get_section_by_name (dynobj, ".got"); 2072218822Sdim s->contents = bfd_alloc (dynobj, s->size); 2073218822Sdim if (s->contents == NULL) 2074218822Sdim return FALSE; 2075218822Sdim 2076218822Sdim *sneedptr = bfd_get_section_by_name (dynobj, ".need"); 2077218822Sdim *srulesptr = bfd_get_section_by_name (dynobj, ".rules"); 2078218822Sdim 2079218822Sdim return TRUE; 2080218822Sdim} 2081218822Sdim 208259024Sobrien/* Link a dynamic object. We actually don't have anything to do at 208359024Sobrien this point. This entry point exists to prevent the regular linker 208459024Sobrien code from doing anything with the object. */ 208559024Sobrien 2086130561Sobrienstatic bfd_boolean 2087218822Sdimsunos_link_dynamic_object (struct bfd_link_info *info ATTRIBUTE_UNUSED, 2088218822Sdim bfd *abfd ATTRIBUTE_UNUSED) 208959024Sobrien{ 2090130561Sobrien return TRUE; 209159024Sobrien} 209259024Sobrien 209359024Sobrien/* Write out a dynamic symbol. This is called by the final traversal 209459024Sobrien over the symbol table. */ 209559024Sobrien 2096130561Sobrienstatic bfd_boolean 2097218822Sdimsunos_write_dynamic_symbol (bfd *output_bfd, 2098218822Sdim struct bfd_link_info *info, 2099218822Sdim struct aout_link_hash_entry *harg) 210059024Sobrien{ 210159024Sobrien struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg; 210259024Sobrien int type; 210359024Sobrien bfd_vma val; 210459024Sobrien asection *s; 210559024Sobrien struct external_nlist *outsym; 210659024Sobrien 210759024Sobrien /* If this symbol is in the procedure linkage table, fill in the 210859024Sobrien table entry. */ 210959024Sobrien if (h->plt_offset != 0) 211059024Sobrien { 211159024Sobrien bfd *dynobj; 211259024Sobrien asection *splt; 211359024Sobrien bfd_byte *p; 211459024Sobrien bfd_vma r_address; 211559024Sobrien 211659024Sobrien dynobj = sunos_hash_table (info)->dynobj; 211759024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 211859024Sobrien p = splt->contents + h->plt_offset; 211959024Sobrien 212059024Sobrien s = bfd_get_section_by_name (dynobj, ".dynrel"); 212159024Sobrien 212259024Sobrien r_address = (splt->output_section->vma 212359024Sobrien + splt->output_offset 212459024Sobrien + h->plt_offset); 212559024Sobrien 212659024Sobrien switch (bfd_get_arch (output_bfd)) 212759024Sobrien { 212859024Sobrien case bfd_arch_sparc: 212959024Sobrien if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0) 213059024Sobrien { 213159024Sobrien bfd_put_32 (output_bfd, SPARC_PLT_ENTRY_WORD0, p); 213259024Sobrien bfd_put_32 (output_bfd, 213359024Sobrien (SPARC_PLT_ENTRY_WORD1 213459024Sobrien + (((- (h->plt_offset + 4) >> 2) 213559024Sobrien & 0x3fffffff))), 213659024Sobrien p + 4); 213759024Sobrien bfd_put_32 (output_bfd, SPARC_PLT_ENTRY_WORD2 + s->reloc_count, 213859024Sobrien p + 8); 213959024Sobrien } 214059024Sobrien else 214159024Sobrien { 214259024Sobrien val = (h->root.root.u.def.section->output_section->vma 214359024Sobrien + h->root.root.u.def.section->output_offset 214459024Sobrien + h->root.root.u.def.value); 214559024Sobrien bfd_put_32 (output_bfd, 214659024Sobrien SPARC_PLT_PIC_WORD0 + ((val >> 10) & 0x3fffff), 214759024Sobrien p); 214859024Sobrien bfd_put_32 (output_bfd, 214959024Sobrien SPARC_PLT_PIC_WORD1 + (val & 0x3ff), 215059024Sobrien p + 4); 215159024Sobrien bfd_put_32 (output_bfd, SPARC_PLT_PIC_WORD2, p + 8); 215259024Sobrien } 215359024Sobrien break; 215459024Sobrien 215559024Sobrien case bfd_arch_m68k: 215659024Sobrien if (! info->shared && (h->flags & SUNOS_DEF_REGULAR) != 0) 215759024Sobrien abort (); 215859024Sobrien bfd_put_16 (output_bfd, M68K_PLT_ENTRY_WORD0, p); 215959024Sobrien bfd_put_32 (output_bfd, (- (h->plt_offset + 2)), p + 2); 216089857Sobrien bfd_put_16 (output_bfd, (bfd_vma) s->reloc_count, p + 6); 216159024Sobrien r_address += 2; 216259024Sobrien break; 216359024Sobrien 216459024Sobrien default: 216559024Sobrien abort (); 216659024Sobrien } 216759024Sobrien 216859024Sobrien /* We also need to add a jump table reloc, unless this is the 2169130561Sobrien result of a JMP_TBL reloc from PIC compiled code. */ 217059024Sobrien if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0) 217159024Sobrien { 217259024Sobrien BFD_ASSERT (h->dynindx >= 0); 217359024Sobrien BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) 2174218822Sdim < s->size); 217559024Sobrien p = s->contents + s->reloc_count * obj_reloc_entry_size (output_bfd); 217659024Sobrien if (obj_reloc_entry_size (output_bfd) == RELOC_STD_SIZE) 217759024Sobrien { 217859024Sobrien struct reloc_std_external *srel; 217959024Sobrien 218059024Sobrien srel = (struct reloc_std_external *) p; 218159024Sobrien PUT_WORD (output_bfd, r_address, srel->r_address); 218259024Sobrien if (bfd_header_big_endian (output_bfd)) 218359024Sobrien { 218484865Sobrien srel->r_index[0] = (bfd_byte) (h->dynindx >> 16); 218584865Sobrien srel->r_index[1] = (bfd_byte) (h->dynindx >> 8); 218684865Sobrien srel->r_index[2] = (bfd_byte) (h->dynindx); 218759024Sobrien srel->r_type[0] = (RELOC_STD_BITS_EXTERN_BIG 218859024Sobrien | RELOC_STD_BITS_JMPTABLE_BIG); 218959024Sobrien } 219059024Sobrien else 219159024Sobrien { 219284865Sobrien srel->r_index[2] = (bfd_byte) (h->dynindx >> 16); 219384865Sobrien srel->r_index[1] = (bfd_byte) (h->dynindx >> 8); 219459024Sobrien srel->r_index[0] = (bfd_byte)h->dynindx; 219559024Sobrien srel->r_type[0] = (RELOC_STD_BITS_EXTERN_LITTLE 219659024Sobrien | RELOC_STD_BITS_JMPTABLE_LITTLE); 219759024Sobrien } 219859024Sobrien } 219959024Sobrien else 220059024Sobrien { 220159024Sobrien struct reloc_ext_external *erel; 220259024Sobrien 220359024Sobrien erel = (struct reloc_ext_external *) p; 220459024Sobrien PUT_WORD (output_bfd, r_address, erel->r_address); 220559024Sobrien if (bfd_header_big_endian (output_bfd)) 220659024Sobrien { 220784865Sobrien erel->r_index[0] = (bfd_byte) (h->dynindx >> 16); 220884865Sobrien erel->r_index[1] = (bfd_byte) (h->dynindx >> 8); 220959024Sobrien erel->r_index[2] = (bfd_byte)h->dynindx; 221059024Sobrien erel->r_type[0] = 221159024Sobrien (RELOC_EXT_BITS_EXTERN_BIG 221259024Sobrien | (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_BIG)); 221359024Sobrien } 221459024Sobrien else 221559024Sobrien { 221684865Sobrien erel->r_index[2] = (bfd_byte) (h->dynindx >> 16); 221784865Sobrien erel->r_index[1] = (bfd_byte) (h->dynindx >> 8); 221859024Sobrien erel->r_index[0] = (bfd_byte)h->dynindx; 221959024Sobrien erel->r_type[0] = 222059024Sobrien (RELOC_EXT_BITS_EXTERN_LITTLE 222159024Sobrien | (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_LITTLE)); 222259024Sobrien } 222359024Sobrien PUT_WORD (output_bfd, (bfd_vma) 0, erel->r_addend); 222459024Sobrien } 222559024Sobrien 222659024Sobrien ++s->reloc_count; 222759024Sobrien } 222859024Sobrien } 222959024Sobrien 223059024Sobrien /* If this is not a dynamic symbol, we don't have to do anything 223159024Sobrien else. We only check this after handling the PLT entry, because 223259024Sobrien we can have a PLT entry for a nondynamic symbol when linking PIC 223359024Sobrien compiled code from a regular object. */ 223459024Sobrien if (h->dynindx < 0) 2235130561Sobrien return TRUE; 223659024Sobrien 223759024Sobrien switch (h->root.root.type) 223859024Sobrien { 223959024Sobrien default: 224059024Sobrien case bfd_link_hash_new: 224159024Sobrien abort (); 224259024Sobrien /* Avoid variable not initialized warnings. */ 2243130561Sobrien return TRUE; 224459024Sobrien case bfd_link_hash_undefined: 224559024Sobrien type = N_UNDF | N_EXT; 224659024Sobrien val = 0; 224759024Sobrien break; 224859024Sobrien case bfd_link_hash_defined: 224959024Sobrien case bfd_link_hash_defweak: 225059024Sobrien { 225159024Sobrien asection *sec; 225259024Sobrien asection *output_section; 225359024Sobrien 225459024Sobrien sec = h->root.root.u.def.section; 225559024Sobrien output_section = sec->output_section; 225659024Sobrien BFD_ASSERT (bfd_is_abs_section (output_section) 225759024Sobrien || output_section->owner == output_bfd); 225859024Sobrien if (h->plt_offset != 0 225959024Sobrien && (h->flags & SUNOS_DEF_REGULAR) == 0) 226059024Sobrien { 226159024Sobrien type = N_UNDF | N_EXT; 226259024Sobrien val = 0; 226359024Sobrien } 226459024Sobrien else 226559024Sobrien { 226659024Sobrien if (output_section == obj_textsec (output_bfd)) 226759024Sobrien type = (h->root.root.type == bfd_link_hash_defined 226859024Sobrien ? N_TEXT 226959024Sobrien : N_WEAKT); 227059024Sobrien else if (output_section == obj_datasec (output_bfd)) 227159024Sobrien type = (h->root.root.type == bfd_link_hash_defined 227259024Sobrien ? N_DATA 227359024Sobrien : N_WEAKD); 227459024Sobrien else if (output_section == obj_bsssec (output_bfd)) 227559024Sobrien type = (h->root.root.type == bfd_link_hash_defined 227659024Sobrien ? N_BSS 227759024Sobrien : N_WEAKB); 227859024Sobrien else 227959024Sobrien type = (h->root.root.type == bfd_link_hash_defined 228059024Sobrien ? N_ABS 228159024Sobrien : N_WEAKA); 228259024Sobrien type |= N_EXT; 228359024Sobrien val = (h->root.root.u.def.value 228459024Sobrien + output_section->vma 228559024Sobrien + sec->output_offset); 228659024Sobrien } 228759024Sobrien } 228859024Sobrien break; 228959024Sobrien case bfd_link_hash_common: 229059024Sobrien type = N_UNDF | N_EXT; 229159024Sobrien val = h->root.root.u.c.size; 229259024Sobrien break; 229359024Sobrien case bfd_link_hash_undefweak: 229459024Sobrien type = N_WEAKU; 229559024Sobrien val = 0; 229659024Sobrien break; 229759024Sobrien case bfd_link_hash_indirect: 229859024Sobrien case bfd_link_hash_warning: 229959024Sobrien /* FIXME: Ignore these for now. The circumstances under which 230059024Sobrien they should be written out are not clear to me. */ 2301130561Sobrien return TRUE; 230259024Sobrien } 230359024Sobrien 230459024Sobrien s = bfd_get_section_by_name (sunos_hash_table (info)->dynobj, ".dynsym"); 230559024Sobrien BFD_ASSERT (s != NULL); 230659024Sobrien outsym = ((struct external_nlist *) 230759024Sobrien (s->contents + h->dynindx * EXTERNAL_NLIST_SIZE)); 230859024Sobrien 230989857Sobrien H_PUT_8 (output_bfd, type, outsym->e_type); 231089857Sobrien H_PUT_8 (output_bfd, 0, outsym->e_other); 231159024Sobrien 231259024Sobrien /* FIXME: The native linker doesn't use 0 for desc. It seems to use 231359024Sobrien one less than the desc value in the shared library, although that 231459024Sobrien seems unlikely. */ 231589857Sobrien H_PUT_16 (output_bfd, 0, outsym->e_desc); 231659024Sobrien 231759024Sobrien PUT_WORD (output_bfd, h->dynstr_index, outsym->e_strx); 231859024Sobrien PUT_WORD (output_bfd, val, outsym->e_value); 231959024Sobrien 2320130561Sobrien return TRUE; 232159024Sobrien} 232259024Sobrien 232359024Sobrien/* This is called for each reloc against an external symbol. If this 232459024Sobrien is a reloc which are are going to copy as a dynamic reloc, then 232559024Sobrien copy it over, and tell the caller to not bother processing this 232659024Sobrien reloc. */ 232759024Sobrien 2328130561Sobrienstatic bfd_boolean 2329218822Sdimsunos_check_dynamic_reloc (struct bfd_link_info *info, 2330218822Sdim bfd *input_bfd, 2331218822Sdim asection *input_section, 2332218822Sdim struct aout_link_hash_entry *harg, 2333218822Sdim void * reloc, 2334218822Sdim bfd_byte *contents ATTRIBUTE_UNUSED, 2335218822Sdim bfd_boolean *skip, 2336218822Sdim bfd_vma *relocationp) 233759024Sobrien{ 233859024Sobrien struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg; 233959024Sobrien bfd *dynobj; 2340130561Sobrien bfd_boolean baserel; 2341130561Sobrien bfd_boolean jmptbl; 2342130561Sobrien bfd_boolean pcrel; 234359024Sobrien asection *s; 234459024Sobrien bfd_byte *p; 234559024Sobrien long indx; 234659024Sobrien 2347130561Sobrien *skip = FALSE; 234859024Sobrien 234959024Sobrien dynobj = sunos_hash_table (info)->dynobj; 235059024Sobrien 235184865Sobrien if (h != NULL 235284865Sobrien && h->plt_offset != 0 235384865Sobrien && (info->shared 235484865Sobrien || (h->flags & SUNOS_DEF_REGULAR) == 0)) 235559024Sobrien { 235659024Sobrien asection *splt; 235759024Sobrien 235859024Sobrien /* Redirect the relocation to the PLT entry. */ 235959024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 236059024Sobrien *relocationp = (splt->output_section->vma 236159024Sobrien + splt->output_offset 236259024Sobrien + h->plt_offset); 236359024Sobrien } 236459024Sobrien 236559024Sobrien if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE) 236659024Sobrien { 236759024Sobrien struct reloc_std_external *srel; 236859024Sobrien 236959024Sobrien srel = (struct reloc_std_external *) reloc; 237059024Sobrien if (bfd_header_big_endian (input_bfd)) 237159024Sobrien { 237259024Sobrien baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG)); 237359024Sobrien jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG)); 237484865Sobrien pcrel = (0 != (srel->r_type[0] & RELOC_STD_BITS_PCREL_BIG)); 237559024Sobrien } 237659024Sobrien else 237759024Sobrien { 237859024Sobrien baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE)); 237959024Sobrien jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE)); 238084865Sobrien pcrel = (0 != (srel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE)); 238159024Sobrien } 238259024Sobrien } 238359024Sobrien else 238459024Sobrien { 238559024Sobrien struct reloc_ext_external *erel; 238659024Sobrien int r_type; 238759024Sobrien 238859024Sobrien erel = (struct reloc_ext_external *) reloc; 238959024Sobrien if (bfd_header_big_endian (input_bfd)) 239059024Sobrien r_type = ((erel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) 239159024Sobrien >> RELOC_EXT_BITS_TYPE_SH_BIG); 239259024Sobrien else 239359024Sobrien r_type = ((erel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) 239459024Sobrien >> RELOC_EXT_BITS_TYPE_SH_LITTLE); 239559024Sobrien baserel = (r_type == RELOC_BASE10 239659024Sobrien || r_type == RELOC_BASE13 239759024Sobrien || r_type == RELOC_BASE22); 239859024Sobrien jmptbl = r_type == RELOC_JMP_TBL; 239984865Sobrien pcrel = (r_type == RELOC_DISP8 240084865Sobrien || r_type == RELOC_DISP16 240184865Sobrien || r_type == RELOC_DISP32 240284865Sobrien || r_type == RELOC_WDISP30 240384865Sobrien || r_type == RELOC_WDISP22); 240484865Sobrien /* We don't consider the PC10 and PC22 types to be PC relative, 2405130561Sobrien because they are pcrel_offset. */ 240659024Sobrien } 240759024Sobrien 240859024Sobrien if (baserel) 240959024Sobrien { 241059024Sobrien bfd_vma *got_offsetp; 241159024Sobrien asection *sgot; 241259024Sobrien 241359024Sobrien if (h != NULL) 241459024Sobrien got_offsetp = &h->got_offset; 241559024Sobrien else if (adata (input_bfd).local_got_offsets == NULL) 241659024Sobrien got_offsetp = NULL; 241759024Sobrien else 241859024Sobrien { 241959024Sobrien struct reloc_std_external *srel; 242059024Sobrien int r_index; 242159024Sobrien 242259024Sobrien srel = (struct reloc_std_external *) reloc; 242359024Sobrien if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE) 242459024Sobrien { 242559024Sobrien if (bfd_header_big_endian (input_bfd)) 242659024Sobrien r_index = ((srel->r_index[0] << 16) 242759024Sobrien | (srel->r_index[1] << 8) 242859024Sobrien | srel->r_index[2]); 242959024Sobrien else 243059024Sobrien r_index = ((srel->r_index[2] << 16) 243159024Sobrien | (srel->r_index[1] << 8) 243259024Sobrien | srel->r_index[0]); 243359024Sobrien } 243459024Sobrien else 243559024Sobrien { 243659024Sobrien struct reloc_ext_external *erel; 243759024Sobrien 243859024Sobrien erel = (struct reloc_ext_external *) reloc; 243959024Sobrien if (bfd_header_big_endian (input_bfd)) 244059024Sobrien r_index = ((erel->r_index[0] << 16) 244159024Sobrien | (erel->r_index[1] << 8) 244259024Sobrien | erel->r_index[2]); 244359024Sobrien else 244459024Sobrien r_index = ((erel->r_index[2] << 16) 244559024Sobrien | (erel->r_index[1] << 8) 244659024Sobrien | erel->r_index[0]); 244759024Sobrien } 244859024Sobrien 244959024Sobrien got_offsetp = adata (input_bfd).local_got_offsets + r_index; 245059024Sobrien } 245159024Sobrien 245259024Sobrien BFD_ASSERT (got_offsetp != NULL && *got_offsetp != 0); 245359024Sobrien 245459024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 245559024Sobrien 245659024Sobrien /* We set the least significant bit to indicate whether we have 245759024Sobrien already initialized the GOT entry. */ 245859024Sobrien if ((*got_offsetp & 1) == 0) 245959024Sobrien { 246059024Sobrien if (h == NULL 246159024Sobrien || (! info->shared 246259024Sobrien && ((h->flags & SUNOS_DEF_DYNAMIC) == 0 246359024Sobrien || (h->flags & SUNOS_DEF_REGULAR) != 0))) 246459024Sobrien PUT_WORD (dynobj, *relocationp, sgot->contents + *got_offsetp); 246559024Sobrien else 246659024Sobrien PUT_WORD (dynobj, 0, sgot->contents + *got_offsetp); 246759024Sobrien 246859024Sobrien if (info->shared 246959024Sobrien || (h != NULL 247059024Sobrien && (h->flags & SUNOS_DEF_DYNAMIC) != 0 247159024Sobrien && (h->flags & SUNOS_DEF_REGULAR) == 0)) 247259024Sobrien { 247359024Sobrien /* We need to create a GLOB_DAT or 32 reloc to tell the 2474130561Sobrien dynamic linker to fill in this entry in the table. */ 247559024Sobrien 247659024Sobrien s = bfd_get_section_by_name (dynobj, ".dynrel"); 247759024Sobrien BFD_ASSERT (s != NULL); 247859024Sobrien BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) 2479218822Sdim < s->size); 248059024Sobrien 248159024Sobrien p = (s->contents 248259024Sobrien + s->reloc_count * obj_reloc_entry_size (dynobj)); 248359024Sobrien 248459024Sobrien if (h != NULL) 248559024Sobrien indx = h->dynindx; 248659024Sobrien else 248759024Sobrien indx = 0; 248859024Sobrien 248959024Sobrien if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE) 249059024Sobrien { 249159024Sobrien struct reloc_std_external *srel; 249259024Sobrien 249359024Sobrien srel = (struct reloc_std_external *) p; 249459024Sobrien PUT_WORD (dynobj, 249559024Sobrien (*got_offsetp 249659024Sobrien + sgot->output_section->vma 249759024Sobrien + sgot->output_offset), 249859024Sobrien srel->r_address); 249959024Sobrien if (bfd_header_big_endian (dynobj)) 250059024Sobrien { 250184865Sobrien srel->r_index[0] = (bfd_byte) (indx >> 16); 250284865Sobrien srel->r_index[1] = (bfd_byte) (indx >> 8); 250359024Sobrien srel->r_index[2] = (bfd_byte)indx; 250459024Sobrien if (h == NULL) 250559024Sobrien srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_BIG; 250659024Sobrien else 250759024Sobrien srel->r_type[0] = 250859024Sobrien (RELOC_STD_BITS_EXTERN_BIG 250959024Sobrien | RELOC_STD_BITS_BASEREL_BIG 251059024Sobrien | RELOC_STD_BITS_RELATIVE_BIG 251159024Sobrien | (2 << RELOC_STD_BITS_LENGTH_SH_BIG)); 251259024Sobrien } 251359024Sobrien else 251459024Sobrien { 251584865Sobrien srel->r_index[2] = (bfd_byte) (indx >> 16); 251684865Sobrien srel->r_index[1] = (bfd_byte) (indx >> 8); 251759024Sobrien srel->r_index[0] = (bfd_byte)indx; 251859024Sobrien if (h == NULL) 251959024Sobrien srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_LITTLE; 252059024Sobrien else 252159024Sobrien srel->r_type[0] = 252259024Sobrien (RELOC_STD_BITS_EXTERN_LITTLE 252359024Sobrien | RELOC_STD_BITS_BASEREL_LITTLE 252459024Sobrien | RELOC_STD_BITS_RELATIVE_LITTLE 252559024Sobrien | (2 << RELOC_STD_BITS_LENGTH_SH_LITTLE)); 252659024Sobrien } 252759024Sobrien } 252859024Sobrien else 252959024Sobrien { 253059024Sobrien struct reloc_ext_external *erel; 253159024Sobrien 253259024Sobrien erel = (struct reloc_ext_external *) p; 253359024Sobrien PUT_WORD (dynobj, 253459024Sobrien (*got_offsetp 253559024Sobrien + sgot->output_section->vma 253659024Sobrien + sgot->output_offset), 253759024Sobrien erel->r_address); 253859024Sobrien if (bfd_header_big_endian (dynobj)) 253959024Sobrien { 254084865Sobrien erel->r_index[0] = (bfd_byte) (indx >> 16); 254184865Sobrien erel->r_index[1] = (bfd_byte) (indx >> 8); 254259024Sobrien erel->r_index[2] = (bfd_byte)indx; 254359024Sobrien if (h == NULL) 254459024Sobrien erel->r_type[0] = 254559024Sobrien RELOC_32 << RELOC_EXT_BITS_TYPE_SH_BIG; 254659024Sobrien else 254759024Sobrien erel->r_type[0] = 254859024Sobrien (RELOC_EXT_BITS_EXTERN_BIG 254959024Sobrien | (RELOC_GLOB_DAT << RELOC_EXT_BITS_TYPE_SH_BIG)); 255059024Sobrien } 255159024Sobrien else 255259024Sobrien { 255384865Sobrien erel->r_index[2] = (bfd_byte) (indx >> 16); 255484865Sobrien erel->r_index[1] = (bfd_byte) (indx >> 8); 255559024Sobrien erel->r_index[0] = (bfd_byte)indx; 255659024Sobrien if (h == NULL) 255759024Sobrien erel->r_type[0] = 255859024Sobrien RELOC_32 << RELOC_EXT_BITS_TYPE_SH_LITTLE; 255959024Sobrien else 256059024Sobrien erel->r_type[0] = 256159024Sobrien (RELOC_EXT_BITS_EXTERN_LITTLE 256259024Sobrien | (RELOC_GLOB_DAT 256359024Sobrien << RELOC_EXT_BITS_TYPE_SH_LITTLE)); 256459024Sobrien } 256559024Sobrien PUT_WORD (dynobj, 0, erel->r_addend); 256659024Sobrien } 256759024Sobrien 256859024Sobrien ++s->reloc_count; 256959024Sobrien } 257059024Sobrien 257159024Sobrien *got_offsetp |= 1; 257259024Sobrien } 257359024Sobrien 257459024Sobrien *relocationp = (sgot->vma 257589857Sobrien + (*got_offsetp &~ (bfd_vma) 1) 257659024Sobrien - sunos_hash_table (info)->got_base); 257759024Sobrien 257859024Sobrien /* There is nothing else to do for a base relative reloc. */ 2579130561Sobrien return TRUE; 258059024Sobrien } 258159024Sobrien 258259024Sobrien if (! sunos_hash_table (info)->dynamic_sections_needed) 2583130561Sobrien return TRUE; 258459024Sobrien if (! info->shared) 258559024Sobrien { 258659024Sobrien if (h == NULL 258759024Sobrien || h->dynindx == -1 258859024Sobrien || h->root.root.type != bfd_link_hash_undefined 258959024Sobrien || (h->flags & SUNOS_DEF_REGULAR) != 0 259059024Sobrien || (h->flags & SUNOS_DEF_DYNAMIC) == 0 259159024Sobrien || (h->root.root.u.undef.abfd->flags & DYNAMIC) == 0) 2592130561Sobrien return TRUE; 259359024Sobrien } 259459024Sobrien else 259559024Sobrien { 259659024Sobrien if (h != NULL 259759024Sobrien && (h->dynindx == -1 259859024Sobrien || jmptbl 259959024Sobrien || strcmp (h->root.root.root.string, 260059024Sobrien "__GLOBAL_OFFSET_TABLE_") == 0)) 2601130561Sobrien return TRUE; 260259024Sobrien } 260359024Sobrien 260459024Sobrien /* It looks like this is a reloc we are supposed to copy. */ 260559024Sobrien 260659024Sobrien s = bfd_get_section_by_name (dynobj, ".dynrel"); 260759024Sobrien BFD_ASSERT (s != NULL); 2608218822Sdim BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) < s->size); 260959024Sobrien 261059024Sobrien p = s->contents + s->reloc_count * obj_reloc_entry_size (dynobj); 261159024Sobrien 261259024Sobrien /* Copy the reloc over. */ 261359024Sobrien memcpy (p, reloc, obj_reloc_entry_size (dynobj)); 261459024Sobrien 261559024Sobrien if (h != NULL) 261659024Sobrien indx = h->dynindx; 261759024Sobrien else 261859024Sobrien indx = 0; 261959024Sobrien 262059024Sobrien /* Adjust the address and symbol index. */ 262159024Sobrien if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE) 262259024Sobrien { 262359024Sobrien struct reloc_std_external *srel; 262459024Sobrien 262559024Sobrien srel = (struct reloc_std_external *) p; 262659024Sobrien PUT_WORD (dynobj, 262759024Sobrien (GET_WORD (dynobj, srel->r_address) 262859024Sobrien + input_section->output_section->vma 262959024Sobrien + input_section->output_offset), 263059024Sobrien srel->r_address); 263159024Sobrien if (bfd_header_big_endian (dynobj)) 263259024Sobrien { 263384865Sobrien srel->r_index[0] = (bfd_byte) (indx >> 16); 263484865Sobrien srel->r_index[1] = (bfd_byte) (indx >> 8); 263559024Sobrien srel->r_index[2] = (bfd_byte)indx; 263659024Sobrien } 263759024Sobrien else 263859024Sobrien { 263984865Sobrien srel->r_index[2] = (bfd_byte) (indx >> 16); 264084865Sobrien srel->r_index[1] = (bfd_byte) (indx >> 8); 264159024Sobrien srel->r_index[0] = (bfd_byte)indx; 264259024Sobrien } 264384865Sobrien /* FIXME: We may have to change the addend for a PC relative 2644130561Sobrien reloc. */ 264559024Sobrien } 264659024Sobrien else 264759024Sobrien { 264859024Sobrien struct reloc_ext_external *erel; 264959024Sobrien 265059024Sobrien erel = (struct reloc_ext_external *) p; 265159024Sobrien PUT_WORD (dynobj, 265259024Sobrien (GET_WORD (dynobj, erel->r_address) 265359024Sobrien + input_section->output_section->vma 265459024Sobrien + input_section->output_offset), 265559024Sobrien erel->r_address); 265659024Sobrien if (bfd_header_big_endian (dynobj)) 265759024Sobrien { 265884865Sobrien erel->r_index[0] = (bfd_byte) (indx >> 16); 265984865Sobrien erel->r_index[1] = (bfd_byte) (indx >> 8); 266059024Sobrien erel->r_index[2] = (bfd_byte)indx; 266159024Sobrien } 266259024Sobrien else 266359024Sobrien { 266484865Sobrien erel->r_index[2] = (bfd_byte) (indx >> 16); 266584865Sobrien erel->r_index[1] = (bfd_byte) (indx >> 8); 266659024Sobrien erel->r_index[0] = (bfd_byte)indx; 266759024Sobrien } 266884865Sobrien if (pcrel && h != NULL) 266984865Sobrien { 267084865Sobrien /* Adjust the addend for the change in address. */ 267184865Sobrien PUT_WORD (dynobj, 267284865Sobrien (GET_WORD (dynobj, erel->r_addend) 267384865Sobrien - (input_section->output_section->vma 267484865Sobrien + input_section->output_offset 267584865Sobrien - input_section->vma)), 267684865Sobrien erel->r_addend); 267784865Sobrien } 267859024Sobrien } 267959024Sobrien 268059024Sobrien ++s->reloc_count; 268159024Sobrien 268259024Sobrien if (h != NULL) 2683130561Sobrien *skip = TRUE; 268459024Sobrien 2685130561Sobrien return TRUE; 268659024Sobrien} 268759024Sobrien 268859024Sobrien/* Finish up the dynamic linking information. */ 268959024Sobrien 2690130561Sobrienstatic bfd_boolean 2691218822Sdimsunos_finish_dynamic_link (bfd *abfd, struct bfd_link_info *info) 269259024Sobrien{ 269359024Sobrien bfd *dynobj; 269459024Sobrien asection *o; 269559024Sobrien asection *s; 269659024Sobrien asection *sdyn; 269759024Sobrien 269859024Sobrien if (! sunos_hash_table (info)->dynamic_sections_needed 269959024Sobrien && ! sunos_hash_table (info)->got_needed) 2700130561Sobrien return TRUE; 270159024Sobrien 270259024Sobrien dynobj = sunos_hash_table (info)->dynobj; 270359024Sobrien 270459024Sobrien sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 270559024Sobrien BFD_ASSERT (sdyn != NULL); 270659024Sobrien 270759024Sobrien /* Finish up the .need section. The linker emulation code filled it 270859024Sobrien in, but with offsets from the start of the section instead of 270959024Sobrien real addresses. Now that we know the section location, we can 271059024Sobrien fill in the final values. */ 271159024Sobrien s = bfd_get_section_by_name (dynobj, ".need"); 2712218822Sdim if (s != NULL && s->size != 0) 271359024Sobrien { 271459024Sobrien file_ptr filepos; 271559024Sobrien bfd_byte *p; 271659024Sobrien 271759024Sobrien filepos = s->output_section->filepos + s->output_offset; 271859024Sobrien p = s->contents; 271959024Sobrien while (1) 272059024Sobrien { 272159024Sobrien bfd_vma val; 272259024Sobrien 272359024Sobrien PUT_WORD (dynobj, GET_WORD (dynobj, p) + filepos, p); 272459024Sobrien val = GET_WORD (dynobj, p + 12); 272559024Sobrien if (val == 0) 272659024Sobrien break; 272759024Sobrien PUT_WORD (dynobj, val + filepos, p + 12); 272859024Sobrien p += 16; 272959024Sobrien } 273059024Sobrien } 273159024Sobrien 273259024Sobrien /* The first entry in the .got section is the address of the 273359024Sobrien dynamic information, unless this is a shared library. */ 273459024Sobrien s = bfd_get_section_by_name (dynobj, ".got"); 273559024Sobrien BFD_ASSERT (s != NULL); 2736218822Sdim if (info->shared || sdyn->size == 0) 273759024Sobrien PUT_WORD (dynobj, 0, s->contents); 273859024Sobrien else 273959024Sobrien PUT_WORD (dynobj, sdyn->output_section->vma + sdyn->output_offset, 274059024Sobrien s->contents); 274159024Sobrien 274259024Sobrien for (o = dynobj->sections; o != NULL; o = o->next) 274359024Sobrien { 274459024Sobrien if ((o->flags & SEC_HAS_CONTENTS) != 0 274559024Sobrien && o->contents != NULL) 274659024Sobrien { 274759024Sobrien BFD_ASSERT (o->output_section != NULL 274859024Sobrien && o->output_section->owner == abfd); 274959024Sobrien if (! bfd_set_section_contents (abfd, o->output_section, 275089857Sobrien o->contents, 275189857Sobrien (file_ptr) o->output_offset, 2752218822Sdim o->size)) 2753130561Sobrien return FALSE; 275459024Sobrien } 275559024Sobrien } 275659024Sobrien 2757218822Sdim if (sdyn->size > 0) 275859024Sobrien { 275959024Sobrien struct external_sun4_dynamic esd; 276059024Sobrien struct external_sun4_dynamic_link esdl; 276189857Sobrien file_ptr pos; 276259024Sobrien 276359024Sobrien /* Finish up the dynamic link information. */ 276459024Sobrien PUT_WORD (dynobj, (bfd_vma) 3, esd.ld_version); 276559024Sobrien PUT_WORD (dynobj, 276659024Sobrien sdyn->output_section->vma + sdyn->output_offset + sizeof esd, 276759024Sobrien esd.ldd); 276859024Sobrien PUT_WORD (dynobj, 276959024Sobrien (sdyn->output_section->vma 277059024Sobrien + sdyn->output_offset 277159024Sobrien + sizeof esd 277259024Sobrien + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE), 277359024Sobrien esd.ld); 277459024Sobrien 277559024Sobrien if (! bfd_set_section_contents (abfd, sdyn->output_section, &esd, 277689857Sobrien (file_ptr) sdyn->output_offset, 277789857Sobrien (bfd_size_type) sizeof esd)) 2778130561Sobrien return FALSE; 277959024Sobrien 278059024Sobrien PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_loaded); 278159024Sobrien 278259024Sobrien s = bfd_get_section_by_name (dynobj, ".need"); 2783218822Sdim if (s == NULL || s->size == 0) 278459024Sobrien PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_need); 278559024Sobrien else 278659024Sobrien PUT_WORD (dynobj, s->output_section->filepos + s->output_offset, 278759024Sobrien esdl.ld_need); 278859024Sobrien 278959024Sobrien s = bfd_get_section_by_name (dynobj, ".rules"); 2790218822Sdim if (s == NULL || s->size == 0) 279159024Sobrien PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_rules); 279259024Sobrien else 279359024Sobrien PUT_WORD (dynobj, s->output_section->filepos + s->output_offset, 279459024Sobrien esdl.ld_rules); 279559024Sobrien 279659024Sobrien s = bfd_get_section_by_name (dynobj, ".got"); 279759024Sobrien BFD_ASSERT (s != NULL); 279859024Sobrien PUT_WORD (dynobj, s->output_section->vma + s->output_offset, 279959024Sobrien esdl.ld_got); 280059024Sobrien 280159024Sobrien s = bfd_get_section_by_name (dynobj, ".plt"); 280259024Sobrien BFD_ASSERT (s != NULL); 280359024Sobrien PUT_WORD (dynobj, s->output_section->vma + s->output_offset, 280459024Sobrien esdl.ld_plt); 2805218822Sdim PUT_WORD (dynobj, s->size, esdl.ld_plt_sz); 280659024Sobrien 280759024Sobrien s = bfd_get_section_by_name (dynobj, ".dynrel"); 280859024Sobrien BFD_ASSERT (s != NULL); 280959024Sobrien BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) 2810218822Sdim == s->size); 281159024Sobrien PUT_WORD (dynobj, s->output_section->filepos + s->output_offset, 281259024Sobrien esdl.ld_rel); 281359024Sobrien 281459024Sobrien s = bfd_get_section_by_name (dynobj, ".hash"); 281559024Sobrien BFD_ASSERT (s != NULL); 281659024Sobrien PUT_WORD (dynobj, s->output_section->filepos + s->output_offset, 281759024Sobrien esdl.ld_hash); 281859024Sobrien 281959024Sobrien s = bfd_get_section_by_name (dynobj, ".dynsym"); 282059024Sobrien BFD_ASSERT (s != NULL); 282159024Sobrien PUT_WORD (dynobj, s->output_section->filepos + s->output_offset, 282259024Sobrien esdl.ld_stab); 282359024Sobrien 282459024Sobrien PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_stab_hash); 282559024Sobrien 282659024Sobrien PUT_WORD (dynobj, (bfd_vma) sunos_hash_table (info)->bucketcount, 282759024Sobrien esdl.ld_buckets); 282859024Sobrien 282959024Sobrien s = bfd_get_section_by_name (dynobj, ".dynstr"); 283059024Sobrien BFD_ASSERT (s != NULL); 283159024Sobrien PUT_WORD (dynobj, s->output_section->filepos + s->output_offset, 283259024Sobrien esdl.ld_symbols); 2833218822Sdim PUT_WORD (dynobj, s->size, esdl.ld_symb_size); 283459024Sobrien 283559024Sobrien /* The size of the text area is the size of the .text section 283659024Sobrien rounded up to a page boundary. FIXME: Should the page size be 283759024Sobrien conditional on something? */ 283859024Sobrien PUT_WORD (dynobj, 2839218822Sdim BFD_ALIGN (obj_textsec (abfd)->size, 0x2000), 284059024Sobrien esdl.ld_text); 284184865Sobrien 284289857Sobrien pos = sdyn->output_offset; 284389857Sobrien pos += sizeof esd + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE; 284459024Sobrien if (! bfd_set_section_contents (abfd, sdyn->output_section, &esdl, 284589857Sobrien pos, (bfd_size_type) sizeof esdl)) 2846130561Sobrien return FALSE; 284759024Sobrien 284859024Sobrien abfd->flags |= DYNAMIC; 284959024Sobrien } 285059024Sobrien 2851130561Sobrien return TRUE; 285259024Sobrien} 2853