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