sunos.c revision 130561
159024Sobrien/* BFD backend for SunOS binaries. 289857Sobrien Copyright 1990, 1991, 1992, 1994, 1995, 1996, 1997, 1998, 2000, 2001, 3130561Sobrien 2002, 2003 Free Software Foundation, Inc. 459024Sobrien Written by Cygnus Support. 559024Sobrien 659024SobrienThis file is part of BFD, the Binary File Descriptor library. 759024Sobrien 859024SobrienThis program is free software; you can redistribute it and/or modify 959024Sobrienit under the terms of the GNU General Public License as published by 1059024Sobrienthe Free Software Foundation; either version 2 of the License, or 1159024Sobrien(at your option) any later version. 1259024Sobrien 1359024SobrienThis program is distributed in the hope that it will be useful, 1459024Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 1559024SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1659024SobrienGNU General Public License for more details. 1759024Sobrien 1859024SobrienYou should have received a copy of the GNU General Public License 1959024Sobrienalong with this program; if not, write to the Free Software 2059024SobrienFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/* Static routines defined in this file. */ 3459024Sobrien 35130561Sobrienstatic bfd_boolean sunos_read_dynamic_info PARAMS ((bfd *)); 3659024Sobrienstatic long sunos_get_dynamic_symtab_upper_bound PARAMS ((bfd *)); 37130561Sobrienstatic bfd_boolean sunos_slurp_dynamic_symtab PARAMS ((bfd *)); 3859024Sobrienstatic long sunos_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **)); 3959024Sobrienstatic long sunos_get_dynamic_reloc_upper_bound PARAMS ((bfd *)); 4059024Sobrienstatic long sunos_canonicalize_dynamic_reloc 4159024Sobrien PARAMS ((bfd *, arelent **, asymbol **)); 4259024Sobrienstatic struct bfd_hash_entry *sunos_link_hash_newfunc 4359024Sobrien PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); 4459024Sobrienstatic struct bfd_link_hash_table *sunos_link_hash_table_create 4559024Sobrien PARAMS ((bfd *)); 46130561Sobrienstatic bfd_boolean sunos_create_dynamic_sections 47130561Sobrien PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean)); 48130561Sobrienstatic bfd_boolean sunos_add_dynamic_symbols 4959024Sobrien PARAMS ((bfd *, struct bfd_link_info *, struct external_nlist **, 5059024Sobrien bfd_size_type *, char **)); 51130561Sobrienstatic bfd_boolean sunos_add_one_symbol 5259024Sobrien PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *, 53130561Sobrien bfd_vma, const char *, bfd_boolean, bfd_boolean, 5459024Sobrien struct bfd_link_hash_entry **)); 55130561Sobrienstatic bfd_boolean sunos_scan_relocs 5659024Sobrien PARAMS ((struct bfd_link_info *, bfd *, asection *, bfd_size_type)); 57130561Sobrienstatic bfd_boolean sunos_scan_std_relocs 5859024Sobrien PARAMS ((struct bfd_link_info *, bfd *, asection *, 5959024Sobrien const struct reloc_std_external *, bfd_size_type)); 60130561Sobrienstatic bfd_boolean sunos_scan_ext_relocs 6159024Sobrien PARAMS ((struct bfd_link_info *, bfd *, asection *, 6259024Sobrien const struct reloc_ext_external *, bfd_size_type)); 63130561Sobrienstatic bfd_boolean sunos_link_dynamic_object 6459024Sobrien PARAMS ((struct bfd_link_info *, bfd *)); 65130561Sobrienstatic bfd_boolean sunos_write_dynamic_symbol 6659024Sobrien PARAMS ((bfd *, struct bfd_link_info *, struct aout_link_hash_entry *)); 67130561Sobrienstatic bfd_boolean sunos_check_dynamic_reloc 6859024Sobrien PARAMS ((struct bfd_link_info *, bfd *, asection *, 69130561Sobrien struct aout_link_hash_entry *, PTR, bfd_byte *, bfd_boolean *, 7059024Sobrien bfd_vma *)); 71130561Sobrienstatic bfd_boolean sunos_finish_dynamic_link 7259024Sobrien PARAMS ((bfd *, struct bfd_link_info *)); 7359024Sobrien 7459024Sobrien#define MY_get_dynamic_symtab_upper_bound sunos_get_dynamic_symtab_upper_bound 7559024Sobrien#define MY_canonicalize_dynamic_symtab sunos_canonicalize_dynamic_symtab 7659024Sobrien#define MY_get_dynamic_reloc_upper_bound sunos_get_dynamic_reloc_upper_bound 7759024Sobrien#define MY_canonicalize_dynamic_reloc sunos_canonicalize_dynamic_reloc 7859024Sobrien#define MY_bfd_link_hash_table_create sunos_link_hash_table_create 7959024Sobrien#define MY_add_dynamic_symbols sunos_add_dynamic_symbols 8059024Sobrien#define MY_add_one_symbol sunos_add_one_symbol 8159024Sobrien#define MY_link_dynamic_object sunos_link_dynamic_object 8259024Sobrien#define MY_write_dynamic_symbol sunos_write_dynamic_symbol 8359024Sobrien#define MY_check_dynamic_reloc sunos_check_dynamic_reloc 8459024Sobrien#define MY_finish_dynamic_link sunos_finish_dynamic_link 8559024Sobrien 8659024Sobrien/* ??? Where should this go? */ 8759024Sobrien#define MACHTYPE_OK(mtype) \ 8859024Sobrien (((mtype) == M_SPARC && bfd_lookup_arch (bfd_arch_sparc, 0) != NULL) \ 8959024Sobrien || ((mtype) == M_SPARCLET \ 9059024Sobrien && bfd_lookup_arch (bfd_arch_sparc, bfd_mach_sparc_sparclet) != NULL) \ 9184865Sobrien || ((mtype) == M_SPARCLITE_LE \ 9284865Sobrien && bfd_lookup_arch (bfd_arch_sparc, bfd_mach_sparc_sparclet) != NULL) \ 9359024Sobrien || (((mtype) == M_UNKNOWN || (mtype) == M_68010 || (mtype) == M_68020) \ 9459024Sobrien && bfd_lookup_arch (bfd_arch_m68k, 0) != NULL)) 9559024Sobrien 9659024Sobrien/* Include the usual a.out support. */ 9759024Sobrien#include "aoutf1.h" 9859024Sobrien 9984865Sobrien/* The SunOS 4.1.4 /usr/include/locale.h defines valid as a macro. */ 10084865Sobrien#undef valid 10184865Sobrien 10259024Sobrien/* SunOS shared library support. We store a pointer to this structure 10359024Sobrien in obj_aout_dynamic_info (abfd). */ 10459024Sobrien 10559024Sobrienstruct sunos_dynamic_info 10659024Sobrien{ 10759024Sobrien /* Whether we found any dynamic information. */ 108130561Sobrien bfd_boolean valid; 10959024Sobrien /* Dynamic information. */ 11059024Sobrien struct internal_sun4_dynamic_link dyninfo; 11159024Sobrien /* Number of dynamic symbols. */ 11259024Sobrien unsigned long dynsym_count; 11359024Sobrien /* Read in nlists for dynamic symbols. */ 11459024Sobrien struct external_nlist *dynsym; 11559024Sobrien /* asymbol structures for dynamic symbols. */ 11659024Sobrien aout_symbol_type *canonical_dynsym; 11759024Sobrien /* Read in dynamic string table. */ 11859024Sobrien char *dynstr; 11959024Sobrien /* Number of dynamic relocs. */ 12059024Sobrien unsigned long dynrel_count; 12159024Sobrien /* Read in dynamic relocs. This may be reloc_std_external or 12259024Sobrien reloc_ext_external. */ 12359024Sobrien PTR dynrel; 12459024Sobrien /* arelent structures for dynamic relocs. */ 12559024Sobrien arelent *canonical_dynrel; 12659024Sobrien}; 12759024Sobrien 12859024Sobrien/* The hash table of dynamic symbols is composed of two word entries. 12959024Sobrien See include/aout/sun4.h for details. */ 13059024Sobrien 13159024Sobrien#define HASH_ENTRY_SIZE (2 * BYTES_IN_WORD) 13259024Sobrien 13359024Sobrien/* Read in the basic dynamic information. This locates the __DYNAMIC 13459024Sobrien structure and uses it to find the dynamic_link structure. It 13559024Sobrien creates and saves a sunos_dynamic_info structure. If it can't find 13659024Sobrien __DYNAMIC, it sets the valid field of the sunos_dynamic_info 137130561Sobrien structure to FALSE to avoid doing this work again. */ 13859024Sobrien 139130561Sobrienstatic bfd_boolean 14059024Sobriensunos_read_dynamic_info (abfd) 14159024Sobrien bfd *abfd; 14259024Sobrien{ 14359024Sobrien struct sunos_dynamic_info *info; 14459024Sobrien asection *dynsec; 14559024Sobrien bfd_vma dynoff; 14659024Sobrien struct external_sun4_dynamic dyninfo; 14759024Sobrien unsigned long dynver; 14859024Sobrien struct external_sun4_dynamic_link linkinfo; 14989857Sobrien bfd_size_type amt; 15059024Sobrien 15159024Sobrien if (obj_aout_dynamic_info (abfd) != (PTR) NULL) 152130561Sobrien return TRUE; 15359024Sobrien 15459024Sobrien if ((abfd->flags & DYNAMIC) == 0) 15559024Sobrien { 15659024Sobrien bfd_set_error (bfd_error_invalid_operation); 157130561Sobrien return FALSE; 15859024Sobrien } 15959024Sobrien 16089857Sobrien amt = sizeof (struct sunos_dynamic_info); 16189857Sobrien info = (struct sunos_dynamic_info *) bfd_zalloc (abfd, amt); 16259024Sobrien if (!info) 163130561Sobrien return FALSE; 164130561Sobrien info->valid = FALSE; 16559024Sobrien info->dynsym = NULL; 16659024Sobrien info->dynstr = NULL; 16759024Sobrien info->canonical_dynsym = NULL; 16859024Sobrien info->dynrel = NULL; 16959024Sobrien info->canonical_dynrel = NULL; 17059024Sobrien obj_aout_dynamic_info (abfd) = (PTR) info; 17159024Sobrien 17259024Sobrien /* This code used to look for the __DYNAMIC symbol to locate the dynamic 17359024Sobrien linking information. 17459024Sobrien However this inhibits recovering the dynamic symbols from a 17559024Sobrien stripped object file, so blindly assume that the dynamic linking 17659024Sobrien information is located at the start of the data section. 17759024Sobrien We could verify this assumption later by looking through the dynamic 17859024Sobrien symbols for the __DYNAMIC symbol. */ 17959024Sobrien if ((abfd->flags & DYNAMIC) == 0) 180130561Sobrien return TRUE; 18159024Sobrien if (! bfd_get_section_contents (abfd, obj_datasec (abfd), (PTR) &dyninfo, 18289857Sobrien (file_ptr) 0, 18389857Sobrien (bfd_size_type) sizeof dyninfo)) 184130561Sobrien return TRUE; 18559024Sobrien 18659024Sobrien dynver = GET_WORD (abfd, dyninfo.ld_version); 18759024Sobrien if (dynver != 2 && dynver != 3) 188130561Sobrien return TRUE; 18959024Sobrien 19059024Sobrien dynoff = GET_WORD (abfd, dyninfo.ld); 19159024Sobrien 19259024Sobrien /* dynoff is a virtual address. It is probably always in the .data 19359024Sobrien section, but this code should work even if it moves. */ 19459024Sobrien if (dynoff < bfd_get_section_vma (abfd, obj_datasec (abfd))) 19559024Sobrien dynsec = obj_textsec (abfd); 19659024Sobrien else 19759024Sobrien dynsec = obj_datasec (abfd); 19859024Sobrien dynoff -= bfd_get_section_vma (abfd, dynsec); 19959024Sobrien if (dynoff > bfd_section_size (abfd, dynsec)) 200130561Sobrien return TRUE; 20159024Sobrien 20259024Sobrien /* This executable appears to be dynamically linked in a way that we 20359024Sobrien can understand. */ 20489857Sobrien if (! bfd_get_section_contents (abfd, dynsec, (PTR) &linkinfo, 20589857Sobrien (file_ptr) dynoff, 20659024Sobrien (bfd_size_type) sizeof linkinfo)) 207130561Sobrien return TRUE; 20859024Sobrien 20959024Sobrien /* Swap in the dynamic link information. */ 21059024Sobrien info->dyninfo.ld_loaded = GET_WORD (abfd, linkinfo.ld_loaded); 21159024Sobrien info->dyninfo.ld_need = GET_WORD (abfd, linkinfo.ld_need); 21259024Sobrien info->dyninfo.ld_rules = GET_WORD (abfd, linkinfo.ld_rules); 21359024Sobrien info->dyninfo.ld_got = GET_WORD (abfd, linkinfo.ld_got); 21459024Sobrien info->dyninfo.ld_plt = GET_WORD (abfd, linkinfo.ld_plt); 21559024Sobrien info->dyninfo.ld_rel = GET_WORD (abfd, linkinfo.ld_rel); 21659024Sobrien info->dyninfo.ld_hash = GET_WORD (abfd, linkinfo.ld_hash); 21759024Sobrien info->dyninfo.ld_stab = GET_WORD (abfd, linkinfo.ld_stab); 21859024Sobrien info->dyninfo.ld_stab_hash = GET_WORD (abfd, linkinfo.ld_stab_hash); 21959024Sobrien info->dyninfo.ld_buckets = GET_WORD (abfd, linkinfo.ld_buckets); 22059024Sobrien info->dyninfo.ld_symbols = GET_WORD (abfd, linkinfo.ld_symbols); 22159024Sobrien info->dyninfo.ld_symb_size = GET_WORD (abfd, linkinfo.ld_symb_size); 22259024Sobrien info->dyninfo.ld_text = GET_WORD (abfd, linkinfo.ld_text); 22359024Sobrien info->dyninfo.ld_plt_sz = GET_WORD (abfd, linkinfo.ld_plt_sz); 22459024Sobrien 22559024Sobrien /* Reportedly the addresses need to be offset by the size of the 22659024Sobrien exec header in an NMAGIC file. */ 22759024Sobrien if (adata (abfd).magic == n_magic) 22859024Sobrien { 22959024Sobrien unsigned long exec_bytes_size = adata (abfd).exec_bytes_size; 23059024Sobrien 23159024Sobrien info->dyninfo.ld_need += exec_bytes_size; 23259024Sobrien info->dyninfo.ld_rules += exec_bytes_size; 23359024Sobrien info->dyninfo.ld_rel += exec_bytes_size; 23459024Sobrien info->dyninfo.ld_hash += exec_bytes_size; 23559024Sobrien info->dyninfo.ld_stab += exec_bytes_size; 23659024Sobrien info->dyninfo.ld_symbols += exec_bytes_size; 23759024Sobrien } 23859024Sobrien 23959024Sobrien /* The only way to get the size of the symbol information appears to 24059024Sobrien be to determine the distance between it and the string table. */ 24159024Sobrien info->dynsym_count = ((info->dyninfo.ld_symbols - info->dyninfo.ld_stab) 24259024Sobrien / EXTERNAL_NLIST_SIZE); 24359024Sobrien BFD_ASSERT (info->dynsym_count * EXTERNAL_NLIST_SIZE 24459024Sobrien == (unsigned long) (info->dyninfo.ld_symbols 24559024Sobrien - info->dyninfo.ld_stab)); 24659024Sobrien 24759024Sobrien /* Similarly, the relocs end at the hash table. */ 24859024Sobrien info->dynrel_count = ((info->dyninfo.ld_hash - info->dyninfo.ld_rel) 24959024Sobrien / obj_reloc_entry_size (abfd)); 25059024Sobrien BFD_ASSERT (info->dynrel_count * obj_reloc_entry_size (abfd) 25159024Sobrien == (unsigned long) (info->dyninfo.ld_hash 25259024Sobrien - info->dyninfo.ld_rel)); 25359024Sobrien 254130561Sobrien info->valid = TRUE; 25559024Sobrien 256130561Sobrien return TRUE; 25759024Sobrien} 25859024Sobrien 25959024Sobrien/* Return the amount of memory required for the dynamic symbols. */ 26059024Sobrien 26159024Sobrienstatic long 26259024Sobriensunos_get_dynamic_symtab_upper_bound (abfd) 26359024Sobrien bfd *abfd; 26459024Sobrien{ 26559024Sobrien struct sunos_dynamic_info *info; 26659024Sobrien 26759024Sobrien if (! sunos_read_dynamic_info (abfd)) 26859024Sobrien return -1; 26959024Sobrien 27059024Sobrien info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); 27159024Sobrien if (! info->valid) 27259024Sobrien { 27359024Sobrien bfd_set_error (bfd_error_no_symbols); 27459024Sobrien return -1; 27559024Sobrien } 27659024Sobrien 27759024Sobrien return (info->dynsym_count + 1) * sizeof (asymbol *); 27859024Sobrien} 27959024Sobrien 28059024Sobrien/* Read the external dynamic symbols. */ 28159024Sobrien 282130561Sobrienstatic bfd_boolean 28359024Sobriensunos_slurp_dynamic_symtab (abfd) 28459024Sobrien bfd *abfd; 28559024Sobrien{ 28659024Sobrien struct sunos_dynamic_info *info; 28789857Sobrien bfd_size_type amt; 28859024Sobrien 28959024Sobrien /* Get the general dynamic information. */ 29059024Sobrien if (obj_aout_dynamic_info (abfd) == NULL) 29159024Sobrien { 29259024Sobrien if (! sunos_read_dynamic_info (abfd)) 293130561Sobrien return FALSE; 29459024Sobrien } 29559024Sobrien 29659024Sobrien info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); 29759024Sobrien if (! info->valid) 29859024Sobrien { 29959024Sobrien bfd_set_error (bfd_error_no_symbols); 300130561Sobrien return FALSE; 30159024Sobrien } 30259024Sobrien 30359024Sobrien /* Get the dynamic nlist structures. */ 30459024Sobrien if (info->dynsym == (struct external_nlist *) NULL) 30559024Sobrien { 30689857Sobrien amt = (bfd_size_type) info->dynsym_count * EXTERNAL_NLIST_SIZE; 30789857Sobrien info->dynsym = (struct external_nlist *) bfd_alloc (abfd, amt); 30859024Sobrien if (info->dynsym == NULL && info->dynsym_count != 0) 309130561Sobrien return FALSE; 31089857Sobrien if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_stab, SEEK_SET) != 0 31189857Sobrien || bfd_bread ((PTR) info->dynsym, amt, abfd) != amt) 31259024Sobrien { 31359024Sobrien if (info->dynsym != NULL) 31459024Sobrien { 31559024Sobrien bfd_release (abfd, info->dynsym); 31659024Sobrien info->dynsym = NULL; 31759024Sobrien } 318130561Sobrien return FALSE; 31959024Sobrien } 32059024Sobrien } 32159024Sobrien 32259024Sobrien /* Get the dynamic strings. */ 32359024Sobrien if (info->dynstr == (char *) NULL) 32459024Sobrien { 32589857Sobrien amt = info->dyninfo.ld_symb_size; 32689857Sobrien info->dynstr = (char *) bfd_alloc (abfd, amt); 32759024Sobrien if (info->dynstr == NULL && info->dyninfo.ld_symb_size != 0) 328130561Sobrien return FALSE; 32989857Sobrien if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_symbols, SEEK_SET) != 0 33089857Sobrien || bfd_bread ((PTR) info->dynstr, amt, abfd) != amt) 33159024Sobrien { 33259024Sobrien if (info->dynstr != NULL) 33359024Sobrien { 33459024Sobrien bfd_release (abfd, info->dynstr); 33559024Sobrien info->dynstr = NULL; 33659024Sobrien } 337130561Sobrien return FALSE; 33859024Sobrien } 33959024Sobrien } 34059024Sobrien 341130561Sobrien return TRUE; 34259024Sobrien} 34359024Sobrien 34459024Sobrien/* Read in the dynamic symbols. */ 34559024Sobrien 34659024Sobrienstatic long 34759024Sobriensunos_canonicalize_dynamic_symtab (abfd, storage) 34859024Sobrien bfd *abfd; 34959024Sobrien asymbol **storage; 35059024Sobrien{ 35159024Sobrien struct sunos_dynamic_info *info; 35259024Sobrien unsigned long i; 35359024Sobrien 35459024Sobrien if (! sunos_slurp_dynamic_symtab (abfd)) 35559024Sobrien return -1; 35659024Sobrien 35759024Sobrien info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); 35859024Sobrien 35959024Sobrien#ifdef CHECK_DYNAMIC_HASH 36059024Sobrien /* Check my understanding of the dynamic hash table by making sure 36159024Sobrien that each symbol can be located in the hash table. */ 36259024Sobrien { 36359024Sobrien bfd_size_type table_size; 36459024Sobrien bfd_byte *table; 36559024Sobrien bfd_size_type i; 36659024Sobrien 36759024Sobrien if (info->dyninfo.ld_buckets > info->dynsym_count) 36859024Sobrien abort (); 36959024Sobrien table_size = info->dyninfo.ld_stab - info->dyninfo.ld_hash; 37059024Sobrien table = (bfd_byte *) bfd_malloc (table_size); 37159024Sobrien if (table == NULL && table_size != 0) 37259024Sobrien abort (); 37389857Sobrien if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_hash, SEEK_SET) != 0 37489857Sobrien || bfd_bread ((PTR) table, table_size, abfd) != table_size) 37559024Sobrien abort (); 37659024Sobrien for (i = 0; i < info->dynsym_count; i++) 37759024Sobrien { 37859024Sobrien unsigned char *name; 37959024Sobrien unsigned long hash; 38059024Sobrien 38159024Sobrien name = ((unsigned char *) info->dynstr 38259024Sobrien + GET_WORD (abfd, info->dynsym[i].e_strx)); 38359024Sobrien hash = 0; 38459024Sobrien while (*name != '\0') 38559024Sobrien hash = (hash << 1) + *name++; 38659024Sobrien hash &= 0x7fffffff; 38759024Sobrien hash %= info->dyninfo.ld_buckets; 38859024Sobrien while (GET_WORD (abfd, table + hash * HASH_ENTRY_SIZE) != i) 38959024Sobrien { 39059024Sobrien hash = GET_WORD (abfd, 39159024Sobrien table + hash * HASH_ENTRY_SIZE + BYTES_IN_WORD); 39259024Sobrien if (hash == 0 || hash >= table_size / HASH_ENTRY_SIZE) 39359024Sobrien abort (); 39459024Sobrien } 39559024Sobrien } 39659024Sobrien free (table); 39759024Sobrien } 39859024Sobrien#endif /* CHECK_DYNAMIC_HASH */ 39959024Sobrien 40059024Sobrien /* Get the asymbol structures corresponding to the dynamic nlist 40159024Sobrien structures. */ 40259024Sobrien if (info->canonical_dynsym == (aout_symbol_type *) NULL) 40359024Sobrien { 40489857Sobrien bfd_size_type size; 40589857Sobrien bfd_size_type strsize = info->dyninfo.ld_symb_size; 40689857Sobrien 40789857Sobrien size = (bfd_size_type) info->dynsym_count * sizeof (aout_symbol_type); 40889857Sobrien info->canonical_dynsym = (aout_symbol_type *) bfd_alloc (abfd, size); 40959024Sobrien if (info->canonical_dynsym == NULL && info->dynsym_count != 0) 41059024Sobrien return -1; 41159024Sobrien 41259024Sobrien if (! aout_32_translate_symbol_table (abfd, info->canonical_dynsym, 41389857Sobrien info->dynsym, 41489857Sobrien (bfd_size_type) info->dynsym_count, 415130561Sobrien info->dynstr, strsize, TRUE)) 41659024Sobrien { 41759024Sobrien if (info->canonical_dynsym != NULL) 41859024Sobrien { 41959024Sobrien bfd_release (abfd, info->canonical_dynsym); 42059024Sobrien info->canonical_dynsym = NULL; 42159024Sobrien } 42259024Sobrien return -1; 42359024Sobrien } 42459024Sobrien } 42559024Sobrien 42659024Sobrien /* Return pointers to the dynamic asymbol structures. */ 42759024Sobrien for (i = 0; i < info->dynsym_count; i++) 42859024Sobrien *storage++ = (asymbol *) (info->canonical_dynsym + i); 42959024Sobrien *storage = NULL; 43059024Sobrien 43159024Sobrien return info->dynsym_count; 43259024Sobrien} 43359024Sobrien 43459024Sobrien/* Return the amount of memory required for the dynamic relocs. */ 43559024Sobrien 43659024Sobrienstatic long 43759024Sobriensunos_get_dynamic_reloc_upper_bound (abfd) 43859024Sobrien bfd *abfd; 43959024Sobrien{ 44059024Sobrien struct sunos_dynamic_info *info; 44159024Sobrien 44259024Sobrien if (! sunos_read_dynamic_info (abfd)) 44359024Sobrien return -1; 44459024Sobrien 44559024Sobrien info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); 44659024Sobrien if (! info->valid) 44759024Sobrien { 44859024Sobrien bfd_set_error (bfd_error_no_symbols); 44959024Sobrien return -1; 45059024Sobrien } 45159024Sobrien 45259024Sobrien return (info->dynrel_count + 1) * sizeof (arelent *); 45359024Sobrien} 45459024Sobrien 45559024Sobrien/* Read in the dynamic relocs. */ 45659024Sobrien 45759024Sobrienstatic long 45859024Sobriensunos_canonicalize_dynamic_reloc (abfd, storage, syms) 45959024Sobrien bfd *abfd; 46059024Sobrien arelent **storage; 46159024Sobrien asymbol **syms; 46259024Sobrien{ 46359024Sobrien struct sunos_dynamic_info *info; 46459024Sobrien unsigned long i; 46589857Sobrien bfd_size_type size; 46659024Sobrien 46759024Sobrien /* Get the general dynamic information. */ 46859024Sobrien if (obj_aout_dynamic_info (abfd) == (PTR) NULL) 46959024Sobrien { 47059024Sobrien if (! sunos_read_dynamic_info (abfd)) 47159024Sobrien return -1; 47259024Sobrien } 47359024Sobrien 47459024Sobrien info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); 47559024Sobrien if (! info->valid) 47659024Sobrien { 47759024Sobrien bfd_set_error (bfd_error_no_symbols); 47859024Sobrien return -1; 47959024Sobrien } 48059024Sobrien 48159024Sobrien /* Get the dynamic reloc information. */ 48259024Sobrien if (info->dynrel == NULL) 48359024Sobrien { 48489857Sobrien size = (bfd_size_type) info->dynrel_count * obj_reloc_entry_size (abfd); 48589857Sobrien info->dynrel = (PTR) bfd_alloc (abfd, size); 48689857Sobrien if (info->dynrel == NULL && size != 0) 48759024Sobrien return -1; 48889857Sobrien if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_rel, SEEK_SET) != 0 48989857Sobrien || bfd_bread ((PTR) info->dynrel, size, abfd) != size) 49059024Sobrien { 49159024Sobrien if (info->dynrel != NULL) 49259024Sobrien { 49359024Sobrien bfd_release (abfd, info->dynrel); 49459024Sobrien info->dynrel = NULL; 49559024Sobrien } 49659024Sobrien return -1; 49759024Sobrien } 49859024Sobrien } 49959024Sobrien 50059024Sobrien /* Get the arelent structures corresponding to the dynamic reloc 50159024Sobrien information. */ 50259024Sobrien if (info->canonical_dynrel == (arelent *) NULL) 50359024Sobrien { 50459024Sobrien arelent *to; 50559024Sobrien 50689857Sobrien size = (bfd_size_type) info->dynrel_count * sizeof (arelent); 50789857Sobrien info->canonical_dynrel = (arelent *) bfd_alloc (abfd, size); 50859024Sobrien if (info->canonical_dynrel == NULL && info->dynrel_count != 0) 50959024Sobrien return -1; 51084865Sobrien 51159024Sobrien to = info->canonical_dynrel; 51259024Sobrien 51359024Sobrien if (obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE) 51459024Sobrien { 51559024Sobrien register struct reloc_ext_external *p; 51659024Sobrien struct reloc_ext_external *pend; 51759024Sobrien 51859024Sobrien p = (struct reloc_ext_external *) info->dynrel; 51959024Sobrien pend = p + info->dynrel_count; 52059024Sobrien for (; p < pend; p++, to++) 52159024Sobrien NAME(aout,swap_ext_reloc_in) (abfd, p, to, syms, 52289857Sobrien (bfd_size_type) info->dynsym_count); 52359024Sobrien } 52459024Sobrien else 52559024Sobrien { 52659024Sobrien register struct reloc_std_external *p; 52759024Sobrien struct reloc_std_external *pend; 52859024Sobrien 52959024Sobrien p = (struct reloc_std_external *) info->dynrel; 53059024Sobrien pend = p + info->dynrel_count; 53159024Sobrien for (; p < pend; p++, to++) 53259024Sobrien NAME(aout,swap_std_reloc_in) (abfd, p, to, syms, 53389857Sobrien (bfd_size_type) info->dynsym_count); 53459024Sobrien } 53559024Sobrien } 53659024Sobrien 53759024Sobrien /* Return pointers to the dynamic arelent structures. */ 53859024Sobrien for (i = 0; i < info->dynrel_count; i++) 53959024Sobrien *storage++ = info->canonical_dynrel + i; 54059024Sobrien *storage = NULL; 54159024Sobrien 54259024Sobrien return info->dynrel_count; 54359024Sobrien} 54459024Sobrien 54559024Sobrien/* Code to handle linking of SunOS shared libraries. */ 54659024Sobrien 54759024Sobrien/* A SPARC procedure linkage table entry is 12 bytes. The first entry 54859024Sobrien in the table is a jump which is filled in by the runtime linker. 54959024Sobrien The remaining entries are branches back to the first entry, 55059024Sobrien followed by an index into the relocation table encoded to look like 55159024Sobrien a sethi of %g0. */ 55259024Sobrien 55359024Sobrien#define SPARC_PLT_ENTRY_SIZE (12) 55459024Sobrien 55559024Sobrienstatic const bfd_byte sparc_plt_first_entry[SPARC_PLT_ENTRY_SIZE] = 55659024Sobrien{ 55759024Sobrien /* sethi %hi(0),%g1; address filled in by runtime linker. */ 55859024Sobrien 0x3, 0, 0, 0, 55959024Sobrien /* jmp %g1; offset filled in by runtime linker. */ 56059024Sobrien 0x81, 0xc0, 0x60, 0, 56159024Sobrien /* nop */ 56259024Sobrien 0x1, 0, 0, 0 56359024Sobrien}; 56459024Sobrien 56559024Sobrien/* save %sp, -96, %sp */ 56689857Sobrien#define SPARC_PLT_ENTRY_WORD0 ((bfd_vma) 0x9de3bfa0) 56759024Sobrien/* call; address filled in later. */ 56889857Sobrien#define SPARC_PLT_ENTRY_WORD1 ((bfd_vma) 0x40000000) 56959024Sobrien/* sethi; reloc index filled in later. */ 57089857Sobrien#define SPARC_PLT_ENTRY_WORD2 ((bfd_vma) 0x01000000) 57159024Sobrien 57259024Sobrien/* This sequence is used when for the jump table entry to a defined 57359024Sobrien symbol in a complete executable. It is used when linking PIC 57459024Sobrien compiled code which is not being put into a shared library. */ 57559024Sobrien/* sethi <address to be filled in later>, %g1 */ 57689857Sobrien#define SPARC_PLT_PIC_WORD0 ((bfd_vma) 0x03000000) 57759024Sobrien/* jmp %g1 + <address to be filled in later> */ 57889857Sobrien#define SPARC_PLT_PIC_WORD1 ((bfd_vma) 0x81c06000) 57959024Sobrien/* nop */ 58089857Sobrien#define SPARC_PLT_PIC_WORD2 ((bfd_vma) 0x01000000) 58159024Sobrien 58259024Sobrien/* An m68k procedure linkage table entry is 8 bytes. The first entry 58359024Sobrien in the table is a jump which is filled in the by the runtime 58459024Sobrien linker. The remaining entries are branches back to the first 58559024Sobrien entry, followed by a two byte index into the relocation table. */ 58659024Sobrien 58759024Sobrien#define M68K_PLT_ENTRY_SIZE (8) 58859024Sobrien 58959024Sobrienstatic const bfd_byte m68k_plt_first_entry[M68K_PLT_ENTRY_SIZE] = 59059024Sobrien{ 59159024Sobrien /* jmps @# */ 59259024Sobrien 0x4e, 0xf9, 59359024Sobrien /* Filled in by runtime linker with a magic address. */ 59459024Sobrien 0, 0, 0, 0, 59559024Sobrien /* Not used? */ 59659024Sobrien 0, 0 59759024Sobrien}; 59859024Sobrien 59959024Sobrien/* bsrl */ 60089857Sobrien#define M68K_PLT_ENTRY_WORD0 ((bfd_vma) 0x61ff) 60159024Sobrien/* Remaining words filled in later. */ 60259024Sobrien 60359024Sobrien/* An entry in the SunOS linker hash table. */ 60459024Sobrien 60559024Sobrienstruct sunos_link_hash_entry 60659024Sobrien{ 60759024Sobrien struct aout_link_hash_entry root; 60859024Sobrien 60959024Sobrien /* If this is a dynamic symbol, this is its index into the dynamic 61059024Sobrien symbol table. This is initialized to -1. As the linker looks at 61159024Sobrien the input files, it changes this to -2 if it will be added to the 61259024Sobrien dynamic symbol table. After all the input files have been seen, 61359024Sobrien the linker will know whether to build a dynamic symbol table; if 61459024Sobrien it does build one, this becomes the index into the table. */ 61559024Sobrien long dynindx; 61659024Sobrien 61759024Sobrien /* If this is a dynamic symbol, this is the index of the name in the 61859024Sobrien dynamic symbol string table. */ 61959024Sobrien long dynstr_index; 62059024Sobrien 62159024Sobrien /* The offset into the global offset table used for this symbol. If 62259024Sobrien the symbol does not require a GOT entry, this is 0. */ 62359024Sobrien bfd_vma got_offset; 62459024Sobrien 62559024Sobrien /* The offset into the procedure linkage table used for this symbol. 62659024Sobrien If the symbol does not require a PLT entry, this is 0. */ 62759024Sobrien bfd_vma plt_offset; 62859024Sobrien 62959024Sobrien /* Some linker flags. */ 63059024Sobrien unsigned char flags; 63159024Sobrien /* Symbol is referenced by a regular object. */ 63259024Sobrien#define SUNOS_REF_REGULAR 01 63359024Sobrien /* Symbol is defined by a regular object. */ 63459024Sobrien#define SUNOS_DEF_REGULAR 02 63559024Sobrien /* Symbol is referenced by a dynamic object. */ 63659024Sobrien#define SUNOS_REF_DYNAMIC 04 63759024Sobrien /* Symbol is defined by a dynamic object. */ 63859024Sobrien#define SUNOS_DEF_DYNAMIC 010 63959024Sobrien /* Symbol is a constructor symbol in a regular object. */ 64059024Sobrien#define SUNOS_CONSTRUCTOR 020 64159024Sobrien}; 64259024Sobrien 64359024Sobrien/* The SunOS linker hash table. */ 64459024Sobrien 64559024Sobrienstruct sunos_link_hash_table 64659024Sobrien{ 64759024Sobrien struct aout_link_hash_table root; 64859024Sobrien 64959024Sobrien /* The object which holds the dynamic sections. */ 65059024Sobrien bfd *dynobj; 65159024Sobrien 65259024Sobrien /* Whether we have created the dynamic sections. */ 653130561Sobrien bfd_boolean dynamic_sections_created; 65459024Sobrien 65559024Sobrien /* Whether we need the dynamic sections. */ 656130561Sobrien bfd_boolean dynamic_sections_needed; 65759024Sobrien 65859024Sobrien /* Whether we need the .got table. */ 659130561Sobrien bfd_boolean got_needed; 66059024Sobrien 66159024Sobrien /* The number of dynamic symbols. */ 66259024Sobrien size_t dynsymcount; 66359024Sobrien 66459024Sobrien /* The number of buckets in the hash table. */ 66559024Sobrien size_t bucketcount; 66659024Sobrien 66759024Sobrien /* The list of dynamic objects needed by dynamic objects included in 66859024Sobrien the link. */ 66959024Sobrien struct bfd_link_needed_list *needed; 67059024Sobrien 67159024Sobrien /* The offset of __GLOBAL_OFFSET_TABLE_ into the .got section. */ 67259024Sobrien bfd_vma got_base; 67359024Sobrien}; 67459024Sobrien 67559024Sobrien/* Routine to create an entry in an SunOS link hash table. */ 67659024Sobrien 67759024Sobrienstatic struct bfd_hash_entry * 67859024Sobriensunos_link_hash_newfunc (entry, table, string) 67959024Sobrien struct bfd_hash_entry *entry; 68059024Sobrien struct bfd_hash_table *table; 68159024Sobrien const char *string; 68259024Sobrien{ 68359024Sobrien struct sunos_link_hash_entry *ret = (struct sunos_link_hash_entry *) entry; 68459024Sobrien 68559024Sobrien /* Allocate the structure if it has not already been allocated by a 68659024Sobrien subclass. */ 68759024Sobrien if (ret == (struct sunos_link_hash_entry *) NULL) 68859024Sobrien ret = ((struct sunos_link_hash_entry *) 68959024Sobrien bfd_hash_allocate (table, sizeof (struct sunos_link_hash_entry))); 69059024Sobrien if (ret == (struct sunos_link_hash_entry *) NULL) 69159024Sobrien return (struct bfd_hash_entry *) ret; 69259024Sobrien 69359024Sobrien /* Call the allocation method of the superclass. */ 69459024Sobrien ret = ((struct sunos_link_hash_entry *) 69559024Sobrien NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret, 69659024Sobrien table, string)); 69759024Sobrien if (ret != NULL) 69859024Sobrien { 69959024Sobrien /* Set local fields. */ 70059024Sobrien ret->dynindx = -1; 70159024Sobrien ret->dynstr_index = -1; 70259024Sobrien ret->got_offset = 0; 70359024Sobrien ret->plt_offset = 0; 70459024Sobrien ret->flags = 0; 70559024Sobrien } 70659024Sobrien 70759024Sobrien return (struct bfd_hash_entry *) ret; 70859024Sobrien} 70959024Sobrien 71059024Sobrien/* Create a SunOS link hash table. */ 71159024Sobrien 71259024Sobrienstatic struct bfd_link_hash_table * 71359024Sobriensunos_link_hash_table_create (abfd) 71459024Sobrien bfd *abfd; 71559024Sobrien{ 71659024Sobrien struct sunos_link_hash_table *ret; 71789857Sobrien bfd_size_type amt = sizeof (struct sunos_link_hash_table); 71859024Sobrien 719104834Sobrien ret = (struct sunos_link_hash_table *) bfd_malloc (amt); 72059024Sobrien if (ret == (struct sunos_link_hash_table *) NULL) 72159024Sobrien return (struct bfd_link_hash_table *) NULL; 72259024Sobrien if (! NAME(aout,link_hash_table_init) (&ret->root, abfd, 72359024Sobrien sunos_link_hash_newfunc)) 72459024Sobrien { 725104834Sobrien free (ret); 72659024Sobrien return (struct bfd_link_hash_table *) NULL; 72759024Sobrien } 72859024Sobrien 72959024Sobrien ret->dynobj = NULL; 730130561Sobrien ret->dynamic_sections_created = FALSE; 731130561Sobrien ret->dynamic_sections_needed = FALSE; 732130561Sobrien ret->got_needed = FALSE; 73359024Sobrien ret->dynsymcount = 0; 73459024Sobrien ret->bucketcount = 0; 73559024Sobrien ret->needed = NULL; 73659024Sobrien ret->got_base = 0; 73759024Sobrien 73859024Sobrien return &ret->root.root; 73959024Sobrien} 74059024Sobrien 74159024Sobrien/* Look up an entry in an SunOS link hash table. */ 74259024Sobrien 74359024Sobrien#define sunos_link_hash_lookup(table, string, create, copy, follow) \ 74459024Sobrien ((struct sunos_link_hash_entry *) \ 74559024Sobrien aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\ 74659024Sobrien (follow))) 74759024Sobrien 74859024Sobrien/* Traverse a SunOS link hash table. */ 74959024Sobrien 75059024Sobrien#define sunos_link_hash_traverse(table, func, info) \ 75159024Sobrien (aout_link_hash_traverse \ 75259024Sobrien (&(table)->root, \ 753130561Sobrien (bfd_boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \ 75459024Sobrien (info))) 75559024Sobrien 75659024Sobrien/* Get the SunOS link hash table from the info structure. This is 75759024Sobrien just a cast. */ 75859024Sobrien 75959024Sobrien#define sunos_hash_table(p) ((struct sunos_link_hash_table *) ((p)->hash)) 76059024Sobrien 761130561Sobrienstatic bfd_boolean sunos_scan_dynamic_symbol 76259024Sobrien PARAMS ((struct sunos_link_hash_entry *, PTR)); 76359024Sobrien 76459024Sobrien/* Create the dynamic sections needed if we are linking against a 76559024Sobrien dynamic object, or if we are linking PIC compiled code. ABFD is a 76659024Sobrien bfd we can attach the dynamic sections to. The linker script will 76759024Sobrien look for these special sections names and put them in the right 76859024Sobrien place in the output file. See include/aout/sun4.h for more details 76959024Sobrien of the dynamic linking information. */ 77059024Sobrien 771130561Sobrienstatic bfd_boolean 77259024Sobriensunos_create_dynamic_sections (abfd, info, needed) 77359024Sobrien bfd *abfd; 77459024Sobrien struct bfd_link_info *info; 775130561Sobrien bfd_boolean needed; 77659024Sobrien{ 77759024Sobrien asection *s; 77859024Sobrien 77959024Sobrien if (! sunos_hash_table (info)->dynamic_sections_created) 78059024Sobrien { 78159024Sobrien flagword flags; 78259024Sobrien 78359024Sobrien sunos_hash_table (info)->dynobj = abfd; 78459024Sobrien 78559024Sobrien flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY 78659024Sobrien | SEC_LINKER_CREATED); 78759024Sobrien 78859024Sobrien /* The .dynamic section holds the basic dynamic information: the 78959024Sobrien sun4_dynamic structure, the dynamic debugger information, and 79059024Sobrien the sun4_dynamic_link structure. */ 79159024Sobrien s = bfd_make_section (abfd, ".dynamic"); 79259024Sobrien if (s == NULL 79359024Sobrien || ! bfd_set_section_flags (abfd, s, flags) 79459024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 795130561Sobrien return FALSE; 79659024Sobrien 79759024Sobrien /* The .got section holds the global offset table. The address 79859024Sobrien is put in the ld_got field. */ 79959024Sobrien s = bfd_make_section (abfd, ".got"); 80059024Sobrien if (s == NULL 80159024Sobrien || ! bfd_set_section_flags (abfd, s, flags) 80259024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 803130561Sobrien return FALSE; 80459024Sobrien 80559024Sobrien /* The .plt section holds the procedure linkage table. The 80659024Sobrien address is put in the ld_plt field. */ 80759024Sobrien s = bfd_make_section (abfd, ".plt"); 80859024Sobrien if (s == NULL 80959024Sobrien || ! bfd_set_section_flags (abfd, s, flags | SEC_CODE) 81059024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 811130561Sobrien return FALSE; 81259024Sobrien 81359024Sobrien /* The .dynrel section holds the dynamic relocs. The address is 81459024Sobrien put in the ld_rel field. */ 81559024Sobrien s = bfd_make_section (abfd, ".dynrel"); 81659024Sobrien if (s == NULL 81759024Sobrien || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) 81859024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 819130561Sobrien return FALSE; 82059024Sobrien 82159024Sobrien /* The .hash section holds the dynamic hash table. The address 82259024Sobrien is put in the ld_hash field. */ 82359024Sobrien s = bfd_make_section (abfd, ".hash"); 82459024Sobrien if (s == NULL 82559024Sobrien || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) 82659024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 827130561Sobrien return FALSE; 82859024Sobrien 82959024Sobrien /* The .dynsym section holds the dynamic symbols. The address 83059024Sobrien is put in the ld_stab field. */ 83159024Sobrien s = bfd_make_section (abfd, ".dynsym"); 83259024Sobrien if (s == NULL 83359024Sobrien || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) 83459024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 835130561Sobrien return FALSE; 83659024Sobrien 83759024Sobrien /* The .dynstr section holds the dynamic symbol string table. 83859024Sobrien The address is put in the ld_symbols field. */ 83959024Sobrien s = bfd_make_section (abfd, ".dynstr"); 84059024Sobrien if (s == NULL 84159024Sobrien || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) 84259024Sobrien || ! bfd_set_section_alignment (abfd, s, 2)) 843130561Sobrien return FALSE; 84459024Sobrien 845130561Sobrien sunos_hash_table (info)->dynamic_sections_created = TRUE; 84659024Sobrien } 84759024Sobrien 84859024Sobrien if ((needed && ! sunos_hash_table (info)->dynamic_sections_needed) 84959024Sobrien || info->shared) 85059024Sobrien { 85159024Sobrien bfd *dynobj; 85259024Sobrien 85359024Sobrien dynobj = sunos_hash_table (info)->dynobj; 85459024Sobrien 85559024Sobrien s = bfd_get_section_by_name (dynobj, ".got"); 85659024Sobrien if (s->_raw_size == 0) 85759024Sobrien s->_raw_size = BYTES_IN_WORD; 85859024Sobrien 859130561Sobrien sunos_hash_table (info)->dynamic_sections_needed = TRUE; 860130561Sobrien sunos_hash_table (info)->got_needed = TRUE; 86159024Sobrien } 86259024Sobrien 863130561Sobrien return TRUE; 86459024Sobrien} 86559024Sobrien 86659024Sobrien/* Add dynamic symbols during a link. This is called by the a.out 86759024Sobrien backend linker for each object it encounters. */ 86859024Sobrien 869130561Sobrienstatic bfd_boolean 87059024Sobriensunos_add_dynamic_symbols (abfd, info, symsp, sym_countp, stringsp) 87159024Sobrien bfd *abfd; 87259024Sobrien struct bfd_link_info *info; 87359024Sobrien struct external_nlist **symsp; 87459024Sobrien bfd_size_type *sym_countp; 87559024Sobrien char **stringsp; 87659024Sobrien{ 87759024Sobrien bfd *dynobj; 87859024Sobrien struct sunos_dynamic_info *dinfo; 87959024Sobrien unsigned long need; 88089857Sobrien asection **ps; 88159024Sobrien 88259024Sobrien /* Make sure we have all the required sections. */ 88359024Sobrien if (info->hash->creator == abfd->xvec) 88459024Sobrien { 88559024Sobrien if (! sunos_create_dynamic_sections (abfd, info, 886130561Sobrien ((abfd->flags & DYNAMIC) != 0 887130561Sobrien && !info->relocatable))) 888130561Sobrien return FALSE; 88959024Sobrien } 89059024Sobrien 89159024Sobrien /* There is nothing else to do for a normal object. */ 89259024Sobrien if ((abfd->flags & DYNAMIC) == 0) 893130561Sobrien return TRUE; 89459024Sobrien 89559024Sobrien dynobj = sunos_hash_table (info)->dynobj; 89659024Sobrien 89759024Sobrien /* We do not want to include the sections in a dynamic object in the 89859024Sobrien output file. We hack by simply clobbering the list of sections 89959024Sobrien in the BFD. This could be handled more cleanly by, say, a new 90059024Sobrien section flag; the existing SEC_NEVER_LOAD flag is not the one we 90159024Sobrien want, because that one still implies that the section takes up 90259024Sobrien space in the output file. If this is the first object we have 90359024Sobrien seen, we must preserve the dynamic sections we just created. */ 90489857Sobrien for (ps = &abfd->sections; *ps != NULL; ) 90559024Sobrien { 90689857Sobrien if (abfd != dynobj || ((*ps)->flags & SEC_LINKER_CREATED) == 0) 90789857Sobrien bfd_section_list_remove (abfd, ps); 90889857Sobrien else 90989857Sobrien ps = &(*ps)->next; 91059024Sobrien } 91159024Sobrien 91259024Sobrien /* The native linker seems to just ignore dynamic objects when -r is 91359024Sobrien used. */ 914130561Sobrien if (info->relocatable) 915130561Sobrien return TRUE; 91659024Sobrien 91759024Sobrien /* There's no hope of using a dynamic object which does not exactly 91859024Sobrien match the format of the output file. */ 91959024Sobrien if (info->hash->creator != abfd->xvec) 92059024Sobrien { 92159024Sobrien bfd_set_error (bfd_error_invalid_operation); 922130561Sobrien return FALSE; 92359024Sobrien } 92459024Sobrien 92559024Sobrien /* Make sure we have a .need and a .rules sections. These are only 92659024Sobrien needed if there really is a dynamic object in the link, so they 92759024Sobrien are not added by sunos_create_dynamic_sections. */ 92859024Sobrien if (bfd_get_section_by_name (dynobj, ".need") == NULL) 92959024Sobrien { 93059024Sobrien /* The .need section holds the list of names of shared objets 93159024Sobrien which must be included at runtime. The address of this 93259024Sobrien section is put in the ld_need field. */ 93389857Sobrien asection *s = bfd_make_section (dynobj, ".need"); 93459024Sobrien if (s == NULL 93559024Sobrien || ! bfd_set_section_flags (dynobj, s, 93659024Sobrien (SEC_ALLOC 93759024Sobrien | SEC_LOAD 93859024Sobrien | SEC_HAS_CONTENTS 93959024Sobrien | SEC_IN_MEMORY 94059024Sobrien | SEC_READONLY)) 94159024Sobrien || ! bfd_set_section_alignment (dynobj, s, 2)) 942130561Sobrien return FALSE; 94359024Sobrien } 94459024Sobrien 94559024Sobrien if (bfd_get_section_by_name (dynobj, ".rules") == NULL) 94659024Sobrien { 94759024Sobrien /* The .rules section holds the path to search for shared 94859024Sobrien objects. The address of this section is put in the ld_rules 94959024Sobrien field. */ 95089857Sobrien asection *s = bfd_make_section (dynobj, ".rules"); 95159024Sobrien if (s == NULL 95259024Sobrien || ! bfd_set_section_flags (dynobj, s, 95359024Sobrien (SEC_ALLOC 95459024Sobrien | SEC_LOAD 95559024Sobrien | SEC_HAS_CONTENTS 95659024Sobrien | SEC_IN_MEMORY 95759024Sobrien | SEC_READONLY)) 95859024Sobrien || ! bfd_set_section_alignment (dynobj, s, 2)) 959130561Sobrien return FALSE; 96059024Sobrien } 96159024Sobrien 96259024Sobrien /* Pick up the dynamic symbols and return them to the caller. */ 96359024Sobrien if (! sunos_slurp_dynamic_symtab (abfd)) 964130561Sobrien return FALSE; 96559024Sobrien 96659024Sobrien dinfo = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); 96759024Sobrien *symsp = dinfo->dynsym; 96859024Sobrien *sym_countp = dinfo->dynsym_count; 96959024Sobrien *stringsp = dinfo->dynstr; 97059024Sobrien 97159024Sobrien /* Record information about any other objects needed by this one. */ 97259024Sobrien need = dinfo->dyninfo.ld_need; 97359024Sobrien while (need != 0) 97459024Sobrien { 97559024Sobrien bfd_byte buf[16]; 97659024Sobrien unsigned long name, flags; 97759024Sobrien unsigned short major_vno, minor_vno; 97859024Sobrien struct bfd_link_needed_list *needed, **pp; 97959024Sobrien char *namebuf, *p; 98089857Sobrien bfd_size_type alc; 98159024Sobrien bfd_byte b; 98259024Sobrien char *namecopy; 98359024Sobrien 98489857Sobrien if (bfd_seek (abfd, (file_ptr) need, SEEK_SET) != 0 98589857Sobrien || bfd_bread (buf, (bfd_size_type) 16, abfd) != 16) 986130561Sobrien return FALSE; 98759024Sobrien 98859024Sobrien /* For the format of an ld_need entry, see aout/sun4.h. We 989130561Sobrien should probably define structs for this manipulation. */ 99059024Sobrien 99159024Sobrien name = bfd_get_32 (abfd, buf); 99259024Sobrien flags = bfd_get_32 (abfd, buf + 4); 99389857Sobrien major_vno = (unsigned short) bfd_get_16 (abfd, buf + 8); 99489857Sobrien minor_vno = (unsigned short) bfd_get_16 (abfd, buf + 10); 99559024Sobrien need = bfd_get_32 (abfd, buf + 12); 99659024Sobrien 99789857Sobrien alc = sizeof (struct bfd_link_needed_list); 99889857Sobrien needed = (struct bfd_link_needed_list *) bfd_alloc (abfd, alc); 99959024Sobrien if (needed == NULL) 1000130561Sobrien return FALSE; 100159024Sobrien needed->by = abfd; 100259024Sobrien 100359024Sobrien /* We return the name as [-l]name[.maj][.min]. */ 100459024Sobrien alc = 30; 100559024Sobrien namebuf = (char *) bfd_malloc (alc + 1); 100659024Sobrien if (namebuf == NULL) 1007130561Sobrien return FALSE; 100859024Sobrien p = namebuf; 100959024Sobrien 101059024Sobrien if ((flags & 0x80000000) != 0) 101159024Sobrien { 101259024Sobrien *p++ = '-'; 101359024Sobrien *p++ = 'l'; 101459024Sobrien } 101589857Sobrien if (bfd_seek (abfd, (file_ptr) name, SEEK_SET) != 0) 101659024Sobrien { 101759024Sobrien free (namebuf); 1018130561Sobrien return FALSE; 101959024Sobrien } 102059024Sobrien 102159024Sobrien do 102259024Sobrien { 102389857Sobrien if (bfd_bread (&b, (bfd_size_type) 1, abfd) != 1) 102459024Sobrien { 102559024Sobrien free (namebuf); 1026130561Sobrien return FALSE; 102759024Sobrien } 102859024Sobrien 102989857Sobrien if ((bfd_size_type) (p - namebuf) >= alc) 103059024Sobrien { 103159024Sobrien char *n; 103259024Sobrien 103359024Sobrien alc *= 2; 103459024Sobrien n = (char *) bfd_realloc (namebuf, alc + 1); 103559024Sobrien if (n == NULL) 103659024Sobrien { 103759024Sobrien free (namebuf); 1038130561Sobrien return FALSE; 103959024Sobrien } 104059024Sobrien p = n + (p - namebuf); 104159024Sobrien namebuf = n; 104259024Sobrien } 104359024Sobrien 104459024Sobrien *p++ = b; 104559024Sobrien } 104659024Sobrien while (b != '\0'); 104759024Sobrien 104859024Sobrien if (major_vno == 0) 104959024Sobrien *p = '\0'; 105059024Sobrien else 105159024Sobrien { 105259024Sobrien char majbuf[30]; 105359024Sobrien char minbuf[30]; 105459024Sobrien 105559024Sobrien sprintf (majbuf, ".%d", major_vno); 105659024Sobrien if (minor_vno == 0) 105759024Sobrien minbuf[0] = '\0'; 105859024Sobrien else 105959024Sobrien sprintf (minbuf, ".%d", minor_vno); 106059024Sobrien 106159024Sobrien if ((p - namebuf) + strlen (majbuf) + strlen (minbuf) >= alc) 106259024Sobrien { 106359024Sobrien char *n; 106459024Sobrien 106559024Sobrien alc = (p - namebuf) + strlen (majbuf) + strlen (minbuf); 106659024Sobrien n = (char *) bfd_realloc (namebuf, alc + 1); 106759024Sobrien if (n == NULL) 106859024Sobrien { 106959024Sobrien free (namebuf); 1070130561Sobrien return FALSE; 107159024Sobrien } 107259024Sobrien p = n + (p - namebuf); 107359024Sobrien namebuf = n; 107459024Sobrien } 107559024Sobrien 107659024Sobrien strcpy (p, majbuf); 107759024Sobrien strcat (p, minbuf); 107859024Sobrien } 107959024Sobrien 108089857Sobrien namecopy = bfd_alloc (abfd, (bfd_size_type) strlen (namebuf) + 1); 108159024Sobrien if (namecopy == NULL) 108259024Sobrien { 108359024Sobrien free (namebuf); 1084130561Sobrien return FALSE; 108559024Sobrien } 108659024Sobrien strcpy (namecopy, namebuf); 108759024Sobrien free (namebuf); 108859024Sobrien needed->name = namecopy; 108959024Sobrien 109059024Sobrien needed->next = NULL; 109159024Sobrien 109259024Sobrien for (pp = &sunos_hash_table (info)->needed; 109359024Sobrien *pp != NULL; 109459024Sobrien pp = &(*pp)->next) 109559024Sobrien ; 109659024Sobrien *pp = needed; 109759024Sobrien } 109859024Sobrien 1099130561Sobrien return TRUE; 110059024Sobrien} 110159024Sobrien 110259024Sobrien/* Function to add a single symbol to the linker hash table. This is 110359024Sobrien a wrapper around _bfd_generic_link_add_one_symbol which handles the 110459024Sobrien tweaking needed for dynamic linking support. */ 110559024Sobrien 1106130561Sobrienstatic bfd_boolean 110759024Sobriensunos_add_one_symbol (info, abfd, name, flags, section, value, string, 110859024Sobrien copy, collect, hashp) 110959024Sobrien struct bfd_link_info *info; 111059024Sobrien bfd *abfd; 111159024Sobrien const char *name; 111259024Sobrien flagword flags; 111359024Sobrien asection *section; 111459024Sobrien bfd_vma value; 111559024Sobrien const char *string; 1116130561Sobrien bfd_boolean copy; 1117130561Sobrien bfd_boolean collect; 111859024Sobrien struct bfd_link_hash_entry **hashp; 111959024Sobrien{ 112059024Sobrien struct sunos_link_hash_entry *h; 112159024Sobrien int new_flag; 112259024Sobrien 112359024Sobrien if ((flags & (BSF_INDIRECT | BSF_WARNING | BSF_CONSTRUCTOR)) != 0 112459024Sobrien || ! bfd_is_und_section (section)) 1125130561Sobrien h = sunos_link_hash_lookup (sunos_hash_table (info), name, TRUE, copy, 1126130561Sobrien FALSE); 112759024Sobrien else 112859024Sobrien h = ((struct sunos_link_hash_entry *) 1129130561Sobrien bfd_wrapped_link_hash_lookup (abfd, info, name, TRUE, copy, FALSE)); 113059024Sobrien if (h == NULL) 1131130561Sobrien return FALSE; 113259024Sobrien 113359024Sobrien if (hashp != NULL) 113459024Sobrien *hashp = (struct bfd_link_hash_entry *) h; 113559024Sobrien 113659024Sobrien /* Treat a common symbol in a dynamic object as defined in the .bss 113759024Sobrien section of the dynamic object. We don't want to allocate space 113859024Sobrien for it in our process image. */ 113959024Sobrien if ((abfd->flags & DYNAMIC) != 0 114059024Sobrien && bfd_is_com_section (section)) 114159024Sobrien section = obj_bsssec (abfd); 114259024Sobrien 114359024Sobrien if (! bfd_is_und_section (section) 114459024Sobrien && h->root.root.type != bfd_link_hash_new 114559024Sobrien && h->root.root.type != bfd_link_hash_undefined 114659024Sobrien && h->root.root.type != bfd_link_hash_defweak) 114759024Sobrien { 114859024Sobrien /* We are defining the symbol, and it is already defined. This 114959024Sobrien is a potential multiple definition error. */ 115059024Sobrien if ((abfd->flags & DYNAMIC) != 0) 115159024Sobrien { 115259024Sobrien /* The definition we are adding is from a dynamic object. 115359024Sobrien We do not want this new definition to override the 115459024Sobrien existing definition, so we pretend it is just a 115559024Sobrien reference. */ 115659024Sobrien section = bfd_und_section_ptr; 115759024Sobrien } 115859024Sobrien else if (h->root.root.type == bfd_link_hash_defined 115959024Sobrien && h->root.root.u.def.section->owner != NULL 116059024Sobrien && (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0) 116159024Sobrien { 116259024Sobrien /* The existing definition is from a dynamic object. We 116359024Sobrien want to override it with the definition we just found. 116459024Sobrien Clobber the existing definition. */ 116559024Sobrien h->root.root.type = bfd_link_hash_undefined; 116659024Sobrien h->root.root.u.undef.abfd = h->root.root.u.def.section->owner; 116759024Sobrien } 116859024Sobrien else if (h->root.root.type == bfd_link_hash_common 116959024Sobrien && (h->root.root.u.c.p->section->owner->flags & DYNAMIC) != 0) 117059024Sobrien { 117159024Sobrien /* The existing definition is from a dynamic object. We 117259024Sobrien want to override it with the definition we just found. 117359024Sobrien Clobber the existing definition. We can't set it to new, 117459024Sobrien because it is on the undefined list. */ 117559024Sobrien h->root.root.type = bfd_link_hash_undefined; 117659024Sobrien h->root.root.u.undef.abfd = h->root.root.u.c.p->section->owner; 117759024Sobrien } 117859024Sobrien } 117959024Sobrien 118059024Sobrien if ((abfd->flags & DYNAMIC) != 0 118159024Sobrien && abfd->xvec == info->hash->creator 118259024Sobrien && (h->flags & SUNOS_CONSTRUCTOR) != 0) 118359024Sobrien { 118459024Sobrien /* The existing symbol is a constructor symbol, and this symbol 1185130561Sobrien is from a dynamic object. A constructor symbol is actually a 1186130561Sobrien definition, although the type will be bfd_link_hash_undefined 1187130561Sobrien at this point. We want to ignore the definition from the 1188130561Sobrien dynamic object. */ 118959024Sobrien section = bfd_und_section_ptr; 119059024Sobrien } 119159024Sobrien else if ((flags & BSF_CONSTRUCTOR) != 0 119259024Sobrien && (abfd->flags & DYNAMIC) == 0 119359024Sobrien && h->root.root.type == bfd_link_hash_defined 119459024Sobrien && h->root.root.u.def.section->owner != NULL 119559024Sobrien && (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0) 119659024Sobrien { 119759024Sobrien /* The existing symbol is defined by a dynamic object, and this 1198130561Sobrien is a constructor symbol. As above, we want to force the use 1199130561Sobrien of the constructor symbol from the regular object. */ 120059024Sobrien h->root.root.type = bfd_link_hash_new; 120159024Sobrien } 120259024Sobrien 120359024Sobrien /* Do the usual procedure for adding a symbol. */ 120459024Sobrien if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, 120559024Sobrien value, string, copy, collect, 120659024Sobrien hashp)) 1207130561Sobrien return FALSE; 120859024Sobrien 120959024Sobrien if (abfd->xvec == info->hash->creator) 121059024Sobrien { 121159024Sobrien /* Set a flag in the hash table entry indicating the type of 121259024Sobrien reference or definition we just found. Keep a count of the 121359024Sobrien number of dynamic symbols we find. A dynamic symbol is one 121459024Sobrien which is referenced or defined by both a regular object and a 121559024Sobrien shared object. */ 121659024Sobrien if ((abfd->flags & DYNAMIC) == 0) 121759024Sobrien { 121859024Sobrien if (bfd_is_und_section (section)) 121959024Sobrien new_flag = SUNOS_REF_REGULAR; 122059024Sobrien else 122159024Sobrien new_flag = SUNOS_DEF_REGULAR; 122259024Sobrien } 122359024Sobrien else 122459024Sobrien { 122559024Sobrien if (bfd_is_und_section (section)) 122659024Sobrien new_flag = SUNOS_REF_DYNAMIC; 122759024Sobrien else 122859024Sobrien new_flag = SUNOS_DEF_DYNAMIC; 122959024Sobrien } 123059024Sobrien h->flags |= new_flag; 123159024Sobrien 123259024Sobrien if (h->dynindx == -1 123359024Sobrien && (h->flags & (SUNOS_DEF_REGULAR | SUNOS_REF_REGULAR)) != 0) 123459024Sobrien { 123559024Sobrien ++sunos_hash_table (info)->dynsymcount; 123659024Sobrien h->dynindx = -2; 123759024Sobrien } 123859024Sobrien 123959024Sobrien if ((flags & BSF_CONSTRUCTOR) != 0 124059024Sobrien && (abfd->flags & DYNAMIC) == 0) 124159024Sobrien h->flags |= SUNOS_CONSTRUCTOR; 124259024Sobrien } 124359024Sobrien 1244130561Sobrien return TRUE; 124559024Sobrien} 124659024Sobrien 124759024Sobrien/* Return the list of objects needed by BFD. */ 124859024Sobrien 124959024Sobrienstruct bfd_link_needed_list * 125059024Sobrienbfd_sunos_get_needed_list (abfd, info) 125184865Sobrien bfd *abfd ATTRIBUTE_UNUSED; 125259024Sobrien struct bfd_link_info *info; 125359024Sobrien{ 125459024Sobrien if (info->hash->creator != &MY(vec)) 125559024Sobrien return NULL; 125659024Sobrien return sunos_hash_table (info)->needed; 125759024Sobrien} 125859024Sobrien 125959024Sobrien/* Record an assignment made to a symbol by a linker script. We need 126059024Sobrien this in case some dynamic object refers to this symbol. */ 126159024Sobrien 1262130561Sobrienbfd_boolean 126359024Sobrienbfd_sunos_record_link_assignment (output_bfd, info, name) 126459024Sobrien bfd *output_bfd; 126559024Sobrien struct bfd_link_info *info; 126659024Sobrien const char *name; 126759024Sobrien{ 126859024Sobrien struct sunos_link_hash_entry *h; 126959024Sobrien 127059024Sobrien if (output_bfd->xvec != &MY(vec)) 1271130561Sobrien return TRUE; 127259024Sobrien 127359024Sobrien /* This is called after we have examined all the input objects. If 127459024Sobrien the symbol does not exist, it merely means that no object refers 127559024Sobrien to it, and we can just ignore it at this point. */ 127659024Sobrien h = sunos_link_hash_lookup (sunos_hash_table (info), name, 1277130561Sobrien FALSE, FALSE, FALSE); 127859024Sobrien if (h == NULL) 1279130561Sobrien return TRUE; 128059024Sobrien 128159024Sobrien /* In a shared library, the __DYNAMIC symbol does not appear in the 128259024Sobrien dynamic symbol table. */ 128359024Sobrien if (! info->shared || strcmp (name, "__DYNAMIC") != 0) 128459024Sobrien { 128559024Sobrien h->flags |= SUNOS_DEF_REGULAR; 128659024Sobrien 128759024Sobrien if (h->dynindx == -1) 128859024Sobrien { 128959024Sobrien ++sunos_hash_table (info)->dynsymcount; 129059024Sobrien h->dynindx = -2; 129159024Sobrien } 129259024Sobrien } 129359024Sobrien 1294130561Sobrien return TRUE; 129559024Sobrien} 129659024Sobrien 129759024Sobrien/* Set up the sizes and contents of the dynamic sections created in 129859024Sobrien sunos_add_dynamic_symbols. This is called by the SunOS linker 129959024Sobrien emulation before_allocation routine. We must set the sizes of the 130059024Sobrien sections before the linker sets the addresses of the various 130159024Sobrien sections. This unfortunately requires reading all the relocs so 130259024Sobrien that we can work out which ones need to become dynamic relocs. If 1303130561Sobrien info->keep_memory is TRUE, we keep the relocs in memory; otherwise, 130459024Sobrien we discard them, and will read them again later. */ 130559024Sobrien 1306130561Sobrienbfd_boolean 130759024Sobrienbfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr, 130859024Sobrien srulesptr) 130959024Sobrien bfd *output_bfd; 131059024Sobrien struct bfd_link_info *info; 131159024Sobrien asection **sdynptr; 131259024Sobrien asection **sneedptr; 131359024Sobrien asection **srulesptr; 131459024Sobrien{ 131559024Sobrien bfd *dynobj; 131689857Sobrien bfd_size_type dynsymcount; 131759024Sobrien struct sunos_link_hash_entry *h; 131859024Sobrien asection *s; 131959024Sobrien size_t bucketcount; 132089857Sobrien bfd_size_type hashalloc; 132159024Sobrien size_t i; 132259024Sobrien bfd *sub; 132359024Sobrien 132459024Sobrien *sdynptr = NULL; 132559024Sobrien *sneedptr = NULL; 132659024Sobrien *srulesptr = NULL; 132759024Sobrien 1328130561Sobrien if (info->relocatable) 1329130561Sobrien return TRUE; 133059024Sobrien 133159024Sobrien if (output_bfd->xvec != &MY(vec)) 1332130561Sobrien return TRUE; 133359024Sobrien 133459024Sobrien /* Look through all the input BFD's and read their relocs. It would 133559024Sobrien be better if we didn't have to do this, but there is no other way 133659024Sobrien to determine the number of dynamic relocs we need, and, more 133759024Sobrien importantly, there is no other way to know which symbols should 133859024Sobrien get an entry in the procedure linkage table. */ 133959024Sobrien for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) 134059024Sobrien { 134159024Sobrien if ((sub->flags & DYNAMIC) == 0 134259024Sobrien && sub->xvec == output_bfd->xvec) 134359024Sobrien { 134459024Sobrien if (! sunos_scan_relocs (info, sub, obj_textsec (sub), 134559024Sobrien exec_hdr (sub)->a_trsize) 134659024Sobrien || ! sunos_scan_relocs (info, sub, obj_datasec (sub), 134759024Sobrien exec_hdr (sub)->a_drsize)) 1348130561Sobrien return FALSE; 134959024Sobrien } 135059024Sobrien } 135159024Sobrien 135259024Sobrien dynobj = sunos_hash_table (info)->dynobj; 135359024Sobrien dynsymcount = sunos_hash_table (info)->dynsymcount; 135459024Sobrien 135559024Sobrien /* If there were no dynamic objects in the link, and we don't need 135659024Sobrien to build a global offset table, there is nothing to do here. */ 135759024Sobrien if (! sunos_hash_table (info)->dynamic_sections_needed 135859024Sobrien && ! sunos_hash_table (info)->got_needed) 1359130561Sobrien return TRUE; 136059024Sobrien 136159024Sobrien /* If __GLOBAL_OFFSET_TABLE_ was mentioned, define it. */ 136259024Sobrien h = sunos_link_hash_lookup (sunos_hash_table (info), 1363130561Sobrien "__GLOBAL_OFFSET_TABLE_", FALSE, FALSE, FALSE); 136459024Sobrien if (h != NULL && (h->flags & SUNOS_REF_REGULAR) != 0) 136559024Sobrien { 136659024Sobrien h->flags |= SUNOS_DEF_REGULAR; 136759024Sobrien if (h->dynindx == -1) 136859024Sobrien { 136959024Sobrien ++sunos_hash_table (info)->dynsymcount; 137059024Sobrien h->dynindx = -2; 137159024Sobrien } 137259024Sobrien h->root.root.type = bfd_link_hash_defined; 137359024Sobrien h->root.root.u.def.section = bfd_get_section_by_name (dynobj, ".got"); 137459024Sobrien 137559024Sobrien /* If the .got section is more than 0x1000 bytes, we set 1376130561Sobrien __GLOBAL_OFFSET_TABLE_ to be 0x1000 bytes into the section, 1377130561Sobrien so that 13 bit relocations have a greater chance of working. */ 137859024Sobrien s = bfd_get_section_by_name (dynobj, ".got"); 137959024Sobrien BFD_ASSERT (s != NULL); 138059024Sobrien if (s->_raw_size >= 0x1000) 138159024Sobrien h->root.root.u.def.value = 0x1000; 138259024Sobrien else 138359024Sobrien h->root.root.u.def.value = 0; 138459024Sobrien 138559024Sobrien sunos_hash_table (info)->got_base = h->root.root.u.def.value; 138659024Sobrien } 138759024Sobrien 138859024Sobrien /* If there are any shared objects in the link, then we need to set 138959024Sobrien up the dynamic linking information. */ 139059024Sobrien if (sunos_hash_table (info)->dynamic_sections_needed) 139159024Sobrien { 139259024Sobrien *sdynptr = bfd_get_section_by_name (dynobj, ".dynamic"); 139359024Sobrien 139459024Sobrien /* The .dynamic section is always the same size. */ 139559024Sobrien s = *sdynptr; 139659024Sobrien BFD_ASSERT (s != NULL); 139759024Sobrien s->_raw_size = (sizeof (struct external_sun4_dynamic) 139859024Sobrien + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE 139959024Sobrien + sizeof (struct external_sun4_dynamic_link)); 140059024Sobrien 140159024Sobrien /* Set the size of the .dynsym and .hash sections. We counted 140259024Sobrien the number of dynamic symbols as we read the input files. We 140359024Sobrien will build the dynamic symbol table (.dynsym) and the hash 140459024Sobrien table (.hash) when we build the final symbol table, because 140559024Sobrien until then we do not know the correct value to give the 140659024Sobrien symbols. We build the dynamic symbol string table (.dynstr) 140759024Sobrien in a traversal of the symbol table using 140859024Sobrien sunos_scan_dynamic_symbol. */ 140959024Sobrien s = bfd_get_section_by_name (dynobj, ".dynsym"); 141059024Sobrien BFD_ASSERT (s != NULL); 141159024Sobrien s->_raw_size = dynsymcount * sizeof (struct external_nlist); 141259024Sobrien s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size); 141359024Sobrien if (s->contents == NULL && s->_raw_size != 0) 1414130561Sobrien return FALSE; 141584865Sobrien 141659024Sobrien /* The number of buckets is just the number of symbols divided 141759024Sobrien by four. To compute the final size of the hash table, we 141859024Sobrien must actually compute the hash table. Normally we need 141959024Sobrien exactly as many entries in the hash table as there are 142059024Sobrien dynamic symbols, but if some of the buckets are not used we 142159024Sobrien will need additional entries. In the worst case, every 142259024Sobrien symbol will hash to the same bucket, and we will need 142359024Sobrien BUCKETCOUNT - 1 extra entries. */ 142459024Sobrien if (dynsymcount >= 4) 142559024Sobrien bucketcount = dynsymcount / 4; 142659024Sobrien else if (dynsymcount > 0) 142759024Sobrien bucketcount = dynsymcount; 142859024Sobrien else 142959024Sobrien bucketcount = 1; 143059024Sobrien s = bfd_get_section_by_name (dynobj, ".hash"); 143159024Sobrien BFD_ASSERT (s != NULL); 143259024Sobrien hashalloc = (dynsymcount + bucketcount - 1) * HASH_ENTRY_SIZE; 1433104834Sobrien s->contents = (bfd_byte *) bfd_zalloc (dynobj, hashalloc); 143459024Sobrien if (s->contents == NULL && dynsymcount > 0) 1435130561Sobrien return FALSE; 143659024Sobrien for (i = 0; i < bucketcount; i++) 143759024Sobrien PUT_WORD (output_bfd, (bfd_vma) -1, s->contents + i * HASH_ENTRY_SIZE); 143859024Sobrien s->_raw_size = bucketcount * HASH_ENTRY_SIZE; 143959024Sobrien 144059024Sobrien sunos_hash_table (info)->bucketcount = bucketcount; 144159024Sobrien 144259024Sobrien /* Scan all the symbols, place them in the dynamic symbol table, 144359024Sobrien and build the dynamic hash table. We reuse dynsymcount as a 144459024Sobrien counter for the number of symbols we have added so far. */ 144559024Sobrien sunos_hash_table (info)->dynsymcount = 0; 144659024Sobrien sunos_link_hash_traverse (sunos_hash_table (info), 144759024Sobrien sunos_scan_dynamic_symbol, 144859024Sobrien (PTR) info); 144959024Sobrien BFD_ASSERT (sunos_hash_table (info)->dynsymcount == dynsymcount); 145059024Sobrien 145159024Sobrien /* The SunOS native linker seems to align the total size of the 145259024Sobrien symbol strings to a multiple of 8. I don't know if this is 145359024Sobrien important, but it can't hurt much. */ 145459024Sobrien s = bfd_get_section_by_name (dynobj, ".dynstr"); 145559024Sobrien BFD_ASSERT (s != NULL); 145659024Sobrien if ((s->_raw_size & 7) != 0) 145759024Sobrien { 145859024Sobrien bfd_size_type add; 145959024Sobrien bfd_byte *contents; 146059024Sobrien 146159024Sobrien add = 8 - (s->_raw_size & 7); 146259024Sobrien contents = (bfd_byte *) bfd_realloc (s->contents, 146389857Sobrien s->_raw_size + add); 146459024Sobrien if (contents == NULL) 1465130561Sobrien return FALSE; 146659024Sobrien memset (contents + s->_raw_size, 0, (size_t) add); 146759024Sobrien s->contents = contents; 146859024Sobrien s->_raw_size += add; 146959024Sobrien } 147059024Sobrien } 147159024Sobrien 147259024Sobrien /* Now that we have worked out the sizes of the procedure linkage 147359024Sobrien table and the dynamic relocs, allocate storage for them. */ 147459024Sobrien s = bfd_get_section_by_name (dynobj, ".plt"); 147559024Sobrien BFD_ASSERT (s != NULL); 147659024Sobrien if (s->_raw_size != 0) 147759024Sobrien { 147859024Sobrien s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size); 147959024Sobrien if (s->contents == NULL) 1480130561Sobrien return FALSE; 148159024Sobrien 148259024Sobrien /* Fill in the first entry in the table. */ 148359024Sobrien switch (bfd_get_arch (dynobj)) 148459024Sobrien { 148559024Sobrien case bfd_arch_sparc: 148659024Sobrien memcpy (s->contents, sparc_plt_first_entry, SPARC_PLT_ENTRY_SIZE); 148759024Sobrien break; 148859024Sobrien 148959024Sobrien case bfd_arch_m68k: 149059024Sobrien memcpy (s->contents, m68k_plt_first_entry, M68K_PLT_ENTRY_SIZE); 149159024Sobrien break; 149259024Sobrien 149359024Sobrien default: 149459024Sobrien abort (); 149559024Sobrien } 149659024Sobrien } 149759024Sobrien 149859024Sobrien s = bfd_get_section_by_name (dynobj, ".dynrel"); 149959024Sobrien if (s->_raw_size != 0) 150059024Sobrien { 150159024Sobrien s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size); 150259024Sobrien if (s->contents == NULL) 1503130561Sobrien return FALSE; 150459024Sobrien } 150559024Sobrien /* We use the reloc_count field to keep track of how many of the 150659024Sobrien relocs we have output so far. */ 150759024Sobrien s->reloc_count = 0; 150859024Sobrien 150959024Sobrien /* Make space for the global offset table. */ 151059024Sobrien s = bfd_get_section_by_name (dynobj, ".got"); 151159024Sobrien s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size); 151259024Sobrien if (s->contents == NULL) 1513130561Sobrien return FALSE; 151459024Sobrien 151559024Sobrien *sneedptr = bfd_get_section_by_name (dynobj, ".need"); 151659024Sobrien *srulesptr = bfd_get_section_by_name (dynobj, ".rules"); 151759024Sobrien 1518130561Sobrien return TRUE; 151959024Sobrien} 152059024Sobrien 152159024Sobrien/* Scan the relocs for an input section. */ 152259024Sobrien 1523130561Sobrienstatic bfd_boolean 152459024Sobriensunos_scan_relocs (info, abfd, sec, rel_size) 152559024Sobrien struct bfd_link_info *info; 152659024Sobrien bfd *abfd; 152759024Sobrien asection *sec; 152859024Sobrien bfd_size_type rel_size; 152959024Sobrien{ 153059024Sobrien PTR relocs; 153159024Sobrien PTR free_relocs = NULL; 153259024Sobrien 153359024Sobrien if (rel_size == 0) 1534130561Sobrien return TRUE; 153559024Sobrien 153659024Sobrien if (! info->keep_memory) 153789857Sobrien relocs = free_relocs = bfd_malloc (rel_size); 153859024Sobrien else 153959024Sobrien { 154059024Sobrien struct aout_section_data_struct *n; 154189857Sobrien bfd_size_type amt = sizeof (struct aout_section_data_struct); 154259024Sobrien 154389857Sobrien n = (struct aout_section_data_struct *) bfd_alloc (abfd, amt); 154459024Sobrien if (n == NULL) 154559024Sobrien relocs = NULL; 154659024Sobrien else 154759024Sobrien { 154859024Sobrien set_aout_section_data (sec, n); 154989857Sobrien relocs = bfd_malloc (rel_size); 155059024Sobrien aout_section_data (sec)->relocs = relocs; 155159024Sobrien } 155259024Sobrien } 155359024Sobrien if (relocs == NULL) 1554130561Sobrien return FALSE; 155559024Sobrien 155659024Sobrien if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0 155789857Sobrien || bfd_bread (relocs, rel_size, abfd) != rel_size) 155859024Sobrien goto error_return; 155959024Sobrien 156059024Sobrien if (obj_reloc_entry_size (abfd) == RELOC_STD_SIZE) 156159024Sobrien { 156259024Sobrien if (! sunos_scan_std_relocs (info, abfd, sec, 156359024Sobrien (struct reloc_std_external *) relocs, 156459024Sobrien rel_size)) 156559024Sobrien goto error_return; 156659024Sobrien } 156759024Sobrien else 156859024Sobrien { 156959024Sobrien if (! sunos_scan_ext_relocs (info, abfd, sec, 157059024Sobrien (struct reloc_ext_external *) relocs, 157159024Sobrien rel_size)) 157259024Sobrien goto error_return; 157359024Sobrien } 157459024Sobrien 157559024Sobrien if (free_relocs != NULL) 157659024Sobrien free (free_relocs); 157759024Sobrien 1578130561Sobrien return TRUE; 157959024Sobrien 158059024Sobrien error_return: 158159024Sobrien if (free_relocs != NULL) 158259024Sobrien free (free_relocs); 1583130561Sobrien return FALSE; 158459024Sobrien} 158559024Sobrien 158659024Sobrien/* Scan the relocs for an input section using standard relocs. We 158759024Sobrien need to figure out what to do for each reloc against a dynamic 158859024Sobrien symbol. If the symbol is in the .text section, an entry is made in 158959024Sobrien the procedure linkage table. Note that this will do the wrong 159059024Sobrien thing if the symbol is actually data; I don't think the Sun 3 159159024Sobrien native linker handles this case correctly either. If the symbol is 159259024Sobrien not in the .text section, we must preserve the reloc as a dynamic 159359024Sobrien reloc. FIXME: We should also handle the PIC relocs here by 159459024Sobrien building global offset table entries. */ 159559024Sobrien 1596130561Sobrienstatic bfd_boolean 159759024Sobriensunos_scan_std_relocs (info, abfd, sec, relocs, rel_size) 159859024Sobrien struct bfd_link_info *info; 159959024Sobrien bfd *abfd; 160084865Sobrien asection *sec ATTRIBUTE_UNUSED; 160159024Sobrien const struct reloc_std_external *relocs; 160259024Sobrien bfd_size_type rel_size; 160359024Sobrien{ 160459024Sobrien bfd *dynobj; 160559024Sobrien asection *splt = NULL; 160659024Sobrien asection *srel = NULL; 160759024Sobrien struct sunos_link_hash_entry **sym_hashes; 160859024Sobrien const struct reloc_std_external *rel, *relend; 160959024Sobrien 161059024Sobrien /* We only know how to handle m68k plt entries. */ 161159024Sobrien if (bfd_get_arch (abfd) != bfd_arch_m68k) 161259024Sobrien { 161359024Sobrien bfd_set_error (bfd_error_invalid_target); 1614130561Sobrien return FALSE; 161559024Sobrien } 161659024Sobrien 161759024Sobrien dynobj = NULL; 161859024Sobrien 161959024Sobrien sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd); 162059024Sobrien 162159024Sobrien relend = relocs + rel_size / RELOC_STD_SIZE; 162259024Sobrien for (rel = relocs; rel < relend; rel++) 162359024Sobrien { 162459024Sobrien int r_index; 162559024Sobrien struct sunos_link_hash_entry *h; 162659024Sobrien 162759024Sobrien /* We only want relocs against external symbols. */ 162859024Sobrien if (bfd_header_big_endian (abfd)) 162959024Sobrien { 163059024Sobrien if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG) == 0) 163159024Sobrien continue; 163259024Sobrien } 163359024Sobrien else 163459024Sobrien { 163559024Sobrien if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE) == 0) 163659024Sobrien continue; 163759024Sobrien } 163859024Sobrien 163959024Sobrien /* Get the symbol index. */ 164059024Sobrien if (bfd_header_big_endian (abfd)) 164159024Sobrien r_index = ((rel->r_index[0] << 16) 164259024Sobrien | (rel->r_index[1] << 8) 164359024Sobrien | rel->r_index[2]); 164459024Sobrien else 164559024Sobrien r_index = ((rel->r_index[2] << 16) 164659024Sobrien | (rel->r_index[1] << 8) 164759024Sobrien | rel->r_index[0]); 164859024Sobrien 164959024Sobrien /* Get the hash table entry. */ 165059024Sobrien h = sym_hashes[r_index]; 165159024Sobrien if (h == NULL) 165259024Sobrien { 165359024Sobrien /* This should not normally happen, but it will in any case 165459024Sobrien be caught in the relocation phase. */ 165559024Sobrien continue; 165659024Sobrien } 165759024Sobrien 165859024Sobrien /* At this point common symbols have already been allocated, so 165959024Sobrien we don't have to worry about them. We need to consider that 166059024Sobrien we may have already seen this symbol and marked it undefined; 166159024Sobrien if the symbol is really undefined, then SUNOS_DEF_DYNAMIC 166259024Sobrien will be zero. */ 166359024Sobrien if (h->root.root.type != bfd_link_hash_defined 166459024Sobrien && h->root.root.type != bfd_link_hash_defweak 166559024Sobrien && h->root.root.type != bfd_link_hash_undefined) 166659024Sobrien continue; 166759024Sobrien 166859024Sobrien if ((h->flags & SUNOS_DEF_DYNAMIC) == 0 166959024Sobrien || (h->flags & SUNOS_DEF_REGULAR) != 0) 167059024Sobrien continue; 167159024Sobrien 167259024Sobrien if (dynobj == NULL) 167359024Sobrien { 167459024Sobrien asection *sgot; 167559024Sobrien 1676130561Sobrien if (! sunos_create_dynamic_sections (abfd, info, FALSE)) 1677130561Sobrien return FALSE; 167859024Sobrien dynobj = sunos_hash_table (info)->dynobj; 167959024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 168059024Sobrien srel = bfd_get_section_by_name (dynobj, ".dynrel"); 168159024Sobrien BFD_ASSERT (splt != NULL && srel != NULL); 168259024Sobrien 168359024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 168459024Sobrien BFD_ASSERT (sgot != NULL); 168559024Sobrien if (sgot->_raw_size == 0) 168659024Sobrien sgot->_raw_size = BYTES_IN_WORD; 1687130561Sobrien sunos_hash_table (info)->got_needed = TRUE; 168859024Sobrien } 168959024Sobrien 169059024Sobrien BFD_ASSERT ((h->flags & SUNOS_REF_REGULAR) != 0); 169159024Sobrien BFD_ASSERT (h->plt_offset != 0 169259024Sobrien || ((h->root.root.type == bfd_link_hash_defined 169359024Sobrien || h->root.root.type == bfd_link_hash_defweak) 169459024Sobrien ? (h->root.root.u.def.section->owner->flags 169559024Sobrien & DYNAMIC) != 0 169659024Sobrien : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0)); 169759024Sobrien 169859024Sobrien /* This reloc is against a symbol defined only by a dynamic 169959024Sobrien object. */ 170059024Sobrien 170159024Sobrien if (h->root.root.type == bfd_link_hash_undefined) 170259024Sobrien { 170359024Sobrien /* Presumably this symbol was marked as being undefined by 170459024Sobrien an earlier reloc. */ 170559024Sobrien srel->_raw_size += RELOC_STD_SIZE; 170659024Sobrien } 170759024Sobrien else if ((h->root.root.u.def.section->flags & SEC_CODE) == 0) 170859024Sobrien { 170959024Sobrien bfd *sub; 171059024Sobrien 171159024Sobrien /* This reloc is not in the .text section. It must be 171259024Sobrien copied into the dynamic relocs. We mark the symbol as 171359024Sobrien being undefined. */ 171459024Sobrien srel->_raw_size += RELOC_STD_SIZE; 171559024Sobrien sub = h->root.root.u.def.section->owner; 171659024Sobrien h->root.root.type = bfd_link_hash_undefined; 171759024Sobrien h->root.root.u.undef.abfd = sub; 171859024Sobrien } 171959024Sobrien else 172059024Sobrien { 172159024Sobrien /* This symbol is in the .text section. We must give it an 172259024Sobrien entry in the procedure linkage table, if we have not 172359024Sobrien already done so. We change the definition of the symbol 172459024Sobrien to the .plt section; this will cause relocs against it to 172559024Sobrien be handled correctly. */ 172659024Sobrien if (h->plt_offset == 0) 172759024Sobrien { 172859024Sobrien if (splt->_raw_size == 0) 172959024Sobrien splt->_raw_size = M68K_PLT_ENTRY_SIZE; 173059024Sobrien h->plt_offset = splt->_raw_size; 173159024Sobrien 173259024Sobrien if ((h->flags & SUNOS_DEF_REGULAR) == 0) 173359024Sobrien { 173459024Sobrien h->root.root.u.def.section = splt; 173559024Sobrien h->root.root.u.def.value = splt->_raw_size; 173659024Sobrien } 173759024Sobrien 173859024Sobrien splt->_raw_size += M68K_PLT_ENTRY_SIZE; 173959024Sobrien 174059024Sobrien /* We may also need a dynamic reloc entry. */ 174159024Sobrien if ((h->flags & SUNOS_DEF_REGULAR) == 0) 174259024Sobrien srel->_raw_size += RELOC_STD_SIZE; 174359024Sobrien } 174459024Sobrien } 174559024Sobrien } 174659024Sobrien 1747130561Sobrien return TRUE; 174859024Sobrien} 174959024Sobrien 175059024Sobrien/* Scan the relocs for an input section using extended relocs. We 175159024Sobrien need to figure out what to do for each reloc against a dynamic 175259024Sobrien symbol. If the reloc is a WDISP30, and the symbol is in the .text 175359024Sobrien section, an entry is made in the procedure linkage table. 175459024Sobrien Otherwise, we must preserve the reloc as a dynamic reloc. */ 175559024Sobrien 1756130561Sobrienstatic bfd_boolean 175759024Sobriensunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size) 175859024Sobrien struct bfd_link_info *info; 175959024Sobrien bfd *abfd; 176084865Sobrien asection *sec ATTRIBUTE_UNUSED; 176159024Sobrien const struct reloc_ext_external *relocs; 176259024Sobrien bfd_size_type rel_size; 176359024Sobrien{ 176459024Sobrien bfd *dynobj; 176559024Sobrien struct sunos_link_hash_entry **sym_hashes; 176659024Sobrien const struct reloc_ext_external *rel, *relend; 176759024Sobrien asection *splt = NULL; 176859024Sobrien asection *sgot = NULL; 176959024Sobrien asection *srel = NULL; 177089857Sobrien bfd_size_type amt; 177159024Sobrien 177259024Sobrien /* We only know how to handle SPARC plt entries. */ 177359024Sobrien if (bfd_get_arch (abfd) != bfd_arch_sparc) 177459024Sobrien { 177559024Sobrien bfd_set_error (bfd_error_invalid_target); 1776130561Sobrien return FALSE; 177759024Sobrien } 177859024Sobrien 177959024Sobrien dynobj = NULL; 178059024Sobrien 178159024Sobrien sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd); 178259024Sobrien 178359024Sobrien relend = relocs + rel_size / RELOC_EXT_SIZE; 178459024Sobrien for (rel = relocs; rel < relend; rel++) 178559024Sobrien { 178659024Sobrien unsigned int r_index; 178759024Sobrien int r_extern; 178859024Sobrien int r_type; 178959024Sobrien struct sunos_link_hash_entry *h = NULL; 179059024Sobrien 179159024Sobrien /* Swap in the reloc information. */ 179259024Sobrien if (bfd_header_big_endian (abfd)) 179359024Sobrien { 179459024Sobrien r_index = ((rel->r_index[0] << 16) 179559024Sobrien | (rel->r_index[1] << 8) 179659024Sobrien | rel->r_index[2]); 179759024Sobrien r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG)); 179859024Sobrien r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) 179959024Sobrien >> RELOC_EXT_BITS_TYPE_SH_BIG); 180059024Sobrien } 180159024Sobrien else 180259024Sobrien { 180359024Sobrien r_index = ((rel->r_index[2] << 16) 180459024Sobrien | (rel->r_index[1] << 8) 180559024Sobrien | rel->r_index[0]); 180659024Sobrien r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE)); 180759024Sobrien r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) 180859024Sobrien >> RELOC_EXT_BITS_TYPE_SH_LITTLE); 180959024Sobrien } 181059024Sobrien 181159024Sobrien if (r_extern) 181259024Sobrien { 181359024Sobrien h = sym_hashes[r_index]; 181459024Sobrien if (h == NULL) 181559024Sobrien { 181659024Sobrien /* This should not normally happen, but it will in any 181759024Sobrien case be caught in the relocation phase. */ 181859024Sobrien continue; 181959024Sobrien } 182059024Sobrien } 182159024Sobrien 182259024Sobrien /* If this is a base relative reloc, we need to make an entry in 1823130561Sobrien the .got section. */ 182459024Sobrien if (r_type == RELOC_BASE10 182559024Sobrien || r_type == RELOC_BASE13 182659024Sobrien || r_type == RELOC_BASE22) 182759024Sobrien { 182859024Sobrien if (dynobj == NULL) 182959024Sobrien { 1830130561Sobrien if (! sunos_create_dynamic_sections (abfd, info, FALSE)) 1831130561Sobrien return FALSE; 183259024Sobrien dynobj = sunos_hash_table (info)->dynobj; 183359024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 183459024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 183559024Sobrien srel = bfd_get_section_by_name (dynobj, ".dynrel"); 183659024Sobrien BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL); 183759024Sobrien 183859024Sobrien /* Make sure we have an initial entry in the .got table. */ 183959024Sobrien if (sgot->_raw_size == 0) 184059024Sobrien sgot->_raw_size = BYTES_IN_WORD; 1841130561Sobrien sunos_hash_table (info)->got_needed = TRUE; 184259024Sobrien } 184359024Sobrien 184459024Sobrien if (r_extern) 184559024Sobrien { 184659024Sobrien if (h->got_offset != 0) 184759024Sobrien continue; 184859024Sobrien 184959024Sobrien h->got_offset = sgot->_raw_size; 185059024Sobrien } 185159024Sobrien else 185259024Sobrien { 185359024Sobrien if (r_index >= bfd_get_symcount (abfd)) 185459024Sobrien { 185559024Sobrien /* This is abnormal, but should be caught in the 185659024Sobrien relocation phase. */ 185759024Sobrien continue; 185859024Sobrien } 185959024Sobrien 186059024Sobrien if (adata (abfd).local_got_offsets == NULL) 186159024Sobrien { 186289857Sobrien amt = bfd_get_symcount (abfd); 186389857Sobrien amt *= sizeof (bfd_vma); 186459024Sobrien adata (abfd).local_got_offsets = 186589857Sobrien (bfd_vma *) bfd_zalloc (abfd, amt); 186659024Sobrien if (adata (abfd).local_got_offsets == NULL) 1867130561Sobrien return FALSE; 186859024Sobrien } 186959024Sobrien 187059024Sobrien if (adata (abfd).local_got_offsets[r_index] != 0) 187159024Sobrien continue; 187259024Sobrien 187359024Sobrien adata (abfd).local_got_offsets[r_index] = sgot->_raw_size; 187459024Sobrien } 187559024Sobrien 187659024Sobrien sgot->_raw_size += BYTES_IN_WORD; 187759024Sobrien 187859024Sobrien /* If we are making a shared library, or if the symbol is 187959024Sobrien defined by a dynamic object, we will need a dynamic reloc 188059024Sobrien entry. */ 188159024Sobrien if (info->shared 188259024Sobrien || (h != NULL 188359024Sobrien && (h->flags & SUNOS_DEF_DYNAMIC) != 0 188459024Sobrien && (h->flags & SUNOS_DEF_REGULAR) == 0)) 188559024Sobrien srel->_raw_size += RELOC_EXT_SIZE; 188659024Sobrien 188759024Sobrien continue; 188859024Sobrien } 188959024Sobrien 189059024Sobrien /* Otherwise, we are only interested in relocs against symbols 1891130561Sobrien defined in dynamic objects but not in regular objects. We 1892130561Sobrien only need to consider relocs against external symbols. */ 189359024Sobrien if (! r_extern) 189459024Sobrien { 189559024Sobrien /* But, if we are creating a shared library, we need to 1896130561Sobrien generate an absolute reloc. */ 189759024Sobrien if (info->shared) 189859024Sobrien { 189959024Sobrien if (dynobj == NULL) 190059024Sobrien { 1901130561Sobrien if (! sunos_create_dynamic_sections (abfd, info, TRUE)) 1902130561Sobrien return FALSE; 190359024Sobrien dynobj = sunos_hash_table (info)->dynobj; 190459024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 190559024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 190659024Sobrien srel = bfd_get_section_by_name (dynobj, ".dynrel"); 190759024Sobrien BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL); 190859024Sobrien } 190959024Sobrien 191059024Sobrien srel->_raw_size += RELOC_EXT_SIZE; 191159024Sobrien } 191259024Sobrien 191359024Sobrien continue; 191459024Sobrien } 191559024Sobrien 191659024Sobrien /* At this point common symbols have already been allocated, so 191759024Sobrien we don't have to worry about them. We need to consider that 191859024Sobrien we may have already seen this symbol and marked it undefined; 191959024Sobrien if the symbol is really undefined, then SUNOS_DEF_DYNAMIC 192059024Sobrien will be zero. */ 192159024Sobrien if (h->root.root.type != bfd_link_hash_defined 192259024Sobrien && h->root.root.type != bfd_link_hash_defweak 192359024Sobrien && h->root.root.type != bfd_link_hash_undefined) 192459024Sobrien continue; 192559024Sobrien 192659024Sobrien if (r_type != RELOC_JMP_TBL 192759024Sobrien && ! info->shared 192859024Sobrien && ((h->flags & SUNOS_DEF_DYNAMIC) == 0 192959024Sobrien || (h->flags & SUNOS_DEF_REGULAR) != 0)) 193059024Sobrien continue; 193159024Sobrien 193259024Sobrien if (r_type == RELOC_JMP_TBL 193359024Sobrien && ! info->shared 193459024Sobrien && (h->flags & SUNOS_DEF_DYNAMIC) == 0 193559024Sobrien && (h->flags & SUNOS_DEF_REGULAR) == 0) 193659024Sobrien { 193759024Sobrien /* This symbol is apparently undefined. Don't do anything 1938130561Sobrien here; just let the relocation routine report an undefined 1939130561Sobrien symbol. */ 194059024Sobrien continue; 194159024Sobrien } 194259024Sobrien 194359024Sobrien if (strcmp (h->root.root.root.string, "__GLOBAL_OFFSET_TABLE_") == 0) 194459024Sobrien continue; 194559024Sobrien 194659024Sobrien if (dynobj == NULL) 194759024Sobrien { 1948130561Sobrien if (! sunos_create_dynamic_sections (abfd, info, FALSE)) 1949130561Sobrien return FALSE; 195059024Sobrien dynobj = sunos_hash_table (info)->dynobj; 195159024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 195259024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 195359024Sobrien srel = bfd_get_section_by_name (dynobj, ".dynrel"); 195459024Sobrien BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL); 195559024Sobrien 195659024Sobrien /* Make sure we have an initial entry in the .got table. */ 195759024Sobrien if (sgot->_raw_size == 0) 195859024Sobrien sgot->_raw_size = BYTES_IN_WORD; 1959130561Sobrien sunos_hash_table (info)->got_needed = TRUE; 196059024Sobrien } 196159024Sobrien 196259024Sobrien BFD_ASSERT (r_type == RELOC_JMP_TBL 196359024Sobrien || info->shared 196459024Sobrien || (h->flags & SUNOS_REF_REGULAR) != 0); 196559024Sobrien BFD_ASSERT (r_type == RELOC_JMP_TBL 196659024Sobrien || info->shared 196759024Sobrien || h->plt_offset != 0 196859024Sobrien || ((h->root.root.type == bfd_link_hash_defined 196959024Sobrien || h->root.root.type == bfd_link_hash_defweak) 197059024Sobrien ? (h->root.root.u.def.section->owner->flags 197159024Sobrien & DYNAMIC) != 0 197259024Sobrien : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0)); 197359024Sobrien 197459024Sobrien /* This reloc is against a symbol defined only by a dynamic 197559024Sobrien object, or it is a jump table reloc from PIC compiled code. */ 197659024Sobrien 197759024Sobrien if (r_type != RELOC_JMP_TBL 197859024Sobrien && h->root.root.type == bfd_link_hash_undefined) 197959024Sobrien { 198059024Sobrien /* Presumably this symbol was marked as being undefined by 198159024Sobrien an earlier reloc. */ 198259024Sobrien srel->_raw_size += RELOC_EXT_SIZE; 198359024Sobrien } 198459024Sobrien else if (r_type != RELOC_JMP_TBL 198559024Sobrien && (h->root.root.u.def.section->flags & SEC_CODE) == 0) 198659024Sobrien { 198759024Sobrien bfd *sub; 198859024Sobrien 198959024Sobrien /* This reloc is not in the .text section. It must be 199059024Sobrien copied into the dynamic relocs. We mark the symbol as 199159024Sobrien being undefined. */ 199259024Sobrien srel->_raw_size += RELOC_EXT_SIZE; 199359024Sobrien if ((h->flags & SUNOS_DEF_REGULAR) == 0) 199459024Sobrien { 199559024Sobrien sub = h->root.root.u.def.section->owner; 199659024Sobrien h->root.root.type = bfd_link_hash_undefined; 199759024Sobrien h->root.root.u.undef.abfd = sub; 199859024Sobrien } 199959024Sobrien } 200059024Sobrien else 200159024Sobrien { 200259024Sobrien /* This symbol is in the .text section. We must give it an 200359024Sobrien entry in the procedure linkage table, if we have not 200459024Sobrien already done so. We change the definition of the symbol 200559024Sobrien to the .plt section; this will cause relocs against it to 200659024Sobrien be handled correctly. */ 200759024Sobrien if (h->plt_offset == 0) 200859024Sobrien { 200959024Sobrien if (splt->_raw_size == 0) 201059024Sobrien splt->_raw_size = SPARC_PLT_ENTRY_SIZE; 201159024Sobrien h->plt_offset = splt->_raw_size; 201259024Sobrien 201359024Sobrien if ((h->flags & SUNOS_DEF_REGULAR) == 0) 201459024Sobrien { 201559024Sobrien if (h->root.root.type == bfd_link_hash_undefined) 201659024Sobrien h->root.root.type = bfd_link_hash_defined; 201759024Sobrien h->root.root.u.def.section = splt; 201859024Sobrien h->root.root.u.def.value = splt->_raw_size; 201959024Sobrien } 202059024Sobrien 202159024Sobrien splt->_raw_size += SPARC_PLT_ENTRY_SIZE; 202259024Sobrien 202359024Sobrien /* We will also need a dynamic reloc entry, unless this 2024130561Sobrien is a JMP_TBL reloc produced by linking PIC compiled 2025130561Sobrien code, and we are not making a shared library. */ 202659024Sobrien if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0) 202759024Sobrien srel->_raw_size += RELOC_EXT_SIZE; 202859024Sobrien } 202959024Sobrien 203059024Sobrien /* If we are creating a shared library, we need to copy over 2031130561Sobrien any reloc other than a jump table reloc. */ 203259024Sobrien if (info->shared && r_type != RELOC_JMP_TBL) 203359024Sobrien srel->_raw_size += RELOC_EXT_SIZE; 203459024Sobrien } 203559024Sobrien } 203659024Sobrien 2037130561Sobrien return TRUE; 203859024Sobrien} 203959024Sobrien 204059024Sobrien/* Build the hash table of dynamic symbols, and to mark as written all 204159024Sobrien symbols from dynamic objects which we do not plan to write out. */ 204259024Sobrien 2043130561Sobrienstatic bfd_boolean 204459024Sobriensunos_scan_dynamic_symbol (h, data) 204559024Sobrien struct sunos_link_hash_entry *h; 204659024Sobrien PTR data; 204759024Sobrien{ 204859024Sobrien struct bfd_link_info *info = (struct bfd_link_info *) data; 204959024Sobrien 205094536Sobrien if (h->root.root.type == bfd_link_hash_warning) 205194536Sobrien h = (struct sunos_link_hash_entry *) h->root.root.u.i.link; 205294536Sobrien 205359024Sobrien /* Set the written flag for symbols we do not want to write out as 205459024Sobrien part of the regular symbol table. This is all symbols which are 205559024Sobrien not defined in a regular object file. For some reason symbols 205659024Sobrien which are referenced by a regular object and defined by a dynamic 205759024Sobrien object do not seem to show up in the regular symbol table. It is 205859024Sobrien possible for a symbol to have only SUNOS_REF_REGULAR set here, it 205959024Sobrien is an undefined symbol which was turned into a common symbol 206059024Sobrien because it was found in an archive object which was not included 206159024Sobrien in the link. */ 206259024Sobrien if ((h->flags & SUNOS_DEF_REGULAR) == 0 206359024Sobrien && (h->flags & SUNOS_DEF_DYNAMIC) != 0 206459024Sobrien && strcmp (h->root.root.root.string, "__DYNAMIC") != 0) 2065130561Sobrien h->root.written = TRUE; 206659024Sobrien 206759024Sobrien /* If this symbol is defined by a dynamic object and referenced by a 206859024Sobrien regular object, see whether we gave it a reasonable value while 206959024Sobrien scanning the relocs. */ 207059024Sobrien 207159024Sobrien if ((h->flags & SUNOS_DEF_REGULAR) == 0 207259024Sobrien && (h->flags & SUNOS_DEF_DYNAMIC) != 0 207359024Sobrien && (h->flags & SUNOS_REF_REGULAR) != 0) 207459024Sobrien { 207559024Sobrien if ((h->root.root.type == bfd_link_hash_defined 207659024Sobrien || h->root.root.type == bfd_link_hash_defweak) 207759024Sobrien && ((h->root.root.u.def.section->owner->flags & DYNAMIC) != 0) 207859024Sobrien && h->root.root.u.def.section->output_section == NULL) 207959024Sobrien { 208059024Sobrien bfd *sub; 208159024Sobrien 208259024Sobrien /* This symbol is currently defined in a dynamic section 208359024Sobrien which is not being put into the output file. This 208459024Sobrien implies that there is no reloc against the symbol. I'm 208559024Sobrien not sure why this case would ever occur. In any case, we 208659024Sobrien change the symbol to be undefined. */ 208759024Sobrien sub = h->root.root.u.def.section->owner; 208859024Sobrien h->root.root.type = bfd_link_hash_undefined; 208959024Sobrien h->root.root.u.undef.abfd = sub; 209059024Sobrien } 209159024Sobrien } 209259024Sobrien 209359024Sobrien /* If this symbol is defined or referenced by a regular file, add it 209459024Sobrien to the dynamic symbols. */ 209559024Sobrien if ((h->flags & (SUNOS_DEF_REGULAR | SUNOS_REF_REGULAR)) != 0) 209659024Sobrien { 209759024Sobrien asection *s; 209859024Sobrien size_t len; 209959024Sobrien bfd_byte *contents; 210059024Sobrien unsigned char *name; 210159024Sobrien unsigned long hash; 210259024Sobrien bfd *dynobj; 210359024Sobrien 210459024Sobrien BFD_ASSERT (h->dynindx == -2); 210559024Sobrien 210659024Sobrien dynobj = sunos_hash_table (info)->dynobj; 210759024Sobrien 210859024Sobrien h->dynindx = sunos_hash_table (info)->dynsymcount; 210959024Sobrien ++sunos_hash_table (info)->dynsymcount; 211059024Sobrien 211159024Sobrien len = strlen (h->root.root.root.string); 211259024Sobrien 211359024Sobrien /* We don't bother to construct a BFD hash table for the strings 211459024Sobrien which are the names of the dynamic symbols. Using a hash 211559024Sobrien table for the regular symbols is beneficial, because the 211659024Sobrien regular symbols includes the debugging symbols, which have 211759024Sobrien long names and are often duplicated in several object files. 211859024Sobrien There are no debugging symbols in the dynamic symbols. */ 211959024Sobrien s = bfd_get_section_by_name (dynobj, ".dynstr"); 212059024Sobrien BFD_ASSERT (s != NULL); 212159024Sobrien contents = (bfd_byte *) bfd_realloc (s->contents, 212259024Sobrien s->_raw_size + len + 1); 212359024Sobrien if (contents == NULL) 2124130561Sobrien return FALSE; 212559024Sobrien s->contents = contents; 212659024Sobrien 212759024Sobrien h->dynstr_index = s->_raw_size; 212859024Sobrien strcpy ((char *) contents + s->_raw_size, h->root.root.root.string); 212959024Sobrien s->_raw_size += len + 1; 213059024Sobrien 213159024Sobrien /* Add it to the dynamic hash table. */ 213259024Sobrien name = (unsigned char *) h->root.root.root.string; 213359024Sobrien hash = 0; 213459024Sobrien while (*name != '\0') 213559024Sobrien hash = (hash << 1) + *name++; 213659024Sobrien hash &= 0x7fffffff; 213759024Sobrien hash %= sunos_hash_table (info)->bucketcount; 213859024Sobrien 213959024Sobrien s = bfd_get_section_by_name (dynobj, ".hash"); 214059024Sobrien BFD_ASSERT (s != NULL); 214159024Sobrien 214259024Sobrien if (GET_SWORD (dynobj, s->contents + hash * HASH_ENTRY_SIZE) == -1) 214359024Sobrien PUT_WORD (dynobj, h->dynindx, s->contents + hash * HASH_ENTRY_SIZE); 214459024Sobrien else 214559024Sobrien { 214659024Sobrien bfd_vma next; 214759024Sobrien 214859024Sobrien next = GET_WORD (dynobj, 214959024Sobrien (s->contents 215059024Sobrien + hash * HASH_ENTRY_SIZE 215159024Sobrien + BYTES_IN_WORD)); 215259024Sobrien PUT_WORD (dynobj, s->_raw_size / HASH_ENTRY_SIZE, 215359024Sobrien s->contents + hash * HASH_ENTRY_SIZE + BYTES_IN_WORD); 215459024Sobrien PUT_WORD (dynobj, h->dynindx, s->contents + s->_raw_size); 215559024Sobrien PUT_WORD (dynobj, next, s->contents + s->_raw_size + BYTES_IN_WORD); 215659024Sobrien s->_raw_size += HASH_ENTRY_SIZE; 215759024Sobrien } 215859024Sobrien } 215959024Sobrien 2160130561Sobrien return TRUE; 216159024Sobrien} 216259024Sobrien 216359024Sobrien/* Link a dynamic object. We actually don't have anything to do at 216459024Sobrien this point. This entry point exists to prevent the regular linker 216559024Sobrien code from doing anything with the object. */ 216659024Sobrien 2167130561Sobrienstatic bfd_boolean 216859024Sobriensunos_link_dynamic_object (info, abfd) 216984865Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED; 217084865Sobrien bfd *abfd ATTRIBUTE_UNUSED; 217159024Sobrien{ 2172130561Sobrien return TRUE; 217359024Sobrien} 217459024Sobrien 217559024Sobrien/* Write out a dynamic symbol. This is called by the final traversal 217659024Sobrien over the symbol table. */ 217759024Sobrien 2178130561Sobrienstatic bfd_boolean 217959024Sobriensunos_write_dynamic_symbol (output_bfd, info, harg) 218059024Sobrien bfd *output_bfd; 218159024Sobrien struct bfd_link_info *info; 218259024Sobrien struct aout_link_hash_entry *harg; 218359024Sobrien{ 218459024Sobrien struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg; 218559024Sobrien int type; 218659024Sobrien bfd_vma val; 218759024Sobrien asection *s; 218859024Sobrien struct external_nlist *outsym; 218959024Sobrien 219059024Sobrien /* If this symbol is in the procedure linkage table, fill in the 219159024Sobrien table entry. */ 219259024Sobrien if (h->plt_offset != 0) 219359024Sobrien { 219459024Sobrien bfd *dynobj; 219559024Sobrien asection *splt; 219659024Sobrien bfd_byte *p; 219759024Sobrien bfd_vma r_address; 219859024Sobrien 219959024Sobrien dynobj = sunos_hash_table (info)->dynobj; 220059024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 220159024Sobrien p = splt->contents + h->plt_offset; 220259024Sobrien 220359024Sobrien s = bfd_get_section_by_name (dynobj, ".dynrel"); 220459024Sobrien 220559024Sobrien r_address = (splt->output_section->vma 220659024Sobrien + splt->output_offset 220759024Sobrien + h->plt_offset); 220859024Sobrien 220959024Sobrien switch (bfd_get_arch (output_bfd)) 221059024Sobrien { 221159024Sobrien case bfd_arch_sparc: 221259024Sobrien if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0) 221359024Sobrien { 221459024Sobrien bfd_put_32 (output_bfd, SPARC_PLT_ENTRY_WORD0, p); 221559024Sobrien bfd_put_32 (output_bfd, 221659024Sobrien (SPARC_PLT_ENTRY_WORD1 221759024Sobrien + (((- (h->plt_offset + 4) >> 2) 221859024Sobrien & 0x3fffffff))), 221959024Sobrien p + 4); 222059024Sobrien bfd_put_32 (output_bfd, SPARC_PLT_ENTRY_WORD2 + s->reloc_count, 222159024Sobrien p + 8); 222259024Sobrien } 222359024Sobrien else 222459024Sobrien { 222559024Sobrien val = (h->root.root.u.def.section->output_section->vma 222659024Sobrien + h->root.root.u.def.section->output_offset 222759024Sobrien + h->root.root.u.def.value); 222859024Sobrien bfd_put_32 (output_bfd, 222959024Sobrien SPARC_PLT_PIC_WORD0 + ((val >> 10) & 0x3fffff), 223059024Sobrien p); 223159024Sobrien bfd_put_32 (output_bfd, 223259024Sobrien SPARC_PLT_PIC_WORD1 + (val & 0x3ff), 223359024Sobrien p + 4); 223459024Sobrien bfd_put_32 (output_bfd, SPARC_PLT_PIC_WORD2, p + 8); 223559024Sobrien } 223659024Sobrien break; 223759024Sobrien 223859024Sobrien case bfd_arch_m68k: 223959024Sobrien if (! info->shared && (h->flags & SUNOS_DEF_REGULAR) != 0) 224059024Sobrien abort (); 224159024Sobrien bfd_put_16 (output_bfd, M68K_PLT_ENTRY_WORD0, p); 224259024Sobrien bfd_put_32 (output_bfd, (- (h->plt_offset + 2)), p + 2); 224389857Sobrien bfd_put_16 (output_bfd, (bfd_vma) s->reloc_count, p + 6); 224459024Sobrien r_address += 2; 224559024Sobrien break; 224659024Sobrien 224759024Sobrien default: 224859024Sobrien abort (); 224959024Sobrien } 225059024Sobrien 225159024Sobrien /* We also need to add a jump table reloc, unless this is the 2252130561Sobrien result of a JMP_TBL reloc from PIC compiled code. */ 225359024Sobrien if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0) 225459024Sobrien { 225559024Sobrien BFD_ASSERT (h->dynindx >= 0); 225659024Sobrien BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) 225759024Sobrien < s->_raw_size); 225859024Sobrien p = s->contents + s->reloc_count * obj_reloc_entry_size (output_bfd); 225959024Sobrien if (obj_reloc_entry_size (output_bfd) == RELOC_STD_SIZE) 226059024Sobrien { 226159024Sobrien struct reloc_std_external *srel; 226259024Sobrien 226359024Sobrien srel = (struct reloc_std_external *) p; 226459024Sobrien PUT_WORD (output_bfd, r_address, srel->r_address); 226559024Sobrien if (bfd_header_big_endian (output_bfd)) 226659024Sobrien { 226784865Sobrien srel->r_index[0] = (bfd_byte) (h->dynindx >> 16); 226884865Sobrien srel->r_index[1] = (bfd_byte) (h->dynindx >> 8); 226984865Sobrien srel->r_index[2] = (bfd_byte) (h->dynindx); 227059024Sobrien srel->r_type[0] = (RELOC_STD_BITS_EXTERN_BIG 227159024Sobrien | RELOC_STD_BITS_JMPTABLE_BIG); 227259024Sobrien } 227359024Sobrien else 227459024Sobrien { 227584865Sobrien srel->r_index[2] = (bfd_byte) (h->dynindx >> 16); 227684865Sobrien srel->r_index[1] = (bfd_byte) (h->dynindx >> 8); 227759024Sobrien srel->r_index[0] = (bfd_byte)h->dynindx; 227859024Sobrien srel->r_type[0] = (RELOC_STD_BITS_EXTERN_LITTLE 227959024Sobrien | RELOC_STD_BITS_JMPTABLE_LITTLE); 228059024Sobrien } 228159024Sobrien } 228259024Sobrien else 228359024Sobrien { 228459024Sobrien struct reloc_ext_external *erel; 228559024Sobrien 228659024Sobrien erel = (struct reloc_ext_external *) p; 228759024Sobrien PUT_WORD (output_bfd, r_address, erel->r_address); 228859024Sobrien if (bfd_header_big_endian (output_bfd)) 228959024Sobrien { 229084865Sobrien erel->r_index[0] = (bfd_byte) (h->dynindx >> 16); 229184865Sobrien erel->r_index[1] = (bfd_byte) (h->dynindx >> 8); 229259024Sobrien erel->r_index[2] = (bfd_byte)h->dynindx; 229359024Sobrien erel->r_type[0] = 229459024Sobrien (RELOC_EXT_BITS_EXTERN_BIG 229559024Sobrien | (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_BIG)); 229659024Sobrien } 229759024Sobrien else 229859024Sobrien { 229984865Sobrien erel->r_index[2] = (bfd_byte) (h->dynindx >> 16); 230084865Sobrien erel->r_index[1] = (bfd_byte) (h->dynindx >> 8); 230159024Sobrien erel->r_index[0] = (bfd_byte)h->dynindx; 230259024Sobrien erel->r_type[0] = 230359024Sobrien (RELOC_EXT_BITS_EXTERN_LITTLE 230459024Sobrien | (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_LITTLE)); 230559024Sobrien } 230659024Sobrien PUT_WORD (output_bfd, (bfd_vma) 0, erel->r_addend); 230759024Sobrien } 230859024Sobrien 230959024Sobrien ++s->reloc_count; 231059024Sobrien } 231159024Sobrien } 231259024Sobrien 231359024Sobrien /* If this is not a dynamic symbol, we don't have to do anything 231459024Sobrien else. We only check this after handling the PLT entry, because 231559024Sobrien we can have a PLT entry for a nondynamic symbol when linking PIC 231659024Sobrien compiled code from a regular object. */ 231759024Sobrien if (h->dynindx < 0) 2318130561Sobrien return TRUE; 231959024Sobrien 232059024Sobrien switch (h->root.root.type) 232159024Sobrien { 232259024Sobrien default: 232359024Sobrien case bfd_link_hash_new: 232459024Sobrien abort (); 232559024Sobrien /* Avoid variable not initialized warnings. */ 2326130561Sobrien return TRUE; 232759024Sobrien case bfd_link_hash_undefined: 232859024Sobrien type = N_UNDF | N_EXT; 232959024Sobrien val = 0; 233059024Sobrien break; 233159024Sobrien case bfd_link_hash_defined: 233259024Sobrien case bfd_link_hash_defweak: 233359024Sobrien { 233459024Sobrien asection *sec; 233559024Sobrien asection *output_section; 233659024Sobrien 233759024Sobrien sec = h->root.root.u.def.section; 233859024Sobrien output_section = sec->output_section; 233959024Sobrien BFD_ASSERT (bfd_is_abs_section (output_section) 234059024Sobrien || output_section->owner == output_bfd); 234159024Sobrien if (h->plt_offset != 0 234259024Sobrien && (h->flags & SUNOS_DEF_REGULAR) == 0) 234359024Sobrien { 234459024Sobrien type = N_UNDF | N_EXT; 234559024Sobrien val = 0; 234659024Sobrien } 234759024Sobrien else 234859024Sobrien { 234959024Sobrien if (output_section == obj_textsec (output_bfd)) 235059024Sobrien type = (h->root.root.type == bfd_link_hash_defined 235159024Sobrien ? N_TEXT 235259024Sobrien : N_WEAKT); 235359024Sobrien else if (output_section == obj_datasec (output_bfd)) 235459024Sobrien type = (h->root.root.type == bfd_link_hash_defined 235559024Sobrien ? N_DATA 235659024Sobrien : N_WEAKD); 235759024Sobrien else if (output_section == obj_bsssec (output_bfd)) 235859024Sobrien type = (h->root.root.type == bfd_link_hash_defined 235959024Sobrien ? N_BSS 236059024Sobrien : N_WEAKB); 236159024Sobrien else 236259024Sobrien type = (h->root.root.type == bfd_link_hash_defined 236359024Sobrien ? N_ABS 236459024Sobrien : N_WEAKA); 236559024Sobrien type |= N_EXT; 236659024Sobrien val = (h->root.root.u.def.value 236759024Sobrien + output_section->vma 236859024Sobrien + sec->output_offset); 236959024Sobrien } 237059024Sobrien } 237159024Sobrien break; 237259024Sobrien case bfd_link_hash_common: 237359024Sobrien type = N_UNDF | N_EXT; 237459024Sobrien val = h->root.root.u.c.size; 237559024Sobrien break; 237659024Sobrien case bfd_link_hash_undefweak: 237759024Sobrien type = N_WEAKU; 237859024Sobrien val = 0; 237959024Sobrien break; 238059024Sobrien case bfd_link_hash_indirect: 238159024Sobrien case bfd_link_hash_warning: 238259024Sobrien /* FIXME: Ignore these for now. The circumstances under which 238359024Sobrien they should be written out are not clear to me. */ 2384130561Sobrien return TRUE; 238559024Sobrien } 238659024Sobrien 238759024Sobrien s = bfd_get_section_by_name (sunos_hash_table (info)->dynobj, ".dynsym"); 238859024Sobrien BFD_ASSERT (s != NULL); 238959024Sobrien outsym = ((struct external_nlist *) 239059024Sobrien (s->contents + h->dynindx * EXTERNAL_NLIST_SIZE)); 239159024Sobrien 239289857Sobrien H_PUT_8 (output_bfd, type, outsym->e_type); 239389857Sobrien H_PUT_8 (output_bfd, 0, outsym->e_other); 239459024Sobrien 239559024Sobrien /* FIXME: The native linker doesn't use 0 for desc. It seems to use 239659024Sobrien one less than the desc value in the shared library, although that 239759024Sobrien seems unlikely. */ 239889857Sobrien H_PUT_16 (output_bfd, 0, outsym->e_desc); 239959024Sobrien 240059024Sobrien PUT_WORD (output_bfd, h->dynstr_index, outsym->e_strx); 240159024Sobrien PUT_WORD (output_bfd, val, outsym->e_value); 240259024Sobrien 2403130561Sobrien return TRUE; 240459024Sobrien} 240559024Sobrien 240659024Sobrien/* This is called for each reloc against an external symbol. If this 240759024Sobrien is a reloc which are are going to copy as a dynamic reloc, then 240859024Sobrien copy it over, and tell the caller to not bother processing this 240959024Sobrien reloc. */ 241059024Sobrien 2411130561Sobrienstatic bfd_boolean 241259024Sobriensunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc, 241359024Sobrien contents, skip, relocationp) 241459024Sobrien struct bfd_link_info *info; 241559024Sobrien bfd *input_bfd; 241659024Sobrien asection *input_section; 241759024Sobrien struct aout_link_hash_entry *harg; 241859024Sobrien PTR reloc; 241984865Sobrien bfd_byte *contents ATTRIBUTE_UNUSED; 2420130561Sobrien bfd_boolean *skip; 242159024Sobrien bfd_vma *relocationp; 242259024Sobrien{ 242359024Sobrien struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg; 242459024Sobrien bfd *dynobj; 2425130561Sobrien bfd_boolean baserel; 2426130561Sobrien bfd_boolean jmptbl; 2427130561Sobrien bfd_boolean pcrel; 242859024Sobrien asection *s; 242959024Sobrien bfd_byte *p; 243059024Sobrien long indx; 243159024Sobrien 2432130561Sobrien *skip = FALSE; 243359024Sobrien 243459024Sobrien dynobj = sunos_hash_table (info)->dynobj; 243559024Sobrien 243684865Sobrien if (h != NULL 243784865Sobrien && h->plt_offset != 0 243884865Sobrien && (info->shared 243984865Sobrien || (h->flags & SUNOS_DEF_REGULAR) == 0)) 244059024Sobrien { 244159024Sobrien asection *splt; 244259024Sobrien 244359024Sobrien /* Redirect the relocation to the PLT entry. */ 244459024Sobrien splt = bfd_get_section_by_name (dynobj, ".plt"); 244559024Sobrien *relocationp = (splt->output_section->vma 244659024Sobrien + splt->output_offset 244759024Sobrien + h->plt_offset); 244859024Sobrien } 244959024Sobrien 245059024Sobrien if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE) 245159024Sobrien { 245259024Sobrien struct reloc_std_external *srel; 245359024Sobrien 245459024Sobrien srel = (struct reloc_std_external *) reloc; 245559024Sobrien if (bfd_header_big_endian (input_bfd)) 245659024Sobrien { 245759024Sobrien baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG)); 245859024Sobrien jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG)); 245984865Sobrien pcrel = (0 != (srel->r_type[0] & RELOC_STD_BITS_PCREL_BIG)); 246059024Sobrien } 246159024Sobrien else 246259024Sobrien { 246359024Sobrien baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE)); 246459024Sobrien jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE)); 246584865Sobrien pcrel = (0 != (srel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE)); 246659024Sobrien } 246759024Sobrien } 246859024Sobrien else 246959024Sobrien { 247059024Sobrien struct reloc_ext_external *erel; 247159024Sobrien int r_type; 247259024Sobrien 247359024Sobrien erel = (struct reloc_ext_external *) reloc; 247459024Sobrien if (bfd_header_big_endian (input_bfd)) 247559024Sobrien r_type = ((erel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG) 247659024Sobrien >> RELOC_EXT_BITS_TYPE_SH_BIG); 247759024Sobrien else 247859024Sobrien r_type = ((erel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE) 247959024Sobrien >> RELOC_EXT_BITS_TYPE_SH_LITTLE); 248059024Sobrien baserel = (r_type == RELOC_BASE10 248159024Sobrien || r_type == RELOC_BASE13 248259024Sobrien || r_type == RELOC_BASE22); 248359024Sobrien jmptbl = r_type == RELOC_JMP_TBL; 248484865Sobrien pcrel = (r_type == RELOC_DISP8 248584865Sobrien || r_type == RELOC_DISP16 248684865Sobrien || r_type == RELOC_DISP32 248784865Sobrien || r_type == RELOC_WDISP30 248884865Sobrien || r_type == RELOC_WDISP22); 248984865Sobrien /* We don't consider the PC10 and PC22 types to be PC relative, 2490130561Sobrien because they are pcrel_offset. */ 249159024Sobrien } 249259024Sobrien 249359024Sobrien if (baserel) 249459024Sobrien { 249559024Sobrien bfd_vma *got_offsetp; 249659024Sobrien asection *sgot; 249759024Sobrien 249859024Sobrien if (h != NULL) 249959024Sobrien got_offsetp = &h->got_offset; 250059024Sobrien else if (adata (input_bfd).local_got_offsets == NULL) 250159024Sobrien got_offsetp = NULL; 250259024Sobrien else 250359024Sobrien { 250459024Sobrien struct reloc_std_external *srel; 250559024Sobrien int r_index; 250659024Sobrien 250759024Sobrien srel = (struct reloc_std_external *) reloc; 250859024Sobrien if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE) 250959024Sobrien { 251059024Sobrien if (bfd_header_big_endian (input_bfd)) 251159024Sobrien r_index = ((srel->r_index[0] << 16) 251259024Sobrien | (srel->r_index[1] << 8) 251359024Sobrien | srel->r_index[2]); 251459024Sobrien else 251559024Sobrien r_index = ((srel->r_index[2] << 16) 251659024Sobrien | (srel->r_index[1] << 8) 251759024Sobrien | srel->r_index[0]); 251859024Sobrien } 251959024Sobrien else 252059024Sobrien { 252159024Sobrien struct reloc_ext_external *erel; 252259024Sobrien 252359024Sobrien erel = (struct reloc_ext_external *) reloc; 252459024Sobrien if (bfd_header_big_endian (input_bfd)) 252559024Sobrien r_index = ((erel->r_index[0] << 16) 252659024Sobrien | (erel->r_index[1] << 8) 252759024Sobrien | erel->r_index[2]); 252859024Sobrien else 252959024Sobrien r_index = ((erel->r_index[2] << 16) 253059024Sobrien | (erel->r_index[1] << 8) 253159024Sobrien | erel->r_index[0]); 253259024Sobrien } 253359024Sobrien 253459024Sobrien got_offsetp = adata (input_bfd).local_got_offsets + r_index; 253559024Sobrien } 253659024Sobrien 253759024Sobrien BFD_ASSERT (got_offsetp != NULL && *got_offsetp != 0); 253859024Sobrien 253959024Sobrien sgot = bfd_get_section_by_name (dynobj, ".got"); 254059024Sobrien 254159024Sobrien /* We set the least significant bit to indicate whether we have 254259024Sobrien already initialized the GOT entry. */ 254359024Sobrien if ((*got_offsetp & 1) == 0) 254459024Sobrien { 254559024Sobrien if (h == NULL 254659024Sobrien || (! info->shared 254759024Sobrien && ((h->flags & SUNOS_DEF_DYNAMIC) == 0 254859024Sobrien || (h->flags & SUNOS_DEF_REGULAR) != 0))) 254959024Sobrien PUT_WORD (dynobj, *relocationp, sgot->contents + *got_offsetp); 255059024Sobrien else 255159024Sobrien PUT_WORD (dynobj, 0, sgot->contents + *got_offsetp); 255259024Sobrien 255359024Sobrien if (info->shared 255459024Sobrien || (h != NULL 255559024Sobrien && (h->flags & SUNOS_DEF_DYNAMIC) != 0 255659024Sobrien && (h->flags & SUNOS_DEF_REGULAR) == 0)) 255759024Sobrien { 255859024Sobrien /* We need to create a GLOB_DAT or 32 reloc to tell the 2559130561Sobrien dynamic linker to fill in this entry in the table. */ 256059024Sobrien 256159024Sobrien s = bfd_get_section_by_name (dynobj, ".dynrel"); 256259024Sobrien BFD_ASSERT (s != NULL); 256359024Sobrien BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) 256459024Sobrien < s->_raw_size); 256559024Sobrien 256659024Sobrien p = (s->contents 256759024Sobrien + s->reloc_count * obj_reloc_entry_size (dynobj)); 256859024Sobrien 256959024Sobrien if (h != NULL) 257059024Sobrien indx = h->dynindx; 257159024Sobrien else 257259024Sobrien indx = 0; 257359024Sobrien 257459024Sobrien if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE) 257559024Sobrien { 257659024Sobrien struct reloc_std_external *srel; 257759024Sobrien 257859024Sobrien srel = (struct reloc_std_external *) p; 257959024Sobrien PUT_WORD (dynobj, 258059024Sobrien (*got_offsetp 258159024Sobrien + sgot->output_section->vma 258259024Sobrien + sgot->output_offset), 258359024Sobrien srel->r_address); 258459024Sobrien if (bfd_header_big_endian (dynobj)) 258559024Sobrien { 258684865Sobrien srel->r_index[0] = (bfd_byte) (indx >> 16); 258784865Sobrien srel->r_index[1] = (bfd_byte) (indx >> 8); 258859024Sobrien srel->r_index[2] = (bfd_byte)indx; 258959024Sobrien if (h == NULL) 259059024Sobrien srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_BIG; 259159024Sobrien else 259259024Sobrien srel->r_type[0] = 259359024Sobrien (RELOC_STD_BITS_EXTERN_BIG 259459024Sobrien | RELOC_STD_BITS_BASEREL_BIG 259559024Sobrien | RELOC_STD_BITS_RELATIVE_BIG 259659024Sobrien | (2 << RELOC_STD_BITS_LENGTH_SH_BIG)); 259759024Sobrien } 259859024Sobrien else 259959024Sobrien { 260084865Sobrien srel->r_index[2] = (bfd_byte) (indx >> 16); 260184865Sobrien srel->r_index[1] = (bfd_byte) (indx >> 8); 260259024Sobrien srel->r_index[0] = (bfd_byte)indx; 260359024Sobrien if (h == NULL) 260459024Sobrien srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_LITTLE; 260559024Sobrien else 260659024Sobrien srel->r_type[0] = 260759024Sobrien (RELOC_STD_BITS_EXTERN_LITTLE 260859024Sobrien | RELOC_STD_BITS_BASEREL_LITTLE 260959024Sobrien | RELOC_STD_BITS_RELATIVE_LITTLE 261059024Sobrien | (2 << RELOC_STD_BITS_LENGTH_SH_LITTLE)); 261159024Sobrien } 261259024Sobrien } 261359024Sobrien else 261459024Sobrien { 261559024Sobrien struct reloc_ext_external *erel; 261659024Sobrien 261759024Sobrien erel = (struct reloc_ext_external *) p; 261859024Sobrien PUT_WORD (dynobj, 261959024Sobrien (*got_offsetp 262059024Sobrien + sgot->output_section->vma 262159024Sobrien + sgot->output_offset), 262259024Sobrien erel->r_address); 262359024Sobrien if (bfd_header_big_endian (dynobj)) 262459024Sobrien { 262584865Sobrien erel->r_index[0] = (bfd_byte) (indx >> 16); 262684865Sobrien erel->r_index[1] = (bfd_byte) (indx >> 8); 262759024Sobrien erel->r_index[2] = (bfd_byte)indx; 262859024Sobrien if (h == NULL) 262959024Sobrien erel->r_type[0] = 263059024Sobrien RELOC_32 << RELOC_EXT_BITS_TYPE_SH_BIG; 263159024Sobrien else 263259024Sobrien erel->r_type[0] = 263359024Sobrien (RELOC_EXT_BITS_EXTERN_BIG 263459024Sobrien | (RELOC_GLOB_DAT << RELOC_EXT_BITS_TYPE_SH_BIG)); 263559024Sobrien } 263659024Sobrien else 263759024Sobrien { 263884865Sobrien erel->r_index[2] = (bfd_byte) (indx >> 16); 263984865Sobrien erel->r_index[1] = (bfd_byte) (indx >> 8); 264059024Sobrien erel->r_index[0] = (bfd_byte)indx; 264159024Sobrien if (h == NULL) 264259024Sobrien erel->r_type[0] = 264359024Sobrien RELOC_32 << RELOC_EXT_BITS_TYPE_SH_LITTLE; 264459024Sobrien else 264559024Sobrien erel->r_type[0] = 264659024Sobrien (RELOC_EXT_BITS_EXTERN_LITTLE 264759024Sobrien | (RELOC_GLOB_DAT 264859024Sobrien << RELOC_EXT_BITS_TYPE_SH_LITTLE)); 264959024Sobrien } 265059024Sobrien PUT_WORD (dynobj, 0, erel->r_addend); 265159024Sobrien } 265259024Sobrien 265359024Sobrien ++s->reloc_count; 265459024Sobrien } 265559024Sobrien 265659024Sobrien *got_offsetp |= 1; 265759024Sobrien } 265859024Sobrien 265959024Sobrien *relocationp = (sgot->vma 266089857Sobrien + (*got_offsetp &~ (bfd_vma) 1) 266159024Sobrien - sunos_hash_table (info)->got_base); 266259024Sobrien 266359024Sobrien /* There is nothing else to do for a base relative reloc. */ 2664130561Sobrien return TRUE; 266559024Sobrien } 266659024Sobrien 266759024Sobrien if (! sunos_hash_table (info)->dynamic_sections_needed) 2668130561Sobrien return TRUE; 266959024Sobrien if (! info->shared) 267059024Sobrien { 267159024Sobrien if (h == NULL 267259024Sobrien || h->dynindx == -1 267359024Sobrien || h->root.root.type != bfd_link_hash_undefined 267459024Sobrien || (h->flags & SUNOS_DEF_REGULAR) != 0 267559024Sobrien || (h->flags & SUNOS_DEF_DYNAMIC) == 0 267659024Sobrien || (h->root.root.u.undef.abfd->flags & DYNAMIC) == 0) 2677130561Sobrien return TRUE; 267859024Sobrien } 267959024Sobrien else 268059024Sobrien { 268159024Sobrien if (h != NULL 268259024Sobrien && (h->dynindx == -1 268359024Sobrien || jmptbl 268459024Sobrien || strcmp (h->root.root.root.string, 268559024Sobrien "__GLOBAL_OFFSET_TABLE_") == 0)) 2686130561Sobrien return TRUE; 268759024Sobrien } 268859024Sobrien 268959024Sobrien /* It looks like this is a reloc we are supposed to copy. */ 269059024Sobrien 269159024Sobrien s = bfd_get_section_by_name (dynobj, ".dynrel"); 269259024Sobrien BFD_ASSERT (s != NULL); 269359024Sobrien BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) < s->_raw_size); 269459024Sobrien 269559024Sobrien p = s->contents + s->reloc_count * obj_reloc_entry_size (dynobj); 269659024Sobrien 269759024Sobrien /* Copy the reloc over. */ 269859024Sobrien memcpy (p, reloc, obj_reloc_entry_size (dynobj)); 269959024Sobrien 270059024Sobrien if (h != NULL) 270159024Sobrien indx = h->dynindx; 270259024Sobrien else 270359024Sobrien indx = 0; 270459024Sobrien 270559024Sobrien /* Adjust the address and symbol index. */ 270659024Sobrien if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE) 270759024Sobrien { 270859024Sobrien struct reloc_std_external *srel; 270959024Sobrien 271059024Sobrien srel = (struct reloc_std_external *) p; 271159024Sobrien PUT_WORD (dynobj, 271259024Sobrien (GET_WORD (dynobj, srel->r_address) 271359024Sobrien + input_section->output_section->vma 271459024Sobrien + input_section->output_offset), 271559024Sobrien srel->r_address); 271659024Sobrien if (bfd_header_big_endian (dynobj)) 271759024Sobrien { 271884865Sobrien srel->r_index[0] = (bfd_byte) (indx >> 16); 271984865Sobrien srel->r_index[1] = (bfd_byte) (indx >> 8); 272059024Sobrien srel->r_index[2] = (bfd_byte)indx; 272159024Sobrien } 272259024Sobrien else 272359024Sobrien { 272484865Sobrien srel->r_index[2] = (bfd_byte) (indx >> 16); 272584865Sobrien srel->r_index[1] = (bfd_byte) (indx >> 8); 272659024Sobrien srel->r_index[0] = (bfd_byte)indx; 272759024Sobrien } 272884865Sobrien /* FIXME: We may have to change the addend for a PC relative 2729130561Sobrien reloc. */ 273059024Sobrien } 273159024Sobrien else 273259024Sobrien { 273359024Sobrien struct reloc_ext_external *erel; 273459024Sobrien 273559024Sobrien erel = (struct reloc_ext_external *) p; 273659024Sobrien PUT_WORD (dynobj, 273759024Sobrien (GET_WORD (dynobj, erel->r_address) 273859024Sobrien + input_section->output_section->vma 273959024Sobrien + input_section->output_offset), 274059024Sobrien erel->r_address); 274159024Sobrien if (bfd_header_big_endian (dynobj)) 274259024Sobrien { 274384865Sobrien erel->r_index[0] = (bfd_byte) (indx >> 16); 274484865Sobrien erel->r_index[1] = (bfd_byte) (indx >> 8); 274559024Sobrien erel->r_index[2] = (bfd_byte)indx; 274659024Sobrien } 274759024Sobrien else 274859024Sobrien { 274984865Sobrien erel->r_index[2] = (bfd_byte) (indx >> 16); 275084865Sobrien erel->r_index[1] = (bfd_byte) (indx >> 8); 275159024Sobrien erel->r_index[0] = (bfd_byte)indx; 275259024Sobrien } 275384865Sobrien if (pcrel && h != NULL) 275484865Sobrien { 275584865Sobrien /* Adjust the addend for the change in address. */ 275684865Sobrien PUT_WORD (dynobj, 275784865Sobrien (GET_WORD (dynobj, erel->r_addend) 275884865Sobrien - (input_section->output_section->vma 275984865Sobrien + input_section->output_offset 276084865Sobrien - input_section->vma)), 276184865Sobrien erel->r_addend); 276284865Sobrien } 276359024Sobrien } 276459024Sobrien 276559024Sobrien ++s->reloc_count; 276659024Sobrien 276759024Sobrien if (h != NULL) 2768130561Sobrien *skip = TRUE; 276959024Sobrien 2770130561Sobrien return TRUE; 277159024Sobrien} 277259024Sobrien 277359024Sobrien/* Finish up the dynamic linking information. */ 277459024Sobrien 2775130561Sobrienstatic bfd_boolean 277659024Sobriensunos_finish_dynamic_link (abfd, info) 277759024Sobrien bfd *abfd; 277859024Sobrien struct bfd_link_info *info; 277959024Sobrien{ 278059024Sobrien bfd *dynobj; 278159024Sobrien asection *o; 278259024Sobrien asection *s; 278359024Sobrien asection *sdyn; 278459024Sobrien 278559024Sobrien if (! sunos_hash_table (info)->dynamic_sections_needed 278659024Sobrien && ! sunos_hash_table (info)->got_needed) 2787130561Sobrien return TRUE; 278859024Sobrien 278959024Sobrien dynobj = sunos_hash_table (info)->dynobj; 279059024Sobrien 279159024Sobrien sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 279259024Sobrien BFD_ASSERT (sdyn != NULL); 279359024Sobrien 279459024Sobrien /* Finish up the .need section. The linker emulation code filled it 279559024Sobrien in, but with offsets from the start of the section instead of 279659024Sobrien real addresses. Now that we know the section location, we can 279759024Sobrien fill in the final values. */ 279859024Sobrien s = bfd_get_section_by_name (dynobj, ".need"); 279959024Sobrien if (s != NULL && s->_raw_size != 0) 280059024Sobrien { 280159024Sobrien file_ptr filepos; 280259024Sobrien bfd_byte *p; 280359024Sobrien 280459024Sobrien filepos = s->output_section->filepos + s->output_offset; 280559024Sobrien p = s->contents; 280659024Sobrien while (1) 280759024Sobrien { 280859024Sobrien bfd_vma val; 280959024Sobrien 281059024Sobrien PUT_WORD (dynobj, GET_WORD (dynobj, p) + filepos, p); 281159024Sobrien val = GET_WORD (dynobj, p + 12); 281259024Sobrien if (val == 0) 281359024Sobrien break; 281459024Sobrien PUT_WORD (dynobj, val + filepos, p + 12); 281559024Sobrien p += 16; 281659024Sobrien } 281759024Sobrien } 281859024Sobrien 281959024Sobrien /* The first entry in the .got section is the address of the 282059024Sobrien dynamic information, unless this is a shared library. */ 282159024Sobrien s = bfd_get_section_by_name (dynobj, ".got"); 282259024Sobrien BFD_ASSERT (s != NULL); 282359024Sobrien if (info->shared || sdyn->_raw_size == 0) 282459024Sobrien PUT_WORD (dynobj, 0, s->contents); 282559024Sobrien else 282659024Sobrien PUT_WORD (dynobj, sdyn->output_section->vma + sdyn->output_offset, 282759024Sobrien s->contents); 282859024Sobrien 282959024Sobrien for (o = dynobj->sections; o != NULL; o = o->next) 283059024Sobrien { 283159024Sobrien if ((o->flags & SEC_HAS_CONTENTS) != 0 283259024Sobrien && o->contents != NULL) 283359024Sobrien { 283459024Sobrien BFD_ASSERT (o->output_section != NULL 283559024Sobrien && o->output_section->owner == abfd); 283659024Sobrien if (! bfd_set_section_contents (abfd, o->output_section, 283789857Sobrien o->contents, 283889857Sobrien (file_ptr) o->output_offset, 283959024Sobrien o->_raw_size)) 2840130561Sobrien return FALSE; 284159024Sobrien } 284259024Sobrien } 284359024Sobrien 284459024Sobrien if (sdyn->_raw_size > 0) 284559024Sobrien { 284659024Sobrien struct external_sun4_dynamic esd; 284759024Sobrien struct external_sun4_dynamic_link esdl; 284889857Sobrien file_ptr pos; 284959024Sobrien 285059024Sobrien /* Finish up the dynamic link information. */ 285159024Sobrien PUT_WORD (dynobj, (bfd_vma) 3, esd.ld_version); 285259024Sobrien PUT_WORD (dynobj, 285359024Sobrien sdyn->output_section->vma + sdyn->output_offset + sizeof esd, 285459024Sobrien esd.ldd); 285559024Sobrien PUT_WORD (dynobj, 285659024Sobrien (sdyn->output_section->vma 285759024Sobrien + sdyn->output_offset 285859024Sobrien + sizeof esd 285959024Sobrien + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE), 286059024Sobrien esd.ld); 286159024Sobrien 286259024Sobrien if (! bfd_set_section_contents (abfd, sdyn->output_section, &esd, 286389857Sobrien (file_ptr) sdyn->output_offset, 286489857Sobrien (bfd_size_type) sizeof esd)) 2865130561Sobrien return FALSE; 286659024Sobrien 286759024Sobrien PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_loaded); 286859024Sobrien 286959024Sobrien s = bfd_get_section_by_name (dynobj, ".need"); 287059024Sobrien if (s == NULL || s->_raw_size == 0) 287159024Sobrien PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_need); 287259024Sobrien else 287359024Sobrien PUT_WORD (dynobj, s->output_section->filepos + s->output_offset, 287459024Sobrien esdl.ld_need); 287559024Sobrien 287659024Sobrien s = bfd_get_section_by_name (dynobj, ".rules"); 287759024Sobrien if (s == NULL || s->_raw_size == 0) 287859024Sobrien PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_rules); 287959024Sobrien else 288059024Sobrien PUT_WORD (dynobj, s->output_section->filepos + s->output_offset, 288159024Sobrien esdl.ld_rules); 288259024Sobrien 288359024Sobrien s = bfd_get_section_by_name (dynobj, ".got"); 288459024Sobrien BFD_ASSERT (s != NULL); 288559024Sobrien PUT_WORD (dynobj, s->output_section->vma + s->output_offset, 288659024Sobrien esdl.ld_got); 288759024Sobrien 288859024Sobrien s = bfd_get_section_by_name (dynobj, ".plt"); 288959024Sobrien BFD_ASSERT (s != NULL); 289059024Sobrien PUT_WORD (dynobj, s->output_section->vma + s->output_offset, 289159024Sobrien esdl.ld_plt); 289259024Sobrien PUT_WORD (dynobj, s->_raw_size, esdl.ld_plt_sz); 289359024Sobrien 289459024Sobrien s = bfd_get_section_by_name (dynobj, ".dynrel"); 289559024Sobrien BFD_ASSERT (s != NULL); 289659024Sobrien BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) 289759024Sobrien == s->_raw_size); 289859024Sobrien PUT_WORD (dynobj, s->output_section->filepos + s->output_offset, 289959024Sobrien esdl.ld_rel); 290059024Sobrien 290159024Sobrien s = bfd_get_section_by_name (dynobj, ".hash"); 290259024Sobrien BFD_ASSERT (s != NULL); 290359024Sobrien PUT_WORD (dynobj, s->output_section->filepos + s->output_offset, 290459024Sobrien esdl.ld_hash); 290559024Sobrien 290659024Sobrien s = bfd_get_section_by_name (dynobj, ".dynsym"); 290759024Sobrien BFD_ASSERT (s != NULL); 290859024Sobrien PUT_WORD (dynobj, s->output_section->filepos + s->output_offset, 290959024Sobrien esdl.ld_stab); 291059024Sobrien 291159024Sobrien PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_stab_hash); 291259024Sobrien 291359024Sobrien PUT_WORD (dynobj, (bfd_vma) sunos_hash_table (info)->bucketcount, 291459024Sobrien esdl.ld_buckets); 291559024Sobrien 291659024Sobrien s = bfd_get_section_by_name (dynobj, ".dynstr"); 291759024Sobrien BFD_ASSERT (s != NULL); 291859024Sobrien PUT_WORD (dynobj, s->output_section->filepos + s->output_offset, 291959024Sobrien esdl.ld_symbols); 292059024Sobrien PUT_WORD (dynobj, s->_raw_size, esdl.ld_symb_size); 292159024Sobrien 292259024Sobrien /* The size of the text area is the size of the .text section 292359024Sobrien rounded up to a page boundary. FIXME: Should the page size be 292459024Sobrien conditional on something? */ 292559024Sobrien PUT_WORD (dynobj, 292659024Sobrien BFD_ALIGN (obj_textsec (abfd)->_raw_size, 0x2000), 292759024Sobrien esdl.ld_text); 292884865Sobrien 292989857Sobrien pos = sdyn->output_offset; 293089857Sobrien pos += sizeof esd + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE; 293159024Sobrien if (! bfd_set_section_contents (abfd, sdyn->output_section, &esdl, 293289857Sobrien pos, (bfd_size_type) sizeof esdl)) 2933130561Sobrien return FALSE; 293459024Sobrien 293559024Sobrien abfd->flags |= DYNAMIC; 293659024Sobrien } 293759024Sobrien 2938130561Sobrien return TRUE; 293959024Sobrien} 2940