xref: /openbsd-src/gnu/usr.bin/binutils/bfd/sunos.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
12159047fSniklas /* BFD backend for SunOS binaries.
2c074d1c9Sdrahn    Copyright 1990, 1991, 1992, 1994, 1995, 1996, 1997, 1998, 2000, 2001,
3*007c2a45Smiod    2002, 2003 Free Software Foundation, Inc.
42159047fSniklas    Written by Cygnus Support.
52159047fSniklas 
62159047fSniklas This file is part of BFD, the Binary File Descriptor library.
72159047fSniklas 
82159047fSniklas This program is free software; you can redistribute it and/or modify
92159047fSniklas it under the terms of the GNU General Public License as published by
102159047fSniklas the Free Software Foundation; either version 2 of the License, or
112159047fSniklas (at your option) any later version.
122159047fSniklas 
132159047fSniklas This program is distributed in the hope that it will be useful,
142159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
152159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
162159047fSniklas GNU General Public License for more details.
172159047fSniklas 
182159047fSniklas You should have received a copy of the GNU General Public License
192159047fSniklas along with this program; if not, write to the Free Software
202159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
212159047fSniklas 
222159047fSniklas #define TARGETNAME "a.out-sunos-big"
23c074d1c9Sdrahn 
24c074d1c9Sdrahn /* Do not "beautify" the CONCAT* macro args.  Traditional C will not
25c074d1c9Sdrahn    remove whitespace added here, and thus will fail to concatenate
26c074d1c9Sdrahn    the tokens.  */
27c074d1c9Sdrahn #define MY(OP) CONCAT2 (sunos_big_,OP)
282159047fSniklas 
292159047fSniklas #include "bfd.h"
302159047fSniklas #include "bfdlink.h"
312159047fSniklas #include "libaout.h"
322159047fSniklas 
332159047fSniklas /* Static routines defined in this file.  */
342159047fSniklas 
35c074d1c9Sdrahn static bfd_boolean sunos_read_dynamic_info PARAMS ((bfd *));
362159047fSniklas static long sunos_get_dynamic_symtab_upper_bound PARAMS ((bfd *));
37c074d1c9Sdrahn static bfd_boolean sunos_slurp_dynamic_symtab PARAMS ((bfd *));
382159047fSniklas static long sunos_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **));
392159047fSniklas static long sunos_get_dynamic_reloc_upper_bound PARAMS ((bfd *));
402159047fSniklas static long sunos_canonicalize_dynamic_reloc
412159047fSniklas   PARAMS ((bfd *, arelent **, asymbol **));
422159047fSniklas static struct bfd_hash_entry *sunos_link_hash_newfunc
432159047fSniklas   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
442159047fSniklas static struct bfd_link_hash_table *sunos_link_hash_table_create
452159047fSniklas   PARAMS ((bfd *));
46c074d1c9Sdrahn static bfd_boolean sunos_create_dynamic_sections
47c074d1c9Sdrahn   PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean));
48c074d1c9Sdrahn static bfd_boolean sunos_add_dynamic_symbols
492159047fSniklas   PARAMS ((bfd *, struct bfd_link_info *, struct external_nlist **,
502159047fSniklas 	   bfd_size_type *, char **));
51c074d1c9Sdrahn static bfd_boolean sunos_add_one_symbol
522159047fSniklas   PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
53c074d1c9Sdrahn 	   bfd_vma, const char *, bfd_boolean, bfd_boolean,
542159047fSniklas 	   struct bfd_link_hash_entry **));
55c074d1c9Sdrahn static bfd_boolean sunos_scan_relocs
562159047fSniklas   PARAMS ((struct bfd_link_info *, bfd *, asection *, bfd_size_type));
57c074d1c9Sdrahn static bfd_boolean sunos_scan_std_relocs
582159047fSniklas   PARAMS ((struct bfd_link_info *, bfd *, asection *,
592159047fSniklas 	   const struct reloc_std_external *, bfd_size_type));
60c074d1c9Sdrahn static bfd_boolean sunos_scan_ext_relocs
612159047fSniklas   PARAMS ((struct bfd_link_info *, bfd *, asection *,
622159047fSniklas 	   const struct reloc_ext_external *, bfd_size_type));
63c074d1c9Sdrahn static bfd_boolean sunos_link_dynamic_object
642159047fSniklas   PARAMS ((struct bfd_link_info *, bfd *));
65c074d1c9Sdrahn static bfd_boolean sunos_write_dynamic_symbol
662159047fSniklas   PARAMS ((bfd *, struct bfd_link_info *, struct aout_link_hash_entry *));
67c074d1c9Sdrahn static bfd_boolean sunos_check_dynamic_reloc
682159047fSniklas   PARAMS ((struct bfd_link_info *, bfd *, asection *,
69c074d1c9Sdrahn 	   struct aout_link_hash_entry *, PTR, bfd_byte *, bfd_boolean *,
702159047fSniklas 	   bfd_vma *));
71c074d1c9Sdrahn static bfd_boolean sunos_finish_dynamic_link
722159047fSniklas   PARAMS ((bfd *, struct bfd_link_info *));
732159047fSniklas 
742159047fSniklas #define MY_get_dynamic_symtab_upper_bound sunos_get_dynamic_symtab_upper_bound
752159047fSniklas #define MY_canonicalize_dynamic_symtab sunos_canonicalize_dynamic_symtab
762159047fSniklas #define MY_get_dynamic_reloc_upper_bound sunos_get_dynamic_reloc_upper_bound
772159047fSniklas #define MY_canonicalize_dynamic_reloc sunos_canonicalize_dynamic_reloc
782159047fSniklas #define MY_bfd_link_hash_table_create sunos_link_hash_table_create
792159047fSniklas #define MY_add_dynamic_symbols sunos_add_dynamic_symbols
802159047fSniklas #define MY_add_one_symbol sunos_add_one_symbol
812159047fSniklas #define MY_link_dynamic_object sunos_link_dynamic_object
822159047fSniklas #define MY_write_dynamic_symbol sunos_write_dynamic_symbol
832159047fSniklas #define MY_check_dynamic_reloc sunos_check_dynamic_reloc
842159047fSniklas #define MY_finish_dynamic_link sunos_finish_dynamic_link
852159047fSniklas 
86c88b1d6cSniklas /* ??? Where should this go?  */
87c88b1d6cSniklas #define MACHTYPE_OK(mtype) \
88c88b1d6cSniklas   (((mtype) == M_SPARC && bfd_lookup_arch (bfd_arch_sparc, 0) != NULL) \
89c88b1d6cSniklas    || ((mtype) == M_SPARCLET \
90c88b1d6cSniklas        && bfd_lookup_arch (bfd_arch_sparc, bfd_mach_sparc_sparclet) != NULL) \
91b305b0f1Sespie    || ((mtype) == M_SPARCLITE_LE \
92b305b0f1Sespie        && bfd_lookup_arch (bfd_arch_sparc, bfd_mach_sparc_sparclet) != NULL) \
93c88b1d6cSniklas    || (((mtype) == M_UNKNOWN || (mtype) == M_68010 || (mtype) == M_68020) \
94c88b1d6cSniklas        && bfd_lookup_arch (bfd_arch_m68k, 0) != NULL))
95c88b1d6cSniklas 
962159047fSniklas /* Include the usual a.out support.  */
972159047fSniklas #include "aoutf1.h"
982159047fSniklas 
99b305b0f1Sespie /* The SunOS 4.1.4 /usr/include/locale.h defines valid as a macro.  */
100b305b0f1Sespie #undef valid
101b305b0f1Sespie 
1022159047fSniklas /* SunOS shared library support.  We store a pointer to this structure
1032159047fSniklas    in obj_aout_dynamic_info (abfd).  */
1042159047fSniklas 
1052159047fSniklas struct sunos_dynamic_info
1062159047fSniklas {
1072159047fSniklas   /* Whether we found any dynamic information.  */
108c074d1c9Sdrahn   bfd_boolean valid;
1092159047fSniklas   /* Dynamic information.  */
1102159047fSniklas   struct internal_sun4_dynamic_link dyninfo;
1112159047fSniklas   /* Number of dynamic symbols.  */
1122159047fSniklas   unsigned long dynsym_count;
1132159047fSniklas   /* Read in nlists for dynamic symbols.  */
1142159047fSniklas   struct external_nlist *dynsym;
1152159047fSniklas   /* asymbol structures for dynamic symbols.  */
1162159047fSniklas   aout_symbol_type *canonical_dynsym;
1172159047fSniklas   /* Read in dynamic string table.  */
1182159047fSniklas   char *dynstr;
1192159047fSniklas   /* Number of dynamic relocs.  */
1202159047fSniklas   unsigned long dynrel_count;
1212159047fSniklas   /* Read in dynamic relocs.  This may be reloc_std_external or
1222159047fSniklas      reloc_ext_external.  */
1232159047fSniklas   PTR dynrel;
1242159047fSniklas   /* arelent structures for dynamic relocs.  */
1252159047fSniklas   arelent *canonical_dynrel;
1262159047fSniklas };
1272159047fSniklas 
1282159047fSniklas /* The hash table of dynamic symbols is composed of two word entries.
1292159047fSniklas    See include/aout/sun4.h for details.  */
1302159047fSniklas 
1312159047fSniklas #define HASH_ENTRY_SIZE (2 * BYTES_IN_WORD)
1322159047fSniklas 
1332159047fSniklas /* Read in the basic dynamic information.  This locates the __DYNAMIC
1342159047fSniklas    structure and uses it to find the dynamic_link structure.  It
1352159047fSniklas    creates and saves a sunos_dynamic_info structure.  If it can't find
1362159047fSniklas    __DYNAMIC, it sets the valid field of the sunos_dynamic_info
137c074d1c9Sdrahn    structure to FALSE to avoid doing this work again.  */
1382159047fSniklas 
139c074d1c9Sdrahn static bfd_boolean
sunos_read_dynamic_info(abfd)1402159047fSniklas sunos_read_dynamic_info (abfd)
1412159047fSniklas      bfd *abfd;
1422159047fSniklas {
1432159047fSniklas   struct sunos_dynamic_info *info;
1442159047fSniklas   asection *dynsec;
1452159047fSniklas   bfd_vma dynoff;
1462159047fSniklas   struct external_sun4_dynamic dyninfo;
1472159047fSniklas   unsigned long dynver;
1482159047fSniklas   struct external_sun4_dynamic_link linkinfo;
149c074d1c9Sdrahn   bfd_size_type amt;
1502159047fSniklas 
1512159047fSniklas   if (obj_aout_dynamic_info (abfd) != (PTR) NULL)
152c074d1c9Sdrahn     return TRUE;
1532159047fSniklas 
1542159047fSniklas   if ((abfd->flags & DYNAMIC) == 0)
1552159047fSniklas     {
1562159047fSniklas       bfd_set_error (bfd_error_invalid_operation);
157c074d1c9Sdrahn       return FALSE;
1582159047fSniklas     }
1592159047fSniklas 
160c074d1c9Sdrahn   amt = sizeof (struct sunos_dynamic_info);
161c074d1c9Sdrahn   info = (struct sunos_dynamic_info *) bfd_zalloc (abfd, amt);
1622159047fSniklas   if (!info)
163c074d1c9Sdrahn     return FALSE;
164c074d1c9Sdrahn   info->valid = FALSE;
1652159047fSniklas   info->dynsym = NULL;
1662159047fSniklas   info->dynstr = NULL;
1672159047fSniklas   info->canonical_dynsym = NULL;
1682159047fSniklas   info->dynrel = NULL;
1692159047fSniklas   info->canonical_dynrel = NULL;
1702159047fSniklas   obj_aout_dynamic_info (abfd) = (PTR) info;
1712159047fSniklas 
1722159047fSniklas   /* This code used to look for the __DYNAMIC symbol to locate the dynamic
1732159047fSniklas      linking information.
1742159047fSniklas      However this inhibits recovering the dynamic symbols from a
1752159047fSniklas      stripped object file, so blindly assume that the dynamic linking
1762159047fSniklas      information is located at the start of the data section.
1772159047fSniklas      We could verify this assumption later by looking through the dynamic
1782159047fSniklas      symbols for the __DYNAMIC symbol.  */
1792159047fSniklas   if ((abfd->flags & DYNAMIC) == 0)
180c074d1c9Sdrahn     return TRUE;
1812159047fSniklas   if (! bfd_get_section_contents (abfd, obj_datasec (abfd), (PTR) &dyninfo,
182c074d1c9Sdrahn 				  (file_ptr) 0,
183c074d1c9Sdrahn 				  (bfd_size_type) sizeof dyninfo))
184c074d1c9Sdrahn     return TRUE;
1852159047fSniklas 
1862159047fSniklas   dynver = GET_WORD (abfd, dyninfo.ld_version);
1872159047fSniklas   if (dynver != 2 && dynver != 3)
188c074d1c9Sdrahn     return TRUE;
1892159047fSniklas 
1902159047fSniklas   dynoff = GET_WORD (abfd, dyninfo.ld);
1912159047fSniklas 
1922159047fSniklas   /* dynoff is a virtual address.  It is probably always in the .data
1932159047fSniklas      section, but this code should work even if it moves.  */
1942159047fSniklas   if (dynoff < bfd_get_section_vma (abfd, obj_datasec (abfd)))
1952159047fSniklas     dynsec = obj_textsec (abfd);
1962159047fSniklas   else
1972159047fSniklas     dynsec = obj_datasec (abfd);
1982159047fSniklas   dynoff -= bfd_get_section_vma (abfd, dynsec);
1992159047fSniklas   if (dynoff > bfd_section_size (abfd, dynsec))
200c074d1c9Sdrahn     return TRUE;
2012159047fSniklas 
2022159047fSniklas   /* This executable appears to be dynamically linked in a way that we
2032159047fSniklas      can understand.  */
204c074d1c9Sdrahn   if (! bfd_get_section_contents (abfd, dynsec, (PTR) &linkinfo,
205c074d1c9Sdrahn 				  (file_ptr) dynoff,
2062159047fSniklas 				  (bfd_size_type) sizeof linkinfo))
207c074d1c9Sdrahn     return TRUE;
2082159047fSniklas 
2092159047fSniklas   /* Swap in the dynamic link information.  */
2102159047fSniklas   info->dyninfo.ld_loaded = GET_WORD (abfd, linkinfo.ld_loaded);
2112159047fSniklas   info->dyninfo.ld_need = GET_WORD (abfd, linkinfo.ld_need);
2122159047fSniklas   info->dyninfo.ld_rules = GET_WORD (abfd, linkinfo.ld_rules);
2132159047fSniklas   info->dyninfo.ld_got = GET_WORD (abfd, linkinfo.ld_got);
2142159047fSniklas   info->dyninfo.ld_plt = GET_WORD (abfd, linkinfo.ld_plt);
2152159047fSniklas   info->dyninfo.ld_rel = GET_WORD (abfd, linkinfo.ld_rel);
2162159047fSniklas   info->dyninfo.ld_hash = GET_WORD (abfd, linkinfo.ld_hash);
2172159047fSniklas   info->dyninfo.ld_stab = GET_WORD (abfd, linkinfo.ld_stab);
2182159047fSniklas   info->dyninfo.ld_stab_hash = GET_WORD (abfd, linkinfo.ld_stab_hash);
2192159047fSniklas   info->dyninfo.ld_buckets = GET_WORD (abfd, linkinfo.ld_buckets);
2202159047fSniklas   info->dyninfo.ld_symbols = GET_WORD (abfd, linkinfo.ld_symbols);
2212159047fSniklas   info->dyninfo.ld_symb_size = GET_WORD (abfd, linkinfo.ld_symb_size);
2222159047fSniklas   info->dyninfo.ld_text = GET_WORD (abfd, linkinfo.ld_text);
2232159047fSniklas   info->dyninfo.ld_plt_sz = GET_WORD (abfd, linkinfo.ld_plt_sz);
2242159047fSniklas 
2252159047fSniklas   /* Reportedly the addresses need to be offset by the size of the
2262159047fSniklas      exec header in an NMAGIC file.  */
2272159047fSniklas   if (adata (abfd).magic == n_magic)
2282159047fSniklas     {
2292159047fSniklas       unsigned long exec_bytes_size = adata (abfd).exec_bytes_size;
2302159047fSniklas 
2312159047fSniklas       info->dyninfo.ld_need += exec_bytes_size;
2322159047fSniklas       info->dyninfo.ld_rules += exec_bytes_size;
2332159047fSniklas       info->dyninfo.ld_rel += exec_bytes_size;
2342159047fSniklas       info->dyninfo.ld_hash += exec_bytes_size;
2352159047fSniklas       info->dyninfo.ld_stab += exec_bytes_size;
2362159047fSniklas       info->dyninfo.ld_symbols += exec_bytes_size;
2372159047fSniklas     }
2382159047fSniklas 
2392159047fSniklas   /* The only way to get the size of the symbol information appears to
2402159047fSniklas      be to determine the distance between it and the string table.  */
2412159047fSniklas   info->dynsym_count = ((info->dyninfo.ld_symbols - info->dyninfo.ld_stab)
2422159047fSniklas 			/ EXTERNAL_NLIST_SIZE);
2432159047fSniklas   BFD_ASSERT (info->dynsym_count * EXTERNAL_NLIST_SIZE
2442159047fSniklas 	      == (unsigned long) (info->dyninfo.ld_symbols
2452159047fSniklas 				  - info->dyninfo.ld_stab));
2462159047fSniklas 
2472159047fSniklas   /* Similarly, the relocs end at the hash table.  */
2482159047fSniklas   info->dynrel_count = ((info->dyninfo.ld_hash - info->dyninfo.ld_rel)
2492159047fSniklas 			/ obj_reloc_entry_size (abfd));
2502159047fSniklas   BFD_ASSERT (info->dynrel_count * obj_reloc_entry_size (abfd)
2512159047fSniklas 	      == (unsigned long) (info->dyninfo.ld_hash
2522159047fSniklas 				  - info->dyninfo.ld_rel));
2532159047fSniklas 
254c074d1c9Sdrahn   info->valid = TRUE;
2552159047fSniklas 
256c074d1c9Sdrahn   return TRUE;
2572159047fSniklas }
2582159047fSniklas 
2592159047fSniklas /* Return the amount of memory required for the dynamic symbols.  */
2602159047fSniklas 
2612159047fSniklas static long
sunos_get_dynamic_symtab_upper_bound(abfd)2622159047fSniklas sunos_get_dynamic_symtab_upper_bound (abfd)
2632159047fSniklas      bfd *abfd;
2642159047fSniklas {
2652159047fSniklas   struct sunos_dynamic_info *info;
2662159047fSniklas 
2672159047fSniklas   if (! sunos_read_dynamic_info (abfd))
2682159047fSniklas     return -1;
2692159047fSniklas 
2702159047fSniklas   info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
2712159047fSniklas   if (! info->valid)
2722159047fSniklas     {
2732159047fSniklas       bfd_set_error (bfd_error_no_symbols);
2742159047fSniklas       return -1;
2752159047fSniklas     }
2762159047fSniklas 
2772159047fSniklas   return (info->dynsym_count + 1) * sizeof (asymbol *);
2782159047fSniklas }
2792159047fSniklas 
2802159047fSniklas /* Read the external dynamic symbols.  */
2812159047fSniklas 
282c074d1c9Sdrahn static bfd_boolean
sunos_slurp_dynamic_symtab(abfd)2832159047fSniklas sunos_slurp_dynamic_symtab (abfd)
2842159047fSniklas      bfd *abfd;
2852159047fSniklas {
2862159047fSniklas   struct sunos_dynamic_info *info;
287c074d1c9Sdrahn   bfd_size_type amt;
2882159047fSniklas 
2892159047fSniklas   /* Get the general dynamic information.  */
2902159047fSniklas   if (obj_aout_dynamic_info (abfd) == NULL)
2912159047fSniklas     {
2922159047fSniklas       if (! sunos_read_dynamic_info (abfd))
293c074d1c9Sdrahn 	  return FALSE;
2942159047fSniklas     }
2952159047fSniklas 
2962159047fSniklas   info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
2972159047fSniklas   if (! info->valid)
2982159047fSniklas     {
2992159047fSniklas       bfd_set_error (bfd_error_no_symbols);
300c074d1c9Sdrahn       return FALSE;
3012159047fSniklas     }
3022159047fSniklas 
3032159047fSniklas   /* Get the dynamic nlist structures.  */
3042159047fSniklas   if (info->dynsym == (struct external_nlist *) NULL)
3052159047fSniklas     {
306c074d1c9Sdrahn       amt = (bfd_size_type) info->dynsym_count * EXTERNAL_NLIST_SIZE;
307c074d1c9Sdrahn       info->dynsym = (struct external_nlist *) bfd_alloc (abfd, amt);
3082159047fSniklas       if (info->dynsym == NULL && info->dynsym_count != 0)
309c074d1c9Sdrahn 	return FALSE;
310c074d1c9Sdrahn       if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_stab, SEEK_SET) != 0
311c074d1c9Sdrahn 	  || bfd_bread ((PTR) info->dynsym, amt, abfd) != amt)
3122159047fSniklas 	{
3132159047fSniklas 	  if (info->dynsym != NULL)
3142159047fSniklas 	    {
3152159047fSniklas 	      bfd_release (abfd, info->dynsym);
3162159047fSniklas 	      info->dynsym = NULL;
3172159047fSniklas 	    }
318c074d1c9Sdrahn 	  return FALSE;
3192159047fSniklas 	}
3202159047fSniklas     }
3212159047fSniklas 
3222159047fSniklas   /* Get the dynamic strings.  */
3232159047fSniklas   if (info->dynstr == (char *) NULL)
3242159047fSniklas     {
325c074d1c9Sdrahn       amt = info->dyninfo.ld_symb_size;
326c074d1c9Sdrahn       info->dynstr = (char *) bfd_alloc (abfd, amt);
3272159047fSniklas       if (info->dynstr == NULL && info->dyninfo.ld_symb_size != 0)
328c074d1c9Sdrahn 	return FALSE;
329c074d1c9Sdrahn       if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_symbols, SEEK_SET) != 0
330c074d1c9Sdrahn 	  || bfd_bread ((PTR) info->dynstr, amt, abfd) != amt)
3312159047fSniklas 	{
3322159047fSniklas 	  if (info->dynstr != NULL)
3332159047fSniklas 	    {
3342159047fSniklas 	      bfd_release (abfd, info->dynstr);
3352159047fSniklas 	      info->dynstr = NULL;
3362159047fSniklas 	    }
337c074d1c9Sdrahn 	  return FALSE;
3382159047fSniklas 	}
3392159047fSniklas     }
3402159047fSniklas 
341c074d1c9Sdrahn   return TRUE;
3422159047fSniklas }
3432159047fSniklas 
3442159047fSniklas /* Read in the dynamic symbols.  */
3452159047fSniklas 
3462159047fSniklas static long
sunos_canonicalize_dynamic_symtab(abfd,storage)3472159047fSniklas sunos_canonicalize_dynamic_symtab (abfd, storage)
3482159047fSniklas      bfd *abfd;
3492159047fSniklas      asymbol **storage;
3502159047fSniklas {
3512159047fSniklas   struct sunos_dynamic_info *info;
3522159047fSniklas   unsigned long i;
3532159047fSniklas 
3542159047fSniklas   if (! sunos_slurp_dynamic_symtab (abfd))
3552159047fSniklas     return -1;
3562159047fSniklas 
3572159047fSniklas   info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
3582159047fSniklas 
3592159047fSniklas #ifdef CHECK_DYNAMIC_HASH
3602159047fSniklas   /* Check my understanding of the dynamic hash table by making sure
3612159047fSniklas      that each symbol can be located in the hash table.  */
3622159047fSniklas   {
3632159047fSniklas     bfd_size_type table_size;
3642159047fSniklas     bfd_byte *table;
3652159047fSniklas     bfd_size_type i;
3662159047fSniklas 
3672159047fSniklas     if (info->dyninfo.ld_buckets > info->dynsym_count)
3682159047fSniklas       abort ();
3692159047fSniklas     table_size = info->dyninfo.ld_stab - info->dyninfo.ld_hash;
370c88b1d6cSniklas     table = (bfd_byte *) bfd_malloc (table_size);
3712159047fSniklas     if (table == NULL && table_size != 0)
3722159047fSniklas       abort ();
373c074d1c9Sdrahn     if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_hash, SEEK_SET) != 0
374c074d1c9Sdrahn 	|| bfd_bread ((PTR) table, table_size, abfd) != table_size)
3752159047fSniklas       abort ();
3762159047fSniklas     for (i = 0; i < info->dynsym_count; i++)
3772159047fSniklas       {
3782159047fSniklas 	unsigned char *name;
3792159047fSniklas 	unsigned long hash;
3802159047fSniklas 
3812159047fSniklas 	name = ((unsigned char *) info->dynstr
3822159047fSniklas 		+ GET_WORD (abfd, info->dynsym[i].e_strx));
3832159047fSniklas 	hash = 0;
3842159047fSniklas 	while (*name != '\0')
3852159047fSniklas 	  hash = (hash << 1) + *name++;
3862159047fSniklas 	hash &= 0x7fffffff;
3872159047fSniklas 	hash %= info->dyninfo.ld_buckets;
3882159047fSniklas 	while (GET_WORD (abfd, table + hash * HASH_ENTRY_SIZE) != i)
3892159047fSniklas 	  {
3902159047fSniklas 	    hash = GET_WORD (abfd,
3912159047fSniklas 			     table + hash * HASH_ENTRY_SIZE + BYTES_IN_WORD);
3922159047fSniklas 	    if (hash == 0 || hash >= table_size / HASH_ENTRY_SIZE)
3932159047fSniklas 	      abort ();
3942159047fSniklas 	  }
3952159047fSniklas       }
3962159047fSniklas     free (table);
3972159047fSniklas   }
3982159047fSniklas #endif /* CHECK_DYNAMIC_HASH */
3992159047fSniklas 
4002159047fSniklas   /* Get the asymbol structures corresponding to the dynamic nlist
4012159047fSniklas      structures.  */
4022159047fSniklas   if (info->canonical_dynsym == (aout_symbol_type *) NULL)
4032159047fSniklas     {
404c074d1c9Sdrahn       bfd_size_type size;
405c074d1c9Sdrahn       bfd_size_type strsize = info->dyninfo.ld_symb_size;
406c074d1c9Sdrahn 
407c074d1c9Sdrahn       size = (bfd_size_type) info->dynsym_count * sizeof (aout_symbol_type);
408c074d1c9Sdrahn       info->canonical_dynsym = (aout_symbol_type *) bfd_alloc (abfd, size);
4092159047fSniklas       if (info->canonical_dynsym == NULL && info->dynsym_count != 0)
4102159047fSniklas 	return -1;
4112159047fSniklas 
4122159047fSniklas       if (! aout_32_translate_symbol_table (abfd, info->canonical_dynsym,
413c074d1c9Sdrahn 					    info->dynsym,
414c074d1c9Sdrahn 					    (bfd_size_type) info->dynsym_count,
415c074d1c9Sdrahn 					    info->dynstr, strsize, TRUE))
4162159047fSniklas 	{
4172159047fSniklas 	  if (info->canonical_dynsym != NULL)
4182159047fSniklas 	    {
4192159047fSniklas 	      bfd_release (abfd, info->canonical_dynsym);
4202159047fSniklas 	      info->canonical_dynsym = NULL;
4212159047fSniklas 	    }
4222159047fSniklas 	  return -1;
4232159047fSniklas 	}
4242159047fSniklas     }
4252159047fSniklas 
4262159047fSniklas   /* Return pointers to the dynamic asymbol structures.  */
4272159047fSniklas   for (i = 0; i < info->dynsym_count; i++)
4282159047fSniklas     *storage++ = (asymbol *) (info->canonical_dynsym + i);
4292159047fSniklas   *storage = NULL;
4302159047fSniklas 
4312159047fSniklas   return info->dynsym_count;
4322159047fSniklas }
4332159047fSniklas 
4342159047fSniklas /* Return the amount of memory required for the dynamic relocs.  */
4352159047fSniklas 
4362159047fSniklas static long
sunos_get_dynamic_reloc_upper_bound(abfd)4372159047fSniklas sunos_get_dynamic_reloc_upper_bound (abfd)
4382159047fSniklas      bfd *abfd;
4392159047fSniklas {
4402159047fSniklas   struct sunos_dynamic_info *info;
4412159047fSniklas 
4422159047fSniklas   if (! sunos_read_dynamic_info (abfd))
4432159047fSniklas     return -1;
4442159047fSniklas 
4452159047fSniklas   info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
4462159047fSniklas   if (! info->valid)
4472159047fSniklas     {
4482159047fSniklas       bfd_set_error (bfd_error_no_symbols);
4492159047fSniklas       return -1;
4502159047fSniklas     }
4512159047fSniklas 
4522159047fSniklas   return (info->dynrel_count + 1) * sizeof (arelent *);
4532159047fSniklas }
4542159047fSniklas 
4552159047fSniklas /* Read in the dynamic relocs.  */
4562159047fSniklas 
4572159047fSniklas static long
sunos_canonicalize_dynamic_reloc(abfd,storage,syms)4582159047fSniklas sunos_canonicalize_dynamic_reloc (abfd, storage, syms)
4592159047fSniklas      bfd *abfd;
4602159047fSniklas      arelent **storage;
4612159047fSniklas      asymbol **syms;
4622159047fSniklas {
4632159047fSniklas   struct sunos_dynamic_info *info;
4642159047fSniklas   unsigned long i;
465c074d1c9Sdrahn   bfd_size_type size;
4662159047fSniklas 
4672159047fSniklas   /* Get the general dynamic information.  */
4682159047fSniklas   if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
4692159047fSniklas     {
4702159047fSniklas       if (! sunos_read_dynamic_info (abfd))
4712159047fSniklas 	return -1;
4722159047fSniklas     }
4732159047fSniklas 
4742159047fSniklas   info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
4752159047fSniklas   if (! info->valid)
4762159047fSniklas     {
4772159047fSniklas       bfd_set_error (bfd_error_no_symbols);
4782159047fSniklas       return -1;
4792159047fSniklas     }
4802159047fSniklas 
4812159047fSniklas   /* Get the dynamic reloc information.  */
4822159047fSniklas   if (info->dynrel == NULL)
4832159047fSniklas     {
484c074d1c9Sdrahn       size = (bfd_size_type) info->dynrel_count * obj_reloc_entry_size (abfd);
485c074d1c9Sdrahn       info->dynrel = (PTR) bfd_alloc (abfd, size);
486c074d1c9Sdrahn       if (info->dynrel == NULL && size != 0)
4872159047fSniklas 	return -1;
488c074d1c9Sdrahn       if (bfd_seek (abfd, (file_ptr) info->dyninfo.ld_rel, SEEK_SET) != 0
489c074d1c9Sdrahn 	  || bfd_bread ((PTR) info->dynrel, size, abfd) != size)
4902159047fSniklas 	{
4912159047fSniklas 	  if (info->dynrel != NULL)
4922159047fSniklas 	    {
4932159047fSniklas 	      bfd_release (abfd, info->dynrel);
4942159047fSniklas 	      info->dynrel = NULL;
4952159047fSniklas 	    }
4962159047fSniklas 	  return -1;
4972159047fSniklas 	}
4982159047fSniklas     }
4992159047fSniklas 
5002159047fSniklas   /* Get the arelent structures corresponding to the dynamic reloc
5012159047fSniklas      information.  */
5022159047fSniklas   if (info->canonical_dynrel == (arelent *) NULL)
5032159047fSniklas     {
5042159047fSniklas       arelent *to;
5052159047fSniklas 
506c074d1c9Sdrahn       size = (bfd_size_type) info->dynrel_count * sizeof (arelent);
507c074d1c9Sdrahn       info->canonical_dynrel = (arelent *) bfd_alloc (abfd, size);
5082159047fSniklas       if (info->canonical_dynrel == NULL && info->dynrel_count != 0)
5092159047fSniklas 	return -1;
5102159047fSniklas 
5112159047fSniklas       to = info->canonical_dynrel;
5122159047fSniklas 
5132159047fSniklas       if (obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE)
5142159047fSniklas 	{
5152159047fSniklas 	  register struct reloc_ext_external *p;
5162159047fSniklas 	  struct reloc_ext_external *pend;
5172159047fSniklas 
5182159047fSniklas 	  p = (struct reloc_ext_external *) info->dynrel;
5192159047fSniklas 	  pend = p + info->dynrel_count;
5202159047fSniklas 	  for (; p < pend; p++, to++)
5212159047fSniklas 	    NAME(aout,swap_ext_reloc_in) (abfd, p, to, syms,
522c074d1c9Sdrahn 					  (bfd_size_type) info->dynsym_count);
5232159047fSniklas 	}
5242159047fSniklas       else
5252159047fSniklas 	{
5262159047fSniklas 	  register struct reloc_std_external *p;
5272159047fSniklas 	  struct reloc_std_external *pend;
5282159047fSniklas 
5292159047fSniklas 	  p = (struct reloc_std_external *) info->dynrel;
5302159047fSniklas 	  pend = p + info->dynrel_count;
5312159047fSniklas 	  for (; p < pend; p++, to++)
5322159047fSniklas 	    NAME(aout,swap_std_reloc_in) (abfd, p, to, syms,
533c074d1c9Sdrahn 					  (bfd_size_type) info->dynsym_count);
5342159047fSniklas 	}
5352159047fSniklas     }
5362159047fSniklas 
5372159047fSniklas   /* Return pointers to the dynamic arelent structures.  */
5382159047fSniklas   for (i = 0; i < info->dynrel_count; i++)
5392159047fSniklas     *storage++ = info->canonical_dynrel + i;
5402159047fSniklas   *storage = NULL;
5412159047fSniklas 
5422159047fSniklas   return info->dynrel_count;
5432159047fSniklas }
5442159047fSniklas 
5452159047fSniklas /* Code to handle linking of SunOS shared libraries.  */
5462159047fSniklas 
5472159047fSniklas /* A SPARC procedure linkage table entry is 12 bytes.  The first entry
5482159047fSniklas    in the table is a jump which is filled in by the runtime linker.
5492159047fSniklas    The remaining entries are branches back to the first entry,
5502159047fSniklas    followed by an index into the relocation table encoded to look like
5512159047fSniklas    a sethi of %g0.  */
5522159047fSniklas 
5532159047fSniklas #define SPARC_PLT_ENTRY_SIZE (12)
5542159047fSniklas 
5552159047fSniklas static const bfd_byte sparc_plt_first_entry[SPARC_PLT_ENTRY_SIZE] =
5562159047fSniklas {
5572159047fSniklas   /* sethi %hi(0),%g1; address filled in by runtime linker.  */
5582159047fSniklas   0x3, 0, 0, 0,
5592159047fSniklas   /* jmp %g1; offset filled in by runtime linker.  */
5602159047fSniklas   0x81, 0xc0, 0x60, 0,
5612159047fSniklas   /* nop */
5622159047fSniklas   0x1, 0, 0, 0
5632159047fSniklas };
5642159047fSniklas 
5652159047fSniklas /* save %sp, -96, %sp */
566c074d1c9Sdrahn #define SPARC_PLT_ENTRY_WORD0 ((bfd_vma) 0x9de3bfa0)
5672159047fSniklas /* call; address filled in later.  */
568c074d1c9Sdrahn #define SPARC_PLT_ENTRY_WORD1 ((bfd_vma) 0x40000000)
5692159047fSniklas /* sethi; reloc index filled in later.  */
570c074d1c9Sdrahn #define SPARC_PLT_ENTRY_WORD2 ((bfd_vma) 0x01000000)
5712159047fSniklas 
5722159047fSniklas /* This sequence is used when for the jump table entry to a defined
5732159047fSniklas    symbol in a complete executable.  It is used when linking PIC
5742159047fSniklas    compiled code which is not being put into a shared library.  */
5752159047fSniklas /* sethi <address to be filled in later>, %g1 */
576c074d1c9Sdrahn #define SPARC_PLT_PIC_WORD0 ((bfd_vma) 0x03000000)
5772159047fSniklas /* jmp %g1 + <address to be filled in later> */
578c074d1c9Sdrahn #define SPARC_PLT_PIC_WORD1 ((bfd_vma) 0x81c06000)
5792159047fSniklas /* nop */
580c074d1c9Sdrahn #define SPARC_PLT_PIC_WORD2 ((bfd_vma) 0x01000000)
5812159047fSniklas 
5822159047fSniklas /* An m68k procedure linkage table entry is 8 bytes.  The first entry
5832159047fSniklas    in the table is a jump which is filled in the by the runtime
5842159047fSniklas    linker.  The remaining entries are branches back to the first
5852159047fSniklas    entry, followed by a two byte index into the relocation table.  */
5862159047fSniklas 
5872159047fSniklas #define M68K_PLT_ENTRY_SIZE (8)
5882159047fSniklas 
5892159047fSniklas static const bfd_byte m68k_plt_first_entry[M68K_PLT_ENTRY_SIZE] =
5902159047fSniklas {
5912159047fSniklas   /* jmps @# */
5922159047fSniklas   0x4e, 0xf9,
5932159047fSniklas   /* Filled in by runtime linker with a magic address.  */
5942159047fSniklas   0, 0, 0, 0,
5952159047fSniklas   /* Not used?  */
5962159047fSniklas   0, 0
5972159047fSniklas };
5982159047fSniklas 
5992159047fSniklas /* bsrl */
600c074d1c9Sdrahn #define M68K_PLT_ENTRY_WORD0 ((bfd_vma) 0x61ff)
6012159047fSniklas /* Remaining words filled in later.  */
6022159047fSniklas 
6032159047fSniklas /* An entry in the SunOS linker hash table.  */
6042159047fSniklas 
6052159047fSniklas struct sunos_link_hash_entry
6062159047fSniklas {
6072159047fSniklas   struct aout_link_hash_entry root;
6082159047fSniklas 
6092159047fSniklas   /* If this is a dynamic symbol, this is its index into the dynamic
6102159047fSniklas      symbol table.  This is initialized to -1.  As the linker looks at
6112159047fSniklas      the input files, it changes this to -2 if it will be added to the
6122159047fSniklas      dynamic symbol table.  After all the input files have been seen,
6132159047fSniklas      the linker will know whether to build a dynamic symbol table; if
6142159047fSniklas      it does build one, this becomes the index into the table.  */
6152159047fSniklas   long dynindx;
6162159047fSniklas 
6172159047fSniklas   /* If this is a dynamic symbol, this is the index of the name in the
6182159047fSniklas      dynamic symbol string table.  */
6192159047fSniklas   long dynstr_index;
6202159047fSniklas 
6212159047fSniklas   /* The offset into the global offset table used for this symbol.  If
6222159047fSniklas      the symbol does not require a GOT entry, this is 0.  */
6232159047fSniklas   bfd_vma got_offset;
6242159047fSniklas 
6252159047fSniklas   /* The offset into the procedure linkage table used for this symbol.
6262159047fSniklas      If the symbol does not require a PLT entry, this is 0.  */
6272159047fSniklas   bfd_vma plt_offset;
6282159047fSniklas 
6292159047fSniklas   /* Some linker flags.  */
6302159047fSniklas   unsigned char flags;
6312159047fSniklas   /* Symbol is referenced by a regular object.  */
6322159047fSniklas #define SUNOS_REF_REGULAR 01
6332159047fSniklas   /* Symbol is defined by a regular object.  */
6342159047fSniklas #define SUNOS_DEF_REGULAR 02
6352159047fSniklas   /* Symbol is referenced by a dynamic object.  */
636c88b1d6cSniklas #define SUNOS_REF_DYNAMIC 04
6372159047fSniklas   /* Symbol is defined by a dynamic object.  */
638c88b1d6cSniklas #define SUNOS_DEF_DYNAMIC 010
639c88b1d6cSniklas   /* Symbol is a constructor symbol in a regular object.  */
640c88b1d6cSniklas #define SUNOS_CONSTRUCTOR 020
6412159047fSniklas };
6422159047fSniklas 
6432159047fSniklas /* The SunOS linker hash table.  */
6442159047fSniklas 
6452159047fSniklas struct sunos_link_hash_table
6462159047fSniklas {
6472159047fSniklas   struct aout_link_hash_table root;
6482159047fSniklas 
6492159047fSniklas   /* The object which holds the dynamic sections.  */
6502159047fSniklas   bfd *dynobj;
6512159047fSniklas 
6522159047fSniklas   /* Whether we have created the dynamic sections.  */
653c074d1c9Sdrahn   bfd_boolean dynamic_sections_created;
6542159047fSniklas 
6552159047fSniklas   /* Whether we need the dynamic sections.  */
656c074d1c9Sdrahn   bfd_boolean dynamic_sections_needed;
6572159047fSniklas 
658b305b0f1Sespie   /* Whether we need the .got table.  */
659c074d1c9Sdrahn   bfd_boolean got_needed;
660b305b0f1Sespie 
6612159047fSniklas   /* The number of dynamic symbols.  */
6622159047fSniklas   size_t dynsymcount;
6632159047fSniklas 
6642159047fSniklas   /* The number of buckets in the hash table.  */
6652159047fSniklas   size_t bucketcount;
6662159047fSniklas 
6672159047fSniklas   /* The list of dynamic objects needed by dynamic objects included in
6682159047fSniklas      the link.  */
6692159047fSniklas   struct bfd_link_needed_list *needed;
670e93f7393Sniklas 
671e93f7393Sniklas   /* The offset of __GLOBAL_OFFSET_TABLE_ into the .got section.  */
672e93f7393Sniklas   bfd_vma got_base;
6732159047fSniklas };
6742159047fSniklas 
6752159047fSniklas /* Routine to create an entry in an SunOS link hash table.  */
6762159047fSniklas 
6772159047fSniklas static struct bfd_hash_entry *
sunos_link_hash_newfunc(entry,table,string)6782159047fSniklas sunos_link_hash_newfunc (entry, table, string)
6792159047fSniklas      struct bfd_hash_entry *entry;
6802159047fSniklas      struct bfd_hash_table *table;
6812159047fSniklas      const char *string;
6822159047fSniklas {
6832159047fSniklas   struct sunos_link_hash_entry *ret = (struct sunos_link_hash_entry *) entry;
6842159047fSniklas 
6852159047fSniklas   /* Allocate the structure if it has not already been allocated by a
6862159047fSniklas      subclass.  */
6872159047fSniklas   if (ret == (struct sunos_link_hash_entry *) NULL)
6882159047fSniklas     ret = ((struct sunos_link_hash_entry *)
6892159047fSniklas 	   bfd_hash_allocate (table, sizeof (struct sunos_link_hash_entry)));
6902159047fSniklas   if (ret == (struct sunos_link_hash_entry *) NULL)
6912159047fSniklas     return (struct bfd_hash_entry *) ret;
6922159047fSniklas 
6932159047fSniklas   /* Call the allocation method of the superclass.  */
6942159047fSniklas   ret = ((struct sunos_link_hash_entry *)
6952159047fSniklas 	 NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret,
6962159047fSniklas 				       table, string));
6972159047fSniklas   if (ret != NULL)
6982159047fSniklas     {
6992159047fSniklas       /* Set local fields.  */
7002159047fSniklas       ret->dynindx = -1;
7012159047fSniklas       ret->dynstr_index = -1;
7022159047fSniklas       ret->got_offset = 0;
7032159047fSniklas       ret->plt_offset = 0;
7042159047fSniklas       ret->flags = 0;
7052159047fSniklas     }
7062159047fSniklas 
7072159047fSniklas   return (struct bfd_hash_entry *) ret;
7082159047fSniklas }
7092159047fSniklas 
7102159047fSniklas /* Create a SunOS link hash table.  */
7112159047fSniklas 
7122159047fSniklas static struct bfd_link_hash_table *
sunos_link_hash_table_create(abfd)7132159047fSniklas sunos_link_hash_table_create (abfd)
7142159047fSniklas      bfd *abfd;
7152159047fSniklas {
7162159047fSniklas   struct sunos_link_hash_table *ret;
717c074d1c9Sdrahn   bfd_size_type amt = sizeof (struct sunos_link_hash_table);
7182159047fSniklas 
719c074d1c9Sdrahn   ret = (struct sunos_link_hash_table *) bfd_malloc (amt);
7202159047fSniklas   if (ret == (struct sunos_link_hash_table *) NULL)
7212159047fSniklas     return (struct bfd_link_hash_table *) NULL;
7222159047fSniklas   if (! NAME(aout,link_hash_table_init) (&ret->root, abfd,
7232159047fSniklas 					 sunos_link_hash_newfunc))
7242159047fSniklas     {
725c074d1c9Sdrahn       free (ret);
7262159047fSniklas       return (struct bfd_link_hash_table *) NULL;
7272159047fSniklas     }
7282159047fSniklas 
7292159047fSniklas   ret->dynobj = NULL;
730c074d1c9Sdrahn   ret->dynamic_sections_created = FALSE;
731c074d1c9Sdrahn   ret->dynamic_sections_needed = FALSE;
732c074d1c9Sdrahn   ret->got_needed = FALSE;
7332159047fSniklas   ret->dynsymcount = 0;
7342159047fSniklas   ret->bucketcount = 0;
7352159047fSniklas   ret->needed = NULL;
736e93f7393Sniklas   ret->got_base = 0;
7372159047fSniklas 
7382159047fSniklas   return &ret->root.root;
7392159047fSniklas }
7402159047fSniklas 
7412159047fSniklas /* Look up an entry in an SunOS link hash table.  */
7422159047fSniklas 
7432159047fSniklas #define sunos_link_hash_lookup(table, string, create, copy, follow) \
7442159047fSniklas   ((struct sunos_link_hash_entry *) \
7452159047fSniklas    aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\
7462159047fSniklas 			  (follow)))
7472159047fSniklas 
7482159047fSniklas /* Traverse a SunOS link hash table.  */
7492159047fSniklas 
7502159047fSniklas #define sunos_link_hash_traverse(table, func, info)			\
7512159047fSniklas   (aout_link_hash_traverse						\
7522159047fSniklas    (&(table)->root,							\
753c074d1c9Sdrahn     (bfd_boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \
7542159047fSniklas     (info)))
7552159047fSniklas 
7562159047fSniklas /* Get the SunOS link hash table from the info structure.  This is
7572159047fSniklas    just a cast.  */
7582159047fSniklas 
7592159047fSniklas #define sunos_hash_table(p) ((struct sunos_link_hash_table *) ((p)->hash))
7602159047fSniklas 
761c074d1c9Sdrahn static bfd_boolean sunos_scan_dynamic_symbol
7622159047fSniklas   PARAMS ((struct sunos_link_hash_entry *, PTR));
7632159047fSniklas 
7642159047fSniklas /* Create the dynamic sections needed if we are linking against a
7652159047fSniklas    dynamic object, or if we are linking PIC compiled code.  ABFD is a
7662159047fSniklas    bfd we can attach the dynamic sections to.  The linker script will
7672159047fSniklas    look for these special sections names and put them in the right
7682159047fSniklas    place in the output file.  See include/aout/sun4.h for more details
7692159047fSniklas    of the dynamic linking information.  */
7702159047fSniklas 
771c074d1c9Sdrahn static bfd_boolean
sunos_create_dynamic_sections(abfd,info,needed)7722159047fSniklas sunos_create_dynamic_sections (abfd, info, needed)
7732159047fSniklas      bfd *abfd;
7742159047fSniklas      struct bfd_link_info *info;
775c074d1c9Sdrahn      bfd_boolean needed;
7762159047fSniklas {
7772159047fSniklas   asection *s;
7782159047fSniklas 
7792159047fSniklas   if (! sunos_hash_table (info)->dynamic_sections_created)
7802159047fSniklas     {
7812159047fSniklas       flagword flags;
7822159047fSniklas 
7832159047fSniklas       sunos_hash_table (info)->dynobj = abfd;
7842159047fSniklas 
785b305b0f1Sespie       flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
786b305b0f1Sespie 	       | SEC_LINKER_CREATED);
7872159047fSniklas 
7882159047fSniklas       /* The .dynamic section holds the basic dynamic information: the
7892159047fSniklas 	 sun4_dynamic structure, the dynamic debugger information, and
7902159047fSniklas 	 the sun4_dynamic_link structure.  */
7912159047fSniklas       s = bfd_make_section (abfd, ".dynamic");
7922159047fSniklas       if (s == NULL
7932159047fSniklas 	  || ! bfd_set_section_flags (abfd, s, flags)
7942159047fSniklas 	  || ! bfd_set_section_alignment (abfd, s, 2))
795c074d1c9Sdrahn 	return FALSE;
7962159047fSniklas 
7972159047fSniklas       /* The .got section holds the global offset table.  The address
7982159047fSniklas 	 is put in the ld_got field.  */
7992159047fSniklas       s = bfd_make_section (abfd, ".got");
8002159047fSniklas       if (s == NULL
8012159047fSniklas 	  || ! bfd_set_section_flags (abfd, s, flags)
8022159047fSniklas 	  || ! bfd_set_section_alignment (abfd, s, 2))
803c074d1c9Sdrahn 	return FALSE;
8042159047fSniklas 
8052159047fSniklas       /* The .plt section holds the procedure linkage table.  The
8062159047fSniklas 	 address is put in the ld_plt field.  */
8072159047fSniklas       s = bfd_make_section (abfd, ".plt");
8082159047fSniklas       if (s == NULL
8092159047fSniklas 	  || ! bfd_set_section_flags (abfd, s, flags | SEC_CODE)
8102159047fSniklas 	  || ! bfd_set_section_alignment (abfd, s, 2))
811c074d1c9Sdrahn 	return FALSE;
8122159047fSniklas 
8132159047fSniklas       /* The .dynrel section holds the dynamic relocs.  The address is
8142159047fSniklas 	 put in the ld_rel field.  */
8152159047fSniklas       s = bfd_make_section (abfd, ".dynrel");
8162159047fSniklas       if (s == NULL
8172159047fSniklas 	  || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
8182159047fSniklas 	  || ! bfd_set_section_alignment (abfd, s, 2))
819c074d1c9Sdrahn 	return FALSE;
8202159047fSniklas 
8212159047fSniklas       /* The .hash section holds the dynamic hash table.  The address
8222159047fSniklas 	 is put in the ld_hash field.  */
8232159047fSniklas       s = bfd_make_section (abfd, ".hash");
8242159047fSniklas       if (s == NULL
8252159047fSniklas 	  || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
8262159047fSniklas 	  || ! bfd_set_section_alignment (abfd, s, 2))
827c074d1c9Sdrahn 	return FALSE;
8282159047fSniklas 
8292159047fSniklas       /* The .dynsym section holds the dynamic symbols.  The address
8302159047fSniklas 	 is put in the ld_stab field.  */
8312159047fSniklas       s = bfd_make_section (abfd, ".dynsym");
8322159047fSniklas       if (s == NULL
8332159047fSniklas 	  || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
8342159047fSniklas 	  || ! bfd_set_section_alignment (abfd, s, 2))
835c074d1c9Sdrahn 	return FALSE;
8362159047fSniklas 
8372159047fSniklas       /* The .dynstr section holds the dynamic symbol string table.
8382159047fSniklas 	 The address is put in the ld_symbols field.  */
8392159047fSniklas       s = bfd_make_section (abfd, ".dynstr");
8402159047fSniklas       if (s == NULL
8412159047fSniklas 	  || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
8422159047fSniklas 	  || ! bfd_set_section_alignment (abfd, s, 2))
843c074d1c9Sdrahn 	return FALSE;
8442159047fSniklas 
845c074d1c9Sdrahn       sunos_hash_table (info)->dynamic_sections_created = TRUE;
8462159047fSniklas     }
8472159047fSniklas 
848b305b0f1Sespie   if ((needed && ! sunos_hash_table (info)->dynamic_sections_needed)
849b305b0f1Sespie       || info->shared)
8502159047fSniklas     {
8512159047fSniklas       bfd *dynobj;
8522159047fSniklas 
8532159047fSniklas       dynobj = sunos_hash_table (info)->dynobj;
8542159047fSniklas 
8552159047fSniklas       s = bfd_get_section_by_name (dynobj, ".got");
856b305b0f1Sespie       if (s->_raw_size == 0)
8572159047fSniklas 	s->_raw_size = BYTES_IN_WORD;
8582159047fSniklas 
859c074d1c9Sdrahn       sunos_hash_table (info)->dynamic_sections_needed = TRUE;
860c074d1c9Sdrahn       sunos_hash_table (info)->got_needed = TRUE;
8612159047fSniklas     }
8622159047fSniklas 
863c074d1c9Sdrahn   return TRUE;
8642159047fSniklas }
8652159047fSniklas 
8662159047fSniklas /* Add dynamic symbols during a link.  This is called by the a.out
867c88b1d6cSniklas    backend linker for each object it encounters.  */
8682159047fSniklas 
869c074d1c9Sdrahn static bfd_boolean
sunos_add_dynamic_symbols(abfd,info,symsp,sym_countp,stringsp)8702159047fSniklas sunos_add_dynamic_symbols (abfd, info, symsp, sym_countp, stringsp)
8712159047fSniklas      bfd *abfd;
8722159047fSniklas      struct bfd_link_info *info;
8732159047fSniklas      struct external_nlist **symsp;
8742159047fSniklas      bfd_size_type *sym_countp;
8752159047fSniklas      char **stringsp;
8762159047fSniklas {
8772159047fSniklas   bfd *dynobj;
8782159047fSniklas   struct sunos_dynamic_info *dinfo;
8792159047fSniklas   unsigned long need;
880c074d1c9Sdrahn   asection **ps;
8812159047fSniklas 
882c88b1d6cSniklas   /* Make sure we have all the required sections.  */
8830c6d0228Sniklas   if (info->hash->creator == abfd->xvec)
8840c6d0228Sniklas     {
885c88b1d6cSniklas       if (! sunos_create_dynamic_sections (abfd, info,
886c074d1c9Sdrahn 					   ((abfd->flags & DYNAMIC) != 0
887*007c2a45Smiod 					    && !info->relocatable)))
888c074d1c9Sdrahn 	return FALSE;
8890c6d0228Sniklas     }
890c88b1d6cSniklas 
891c88b1d6cSniklas   /* There is nothing else to do for a normal object.  */
892c88b1d6cSniklas   if ((abfd->flags & DYNAMIC) == 0)
893c074d1c9Sdrahn     return TRUE;
894c88b1d6cSniklas 
895b305b0f1Sespie   dynobj = sunos_hash_table (info)->dynobj;
896b305b0f1Sespie 
8972159047fSniklas   /* We do not want to include the sections in a dynamic object in the
8982159047fSniklas      output file.  We hack by simply clobbering the list of sections
8992159047fSniklas      in the BFD.  This could be handled more cleanly by, say, a new
9002159047fSniklas      section flag; the existing SEC_NEVER_LOAD flag is not the one we
9012159047fSniklas      want, because that one still implies that the section takes up
902b305b0f1Sespie      space in the output file.  If this is the first object we have
903b305b0f1Sespie      seen, we must preserve the dynamic sections we just created.  */
904c074d1c9Sdrahn   for (ps = &abfd->sections; *ps != NULL; )
905b305b0f1Sespie     {
906c074d1c9Sdrahn       if (abfd != dynobj || ((*ps)->flags & SEC_LINKER_CREATED) == 0)
907c074d1c9Sdrahn 	bfd_section_list_remove (abfd, ps);
908c074d1c9Sdrahn       else
909c074d1c9Sdrahn 	ps = &(*ps)->next;
910b305b0f1Sespie     }
9112159047fSniklas 
9122159047fSniklas   /* The native linker seems to just ignore dynamic objects when -r is
9132159047fSniklas      used.  */
914*007c2a45Smiod   if (info->relocatable)
915c074d1c9Sdrahn     return TRUE;
9162159047fSniklas 
9172159047fSniklas   /* There's no hope of using a dynamic object which does not exactly
9182159047fSniklas      match the format of the output file.  */
9192159047fSniklas   if (info->hash->creator != abfd->xvec)
9202159047fSniklas     {
9212159047fSniklas       bfd_set_error (bfd_error_invalid_operation);
922c074d1c9Sdrahn       return FALSE;
9232159047fSniklas     }
9242159047fSniklas 
9252159047fSniklas   /* Make sure we have a .need and a .rules sections.  These are only
9262159047fSniklas      needed if there really is a dynamic object in the link, so they
9272159047fSniklas      are not added by sunos_create_dynamic_sections.  */
9282159047fSniklas   if (bfd_get_section_by_name (dynobj, ".need") == NULL)
9292159047fSniklas     {
9302159047fSniklas       /* The .need section holds the list of names of shared objets
9312159047fSniklas 	 which must be included at runtime.  The address of this
9322159047fSniklas 	 section is put in the ld_need field.  */
933c074d1c9Sdrahn       asection *s = bfd_make_section (dynobj, ".need");
9342159047fSniklas       if (s == NULL
9352159047fSniklas 	  || ! bfd_set_section_flags (dynobj, s,
9362159047fSniklas 				      (SEC_ALLOC
9372159047fSniklas 				       | SEC_LOAD
9382159047fSniklas 				       | SEC_HAS_CONTENTS
9392159047fSniklas 				       | SEC_IN_MEMORY
9402159047fSniklas 				       | SEC_READONLY))
9412159047fSniklas 	  || ! bfd_set_section_alignment (dynobj, s, 2))
942c074d1c9Sdrahn 	return FALSE;
9432159047fSniklas     }
9442159047fSniklas 
9452159047fSniklas   if (bfd_get_section_by_name (dynobj, ".rules") == NULL)
9462159047fSniklas     {
9472159047fSniklas       /* The .rules section holds the path to search for shared
9482159047fSniklas 	 objects.  The address of this section is put in the ld_rules
9492159047fSniklas 	 field.  */
950c074d1c9Sdrahn       asection *s = bfd_make_section (dynobj, ".rules");
9512159047fSniklas       if (s == NULL
9522159047fSniklas 	  || ! bfd_set_section_flags (dynobj, s,
9532159047fSniklas 				      (SEC_ALLOC
9542159047fSniklas 				       | SEC_LOAD
9552159047fSniklas 				       | SEC_HAS_CONTENTS
9562159047fSniklas 				       | SEC_IN_MEMORY
9572159047fSniklas 				       | SEC_READONLY))
9582159047fSniklas 	  || ! bfd_set_section_alignment (dynobj, s, 2))
959c074d1c9Sdrahn 	return FALSE;
9602159047fSniklas     }
9612159047fSniklas 
9622159047fSniklas   /* Pick up the dynamic symbols and return them to the caller.  */
9632159047fSniklas   if (! sunos_slurp_dynamic_symtab (abfd))
964c074d1c9Sdrahn     return FALSE;
9652159047fSniklas 
9662159047fSniklas   dinfo = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
9672159047fSniklas   *symsp = dinfo->dynsym;
9682159047fSniklas   *sym_countp = dinfo->dynsym_count;
9692159047fSniklas   *stringsp = dinfo->dynstr;
9702159047fSniklas 
9712159047fSniklas   /* Record information about any other objects needed by this one.  */
9722159047fSniklas   need = dinfo->dyninfo.ld_need;
9732159047fSniklas   while (need != 0)
9742159047fSniklas     {
9752159047fSniklas       bfd_byte buf[16];
9762159047fSniklas       unsigned long name, flags;
9772159047fSniklas       unsigned short major_vno, minor_vno;
9782159047fSniklas       struct bfd_link_needed_list *needed, **pp;
979b305b0f1Sespie       char *namebuf, *p;
980c074d1c9Sdrahn       bfd_size_type alc;
9812159047fSniklas       bfd_byte b;
982b305b0f1Sespie       char *namecopy;
9832159047fSniklas 
984c074d1c9Sdrahn       if (bfd_seek (abfd, (file_ptr) need, SEEK_SET) != 0
985c074d1c9Sdrahn 	  || bfd_bread (buf, (bfd_size_type) 16, abfd) != 16)
986c074d1c9Sdrahn 	return FALSE;
9872159047fSniklas 
9882159047fSniklas       /* For the format of an ld_need entry, see aout/sun4.h.  We
9892159047fSniklas 	 should probably define structs for this manipulation.  */
9902159047fSniklas 
9912159047fSniklas       name = bfd_get_32 (abfd, buf);
9922159047fSniklas       flags = bfd_get_32 (abfd, buf + 4);
993b305b0f1Sespie       major_vno = (unsigned short) bfd_get_16 (abfd, buf + 8);
994b305b0f1Sespie       minor_vno = (unsigned short) bfd_get_16 (abfd, buf + 10);
9952159047fSniklas       need = bfd_get_32 (abfd, buf + 12);
9962159047fSniklas 
997c074d1c9Sdrahn       alc = sizeof (struct bfd_link_needed_list);
998c074d1c9Sdrahn       needed = (struct bfd_link_needed_list *) bfd_alloc (abfd, alc);
9992159047fSniklas       if (needed == NULL)
1000c074d1c9Sdrahn 	return FALSE;
10012159047fSniklas       needed->by = abfd;
10022159047fSniklas 
10032159047fSniklas       /* We return the name as [-l]name[.maj][.min].  */
1004b305b0f1Sespie       alc = 30;
1005b305b0f1Sespie       namebuf = (char *) bfd_malloc (alc + 1);
1006b305b0f1Sespie       if (namebuf == NULL)
1007c074d1c9Sdrahn 	return FALSE;
1008b305b0f1Sespie       p = namebuf;
10092159047fSniklas 
10102159047fSniklas       if ((flags & 0x80000000) != 0)
1011b305b0f1Sespie 	{
1012b305b0f1Sespie 	  *p++ = '-';
1013b305b0f1Sespie 	  *p++ = 'l';
1014b305b0f1Sespie 	}
1015c074d1c9Sdrahn       if (bfd_seek (abfd, (file_ptr) name, SEEK_SET) != 0)
1016b305b0f1Sespie 	{
1017b305b0f1Sespie 	  free (namebuf);
1018c074d1c9Sdrahn 	  return FALSE;
1019b305b0f1Sespie 	}
1020b305b0f1Sespie 
10212159047fSniklas       do
10222159047fSniklas 	{
1023c074d1c9Sdrahn 	  if (bfd_bread (&b, (bfd_size_type) 1, abfd) != 1)
1024b305b0f1Sespie 	    {
1025b305b0f1Sespie 	      free (namebuf);
1026c074d1c9Sdrahn 	      return FALSE;
1027b305b0f1Sespie 	    }
1028b305b0f1Sespie 
1029c074d1c9Sdrahn 	  if ((bfd_size_type) (p - namebuf) >= alc)
1030b305b0f1Sespie 	    {
1031b305b0f1Sespie 	      char *n;
1032b305b0f1Sespie 
1033b305b0f1Sespie 	      alc *= 2;
1034b305b0f1Sespie 	      n = (char *) bfd_realloc (namebuf, alc + 1);
1035b305b0f1Sespie 	      if (n == NULL)
1036b305b0f1Sespie 		{
1037b305b0f1Sespie 		  free (namebuf);
1038c074d1c9Sdrahn 		  return FALSE;
1039b305b0f1Sespie 		}
1040b305b0f1Sespie 	      p = n + (p - namebuf);
1041b305b0f1Sespie 	      namebuf = n;
1042b305b0f1Sespie 	    }
1043b305b0f1Sespie 
1044b305b0f1Sespie 	  *p++ = b;
10452159047fSniklas 	}
10462159047fSniklas       while (b != '\0');
10472159047fSniklas 
1048b305b0f1Sespie       if (major_vno == 0)
1049b305b0f1Sespie 	*p = '\0';
1050b305b0f1Sespie       else
10512159047fSniklas 	{
1052b305b0f1Sespie 	  char majbuf[30];
1053b305b0f1Sespie 	  char minbuf[30];
1054b305b0f1Sespie 
1055b305b0f1Sespie 	  sprintf (majbuf, ".%d", major_vno);
1056b305b0f1Sespie 	  if (minor_vno == 0)
1057b305b0f1Sespie 	    minbuf[0] = '\0';
1058b305b0f1Sespie 	  else
1059b305b0f1Sespie 	    sprintf (minbuf, ".%d", minor_vno);
1060b305b0f1Sespie 
1061b305b0f1Sespie 	  if ((p - namebuf) + strlen (majbuf) + strlen (minbuf) >= alc)
1062b305b0f1Sespie 	    {
1063b305b0f1Sespie 	      char *n;
1064b305b0f1Sespie 
1065b305b0f1Sespie 	      alc = (p - namebuf) + strlen (majbuf) + strlen (minbuf);
1066b305b0f1Sespie 	      n = (char *) bfd_realloc (namebuf, alc + 1);
1067b305b0f1Sespie 	      if (n == NULL)
1068b305b0f1Sespie 		{
1069b305b0f1Sespie 		  free (namebuf);
1070c074d1c9Sdrahn 		  return FALSE;
1071b305b0f1Sespie 		}
1072b305b0f1Sespie 	      p = n + (p - namebuf);
1073b305b0f1Sespie 	      namebuf = n;
1074b305b0f1Sespie 	    }
1075b305b0f1Sespie 
1076b305b0f1Sespie 	  strcpy (p, majbuf);
1077b305b0f1Sespie 	  strcat (p, minbuf);
1078b305b0f1Sespie 	}
1079b305b0f1Sespie 
1080c074d1c9Sdrahn       namecopy = bfd_alloc (abfd, (bfd_size_type) strlen (namebuf) + 1);
1081b305b0f1Sespie       if (namecopy == NULL)
1082b305b0f1Sespie 	{
1083b305b0f1Sespie 	  free (namebuf);
1084c074d1c9Sdrahn 	  return FALSE;
1085b305b0f1Sespie 	}
1086b305b0f1Sespie       strcpy (namecopy, namebuf);
1087b305b0f1Sespie       free (namebuf);
1088b305b0f1Sespie       needed->name = namecopy;
10892159047fSniklas 
10902159047fSniklas       needed->next = NULL;
10912159047fSniklas 
10922159047fSniklas       for (pp = &sunos_hash_table (info)->needed;
10932159047fSniklas 	   *pp != NULL;
10942159047fSniklas 	   pp = &(*pp)->next)
10952159047fSniklas 	;
10962159047fSniklas       *pp = needed;
10972159047fSniklas     }
10982159047fSniklas 
1099c074d1c9Sdrahn   return TRUE;
11002159047fSniklas }
11012159047fSniklas 
11022159047fSniklas /* Function to add a single symbol to the linker hash table.  This is
11032159047fSniklas    a wrapper around _bfd_generic_link_add_one_symbol which handles the
11042159047fSniklas    tweaking needed for dynamic linking support.  */
11052159047fSniklas 
1106c074d1c9Sdrahn static bfd_boolean
sunos_add_one_symbol(info,abfd,name,flags,section,value,string,copy,collect,hashp)11072159047fSniklas sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
11082159047fSniklas 		      copy, collect, hashp)
11092159047fSniklas      struct bfd_link_info *info;
11102159047fSniklas      bfd *abfd;
11112159047fSniklas      const char *name;
11122159047fSniklas      flagword flags;
11132159047fSniklas      asection *section;
11142159047fSniklas      bfd_vma value;
11152159047fSniklas      const char *string;
1116c074d1c9Sdrahn      bfd_boolean copy;
1117c074d1c9Sdrahn      bfd_boolean collect;
11182159047fSniklas      struct bfd_link_hash_entry **hashp;
11192159047fSniklas {
11202159047fSniklas   struct sunos_link_hash_entry *h;
11212159047fSniklas   int new_flag;
11222159047fSniklas 
1123c88b1d6cSniklas   if ((flags & (BSF_INDIRECT | BSF_WARNING | BSF_CONSTRUCTOR)) != 0
1124c88b1d6cSniklas       || ! bfd_is_und_section (section))
1125c074d1c9Sdrahn     h = sunos_link_hash_lookup (sunos_hash_table (info), name, TRUE, copy,
1126c074d1c9Sdrahn 				FALSE);
1127c88b1d6cSniklas   else
1128c88b1d6cSniklas     h = ((struct sunos_link_hash_entry *)
1129c074d1c9Sdrahn 	 bfd_wrapped_link_hash_lookup (abfd, info, name, TRUE, copy, FALSE));
11302159047fSniklas   if (h == NULL)
1131c074d1c9Sdrahn     return FALSE;
11322159047fSniklas 
11332159047fSniklas   if (hashp != NULL)
11342159047fSniklas     *hashp = (struct bfd_link_hash_entry *) h;
11352159047fSniklas 
11362159047fSniklas   /* Treat a common symbol in a dynamic object as defined in the .bss
11372159047fSniklas      section of the dynamic object.  We don't want to allocate space
11382159047fSniklas      for it in our process image.  */
11392159047fSniklas   if ((abfd->flags & DYNAMIC) != 0
11402159047fSniklas       && bfd_is_com_section (section))
11412159047fSniklas     section = obj_bsssec (abfd);
11422159047fSniklas 
11432159047fSniklas   if (! bfd_is_und_section (section)
11442159047fSniklas       && h->root.root.type != bfd_link_hash_new
11452159047fSniklas       && h->root.root.type != bfd_link_hash_undefined
11462159047fSniklas       && h->root.root.type != bfd_link_hash_defweak)
11472159047fSniklas     {
11482159047fSniklas       /* We are defining the symbol, and it is already defined.  This
11492159047fSniklas 	 is a potential multiple definition error.  */
11502159047fSniklas       if ((abfd->flags & DYNAMIC) != 0)
11512159047fSniklas 	{
11522159047fSniklas 	  /* The definition we are adding is from a dynamic object.
11532159047fSniklas 	     We do not want this new definition to override the
11542159047fSniklas 	     existing definition, so we pretend it is just a
11552159047fSniklas 	     reference.  */
11562159047fSniklas 	  section = bfd_und_section_ptr;
11572159047fSniklas 	}
11582159047fSniklas       else if (h->root.root.type == bfd_link_hash_defined
11592159047fSniklas 	       && h->root.root.u.def.section->owner != NULL
11602159047fSniklas 	       && (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
11612159047fSniklas 	{
11622159047fSniklas 	  /* The existing definition is from a dynamic object.  We
11632159047fSniklas 	     want to override it with the definition we just found.
11642159047fSniklas 	     Clobber the existing definition.  */
1165b305b0f1Sespie 	  h->root.root.type = bfd_link_hash_undefined;
1166b305b0f1Sespie 	  h->root.root.u.undef.abfd = h->root.root.u.def.section->owner;
11672159047fSniklas 	}
11682159047fSniklas       else if (h->root.root.type == bfd_link_hash_common
11692159047fSniklas 	       && (h->root.root.u.c.p->section->owner->flags & DYNAMIC) != 0)
11702159047fSniklas 	{
11712159047fSniklas 	  /* The existing definition is from a dynamic object.  We
11722159047fSniklas 	     want to override it with the definition we just found.
11732159047fSniklas 	     Clobber the existing definition.  We can't set it to new,
11742159047fSniklas 	     because it is on the undefined list.  */
11752159047fSniklas 	  h->root.root.type = bfd_link_hash_undefined;
11762159047fSniklas 	  h->root.root.u.undef.abfd = h->root.root.u.c.p->section->owner;
11772159047fSniklas 	}
11782159047fSniklas     }
11792159047fSniklas 
1180c88b1d6cSniklas   if ((abfd->flags & DYNAMIC) != 0
1181c88b1d6cSniklas       && abfd->xvec == info->hash->creator
1182c88b1d6cSniklas       && (h->flags & SUNOS_CONSTRUCTOR) != 0)
1183c88b1d6cSniklas     {
1184c88b1d6cSniklas       /* The existing symbol is a constructor symbol, and this symbol
1185c88b1d6cSniklas 	 is from a dynamic object.  A constructor symbol is actually a
1186c88b1d6cSniklas 	 definition, although the type will be bfd_link_hash_undefined
1187c88b1d6cSniklas 	 at this point.  We want to ignore the definition from the
1188c88b1d6cSniklas 	 dynamic object.  */
1189c88b1d6cSniklas       section = bfd_und_section_ptr;
1190c88b1d6cSniklas     }
1191c88b1d6cSniklas   else if ((flags & BSF_CONSTRUCTOR) != 0
1192c88b1d6cSniklas 	   && (abfd->flags & DYNAMIC) == 0
1193c88b1d6cSniklas 	   && h->root.root.type == bfd_link_hash_defined
1194c88b1d6cSniklas 	   && h->root.root.u.def.section->owner != NULL
1195c88b1d6cSniklas 	   && (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
1196c88b1d6cSniklas     {
1197c88b1d6cSniklas       /* The existing symbol is defined by a dynamic object, and this
1198c88b1d6cSniklas 	 is a constructor symbol.  As above, we want to force the use
1199c88b1d6cSniklas 	 of the constructor symbol from the regular object.  */
1200c88b1d6cSniklas       h->root.root.type = bfd_link_hash_new;
1201c88b1d6cSniklas     }
1202c88b1d6cSniklas 
12032159047fSniklas   /* Do the usual procedure for adding a symbol.  */
12042159047fSniklas   if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
12052159047fSniklas 					  value, string, copy, collect,
12062159047fSniklas 					  hashp))
1207c074d1c9Sdrahn     return FALSE;
12082159047fSniklas 
12092159047fSniklas   if (abfd->xvec == info->hash->creator)
12102159047fSniklas     {
12112159047fSniklas       /* Set a flag in the hash table entry indicating the type of
12122159047fSniklas 	 reference or definition we just found.  Keep a count of the
12132159047fSniklas 	 number of dynamic symbols we find.  A dynamic symbol is one
12142159047fSniklas 	 which is referenced or defined by both a regular object and a
12152159047fSniklas 	 shared object.  */
12162159047fSniklas       if ((abfd->flags & DYNAMIC) == 0)
12172159047fSniklas 	{
12182159047fSniklas 	  if (bfd_is_und_section (section))
12192159047fSniklas 	    new_flag = SUNOS_REF_REGULAR;
12202159047fSniklas 	  else
12212159047fSniklas 	    new_flag = SUNOS_DEF_REGULAR;
12222159047fSniklas 	}
12232159047fSniklas       else
12242159047fSniklas 	{
12252159047fSniklas 	  if (bfd_is_und_section (section))
12262159047fSniklas 	    new_flag = SUNOS_REF_DYNAMIC;
12272159047fSniklas 	  else
12282159047fSniklas 	    new_flag = SUNOS_DEF_DYNAMIC;
12292159047fSniklas 	}
12302159047fSniklas       h->flags |= new_flag;
12312159047fSniklas 
12322159047fSniklas       if (h->dynindx == -1
12332159047fSniklas 	  && (h->flags & (SUNOS_DEF_REGULAR | SUNOS_REF_REGULAR)) != 0)
12342159047fSniklas 	{
12352159047fSniklas 	  ++sunos_hash_table (info)->dynsymcount;
12362159047fSniklas 	  h->dynindx = -2;
12372159047fSniklas 	}
1238c88b1d6cSniklas 
1239c88b1d6cSniklas       if ((flags & BSF_CONSTRUCTOR) != 0
1240c88b1d6cSniklas 	  && (abfd->flags & DYNAMIC) == 0)
1241c88b1d6cSniklas 	h->flags |= SUNOS_CONSTRUCTOR;
12422159047fSniklas     }
12432159047fSniklas 
1244c074d1c9Sdrahn   return TRUE;
12452159047fSniklas }
12462159047fSniklas 
12472159047fSniklas /* Return the list of objects needed by BFD.  */
12482159047fSniklas 
12492159047fSniklas struct bfd_link_needed_list *
bfd_sunos_get_needed_list(abfd,info)12502159047fSniklas bfd_sunos_get_needed_list (abfd, info)
1251b305b0f1Sespie      bfd *abfd ATTRIBUTE_UNUSED;
12522159047fSniklas      struct bfd_link_info *info;
12532159047fSniklas {
12542159047fSniklas   if (info->hash->creator != &MY(vec))
12552159047fSniklas     return NULL;
12562159047fSniklas   return sunos_hash_table (info)->needed;
12572159047fSniklas }
12582159047fSniklas 
12592159047fSniklas /* Record an assignment made to a symbol by a linker script.  We need
12602159047fSniklas    this in case some dynamic object refers to this symbol.  */
12612159047fSniklas 
1262c074d1c9Sdrahn bfd_boolean
bfd_sunos_record_link_assignment(output_bfd,info,name)12632159047fSniklas bfd_sunos_record_link_assignment (output_bfd, info, name)
12642159047fSniklas      bfd *output_bfd;
12652159047fSniklas      struct bfd_link_info *info;
12662159047fSniklas      const char *name;
12672159047fSniklas {
12682159047fSniklas   struct sunos_link_hash_entry *h;
12692159047fSniklas 
12702159047fSniklas   if (output_bfd->xvec != &MY(vec))
1271c074d1c9Sdrahn     return TRUE;
12722159047fSniklas 
12732159047fSniklas   /* This is called after we have examined all the input objects.  If
12742159047fSniklas      the symbol does not exist, it merely means that no object refers
12752159047fSniklas      to it, and we can just ignore it at this point.  */
12762159047fSniklas   h = sunos_link_hash_lookup (sunos_hash_table (info), name,
1277c074d1c9Sdrahn 			      FALSE, FALSE, FALSE);
12782159047fSniklas   if (h == NULL)
1279c074d1c9Sdrahn     return TRUE;
12802159047fSniklas 
12812159047fSniklas   /* In a shared library, the __DYNAMIC symbol does not appear in the
12822159047fSniklas      dynamic symbol table.  */
12832159047fSniklas   if (! info->shared || strcmp (name, "__DYNAMIC") != 0)
12842159047fSniklas     {
12852159047fSniklas       h->flags |= SUNOS_DEF_REGULAR;
12862159047fSniklas 
12872159047fSniklas       if (h->dynindx == -1)
12882159047fSniklas 	{
12892159047fSniklas 	  ++sunos_hash_table (info)->dynsymcount;
12902159047fSniklas 	  h->dynindx = -2;
12912159047fSniklas 	}
12922159047fSniklas     }
12932159047fSniklas 
1294c074d1c9Sdrahn   return TRUE;
12952159047fSniklas }
12962159047fSniklas 
12972159047fSniklas /* Set up the sizes and contents of the dynamic sections created in
12982159047fSniklas    sunos_add_dynamic_symbols.  This is called by the SunOS linker
12992159047fSniklas    emulation before_allocation routine.  We must set the sizes of the
13002159047fSniklas    sections before the linker sets the addresses of the various
13012159047fSniklas    sections.  This unfortunately requires reading all the relocs so
13022159047fSniklas    that we can work out which ones need to become dynamic relocs.  If
1303c074d1c9Sdrahn    info->keep_memory is TRUE, we keep the relocs in memory; otherwise,
13042159047fSniklas    we discard them, and will read them again later.  */
13052159047fSniklas 
1306c074d1c9Sdrahn bfd_boolean
bfd_sunos_size_dynamic_sections(output_bfd,info,sdynptr,sneedptr,srulesptr)13072159047fSniklas bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
13082159047fSniklas 				 srulesptr)
13092159047fSniklas      bfd *output_bfd;
13102159047fSniklas      struct bfd_link_info *info;
13112159047fSniklas      asection **sdynptr;
13122159047fSniklas      asection **sneedptr;
13132159047fSniklas      asection **srulesptr;
13142159047fSniklas {
13152159047fSniklas   bfd *dynobj;
1316c074d1c9Sdrahn   bfd_size_type dynsymcount;
13172159047fSniklas   struct sunos_link_hash_entry *h;
13182159047fSniklas   asection *s;
13192159047fSniklas   size_t bucketcount;
1320c074d1c9Sdrahn   bfd_size_type hashalloc;
13212159047fSniklas   size_t i;
13222159047fSniklas   bfd *sub;
13232159047fSniklas 
13242159047fSniklas   *sdynptr = NULL;
13252159047fSniklas   *sneedptr = NULL;
13262159047fSniklas   *srulesptr = NULL;
13272159047fSniklas 
1328*007c2a45Smiod   if (info->relocatable)
1329c074d1c9Sdrahn     return TRUE;
1330e93f7393Sniklas 
13312159047fSniklas   if (output_bfd->xvec != &MY(vec))
1332c074d1c9Sdrahn     return TRUE;
13332159047fSniklas 
13342159047fSniklas   /* Look through all the input BFD's and read their relocs.  It would
13352159047fSniklas      be better if we didn't have to do this, but there is no other way
13362159047fSniklas      to determine the number of dynamic relocs we need, and, more
13372159047fSniklas      importantly, there is no other way to know which symbols should
13382159047fSniklas      get an entry in the procedure linkage table.  */
13392159047fSniklas   for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
13402159047fSniklas     {
13412159047fSniklas       if ((sub->flags & DYNAMIC) == 0
13422159047fSniklas 	  && sub->xvec == output_bfd->xvec)
13432159047fSniklas 	{
13442159047fSniklas 	  if (! sunos_scan_relocs (info, sub, obj_textsec (sub),
13452159047fSniklas 				   exec_hdr (sub)->a_trsize)
13462159047fSniklas 	      || ! sunos_scan_relocs (info, sub, obj_datasec (sub),
13472159047fSniklas 				      exec_hdr (sub)->a_drsize))
1348c074d1c9Sdrahn 	    return FALSE;
13492159047fSniklas 	}
13502159047fSniklas     }
13512159047fSniklas 
13522159047fSniklas   dynobj = sunos_hash_table (info)->dynobj;
13532159047fSniklas   dynsymcount = sunos_hash_table (info)->dynsymcount;
13542159047fSniklas 
13552159047fSniklas   /* If there were no dynamic objects in the link, and we don't need
13562159047fSniklas      to build a global offset table, there is nothing to do here.  */
1357b305b0f1Sespie   if (! sunos_hash_table (info)->dynamic_sections_needed
1358b305b0f1Sespie       && ! sunos_hash_table (info)->got_needed)
1359c074d1c9Sdrahn     return TRUE;
13602159047fSniklas 
13612159047fSniklas   /* If __GLOBAL_OFFSET_TABLE_ was mentioned, define it.  */
13622159047fSniklas   h = sunos_link_hash_lookup (sunos_hash_table (info),
1363c074d1c9Sdrahn 			      "__GLOBAL_OFFSET_TABLE_", FALSE, FALSE, FALSE);
13642159047fSniklas   if (h != NULL && (h->flags & SUNOS_REF_REGULAR) != 0)
13652159047fSniklas     {
13662159047fSniklas       h->flags |= SUNOS_DEF_REGULAR;
13672159047fSniklas       if (h->dynindx == -1)
13682159047fSniklas 	{
13692159047fSniklas 	  ++sunos_hash_table (info)->dynsymcount;
13702159047fSniklas 	  h->dynindx = -2;
13712159047fSniklas 	}
13722159047fSniklas       h->root.root.type = bfd_link_hash_defined;
13732159047fSniklas       h->root.root.u.def.section = bfd_get_section_by_name (dynobj, ".got");
1374e93f7393Sniklas 
1375e93f7393Sniklas       /* If the .got section is more than 0x1000 bytes, we set
1376e93f7393Sniklas 	 __GLOBAL_OFFSET_TABLE_ to be 0x1000 bytes into the section,
1377e93f7393Sniklas 	 so that 13 bit relocations have a greater chance of working.  */
1378e93f7393Sniklas       s = bfd_get_section_by_name (dynobj, ".got");
1379e93f7393Sniklas       BFD_ASSERT (s != NULL);
1380e93f7393Sniklas       if (s->_raw_size >= 0x1000)
1381e93f7393Sniklas 	h->root.root.u.def.value = 0x1000;
1382e93f7393Sniklas       else
13832159047fSniklas 	h->root.root.u.def.value = 0;
1384e93f7393Sniklas 
1385e93f7393Sniklas       sunos_hash_table (info)->got_base = h->root.root.u.def.value;
13862159047fSniklas     }
13872159047fSniklas 
1388b305b0f1Sespie   /* If there are any shared objects in the link, then we need to set
1389b305b0f1Sespie      up the dynamic linking information.  */
1390b305b0f1Sespie   if (sunos_hash_table (info)->dynamic_sections_needed)
1391b305b0f1Sespie     {
1392b305b0f1Sespie       *sdynptr = bfd_get_section_by_name (dynobj, ".dynamic");
1393b305b0f1Sespie 
13942159047fSniklas       /* The .dynamic section is always the same size.  */
1395b305b0f1Sespie       s = *sdynptr;
13962159047fSniklas       BFD_ASSERT (s != NULL);
13972159047fSniklas       s->_raw_size = (sizeof (struct external_sun4_dynamic)
13982159047fSniklas 		      + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE
13992159047fSniklas 		      + sizeof (struct external_sun4_dynamic_link));
14002159047fSniklas 
1401b305b0f1Sespie       /* Set the size of the .dynsym and .hash sections.  We counted
1402b305b0f1Sespie 	 the number of dynamic symbols as we read the input files.  We
1403b305b0f1Sespie 	 will build the dynamic symbol table (.dynsym) and the hash
1404b305b0f1Sespie 	 table (.hash) when we build the final symbol table, because
1405b305b0f1Sespie 	 until then we do not know the correct value to give the
1406b305b0f1Sespie 	 symbols.  We build the dynamic symbol string table (.dynstr)
1407b305b0f1Sespie 	 in a traversal of the symbol table using
1408b305b0f1Sespie 	 sunos_scan_dynamic_symbol.  */
14092159047fSniklas       s = bfd_get_section_by_name (dynobj, ".dynsym");
14102159047fSniklas       BFD_ASSERT (s != NULL);
14112159047fSniklas       s->_raw_size = dynsymcount * sizeof (struct external_nlist);
14122159047fSniklas       s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
14132159047fSniklas       if (s->contents == NULL && s->_raw_size != 0)
1414c074d1c9Sdrahn 	return FALSE;
14152159047fSniklas 
1416b305b0f1Sespie       /* The number of buckets is just the number of symbols divided
1417b305b0f1Sespie 	 by four.  To compute the final size of the hash table, we
1418b305b0f1Sespie 	 must actually compute the hash table.  Normally we need
1419b305b0f1Sespie 	 exactly as many entries in the hash table as there are
1420b305b0f1Sespie 	 dynamic symbols, but if some of the buckets are not used we
1421b305b0f1Sespie 	 will need additional entries.  In the worst case, every
1422b305b0f1Sespie 	 symbol will hash to the same bucket, and we will need
1423b305b0f1Sespie 	 BUCKETCOUNT - 1 extra entries.  */
14242159047fSniklas       if (dynsymcount >= 4)
14252159047fSniklas 	bucketcount = dynsymcount / 4;
14262159047fSniklas       else if (dynsymcount > 0)
14272159047fSniklas 	bucketcount = dynsymcount;
14282159047fSniklas       else
14292159047fSniklas 	bucketcount = 1;
14302159047fSniklas       s = bfd_get_section_by_name (dynobj, ".hash");
14312159047fSniklas       BFD_ASSERT (s != NULL);
14322159047fSniklas       hashalloc = (dynsymcount + bucketcount - 1) * HASH_ENTRY_SIZE;
1433c074d1c9Sdrahn       s->contents = (bfd_byte *) bfd_zalloc (dynobj, hashalloc);
14342159047fSniklas       if (s->contents == NULL && dynsymcount > 0)
1435c074d1c9Sdrahn 	return FALSE;
14362159047fSniklas       for (i = 0; i < bucketcount; i++)
14372159047fSniklas 	PUT_WORD (output_bfd, (bfd_vma) -1, s->contents + i * HASH_ENTRY_SIZE);
14382159047fSniklas       s->_raw_size = bucketcount * HASH_ENTRY_SIZE;
14392159047fSniklas 
14402159047fSniklas       sunos_hash_table (info)->bucketcount = bucketcount;
14412159047fSniklas 
1442b305b0f1Sespie       /* Scan all the symbols, place them in the dynamic symbol table,
1443b305b0f1Sespie 	 and build the dynamic hash table.  We reuse dynsymcount as a
1444b305b0f1Sespie 	 counter for the number of symbols we have added so far.  */
14452159047fSniklas       sunos_hash_table (info)->dynsymcount = 0;
14462159047fSniklas       sunos_link_hash_traverse (sunos_hash_table (info),
14472159047fSniklas 				sunos_scan_dynamic_symbol,
14482159047fSniklas 				(PTR) info);
14492159047fSniklas       BFD_ASSERT (sunos_hash_table (info)->dynsymcount == dynsymcount);
14502159047fSniklas 
14512159047fSniklas       /* The SunOS native linker seems to align the total size of the
14522159047fSniklas 	 symbol strings to a multiple of 8.  I don't know if this is
14532159047fSniklas 	 important, but it can't hurt much.  */
14542159047fSniklas       s = bfd_get_section_by_name (dynobj, ".dynstr");
14552159047fSniklas       BFD_ASSERT (s != NULL);
14562159047fSniklas       if ((s->_raw_size & 7) != 0)
14572159047fSniklas 	{
14582159047fSniklas 	  bfd_size_type add;
14592159047fSniklas 	  bfd_byte *contents;
14602159047fSniklas 
14612159047fSniklas 	  add = 8 - (s->_raw_size & 7);
1462c88b1d6cSniklas 	  contents = (bfd_byte *) bfd_realloc (s->contents,
1463c074d1c9Sdrahn 					       s->_raw_size + add);
14642159047fSniklas 	  if (contents == NULL)
1465c074d1c9Sdrahn 	    return FALSE;
14662159047fSniklas 	  memset (contents + s->_raw_size, 0, (size_t) add);
14672159047fSniklas 	  s->contents = contents;
14682159047fSniklas 	  s->_raw_size += add;
14692159047fSniklas 	}
1470b305b0f1Sespie     }
14712159047fSniklas 
14722159047fSniklas   /* Now that we have worked out the sizes of the procedure linkage
14732159047fSniklas      table and the dynamic relocs, allocate storage for them.  */
14742159047fSniklas   s = bfd_get_section_by_name (dynobj, ".plt");
14752159047fSniklas   BFD_ASSERT (s != NULL);
14762159047fSniklas   if (s->_raw_size != 0)
14772159047fSniklas     {
14782159047fSniklas       s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
14792159047fSniklas       if (s->contents == NULL)
1480c074d1c9Sdrahn 	return FALSE;
14812159047fSniklas 
14822159047fSniklas       /* Fill in the first entry in the table.  */
14832159047fSniklas       switch (bfd_get_arch (dynobj))
14842159047fSniklas 	{
14852159047fSniklas 	case bfd_arch_sparc:
14862159047fSniklas 	  memcpy (s->contents, sparc_plt_first_entry, SPARC_PLT_ENTRY_SIZE);
14872159047fSniklas 	  break;
14882159047fSniklas 
14892159047fSniklas 	case bfd_arch_m68k:
14902159047fSniklas 	  memcpy (s->contents, m68k_plt_first_entry, M68K_PLT_ENTRY_SIZE);
14912159047fSniklas 	  break;
14922159047fSniklas 
14932159047fSniklas 	default:
14942159047fSniklas 	  abort ();
14952159047fSniklas 	}
14962159047fSniklas     }
14972159047fSniklas 
14982159047fSniklas   s = bfd_get_section_by_name (dynobj, ".dynrel");
14992159047fSniklas   if (s->_raw_size != 0)
15002159047fSniklas     {
15012159047fSniklas       s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
15022159047fSniklas       if (s->contents == NULL)
1503c074d1c9Sdrahn 	return FALSE;
15042159047fSniklas     }
15052159047fSniklas   /* We use the reloc_count field to keep track of how many of the
15062159047fSniklas      relocs we have output so far.  */
15072159047fSniklas   s->reloc_count = 0;
15082159047fSniklas 
15092159047fSniklas   /* Make space for the global offset table.  */
15102159047fSniklas   s = bfd_get_section_by_name (dynobj, ".got");
15112159047fSniklas   s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
15122159047fSniklas   if (s->contents == NULL)
1513c074d1c9Sdrahn     return FALSE;
15142159047fSniklas 
15152159047fSniklas   *sneedptr = bfd_get_section_by_name (dynobj, ".need");
15162159047fSniklas   *srulesptr = bfd_get_section_by_name (dynobj, ".rules");
15172159047fSniklas 
1518c074d1c9Sdrahn   return TRUE;
15192159047fSniklas }
15202159047fSniklas 
15212159047fSniklas /* Scan the relocs for an input section.  */
15222159047fSniklas 
1523c074d1c9Sdrahn static bfd_boolean
sunos_scan_relocs(info,abfd,sec,rel_size)15242159047fSniklas sunos_scan_relocs (info, abfd, sec, rel_size)
15252159047fSniklas      struct bfd_link_info *info;
15262159047fSniklas      bfd *abfd;
15272159047fSniklas      asection *sec;
15282159047fSniklas      bfd_size_type rel_size;
15292159047fSniklas {
15302159047fSniklas   PTR relocs;
15312159047fSniklas   PTR free_relocs = NULL;
15322159047fSniklas 
15332159047fSniklas   if (rel_size == 0)
1534c074d1c9Sdrahn     return TRUE;
15352159047fSniklas 
15362159047fSniklas   if (! info->keep_memory)
1537c074d1c9Sdrahn     relocs = free_relocs = bfd_malloc (rel_size);
15382159047fSniklas   else
15392159047fSniklas     {
15402159047fSniklas       struct aout_section_data_struct *n;
1541c074d1c9Sdrahn       bfd_size_type amt = sizeof (struct aout_section_data_struct);
15422159047fSniklas 
1543c074d1c9Sdrahn       n = (struct aout_section_data_struct *) bfd_alloc (abfd, amt);
15442159047fSniklas       if (n == NULL)
15452159047fSniklas 	relocs = NULL;
15462159047fSniklas       else
15472159047fSniklas 	{
15482159047fSniklas 	  set_aout_section_data (sec, n);
1549c074d1c9Sdrahn 	  relocs = bfd_malloc (rel_size);
15502159047fSniklas 	  aout_section_data (sec)->relocs = relocs;
15512159047fSniklas 	}
15522159047fSniklas     }
15532159047fSniklas   if (relocs == NULL)
1554c074d1c9Sdrahn     return FALSE;
15552159047fSniklas 
15562159047fSniklas   if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
1557c074d1c9Sdrahn       || bfd_bread (relocs, rel_size, abfd) != rel_size)
15582159047fSniklas     goto error_return;
15592159047fSniklas 
15602159047fSniklas   if (obj_reloc_entry_size (abfd) == RELOC_STD_SIZE)
15612159047fSniklas     {
15622159047fSniklas       if (! sunos_scan_std_relocs (info, abfd, sec,
15632159047fSniklas 				   (struct reloc_std_external *) relocs,
15642159047fSniklas 				   rel_size))
15652159047fSniklas 	goto error_return;
15662159047fSniklas     }
15672159047fSniklas   else
15682159047fSniklas     {
15692159047fSniklas       if (! sunos_scan_ext_relocs (info, abfd, sec,
15702159047fSniklas 				   (struct reloc_ext_external *) relocs,
15712159047fSniklas 				   rel_size))
15722159047fSniklas 	goto error_return;
15732159047fSniklas     }
15742159047fSniklas 
15752159047fSniklas   if (free_relocs != NULL)
15762159047fSniklas     free (free_relocs);
15772159047fSniklas 
1578c074d1c9Sdrahn   return TRUE;
15792159047fSniklas 
15802159047fSniklas  error_return:
15812159047fSniklas   if (free_relocs != NULL)
15822159047fSniklas     free (free_relocs);
1583c074d1c9Sdrahn   return FALSE;
15842159047fSniklas }
15852159047fSniklas 
15862159047fSniklas /* Scan the relocs for an input section using standard relocs.  We
15872159047fSniklas    need to figure out what to do for each reloc against a dynamic
15882159047fSniklas    symbol.  If the symbol is in the .text section, an entry is made in
15892159047fSniklas    the procedure linkage table.  Note that this will do the wrong
15902159047fSniklas    thing if the symbol is actually data; I don't think the Sun 3
15912159047fSniklas    native linker handles this case correctly either.  If the symbol is
15922159047fSniklas    not in the .text section, we must preserve the reloc as a dynamic
15932159047fSniklas    reloc.  FIXME: We should also handle the PIC relocs here by
15942159047fSniklas    building global offset table entries.  */
15952159047fSniklas 
1596c074d1c9Sdrahn static bfd_boolean
sunos_scan_std_relocs(info,abfd,sec,relocs,rel_size)15972159047fSniklas sunos_scan_std_relocs (info, abfd, sec, relocs, rel_size)
15982159047fSniklas      struct bfd_link_info *info;
15992159047fSniklas      bfd *abfd;
1600b305b0f1Sespie      asection *sec ATTRIBUTE_UNUSED;
16012159047fSniklas      const struct reloc_std_external *relocs;
16022159047fSniklas      bfd_size_type rel_size;
16032159047fSniklas {
16042159047fSniklas   bfd *dynobj;
16052159047fSniklas   asection *splt = NULL;
16062159047fSniklas   asection *srel = NULL;
16072159047fSniklas   struct sunos_link_hash_entry **sym_hashes;
16082159047fSniklas   const struct reloc_std_external *rel, *relend;
16092159047fSniklas 
16102159047fSniklas   /* We only know how to handle m68k plt entries.  */
16112159047fSniklas   if (bfd_get_arch (abfd) != bfd_arch_m68k)
16122159047fSniklas     {
16132159047fSniklas       bfd_set_error (bfd_error_invalid_target);
1614c074d1c9Sdrahn       return FALSE;
16152159047fSniklas     }
16162159047fSniklas 
16172159047fSniklas   dynobj = NULL;
16182159047fSniklas 
16192159047fSniklas   sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd);
16202159047fSniklas 
16212159047fSniklas   relend = relocs + rel_size / RELOC_STD_SIZE;
16222159047fSniklas   for (rel = relocs; rel < relend; rel++)
16232159047fSniklas     {
16242159047fSniklas       int r_index;
16252159047fSniklas       struct sunos_link_hash_entry *h;
16262159047fSniklas 
16272159047fSniklas       /* We only want relocs against external symbols.  */
1628c88b1d6cSniklas       if (bfd_header_big_endian (abfd))
16292159047fSniklas 	{
16302159047fSniklas 	  if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG) == 0)
16312159047fSniklas 	    continue;
16322159047fSniklas 	}
16332159047fSniklas       else
16342159047fSniklas 	{
16352159047fSniklas 	  if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE) == 0)
16362159047fSniklas 	    continue;
16372159047fSniklas 	}
16382159047fSniklas 
16392159047fSniklas       /* Get the symbol index.  */
1640c88b1d6cSniklas       if (bfd_header_big_endian (abfd))
16412159047fSniklas 	r_index = ((rel->r_index[0] << 16)
16422159047fSniklas 		   | (rel->r_index[1] << 8)
16432159047fSniklas 		   | rel->r_index[2]);
16442159047fSniklas       else
16452159047fSniklas 	r_index = ((rel->r_index[2] << 16)
16462159047fSniklas 		   | (rel->r_index[1] << 8)
16472159047fSniklas 		   | rel->r_index[0]);
16482159047fSniklas 
16492159047fSniklas       /* Get the hash table entry.  */
16502159047fSniklas       h = sym_hashes[r_index];
16512159047fSniklas       if (h == NULL)
16522159047fSniklas 	{
16532159047fSniklas 	  /* This should not normally happen, but it will in any case
16542159047fSniklas 	     be caught in the relocation phase.  */
16552159047fSniklas 	  continue;
16562159047fSniklas 	}
16572159047fSniklas 
16582159047fSniklas       /* At this point common symbols have already been allocated, so
16592159047fSniklas 	 we don't have to worry about them.  We need to consider that
16602159047fSniklas 	 we may have already seen this symbol and marked it undefined;
16612159047fSniklas 	 if the symbol is really undefined, then SUNOS_DEF_DYNAMIC
16622159047fSniklas 	 will be zero.  */
16632159047fSniklas       if (h->root.root.type != bfd_link_hash_defined
16642159047fSniklas 	  && h->root.root.type != bfd_link_hash_defweak
16652159047fSniklas 	  && h->root.root.type != bfd_link_hash_undefined)
16662159047fSniklas 	continue;
16672159047fSniklas 
16682159047fSniklas       if ((h->flags & SUNOS_DEF_DYNAMIC) == 0
16692159047fSniklas 	  || (h->flags & SUNOS_DEF_REGULAR) != 0)
16702159047fSniklas 	continue;
16712159047fSniklas 
16722159047fSniklas       if (dynobj == NULL)
16732159047fSniklas 	{
1674b305b0f1Sespie 	  asection *sgot;
1675b305b0f1Sespie 
1676c074d1c9Sdrahn 	  if (! sunos_create_dynamic_sections (abfd, info, FALSE))
1677c074d1c9Sdrahn 	    return FALSE;
16782159047fSniklas 	  dynobj = sunos_hash_table (info)->dynobj;
16792159047fSniklas 	  splt = bfd_get_section_by_name (dynobj, ".plt");
16802159047fSniklas 	  srel = bfd_get_section_by_name (dynobj, ".dynrel");
16812159047fSniklas 	  BFD_ASSERT (splt != NULL && srel != NULL);
1682b305b0f1Sespie 
1683b305b0f1Sespie 	  sgot = bfd_get_section_by_name (dynobj, ".got");
1684b305b0f1Sespie 	  BFD_ASSERT (sgot != NULL);
1685b305b0f1Sespie 	  if (sgot->_raw_size == 0)
1686b305b0f1Sespie 	    sgot->_raw_size = BYTES_IN_WORD;
1687c074d1c9Sdrahn 	  sunos_hash_table (info)->got_needed = TRUE;
16882159047fSniklas 	}
16892159047fSniklas 
16902159047fSniklas       BFD_ASSERT ((h->flags & SUNOS_REF_REGULAR) != 0);
16912159047fSniklas       BFD_ASSERT (h->plt_offset != 0
16922159047fSniklas 		  || ((h->root.root.type == bfd_link_hash_defined
16932159047fSniklas 		       || h->root.root.type == bfd_link_hash_defweak)
16942159047fSniklas 		      ? (h->root.root.u.def.section->owner->flags
16952159047fSniklas 			 & DYNAMIC) != 0
16962159047fSniklas 		      : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0));
16972159047fSniklas 
16982159047fSniklas       /* This reloc is against a symbol defined only by a dynamic
16992159047fSniklas 	 object.  */
17002159047fSniklas 
17012159047fSniklas       if (h->root.root.type == bfd_link_hash_undefined)
17022159047fSniklas 	{
17032159047fSniklas 	  /* Presumably this symbol was marked as being undefined by
17042159047fSniklas 	     an earlier reloc.  */
17052159047fSniklas 	  srel->_raw_size += RELOC_STD_SIZE;
17062159047fSniklas 	}
17072159047fSniklas       else if ((h->root.root.u.def.section->flags & SEC_CODE) == 0)
17082159047fSniklas 	{
17092159047fSniklas 	  bfd *sub;
17102159047fSniklas 
17112159047fSniklas 	  /* This reloc is not in the .text section.  It must be
17122159047fSniklas 	     copied into the dynamic relocs.  We mark the symbol as
17132159047fSniklas 	     being undefined.  */
17142159047fSniklas 	  srel->_raw_size += RELOC_STD_SIZE;
17152159047fSniklas 	  sub = h->root.root.u.def.section->owner;
17162159047fSniklas 	  h->root.root.type = bfd_link_hash_undefined;
17172159047fSniklas 	  h->root.root.u.undef.abfd = sub;
17182159047fSniklas 	}
17192159047fSniklas       else
17202159047fSniklas 	{
17212159047fSniklas 	  /* This symbol is in the .text section.  We must give it an
17222159047fSniklas 	     entry in the procedure linkage table, if we have not
17232159047fSniklas 	     already done so.  We change the definition of the symbol
17242159047fSniklas 	     to the .plt section; this will cause relocs against it to
17252159047fSniklas 	     be handled correctly.  */
17262159047fSniklas 	  if (h->plt_offset == 0)
17272159047fSniklas 	    {
17282159047fSniklas 	      if (splt->_raw_size == 0)
17292159047fSniklas 		splt->_raw_size = M68K_PLT_ENTRY_SIZE;
17302159047fSniklas 	      h->plt_offset = splt->_raw_size;
17312159047fSniklas 
17322159047fSniklas 	      if ((h->flags & SUNOS_DEF_REGULAR) == 0)
17332159047fSniklas 		{
17342159047fSniklas 		  h->root.root.u.def.section = splt;
17352159047fSniklas 		  h->root.root.u.def.value = splt->_raw_size;
17362159047fSniklas 		}
17372159047fSniklas 
17382159047fSniklas 	      splt->_raw_size += M68K_PLT_ENTRY_SIZE;
17392159047fSniklas 
17402159047fSniklas 	      /* We may also need a dynamic reloc entry.  */
17412159047fSniklas 	      if ((h->flags & SUNOS_DEF_REGULAR) == 0)
17422159047fSniklas 		srel->_raw_size += RELOC_STD_SIZE;
17432159047fSniklas 	    }
17442159047fSniklas 	}
17452159047fSniklas     }
17462159047fSniklas 
1747c074d1c9Sdrahn   return TRUE;
17482159047fSniklas }
17492159047fSniklas 
17502159047fSniklas /* Scan the relocs for an input section using extended relocs.  We
17512159047fSniklas    need to figure out what to do for each reloc against a dynamic
17522159047fSniklas    symbol.  If the reloc is a WDISP30, and the symbol is in the .text
17532159047fSniklas    section, an entry is made in the procedure linkage table.
17542159047fSniklas    Otherwise, we must preserve the reloc as a dynamic reloc.  */
17552159047fSniklas 
1756c074d1c9Sdrahn static bfd_boolean
sunos_scan_ext_relocs(info,abfd,sec,relocs,rel_size)17572159047fSniklas sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
17582159047fSniklas      struct bfd_link_info *info;
17592159047fSniklas      bfd *abfd;
1760b305b0f1Sespie      asection *sec ATTRIBUTE_UNUSED;
17612159047fSniklas      const struct reloc_ext_external *relocs;
17622159047fSniklas      bfd_size_type rel_size;
17632159047fSniklas {
17642159047fSniklas   bfd *dynobj;
17652159047fSniklas   struct sunos_link_hash_entry **sym_hashes;
17662159047fSniklas   const struct reloc_ext_external *rel, *relend;
17672159047fSniklas   asection *splt = NULL;
17682159047fSniklas   asection *sgot = NULL;
17692159047fSniklas   asection *srel = NULL;
1770c074d1c9Sdrahn   bfd_size_type amt;
17712159047fSniklas 
17722159047fSniklas   /* We only know how to handle SPARC plt entries.  */
17732159047fSniklas   if (bfd_get_arch (abfd) != bfd_arch_sparc)
17742159047fSniklas     {
17752159047fSniklas       bfd_set_error (bfd_error_invalid_target);
1776c074d1c9Sdrahn       return FALSE;
17772159047fSniklas     }
17782159047fSniklas 
17792159047fSniklas   dynobj = NULL;
17802159047fSniklas 
17812159047fSniklas   sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd);
17822159047fSniklas 
17832159047fSniklas   relend = relocs + rel_size / RELOC_EXT_SIZE;
17842159047fSniklas   for (rel = relocs; rel < relend; rel++)
17852159047fSniklas     {
17862159047fSniklas       unsigned int r_index;
17872159047fSniklas       int r_extern;
17882159047fSniklas       int r_type;
17892159047fSniklas       struct sunos_link_hash_entry *h = NULL;
17902159047fSniklas 
17912159047fSniklas       /* Swap in the reloc information.  */
1792c88b1d6cSniklas       if (bfd_header_big_endian (abfd))
17932159047fSniklas 	{
17942159047fSniklas 	  r_index = ((rel->r_index[0] << 16)
17952159047fSniklas 		     | (rel->r_index[1] << 8)
17962159047fSniklas 		     | rel->r_index[2]);
17972159047fSniklas 	  r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
17982159047fSniklas 	  r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
17992159047fSniklas 		    >> RELOC_EXT_BITS_TYPE_SH_BIG);
18002159047fSniklas 	}
18012159047fSniklas       else
18022159047fSniklas 	{
18032159047fSniklas 	  r_index = ((rel->r_index[2] << 16)
18042159047fSniklas 		     | (rel->r_index[1] << 8)
18052159047fSniklas 		     | rel->r_index[0]);
18062159047fSniklas 	  r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
18072159047fSniklas 	  r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
18082159047fSniklas 		    >> RELOC_EXT_BITS_TYPE_SH_LITTLE);
18092159047fSniklas 	}
18102159047fSniklas 
18112159047fSniklas       if (r_extern)
18122159047fSniklas 	{
18132159047fSniklas 	  h = sym_hashes[r_index];
18142159047fSniklas 	  if (h == NULL)
18152159047fSniklas 	    {
18162159047fSniklas 	      /* This should not normally happen, but it will in any
18172159047fSniklas 		 case be caught in the relocation phase.  */
18182159047fSniklas 	      continue;
18192159047fSniklas 	    }
18202159047fSniklas 	}
18212159047fSniklas 
18222159047fSniklas       /* If this is a base relative reloc, we need to make an entry in
18232159047fSniklas 	 the .got section.  */
18242159047fSniklas       if (r_type == RELOC_BASE10
18252159047fSniklas 	  || r_type == RELOC_BASE13
18262159047fSniklas 	  || r_type == RELOC_BASE22)
18272159047fSniklas 	{
18282159047fSniklas 	  if (dynobj == NULL)
18292159047fSniklas 	    {
1830c074d1c9Sdrahn 	      if (! sunos_create_dynamic_sections (abfd, info, FALSE))
1831c074d1c9Sdrahn 		return FALSE;
18322159047fSniklas 	      dynobj = sunos_hash_table (info)->dynobj;
18332159047fSniklas 	      splt = bfd_get_section_by_name (dynobj, ".plt");
18342159047fSniklas 	      sgot = bfd_get_section_by_name (dynobj, ".got");
18352159047fSniklas 	      srel = bfd_get_section_by_name (dynobj, ".dynrel");
18362159047fSniklas 	      BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
1837b305b0f1Sespie 
1838b305b0f1Sespie 	      /* Make sure we have an initial entry in the .got table.  */
1839b305b0f1Sespie 	      if (sgot->_raw_size == 0)
1840b305b0f1Sespie 		sgot->_raw_size = BYTES_IN_WORD;
1841c074d1c9Sdrahn 	      sunos_hash_table (info)->got_needed = TRUE;
18422159047fSniklas 	    }
18432159047fSniklas 
18442159047fSniklas 	  if (r_extern)
18452159047fSniklas 	    {
18462159047fSniklas 	      if (h->got_offset != 0)
18472159047fSniklas 		continue;
18482159047fSniklas 
18492159047fSniklas 	      h->got_offset = sgot->_raw_size;
18502159047fSniklas 	    }
18512159047fSniklas 	  else
18522159047fSniklas 	    {
18532159047fSniklas 	      if (r_index >= bfd_get_symcount (abfd))
18542159047fSniklas 		{
18552159047fSniklas 		  /* This is abnormal, but should be caught in the
18562159047fSniklas 		     relocation phase.  */
18572159047fSniklas 		  continue;
18582159047fSniklas 		}
18592159047fSniklas 
18602159047fSniklas 	      if (adata (abfd).local_got_offsets == NULL)
18612159047fSniklas 		{
1862c074d1c9Sdrahn 		  amt = bfd_get_symcount (abfd);
1863c074d1c9Sdrahn 		  amt *= sizeof (bfd_vma);
18642159047fSniklas 		  adata (abfd).local_got_offsets =
1865c074d1c9Sdrahn 		    (bfd_vma *) bfd_zalloc (abfd, amt);
18662159047fSniklas 		  if (adata (abfd).local_got_offsets == NULL)
1867c074d1c9Sdrahn 		    return FALSE;
18682159047fSniklas 		}
18692159047fSniklas 
18702159047fSniklas 	      if (adata (abfd).local_got_offsets[r_index] != 0)
18712159047fSniklas 		continue;
18722159047fSniklas 
18732159047fSniklas 	      adata (abfd).local_got_offsets[r_index] = sgot->_raw_size;
18742159047fSniklas 	    }
18752159047fSniklas 
18762159047fSniklas 	  sgot->_raw_size += BYTES_IN_WORD;
18772159047fSniklas 
18782159047fSniklas 	  /* If we are making a shared library, or if the symbol is
18792159047fSniklas 	     defined by a dynamic object, we will need a dynamic reloc
18802159047fSniklas 	     entry.  */
18812159047fSniklas 	  if (info->shared
18822159047fSniklas 	      || (h != NULL
18832159047fSniklas 		  && (h->flags & SUNOS_DEF_DYNAMIC) != 0
18842159047fSniklas 		  && (h->flags & SUNOS_DEF_REGULAR) == 0))
18852159047fSniklas 	    srel->_raw_size += RELOC_EXT_SIZE;
18862159047fSniklas 
18872159047fSniklas 	  continue;
18882159047fSniklas 	}
18892159047fSniklas 
18902159047fSniklas       /* Otherwise, we are only interested in relocs against symbols
18912159047fSniklas 	 defined in dynamic objects but not in regular objects.  We
18922159047fSniklas 	 only need to consider relocs against external symbols.  */
18932159047fSniklas       if (! r_extern)
18942159047fSniklas 	{
18952159047fSniklas 	  /* But, if we are creating a shared library, we need to
18962159047fSniklas 	     generate an absolute reloc.  */
18972159047fSniklas 	  if (info->shared)
18982159047fSniklas 	    {
18992159047fSniklas 	      if (dynobj == NULL)
19002159047fSniklas 		{
1901c074d1c9Sdrahn 		  if (! sunos_create_dynamic_sections (abfd, info, TRUE))
1902c074d1c9Sdrahn 		    return FALSE;
19032159047fSniklas 		  dynobj = sunos_hash_table (info)->dynobj;
19042159047fSniklas 		  splt = bfd_get_section_by_name (dynobj, ".plt");
19052159047fSniklas 		  sgot = bfd_get_section_by_name (dynobj, ".got");
19062159047fSniklas 		  srel = bfd_get_section_by_name (dynobj, ".dynrel");
19072159047fSniklas 		  BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
19082159047fSniklas 		}
19092159047fSniklas 
19102159047fSniklas 	      srel->_raw_size += RELOC_EXT_SIZE;
19112159047fSniklas 	    }
19122159047fSniklas 
19132159047fSniklas 	  continue;
19142159047fSniklas 	}
19152159047fSniklas 
19162159047fSniklas       /* At this point common symbols have already been allocated, so
19172159047fSniklas 	 we don't have to worry about them.  We need to consider that
19182159047fSniklas 	 we may have already seen this symbol and marked it undefined;
19192159047fSniklas 	 if the symbol is really undefined, then SUNOS_DEF_DYNAMIC
19202159047fSniklas 	 will be zero.  */
19212159047fSniklas       if (h->root.root.type != bfd_link_hash_defined
19222159047fSniklas 	  && h->root.root.type != bfd_link_hash_defweak
19232159047fSniklas 	  && h->root.root.type != bfd_link_hash_undefined)
19242159047fSniklas 	continue;
19252159047fSniklas 
19262159047fSniklas       if (r_type != RELOC_JMP_TBL
19272159047fSniklas 	  && ! info->shared
19282159047fSniklas 	  && ((h->flags & SUNOS_DEF_DYNAMIC) == 0
19292159047fSniklas 	      || (h->flags & SUNOS_DEF_REGULAR) != 0))
19302159047fSniklas 	continue;
19312159047fSniklas 
1932c88b1d6cSniklas       if (r_type == RELOC_JMP_TBL
1933c88b1d6cSniklas 	  && ! info->shared
1934c88b1d6cSniklas 	  && (h->flags & SUNOS_DEF_DYNAMIC) == 0
1935c88b1d6cSniklas 	  && (h->flags & SUNOS_DEF_REGULAR) == 0)
1936c88b1d6cSniklas 	{
1937c88b1d6cSniklas 	  /* This symbol is apparently undefined.  Don't do anything
1938c88b1d6cSniklas 	     here; just let the relocation routine report an undefined
1939c88b1d6cSniklas 	     symbol.  */
1940c88b1d6cSniklas 	  continue;
1941c88b1d6cSniklas 	}
1942c88b1d6cSniklas 
19432159047fSniklas       if (strcmp (h->root.root.root.string, "__GLOBAL_OFFSET_TABLE_") == 0)
19442159047fSniklas 	continue;
19452159047fSniklas 
19462159047fSniklas       if (dynobj == NULL)
19472159047fSniklas 	{
1948c074d1c9Sdrahn 	  if (! sunos_create_dynamic_sections (abfd, info, FALSE))
1949c074d1c9Sdrahn 	    return FALSE;
19502159047fSniklas 	  dynobj = sunos_hash_table (info)->dynobj;
19512159047fSniklas 	  splt = bfd_get_section_by_name (dynobj, ".plt");
19522159047fSniklas 	  sgot = bfd_get_section_by_name (dynobj, ".got");
19532159047fSniklas 	  srel = bfd_get_section_by_name (dynobj, ".dynrel");
19542159047fSniklas 	  BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
1955b305b0f1Sespie 
1956b305b0f1Sespie 	  /* Make sure we have an initial entry in the .got table.  */
1957b305b0f1Sespie 	  if (sgot->_raw_size == 0)
1958b305b0f1Sespie 	    sgot->_raw_size = BYTES_IN_WORD;
1959c074d1c9Sdrahn 	  sunos_hash_table (info)->got_needed = TRUE;
19602159047fSniklas 	}
19612159047fSniklas 
19622159047fSniklas       BFD_ASSERT (r_type == RELOC_JMP_TBL
1963c88b1d6cSniklas 		  || info->shared
19642159047fSniklas 		  || (h->flags & SUNOS_REF_REGULAR) != 0);
19652159047fSniklas       BFD_ASSERT (r_type == RELOC_JMP_TBL
19662159047fSniklas 		  || info->shared
19672159047fSniklas 		  || h->plt_offset != 0
19682159047fSniklas 		  || ((h->root.root.type == bfd_link_hash_defined
19692159047fSniklas 		       || h->root.root.type == bfd_link_hash_defweak)
19702159047fSniklas 		      ? (h->root.root.u.def.section->owner->flags
19712159047fSniklas 			 & DYNAMIC) != 0
19722159047fSniklas 		      : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0));
19732159047fSniklas 
19742159047fSniklas       /* This reloc is against a symbol defined only by a dynamic
19752159047fSniklas 	 object, or it is a jump table reloc from PIC compiled code.  */
19762159047fSniklas 
19772159047fSniklas       if (r_type != RELOC_JMP_TBL
19782159047fSniklas 	  && h->root.root.type == bfd_link_hash_undefined)
19792159047fSniklas 	{
19802159047fSniklas 	  /* Presumably this symbol was marked as being undefined by
19812159047fSniklas 	     an earlier reloc.  */
19822159047fSniklas 	  srel->_raw_size += RELOC_EXT_SIZE;
19832159047fSniklas 	}
19842159047fSniklas       else if (r_type != RELOC_JMP_TBL
19852159047fSniklas 	       && (h->root.root.u.def.section->flags & SEC_CODE) == 0)
19862159047fSniklas 	{
19872159047fSniklas 	  bfd *sub;
19882159047fSniklas 
19892159047fSniklas 	  /* This reloc is not in the .text section.  It must be
19902159047fSniklas 	     copied into the dynamic relocs.  We mark the symbol as
19912159047fSniklas 	     being undefined.  */
19922159047fSniklas 	  srel->_raw_size += RELOC_EXT_SIZE;
19932159047fSniklas 	  if ((h->flags & SUNOS_DEF_REGULAR) == 0)
19942159047fSniklas 	    {
19952159047fSniklas 	      sub = h->root.root.u.def.section->owner;
19962159047fSniklas 	      h->root.root.type = bfd_link_hash_undefined;
19972159047fSniklas 	      h->root.root.u.undef.abfd = sub;
19982159047fSniklas 	    }
19992159047fSniklas 	}
20002159047fSniklas       else
20012159047fSniklas 	{
20022159047fSniklas 	  /* This symbol is in the .text section.  We must give it an
20032159047fSniklas 	     entry in the procedure linkage table, if we have not
20042159047fSniklas 	     already done so.  We change the definition of the symbol
20052159047fSniklas 	     to the .plt section; this will cause relocs against it to
20062159047fSniklas 	     be handled correctly.  */
20072159047fSniklas 	  if (h->plt_offset == 0)
20082159047fSniklas 	    {
20092159047fSniklas 	      if (splt->_raw_size == 0)
20102159047fSniklas 		splt->_raw_size = SPARC_PLT_ENTRY_SIZE;
20112159047fSniklas 	      h->plt_offset = splt->_raw_size;
20122159047fSniklas 
20132159047fSniklas 	      if ((h->flags & SUNOS_DEF_REGULAR) == 0)
20142159047fSniklas 		{
20152159047fSniklas 		  if (h->root.root.type == bfd_link_hash_undefined)
20162159047fSniklas 		    h->root.root.type = bfd_link_hash_defined;
20172159047fSniklas 		  h->root.root.u.def.section = splt;
20182159047fSniklas 		  h->root.root.u.def.value = splt->_raw_size;
20192159047fSniklas 		}
20202159047fSniklas 
20212159047fSniklas 	      splt->_raw_size += SPARC_PLT_ENTRY_SIZE;
20222159047fSniklas 
20232159047fSniklas 	      /* We will also need a dynamic reloc entry, unless this
20242159047fSniklas 		 is a JMP_TBL reloc produced by linking PIC compiled
20252159047fSniklas 		 code, and we are not making a shared library.  */
20262159047fSniklas 	      if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
20272159047fSniklas 		srel->_raw_size += RELOC_EXT_SIZE;
20282159047fSniklas 	    }
20292159047fSniklas 
20302159047fSniklas 	  /* If we are creating a shared library, we need to copy over
20312159047fSniklas 	     any reloc other than a jump table reloc.  */
20322159047fSniklas 	  if (info->shared && r_type != RELOC_JMP_TBL)
20332159047fSniklas 	    srel->_raw_size += RELOC_EXT_SIZE;
20342159047fSniklas 	}
20352159047fSniklas     }
20362159047fSniklas 
2037c074d1c9Sdrahn   return TRUE;
20382159047fSniklas }
20392159047fSniklas 
20402159047fSniklas /* Build the hash table of dynamic symbols, and to mark as written all
20412159047fSniklas    symbols from dynamic objects which we do not plan to write out.  */
20422159047fSniklas 
2043c074d1c9Sdrahn static bfd_boolean
sunos_scan_dynamic_symbol(h,data)20442159047fSniklas sunos_scan_dynamic_symbol (h, data)
20452159047fSniklas      struct sunos_link_hash_entry *h;
20462159047fSniklas      PTR data;
20472159047fSniklas {
20482159047fSniklas   struct bfd_link_info *info = (struct bfd_link_info *) data;
20492159047fSniklas 
2050c074d1c9Sdrahn   if (h->root.root.type == bfd_link_hash_warning)
2051c074d1c9Sdrahn     h = (struct sunos_link_hash_entry *) h->root.root.u.i.link;
2052c074d1c9Sdrahn 
20532159047fSniklas   /* Set the written flag for symbols we do not want to write out as
20542159047fSniklas      part of the regular symbol table.  This is all symbols which are
20552159047fSniklas      not defined in a regular object file.  For some reason symbols
20562159047fSniklas      which are referenced by a regular object and defined by a dynamic
2057c88b1d6cSniklas      object do not seem to show up in the regular symbol table.  It is
2058c88b1d6cSniklas      possible for a symbol to have only SUNOS_REF_REGULAR set here, it
2059c88b1d6cSniklas      is an undefined symbol which was turned into a common symbol
2060c88b1d6cSniklas      because it was found in an archive object which was not included
2061c88b1d6cSniklas      in the link.  */
20622159047fSniklas   if ((h->flags & SUNOS_DEF_REGULAR) == 0
2063c88b1d6cSniklas       && (h->flags & SUNOS_DEF_DYNAMIC) != 0
20642159047fSniklas       && strcmp (h->root.root.root.string, "__DYNAMIC") != 0)
2065c074d1c9Sdrahn     h->root.written = TRUE;
20662159047fSniklas 
20672159047fSniklas   /* If this symbol is defined by a dynamic object and referenced by a
20682159047fSniklas      regular object, see whether we gave it a reasonable value while
20692159047fSniklas      scanning the relocs.  */
20702159047fSniklas 
20712159047fSniklas   if ((h->flags & SUNOS_DEF_REGULAR) == 0
20722159047fSniklas       && (h->flags & SUNOS_DEF_DYNAMIC) != 0
20732159047fSniklas       && (h->flags & SUNOS_REF_REGULAR) != 0)
20742159047fSniklas     {
20752159047fSniklas       if ((h->root.root.type == bfd_link_hash_defined
20762159047fSniklas 	   || h->root.root.type == bfd_link_hash_defweak)
20772159047fSniklas 	  && ((h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
20782159047fSniklas 	  && h->root.root.u.def.section->output_section == NULL)
20792159047fSniklas 	{
20802159047fSniklas 	  bfd *sub;
20812159047fSniklas 
20822159047fSniklas 	  /* This symbol is currently defined in a dynamic section
20832159047fSniklas 	     which is not being put into the output file.  This
20842159047fSniklas 	     implies that there is no reloc against the symbol.  I'm
20852159047fSniklas 	     not sure why this case would ever occur.  In any case, we
20862159047fSniklas 	     change the symbol to be undefined.  */
20872159047fSniklas 	  sub = h->root.root.u.def.section->owner;
20882159047fSniklas 	  h->root.root.type = bfd_link_hash_undefined;
20892159047fSniklas 	  h->root.root.u.undef.abfd = sub;
20902159047fSniklas 	}
20912159047fSniklas     }
20922159047fSniklas 
20932159047fSniklas   /* If this symbol is defined or referenced by a regular file, add it
20942159047fSniklas      to the dynamic symbols.  */
20952159047fSniklas   if ((h->flags & (SUNOS_DEF_REGULAR | SUNOS_REF_REGULAR)) != 0)
20962159047fSniklas     {
20972159047fSniklas       asection *s;
20982159047fSniklas       size_t len;
20992159047fSniklas       bfd_byte *contents;
21002159047fSniklas       unsigned char *name;
21012159047fSniklas       unsigned long hash;
21022159047fSniklas       bfd *dynobj;
21032159047fSniklas 
21042159047fSniklas       BFD_ASSERT (h->dynindx == -2);
21052159047fSniklas 
21062159047fSniklas       dynobj = sunos_hash_table (info)->dynobj;
21072159047fSniklas 
21082159047fSniklas       h->dynindx = sunos_hash_table (info)->dynsymcount;
21092159047fSniklas       ++sunos_hash_table (info)->dynsymcount;
21102159047fSniklas 
21112159047fSniklas       len = strlen (h->root.root.root.string);
21122159047fSniklas 
21132159047fSniklas       /* We don't bother to construct a BFD hash table for the strings
21142159047fSniklas 	 which are the names of the dynamic symbols.  Using a hash
21152159047fSniklas 	 table for the regular symbols is beneficial, because the
21162159047fSniklas 	 regular symbols includes the debugging symbols, which have
21172159047fSniklas 	 long names and are often duplicated in several object files.
21182159047fSniklas 	 There are no debugging symbols in the dynamic symbols.  */
21192159047fSniklas       s = bfd_get_section_by_name (dynobj, ".dynstr");
21202159047fSniklas       BFD_ASSERT (s != NULL);
2121c88b1d6cSniklas       contents = (bfd_byte *) bfd_realloc (s->contents,
2122c88b1d6cSniklas 					   s->_raw_size + len + 1);
21232159047fSniklas       if (contents == NULL)
2124c074d1c9Sdrahn 	return FALSE;
21252159047fSniklas       s->contents = contents;
21262159047fSniklas 
21272159047fSniklas       h->dynstr_index = s->_raw_size;
2128b305b0f1Sespie       strcpy ((char *) contents + s->_raw_size, h->root.root.root.string);
21292159047fSniklas       s->_raw_size += len + 1;
21302159047fSniklas 
21312159047fSniklas       /* Add it to the dynamic hash table.  */
21322159047fSniklas       name = (unsigned char *) h->root.root.root.string;
21332159047fSniklas       hash = 0;
21342159047fSniklas       while (*name != '\0')
21352159047fSniklas 	hash = (hash << 1) + *name++;
21362159047fSniklas       hash &= 0x7fffffff;
21372159047fSniklas       hash %= sunos_hash_table (info)->bucketcount;
21382159047fSniklas 
21392159047fSniklas       s = bfd_get_section_by_name (dynobj, ".hash");
21402159047fSniklas       BFD_ASSERT (s != NULL);
21412159047fSniklas 
21422159047fSniklas       if (GET_SWORD (dynobj, s->contents + hash * HASH_ENTRY_SIZE) == -1)
21432159047fSniklas 	PUT_WORD (dynobj, h->dynindx, s->contents + hash * HASH_ENTRY_SIZE);
21442159047fSniklas       else
21452159047fSniklas 	{
21462159047fSniklas 	  bfd_vma next;
21472159047fSniklas 
21482159047fSniklas 	  next = GET_WORD (dynobj,
21492159047fSniklas 			   (s->contents
21502159047fSniklas 			    + hash * HASH_ENTRY_SIZE
21512159047fSniklas 			    + BYTES_IN_WORD));
21522159047fSniklas 	  PUT_WORD (dynobj, s->_raw_size / HASH_ENTRY_SIZE,
21532159047fSniklas 		    s->contents + hash * HASH_ENTRY_SIZE + BYTES_IN_WORD);
21542159047fSniklas 	  PUT_WORD (dynobj, h->dynindx, s->contents + s->_raw_size);
21552159047fSniklas 	  PUT_WORD (dynobj, next, s->contents + s->_raw_size + BYTES_IN_WORD);
21562159047fSniklas 	  s->_raw_size += HASH_ENTRY_SIZE;
21572159047fSniklas 	}
21582159047fSniklas     }
21592159047fSniklas 
2160c074d1c9Sdrahn   return TRUE;
21612159047fSniklas }
21622159047fSniklas 
21632159047fSniklas /* Link a dynamic object.  We actually don't have anything to do at
21642159047fSniklas    this point.  This entry point exists to prevent the regular linker
21652159047fSniklas    code from doing anything with the object.  */
21662159047fSniklas 
2167c074d1c9Sdrahn static bfd_boolean
sunos_link_dynamic_object(info,abfd)21682159047fSniklas sunos_link_dynamic_object (info, abfd)
2169b305b0f1Sespie      struct bfd_link_info *info ATTRIBUTE_UNUSED;
2170b305b0f1Sespie      bfd *abfd ATTRIBUTE_UNUSED;
21712159047fSniklas {
2172c074d1c9Sdrahn   return TRUE;
21732159047fSniklas }
21742159047fSniklas 
21752159047fSniklas /* Write out a dynamic symbol.  This is called by the final traversal
21762159047fSniklas    over the symbol table.  */
21772159047fSniklas 
2178c074d1c9Sdrahn static bfd_boolean
sunos_write_dynamic_symbol(output_bfd,info,harg)21792159047fSniklas sunos_write_dynamic_symbol (output_bfd, info, harg)
21802159047fSniklas      bfd *output_bfd;
21812159047fSniklas      struct bfd_link_info *info;
21822159047fSniklas      struct aout_link_hash_entry *harg;
21832159047fSniklas {
21842159047fSniklas   struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg;
21852159047fSniklas   int type;
21862159047fSniklas   bfd_vma val;
21872159047fSniklas   asection *s;
21882159047fSniklas   struct external_nlist *outsym;
21892159047fSniklas 
2190b305b0f1Sespie   /* If this symbol is in the procedure linkage table, fill in the
2191b305b0f1Sespie      table entry.  */
2192b305b0f1Sespie   if (h->plt_offset != 0)
2193b305b0f1Sespie     {
2194b305b0f1Sespie       bfd *dynobj;
2195b305b0f1Sespie       asection *splt;
2196b305b0f1Sespie       bfd_byte *p;
2197b305b0f1Sespie       bfd_vma r_address;
2198b305b0f1Sespie 
2199b305b0f1Sespie       dynobj = sunos_hash_table (info)->dynobj;
2200b305b0f1Sespie       splt = bfd_get_section_by_name (dynobj, ".plt");
2201b305b0f1Sespie       p = splt->contents + h->plt_offset;
2202b305b0f1Sespie 
2203b305b0f1Sespie       s = bfd_get_section_by_name (dynobj, ".dynrel");
2204b305b0f1Sespie 
2205b305b0f1Sespie       r_address = (splt->output_section->vma
2206b305b0f1Sespie 		   + splt->output_offset
2207b305b0f1Sespie 		   + h->plt_offset);
2208b305b0f1Sespie 
2209b305b0f1Sespie       switch (bfd_get_arch (output_bfd))
2210b305b0f1Sespie 	{
2211b305b0f1Sespie 	case bfd_arch_sparc:
2212b305b0f1Sespie 	  if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
2213b305b0f1Sespie 	    {
2214b305b0f1Sespie 	      bfd_put_32 (output_bfd, SPARC_PLT_ENTRY_WORD0, p);
2215b305b0f1Sespie 	      bfd_put_32 (output_bfd,
2216b305b0f1Sespie 			  (SPARC_PLT_ENTRY_WORD1
2217b305b0f1Sespie 			   + (((- (h->plt_offset + 4) >> 2)
2218b305b0f1Sespie 			       & 0x3fffffff))),
2219b305b0f1Sespie 			  p + 4);
2220b305b0f1Sespie 	      bfd_put_32 (output_bfd, SPARC_PLT_ENTRY_WORD2 + s->reloc_count,
2221b305b0f1Sespie 			  p + 8);
2222b305b0f1Sespie 	    }
2223b305b0f1Sespie 	  else
2224b305b0f1Sespie 	    {
2225b305b0f1Sespie 	      val = (h->root.root.u.def.section->output_section->vma
2226b305b0f1Sespie 		     + h->root.root.u.def.section->output_offset
2227b305b0f1Sespie 		     + h->root.root.u.def.value);
2228b305b0f1Sespie 	      bfd_put_32 (output_bfd,
2229b305b0f1Sespie 			  SPARC_PLT_PIC_WORD0 + ((val >> 10) & 0x3fffff),
2230b305b0f1Sespie 			  p);
2231b305b0f1Sespie 	      bfd_put_32 (output_bfd,
2232b305b0f1Sespie 			  SPARC_PLT_PIC_WORD1 + (val & 0x3ff),
2233b305b0f1Sespie 			  p + 4);
2234b305b0f1Sespie 	      bfd_put_32 (output_bfd, SPARC_PLT_PIC_WORD2, p + 8);
2235b305b0f1Sespie 	    }
2236b305b0f1Sespie 	  break;
2237b305b0f1Sespie 
2238b305b0f1Sespie 	case bfd_arch_m68k:
2239b305b0f1Sespie 	  if (! info->shared && (h->flags & SUNOS_DEF_REGULAR) != 0)
2240b305b0f1Sespie 	    abort ();
2241b305b0f1Sespie 	  bfd_put_16 (output_bfd, M68K_PLT_ENTRY_WORD0, p);
2242b305b0f1Sespie 	  bfd_put_32 (output_bfd, (- (h->plt_offset + 2)), p + 2);
2243c074d1c9Sdrahn 	  bfd_put_16 (output_bfd, (bfd_vma) s->reloc_count, p + 6);
2244b305b0f1Sespie 	  r_address += 2;
2245b305b0f1Sespie 	  break;
2246b305b0f1Sespie 
2247b305b0f1Sespie 	default:
2248b305b0f1Sespie 	  abort ();
2249b305b0f1Sespie 	}
2250b305b0f1Sespie 
2251b305b0f1Sespie       /* We also need to add a jump table reloc, unless this is the
2252b305b0f1Sespie 	 result of a JMP_TBL reloc from PIC compiled code.  */
2253b305b0f1Sespie       if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
2254b305b0f1Sespie 	{
2255b305b0f1Sespie 	  BFD_ASSERT (h->dynindx >= 0);
2256b305b0f1Sespie 	  BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
2257b305b0f1Sespie 		      < s->_raw_size);
2258b305b0f1Sespie 	  p = s->contents + s->reloc_count * obj_reloc_entry_size (output_bfd);
2259b305b0f1Sespie 	  if (obj_reloc_entry_size (output_bfd) == RELOC_STD_SIZE)
2260b305b0f1Sespie 	    {
2261b305b0f1Sespie 	      struct reloc_std_external *srel;
2262b305b0f1Sespie 
2263b305b0f1Sespie 	      srel = (struct reloc_std_external *) p;
2264b305b0f1Sespie 	      PUT_WORD (output_bfd, r_address, srel->r_address);
2265b305b0f1Sespie 	      if (bfd_header_big_endian (output_bfd))
2266b305b0f1Sespie 		{
2267b305b0f1Sespie 		  srel->r_index[0] = (bfd_byte) (h->dynindx >> 16);
2268b305b0f1Sespie 		  srel->r_index[1] = (bfd_byte) (h->dynindx >> 8);
2269b305b0f1Sespie 		  srel->r_index[2] = (bfd_byte) (h->dynindx);
2270b305b0f1Sespie 		  srel->r_type[0] = (RELOC_STD_BITS_EXTERN_BIG
2271b305b0f1Sespie 				     | RELOC_STD_BITS_JMPTABLE_BIG);
2272b305b0f1Sespie 		}
2273b305b0f1Sespie 	      else
2274b305b0f1Sespie 		{
2275b305b0f1Sespie 		  srel->r_index[2] = (bfd_byte) (h->dynindx >> 16);
2276b305b0f1Sespie 		  srel->r_index[1] = (bfd_byte) (h->dynindx >> 8);
2277b305b0f1Sespie 		  srel->r_index[0] = (bfd_byte)h->dynindx;
2278b305b0f1Sespie 		  srel->r_type[0] = (RELOC_STD_BITS_EXTERN_LITTLE
2279b305b0f1Sespie 				     | RELOC_STD_BITS_JMPTABLE_LITTLE);
2280b305b0f1Sespie 		}
2281b305b0f1Sespie 	    }
2282b305b0f1Sespie 	  else
2283b305b0f1Sespie 	    {
2284b305b0f1Sespie 	      struct reloc_ext_external *erel;
2285b305b0f1Sespie 
2286b305b0f1Sespie 	      erel = (struct reloc_ext_external *) p;
2287b305b0f1Sespie 	      PUT_WORD (output_bfd, r_address, erel->r_address);
2288b305b0f1Sespie 	      if (bfd_header_big_endian (output_bfd))
2289b305b0f1Sespie 		{
2290b305b0f1Sespie 		  erel->r_index[0] = (bfd_byte) (h->dynindx >> 16);
2291b305b0f1Sespie 		  erel->r_index[1] = (bfd_byte) (h->dynindx >> 8);
2292b305b0f1Sespie 		  erel->r_index[2] = (bfd_byte)h->dynindx;
2293b305b0f1Sespie 		  erel->r_type[0] =
2294b305b0f1Sespie 		    (RELOC_EXT_BITS_EXTERN_BIG
2295b305b0f1Sespie 		     | (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_BIG));
2296b305b0f1Sespie 		}
2297b305b0f1Sespie 	      else
2298b305b0f1Sespie 		{
2299b305b0f1Sespie 		  erel->r_index[2] = (bfd_byte) (h->dynindx >> 16);
2300b305b0f1Sespie 		  erel->r_index[1] = (bfd_byte) (h->dynindx >> 8);
2301b305b0f1Sespie 		  erel->r_index[0] = (bfd_byte)h->dynindx;
2302b305b0f1Sespie 		  erel->r_type[0] =
2303b305b0f1Sespie 		    (RELOC_EXT_BITS_EXTERN_LITTLE
2304b305b0f1Sespie 		     | (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_LITTLE));
2305b305b0f1Sespie 		}
2306b305b0f1Sespie 	      PUT_WORD (output_bfd, (bfd_vma) 0, erel->r_addend);
2307b305b0f1Sespie 	    }
2308b305b0f1Sespie 
2309b305b0f1Sespie 	  ++s->reloc_count;
2310b305b0f1Sespie 	}
2311b305b0f1Sespie     }
2312b305b0f1Sespie 
2313b305b0f1Sespie   /* If this is not a dynamic symbol, we don't have to do anything
2314b305b0f1Sespie      else.  We only check this after handling the PLT entry, because
2315b305b0f1Sespie      we can have a PLT entry for a nondynamic symbol when linking PIC
2316b305b0f1Sespie      compiled code from a regular object.  */
23172159047fSniklas   if (h->dynindx < 0)
2318c074d1c9Sdrahn     return TRUE;
23192159047fSniklas 
23202159047fSniklas   switch (h->root.root.type)
23212159047fSniklas     {
23222159047fSniklas     default:
23232159047fSniklas     case bfd_link_hash_new:
23242159047fSniklas       abort ();
23252159047fSniklas       /* Avoid variable not initialized warnings.  */
2326c074d1c9Sdrahn       return TRUE;
23272159047fSniklas     case bfd_link_hash_undefined:
23282159047fSniklas       type = N_UNDF | N_EXT;
23292159047fSniklas       val = 0;
23302159047fSniklas       break;
23312159047fSniklas     case bfd_link_hash_defined:
23322159047fSniklas     case bfd_link_hash_defweak:
23332159047fSniklas       {
23342159047fSniklas 	asection *sec;
23352159047fSniklas 	asection *output_section;
23362159047fSniklas 
23372159047fSniklas 	sec = h->root.root.u.def.section;
23382159047fSniklas 	output_section = sec->output_section;
23392159047fSniklas 	BFD_ASSERT (bfd_is_abs_section (output_section)
23402159047fSniklas 		    || output_section->owner == output_bfd);
23412159047fSniklas 	if (h->plt_offset != 0
23422159047fSniklas 	    && (h->flags & SUNOS_DEF_REGULAR) == 0)
23432159047fSniklas 	  {
23442159047fSniklas 	    type = N_UNDF | N_EXT;
23452159047fSniklas 	    val = 0;
23462159047fSniklas 	  }
23472159047fSniklas 	else
23482159047fSniklas 	  {
23492159047fSniklas 	    if (output_section == obj_textsec (output_bfd))
23502159047fSniklas 	      type = (h->root.root.type == bfd_link_hash_defined
23512159047fSniklas 		      ? N_TEXT
23522159047fSniklas 		      : N_WEAKT);
23532159047fSniklas 	    else if (output_section == obj_datasec (output_bfd))
23542159047fSniklas 	      type = (h->root.root.type == bfd_link_hash_defined
23552159047fSniklas 		      ? N_DATA
23562159047fSniklas 		      : N_WEAKD);
23572159047fSniklas 	    else if (output_section == obj_bsssec (output_bfd))
23582159047fSniklas 	      type = (h->root.root.type == bfd_link_hash_defined
23592159047fSniklas 		      ? N_BSS
23602159047fSniklas 		      : N_WEAKB);
23612159047fSniklas 	    else
23622159047fSniklas 	      type = (h->root.root.type == bfd_link_hash_defined
23632159047fSniklas 		      ? N_ABS
23642159047fSniklas 		      : N_WEAKA);
23652159047fSniklas 	    type |= N_EXT;
23662159047fSniklas 	    val = (h->root.root.u.def.value
23672159047fSniklas 		   + output_section->vma
23682159047fSniklas 		   + sec->output_offset);
23692159047fSniklas 	  }
23702159047fSniklas       }
23712159047fSniklas       break;
23722159047fSniklas     case bfd_link_hash_common:
23732159047fSniklas       type = N_UNDF | N_EXT;
23742159047fSniklas       val = h->root.root.u.c.size;
23752159047fSniklas       break;
23762159047fSniklas     case bfd_link_hash_undefweak:
23772159047fSniklas       type = N_WEAKU;
23782159047fSniklas       val = 0;
23792159047fSniklas       break;
23802159047fSniklas     case bfd_link_hash_indirect:
23812159047fSniklas     case bfd_link_hash_warning:
23822159047fSniklas       /* FIXME: Ignore these for now.  The circumstances under which
23832159047fSniklas 	 they should be written out are not clear to me.  */
2384c074d1c9Sdrahn       return TRUE;
23852159047fSniklas     }
23862159047fSniklas 
23872159047fSniklas   s = bfd_get_section_by_name (sunos_hash_table (info)->dynobj, ".dynsym");
23882159047fSniklas   BFD_ASSERT (s != NULL);
23892159047fSniklas   outsym = ((struct external_nlist *)
23902159047fSniklas 	    (s->contents + h->dynindx * EXTERNAL_NLIST_SIZE));
23912159047fSniklas 
2392c074d1c9Sdrahn   H_PUT_8 (output_bfd, type, outsym->e_type);
2393c074d1c9Sdrahn   H_PUT_8 (output_bfd, 0, outsym->e_other);
23942159047fSniklas 
23952159047fSniklas   /* FIXME: The native linker doesn't use 0 for desc.  It seems to use
23962159047fSniklas      one less than the desc value in the shared library, although that
23972159047fSniklas      seems unlikely.  */
2398c074d1c9Sdrahn   H_PUT_16 (output_bfd, 0, outsym->e_desc);
23992159047fSniklas 
24002159047fSniklas   PUT_WORD (output_bfd, h->dynstr_index, outsym->e_strx);
24012159047fSniklas   PUT_WORD (output_bfd, val, outsym->e_value);
24022159047fSniklas 
2403c074d1c9Sdrahn   return TRUE;
24042159047fSniklas }
24052159047fSniklas 
24062159047fSniklas /* This is called for each reloc against an external symbol.  If this
24072159047fSniklas    is a reloc which are are going to copy as a dynamic reloc, then
24082159047fSniklas    copy it over, and tell the caller to not bother processing this
24092159047fSniklas    reloc.  */
24102159047fSniklas 
2411c074d1c9Sdrahn static bfd_boolean
sunos_check_dynamic_reloc(info,input_bfd,input_section,harg,reloc,contents,skip,relocationp)24122159047fSniklas sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
24132159047fSniklas 			   contents, skip, relocationp)
24142159047fSniklas      struct bfd_link_info *info;
24152159047fSniklas      bfd *input_bfd;
24162159047fSniklas      asection *input_section;
24172159047fSniklas      struct aout_link_hash_entry *harg;
24182159047fSniklas      PTR reloc;
2419b305b0f1Sespie      bfd_byte *contents ATTRIBUTE_UNUSED;
2420c074d1c9Sdrahn      bfd_boolean *skip;
24212159047fSniklas      bfd_vma *relocationp;
24222159047fSniklas {
24232159047fSniklas   struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg;
24242159047fSniklas   bfd *dynobj;
2425c074d1c9Sdrahn   bfd_boolean baserel;
2426c074d1c9Sdrahn   bfd_boolean jmptbl;
2427c074d1c9Sdrahn   bfd_boolean pcrel;
24282159047fSniklas   asection *s;
24292159047fSniklas   bfd_byte *p;
24302159047fSniklas   long indx;
24312159047fSniklas 
2432c074d1c9Sdrahn   *skip = FALSE;
24332159047fSniklas 
24342159047fSniklas   dynobj = sunos_hash_table (info)->dynobj;
24352159047fSniklas 
2436b305b0f1Sespie   if (h != NULL
2437b305b0f1Sespie       && h->plt_offset != 0
2438b305b0f1Sespie       && (info->shared
2439b305b0f1Sespie 	  || (h->flags & SUNOS_DEF_REGULAR) == 0))
24402159047fSniklas     {
24412159047fSniklas       asection *splt;
24422159047fSniklas 
24432159047fSniklas       /* Redirect the relocation to the PLT entry.  */
24442159047fSniklas       splt = bfd_get_section_by_name (dynobj, ".plt");
24452159047fSniklas       *relocationp = (splt->output_section->vma
24462159047fSniklas 		      + splt->output_offset
24472159047fSniklas 		      + h->plt_offset);
24482159047fSniklas     }
24492159047fSniklas 
24502159047fSniklas   if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE)
24512159047fSniklas     {
24522159047fSniklas       struct reloc_std_external *srel;
24532159047fSniklas 
24542159047fSniklas       srel = (struct reloc_std_external *) reloc;
2455c88b1d6cSniklas       if (bfd_header_big_endian (input_bfd))
24562159047fSniklas 	{
24572159047fSniklas 	  baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
24582159047fSniklas 	  jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
2459b305b0f1Sespie 	  pcrel = (0 != (srel->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
24602159047fSniklas 	}
24612159047fSniklas       else
24622159047fSniklas 	{
24632159047fSniklas 	  baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
24642159047fSniklas 	  jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
2465b305b0f1Sespie 	  pcrel = (0 != (srel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
24662159047fSniklas 	}
24672159047fSniklas     }
24682159047fSniklas   else
24692159047fSniklas     {
24702159047fSniklas       struct reloc_ext_external *erel;
24712159047fSniklas       int r_type;
24722159047fSniklas 
24732159047fSniklas       erel = (struct reloc_ext_external *) reloc;
2474c88b1d6cSniklas       if (bfd_header_big_endian (input_bfd))
24752159047fSniklas 	r_type = ((erel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
24762159047fSniklas 		  >> RELOC_EXT_BITS_TYPE_SH_BIG);
24772159047fSniklas       else
24782159047fSniklas 	r_type = ((erel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
24792159047fSniklas 		  >> RELOC_EXT_BITS_TYPE_SH_LITTLE);
24802159047fSniklas       baserel = (r_type == RELOC_BASE10
24812159047fSniklas 		 || r_type == RELOC_BASE13
24822159047fSniklas 		 || r_type == RELOC_BASE22);
24832159047fSniklas       jmptbl = r_type == RELOC_JMP_TBL;
2484b305b0f1Sespie       pcrel = (r_type == RELOC_DISP8
2485b305b0f1Sespie 	       || r_type == RELOC_DISP16
2486b305b0f1Sespie 	       || r_type == RELOC_DISP32
2487b305b0f1Sespie 	       || r_type == RELOC_WDISP30
2488b305b0f1Sespie 	       || r_type == RELOC_WDISP22);
2489b305b0f1Sespie       /* We don't consider the PC10 and PC22 types to be PC relative,
2490b305b0f1Sespie 	 because they are pcrel_offset.  */
24912159047fSniklas     }
24922159047fSniklas 
24932159047fSniklas   if (baserel)
24942159047fSniklas     {
24952159047fSniklas       bfd_vma *got_offsetp;
24962159047fSniklas       asection *sgot;
24972159047fSniklas 
24982159047fSniklas       if (h != NULL)
24992159047fSniklas 	got_offsetp = &h->got_offset;
25002159047fSniklas       else if (adata (input_bfd).local_got_offsets == NULL)
25012159047fSniklas 	got_offsetp = NULL;
25022159047fSniklas       else
25032159047fSniklas 	{
25042159047fSniklas 	  struct reloc_std_external *srel;
25052159047fSniklas 	  int r_index;
25062159047fSniklas 
25072159047fSniklas 	  srel = (struct reloc_std_external *) reloc;
25082159047fSniklas 	  if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE)
25092159047fSniklas 	    {
2510c88b1d6cSniklas 	      if (bfd_header_big_endian (input_bfd))
25112159047fSniklas 		r_index = ((srel->r_index[0] << 16)
25122159047fSniklas 			   | (srel->r_index[1] << 8)
25132159047fSniklas 			   | srel->r_index[2]);
25142159047fSniklas 	      else
25152159047fSniklas 		r_index = ((srel->r_index[2] << 16)
25162159047fSniklas 			   | (srel->r_index[1] << 8)
25172159047fSniklas 			   | srel->r_index[0]);
25182159047fSniklas 	    }
25192159047fSniklas 	  else
25202159047fSniklas 	    {
25212159047fSniklas 	      struct reloc_ext_external *erel;
25222159047fSniklas 
25232159047fSniklas 	      erel = (struct reloc_ext_external *) reloc;
2524c88b1d6cSniklas 	      if (bfd_header_big_endian (input_bfd))
25252159047fSniklas 		r_index = ((erel->r_index[0] << 16)
25262159047fSniklas 			   | (erel->r_index[1] << 8)
25272159047fSniklas 			   | erel->r_index[2]);
25282159047fSniklas 	      else
25292159047fSniklas 		r_index = ((erel->r_index[2] << 16)
25302159047fSniklas 			   | (erel->r_index[1] << 8)
25312159047fSniklas 			   | erel->r_index[0]);
25322159047fSniklas 	    }
25332159047fSniklas 
25342159047fSniklas 	  got_offsetp = adata (input_bfd).local_got_offsets + r_index;
25352159047fSniklas 	}
25362159047fSniklas 
25372159047fSniklas       BFD_ASSERT (got_offsetp != NULL && *got_offsetp != 0);
25382159047fSniklas 
25392159047fSniklas       sgot = bfd_get_section_by_name (dynobj, ".got");
25402159047fSniklas 
25412159047fSniklas       /* We set the least significant bit to indicate whether we have
25422159047fSniklas 	 already initialized the GOT entry.  */
25432159047fSniklas       if ((*got_offsetp & 1) == 0)
25442159047fSniklas 	{
25452159047fSniklas 	  if (h == NULL
25462159047fSniklas 	      || (! info->shared
25472159047fSniklas 		  && ((h->flags & SUNOS_DEF_DYNAMIC) == 0
25482159047fSniklas 		      || (h->flags & SUNOS_DEF_REGULAR) != 0)))
25492159047fSniklas 	    PUT_WORD (dynobj, *relocationp, sgot->contents + *got_offsetp);
25502159047fSniklas 	  else
25512159047fSniklas 	    PUT_WORD (dynobj, 0, sgot->contents + *got_offsetp);
25522159047fSniklas 
25532159047fSniklas 	  if (info->shared
25542159047fSniklas 	      || (h != NULL
25552159047fSniklas 		  && (h->flags & SUNOS_DEF_DYNAMIC) != 0
25562159047fSniklas 		  && (h->flags & SUNOS_DEF_REGULAR) == 0))
25572159047fSniklas 	    {
25582159047fSniklas 	      /* We need to create a GLOB_DAT or 32 reloc to tell the
25592159047fSniklas 		 dynamic linker to fill in this entry in the table.  */
25602159047fSniklas 
25612159047fSniklas 	      s = bfd_get_section_by_name (dynobj, ".dynrel");
25622159047fSniklas 	      BFD_ASSERT (s != NULL);
25632159047fSniklas 	      BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
25642159047fSniklas 			  < s->_raw_size);
25652159047fSniklas 
25662159047fSniklas 	      p = (s->contents
25672159047fSniklas 		   + s->reloc_count * obj_reloc_entry_size (dynobj));
25682159047fSniklas 
25692159047fSniklas 	      if (h != NULL)
25702159047fSniklas 		indx = h->dynindx;
25712159047fSniklas 	      else
25722159047fSniklas 		indx = 0;
25732159047fSniklas 
25742159047fSniklas 	      if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE)
25752159047fSniklas 		{
25762159047fSniklas 		  struct reloc_std_external *srel;
25772159047fSniklas 
25782159047fSniklas 		  srel = (struct reloc_std_external *) p;
25792159047fSniklas 		  PUT_WORD (dynobj,
25802159047fSniklas 			    (*got_offsetp
25812159047fSniklas 			     + sgot->output_section->vma
25822159047fSniklas 			     + sgot->output_offset),
25832159047fSniklas 			    srel->r_address);
2584c88b1d6cSniklas 		  if (bfd_header_big_endian (dynobj))
25852159047fSniklas 		    {
2586b305b0f1Sespie 		      srel->r_index[0] = (bfd_byte) (indx >> 16);
2587b305b0f1Sespie 		      srel->r_index[1] = (bfd_byte) (indx >> 8);
2588b305b0f1Sespie 		      srel->r_index[2] = (bfd_byte)indx;
25892159047fSniklas 		      if (h == NULL)
25902159047fSniklas 			srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_BIG;
25912159047fSniklas 		      else
25922159047fSniklas 			srel->r_type[0] =
25932159047fSniklas 			  (RELOC_STD_BITS_EXTERN_BIG
25942159047fSniklas 			   | RELOC_STD_BITS_BASEREL_BIG
25952159047fSniklas 			   | RELOC_STD_BITS_RELATIVE_BIG
25962159047fSniklas 			   | (2 << RELOC_STD_BITS_LENGTH_SH_BIG));
25972159047fSniklas 		    }
25982159047fSniklas 		  else
25992159047fSniklas 		    {
2600b305b0f1Sespie 		      srel->r_index[2] = (bfd_byte) (indx >> 16);
2601b305b0f1Sespie 		      srel->r_index[1] = (bfd_byte) (indx >> 8);
2602b305b0f1Sespie 		      srel->r_index[0] = (bfd_byte)indx;
26032159047fSniklas 		      if (h == NULL)
26042159047fSniklas 			srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_LITTLE;
26052159047fSniklas 		      else
26062159047fSniklas 			srel->r_type[0] =
26072159047fSniklas 			  (RELOC_STD_BITS_EXTERN_LITTLE
26082159047fSniklas 			   | RELOC_STD_BITS_BASEREL_LITTLE
26092159047fSniklas 			   | RELOC_STD_BITS_RELATIVE_LITTLE
26102159047fSniklas 			   | (2 << RELOC_STD_BITS_LENGTH_SH_LITTLE));
26112159047fSniklas 		    }
26122159047fSniklas 		}
26132159047fSniklas 	      else
26142159047fSniklas 		{
26152159047fSniklas 		  struct reloc_ext_external *erel;
26162159047fSniklas 
26172159047fSniklas 		  erel = (struct reloc_ext_external *) p;
26182159047fSniklas 		  PUT_WORD (dynobj,
26192159047fSniklas 			    (*got_offsetp
26202159047fSniklas 			     + sgot->output_section->vma
26212159047fSniklas 			     + sgot->output_offset),
26222159047fSniklas 			    erel->r_address);
2623c88b1d6cSniklas 		  if (bfd_header_big_endian (dynobj))
26242159047fSniklas 		    {
2625b305b0f1Sespie 		      erel->r_index[0] = (bfd_byte) (indx >> 16);
2626b305b0f1Sespie 		      erel->r_index[1] = (bfd_byte) (indx >> 8);
2627b305b0f1Sespie 		      erel->r_index[2] = (bfd_byte)indx;
26282159047fSniklas 		      if (h == NULL)
26292159047fSniklas 			erel->r_type[0] =
26302159047fSniklas 			  RELOC_32 << RELOC_EXT_BITS_TYPE_SH_BIG;
26312159047fSniklas 		      else
26322159047fSniklas 			erel->r_type[0] =
26332159047fSniklas 			  (RELOC_EXT_BITS_EXTERN_BIG
26342159047fSniklas 			   | (RELOC_GLOB_DAT << RELOC_EXT_BITS_TYPE_SH_BIG));
26352159047fSniklas 		    }
26362159047fSniklas 		  else
26372159047fSniklas 		    {
2638b305b0f1Sespie 		      erel->r_index[2] = (bfd_byte) (indx >> 16);
2639b305b0f1Sespie 		      erel->r_index[1] = (bfd_byte) (indx >> 8);
2640b305b0f1Sespie 		      erel->r_index[0] = (bfd_byte)indx;
26412159047fSniklas 		      if (h == NULL)
26422159047fSniklas 			erel->r_type[0] =
26432159047fSniklas 			  RELOC_32 << RELOC_EXT_BITS_TYPE_SH_LITTLE;
26442159047fSniklas 		      else
26452159047fSniklas 			erel->r_type[0] =
26462159047fSniklas 			  (RELOC_EXT_BITS_EXTERN_LITTLE
26472159047fSniklas 			   | (RELOC_GLOB_DAT
26482159047fSniklas 			      << RELOC_EXT_BITS_TYPE_SH_LITTLE));
26492159047fSniklas 		    }
26502159047fSniklas 		  PUT_WORD (dynobj, 0, erel->r_addend);
26512159047fSniklas 		}
26522159047fSniklas 
26532159047fSniklas 	      ++s->reloc_count;
26542159047fSniklas 	    }
26552159047fSniklas 
26562159047fSniklas 	  *got_offsetp |= 1;
26572159047fSniklas 	}
26582159047fSniklas 
2659e93f7393Sniklas       *relocationp = (sgot->vma
2660c074d1c9Sdrahn 		      + (*got_offsetp &~ (bfd_vma) 1)
2661e93f7393Sniklas 		      - sunos_hash_table (info)->got_base);
26622159047fSniklas 
26632159047fSniklas       /* There is nothing else to do for a base relative reloc.  */
2664c074d1c9Sdrahn       return TRUE;
26652159047fSniklas     }
26662159047fSniklas 
26672159047fSniklas   if (! sunos_hash_table (info)->dynamic_sections_needed)
2668c074d1c9Sdrahn     return TRUE;
26692159047fSniklas   if (! info->shared)
26702159047fSniklas     {
26712159047fSniklas       if (h == NULL
26722159047fSniklas 	  || h->dynindx == -1
26732159047fSniklas 	  || h->root.root.type != bfd_link_hash_undefined
26742159047fSniklas 	  || (h->flags & SUNOS_DEF_REGULAR) != 0
26752159047fSniklas 	  || (h->flags & SUNOS_DEF_DYNAMIC) == 0
26762159047fSniklas 	  || (h->root.root.u.undef.abfd->flags & DYNAMIC) == 0)
2677c074d1c9Sdrahn 	return TRUE;
26782159047fSniklas     }
26792159047fSniklas   else
26802159047fSniklas     {
26812159047fSniklas       if (h != NULL
26822159047fSniklas 	  && (h->dynindx == -1
26832159047fSniklas 	      || jmptbl
26842159047fSniklas 	      || strcmp (h->root.root.root.string,
26852159047fSniklas 			 "__GLOBAL_OFFSET_TABLE_") == 0))
2686c074d1c9Sdrahn 	return TRUE;
26872159047fSniklas     }
26882159047fSniklas 
26892159047fSniklas   /* It looks like this is a reloc we are supposed to copy.  */
26902159047fSniklas 
26912159047fSniklas   s = bfd_get_section_by_name (dynobj, ".dynrel");
26922159047fSniklas   BFD_ASSERT (s != NULL);
26932159047fSniklas   BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) < s->_raw_size);
26942159047fSniklas 
26952159047fSniklas   p = s->contents + s->reloc_count * obj_reloc_entry_size (dynobj);
26962159047fSniklas 
26972159047fSniklas   /* Copy the reloc over.  */
26982159047fSniklas   memcpy (p, reloc, obj_reloc_entry_size (dynobj));
26992159047fSniklas 
27002159047fSniklas   if (h != NULL)
27012159047fSniklas     indx = h->dynindx;
27022159047fSniklas   else
27032159047fSniklas     indx = 0;
27042159047fSniklas 
27052159047fSniklas   /* Adjust the address and symbol index.  */
27062159047fSniklas   if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE)
27072159047fSniklas     {
27082159047fSniklas       struct reloc_std_external *srel;
27092159047fSniklas 
27102159047fSniklas       srel = (struct reloc_std_external *) p;
27112159047fSniklas       PUT_WORD (dynobj,
27122159047fSniklas 		(GET_WORD (dynobj, srel->r_address)
27132159047fSniklas 		 + input_section->output_section->vma
27142159047fSniklas 		 + input_section->output_offset),
27152159047fSniklas 		srel->r_address);
2716c88b1d6cSniklas       if (bfd_header_big_endian (dynobj))
27172159047fSniklas 	{
2718b305b0f1Sespie 	  srel->r_index[0] = (bfd_byte) (indx >> 16);
2719b305b0f1Sespie 	  srel->r_index[1] = (bfd_byte) (indx >> 8);
2720b305b0f1Sespie 	  srel->r_index[2] = (bfd_byte)indx;
27212159047fSniklas 	}
27222159047fSniklas       else
27232159047fSniklas 	{
2724b305b0f1Sespie 	  srel->r_index[2] = (bfd_byte) (indx >> 16);
2725b305b0f1Sespie 	  srel->r_index[1] = (bfd_byte) (indx >> 8);
2726b305b0f1Sespie 	  srel->r_index[0] = (bfd_byte)indx;
27272159047fSniklas 	}
2728b305b0f1Sespie       /* FIXME: We may have to change the addend for a PC relative
2729b305b0f1Sespie 	 reloc.  */
27302159047fSniklas     }
27312159047fSniklas   else
27322159047fSniklas     {
27332159047fSniklas       struct reloc_ext_external *erel;
27342159047fSniklas 
27352159047fSniklas       erel = (struct reloc_ext_external *) p;
27362159047fSniklas       PUT_WORD (dynobj,
27372159047fSniklas 		(GET_WORD (dynobj, erel->r_address)
27382159047fSniklas 		 + input_section->output_section->vma
27392159047fSniklas 		 + input_section->output_offset),
27402159047fSniklas 		erel->r_address);
2741c88b1d6cSniklas       if (bfd_header_big_endian (dynobj))
27422159047fSniklas 	{
2743b305b0f1Sespie 	  erel->r_index[0] = (bfd_byte) (indx >> 16);
2744b305b0f1Sespie 	  erel->r_index[1] = (bfd_byte) (indx >> 8);
2745b305b0f1Sespie 	  erel->r_index[2] = (bfd_byte)indx;
27462159047fSniklas 	}
27472159047fSniklas       else
27482159047fSniklas 	{
2749b305b0f1Sespie 	  erel->r_index[2] = (bfd_byte) (indx >> 16);
2750b305b0f1Sespie 	  erel->r_index[1] = (bfd_byte) (indx >> 8);
2751b305b0f1Sespie 	  erel->r_index[0] = (bfd_byte)indx;
2752b305b0f1Sespie 	}
2753b305b0f1Sespie       if (pcrel && h != NULL)
2754b305b0f1Sespie 	{
2755b305b0f1Sespie 	  /* Adjust the addend for the change in address.  */
2756b305b0f1Sespie 	  PUT_WORD (dynobj,
2757b305b0f1Sespie 		    (GET_WORD (dynobj, erel->r_addend)
2758b305b0f1Sespie 		     - (input_section->output_section->vma
2759b305b0f1Sespie 			+ input_section->output_offset
2760b305b0f1Sespie 			- input_section->vma)),
2761b305b0f1Sespie 		    erel->r_addend);
27622159047fSniklas 	}
27632159047fSniklas     }
27642159047fSniklas 
27652159047fSniklas   ++s->reloc_count;
27662159047fSniklas 
27672159047fSniklas   if (h != NULL)
2768c074d1c9Sdrahn     *skip = TRUE;
27692159047fSniklas 
2770c074d1c9Sdrahn   return TRUE;
27712159047fSniklas }
27722159047fSniklas 
27732159047fSniklas /* Finish up the dynamic linking information.  */
27742159047fSniklas 
2775c074d1c9Sdrahn static bfd_boolean
sunos_finish_dynamic_link(abfd,info)27762159047fSniklas sunos_finish_dynamic_link (abfd, info)
27772159047fSniklas      bfd *abfd;
27782159047fSniklas      struct bfd_link_info *info;
27792159047fSniklas {
27802159047fSniklas   bfd *dynobj;
27812159047fSniklas   asection *o;
27822159047fSniklas   asection *s;
27832159047fSniklas   asection *sdyn;
27842159047fSniklas 
2785b305b0f1Sespie   if (! sunos_hash_table (info)->dynamic_sections_needed
2786b305b0f1Sespie       && ! sunos_hash_table (info)->got_needed)
2787c074d1c9Sdrahn     return TRUE;
27882159047fSniklas 
27892159047fSniklas   dynobj = sunos_hash_table (info)->dynobj;
27902159047fSniklas 
27912159047fSniklas   sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
27922159047fSniklas   BFD_ASSERT (sdyn != NULL);
27932159047fSniklas 
27942159047fSniklas   /* Finish up the .need section.  The linker emulation code filled it
27952159047fSniklas      in, but with offsets from the start of the section instead of
27962159047fSniklas      real addresses.  Now that we know the section location, we can
27972159047fSniklas      fill in the final values.  */
27982159047fSniklas   s = bfd_get_section_by_name (dynobj, ".need");
27992159047fSniklas   if (s != NULL && s->_raw_size != 0)
28002159047fSniklas     {
28012159047fSniklas       file_ptr filepos;
28022159047fSniklas       bfd_byte *p;
28032159047fSniklas 
28042159047fSniklas       filepos = s->output_section->filepos + s->output_offset;
28052159047fSniklas       p = s->contents;
28062159047fSniklas       while (1)
28072159047fSniklas 	{
28082159047fSniklas 	  bfd_vma val;
28092159047fSniklas 
28102159047fSniklas 	  PUT_WORD (dynobj, GET_WORD (dynobj, p) + filepos, p);
28112159047fSniklas 	  val = GET_WORD (dynobj, p + 12);
28122159047fSniklas 	  if (val == 0)
28132159047fSniklas 	    break;
28142159047fSniklas 	  PUT_WORD (dynobj, val + filepos, p + 12);
28152159047fSniklas 	  p += 16;
28162159047fSniklas 	}
28172159047fSniklas     }
28182159047fSniklas 
28192159047fSniklas   /* The first entry in the .got section is the address of the
28202159047fSniklas      dynamic information, unless this is a shared library.  */
28212159047fSniklas   s = bfd_get_section_by_name (dynobj, ".got");
28222159047fSniklas   BFD_ASSERT (s != NULL);
2823b305b0f1Sespie   if (info->shared || sdyn->_raw_size == 0)
28242159047fSniklas     PUT_WORD (dynobj, 0, s->contents);
28252159047fSniklas   else
28262159047fSniklas     PUT_WORD (dynobj, sdyn->output_section->vma + sdyn->output_offset,
28272159047fSniklas 	      s->contents);
28282159047fSniklas 
28292159047fSniklas   for (o = dynobj->sections; o != NULL; o = o->next)
28302159047fSniklas     {
28312159047fSniklas       if ((o->flags & SEC_HAS_CONTENTS) != 0
28322159047fSniklas 	  && o->contents != NULL)
28332159047fSniklas 	{
28342159047fSniklas 	  BFD_ASSERT (o->output_section != NULL
28352159047fSniklas 		      && o->output_section->owner == abfd);
28362159047fSniklas 	  if (! bfd_set_section_contents (abfd, o->output_section,
2837c074d1c9Sdrahn 					  o->contents,
2838c074d1c9Sdrahn 					  (file_ptr) o->output_offset,
28392159047fSniklas 					  o->_raw_size))
2840c074d1c9Sdrahn 	    return FALSE;
28412159047fSniklas 	}
28422159047fSniklas     }
28432159047fSniklas 
2844b305b0f1Sespie   if (sdyn->_raw_size > 0)
2845b305b0f1Sespie     {
2846b305b0f1Sespie       struct external_sun4_dynamic esd;
2847b305b0f1Sespie       struct external_sun4_dynamic_link esdl;
2848c074d1c9Sdrahn       file_ptr pos;
2849b305b0f1Sespie 
28502159047fSniklas       /* Finish up the dynamic link information.  */
28512159047fSniklas       PUT_WORD (dynobj, (bfd_vma) 3, esd.ld_version);
28522159047fSniklas       PUT_WORD (dynobj,
28532159047fSniklas 		sdyn->output_section->vma + sdyn->output_offset + sizeof esd,
28542159047fSniklas 		esd.ldd);
28552159047fSniklas       PUT_WORD (dynobj,
28562159047fSniklas 		(sdyn->output_section->vma
28572159047fSniklas 		 + sdyn->output_offset
28582159047fSniklas 		 + sizeof esd
28592159047fSniklas 		 + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE),
28602159047fSniklas 		esd.ld);
28612159047fSniklas 
28622159047fSniklas       if (! bfd_set_section_contents (abfd, sdyn->output_section, &esd,
2863c074d1c9Sdrahn 				      (file_ptr) sdyn->output_offset,
2864c074d1c9Sdrahn 				      (bfd_size_type) sizeof esd))
2865c074d1c9Sdrahn 	return FALSE;
28662159047fSniklas 
28672159047fSniklas       PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_loaded);
28682159047fSniklas 
28692159047fSniklas       s = bfd_get_section_by_name (dynobj, ".need");
28702159047fSniklas       if (s == NULL || s->_raw_size == 0)
28712159047fSniklas 	PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_need);
28722159047fSniklas       else
28732159047fSniklas 	PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
28742159047fSniklas 		  esdl.ld_need);
28752159047fSniklas 
28762159047fSniklas       s = bfd_get_section_by_name (dynobj, ".rules");
28772159047fSniklas       if (s == NULL || s->_raw_size == 0)
28782159047fSniklas 	PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_rules);
28792159047fSniklas       else
28802159047fSniklas 	PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
28812159047fSniklas 		  esdl.ld_rules);
28822159047fSniklas 
28832159047fSniklas       s = bfd_get_section_by_name (dynobj, ".got");
28842159047fSniklas       BFD_ASSERT (s != NULL);
2885b305b0f1Sespie       PUT_WORD (dynobj, s->output_section->vma + s->output_offset,
2886b305b0f1Sespie 		esdl.ld_got);
28872159047fSniklas 
28882159047fSniklas       s = bfd_get_section_by_name (dynobj, ".plt");
28892159047fSniklas       BFD_ASSERT (s != NULL);
2890b305b0f1Sespie       PUT_WORD (dynobj, s->output_section->vma + s->output_offset,
2891b305b0f1Sespie 		esdl.ld_plt);
28922159047fSniklas       PUT_WORD (dynobj, s->_raw_size, esdl.ld_plt_sz);
28932159047fSniklas 
28942159047fSniklas       s = bfd_get_section_by_name (dynobj, ".dynrel");
28952159047fSniklas       BFD_ASSERT (s != NULL);
2896b305b0f1Sespie       BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
2897b305b0f1Sespie 		  == s->_raw_size);
28982159047fSniklas       PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
28992159047fSniklas 		esdl.ld_rel);
29002159047fSniklas 
29012159047fSniklas       s = bfd_get_section_by_name (dynobj, ".hash");
29022159047fSniklas       BFD_ASSERT (s != NULL);
29032159047fSniklas       PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
29042159047fSniklas 		esdl.ld_hash);
29052159047fSniklas 
29062159047fSniklas       s = bfd_get_section_by_name (dynobj, ".dynsym");
29072159047fSniklas       BFD_ASSERT (s != NULL);
29082159047fSniklas       PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
29092159047fSniklas 		esdl.ld_stab);
29102159047fSniklas 
29112159047fSniklas       PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_stab_hash);
29122159047fSniklas 
29132159047fSniklas       PUT_WORD (dynobj, (bfd_vma) sunos_hash_table (info)->bucketcount,
29142159047fSniklas 		esdl.ld_buckets);
29152159047fSniklas 
29162159047fSniklas       s = bfd_get_section_by_name (dynobj, ".dynstr");
29172159047fSniklas       BFD_ASSERT (s != NULL);
29182159047fSniklas       PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
29192159047fSniklas 		esdl.ld_symbols);
29202159047fSniklas       PUT_WORD (dynobj, s->_raw_size, esdl.ld_symb_size);
29212159047fSniklas 
29222159047fSniklas       /* The size of the text area is the size of the .text section
29232159047fSniklas 	 rounded up to a page boundary.  FIXME: Should the page size be
29242159047fSniklas 	 conditional on something?  */
29252159047fSniklas       PUT_WORD (dynobj,
29262159047fSniklas 		BFD_ALIGN (obj_textsec (abfd)->_raw_size, 0x2000),
29272159047fSniklas 		esdl.ld_text);
29282159047fSniklas 
2929c074d1c9Sdrahn       pos = sdyn->output_offset;
2930c074d1c9Sdrahn       pos += sizeof esd + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE;
29312159047fSniklas       if (! bfd_set_section_contents (abfd, sdyn->output_section, &esdl,
2932c074d1c9Sdrahn 				      pos, (bfd_size_type) sizeof esdl))
2933c074d1c9Sdrahn 	return FALSE;
29342159047fSniklas 
29352159047fSniklas       abfd->flags |= DYNAMIC;
2936b305b0f1Sespie     }
29372159047fSniklas 
2938c074d1c9Sdrahn   return TRUE;
29392159047fSniklas }
2940